Mercurial > repos > blastem
comparison sms.c @ 2134:9caebcfeac72
Implement word RAM interleaving in 1M mode, now passes mcd-verificator word RAM tests
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 18 Mar 2022 20:49:07 -0700 |
parents | 81df9aa2de9b |
children | 9a8dd4ba2753 |
comparison
equal
deleted
inserted
replaced
2133:8554751f17b5 | 2134:9caebcfeac72 |
---|---|
194 } | 194 } |
195 return 1; | 195 return 1; |
196 } | 196 } |
197 | 197 |
198 static memmap_chunk io_map[] = { | 198 static memmap_chunk io_map[] = { |
199 {0x00, 0x40, 0xFF, 0, 0, 0, NULL, NULL, NULL, NULL, memory_io_write}, | 199 {0x00, 0x40, 0xFF, .write_8 = memory_io_write}, |
200 {0x40, 0x80, 0xFF, 0, 0, 0, NULL, NULL, NULL, hv_read, sms_psg_write}, | 200 {0x40, 0x80, 0xFF, .read_8 = hv_read, .write_8 = sms_psg_write}, |
201 {0x80, 0xC0, 0xFF, 0, 0, 0, NULL, NULL, NULL, vdp_read, vdp_write}, | 201 {0x80, 0xC0, 0xFF, .read_8 = vdp_read, .write_8 = vdp_write}, |
202 {0xC0, 0x100,0xFF, 0, 0, 0, NULL, NULL, NULL, io_read, NULL} | 202 {0xC0, 0x100,0xFF, .read_8 = io_read} |
203 }; | 203 }; |
204 | 204 |
205 static void set_speed_percent(system_header * system, uint32_t percent) | 205 static void set_speed_percent(system_header * system, uint32_t percent) |
206 { | 206 { |
207 sms_context *context = (sms_context *)system; | 207 sms_context *context = (sms_context *)system; |
214 void sms_serialize(sms_context *sms, serialize_buffer *buf) | 214 void sms_serialize(sms_context *sms, serialize_buffer *buf) |
215 { | 215 { |
216 start_section(buf, SECTION_Z80); | 216 start_section(buf, SECTION_Z80); |
217 z80_serialize(sms->z80, buf); | 217 z80_serialize(sms->z80, buf); |
218 end_section(buf); | 218 end_section(buf); |
219 | 219 |
220 start_section(buf, SECTION_VDP); | 220 start_section(buf, SECTION_VDP); |
221 vdp_serialize(sms->vdp, buf); | 221 vdp_serialize(sms->vdp, buf); |
222 end_section(buf); | 222 end_section(buf); |
223 | 223 |
224 start_section(buf, SECTION_PSG); | 224 start_section(buf, SECTION_PSG); |
225 psg_serialize(sms->psg, buf); | 225 psg_serialize(sms->psg, buf); |
226 end_section(buf); | 226 end_section(buf); |
227 | 227 |
228 start_section(buf, SECTION_SEGA_IO_1); | 228 start_section(buf, SECTION_SEGA_IO_1); |
229 io_serialize(sms->io.ports, buf); | 229 io_serialize(sms->io.ports, buf); |
230 end_section(buf); | 230 end_section(buf); |
231 | 231 |
232 start_section(buf, SECTION_SEGA_IO_2); | 232 start_section(buf, SECTION_SEGA_IO_2); |
233 io_serialize(sms->io.ports + 1, buf); | 233 io_serialize(sms->io.ports + 1, buf); |
234 end_section(buf); | 234 end_section(buf); |
235 | 235 |
236 start_section(buf, SECTION_MAIN_RAM); | 236 start_section(buf, SECTION_MAIN_RAM); |
237 save_int8(buf, sizeof(sms->ram) / 1024); | 237 save_int8(buf, sizeof(sms->ram) / 1024); |
238 save_buffer8(buf, sms->ram, sizeof(sms->ram)); | 238 save_buffer8(buf, sms->ram, sizeof(sms->ram)); |
239 end_section(buf); | 239 end_section(buf); |
240 | 240 |
241 start_section(buf, SECTION_MAPPER); | 241 start_section(buf, SECTION_MAPPER); |
242 save_int8(buf, 1);//mapper type, 1 for Sega mapper | 242 save_int8(buf, 1);//mapper type, 1 for Sega mapper |
243 save_buffer8(buf, sms->bank_regs, sizeof(sms->bank_regs)); | 243 save_buffer8(buf, sms->bank_regs, sizeof(sms->bank_regs)); |
244 end_section(buf); | 244 end_section(buf); |
245 | 245 |
246 start_section(buf, SECTION_CART_RAM); | 246 start_section(buf, SECTION_CART_RAM); |
247 save_int8(buf, SMS_CART_RAM_SIZE / 1024); | 247 save_int8(buf, SMS_CART_RAM_SIZE / 1024); |
248 save_buffer8(buf, sms->cart_ram, SMS_CART_RAM_SIZE); | 248 save_buffer8(buf, sms->cart_ram, SMS_CART_RAM_SIZE); |
249 end_section(buf); | 249 end_section(buf); |
250 } | 250 } |
362 ret = get_modification_time(statepath) != 0; | 362 ret = get_modification_time(statepath) != 0; |
363 if (ret) { | 363 if (ret) { |
364 system->delayed_load_slot = slot + 1; | 364 system->delayed_load_slot = slot + 1; |
365 } | 365 } |
366 goto done; | 366 goto done; |
367 | 367 |
368 } | 368 } |
369 #endif | 369 #endif |
370 ret = load_state_path(sms, statepath); | 370 ret = load_state_path(sms, statepath); |
371 done: | 371 done: |
372 free(statepath); | 372 free(statepath); |
382 while (!sms->should_return) | 382 while (!sms->should_return) |
383 { | 383 { |
384 if (system->delayed_load_slot) { | 384 if (system->delayed_load_slot) { |
385 load_state(system, system->delayed_load_slot - 1); | 385 load_state(system, system->delayed_load_slot - 1); |
386 system->delayed_load_slot = 0; | 386 system->delayed_load_slot = 0; |
387 | 387 |
388 } | 388 } |
389 if (system->enter_debugger && sms->z80->pc) { | 389 if (system->enter_debugger && sms->z80->pc) { |
390 system->enter_debugger = 0; | 390 system->enter_debugger = 0; |
391 zdebugger(sms->z80, sms->z80->pc); | 391 zdebugger(sms->z80, sms->z80->pc); |
392 } | 392 } |
405 z80_clear_reset(sms->z80, sms->z80->Z80_CYCLE + 128*15); | 405 z80_clear_reset(sms->z80, sms->z80->Z80_CYCLE + 128*15); |
406 } | 406 } |
407 target_cycle = sms->z80->Z80_CYCLE; | 407 target_cycle = sms->z80->Z80_CYCLE; |
408 vdp_run_context(sms->vdp, target_cycle); | 408 vdp_run_context(sms->vdp, target_cycle); |
409 psg_run(sms->psg, target_cycle); | 409 psg_run(sms->psg, target_cycle); |
410 | 410 |
411 if (system->save_state) { | 411 if (system->save_state) { |
412 while (!sms->z80->pc) { | 412 while (!sms->z80->pc) { |
413 //advance Z80 to an instruction boundary | 413 //advance Z80 to an instruction boundary |
414 z80_run(sms->z80, sms->z80->Z80_CYCLE + 1); | 414 z80_run(sms->z80, sms->z80->Z80_CYCLE + 1); |
415 } | 415 } |
416 save_state(sms, system->save_state - 1); | 416 save_state(sms, system->save_state - 1); |
417 system->save_state = 0; | 417 system->save_state = 0; |
418 } | 418 } |
419 | 419 |
420 target_cycle += 3420*16; | 420 target_cycle += 3420*16; |
421 if (target_cycle > 0x10000000) { | 421 if (target_cycle > 0x10000000) { |
422 uint32_t adjust = sms->z80->Z80_CYCLE - 3420*262*2; | 422 uint32_t adjust = sms->z80->Z80_CYCLE - 3420*262*2; |
423 io_adjust_cycles(sms->io.ports, sms->z80->Z80_CYCLE, adjust); | 423 io_adjust_cycles(sms->io.ports, sms->z80->Z80_CYCLE, adjust); |
424 io_adjust_cycles(sms->io.ports+1, sms->z80->Z80_CYCLE, adjust); | 424 io_adjust_cycles(sms->io.ports+1, sms->z80->Z80_CYCLE, adjust); |
449 } | 449 } |
450 | 450 |
451 static void start_sms(system_header *system, char *statefile) | 451 static void start_sms(system_header *system, char *statefile) |
452 { | 452 { |
453 sms_context *sms = (sms_context *)system; | 453 sms_context *sms = (sms_context *)system; |
454 | 454 |
455 z80_assert_reset(sms->z80, 0); | 455 z80_assert_reset(sms->z80, 0); |
456 z80_clear_reset(sms->z80, 128*15); | 456 z80_clear_reset(sms->z80, 128*15); |
457 | 457 |
458 if (statefile) { | 458 if (statefile) { |
459 load_state_path(sms, statefile); | 459 load_state_path(sms, statefile); |
460 } | 460 } |
461 | 461 |
462 if (system->enter_debugger) { | 462 if (system->enter_debugger) { |
463 system->enter_debugger = 0; | 463 system->enter_debugger = 0; |
464 zinsert_breakpoint(sms->z80, sms->z80->pc, (uint8_t *)zdebugger); | 464 zinsert_breakpoint(sms->z80, sms->z80->pc, (uint8_t *)zdebugger); |
465 } | 465 } |
466 | 466 |
467 run_sms(system); | 467 run_sms(system); |
468 } | 468 } |
469 | 469 |
470 static void soft_reset(system_header *system) | 470 static void soft_reset(system_header *system) |
471 { | 471 { |
590 uint32_t rom_size = nearest_pow2(media->size); | 590 uint32_t rom_size = nearest_pow2(media->size); |
591 memmap_chunk memory_map[6]; | 591 memmap_chunk memory_map[6]; |
592 if (media->size > 0xC000) { | 592 if (media->size > 0xC000) { |
593 sms->header.info.map_chunks = 6; | 593 sms->header.info.map_chunks = 6; |
594 uint8_t *ram_reg_overlap = sms->ram + sizeof(sms->ram) - 4; | 594 uint8_t *ram_reg_overlap = sms->ram + sizeof(sms->ram) - 4; |
595 memory_map[0] = (memmap_chunk){0x0000, 0x0400, 0xFFFF, 0, 0, MMAP_READ, media->buffer, NULL, NULL, NULL, NULL}; | 595 memory_map[0] = (memmap_chunk){0x0000, 0x0400, 0xFFFF, .flags = MMAP_READ, .buffer = media->buffer}; |
596 memory_map[1] = (memmap_chunk){0x0400, 0x4000, 0xFFFF, 0, 0, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, NULL}; | 596 memory_map[1] = (memmap_chunk){0x0400, 0x4000, 0xFFFF, .ptr_index = 0, .flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE}; |
597 memory_map[2] = (memmap_chunk){0x4000, 0x8000, 0x3FFF, 0, 1, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, NULL}; | 597 memory_map[2] = (memmap_chunk){0x4000, 0x8000, 0x3FFF, .ptr_index = 1, .flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE}; |
598 memory_map[3] = (memmap_chunk){0x8000, 0xC000, 0x3FFF, 0, 2, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, cart_ram_write}; | 598 memory_map[3] = (memmap_chunk){0x8000, 0xC000, 0x3FFF, .ptr_index = 2, .flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, .write_8 = cart_ram_write}; |
599 memory_map[4] = (memmap_chunk){0xC000, 0xFFFC, sizeof(sms->ram)-1, 0, 0, MMAP_READ|MMAP_WRITE|MMAP_CODE, sms->ram, NULL, NULL, NULL, NULL}; | 599 memory_map[4] = (memmap_chunk){0xC000, 0xFFFC, sizeof(sms->ram)-1, .ptr_index = 0, .flags = MMAP_READ|MMAP_WRITE|MMAP_CODE, .buffer = sms->ram}; |
600 memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0x0003, 0, 0, MMAP_READ, ram_reg_overlap, NULL, NULL, NULL, mapper_write}; | 600 memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0x0003, .ptr_index = 0, .flags = MMAP_READ, .buffer = ram_reg_overlap, .write_8 = mapper_write}; |
601 } else { | 601 } else { |
602 sms->header.info.map_chunks = 2; | 602 sms->header.info.map_chunks = 2; |
603 memory_map[0] = (memmap_chunk){0x0000, 0xC000, rom_size-1, 0, 0, MMAP_READ, media->buffer, NULL, NULL, NULL, NULL}; | 603 memory_map[0] = (memmap_chunk){0x0000, 0xC000, rom_size-1, 0, 0, .flags = MMAP_READ, .buffer = media->buffer}; |
604 memory_map[1] = (memmap_chunk){0xC000, 0x10000, sizeof(sms->ram)-1, 0, 0, MMAP_READ|MMAP_WRITE|MMAP_CODE, sms->ram, NULL, NULL, NULL, NULL}; | 604 memory_map[1] = (memmap_chunk){0xC000, 0x10000, sizeof(sms->ram)-1, 0, 0, .flags = MMAP_READ|MMAP_WRITE|MMAP_CODE, .buffer = sms->ram}; |
605 }; | 605 }; |
606 sms->header.info.map = malloc(sizeof(memmap_chunk) * sms->header.info.map_chunks); | 606 sms->header.info.map = malloc(sizeof(memmap_chunk) * sms->header.info.map_chunks); |
607 memcpy(sms->header.info.map, memory_map, sizeof(memmap_chunk) * sms->header.info.map_chunks); | 607 memcpy(sms->header.info.map, memory_map, sizeof(memmap_chunk) * sms->header.info.map_chunks); |
608 z80_options *zopts = malloc(sizeof(z80_options)); | 608 z80_options *zopts = malloc(sizeof(z80_options)); |
609 init_z80_opts(zopts, sms->header.info.map, sms->header.info.map_chunks, io_map, 4, 15, 0xFF); | 609 init_z80_opts(zopts, sms->header.info.map, sms->header.info.map_chunks, io_map, 4, 15, 0xFF); |
610 sms->z80 = init_z80_context(zopts); | 610 sms->z80 = init_z80_context(zopts); |
611 sms->z80->system = sms; | 611 sms->z80->system = sms; |
612 sms->z80->Z80_OPTS->gen.debug_cmd_handler = debug_commands; | 612 sms->z80->Z80_OPTS->gen.debug_cmd_handler = debug_commands; |
613 | 613 |
614 sms->rom = media->buffer; | 614 sms->rom = media->buffer; |
615 sms->rom_size = rom_size; | 615 sms->rom_size = rom_size; |
616 if (sms->header.info.map_chunks > 2) { | 616 if (sms->header.info.map_chunks > 2) { |
617 sms->z80->mem_pointers[0] = sms->rom; | 617 sms->z80->mem_pointers[0] = sms->rom; |
618 sms->z80->mem_pointers[1] = sms->rom + 0x4000; | 618 sms->z80->mem_pointers[1] = sms->rom + 0x4000; |
619 sms->z80->mem_pointers[2] = sms->rom + 0x8000; | 619 sms->z80->mem_pointers[2] = sms->rom + 0x8000; |
620 sms->bank_regs[1] = 0; | 620 sms->bank_regs[1] = 0; |
621 sms->bank_regs[2] = 0x4000 >> 14; | 621 sms->bank_regs[2] = 0x4000 >> 14; |
622 sms->bank_regs[3] = 0x8000 >> 14; | 622 sms->bank_regs[3] = 0x8000 >> 14; |
623 } | 623 } |
624 | 624 |
625 //TODO: Detect region and pick master clock based off of that | 625 //TODO: Detect region and pick master clock based off of that |
626 sms->normal_clock = sms->master_clock = 53693175; | 626 sms->normal_clock = sms->master_clock = 53693175; |
627 | 627 |
628 sms->psg = malloc(sizeof(psg_context)); | 628 sms->psg = malloc(sizeof(psg_context)); |
629 psg_init(sms->psg, sms->master_clock, 15*16); | 629 psg_init(sms->psg, sms->master_clock, 15*16); |
630 | 630 |
631 set_gain_config(sms); | 631 set_gain_config(sms); |
632 | 632 |
633 sms->vdp = init_vdp_context(0, 0); | 633 sms->vdp = init_vdp_context(0, 0); |
634 sms->vdp->system = &sms->header; | 634 sms->vdp->system = &sms->header; |
635 | 635 |
636 sms->header.info.save_type = SAVE_NONE; | 636 sms->header.info.save_type = SAVE_NONE; |
637 sms->header.info.name = strdup(media->name); | 637 sms->header.info.name = strdup(media->name); |
638 | 638 |
639 setup_io_devices(config, &sms->header.info, &sms->io); | 639 setup_io_devices(config, &sms->header.info, &sms->io); |
640 sms->header.has_keyboard = io_has_keyboard(&sms->io); | 640 sms->header.has_keyboard = io_has_keyboard(&sms->io); |
641 | 641 |
642 sms->header.set_speed_percent = set_speed_percent; | 642 sms->header.set_speed_percent = set_speed_percent; |
643 sms->header.start_context = start_sms; | 643 sms->header.start_context = start_sms; |
644 sms->header.resume_context = resume_sms; | 644 sms->header.resume_context = resume_sms; |
645 sms->header.load_save = load_save; | 645 sms->header.load_save = load_save; |
646 sms->header.persist_save = persist_save; | 646 sms->header.persist_save = persist_save; |
660 sms->header.keyboard_up = keyboard_up; | 660 sms->header.keyboard_up = keyboard_up; |
661 sms->header.config_updated = config_updated; | 661 sms->header.config_updated = config_updated; |
662 sms->header.serialize = serialize; | 662 sms->header.serialize = serialize; |
663 sms->header.deserialize = deserialize; | 663 sms->header.deserialize = deserialize; |
664 sms->header.type = SYSTEM_SMS; | 664 sms->header.type = SYSTEM_SMS; |
665 | 665 |
666 return sms; | 666 return sms; |
667 } | 667 } |