comparison segacd.c @ 2054:8ee7ecbf3f21 segacd

Implement enough of Sega CD gate array and Sub CPU to pass Sik's Mode 1 test ROM
author Michael Pavone <pavone@retrodev.com>
date Tue, 18 Jan 2022 00:03:50 -0800
parents 95b3a1a8b26c
children c4d066d798c4
comparison
equal deleted inserted replaced
2053:3414a4423de1 2054:8ee7ecbf3f21
2 #include <string.h> 2 #include <string.h>
3 #include "segacd.h" 3 #include "segacd.h"
4 #include "genesis.h" 4 #include "genesis.h"
5 #include "util.h" 5 #include "util.h"
6 6
7 #define SCD_MCLKS 50000000
8 #define SCD_PERIPH_RESET_CLKS (SCD_MCLKS / 10)
9 #define TIMER_TICK_CLKS 1536
10
11 enum {
12 GA_SUB_CPU_CTRL,
13 GA_MEM_MODE,
14 GA_CDC_CTRL,
15 GA_CDC_REG_DATA,
16 GA_CDC_HOST_DATA,
17 GA_CDC_DMA_ADDR,
18 GA_STOP_WATCH,
19 GA_COMM_FLAG,
20 GA_COMM_CMD0,
21 GA_COMM_CMD1,
22 GA_COMM_CMD2,
23 GA_COMM_CMD3,
24 GA_COMM_CMD4,
25 GA_COMM_CMD5,
26 GA_COMM_CMD6,
27 GA_COMM_CMD7,
28 GA_COMM_STATUS0,
29 GA_COMM_STATUS1,
30 GA_COMM_STATUS2,
31 GA_COMM_STATUS3,
32 GA_COMM_STATUS4,
33 GA_COMM_STATUS5,
34 GA_COMM_STATUS6,
35 GA_COMM_STATUS7,
36 GA_TIMER,
37 GA_INT_MASK,
38 GA_CDD_FADER,
39 GA_CDD_CTRL,
40
41 GA_HINT_VECTOR = GA_CDC_REG_DATA
42 };
43 //GA_SUB_CPU_CTRL
44 #define BIT_IEN2 0x8000
45 #define BIT_IFL2 0x0100
46 #define BIT_LEDG 0x0100
47 #define BIT_LEDR 0x0080
48 #define BIT_SBRQ 0x0002
49 #define BIT_SRES 0x0001
50 #define BIT_PRES 0x0001
51 //GA_MEM_MODE
52 #define MASK_PROG_BANK 0x00C0
53 #define MASK_PRIORITY 0x0018
54 #define BIT_MEM_MODE 0x0004
55 #define BIT_DMNA 0x0002
56 #define BIT_RET 0x0001
57 //GA_INT_MASK
58 #define BIT_MASK_IEN1 0x0002
59 #define BIT_MASK_IEN2 0x0004
60 #define BIT_MASK_IEN3 0x0008
61 #define BIT_MASK_IEN4 0x0010
62 #define BIT_MASK_IEN5 0x0020
63 #define BIT_MASK_IEN6 0x0040
64
7 static void *prog_ram_wp_write16(uint32_t address, void *vcontext, uint16_t value) 65 static void *prog_ram_wp_write16(uint32_t address, void *vcontext, uint16_t value)
8 { 66 {
67 m68k_context *m68k = vcontext;
68 segacd_context *cd = m68k->system;
69 if (!(cd->gate_array[GA_MEM_MODE] & (1 << ((address >> 17) + 8)))) {
70 cd->prog_ram[address >> 1] = value;
71 m68k_invalidate_code_range(m68k, address, address + 2);
72 }
9 return vcontext; 73 return vcontext;
10 } 74 }
11 75
12 static void *prog_ram_wp_write8(uint32_t address, void *vcontext, uint8_t value) 76 static void *prog_ram_wp_write8(uint32_t address, void *vcontext, uint8_t value)
13 { 77 {
14 return vcontext; 78 m68k_context *m68k = vcontext;
15 } 79 segacd_context *cd = m68k->system;
16 80 if (!(cd->gate_array[GA_MEM_MODE] & (1 << ((address >> 17) + 8)))) {
17 static uint16_t work_ram_2M_read16(uint32_t address, void *vcontext) 81 ((uint8_t *)cd->prog_ram)[address ^ 1] = value;
82 m68k_invalidate_code_range(m68k, address, address + 1);
83 }
84 return vcontext;
85 }
86
87 static uint16_t word_ram_2M_read16(uint32_t address, void *vcontext)
18 { 88 {
19 return 0; 89 return 0;
20 } 90 }
21 91
22 static uint8_t work_ram_2M_read8(uint32_t address, void *vcontext) 92 static uint8_t word_ram_2M_read8(uint32_t address, void *vcontext)
23 { 93 {
24 return 0; 94 return 0;
25 } 95 }
26 96
27 static void *work_ram_2M_write16(uint32_t address, void *vcontext, uint16_t value) 97 static void *word_ram_2M_write16(uint32_t address, void *vcontext, uint16_t value)
28 { 98 {
29 return vcontext; 99 return vcontext;
30 } 100 }
31 101
32 static void *work_ram_2M_write8(uint32_t address, void *vcontext, uint8_t value) 102 static void *word_ram_2M_write8(uint32_t address, void *vcontext, uint8_t value)
33 { 103 {
34 return vcontext; 104 return vcontext;
35 } 105 }
36 106
37 static uint16_t work_ram_1M_read16(uint32_t address, void *vcontext) 107 static uint16_t word_ram_1M_read16(uint32_t address, void *vcontext)
38 { 108 {
39 return 0; 109 return 0;
40 } 110 }
41 111
42 static uint8_t work_ram_1M_read8(uint32_t address, void *vcontext) 112 static uint8_t word_ram_1M_read8(uint32_t address, void *vcontext)
43 { 113 {
44 return 0; 114 return 0;
45 } 115 }
46 116
47 static void *work_ram_1M_write16(uint32_t address, void *vcontext, uint16_t value) 117 static void *word_ram_1M_write16(uint32_t address, void *vcontext, uint16_t value)
48 { 118 {
49 return vcontext; 119 return vcontext;
50 } 120 }
51 121
52 static void *work_ram_1M_write8(uint32_t address, void *vcontext, uint8_t value) 122 static void *word_ram_1M_write8(uint32_t address, void *vcontext, uint8_t value)
123 {
124 return vcontext;
125 }
126
127
128 static uint16_t unmapped_prog_read16(uint32_t address, void *vcontext)
129 {
130 return 0xFFFF;
131 }
132
133 static uint8_t unmapped_prog_read8(uint32_t address, void *vcontext)
134 {
135 return 0xFF;
136 }
137
138 static void *unmapped_prog_write16(uint32_t address, void *vcontext, uint16_t value)
139 {
140 return vcontext;
141 }
142
143 static void *unmapped_prog_write8(uint32_t address, void *vcontext, uint8_t value)
53 { 144 {
54 return vcontext; 145 return vcontext;
55 } 146 }
56 147
57 static uint8_t pcm_read8(uint32_t address, void *vcontext) 148 static uint8_t pcm_read8(uint32_t address, void *vcontext)
72 static void *pcm_write16(uint32_t address, void *vcontext, uint16_t value) 163 static void *pcm_write16(uint32_t address, void *vcontext, uint16_t value)
73 { 164 {
74 return pcm_write8(address+1, vcontext, value); 165 return pcm_write8(address+1, vcontext, value);
75 } 166 }
76 167
168
169 static void timers_run(segacd_context *cd, uint32_t cycle)
170 {
171 uint32_t ticks = (cycle - cd->stopwatch_cycle) / TIMER_TICK_CLKS;
172 cd->stopwatch_cycle += ticks * TIMER_TICK_CLKS;
173 cd->gate_array[GA_STOP_WATCH] += ticks;
174 cd->gate_array[GA_STOP_WATCH] &= 0xFFF;
175 if (!cd->timer_value) {
176 --ticks;
177 cd->timer_value = cd->gate_array[GA_TIMER];
178 }
179 if (cd->timer_value) {
180 while (ticks >= (cd->timer_value + 1)) {
181 ticks -= cd->timer_value + 1;
182 cd->timer_value = cd->gate_array[GA_TIMER];
183 cd->timer_pending = 1;
184 }
185 cd->timer_value -= ticks;
186 if (!cd->timer_value) {
187 cd->timer_pending = 1;
188 }
189 }
190 }
191
192 static uint32_t next_timer_int(segacd_context *cd)
193 {
194 if (cd->timer_pending) {
195 return cd->stopwatch_cycle;
196 }
197 if (cd->timer_value) {
198 return cd->stopwatch_cycle + TIMER_TICK_CLKS * cd->timer_value;
199 }
200 if (cd->gate_array[GA_TIMER]) {
201 return cd->stopwatch_cycle + TIMER_TICK_CLKS * (cd->gate_array[GA_TIMER] + 1);
202 }
203 return CYCLE_NEVER;
204 }
205
206 static void calculate_target_cycle(m68k_context * context)
207 {
208 segacd_context *cd = context->system;
209 context->int_cycle = CYCLE_NEVER;
210 uint8_t mask = context->status & 0x7;
211 if (mask < 3) {
212 uint32_t next_timer;
213 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN3) {
214 uint32_t next_timer_cycle = next_timer_int(cd);
215 if (next_timer_cycle < context->int_cycle) {
216 context->int_cycle = next_timer_cycle;
217 context->int_num = 3;
218 }
219 }
220 if (mask < 2) {
221 if (cd->int2_cycle < context->int_cycle && (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN2)) {
222 context->int_cycle = cd->int2_cycle;
223 context->int_num = 2;
224 }
225 }
226 }
227 if (context->int_cycle > context->current_cycle && context->int_pending == INT_PENDING_SR_CHANGE) {
228 context->int_pending = INT_PENDING_NONE;
229 }
230 if (context->current_cycle >= context->sync_cycle) {
231 context->should_return = 1;
232 context->target_cycle = context->current_cycle;
233 return;
234 }
235 if (context->status & M68K_STATUS_TRACE || context->trace_pending) {
236 context->target_cycle = context->current_cycle;
237 return;
238 }
239 context->target_cycle = context->sync_cycle < context->int_cycle ? context->sync_cycle : context->int_cycle;
240 }
241
77 static uint16_t sub_gate_read16(uint32_t address, void *vcontext) 242 static uint16_t sub_gate_read16(uint32_t address, void *vcontext)
78 { 243 {
79 m68k_context *m68k = vcontext; 244 m68k_context *m68k = vcontext;
80 segacd_context *cd = m68k->system; 245 segacd_context *cd = m68k->system;
81 return cd->gate_array[(address & 0x1FF) >> 1]; 246 uint32_t reg = address >> 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) 247 switch (reg)
98 { 248 {
99 case 0x7: 249 case GA_SUB_CPU_CTRL: {
250 uint16_t value = cd->gate_array[reg] & 0xFFFE;
251 if (cd->periph_reset_cycle == CYCLE_NEVER || (m68k->current_cycle - cd->periph_reset_cycle) > SCD_PERIPH_RESET_CLKS) {
252 value |= BIT_PRES;
253 }
254 return value;
255 }
256 case GA_MEM_MODE:
257 return cd->gate_array[reg] & 0xFF1F;
258 case GA_STOP_WATCH:
259 case GA_TIMER:
260 timers_run(cd, m68k->current_cycle);
261 return cd->gate_array[reg];
262 default:
263 return cd->gate_array[reg];
264 }
265 }
266
267 static uint8_t sub_gate_read8(uint32_t address, void *vcontext)
268 {
269 uint16_t val = sub_gate_read16(address, vcontext);
270 return address & 1 ? val : val >> 8;
271 }
272
273 static void *sub_gate_write16(uint32_t address, void *vcontext, uint16_t value)
274 {
275 m68k_context *m68k = vcontext;
276 segacd_context *cd = m68k->system;
277 uint32_t reg = address >> 1;
278 switch (reg)
279 {
280 case GA_SUB_CPU_CTRL:
281 cd->gate_array[reg] &= 0xF0;
282 cd->gate_array[reg] |= value & (BIT_LEDG|BIT_LEDR);
283 if (value & BIT_PRES) {
284 cd->periph_reset_cycle = m68k->current_cycle;
285 }
286 break;
287 case GA_MEM_MODE: {
288 uint16_t changed = value ^ cd->gate_array[reg];
289 genesis_context *gen = cd->genesis;
290 if (changed & BIT_MEM_MODE) {
291 //FIXME: ram banks are supposed to be interleaved when in 2M mode
292 cd->gate_array[reg] &= ~BIT_DMNA;
293 if (value & BIT_MEM_MODE) {
294 //switch to 1M mode
295 gen->m68k->mem_pointers[cd->memptr_start_index + 1] = (value & BIT_RET) ? cd->word_ram + 0x10000 : cd->word_ram;
296 gen->m68k->mem_pointers[cd->memptr_start_index + 2] = NULL;
297 m68k->mem_pointers[0] = NULL;
298 m68k->mem_pointers[1] = (value & BIT_RET) ? cd->word_ram : cd->word_ram + 0x10000;
299 } else {
300 //switch to 2M mode
301 if (value & BIT_RET) {
302 //Main CPU will have word ram
303 genesis_context *gen = cd->genesis;
304 gen->m68k->mem_pointers[cd->memptr_start_index + 1] = cd->word_ram;
305 gen->m68k->mem_pointers[cd->memptr_start_index + 2] = cd->word_ram + 0x10000;
306 m68k->mem_pointers[0] = NULL;
307 m68k->mem_pointers[1] = NULL;
308 } else {
309 //sub cpu will have word ram
310 gen->m68k->mem_pointers[cd->memptr_start_index + 1] = NULL;
311 gen->m68k->mem_pointers[cd->memptr_start_index + 2] = NULL;
312 m68k->mem_pointers[0] = cd->word_ram;
313 m68k->mem_pointers[1] = NULL;
314 }
315 }
316 m68k_invalidate_code_range(gen->m68k, cd->base + 0x200000, cd->base + 0x240000);
317 m68k_invalidate_code_range(m68k, 0x080000, 0x0E0000);
318 } else if (changed & BIT_RET) {
319 cd->gate_array[reg] &= ~BIT_DMNA;
320 if (value & BIT_MEM_MODE) {
321 //swapping banks in 1M mode
322 gen->m68k->mem_pointers[cd->memptr_start_index + 1] = (value & BIT_RET) ? cd->word_ram + 0x10000 : cd->word_ram;
323 m68k->mem_pointers[1] = (value & BIT_RET) ? cd->word_ram : cd->word_ram + 0x10000;
324 m68k_invalidate_code_range(gen->m68k, cd->base + 0x200000, cd->base + 0x240000);
325 m68k_invalidate_code_range(m68k, 0x080000, 0x0E0000);
326 } else if (value & BIT_RET) {
327 //giving word ram to main CPU in 2M mode
328 gen->m68k->mem_pointers[cd->memptr_start_index + 1] = cd->word_ram;
329 gen->m68k->mem_pointers[cd->memptr_start_index + 2] = cd->word_ram + 0x10000;
330 m68k->mem_pointers[0] = NULL;
331 m68k_invalidate_code_range(gen->m68k, cd->base + 0x200000, cd->base + 0x240000);
332 m68k_invalidate_code_range(m68k, 0x080000, 0x0E0000);
333 }
334 }
335 cd->gate_array[reg] &= 0xFFC2;
336 cd->gate_array[reg] |= value & (BIT_RET|BIT_MEM_MODE|MASK_PRIORITY);
337 break;
338 }
339 case GA_STOP_WATCH:
340 //docs say you should only write zero to reset
341 //unclear what happens when other values are written
342 timers_run(cd, m68k->current_cycle);
343 cd->gate_array[reg] = value & 0xFFF;
344 break;
345 case GA_COMM_FLAG:
100 cd->gate_array[reg] &= 0xFF00; 346 cd->gate_array[reg] &= 0xFF00;
101 cd->gate_array[reg] |= value & 0xFF; 347 cd->gate_array[reg] |= value & 0xFF;
102 break; 348 break;
103 case 0x10: 349 case GA_COMM_STATUS0:
104 case 0x11: 350 case GA_COMM_STATUS1:
105 case 0x12: 351 case GA_COMM_STATUS2:
106 case 0x13: 352 case GA_COMM_STATUS3:
107 case 0x14: 353 case GA_COMM_STATUS4:
108 case 0x15: 354 case GA_COMM_STATUS5:
109 case 0x16: 355 case GA_COMM_STATUS6:
110 case 0x17: 356 case GA_COMM_STATUS7:
111 //no effects for these other than saving the value 357 //no effects for these other than saving the value
112 cd->gate_array[reg] = value; 358 cd->gate_array[reg] = value;
359 break;
360 case GA_TIMER:
361 timers_run(cd, m68k->current_cycle);
362 cd->gate_array[reg] = value & 0xFF;
363 calculate_target_cycle(m68k);
364 break;
365 case GA_INT_MASK:
366 cd->gate_array[reg] = value & (BIT_MASK_IEN6|BIT_MASK_IEN5|BIT_MASK_IEN4|BIT_MASK_IEN3|BIT_MASK_IEN2|BIT_MASK_IEN1);
367 calculate_target_cycle(m68k);
113 break; 368 break;
114 default: 369 default:
115 printf("Unhandled gate array write %X:%X\n", address, value); 370 printf("Unhandled gate array write %X:%X\n", address, value);
116 } 371 }
117 return vcontext; 372 return vcontext;
129 value16 = cd->gate_array[reg] & 0xFF | (value << 8); 384 value16 = cd->gate_array[reg] & 0xFF | (value << 8);
130 } 385 }
131 return sub_gate_write16(address, vcontext, value16); 386 return sub_gate_write16(address, vcontext, value16);
132 } 387 }
133 388
389 static uint8_t can_main_access_prog(segacd_context *cd)
390 {
391 //TODO: use actual busack
392 return cd->busreq || !cd->reset;
393 }
394
395 static void scd_peripherals_run(segacd_context *cd, uint32_t cycle)
396 {
397 timers_run(cd, cycle);
398 }
399
400 static m68k_context *sync_components(m68k_context * context, uint32_t address)
401 {
402 segacd_context *cd = context->system;
403 scd_peripherals_run(cd, context->current_cycle);
404 calculate_target_cycle(context);
405 return context;
406 }
407
408 void scd_run(segacd_context *cd, uint32_t cycle)
409 {
410 uint8_t m68k_run = !can_main_access_prog(cd);
411 if (m68k_run) {
412 cd->m68k->sync_cycle = cycle;
413 if (cd->need_reset) {
414 cd->need_reset = 0;
415 m68k_reset(cd->m68k);
416 } else {
417 calculate_target_cycle(cd->m68k);
418 resume_68k(cd->m68k);
419 }
420 } else {
421 cd->m68k->current_cycle = cycle;
422 }
423 scd_peripherals_run(cd, cycle);
424 }
425
426 uint32_t gen_cycle_to_scd(uint32_t cycle, genesis_context *gen)
427 {
428 return ((uint64_t)cycle) * ((uint64_t)gen->normal_clock) / ((uint64_t)SCD_MCLKS);
429 }
430
431 void scd_adjust_cycle(segacd_context *cd, uint32_t deduction)
432 {
433 deduction = gen_cycle_to_scd(deduction, cd->genesis);
434 cd->m68k->current_cycle -= deduction;
435 cd->stopwatch_cycle -= deduction;
436 if (deduction >= cd->int2_cycle) {
437 cd->int2_cycle = 0;
438 } else if (cd->int2_cycle != CYCLE_NEVER) {
439 cd->int2_cycle -= deduction;
440 }
441 if (deduction >= cd->periph_reset_cycle) {
442 cd->periph_reset_cycle = CYCLE_NEVER;
443 } else if (cd->periph_reset_cycle != CYCLE_NEVER) {
444 cd->periph_reset_cycle -= deduction;
445 }
446 }
447
134 static uint16_t main_gate_read16(uint32_t address, void *vcontext) 448 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 { 449 {
151 m68k_context *m68k = vcontext; 450 m68k_context *m68k = vcontext;
152 genesis_context *gen = m68k->system; 451 genesis_context *gen = m68k->system;
153 segacd_context *cd = gen->expansion; 452 segacd_context *cd = gen->expansion;
453 uint32_t scd_cycle = gen_cycle_to_scd(m68k->current_cycle, gen);
454 scd_run(cd, scd_cycle);
455 uint32_t offset = (address & 0x1FF) >> 1;
456 switch (offset)
457 {
458 case GA_SUB_CPU_CTRL: {
459 uint16_t value = 0;
460 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN2) {
461 value |= BIT_IEN2;
462 }
463 if (cd->int2_cycle != CYCLE_NEVER) {
464 value |= BIT_IFL2;
465 }
466 if (can_main_access_prog(cd)) {
467 value |= BIT_SBRQ;
468 }
469 if (cd->reset) {
470 value |= BIT_SRES;
471 }
472 return value;
473 }
474 case GA_MEM_MODE:
475 //Main CPU can't read priority mode bits
476 return cd->gate_array[offset] & 0xFFE7;
477 case GA_HINT_VECTOR:
478 return cd->rom_mut[0x72/2];
479 case GA_CDC_DMA_ADDR:
480 //TODO: open bus maybe?
481 return 0xFFFF;
482 default:
483 if (offset < GA_TIMER) {
484 return cd->gate_array[offset];
485 }
486 //TODO: open bus maybe?
487 return 0xFFFF;
488 }
489 }
490
491 static uint8_t main_gate_read8(uint32_t address, void *vcontext)
492 {
493 uint16_t val = main_gate_read16(address & 0xFE, vcontext);
494 return address & 1 ? val : val >> 8;
495 }
496
497 static void *main_gate_write16(uint32_t address, void *vcontext, uint16_t value)
498 {
499 m68k_context *m68k = vcontext;
500 genesis_context *gen = m68k->system;
501 segacd_context *cd = gen->expansion;
502 uint32_t scd_cycle = gen_cycle_to_scd(m68k->current_cycle, gen);
503 scd_run(cd, scd_cycle);
154 uint32_t reg = (address & 0x1FF) >> 1; 504 uint32_t reg = (address & 0x1FF) >> 1;
155 switch (reg) 505 switch (reg)
156 { 506 {
157 case 0x7: 507 case GA_SUB_CPU_CTRL: {
508 uint8_t old_access = can_main_access_prog(cd);
509 cd->busreq = value & BIT_SBRQ;
510 uint8_t old_reset = cd->reset;
511 cd->reset = value & BIT_SRES;
512 if (cd->reset && !old_reset) {
513 cd->need_reset = 1;
514 }
515 cd->gate_array[reg] &= 0x7FFF;
516 cd->gate_array[reg] |= value & 0x8000;
517 uint8_t new_access = can_main_access_prog(cd);
518 uint32_t bank = cd->gate_array[GA_MEM_MODE] >> 6 & 0x3;
519 if (new_access) {
520 if (!old_access) {
521 m68k->mem_pointers[cd->memptr_start_index] = cd->prog_ram + bank * 0x10000;
522 m68k_invalidate_code_range(m68k, cd->base + 0x220000, cd->base + 0x240000);
523 }
524 } else if (old_access) {
525 m68k->mem_pointers[cd->memptr_start_index] = NULL;
526 m68k_invalidate_code_range(m68k, cd->base + 0x220000, cd->base + 0x240000);
527 m68k_invalidate_code_range(cd->m68k, bank * 0x20000, (bank + 1) * 0x20000);
528 }
529 break;
530 }
531 case GA_MEM_MODE: {
532 uint16_t changed = cd->gate_array[reg] ^ value;
533 //Main CPU can't write priority mode bits, MODE or RET
534 cd->gate_array[reg] &= 0x001D;
535 cd->gate_array[reg] |= value & 0xFFC0;
536 if ((cd->gate_array[reg] & BIT_MEM_MODE)) {
537 //1M mode
538 if (!(value & BIT_DMNA)) {
539 cd->gate_array[reg] |= BIT_DMNA;
540 }
541 } else {
542 cd->gate_array[reg] |= value & BIT_DMNA;
543 //2M mode
544 if (changed & value & BIT_DMNA) {
545 m68k->mem_pointers[cd->memptr_start_index + 1] = NULL;
546 m68k->mem_pointers[cd->memptr_start_index + 2] = NULL;
547 cd->m68k->mem_pointers[0] = cd->word_ram;
548
549 m68k_invalidate_code_range(m68k, cd->base + 0x200000, cd->base + 0x240000);
550 m68k_invalidate_code_range(cd->m68k, 0x080000, 0x0C0000);
551 }
552 }
553 if (changed & MASK_PROG_BANK) {
554 uint32_t bank = cd->gate_array[GA_MEM_MODE] >> 6 & 0x3;
555 m68k->mem_pointers[cd->memptr_start_index] = cd->word_ram + bank * 0x10000;
556 m68k_invalidate_code_range(m68k, cd->base + 0x220000, cd->base + 0x240000);
557 }
558 break;
559 }
560 case GA_HINT_VECTOR:
561 cd->rom_mut[0x72/2] = value;
562 break;
563 case GA_COMM_FLAG:
564 //Main CPU can only write the upper byte;
158 cd->gate_array[reg] &= 0xFF; 565 cd->gate_array[reg] &= 0xFF;
159 cd->gate_array[reg] |= value & 0xFF00; 566 cd->gate_array[reg] |= value & 0xFF00;
160 break; 567 break;
161 case 0x8: 568 case GA_COMM_CMD0:
162 case 0x9: 569 case GA_COMM_CMD1:
163 case 0xA: 570 case GA_COMM_CMD2:
164 case 0xB: 571 case GA_COMM_CMD3:
165 case 0xC: 572 case GA_COMM_CMD4:
166 case 0xD: 573 case GA_COMM_CMD5:
167 case 0xE: 574 case GA_COMM_CMD6:
168 case 0xF: 575 case GA_COMM_CMD7:
169 //no effects for these other than saving the value 576 //no effects for these other than saving the value
170 cd->gate_array[reg] = value; 577 cd->gate_array[reg] = value;
171 break; 578 break;
172 default: 579 default:
173 printf("Unhandled gate array write %X:%X\n", address, value); 580 printf("Unhandled gate array write %X:%X\n", address, value);
191 } 598 }
192 599
193 segacd_context *alloc_configure_segacd(system_media *media, uint32_t opts, uint8_t force_region, rom_info *info) 600 segacd_context *alloc_configure_segacd(system_media *media, uint32_t opts, uint8_t force_region, rom_info *info)
194 { 601 {
195 static memmap_chunk sub_cpu_map[] = { 602 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}, 603 {0x000000, 0x00FEFF, 0xFFFFFF, .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}, 604 {0x00FF00, 0x07FFFF, 0xFFFFFF, .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, 605 {0x080000, 0x0BFFFF, 0x03FFFF, .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}, 606 .read_16 = word_ram_2M_read16, .write_16 = word_ram_2M_write16, .read_8 = word_ram_2M_read8, .write_8 = word_ram_2M_write8},
200 {0x0C0000, 0x0DFFFF, 0x0000, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE | MMAP_PTR_IDX | MMAP_FUNC_NULL, .ptr_index = 1, 607 {0x0C0000, 0x0DFFFF, 0x01FFFF, .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}, 608 .read_16 = word_ram_1M_read16, .write_16 = word_ram_1M_write16, .read_8 = word_ram_1M_read8, .write_8 = word_ram_1M_write8},
202 {0xFE0000, 0xFEFFFF, 0x3FFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_ONLY_ODD}, 609 {0xFE0000, 0xFEFFFF, 0x003FFF, .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}, 610 {0xFF0000, 0xFF7FFF, 0x003FFF, .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} 611 {0xFF8000, 0xFF81FF, 0x0001FF, .read_16 = sub_gate_read16, .write_16 = sub_gate_write16, .read_8 = sub_gate_read8, .write_8 = sub_gate_write8}
205 }; 612 };
206 memset(info, 0, sizeof(*info)); 613
207 segacd_context *cd = calloc(sizeof(segacd_context), 1); 614 segacd_context *cd = calloc(sizeof(segacd_context), 1);
208 FILE *f = fopen("cdbios.bin", "rb"); 615 FILE *f = fopen("cdbios.bin", "rb");
209 if (!f) { 616 if (!f) {
210 fatal_error("Failed to open CD firmware for reading"); 617 fatal_error("Failed to open CD firmware for reading");
211 } 618 }
216 fatal_error("Failed to read CD firmware"); 623 fatal_error("Failed to read CD firmware");
217 } 624 }
218 cd->rom_mut = malloc(adjusted_size); 625 cd->rom_mut = malloc(adjusted_size);
219 byteswap_rom(adjusted_size, cd->rom); 626 byteswap_rom(adjusted_size, cd->rom);
220 memcpy(cd->rom_mut, cd->rom, adjusted_size); 627 memcpy(cd->rom_mut, cd->rom, adjusted_size);
221 628 cd->rom_mut[0x72/2] = 0xFFFF;
222 tern_node *db = get_rom_db(); 629
223 *info = configure_rom(db, media->buffer, media->size, media->chain ? media->chain->buffer : NULL, media->chain ? media->chain->size : 0, NULL, 0); 630 //memset(info, 0, sizeof(*info));
224 631 //tern_node *db = get_rom_db();
632 //*info = configure_rom(db, media->buffer, media->size, media->chain ? media->chain->buffer : NULL, media->chain ? media->chain->size : 0, NULL, 0);
633
225 cd->prog_ram = malloc(512*1024); 634 cd->prog_ram = malloc(512*1024);
226 cd->work_ram = malloc(256*1024); 635 cd->word_ram = malloc(256*1024);
227 cd->pcm_ram = malloc(64*1024); 636 cd->pcm_ram = malloc(64*1024);
228 //TODO: Load state from file 637 //TODO: Load state from file
229 cd->bram = malloc(8*1024); 638 cd->bram = malloc(8*1024);
230 639
640
231 sub_cpu_map[0].buffer = sub_cpu_map[1].buffer = cd->prog_ram; 641 sub_cpu_map[0].buffer = sub_cpu_map[1].buffer = cd->prog_ram;
232 sub_cpu_map[4].buffer = cd->bram; 642 sub_cpu_map[4].buffer = cd->bram;
233 m68k_options *mopts = malloc(sizeof(m68k_options)); 643 m68k_options *mopts = malloc(sizeof(m68k_options));
234 init_m68k_opts(mopts, sub_cpu_map, sizeof(sub_cpu_map) / sizeof(*sub_cpu_map), 4); 644 init_m68k_opts(mopts, sub_cpu_map, sizeof(sub_cpu_map) / sizeof(*sub_cpu_map), 4, sync_components);
235 cd->m68k = init_68k_context(mopts, NULL); 645 cd->m68k = init_68k_context(mopts, NULL);
236 cd->m68k->system = cd; 646 cd->m68k->system = cd;
647 cd->int2_cycle = CYCLE_NEVER;
237 cd->busreq = 1; 648 cd->busreq = 1;
238 cd->busack = 1; 649 cd->busack = 1;
239 650 cd->need_reset = 1;
651 cd->reset = 1; //active low, so reset is not active on start
652 cd->memptr_start_index = 0;
653 cd->gate_array[1] = 1;
654 cd->gate_array[0x1B] = 0x100;
655
240 return cd; 656 return cd;
241 } 657 }
242 658
243 memmap_chunk *segacd_main_cpu_map(segacd_context *cd, uint32_t *num_chunks) 659 memmap_chunk *segacd_main_cpu_map(segacd_context *cd, uint8_t cart_boot, uint32_t *num_chunks)
244 { 660 {
245 static memmap_chunk main_cpu_map[] = { 661 static memmap_chunk main_cpu_map[] = {
246 {0x000000, 0x01FFFF, 0xFFFFFF, .flags=MMAP_READ}, 662 {0x000000, 0x01FFFF, 0x01FFFF, .flags=MMAP_READ},
247 {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 663 {0x020000, 0x03FFFF, 0x01FFFF, .flags=MMAP_READ|MMAP_WRITE|MMAP_PTR_IDX|MMAP_FUNC_NULL|MMAP_CODE, .ptr_index = 0,
248 {0x040000, 0x05FFFF, 0x1FFFF, .flags=MMAP_READ}, //first ROM alias 664 .read_16 = unmapped_prog_read16, .write_16 = unmapped_prog_write16, .read_8 = unmapped_prog_read8, .write_8 = unmapped_prog_write8},
665 {0x040000, 0x05FFFF, 0x01FFFF, .flags=MMAP_READ}, //first ROM alias
249 //TODO: additional ROM/prog RAM aliases 666 //TODO: additional ROM/prog RAM aliases
250 {0x200000, 0x01FFFF, 0x1FFFF, .flags=MMAP_READ|MMAP_WRITE|MMAP_PTR_IDX|MMAP_FUNC_NULL, .ptr_index = 1}, 667 {0x200000, 0x21FFFF, 0x01FFFF, .flags=MMAP_READ|MMAP_WRITE|MMAP_PTR_IDX|MMAP_FUNC_NULL|MMAP_CODE, .ptr_index = 1},
251 {0x220000, 0x03FFFF, 0x1FFFF, .flags=MMAP_READ|MMAP_WRITE|MMAP_PTR_IDX|MMAP_FUNC_NULL, .ptr_index = 2}, 668 {0x220000, 0x23FFFF, 0x01FFFF, .flags=MMAP_READ|MMAP_WRITE|MMAP_PTR_IDX|MMAP_FUNC_NULL|MMAP_CODE, .ptr_index = 2},
252 {0xA12000, 0xA12FFF, 0xFFFFFF, .read_16 = main_gate_read16, .write_16 = main_gate_write16, .read_8 = main_gate_read8, .write_8 = main_gate_write8} 669 {0xA12000, 0xA12FFF, 0xFFFFFF, .read_16 = main_gate_read16, .write_16 = main_gate_write16, .read_8 = main_gate_read8, .write_8 = main_gate_write8}
253 }; 670 };
254 //TODO: support cart boot maps 671 for (int i = 0; i < sizeof(main_cpu_map) / sizeof(*main_cpu_map); i++)
672 {
673 if (main_cpu_map[i].start < 0x800000) {
674 if (cart_boot) {
675 main_cpu_map[i].start |= 0x400000;
676 main_cpu_map[i].end |= 0x400000;
677 } else {
678 main_cpu_map[i].start &= 0x3FFFFF;
679 main_cpu_map[i].end &= 0x3FFFFF;
680 }
681 }
682 }
255 //TODO: support BRAM cart 683 //TODO: support BRAM cart
256 main_cpu_map[0].buffer = cd->rom_mut; 684 main_cpu_map[0].buffer = cd->rom_mut;
257 main_cpu_map[2].buffer = cd->rom; 685 main_cpu_map[2].buffer = cd->rom;
258 main_cpu_map[1].buffer = cd->prog_ram; 686 main_cpu_map[1].buffer = cd->prog_ram;
259 main_cpu_map[3].buffer = cd->work_ram; 687 main_cpu_map[3].buffer = cd->word_ram;
260 main_cpu_map[3].buffer = cd->work_ram + 0x10000; 688 main_cpu_map[4].buffer = cd->word_ram + 0x10000;
261 *num_chunks = sizeof(main_cpu_map) / sizeof(*main_cpu_map); 689 *num_chunks = sizeof(main_cpu_map) / sizeof(*main_cpu_map);
262 return main_cpu_map; 690 return main_cpu_map;
263 } 691 }