1 /********************************************************************************/
2 /* */
3 /* CZ80 (Z80 CPU emulator) version 0.91 */
4 /* Compiled with Dev-C++ */
5 /* Copyright 2004-2005 Stephane Dallongeville */
6 /* */
7 /********************************************************************************/
8
9 //#ifdef CPUZ80_CZ80_CORE
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <stddef.h>
14 #include "cz80.h"
15
16
17 // include macro file
18 //////////////////////
19
20 #include "cz80.inc"
21
22 // shared global variable
23 //////////////////////////
24
25 cz80_struc CZ80;
26
27 static uint8_t SZXY[256]; // zero and sign flags
28 static uint8_t SZXYP[256]; // zero, sign and parity flags
29 static uint8_t SZXY_BIT[256]; // zero, sign and parity/overflow (=zero) flags for BIT opcode
30 static uint8_t SZXYHV_inc[256]; // zero, sign, half carry and overflow flags INC R8
31 static uint8_t SZXYHV_dec[256]; // zero, sign, half carry and overflow flags DEC R8
32
33 // prototype
34 /////////////
35
36 uint8_t FASTCALL Cz80_Read_Dummy(void *ctx, const uint16_t adr);
37 void FASTCALL Cz80_Write_Dummy(void *ctx, const uint16_t adr, uint8_t data);
38
39 uint8_t FASTCALL Cz80_Interrupt_Ack_Dummy(void *ctx, uint8_t param);
40 void FASTCALL Cz80_RetI_Dummy(void *ctx);
41
42 // core main functions
43 ///////////////////////
44
Cz80_Init(cz80_struc * cpu)45 void Cz80_Init(cz80_struc *cpu)
46 {
47 unsigned int i, j, p;
48
49 memset(cpu, 0, sizeof(cz80_struc));
50
51 // flags tables initialisation
52 for (i = 0; i < 256; i++)
53 {
54 SZXY[i] = i & (CZ80_SF | CZ80_YF | CZ80_XF);
55 if (!i) SZXY[i] |= CZ80_ZF;
56
57 SZXY_BIT[i] = i & (CZ80_SF | CZ80_YF | CZ80_XF);
58 if (!i) SZXY_BIT[i] |= CZ80_ZF | CZ80_PF;
59
60 for (j = 0, p = 0; j < 8; j++) if (i & (1 << j)) p++;
61 SZXYP[i] = SZXY[i];
62 if (!(p & 1)) SZXYP[i] |= CZ80_PF;
63
64 SZXYHV_inc[i] = SZXY[i];
65 if(i == 0x80) SZXYHV_inc[i] |= CZ80_VF;
66 if((i & 0x0F) == 0x00) SZXYHV_inc[i] |= CZ80_HF;
67
68 SZXYHV_dec[i] = SZXY[i] | CZ80_NF;
69 if (i == 0x7F) SZXYHV_dec[i] |= CZ80_VF;
70 if ((i & 0x0F) == 0x0F) SZXYHV_dec[i] |= CZ80_HF;
71 }
72
73 Cz80_Set_Fetch(cpu, 0x0000, 0xFFFF, NULL);
74
75 Cz80_Set_ReadB(cpu, Cz80_Read_Dummy);
76 Cz80_Set_WriteB(cpu, Cz80_Write_Dummy);
77
78 cpu->Interrupt_Ack = Cz80_Interrupt_Ack_Dummy;
79 cpu->RetI = Cz80_RetI_Dummy;
80 }
81
Cz80_Reset(cz80_struc * cpu)82 uint8_t Cz80_Reset(cz80_struc *cpu)
83 {
84 cz80_struc *CPU = cpu;
85
86 memset(CPU, 0, offsetof(cz80_struc, CycleSup));
87
88 Cz80_Set_PC(CPU, 0);
89 zIX = 0xFFFF;
90 zIY = 0xFFFF;
91 #if CZ80_DEBUG
92 zF = CZ80_ZF;
93 #else
94 zSP = 0xFFFF;
95 zFA = 0xFFFF;
96 #endif
97
98 return CPU->Status;
99 }
100
101 /////////////////////////////////
102
103 #include "cz80exec.inc"
104
105 /////////////////////////////////
106
Cz80_Set_IRQ(cz80_struc * cpu,uint8_t vector)107 void FASTCALL Cz80_Set_IRQ(cz80_struc *cpu, uint8_t vector)
108 {
109 cpu->IntVect = vector;
110 cpu->Status |= CZ80_HAS_INT;
111 cpu->CycleSup = cpu->CycleIO;
112 cpu->CycleIO = 0;
113 }
114
Cz80_Set_NMI(cz80_struc * cpu)115 void FASTCALL Cz80_Set_NMI(cz80_struc *cpu)
116 {
117 cpu->Status |= CZ80_HAS_NMI;
118 cpu->CycleSup = cpu->CycleIO;
119 cpu->CycleIO = 0;
120 }
121
Cz80_Clear_IRQ(cz80_struc * cpu)122 void FASTCALL Cz80_Clear_IRQ(cz80_struc *cpu)
123 {
124 cpu->Status &= ~CZ80_HAS_INT;
125 }
126
Cz80_Clear_NMI(cz80_struc * cpu)127 void FASTCALL Cz80_Clear_NMI(cz80_struc *cpu)
128 {
129 cpu->Status &= ~CZ80_HAS_NMI;
130 }
131
132 /////////////////////////////////
133
Cz80_Get_CycleToDo(cz80_struc * cpu)134 int FASTCALL Cz80_Get_CycleToDo(cz80_struc *cpu)
135 {
136 if (!(cpu->Status & CZ80_RUNNING)) return -1;
137
138 return cpu->CycleToDo;
139 }
140
Cz80_Get_CycleRemaining(cz80_struc * cpu)141 int FASTCALL Cz80_Get_CycleRemaining(cz80_struc *cpu)
142 {
143 if (!(cpu->Status & CZ80_RUNNING)) return -1;
144
145 return (cpu->CycleIO + cpu->CycleSup);
146 }
147
Cz80_Get_CycleDone(cz80_struc * cpu)148 int FASTCALL Cz80_Get_CycleDone(cz80_struc *cpu)
149 {
150 if (!(cpu->Status & CZ80_RUNNING)) return -1;
151
152 return (cpu->CycleToDo - (cpu->CycleIO + cpu->CycleSup));
153 }
154
Cz80_Release_Cycle(cz80_struc * cpu)155 void FASTCALL Cz80_Release_Cycle(cz80_struc *cpu)
156 {
157 if (cpu->Status & CZ80_RUNNING) cpu->CycleIO = cpu->CycleSup = 0;
158 }
159
Cz80_Add_Cycle(cz80_struc * cpu,unsigned int cycle)160 void FASTCALL Cz80_Add_Cycle(cz80_struc *cpu, unsigned int cycle)
161 {
162 if (cpu->Status & CZ80_RUNNING) cpu->CycleIO -= cycle;
163 }
164
165 // Read / Write dummy functions
166 ////////////////////////////////
167
Cz80_Read_Dummy(void * ctx,const uint16_t adr)168 uint8_t FASTCALL Cz80_Read_Dummy(void *ctx, const uint16_t adr)
169 {
170 (void)ctx;
171 (void)adr;
172 return 0;
173 }
174
Cz80_Write_Dummy(void * ctx,const uint16_t adr,uint8_t data)175 void FASTCALL Cz80_Write_Dummy(void *ctx, const uint16_t adr, uint8_t data)
176 {
177 (void)ctx;
178 (void)adr;
179 (void)data;
180 }
181
Cz80_Interrupt_Ack_Dummy(void * ctx,uint8_t param)182 uint8_t FASTCALL Cz80_Interrupt_Ack_Dummy(void *ctx, uint8_t param)
183 {
184 (void)ctx;
185 (void)param;
186
187 // return vector
188 return -1;
189 }
190
Cz80_RetI_Dummy(void * ctx)191 void FASTCALL Cz80_RetI_Dummy(void *ctx)
192 {
193 (void)ctx;
194 }
195
196
197 // Read / Write core functions
198 ///////////////////////////////
199
Cz80_Set_Ctx(cz80_struc * cpu,void * ctx)200 void Cz80_Set_Ctx(cz80_struc *cpu, void *ctx)
201 {
202 cpu->ctx = ctx;
203 }
204
Cz80_Read_Byte(cz80_struc * cpu,uint16_t adr)205 uint8_t Cz80_Read_Byte(cz80_struc *cpu, uint16_t adr)
206 {
207 return cpu->Read_Byte(cpu->ctx, adr);
208 }
209
Cz80_Read_Word(cz80_struc * cpu,uint16_t adr)210 uint16_t Cz80_Read_Word(cz80_struc *cpu, uint16_t adr)
211 {
212 #if CZ80_USE_WORD_HANDLER
213 return cpu->Read_Word(cpu->ctx, adr);
214 #elif CZ80_LITTLE_ENDIAN
215 return (cpu->Read_Byte(cpu->ctx, adr) |
216 (cpu->Read_Byte(cpu->ctx, (adr + 1)) << 8));
217 #else
218 return ((cpu->Read_Byte(cpu->ctx, adr) << 8) |
219 cpu->Read_Byte(cpu->ctx, (adr + 1)));
220 #endif
221 }
222
Cz80_Write_Byte(cz80_struc * cpu,uint16_t adr,uint8_t data)223 void Cz80_Write_Byte(cz80_struc *cpu, uint16_t adr, uint8_t data)
224 {
225 cpu->Write_Byte(cpu->ctx, adr, data);
226 }
227
Cz80_Write_Word(cz80_struc * cpu,uint16_t adr,uint16_t data)228 void Cz80_Write_Word(cz80_struc *cpu, uint16_t adr, uint16_t data)
229 {
230 #if CZ80_USE_WORD_HANDLER
231 cpu->Write_Word(cpu->ctx, adr, data);
232 #elif CZ80_LITTLE_ENDIAN
233 cpu->Write_Byte(cpu->ctx, adr, (data & 0xFF));
234 cpu->Write_Byte(cpu->ctx, (adr + 1), (data >> 8));
235 #else
236 cpu->Write_Byte(cpu->ctx, adr, (data >> 8));
237 cpu->Write_Byte(cpu->ctx, (adr + 1), (data & 0xFF));
238 #endif
239 }
240
241 // setting core functions
242 //////////////////////////
243
Cz80_Set_Fetch(cz80_struc * cpu,uint16_t low_adr,uint16_t high_adr,void * fetch_adr)244 void Cz80_Set_Fetch(cz80_struc *cpu, uint16_t low_adr, uint16_t high_adr, void *fetch_adr)
245 {
246 uint16_t i, j;
247
248 i = low_adr >> CZ80_FETCH_SFT;
249 j = high_adr >> CZ80_FETCH_SFT;
250 fetch_adr = (void *)((uintptr_t)fetch_adr - (i << CZ80_FETCH_SFT));
251 while (i <= j) cpu->Fetch[i++] = (uint8_t*) fetch_adr;
252 }
253
Cz80_Set_ReadB(cz80_struc * cpu,CZ80_READ * Func)254 void Cz80_Set_ReadB(cz80_struc *cpu, CZ80_READ *Func)
255 {
256 cpu->Read_Byte = Func;
257 }
258
Cz80_Set_WriteB(cz80_struc * cpu,CZ80_WRITE * Func)259 void Cz80_Set_WriteB(cz80_struc *cpu, CZ80_WRITE *Func)
260 {
261 cpu->Write_Byte = Func;
262 }
263
264 #if CZ80_USE_WORD_HANDLER
Cz80_Set_ReadW(cz80_struc * cpu,CZ80_READ_WORD * Func)265 void Cz80_Set_ReadW(cz80_struc *cpu, CZ80_READ_WORD *Func)
266 {
267 cpu->Read_Word = Func;
268 }
269
Cz80_Set_WriteW(cz80_struc * cpu,CZ80_WRITE_WORD * Func)270 void Cz80_Set_WriteW(cz80_struc *cpu, CZ80_WRITE_WORD *Func)
271 {
272 cpu->Write_Word = Func;
273 }
274 #endif
275
Cz80_Set_INPort(cz80_struc * cpu,CZ80_READ * Func)276 void Cz80_Set_INPort(cz80_struc *cpu, CZ80_READ *Func)
277 {
278 cpu->IN_Port = Func;
279 }
280
Cz80_Set_OUTPort(cz80_struc * cpu,CZ80_WRITE * Func)281 void Cz80_Set_OUTPort(cz80_struc *cpu, CZ80_WRITE *Func)
282 {
283 cpu->OUT_Port = Func;
284 }
285
Cz80_Set_IRQ_Callback(cz80_struc * cpu,CZ80_INT_CALLBACK * Func)286 void Cz80_Set_IRQ_Callback(cz80_struc *cpu, CZ80_INT_CALLBACK *Func)
287 {
288 cpu->Interrupt_Ack = Func;
289 }
290
Cz80_Set_RETI_Callback(cz80_struc * cpu,CZ80_RETI_CALLBACK * Func)291 void Cz80_Set_RETI_Callback(cz80_struc *cpu, CZ80_RETI_CALLBACK *Func)
292 {
293 cpu->RetI = Func;
294 }
295
296 // externals main functions
297 ////////////////////////////
298
Cz80_Get_BC(cz80_struc * cpu)299 uint16_t FASTCALL Cz80_Get_BC(cz80_struc *cpu)
300 {
301 cz80_struc *CPU = cpu;
302 return zBC;
303 }
304
Cz80_Get_DE(cz80_struc * cpu)305 uint16_t FASTCALL Cz80_Get_DE(cz80_struc *cpu)
306 {
307 cz80_struc *CPU = cpu;
308 return zDE;
309 }
310
Cz80_Get_HL(cz80_struc * cpu)311 uint16_t FASTCALL Cz80_Get_HL(cz80_struc *cpu)
312 {
313 cz80_struc *CPU = cpu;
314 return zHL;
315 }
316
Cz80_Get_AF(cz80_struc * cpu)317 uint16_t FASTCALL Cz80_Get_AF(cz80_struc *cpu)
318 {
319 cz80_struc *CPU = cpu;
320 return (zF | (zA << 8));
321 }
322
Cz80_Get_BC2(cz80_struc * cpu)323 uint16_t FASTCALL Cz80_Get_BC2(cz80_struc *cpu)
324 {
325 cz80_struc *CPU = cpu;
326 return zBC2;
327 }
328
Cz80_Get_DE2(cz80_struc * cpu)329 uint16_t FASTCALL Cz80_Get_DE2(cz80_struc *cpu)
330 {
331 cz80_struc *CPU = cpu;
332 return zDE2;
333 }
334
Cz80_Get_HL2(cz80_struc * cpu)335 uint16_t FASTCALL Cz80_Get_HL2(cz80_struc *cpu)
336 {
337 cz80_struc *CPU = cpu;
338 return zHL2;
339 }
340
Cz80_Get_AF2(cz80_struc * cpu)341 uint16_t FASTCALL Cz80_Get_AF2(cz80_struc *cpu)
342 {
343 cz80_struc *CPU = cpu;
344 return (zF2 | (zA2 << 8));
345 }
346
Cz80_Get_IX(cz80_struc * cpu)347 uint16_t FASTCALL Cz80_Get_IX(cz80_struc *cpu)
348 {
349 cz80_struc *CPU = cpu;
350 return zIX;
351 }
352
Cz80_Get_IY(cz80_struc * cpu)353 uint16_t FASTCALL Cz80_Get_IY(cz80_struc *cpu)
354 {
355 cz80_struc *CPU = cpu;
356 return zIY;
357 }
358
Cz80_Get_SP(cz80_struc * cpu)359 uint16_t FASTCALL Cz80_Get_SP(cz80_struc *cpu)
360 {
361 cz80_struc *CPU = cpu;
362 return zSP;
363 }
364
Cz80_Get_PC(cz80_struc * cpu)365 uint16_t FASTCALL Cz80_Get_PC(cz80_struc *cpu)
366 {
367 cz80_struc *CPU = cpu;
368 return CPU->PC;
369 }
370
Cz80_Get_R(cz80_struc * cpu)371 uint16_t FASTCALL Cz80_Get_R(cz80_struc *cpu)
372 {
373 cz80_struc *CPU = cpu;
374 return zR;
375 }
376
Cz80_Get_IFF(cz80_struc * cpu)377 uint16_t FASTCALL Cz80_Get_IFF(cz80_struc *cpu)
378 {
379 cz80_struc *CPU = cpu;
380 uint16_t value = 0;
381
382 if (zIFF1 & CZ80_IFF) value |= 1;
383 if (zIFF2 & CZ80_IFF) value |= 2;
384 return value;
385 }
386
Cz80_Get_IM(cz80_struc * cpu)387 uint8_t FASTCALL Cz80_Get_IM(cz80_struc *cpu)
388 {
389 cz80_struc *CPU = cpu;
390 return zIM;
391 }
392
Cz80_Get_I(cz80_struc * cpu)393 uint8_t FASTCALL Cz80_Get_I(cz80_struc *cpu)
394 {
395 cz80_struc *CPU = cpu;
396 return zI;
397 }
398
399
Cz80_Set_BC(cz80_struc * cpu,uint16_t value)400 void FASTCALL Cz80_Set_BC(cz80_struc *cpu, uint16_t value)
401 {
402 cz80_struc *CPU = cpu;
403 zBC = value;
404 }
405
Cz80_Set_DE(cz80_struc * cpu,uint16_t value)406 void FASTCALL Cz80_Set_DE(cz80_struc *cpu, uint16_t value)
407 {
408 cz80_struc *CPU = cpu;
409 zDE = value;
410 }
411
Cz80_Set_HL(cz80_struc * cpu,uint16_t value)412 void FASTCALL Cz80_Set_HL(cz80_struc *cpu, uint16_t value)
413 {
414 cz80_struc *CPU = cpu;
415 zHL = value;
416 }
417
Cz80_Set_AF(cz80_struc * cpu,uint16_t val)418 void FASTCALL Cz80_Set_AF(cz80_struc *cpu, uint16_t val)
419 {
420 cz80_struc *CPU = cpu;
421 zF = val;
422 zA = val >> 8;
423 }
424
Cz80_Set_BC2(cz80_struc * cpu,uint16_t value)425 void FASTCALL Cz80_Set_BC2(cz80_struc *cpu, uint16_t value)
426 {
427 cz80_struc *CPU = cpu;
428 zBC2 = value;
429 }
430
Cz80_Set_DE2(cz80_struc * cpu,uint16_t value)431 void FASTCALL Cz80_Set_DE2(cz80_struc *cpu, uint16_t value)
432 {
433 cz80_struc *CPU = cpu;
434 zDE2 = value;
435 }
436
Cz80_Set_HL2(cz80_struc * cpu,uint16_t value)437 void FASTCALL Cz80_Set_HL2(cz80_struc *cpu, uint16_t value)
438 {
439 cz80_struc *CPU = cpu;
440 zHL2 = value;
441 }
442
Cz80_Set_AF2(cz80_struc * cpu,uint16_t val)443 void FASTCALL Cz80_Set_AF2(cz80_struc *cpu, uint16_t val)
444 {
445 cz80_struc *CPU = cpu;
446 zF2 = val;
447 zA2 = val >> 8;
448 }
449
Cz80_Set_IX(cz80_struc * cpu,uint16_t value)450 void FASTCALL Cz80_Set_IX(cz80_struc *cpu, uint16_t value)
451 {
452 cz80_struc *CPU = cpu;
453 zIX = value;
454 }
455
Cz80_Set_IY(cz80_struc * cpu,uint16_t value)456 void FASTCALL Cz80_Set_IY(cz80_struc *cpu, uint16_t value)
457 {
458 cz80_struc *CPU = cpu;
459 zIY = value;
460 }
461
Cz80_Set_SP(cz80_struc * cpu,uint16_t value)462 void FASTCALL Cz80_Set_SP(cz80_struc *cpu, uint16_t value)
463 {
464 cz80_struc *CPU = cpu;
465 zSP = value;
466 }
467
Cz80_Set_PC(cz80_struc * cpu,uint16_t val)468 void FASTCALL Cz80_Set_PC(cz80_struc *cpu, uint16_t val)
469 {
470 cpu->BasePC = (uintptr_t) cpu->Fetch[val >> CZ80_FETCH_SFT];
471 cpu->PC = val;
472 }
473
474
Cz80_Set_R(cz80_struc * cpu,uint16_t value)475 void FASTCALL Cz80_Set_R(cz80_struc *cpu, uint16_t value)
476 {
477 cz80_struc *CPU = cpu;
478 zR = value & 0xFF;
479 zR2 = value & 0x80;
480 }
481
Cz80_Set_IFF(cz80_struc * cpu,uint16_t value)482 void FASTCALL Cz80_Set_IFF(cz80_struc *cpu, uint16_t value)
483 {
484 cz80_struc *CPU = cpu;
485 zIFF = 0;
486 if (value & 1) zIFF1 = CZ80_IFF;
487 if (value & 2) zIFF2 = CZ80_IFF;
488 }
489
Cz80_Set_IM(cz80_struc * cpu,uint8_t value)490 void FASTCALL Cz80_Set_IM(cz80_struc *cpu, uint8_t value)
491 {
492 cz80_struc *CPU = cpu;
493 zIM = value & 3;
494 }
495
Cz80_Set_I(cz80_struc * cpu,uint8_t value)496 void FASTCALL Cz80_Set_I(cz80_struc *cpu, uint8_t value)
497 {
498 cz80_struc *CPU = cpu;
499 zI = value & 0xFF;
500 }
501
502 //#endif // CPUZ80_CZ80_CORE
503
504
505