1 #include "driver.h"
2 #include "cpuintrf.h"
3 #include "state.h"
4 #include "drz80_z80.h"
5 #include "drz80.h"
6
7 typedef struct {
8 struct DrZ80 regs;
9 unsigned int nmi_state;
10 unsigned int irq_state;
11 int previouspc;
12 int (*MAMEIrqCallback)(int int_level);
13 } drz80_regs;
14
15 static drz80_regs DRZ80;
16 int drz80_ICount;
17
18 #define INT_IRQ 0x01
19 #define NMI_IRQ 0x02
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
Interrupt(void)24 void Interrupt(void)
25 {
26 if (DRZ80.regs.Z80_IRQ&NMI_IRQ)
27 {
28 DRZ80.previouspc=0xffffffff;
29 }
30 else if ((DRZ80.irq_state!=CLEAR_LINE) && (DRZ80.regs.Z80IF&1))
31 {
32 DRZ80.previouspc=0xffffffff;
33 DRZ80.regs.Z80_IRQ=DRZ80.regs.Z80_IRQ|INT_IRQ;
34 DRZ80.regs.z80irqvector=(*DRZ80.MAMEIrqCallback)(0);
35 }
36 }
37 #ifdef __cplusplus
38 } /* End of extern "C" */
39 #endif
40
drz80_rebasePC(unsigned short address)41 static unsigned int drz80_rebasePC(unsigned short address)
42 {
43 change_pc16(address);
44 DRZ80.regs.Z80PC_BASE = (unsigned int) OP_ROM;
45 DRZ80.regs.Z80PC = DRZ80.regs.Z80PC_BASE + address;
46 return (DRZ80.regs.Z80PC);
47 }
48
drz80_rebaseSP(unsigned short address)49 static unsigned int drz80_rebaseSP(unsigned short address)
50 {
51 change_pc16(address);
52 DRZ80.regs.Z80SP_BASE=(unsigned int) OP_ROM;
53 DRZ80.regs.Z80SP=DRZ80.regs.Z80SP_BASE + address;
54 return (DRZ80.regs.Z80SP);
55 }
56
drz80_irq_callback(void)57 static void drz80_irq_callback(void)
58 {
59 if (DRZ80.regs.Z80_IRQ&NMI_IRQ)
60 DRZ80.regs.Z80_IRQ=DRZ80.regs.Z80_IRQ&(~NMI_IRQ);
61 else
62 DRZ80.regs.Z80_IRQ=DRZ80.regs.Z80_IRQ&(~INT_IRQ);
63 DRZ80.previouspc=0;
64 }
65
drz80_read8(unsigned short Addr)66 static unsigned char drz80_read8(unsigned short Addr)
67 {
68 return ((cpu_readmem16(Addr))&0xff);
69 }
70
drz80_read16(unsigned short Addr)71 static unsigned short drz80_read16(unsigned short Addr)
72 {
73 return (((cpu_readmem16(Addr))&0xff)|((cpu_readmem16(Addr+1)&0xff)<<8));
74 }
75
drz80_write8(unsigned char Value,unsigned short Addr)76 static void drz80_write8(unsigned char Value,unsigned short Addr)
77 {
78 cpu_writemem16(Addr,Value);
79 }
80
drz80_write16(unsigned short Value,unsigned short Addr)81 static void drz80_write16(unsigned short Value,unsigned short Addr)
82 {
83 cpu_writemem16(Addr,(unsigned char)Value&0xff);
84 cpu_writemem16(Addr+1,((unsigned char)(Value>>8))&0xff);
85 }
86
drz80_in(unsigned short Addr)87 static unsigned char drz80_in(unsigned short Addr)
88 {
89 return ((cpu_readport16(Addr))&0xff);
90 }
91
drz80_out(unsigned short Addr,unsigned char Value)92 static void drz80_out(unsigned short Addr,unsigned char Value)
93 {
94 cpu_writeport16(Addr,Value);
95 }
96
drz80_init(void)97 void drz80_init(void)
98 {
99
100 }
101
drz80_reset(void * param)102 void drz80_reset(void *param)
103 {
104 memset (&DRZ80, 0, sizeof(drz80_regs));
105 DRZ80.regs.z80_rebasePC=drz80_rebasePC;
106 DRZ80.regs.z80_rebaseSP=drz80_rebaseSP;
107 DRZ80.regs.z80_read8 =drz80_read8;
108 DRZ80.regs.z80_read16 =drz80_read16;
109 DRZ80.regs.z80_write8 =drz80_write8;
110 DRZ80.regs.z80_write16 =drz80_write16;
111 DRZ80.regs.z80_in =drz80_in;
112 DRZ80.regs.z80_out =drz80_out;
113 DRZ80.regs.z80_irq_callback=drz80_irq_callback;
114 DRZ80.regs.Z80IX = 0xffff<<16;
115 DRZ80.regs.Z80IY = 0xffff<<16;
116 DRZ80.regs.Z80F = (1<<2); /* set ZFlag */
117 DRZ80.nmi_state=CLEAR_LINE;
118 DRZ80.irq_state=CLEAR_LINE;
119 /*DRZ80.MAMEIrqCallback=NULL;*/
120 DRZ80.previouspc=0;
121 DRZ80.regs.Z80SP=DRZ80.regs.z80_rebaseSP(0xf000);
122 DRZ80.regs.Z80PC=DRZ80.regs.z80_rebasePC(0);
123 }
124
drz80_exit(void)125 void drz80_exit(void)
126 {
127 }
128
drz80_execute(int cycles)129 int drz80_execute(int cycles)
130 {
131 DRZ80.regs.cycles = cycles;
132 drz80_ICount = DRZ80.regs.cycles;
133 DrZ80Run(&DRZ80.regs, cycles);
134 change_pc16(DRZ80.regs.Z80PC - DRZ80.regs.Z80PC_BASE);
135 drz80_ICount = DRZ80.regs.cycles;
136 return (cycles-DRZ80.regs.cycles);
137 }
138
drz80_burn(int cycles)139 void drz80_burn(int cycles)
140 {
141 if( cycles > 0 )
142 {
143 /* NOP takes 4 cycles per instruction */
144 int n = (cycles + 3) / 4;
145 //DRZ80.regs.Z80R += n;
146 DRZ80.regs.cycles -= 4 * n;
147 drz80_ICount = DRZ80.regs.cycles;
148 }
149 }
150
drz80_get_context(void * dst)151 unsigned drz80_get_context (void *dst)
152 {
153 if (dst)
154 memcpy (dst,&DRZ80,sizeof (drz80_regs));
155 return sizeof(drz80_regs);
156 }
157
drz80_set_context(void * src)158 void drz80_set_context (void *src)
159 {
160 if (src)
161 memcpy (&DRZ80, src, sizeof (drz80_regs));
162 change_pc16(DRZ80.regs.Z80PC - DRZ80.regs.Z80PC_BASE);
163 }
164
drz80_get_cycle_table(int which)165 const void *drz80_get_cycle_table (int which)
166 {
167 return NULL;
168 }
169
drz80_set_cycle_table(int which,void * new_table)170 void drz80_set_cycle_table (int which, void *new_table)
171 {
172 }
173
drz80_get_pc(void)174 unsigned drz80_get_pc (void)
175 {
176 return (DRZ80.regs.Z80PC - DRZ80.regs.Z80PC_BASE);
177 }
178
drz80_set_pc(unsigned val)179 void drz80_set_pc (unsigned val)
180 {
181 DRZ80.regs.Z80PC=drz80_rebasePC(val);
182 }
183
drz80_get_sp(void)184 unsigned drz80_get_sp (void)
185 {
186 return (DRZ80.regs.Z80SP - DRZ80.regs.Z80SP_BASE);
187 }
188
drz80_set_sp(unsigned val)189 void drz80_set_sp (unsigned val)
190 {
191 DRZ80.regs.Z80SP=drz80_rebaseSP(val);
192 }
193
194 enum {
195 Z80_PC=1, Z80_SP, Z80_AF, Z80_BC, Z80_DE, Z80_HL,
196 Z80_IX, Z80_IY, Z80_AF2, Z80_BC2, Z80_DE2, Z80_HL2,
197 Z80_R, Z80_I, Z80_IM, Z80_IFF1, Z80_IFF2, Z80_HALT,
198 Z80_NMI_STATE, Z80_IRQ_STATE, Z80_DC0, Z80_DC1, Z80_DC2, Z80_DC3
199 };
200
drz80_get_reg(int regnum)201 unsigned drz80_get_reg (int regnum)
202 {
203 switch( regnum )
204 {
205 case Z80_PC: return drz80_get_pc();
206 case Z80_SP: return drz80_get_sp();
207 case Z80_AF: return ((DRZ80.regs.Z80A>>16) | (DRZ80.regs.Z80F>>24));
208 case Z80_BC: return (DRZ80.regs.Z80BC>>16);
209 case Z80_DE: return (DRZ80.regs.Z80DE>>16);
210 case Z80_HL: return (DRZ80.regs.Z80HL>>16);
211 case Z80_IX: return (DRZ80.regs.Z80IX>>16);
212 case Z80_IY: return (DRZ80.regs.Z80IY>>16);
213 case Z80_R: return DRZ80.regs.Z80R; /*???*/
214 case Z80_I: return DRZ80.regs.Z80I;
215 case Z80_AF2: return ((DRZ80.regs.Z80A2>>16) | (DRZ80.regs.Z80F2>>24));
216 case Z80_BC2: return (DRZ80.regs.Z80BC2>>16);
217 case Z80_DE2: return (DRZ80.regs.Z80DE2>>16);
218 case Z80_HL2: return (DRZ80.regs.Z80HL2>>16);
219 case Z80_IM: return DRZ80.regs.Z80IM;
220 case Z80_IFF1: return ((DRZ80.regs.Z80IF&1)!=0);
221 case Z80_IFF2: return ((DRZ80.regs.Z80IF&2)!=0);
222 case Z80_HALT: return ((DRZ80.regs.Z80IF&4)!=0);
223 case Z80_NMI_STATE: return DRZ80.nmi_state;
224 case Z80_IRQ_STATE: return DRZ80.irq_state;
225 case Z80_DC0: return 0; /* daisy chain */
226 case Z80_DC1: return 0; /* daisy chain */
227 case Z80_DC2: return 0; /* daisy chain */
228 case Z80_DC3: return 0; /* daisy chain */
229 case REG_PREVIOUSPC: return (DRZ80.previouspc==0xffffffff?0xffffffff:drz80_get_pc());
230 default:
231 if( regnum <= REG_SP_CONTENTS )
232 {
233 unsigned offset = drz80_get_sp() + 2 * (REG_SP_CONTENTS - regnum);
234 if( offset < 0xffff )
235 return drz80_read16(offset);
236 }
237 }
238 return 0;
239 }
240
drz80_set_reg(int regnum,unsigned val)241 void drz80_set_reg (int regnum, unsigned val)
242 {
243 switch( regnum )
244 {
245 case Z80_PC: drz80_set_pc(val); break;
246 case Z80_SP: drz80_set_sp(val); break;
247 case Z80_AF: DRZ80.regs.Z80A=((val&0xff00)<<16); DRZ80.regs.Z80F=((val&0x00ff)<<24); break;
248 case Z80_BC: DRZ80.regs.Z80BC=(val<<16); break;
249 case Z80_DE: DRZ80.regs.Z80DE=(val<<16); break;
250 case Z80_HL: DRZ80.regs.Z80HL=(val<<16); break;
251 case Z80_IX: DRZ80.regs.Z80IX=(val<<16); break;
252 case Z80_IY: DRZ80.regs.Z80IY=(val<<16); break;
253 case Z80_R: DRZ80.regs.Z80R=val; break; /*???*/
254 case Z80_I: DRZ80.regs.Z80I = val; break;
255 case Z80_AF2: DRZ80.regs.Z80A2=((val&0xff00)<<16); DRZ80.regs.Z80F2=((val&0x00ff)<<24); break;
256 case Z80_BC2: DRZ80.regs.Z80BC2=(val<<16); break;
257 case Z80_DE2: DRZ80.regs.Z80DE2=(val<<16); break;
258 case Z80_HL2: DRZ80.regs.Z80HL2=(val<<16); break;
259 case Z80_IM: DRZ80.regs.Z80IM = val; break;
260 case Z80_IFF1: DRZ80.regs.Z80IF=(DRZ80.regs.Z80IF)&(~(val==0)); break;
261 case Z80_IFF2: DRZ80.regs.Z80IF=(DRZ80.regs.Z80IF)&(~((val==0)<<1)); break;
262 case Z80_HALT: DRZ80.regs.Z80IF=(DRZ80.regs.Z80IF)&(~((val==0)<<2)); break;
263 case Z80_NMI_STATE: drz80_set_irq_line(IRQ_LINE_NMI,val); break;
264 case Z80_IRQ_STATE: drz80_set_irq_line(0,val); break;
265 case Z80_DC0: break; /* daisy chain */
266 case Z80_DC1: break; /* daisy chain */
267 case Z80_DC2: break; /* daisy chain */
268 case Z80_DC3: break; /* daisy chain */
269 default:
270 if( regnum <= REG_SP_CONTENTS )
271 {
272 unsigned offset = drz80_get_sp() + 2 * (REG_SP_CONTENTS - regnum);
273 if( offset < 0xffff )
274 drz80_write16(val,offset);
275 }
276 }
277 }
278
drz80_set_irq_line(int irqline,int state)279 void drz80_set_irq_line(int irqline, int state)
280 {
281 if(irqline == IRQ_LINE_NMI){
282 DRZ80.nmi_state=state;
283 if (state!=CLEAR_LINE)
284 DRZ80.regs.Z80_IRQ=DRZ80.regs.Z80_IRQ|NMI_IRQ;
285 } else {
286 DRZ80.irq_state=state;
287 }
288 }
289
drz80_set_irq_callback(int (* callback)(int))290 void drz80_set_irq_callback(int (*callback)(int))
291 {
292 DRZ80.MAMEIrqCallback=callback;
293 }
294
drz80_state_save(void * file)295 void drz80_state_save(void *file)
296 {
297 }
298
drz80_state_load(void * file)299 void drz80_state_load(void *file)
300 {
301 }
302
drz80_info(void * context,int regnum)303 const char *drz80_info(void *context, int regnum)
304 {
305 switch( regnum )
306 {
307 case CPU_INFO_NAME: return "DRZ80 Z80";
308 case CPU_INFO_FAMILY: return "Zilog Z80";
309 case CPU_INFO_VERSION: return "1.0";
310 case CPU_INFO_FILE: return __FILE__;
311 case CPU_INFO_CREDITS: return "Copyright 2005 Reesy, all rights reserved.";
312 }
313 return "";
314 }
315
drz80_dasm(char * buffer,unsigned pc)316 unsigned drz80_dasm( char *buffer, unsigned pc )
317 {
318 sprintf( buffer, "$%02X", cpu_readop(pc) );
319 return 1;
320 }
321