/[VRac]/Z80/Z80.xs
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /Z80/Z80.xs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 112 - (show annotations)
Fri Aug 3 15:03:14 2007 UTC (16 years, 7 months ago) by dpavlin
File size: 6525 byte(s)
first, very rough XS bindings (they just compile)
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #include "ppport.h"
6
7 #include "Z80.h"
8 #include "config.h"
9
10 Z80 *R = NULL;
11 int debug = 0;
12
13 void update_C_R(void) {
14 R->AF.W = SvIV( get_sv("Z80::AF", FALSE) );
15 R->BC.W = SvIV( get_sv("Z80::BC", FALSE) );
16 R->DE.W = SvIV( get_sv("Z80::DE", FALSE) );
17 R->HL.W = SvIV( get_sv("Z80::HL", FALSE) );
18 R->IX.W = SvIV( get_sv("Z80::IX", FALSE) );
19 R->IY.W = SvIV( get_sv("Z80::IY", FALSE) );
20 R->PC.W = SvIV( get_sv("Z80::PC", FALSE) );
21 R->SP.W = SvIV( get_sv("Z80::SP", FALSE) );
22
23 R->AF1.W = SvIV( get_sv("Z80::AF1", FALSE) );
24 R->BC1.W = SvIV( get_sv("Z80::BC1", FALSE) );
25 R->DE1.W = SvIV( get_sv("Z80::DE1", FALSE) );
26 R->HL1.W = SvIV( get_sv("Z80::HL1", FALSE) );
27
28 R->IFF = SvIV( get_sv("Z80::IFF", FALSE) );
29 R->I = SvIV( get_sv("Z80::I", FALSE) );
30
31 R->R = SvIV( get_sv("Z80::R", FALSE) );
32
33 R->PC.W = SvIV( get_sv("Z80::PC", FALSE) );
34 R->IPeriod = SvIV( get_sv("Z80::IPeriod", FALSE) );
35 R->IRequest = SvIV( get_sv("Z80::IRequest", FALSE) );
36 R->IAutoReset = SvIV( get_sv("Z80::IAutoReset", FALSE) );
37 R->TrapBadOps = SvIV( get_sv("Z80::TrapBadOps", FALSE) );
38 R->Trap = SvIV( get_sv("Z80::Trap", FALSE) );
39 R->Trace = SvIV( get_sv("Z80::Trace", FALSE) );
40 debugf(("pull_R finished"));
41 dump_R;
42 }
43
44 void update_perl_R(void) {
45 debugf(("update_perl_R"));
46 dSP;
47 ENTER;
48 SAVETMPS;
49 PUSHMARK(SP);
50
51 XPUSHs( sv_2mortal( newSViv( R->AF.W ) ) );
52 XPUSHs( sv_2mortal( newSViv( R->BC.W ) ) );
53 XPUSHs( sv_2mortal( newSViv( R->DE.W ) ) );
54 XPUSHs( sv_2mortal( newSViv( R->HL.W ) ) );
55 XPUSHs( sv_2mortal( newSViv( R->IX.W ) ) );
56 XPUSHs( sv_2mortal( newSViv( R->IY.W ) ) );
57 XPUSHs( sv_2mortal( newSViv( R->PC.W ) ) );
58 XPUSHs( sv_2mortal( newSViv( R->SP.W ) ) );
59
60 XPUSHs( sv_2mortal( newSViv( R->AF1.W ) ) );
61 XPUSHs( sv_2mortal( newSViv( R->BC1.W ) ) );
62 XPUSHs( sv_2mortal( newSViv( R->DE1.W ) ) );
63 XPUSHs( sv_2mortal( newSViv( R->HL1.W ) ) );
64
65 XPUSHs( sv_2mortal( newSViv( R->IFF ) ) );
66 XPUSHs( sv_2mortal( newSViv( R->I ) ) );
67 XPUSHs( sv_2mortal( newSViv( R->R ) ) );
68
69 XPUSHs( sv_2mortal( newSViv( R->IPeriod ) ) );
70 XPUSHs( sv_2mortal( newSViv( R->ICount ) ) );
71 XPUSHs( sv_2mortal( newSViv( R->IRequest ) ) );
72 XPUSHs( sv_2mortal( newSViv( R->IAutoReset ) ) );
73 XPUSHs( sv_2mortal( newSViv( R->TrapBadOps ) ) );
74 XPUSHs( sv_2mortal( newSViv( R->Trap ) ) );
75 XPUSHs( sv_2mortal( newSViv( R->Trace ) ) );
76
77 PUTBACK;
78 call_pv("Z80::_update_perl_R", G_DISCARD );
79 debugf(("_update_perl_R returned to C"));
80 dump_R;
81 FREETMPS;
82 LEAVE;
83 }
84
85 /** DebugZ80() ***********************************************/
86 /** This function should exist if DEBUG is #defined. When **/
87 /** Trace!=0, it is called after each command executed by **/
88 /** the CPU, and given the Z80 registers. Emulation exits **/
89 /** if DebugZ80() returns 0. **/
90 /*************************************************************/
91
92 byte DebugZ80(Z80 *R) {
93 dump_R;
94 return 1; // continue emulation
95 }
96
97 /** RdZ80()/WrZ80() ******************************************/
98 /** These functions are called when access to RAM occurs. **/
99 /** They allow to control memory access. **/
100 /************************************ TO BE WRITTEN BY USER **/
101
102 byte mem(word Addr) {
103 byte byte;
104 int count;
105 debugf(("mem(%04x)", Addr));
106 dSP;
107 ENTER;
108 SAVETMPS;
109 PUSHMARK(SP);
110 XPUSHs( sv_2mortal( newSViv( Addr ) ) );
111 PUTBACK;
112 count = call_pv("Z80::_read", G_ARRAY | G_EVAL );
113 debugf(("got %d values", count));
114 SPAGAIN;
115 if (SvTRUE(ERRSV)) {
116 printf("ERROR: %s", SvPV_nolen( ERRSV ) );
117 exit(1);
118 }
119 if ( count != 1 ) {
120 printf("expect 1 return value, got %d", count);
121 exit(1);
122 }
123 SV *sv;
124 sv = POPs;
125 byte = SvIV(sv);
126 FREETMPS;
127 LEAVE;
128 debugf(("mem(%04x) = %02x", Addr, byte));
129 return byte;
130 }
131
132 byte RdZ80(register word Addr) {
133 byte Value;
134 Value = mem(Addr);
135 debugf(("RdZ80(%04x) = %02x", Addr, Value));
136 return Value;
137 }
138
139 void WrZ80(register word Addr,register byte Value) {
140 debugf(("WrZ80(%04x,%02x)", Addr, Value));
141 dSP;
142 ENTER;
143 SAVETMPS;
144 PUSHMARK(SP);
145 XPUSHs( sv_2mortal( newSViv( Addr ) ) );
146 XPUSHs( sv_2mortal( newSViv( Value ) ) );
147 PUTBACK;
148 call_pv("Z80::_write", G_DISCARD );
149 FREETMPS;
150 LEAVE;
151 }
152
153 /** LoopZ80() ************************************************/
154 /** Z80 emulation calls this function periodically to check **/
155 /** if the system hardware requires any interrupts. This **/
156 /** function must return an address of the interrupt vector **/
157 /** (0x0038, 0x0066, etc.) or INT_NONE for no interrupt. **/
158 /** Return INT_QUIT to exit the emulation loop. **/
159 /************************************ TO BE WRITTEN BY USER **/
160
161 int hw_int = INT_NONE;
162
163 word LoopZ80(register Z80 *R) {
164 debugf(("LoopZ80"));
165 dump_R;
166 return hw_int;
167 }
168
169 /** JumpZ80() ************************************************/
170 /** Z80 emulation calls this function when it executes a **/
171 /** JP, JR, CALL, RST, or RET. You can use JumpZ80() to **/
172 /** trap these opcodes and switch memory layout. **/
173 /************************************ TO BE WRITTEN BY USER **/
174 #ifndef JUMPZ80
175 #define JumpZ80(PC)
176 #else
177 void JumpZ80(word PC);
178 #endif
179
180 /** PatchZ80() ***********************************************/
181 /** Z80 emulation calls this function when it encounters a **/
182 /** special patch command (ED FE) provided for user needs. **/
183 /** For example, it can be called to emulate BIOS calls, **/
184 /** such as disk and tape access. Replace it with an empty **/
185 /** macro for no patching. **/
186 /************************************ TO BE WRITTEN BY USER **/
187 void PatchZ80(register Z80 *R) {
188 debugf(("PatchZ80"));
189 dump_R;
190 hw_int = INT_QUIT;
191 }
192
193 /*************************************************************/
194
195 int
196 reset (void) {
197 debugf(("Z80::reset called"));
198 if ( ! R ) {
199 debugf(("allocating space for R"));
200 R = malloc(sizeof(Z80));
201 if (!R) {
202 PerlIO_stdoutf("can't alloc %d bytes for Z80", sizeof(Z80));
203 exit(1);
204 }
205 }
206 ResetZ80(R);
207 debugf(("ResetZ80 over"));
208 update_perl_R();
209 dump_R;
210 return 1;
211 }
212
213 int exec(int cycles) {
214 int left;
215 debugf(("exec for %d cycles", cycles));
216
217 if (!R) reset();
218
219 update_C_R();
220 left = ExecZ80(R, cycles);
221 update_perl_R();
222 debugf(("end of %d cycles CPU run\n", cycles));
223 return left;
224 }
225
226 int set_debug(int state) {
227 debug = state;
228 return debug;
229 }
230
231 int get_debug(void) {
232 return debug;
233 }
234
235 MODULE = Z80 PACKAGE = Z80
236
237 PROTOTYPES: DISABLE
238
239 int
240 set_debug(int state)
241
242 int
243 get_debug()
244
245 int
246 reset()
247
248 void
249 update_C_R()
250
251 void
252 update_perl_R()
253
254 int
255 exec(int cycles)

  ViewVC Help
Powered by ViewVC 1.1.26