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_cycles=&DRZ80.regs.cycles;
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_pc(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_pc(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_readport(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_writeport(Addr,Value);
95 }
96
drz80_reset(void * param)97 void drz80_reset(void *param)
98 {
99 memset (&DRZ80, 0, sizeof(drz80_regs));
100 DRZ80.regs.z80_rebasePC=drz80_rebasePC;
101 DRZ80.regs.z80_rebaseSP=drz80_rebaseSP;
102 DRZ80.regs.z80_read8 =drz80_read8;
103 DRZ80.regs.z80_read16 =drz80_read16;
104 DRZ80.regs.z80_write8 =drz80_write8;
105 DRZ80.regs.z80_write16 =drz80_write16;
106 DRZ80.regs.z80_in =drz80_in;
107 DRZ80.regs.z80_out =drz80_out;
108 DRZ80.regs.z80_irq_callback=drz80_irq_callback;
109 DRZ80.regs.Z80IX = 0xffff<<16;
110 DRZ80.regs.Z80IY = 0xffff<<16;
111 DRZ80.regs.Z80F = (1<<2); /* set ZFlag */
112 DRZ80.nmi_state=CLEAR_LINE;
113 DRZ80.irq_state=CLEAR_LINE;
114 /*DRZ80.MAMEIrqCallback=NULL;*/
115 DRZ80.previouspc=0;
116 DRZ80.regs.Z80SP=DRZ80.regs.z80_rebaseSP(0xf000);
117 DRZ80.regs.Z80PC=DRZ80.regs.z80_rebasePC(0);
118 }
119
drz80_exit(void)120 void drz80_exit(void)
121 {
122 }
123
drz80_execute(int cycles)124 int drz80_execute(int cycles)
125 {
126 DRZ80.regs.cycles = cycles;
127 DrZ80Run(&DRZ80.regs, cycles);
128 change_pc(DRZ80.regs.Z80PC - DRZ80.regs.Z80PC_BASE);
129 return (cycles-DRZ80.regs.cycles);
130 }
131
drz80_burn(int cycles)132 void drz80_burn(int cycles)
133 {
134 if( cycles > 0 )
135 {
136 /* NOP takes 4 cycles per instruction */
137 int n = (cycles + 3) / 4;
138 //DRZ80.regs.Z80R += n;
139 DRZ80.regs.cycles -= 4 * n;
140 }
141 }
142
drz80_get_context(void * dst)143 unsigned drz80_get_context (void *dst)
144 {
145 if (dst)
146 memcpy (dst,&DRZ80,sizeof (drz80_regs));
147 return sizeof(drz80_regs);
148 }
149
drz80_set_context(void * src)150 void drz80_set_context (void *src)
151 {
152 if (src)
153 memcpy (&DRZ80, src, sizeof (drz80_regs));
154 change_pc(DRZ80.regs.Z80PC - DRZ80.regs.Z80PC_BASE);
155 }
156
drz80_get_cycle_table(int which)157 void *drz80_get_cycle_table (int which)
158 {
159 return NULL;
160 }
161
drz80_set_cycle_table(int which,void * new_table)162 void drz80_set_cycle_table (int which, void *new_table)
163 {
164 }
165
drz80_get_pc(void)166 unsigned drz80_get_pc (void)
167 {
168 return (DRZ80.regs.Z80PC - DRZ80.regs.Z80PC_BASE);
169 }
170
drz80_set_pc(unsigned val)171 void drz80_set_pc (unsigned val)
172 {
173 DRZ80.regs.Z80PC=drz80_rebasePC(val);
174 }
175
drz80_get_sp(void)176 unsigned drz80_get_sp (void)
177 {
178 return (DRZ80.regs.Z80SP - DRZ80.regs.Z80SP_BASE);
179 }
180
drz80_set_sp(unsigned val)181 void drz80_set_sp (unsigned val)
182 {
183 DRZ80.regs.Z80SP=drz80_rebaseSP(val);
184 }
185
186 enum {
187 Z80_PC=1, Z80_SP, Z80_AF, Z80_BC, Z80_DE, Z80_HL,
188 Z80_IX, Z80_IY, Z80_AF2, Z80_BC2, Z80_DE2, Z80_HL2,
189 Z80_R, Z80_I, Z80_IM, Z80_IFF1, Z80_IFF2, Z80_HALT,
190 Z80_NMI_STATE, Z80_IRQ_STATE, Z80_DC0, Z80_DC1, Z80_DC2, Z80_DC3
191 };
192
drz80_get_reg(int regnum)193 unsigned drz80_get_reg (int regnum)
194 {
195 switch( regnum )
196 {
197 case Z80_PC: return drz80_get_pc();
198 case Z80_SP: return drz80_get_sp();
199 case Z80_AF: return ((DRZ80.regs.Z80A>>16) | (DRZ80.regs.Z80F>>24));
200 case Z80_BC: return (DRZ80.regs.Z80BC>>16);
201 case Z80_DE: return (DRZ80.regs.Z80DE>>16);
202 case Z80_HL: return (DRZ80.regs.Z80HL>>16);
203 case Z80_IX: return (DRZ80.regs.Z80IX>>16);
204 case Z80_IY: return (DRZ80.regs.Z80IY>>16);
205 case Z80_R: return DRZ80.regs.Z80R; /*???*/
206 case Z80_I: return DRZ80.regs.Z80I;
207 case Z80_AF2: return ((DRZ80.regs.Z80A2>>16) | (DRZ80.regs.Z80F2>>24));
208 case Z80_BC2: return (DRZ80.regs.Z80BC2>>16);
209 case Z80_DE2: return (DRZ80.regs.Z80DE2>>16);
210 case Z80_HL2: return (DRZ80.regs.Z80HL2>>16);
211 case Z80_IM: return DRZ80.regs.Z80IM;
212 case Z80_IFF1: return ((DRZ80.regs.Z80IF&1)!=0);
213 case Z80_IFF2: return ((DRZ80.regs.Z80IF&2)!=0);
214 case Z80_HALT: return ((DRZ80.regs.Z80IF&4)!=0);
215 case Z80_NMI_STATE: return DRZ80.nmi_state;
216 case Z80_IRQ_STATE: return DRZ80.irq_state;
217 case Z80_DC0: return 0; /* daisy chain */
218 case Z80_DC1: return 0; /* daisy chain */
219 case Z80_DC2: return 0; /* daisy chain */
220 case Z80_DC3: return 0; /* daisy chain */
221 case REG_PREVIOUSPC: return (DRZ80.previouspc==0xffffffff?0xffffffff:drz80_get_pc());
222 default:
223 if( regnum <= REG_SP_CONTENTS )
224 {
225 unsigned offset = drz80_get_sp() + 2 * (REG_SP_CONTENTS - regnum);
226 if( offset < 0xffff )
227 return drz80_read16(offset);
228 }
229 }
230 return 0;
231 }
232
drz80_set_reg(int regnum,unsigned val)233 void drz80_set_reg (int regnum, unsigned val)
234 {
235 switch( regnum )
236 {
237 case Z80_PC: drz80_set_pc(val); break;
238 case Z80_SP: drz80_set_sp(val); break;
239 case Z80_AF: DRZ80.regs.Z80A=((val&0xff00)<<16); DRZ80.regs.Z80F=((val&0x00ff)<<24); break;
240 case Z80_BC: DRZ80.regs.Z80BC=(val<<16); break;
241 case Z80_DE: DRZ80.regs.Z80DE=(val<<16); break;
242 case Z80_HL: DRZ80.regs.Z80HL=(val<<16); break;
243 case Z80_IX: DRZ80.regs.Z80IX=(val<<16); break;
244 case Z80_IY: DRZ80.regs.Z80IY=(val<<16); break;
245 case Z80_R: DRZ80.regs.Z80R=val; break; /*???*/
246 case Z80_I: DRZ80.regs.Z80I = val; break;
247 case Z80_AF2: DRZ80.regs.Z80A2=((val&0xff00)<<16); DRZ80.regs.Z80F2=((val&0x00ff)<<24); break;
248 case Z80_BC2: DRZ80.regs.Z80BC2=(val<<16); break;
249 case Z80_DE2: DRZ80.regs.Z80DE2=(val<<16); break;
250 case Z80_HL2: DRZ80.regs.Z80HL2=(val<<16); break;
251 case Z80_IM: DRZ80.regs.Z80IM = val; break;
252 case Z80_IFF1: DRZ80.regs.Z80IF=(DRZ80.regs.Z80IF)&(~(val==0)); break;
253 case Z80_IFF2: DRZ80.regs.Z80IF=(DRZ80.regs.Z80IF)&(~((val==0)<<1)); break;
254 case Z80_HALT: DRZ80.regs.Z80IF=(DRZ80.regs.Z80IF)&(~((val==0)<<2)); break;
255 case Z80_NMI_STATE: drz80_set_nmi_line(val); break;
256 case Z80_IRQ_STATE: drz80_set_irq_line(0,val); break;
257 case Z80_DC0: break; /* daisy chain */
258 case Z80_DC1: break; /* daisy chain */
259 case Z80_DC2: break; /* daisy chain */
260 case Z80_DC3: break; /* daisy chain */
261 default:
262 if( regnum <= REG_SP_CONTENTS )
263 {
264 unsigned offset = drz80_get_sp() + 2 * (REG_SP_CONTENTS - regnum);
265 if( offset < 0xffff )
266 drz80_write16(val,offset);
267 }
268 }
269 }
270
drz80_set_nmi_line(int state)271 void drz80_set_nmi_line(int state)
272 {
273 DRZ80.nmi_state=state;
274 if (state!=CLEAR_LINE)
275 DRZ80.regs.Z80_IRQ=DRZ80.regs.Z80_IRQ|NMI_IRQ;
276 }
277
drz80_set_irq_line(int irqline,int state)278 void drz80_set_irq_line(int irqline, int state)
279 {
280 DRZ80.irq_state=state;
281 }
282
drz80_set_irq_callback(int (* callback)(int))283 void drz80_set_irq_callback(int (*callback)(int))
284 {
285 DRZ80.MAMEIrqCallback=callback;
286 }
287
drz80_state_save(void * file)288 void drz80_state_save(void *file)
289 {
290 }
291
drz80_state_load(void * file)292 void drz80_state_load(void *file)
293 {
294 }
295
drz80_info(void * context,int regnum)296 const char *drz80_info(void *context, int regnum)
297 {
298 switch( regnum )
299 {
300 case CPU_INFO_NAME: return "DRZ80 Z80";
301 case CPU_INFO_FAMILY: return "Zilog Z80";
302 case CPU_INFO_VERSION: return "1.0";
303 case CPU_INFO_FILE: return __FILE__;
304 case CPU_INFO_CREDITS: return "Copyright 2005 Reesy, all rights reserved.";
305 }
306 return "";
307 }
308
drz80_dasm(char * buffer,unsigned pc)309 unsigned drz80_dasm( char *buffer, unsigned pc )
310 {
311 sprintf( buffer, "$%02X", cpu_readop(pc) );
312 return 1;
313 }
314