32x: initial code (security code passes)
[picodrive.git] / pico / 32x / memory.c
CommitLineData
be2c4208 1#include "../pico_int.h"
2#include "../memory.h"
3
4static const char str_mars[] = "MARS";
5
6struct Pico32xMem {
7 u8 sdram[0x40000];
8 u8 dram[0x40000]; // AKA fb
9 u8 m68k_rom[M68K_BANK_SIZE]; // 0x100
10};
11
12static struct Pico32xMem *Pico32xMem;
13
14static u32 p32x_reg_read16(u32 a)
15{
16 a &= 0x3e;
17
18 return Pico32x.regs[a / 2];
19}
20
21static void p32x_reg_write16(u32 a, u32 d)
22{
23 a &= 0x3e;
24
25 if (a == 0 && !(Pico32x.regs[0] & 1)) {
26 Pico32x.regs[0] |= 1;
27 Pico32xStartup();
28 return;
29 }
30}
31
32static void p32x_reg_write8(u32 a, u32 d)
33{
34 a &= 0x3f;
35
36 if (a == 1 && !(Pico32x.regs[0] & 1)) {
37 Pico32x.regs[0] |= 1;
38 Pico32xStartup();
39 return;
40 }
41}
42
43// VDP regs
44static u32 p32x_vdp_read16(u32 a)
45{
46 a &= 0x0e;
47
48 return Pico32x.vdp_regs[a / 2];
49}
50
51static void p32x_vdp_write16(u32 a, u32 d)
52{
53 a &= 0x0e;
54
55 switch (a) {
56 case 0x0a:
57 Pico32x.pending_fb = d & 1;
58 if (Pico.video.status & 8) {
59 Pico32x.vdp_regs[0x0a/2] &= ~1;
60 Pico32x.vdp_regs[0x0a/2] |= d & 1;
61 }
62 break;
63 }
64}
65
66static void p32x_vdp_write8(u32 a, u32 d)
67{
68 a &= 0x0f;
69
70 switch (a) {
71 case 0x0b:
72 Pico32x.pending_fb = d & 1;
73 if (Pico.video.status & 8) {
74 Pico32x.vdp_regs[0x0a/2] &= ~1;
75 Pico32x.vdp_regs[0x0a/2] |= d & 1;
76 }
77 break;
78 }
79}
80
81// default 32x handlers
82u32 PicoRead8_32x(u32 a)
83{
84 u32 d = 0;
85 if ((a & 0xffc0) == 0x5100) { // a15100
86 d = p32x_reg_read16(a);
87 goto out_16to8;
88 }
89
90 if ((a & 0xfff0) == 0x5180 && (Pico32x.regs[0] & 1)) {
91 d = p32x_vdp_read16(a);
92 goto out_16to8;
93 }
94
95 if ((a & 0xfffc) == 0x30ec) { // a130ec
96 d = str_mars[a & 3];
97 goto out;
98 }
99
100 elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc);
101 return d;
102
103out_16to8:
104 if (a & 1)
105 d &= 0xff;
106 else
107 d >>= 8;
108
109out:
110 elprintf(EL_32X, "m68k 32x r8 [%06x] %02x @%06x", a, d, SekPc);
111 return d;
112}
113
114u32 PicoRead16_32x(u32 a)
115{
116 u32 d = 0;
117 if ((a & 0xffc0) == 0x5100) { // a15100
118 d = p32x_reg_read16(a);
119 goto out;
120 }
121
122 if ((a & 0xfff0) == 0x5180 && (Pico32x.regs[0] & 1)) { // a15180
123 d = p32x_vdp_read16(a);
124 goto out;
125 }
126
127 if ((a & 0xfffc) == 0x30ec) { // a130ec
128 d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
129 goto out;
130 }
131
132 elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
133 return d;
134
135out:
136 elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
137 return d;
138}
139
140void PicoWrite8_32x(u32 a, u32 d)
141{
142 if ((a & 0xfc00) == 0x5000)
143 elprintf(EL_32X, "m68k 32x w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
144
145 if ((a & 0xffc0) == 0x5100) { // a15100
146 p32x_reg_write8(a, d);
147 return;
148 }
149
150 if ((a & 0xfff0) == 0x5180 && (Pico32x.regs[0] & 1)) { // a15180
151 p32x_vdp_write8(a, d);
152 return;
153 }
154
155 elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
156}
157
158void PicoWrite16_32x(u32 a, u32 d)
159{
160 if ((a & 0xfc00) == 0x5000)
161 elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
162
163 if ((a & 0xffc0) == 0x5100) { // a15100
164 p32x_reg_write16(a, d);
165 return;
166 }
167
168 if ((a & 0xfff0) == 0x5180 && (Pico32x.regs[0] & 1)) { // a15180
169 p32x_vdp_write16(a, d);
170 return;
171 }
172
173 elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
174}
175
176// hint vector is writeable
177static void PicoWrite8_hint(u32 a, u32 d)
178{
179 if ((a & 0xfffc) == 0x0070) {
180 Pico32xMem->m68k_rom[a ^ 1] = d;
181 return;
182 }
183
184 elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
185}
186
187static void PicoWrite16_hint(u32 a, u32 d)
188{
189 if ((a & 0xfffc) == 0x0070) {
190 ((u16 *)Pico32xMem->m68k_rom)[a/2] = d;
191 return;
192 }
193
194 elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
195}
196
197#define HWSWAP(x) (((x) << 16) | ((x) >> 16))
198void PicoMemSetup32x(void)
199{
200 unsigned short *ps;
201 unsigned int *pl;
202 unsigned int rs, rs1;
203 int i;
204
205 Pico32xMem = calloc(1, sizeof(*Pico32xMem));
206 if (Pico32xMem == NULL) {
207 elprintf(EL_STATUS, "OOM");
208 return;
209 }
210
211 // generate 68k ROM
212 ps = (unsigned short *)Pico32xMem->m68k_rom;
213 pl = (unsigned int *)Pico32xMem->m68k_rom;
214 for (i = 1; i < 0xc0/4; i++)
215 pl[i] = HWSWAP(0x880200 + i * 6);
216
217 // fill with nops
218 for (i = 0xc0/2; i < 0x100/2; i++)
219 ps[i] = 0x4e71;
220
221 ps[0xc0/2] = 0x46fc;
222 ps[0xc2/2] = 0x2700; // move #0x2700,sr
223 ps[0xfe/2] = 0x60fe; // jump to self
224
225 // fill remaining mem with ROM
226 memcpy(Pico32xMem->m68k_rom + 0x100, Pico.rom + 0x100, M68K_BANK_SIZE - 0x100);
227
228 // cartridge area becomes unmapped
229 // XXX: we take the easy way and don't unmap ROM,
230 // so that we can avoid handling the RV bit.
231 // m68k_map_unmap(0x000000, 0x3fffff);
232
233 // MD ROM area
234 cpu68k_map_set(m68k_read8_map, 0x000000, M68K_BANK_SIZE - 1, Pico32xMem->m68k_rom, 0);
235 cpu68k_map_set(m68k_read16_map, 0x000000, M68K_BANK_SIZE - 1, Pico32xMem->m68k_rom, 0);
236 cpu68k_map_set(m68k_write8_map, 0x000000, M68K_BANK_SIZE - 1, PicoWrite8_hint, 1); // TODO verify
237 cpu68k_map_set(m68k_write16_map, 0x000000, M68K_BANK_SIZE - 1, PicoWrite16_hint, 1);
238
239 // 32X ROM (unbanked, XXX: consider mirroring?)
240 rs1 = rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
241 if (rs1 > 0x80000)
242 rs1 = 0x80000;
243 cpu68k_map_set(m68k_read8_map, 0x880000, 0x880000 + rs1 - 1, Pico.rom, 0);
244 cpu68k_map_set(m68k_read16_map, 0x880000, 0x880000 + rs1 - 1, Pico.rom, 0);
245
246 // 32X ROM (banked)
247 if (rs > 0x100000)
248 rs = 0x100000;
249 cpu68k_map_set(m68k_read8_map, 0x900000, 0x900000 + rs - 1, Pico.rom, 0);
250 cpu68k_map_set(m68k_read16_map, 0x900000, 0x900000 + rs - 1, Pico.rom, 0);
251}
252