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