b8a1c09a |
1 | #include <stddef.h> |
c8d1e9b6 |
2 | #include "pico_int.h" |
b8a1c09a |
3 | #include "memory.h" |
c8d1e9b6 |
4 | |
b8a1c09a |
5 | uptr z80_read_map [0x10000 >> Z80_MEM_SHIFT]; |
6 | uptr z80_write_map[0x10000 >> Z80_MEM_SHIFT]; |
c8d1e9b6 |
7 | |
c8d1e9b6 |
8 | #ifdef _USE_MZ80 |
9 | |
10 | // memhandlers for mz80 core |
11 | unsigned char mz80_read(UINT32 a, struct MemoryReadByte *w) { return z80_read(a); } |
12 | void mz80_write(UINT32 a, UINT8 d, struct MemoryWriteByte *w) { z80_write(d, a); } |
13 | |
14 | // structures for mz80 core |
15 | static struct MemoryReadByte mz80_mem_read[]= |
16 | { |
17 | {0x0000,0xffff,mz80_read}, |
18 | {(UINT32) -1,(UINT32) -1,NULL} |
19 | }; |
20 | static struct MemoryWriteByte mz80_mem_write[]= |
21 | { |
22 | {0x0000,0xffff,mz80_write}, |
23 | {(UINT32) -1,(UINT32) -1,NULL} |
24 | }; |
25 | static struct z80PortRead mz80_io_read[] ={ |
26 | {(UINT16) -1,(UINT16) -1,NULL} |
27 | }; |
28 | static struct z80PortWrite mz80_io_write[]={ |
29 | {(UINT16) -1,(UINT16) -1,NULL} |
30 | }; |
31 | |
32 | int mz80_run(int cycles) |
33 | { |
34 | int ticks_pre = mz80GetElapsedTicks(0); |
35 | mz80exec(cycles); |
36 | return mz80GetElapsedTicks(0) - ticks_pre; |
37 | } |
38 | |
39 | #endif |
40 | |
41 | #ifdef _USE_DRZ80 |
c8d1e9b6 |
42 | struct DrZ80 drZ80; |
c8d1e9b6 |
43 | #endif |
44 | |
45 | |
46 | PICO_INTERNAL void z80_init(void) |
47 | { |
48 | #ifdef _USE_MZ80 |
49 | struct mz80context z80; |
50 | |
51 | // z80 |
52 | mz80init(); |
53 | // Modify the default context |
54 | mz80GetContext(&z80); |
55 | |
56 | // point mz80 stuff |
57 | z80.z80Base=Pico.zram; |
58 | z80.z80MemRead=mz80_mem_read; |
59 | z80.z80MemWrite=mz80_mem_write; |
60 | z80.z80IoRead=mz80_io_read; |
61 | z80.z80IoWrite=mz80_io_write; |
62 | |
63 | mz80SetContext(&z80); |
64 | #endif |
65 | #ifdef _USE_DRZ80 |
66 | memset(&drZ80, 0, sizeof(drZ80)); |
ee05564f |
67 | drZ80.z80_rebasePC=NULL; // unused, handled by xmap |
68 | drZ80.z80_rebaseSP=NULL; |
c8d1e9b6 |
69 | drZ80.z80_read8 =(void *)z80_read_map; |
70 | drZ80.z80_read16 =NULL; |
71 | drZ80.z80_write8 =(void *)z80_write_map; |
72 | drZ80.z80_write16 =NULL; |
73 | drZ80.z80_irq_callback=NULL; |
74 | #endif |
75 | #ifdef _USE_CZ80 |
76 | memset(&CZ80, 0, sizeof(CZ80)); |
77 | Cz80_Init(&CZ80); |
78 | Cz80_Set_ReadB(&CZ80, NULL); // unused (hacked in) |
79 | Cz80_Set_WriteB(&CZ80, NULL); |
80 | #endif |
81 | } |
82 | |
83 | PICO_INTERNAL void z80_reset(void) |
84 | { |
85 | #ifdef _USE_MZ80 |
86 | mz80reset(); |
87 | #endif |
88 | #ifdef _USE_DRZ80 |
89 | memset(&drZ80, 0, 0x54); |
90 | drZ80.Z80F = (1<<2); // set ZFlag |
91 | drZ80.Z80F2 = (1<<2); // set ZFlag |
92 | drZ80.Z80IX = 0xFFFF << 16; |
93 | drZ80.Z80IY = 0xFFFF << 16; |
94 | drZ80.Z80IM = 0; // 1? |
95 | drZ80.z80irqvector = 0xff0000; // RST 38h |
ee05564f |
96 | drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0] << 1; |
d8f51995 |
97 | // drZ80 is locked in single bank |
3e49ffd0 |
98 | drZ80.Z80SP_BASE = ((PicoAHW & PAHW_SMS) ? |
99 | z80_read_map[0xc000 >> Z80_MEM_SHIFT] : z80_read_map[0]) << 1; |
ee05564f |
100 | // drZ80.Z80SP = drZ80.z80_rebaseSP(0x2000); // 0xf000 ? |
c8d1e9b6 |
101 | #endif |
102 | #ifdef _USE_CZ80 |
103 | Cz80_Reset(&CZ80); |
104 | Cz80_Set_Reg(&CZ80, CZ80_IX, 0xffff); |
105 | Cz80_Set_Reg(&CZ80, CZ80_IY, 0xffff); |
106 | Cz80_Set_Reg(&CZ80, CZ80_SP, 0x2000); |
107 | #endif |
c8d1e9b6 |
108 | } |
109 | |
ee05564f |
110 | // XXX TODO: should better use universal z80 save format |
c8d1e9b6 |
111 | PICO_INTERNAL void z80_pack(unsigned char *data) |
112 | { |
113 | #if defined(_USE_MZ80) |
114 | struct mz80context mz80; |
115 | *(int *)data = 0x00005A6D; // "mZ" |
116 | mz80GetContext(&mz80); |
117 | memcpy(data+4, &mz80.z80clockticks, sizeof(mz80)-5*4); // don't save base&memhandlers |
118 | #elif defined(_USE_DRZ80) |
119 | *(int *)data = 0x015A7244; // "DrZ" v1 |
ee05564f |
120 | // drZ80.Z80PC = drZ80.z80_rebasePC(drZ80.Z80PC-drZ80.Z80PC_BASE); |
121 | // drZ80.Z80SP = drZ80.z80_rebaseSP(drZ80.Z80SP-drZ80.Z80SP_BASE); |
c8d1e9b6 |
122 | memcpy(data+4, &drZ80, 0x54); |
123 | #elif defined(_USE_CZ80) |
124 | *(int *)data = 0x00007a43; // "Cz" |
125 | *(int *)(data+4) = Cz80_Get_Reg(&CZ80, CZ80_PC); |
b8a1c09a |
126 | memcpy(data+8, &CZ80, offsetof(cz80_struc, BasePC)); |
c8d1e9b6 |
127 | #endif |
128 | } |
129 | |
130 | PICO_INTERNAL void z80_unpack(unsigned char *data) |
131 | { |
132 | #if defined(_USE_MZ80) |
133 | if (*(int *)data == 0x00005A6D) { // "mZ" save? |
134 | struct mz80context mz80; |
135 | mz80GetContext(&mz80); |
136 | memcpy(&mz80.z80clockticks, data+4, sizeof(mz80)-5*4); |
137 | mz80SetContext(&mz80); |
138 | } else { |
139 | z80_reset(); |
140 | z80_int(); |
141 | } |
142 | #elif defined(_USE_DRZ80) |
143 | if (*(int *)data == 0x015A7244) { // "DrZ" v1 save? |
ee05564f |
144 | int pc, sp; |
c8d1e9b6 |
145 | memcpy(&drZ80, data+4, 0x54); |
ee05564f |
146 | pc = (drZ80.Z80PC - drZ80.Z80PC_BASE) & 0xffff; |
147 | sp = (drZ80.Z80SP - drZ80.Z80SP_BASE) & 0xffff; |
c8d1e9b6 |
148 | // update bases |
ee05564f |
149 | drZ80.Z80PC_BASE = z80_read_map[pc >> Z80_MEM_SHIFT]; |
150 | if (drZ80.Z80PC & (1<<31)) { |
151 | elprintf(EL_STATUS|EL_ANOMALY, "bad PC in z80 save: %04x", pc); |
152 | drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0]; |
153 | } else { |
154 | drZ80.Z80PC_BASE <<= 1; |
155 | drZ80.Z80PC = drZ80.Z80PC_BASE + pc; |
156 | } |
157 | drZ80.Z80SP_BASE = z80_read_map[sp >> Z80_MEM_SHIFT]; |
158 | if (drZ80.Z80SP & (1<<31)) { |
159 | elprintf(EL_STATUS|EL_ANOMALY, "bad SP in z80 save: %04x", sp); |
160 | drZ80.Z80SP_BASE = z80_read_map[0]; |
161 | drZ80.Z80SP = drZ80.Z80SP_BASE + (1 << Z80_MEM_SHIFT); |
162 | } else { |
163 | drZ80.Z80SP_BASE <<= 1; |
164 | drZ80.Z80SP = drZ80.Z80SP_BASE + sp; |
165 | } |
c8d1e9b6 |
166 | } else { |
167 | z80_reset(); |
168 | drZ80.Z80IM = 1; |
169 | z80_int(); // try to goto int handler, maybe we won't execute trash there? |
170 | } |
171 | #elif defined(_USE_CZ80) |
172 | if (*(int *)data == 0x00007a43) { // "Cz" save? |
b8a1c09a |
173 | memcpy(&CZ80, data+8, offsetof(cz80_struc, BasePC)); |
c8d1e9b6 |
174 | Cz80_Set_Reg(&CZ80, CZ80_PC, *(int *)(data+4)); |
175 | } else { |
176 | z80_reset(); |
177 | z80_int(); |
178 | } |
179 | #endif |
180 | } |
181 | |
182 | PICO_INTERNAL void z80_exit(void) |
183 | { |
184 | #if defined(_USE_MZ80) |
185 | mz80shutdown(); |
186 | #endif |
187 | } |
188 | |
189 | PICO_INTERNAL void z80_debug(char *dstr) |
190 | { |
191 | #if defined(_USE_DRZ80) |
192 | sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", drZ80.Z80PC-drZ80.Z80PC_BASE, drZ80.Z80SP-drZ80.Z80SP_BASE); |
193 | #elif defined(_USE_CZ80) |
b8a1c09a |
194 | sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", (unsigned int)(CZ80.PC - CZ80.BasePC), CZ80.SP.W); |
c8d1e9b6 |
195 | #endif |
196 | } |