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 }