input: unbind old keys when new one is bound
[picodrive.git] / pico / z80if.c
CommitLineData
b8a1c09a 1#include <stddef.h>
c8d1e9b6 2#include "pico_int.h"
b8a1c09a 3#include "memory.h"
c8d1e9b6 4
b8a1c09a 5uptr z80_read_map [0x10000 >> Z80_MEM_SHIFT];
6uptr z80_write_map[0x10000 >> Z80_MEM_SHIFT];
c8d1e9b6 7
b4db550e 8#ifdef _USE_DRZ80
9struct DrZ80 drZ80;
c8d1e9b6 10
b4db550e 11static u32 drz80_sp_base;
c8d1e9b6 12
b4db550e 13static void drz80_load_pcsp(u32 pc, u32 sp)
c8d1e9b6 14{
b4db550e 15 drZ80.Z80PC_BASE = z80_read_map[pc >> Z80_MEM_SHIFT];
16 if (drZ80.Z80PC_BASE & (1<<31)) {
17 elprintf(EL_STATUS|EL_ANOMALY, "load_pcsp: bad PC: %04x", pc);
18 drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0];
19 } else {
20 drZ80.Z80PC_BASE <<= 1;
21 drZ80.Z80PC = drZ80.Z80PC_BASE + pc;
22 }
23 drZ80.Z80SP_BASE = z80_read_map[sp >> Z80_MEM_SHIFT];
24 if (drZ80.Z80SP_BASE & (1<<31)) {
25 elprintf(EL_STATUS|EL_ANOMALY, "load_pcsp: bad SP: %04x", sp);
26 drZ80.Z80SP_BASE = z80_read_map[0];
27 drZ80.Z80SP = drZ80.Z80SP_BASE + (1 << Z80_MEM_SHIFT);
28 } else {
29 drZ80.Z80SP_BASE <<= 1;
30 drZ80.Z80SP = drZ80.Z80SP_BASE + sp;
31 }
32}
c8d1e9b6 33
b4db550e 34// called only if internal xmap rebase fails
35static unsigned int dz80_rebase_pc(unsigned short pc)
c8d1e9b6 36{
b4db550e 37 elprintf(EL_STATUS|EL_ANOMALY, "dz80_rebase_pc: fail on %04x", pc);
38 drZ80.Z80PC_BASE = z80_read_map[0] << 1;
39 return drZ80.Z80PC_BASE;
c8d1e9b6 40}
41
b4db550e 42static unsigned int dz80_rebase_sp(unsigned short sp)
43{
44 elprintf(EL_STATUS|EL_ANOMALY, "dz80_rebase_sp: fail on %04x", sp);
45 drZ80.Z80SP_BASE = z80_read_map[drz80_sp_base >> Z80_MEM_SHIFT] << 1;
46 return drZ80.Z80SP_BASE + (1 << Z80_MEM_SHIFT) - 0x100;
47}
c8d1e9b6 48#endif
49
50
b4db550e 51void z80_init(void)
c8d1e9b6 52{
c8d1e9b6 53#ifdef _USE_DRZ80
54 memset(&drZ80, 0, sizeof(drZ80));
b4db550e 55 drZ80.z80_rebasePC = dz80_rebase_pc;
56 drZ80.z80_rebaseSP = dz80_rebase_sp;
57 drZ80.z80_read8 = (void *)z80_read_map;
58 drZ80.z80_read16 = NULL;
59 drZ80.z80_write8 = (void *)z80_write_map;
60 drZ80.z80_write16 = NULL;
61 drZ80.z80_irq_callback = NULL;
c8d1e9b6 62#endif
63#ifdef _USE_CZ80
64 memset(&CZ80, 0, sizeof(CZ80));
65 Cz80_Init(&CZ80);
66 Cz80_Set_ReadB(&CZ80, NULL); // unused (hacked in)
67 Cz80_Set_WriteB(&CZ80, NULL);
68#endif
69}
70
b4db550e 71void z80_reset(void)
c8d1e9b6 72{
c8d1e9b6 73#ifdef _USE_DRZ80
c7eb229a 74 // FIXME: reset is not correct
c8d1e9b6 75 memset(&drZ80, 0, 0x54);
76 drZ80.Z80F = (1<<2); // set ZFlag
77 drZ80.Z80F2 = (1<<2); // set ZFlag
78 drZ80.Z80IX = 0xFFFF << 16;
79 drZ80.Z80IY = 0xFFFF << 16;
b4db550e 80 drZ80.Z80I = 0;
c8d1e9b6 81 drZ80.Z80IM = 0; // 1?
82 drZ80.z80irqvector = 0xff0000; // RST 38h
ee05564f 83 drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0] << 1;
d8f51995 84 // drZ80 is locked in single bank
b4db550e 85 drz80_sp_base = (PicoAHW & PAHW_SMS) ? 0xc000 : 0x0000;
86 drZ80.Z80SP_BASE = z80_read_map[drz80_sp_base >> Z80_MEM_SHIFT] << 1;
87 if (PicoAHW & PAHW_SMS)
88 drZ80.Z80SP = drZ80.Z80SP_BASE + 0xdff0; // simulate BIOS
c8d1e9b6 89#endif
90#ifdef _USE_CZ80
91 Cz80_Reset(&CZ80);
92 Cz80_Set_Reg(&CZ80, CZ80_IX, 0xffff);
93 Cz80_Set_Reg(&CZ80, CZ80_IY, 0xffff);
b4db550e 94 if (PicoAHW & PAHW_SMS)
95 Cz80_Set_Reg(&CZ80, CZ80_SP, 0xdff0);
c8d1e9b6 96#endif
97}
98
b4db550e 99/* save state stuff */
100static int z80_unpack_legacy(const void *data)
c8d1e9b6 101{
b4db550e 102#if defined(_USE_DRZ80)
c8d1e9b6 103 if (*(int *)data == 0x015A7244) { // "DrZ" v1 save?
b4db550e 104 u32 pc, sp;
c8d1e9b6 105 memcpy(&drZ80, data+4, 0x54);
ee05564f 106 pc = (drZ80.Z80PC - drZ80.Z80PC_BASE) & 0xffff;
107 sp = (drZ80.Z80SP - drZ80.Z80SP_BASE) & 0xffff;
c8d1e9b6 108 // update bases
b4db550e 109 drz80_load_pcsp(pc, sp);
110 return 0;
c8d1e9b6 111 }
112#elif defined(_USE_CZ80)
113 if (*(int *)data == 0x00007a43) { // "Cz" save?
b8a1c09a 114 memcpy(&CZ80, data+8, offsetof(cz80_struc, BasePC));
c8d1e9b6 115 Cz80_Set_Reg(&CZ80, CZ80_PC, *(int *)(data+4));
b4db550e 116 return 0;
c8d1e9b6 117 }
118#endif
b4db550e 119 return -1;
c8d1e9b6 120}
121
b4db550e 122struct z80sr_main {
123 u8 a, f;
124 u8 b, c;
125 u8 d, e;
126 u8 h, l;
127};
128
129struct z80_state {
130 char magic[4];
131 // regs
132 struct z80sr_main m; // main regs
133 struct z80sr_main a; // alt (') regs
134 u8 i, r;
135 u16 ix, iy;
136 u16 sp;
137 u16 pc;
138 // other
139 u8 halted;
140 u8 iff1, iff2;
141 u8 im; // irq mode
142 u8 irq_pending; // irq line level, 1 if active
143 u8 irq_vector[3]; // up to 3 byte vector for irq mode0 handling
144 u8 reserved[8];
145};
146
147void z80_pack(void *data)
c8d1e9b6 148{
b4db550e 149 struct z80_state *s = data;
150 memset(data, 0, Z80_STATE_SIZE);
151 strcpy(s->magic, "Z80");
152#if defined(_USE_DRZ80)
153 #define DRR8(n) (drZ80.Z80##n >> 24)
154 #define DRR16(n) (drZ80.Z80##n >> 16)
155 #define DRR16H(n) (drZ80.Z80##n >> 24)
156 #define DRR16L(n) ((drZ80.Z80##n >> 16) & 0xff)
157 s->m.a = DRR8(A); s->m.f = DRR8(F);
158 s->m.b = DRR16H(BC); s->m.c = DRR16L(BC);
159 s->m.d = DRR16H(DE); s->m.e = DRR16L(DE);
160 s->m.h = DRR16H(HL); s->m.l = DRR16L(HL);
161 s->a.a = DRR8(A2); s->a.f = DRR8(F2);
162 s->a.b = DRR16H(BC2); s->a.c = DRR16L(BC2);
163 s->a.d = DRR16H(DE2); s->a.e = DRR16L(DE2);
164 s->a.h = DRR16H(HL2); s->a.l = DRR16L(HL2);
165 s->i = DRR8(I); s->r = drZ80.spare;
166 s->ix = DRR16(IX); s->iy = DRR16(IY);
167 s->sp = drZ80.Z80SP - drZ80.Z80SP_BASE;
168 s->pc = drZ80.Z80PC - drZ80.Z80PC_BASE;
169 s->halted = !!(drZ80.Z80IF & 4);
170 s->iff1 = !!(drZ80.Z80IF & 1);
171 s->iff2 = !!(drZ80.Z80IF & 2);
172 s->im = drZ80.Z80IM;
173 s->irq_pending = !!drZ80.Z80_IRQ;
174 s->irq_vector[0] = drZ80.z80irqvector >> 16;
175 s->irq_vector[1] = drZ80.z80irqvector >> 8;
176 s->irq_vector[2] = drZ80.z80irqvector;
177#elif defined(_USE_CZ80)
178 {
179 const cz80_struc *CPU = &CZ80;
180 s->m.a = zA; s->m.f = zF;
181 s->m.b = zB; s->m.c = zC;
182 s->m.d = zD; s->m.e = zE;
183 s->m.h = zH; s->m.l = zL;
184 s->a.a = zA2; s->a.f = zF2;
185 s->a.b = CZ80.BC2.B.H; s->a.c = CZ80.BC2.B.L;
186 s->a.d = CZ80.DE2.B.H; s->a.e = CZ80.DE2.B.L;
187 s->a.h = CZ80.HL2.B.H; s->a.l = CZ80.HL2.B.L;
188 s->i = zI; s->r = zR;
189 s->ix = zIX; s->iy = zIY;
190 s->sp = Cz80_Get_Reg(&CZ80, CZ80_SP);
191 s->pc = Cz80_Get_Reg(&CZ80, CZ80_PC);
192 s->halted = !!Cz80_Get_Reg(&CZ80, CZ80_HALT);
193 s->iff1 = !!zIFF1;
194 s->iff2 = !!zIFF2;
195 s->im = zIM;
196 s->irq_pending = (Cz80_Get_Reg(&CZ80, CZ80_IRQ) == HOLD_LINE);
197 s->irq_vector[0] = 0xff;
198 }
c8d1e9b6 199#endif
200}
201
b4db550e 202int z80_unpack(const void *data)
203{
204 const struct z80_state *s = data;
205 if (strcmp(s->magic, "Z80") != 0) {
206 if (z80_unpack_legacy(data) != 0)
207 goto fail;
208 elprintf(EL_STATUS, "legacy z80 state");
209 return 0;
210 }
211
212#if defined(_USE_DRZ80)
213 #define DRW8(n, v) drZ80.Z80##n = (u32)(v) << 24
214 #define DRW16(n, v) drZ80.Z80##n = (u32)(v) << 16
215 #define DRW16HL(n, h, l) drZ80.Z80##n = ((u32)(h) << 24) | ((u32)(l) << 16)
216 DRW8(A, s->m.a); DRW8(F, s->m.f);
217 DRW16HL(BC, s->m.b, s->m.c);
218 DRW16HL(DE, s->m.d, s->m.e);
219 DRW16HL(HL, s->m.h, s->m.l);
220 DRW8(A2, s->a.a); DRW8(F2, s->a.f);
221 DRW16HL(BC2, s->a.b, s->a.c);
222 DRW16HL(DE2, s->a.d, s->a.e);
223 DRW16HL(HL2, s->a.h, s->a.l);
224 DRW8(I, s->i); drZ80.spare = s->r;
225 DRW16(IX, s->ix); DRW16(IY, s->iy);
226 drz80_load_pcsp(s->pc, s->sp);
227 drZ80.Z80IF = 0;
228 if (s->halted) drZ80.Z80IF |= 4;
229 if (s->iff1) drZ80.Z80IF |= 1;
230 if (s->iff2) drZ80.Z80IF |= 2;
231 drZ80.Z80IM = s->im;
232 drZ80.Z80_IRQ = s->irq_pending;
233 drZ80.z80irqvector = ((u32)s->irq_vector[0] << 16) |
234 ((u32)s->irq_vector[1] << 8) | s->irq_vector[2];
235 return 0;
236#elif defined(_USE_CZ80)
237 {
238 cz80_struc *CPU = &CZ80;
239 zA = s->m.a; zF = s->m.f;
240 zB = s->m.b; zC = s->m.c;
241 zD = s->m.d; zE = s->m.e;
242 zH = s->m.h; zL = s->m.l;
243 zA2 = s->a.a; zF2 = s->a.f;
244 CZ80.BC2.B.H = s->a.b; CZ80.BC2.B.L = s->a.c;
245 CZ80.DE2.B.H = s->a.d; CZ80.DE2.B.L = s->a.e;
246 CZ80.HL2.B.H = s->a.h; CZ80.HL2.B.L = s->a.l;
247 zI = s->i; zR = s->r;
248 zIX = s->ix; zIY = s->iy;
249 Cz80_Set_Reg(&CZ80, CZ80_SP, s->sp);
250 Cz80_Set_Reg(&CZ80, CZ80_PC, s->pc);
251 Cz80_Set_Reg(&CZ80, CZ80_HALT, s->halted);
252 Cz80_Set_Reg(&CZ80, CZ80_IFF1, s->iff1);
253 Cz80_Set_Reg(&CZ80, CZ80_IFF2, s->iff2);
254 zIM = s->im;
255 Cz80_Set_Reg(&CZ80, CZ80_IRQ, s->irq_pending ? HOLD_LINE : CLEAR_LINE);
256 return 0;
257 }
258#endif
259
260fail:
261 elprintf(EL_STATUS|EL_ANOMALY, "z80_unpack failed");
262 z80_reset();
263 z80_int();
264 return -1;
265}
266
267void z80_exit(void)
268{
269}
270
271void z80_debug(char *dstr)
c8d1e9b6 272{
273#if defined(_USE_DRZ80)
274 sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", drZ80.Z80PC-drZ80.Z80PC_BASE, drZ80.Z80SP-drZ80.Z80SP_BASE);
275#elif defined(_USE_CZ80)
b8a1c09a 276 sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", (unsigned int)(CZ80.PC - CZ80.BasePC), CZ80.SP.W);
c8d1e9b6 277#endif
278}