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