comparison segacd.c @ 1502:2564b6ba2e12 segacd

Initial skeleton of Sega CD memory handlers
author Michael Pavone <pavone@retrodev.com>
date Tue, 12 Dec 2017 09:44:33 -0800
parents d51230205405
children a763523dadf4
comparison
equal deleted inserted replaced
1472:d2d637dbacfb 1502:2564b6ba2e12
1 #include <stdlib.h>
2 #include <string.h>
3 #include "segacd.h"
4 #include "genesis.h"
5 #include "util.h"
6
7 static void *prog_ram_wp_write16(uint32_t address, void *vcontext, uint16_t value)
8 {
9 return vcontext;
10 }
11
12 static void *prog_ram_wp_write8(uint32_t address, void *vcontext, uint8_t value)
13 {
14 return vcontext;
15 }
16
17 static uint16_t work_ram_2M_read16(uint32_t address, void *vcontext)
18 {
19 return 0;
20 }
21
22 static uint8_t work_ram_2M_read8(uint32_t address, void *vcontext)
23 {
24 return 0;
25 }
26
27 static void *work_ram_2M_write16(uint32_t address, void *vcontext, uint16_t value)
28 {
29 return vcontext;
30 }
31
32 static void *work_ram_2M_write8(uint32_t address, void *vcontext, uint8_t value)
33 {
34 return vcontext;
35 }
36
37 static uint16_t work_ram_1M_read16(uint32_t address, void *vcontext)
38 {
39 return 0;
40 }
41
42 static uint8_t work_ram_1M_read8(uint32_t address, void *vcontext)
43 {
44 return 0;
45 }
46
47 static void *work_ram_1M_write16(uint32_t address, void *vcontext, uint16_t value)
48 {
49 return vcontext;
50 }
51
52 static void *work_ram_1M_write8(uint32_t address, void *vcontext, uint8_t value)
53 {
54 return vcontext;
55 }
56
57 static uint8_t pcm_read8(uint32_t address, void *vcontext)
58 {
59 return 0;
60 }
61
62 static uint16_t pcm_read16(uint32_t address, void *vcontext)
63 {
64 return 0xFF00 | pcm_read8(address+1, vcontext);
65 }
66
67 static void *pcm_write8(uint32_t address, void *vcontext, uint8_t value)
68 {
69 return vcontext;
70 }
71
72 static void *pcm_write16(uint32_t address, void *vcontext, uint16_t value)
73 {
74 return pcm_write8(address+1, vcontext, value);
75 }
76
77 static uint16_t sub_gate_read16(uint32_t address, void *vcontext)
78 {
79 m68k_context *m68k = vcontext;
80 segacd_context *cd = m68k->system;
81 return cd->gate_array[(address & 0x1FF) >> 1];
82 }
83
84 static uint8_t sub_gate_read8(uint32_t address, void *vcontext)
85 {
86 m68k_context *m68k = vcontext;
87 segacd_context *cd = m68k->system;
88 uint16_t val = cd->gate_array[(address & 0x1FF) >> 1];
89 return address & 1 ? val : val >> 8;
90 }
91
92 static void *sub_gate_write16(uint32_t address, void *vcontext, uint16_t value)
93 {
94 m68k_context *m68k = vcontext;
95 segacd_context *cd = m68k->system;
96 uint32_t reg = (address & 0x1FF) >> 1;
97 switch (reg)
98 {
99 case 0x7:
100 cd->gate_array[reg] &= 0xFF00;
101 cd->gate_array[reg] |= value & 0xFF;
102 break;
103 case 0x10:
104 case 0x11:
105 case 0x12:
106 case 0x13:
107 case 0x14:
108 case 0x15:
109 case 0x16:
110 case 0x17:
111 //no effects for these other than saving the value
112 cd->gate_array[reg] = value;
113 break;
114 default:
115 printf("Unhandled gate array write %X:%X\n", address, value);
116 }
117 return vcontext;
118 }
119
120 static void *sub_gate_write8(uint32_t address, void *vcontext, uint8_t value)
121 {
122 m68k_context *m68k = vcontext;
123 segacd_context *cd = m68k->system;
124 uint32_t reg = (address & 0x1FF) >> 1;
125 uint16_t value16;
126 if (address & 1) {
127 value16 = cd->gate_array[reg] & 0xFF00 | value;
128 } else {
129 value16 = cd->gate_array[reg] & 0xFF | (value << 8);
130 }
131 return sub_gate_write16(address, vcontext, value16);
132 }
133
134 static uint16_t main_gate_read16(uint32_t address, void *vcontext)
135 {
136 m68k_context *m68k = vcontext;
137 segacd_context *cd = m68k->system;
138 return cd->gate_array[(address & 0x1FF) >> 1];
139 }
140
141 static uint8_t main_gate_read8(uint32_t address, void *vcontext)
142 {
143 m68k_context *m68k = vcontext;
144 segacd_context *cd = m68k->system;
145 uint16_t val = cd->gate_array[(address & 0x1FF) >> 1];
146 return address & 1 ? val : val >> 8;
147 }
148
149 static void *main_gate_write16(uint32_t address, void *vcontext, uint16_t value)
150 {
151 m68k_context *m68k = vcontext;
152 genesis_context *gen = m68k->system;
153 segacd_context *cd = gen->expansion;
154 uint32_t reg = (address & 0x1FF) >> 1;
155 switch (reg)
156 {
157 case 0x7:
158 cd->gate_array[reg] &= 0xFF;
159 cd->gate_array[reg] |= value & 0xFF00;
160 break;
161 case 0x8:
162 case 0x9:
163 case 0xA:
164 case 0xB:
165 case 0xC:
166 case 0xD:
167 case 0xE:
168 case 0xF:
169 //no effects for these other than saving the value
170 cd->gate_array[reg] = value;
171 break;
172 default:
173 printf("Unhandled gate array write %X:%X\n", address, value);
174 }
175 return vcontext;
176 }
177
178 static void *main_gate_write8(uint32_t address, void *vcontext, uint8_t value)
179 {
180 m68k_context *m68k = vcontext;
181 genesis_context *gen = m68k->system;
182 segacd_context *cd = gen->expansion;
183 uint32_t reg = (address & 0x1FF) >> 1;
184 uint16_t value16;
185 if (address & 1) {
186 value16 = cd->gate_array[reg] & 0xFF00 | value;
187 } else {
188 value16 = cd->gate_array[reg] & 0xFF | (value << 8);
189 }
190 return main_gate_write16(address, vcontext, value16);
191 }
192
193 segacd_context *alloc_configure_segacd(system_media *media, uint32_t opts, uint8_t force_region, rom_info *info)
194 {
195 static memmap_chunk sub_cpu_map[] = {
196 {0x000000, 0x00FEFF, 0x0000, .flags=MMAP_READ | MMAP_CODE, .write_16 = prog_ram_wp_write16, .write_8 = prog_ram_wp_write8},
197 {0x00FF00, 0x07FFFF, 0x0000, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE},
198 {0x080000, 0x0BFFFF, 0x0000, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE | MMAP_PTR_IDX | MMAP_FUNC_NULL, .ptr_index = 0,
199 .read_16 = work_ram_2M_read16, .write_16 = work_ram_2M_write16, .read_8 = work_ram_2M_read8, .write_8 = work_ram_2M_write8},
200 {0x0C0000, 0x0DFFFF, 0x0000, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE | MMAP_PTR_IDX | MMAP_FUNC_NULL, .ptr_index = 1,
201 .read_16 = work_ram_1M_read16, .write_16 = work_ram_1M_write16, .read_8 = work_ram_1M_read8, .write_8 = work_ram_1M_write8},
202 {0xFE0000, 0xFEFFFF, 0x3FFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_ONLY_ODD},
203 {0xFF0000, 0xFF7FFF, 0x0000, .read_16 = pcm_read16, .write_16 = pcm_write16, .read_8 = pcm_read8, .write_8 = pcm_write8},
204 {0xFF8000, 0xFF81FF, 0x0000, .read_16 = sub_gate_read16, .write_16 = sub_gate_write16, .read_8 = sub_gate_read8, .write_8 = sub_gate_write8}
205 };
206 segacd_context *cd = calloc(sizeof(segacd_context), 1);
207 FILE *f = fopen("cdbios.bin", "rb");
208 if (!f) {
209 fatal_error("Failed to open CD firmware for reading");
210 }
211 long firmware_size = file_size(f);
212 uint32_t adjusted_size = nearest_pow2(firmware_size);
213 cd->rom = malloc(adjusted_size);
214 if (firmware_size != fread(cd->rom, 1, firmware_size, f)) {
215 fatal_error("Failed to read CD firmware");
216 }
217 cd->rom_mut = malloc(adjusted_size);
218 memcpy(cd->rom_mut, cd->rom, adjusted_size);
219 byteswap_rom(firmware_size, cd->rom);
220 cd->prog_ram = malloc(512*1024);
221 cd->work_ram = malloc(256*1024);
222 cd->pcm_ram = malloc(64*1024);
223 //TODO: Load state from file
224 cd->bram = malloc(8*1024);
225
226 sub_cpu_map[0].buffer = sub_cpu_map[1].buffer = cd->prog_ram;
227 sub_cpu_map[4].buffer = cd->bram;
228 m68k_options *mopts = malloc(sizeof(m68k_options));
229 init_m68k_opts(mopts, sub_cpu_map, sizeof(sub_cpu_map) / sizeof(*sub_cpu_map), 4);
230 cd->m68k = init_68k_context(mopts, NULL);
231 cd->m68k->system = cd;
232 cd->busreq = 1;
233 cd->busack = 1;
234
235 return cd;
236 }
237
238 memmap_chunk *segacd_main_cpu_map(segacd_context *cd, uint32_t *num_chunks)
239 {
240 static memmap_chunk main_cpu_map[] = {
241 {0x000000, 0x01FFFF, 0x00000, .flags=MMAP_READ},
242 {0x020000, 0x03FFFF, 0x1FFFF, .flags=MMAP_READ|MMAP_WRITE|MMAP_PTR_IDX|MMAP_FUNC_NULL, .ptr_index = 0},//TODO: support running main CPU code from here
243 {0x040000, 0x05FFFF, 0x1FFFF, .flags=MMAP_READ}, //first ROM alias
244 //TODO: additional ROM/prog RAM aliases
245 {0x200000, 0x01FFFF, 0x1FFFF, .flags=MMAP_READ|MMAP_WRITE|MMAP_PTR_IDX|MMAP_FUNC_NULL, .ptr_index = 1},
246 {0x220000, 0x03FFFF, 0x1FFFF, .flags=MMAP_READ|MMAP_WRITE|MMAP_PTR_IDX|MMAP_FUNC_NULL, .ptr_index = 2},
247 };
248 //TODO: support cart boot maps
249 //TODO: support BRAM cart
250 main_cpu_map[0].buffer = cd->rom_mut;
251 main_cpu_map[2].buffer = cd->rom;
252 main_cpu_map[1].buffer = cd->prog_ram;
253 main_cpu_map[3].buffer = cd->work_ram;
254 main_cpu_map[3].buffer = cd->work_ram + 0x10000;
255 *num_chunks = sizeof(main_cpu_map) / sizeof(*main_cpu_map);
256 return main_cpu_map;
257 }