# HG changeset patch # User Michael Pavone # Date 1462248372 25200 # Node ID 5fb64487b6e160a8a95e2a58db0181fd70d36742 # Parent 6c54d5a5c7c0fd29dd8ab7ee2b2ea3a3b08db35e Very basic support for S&K lock-on. Needs more work for full functionality. diff -r 6c54d5a5c7c0 -r 5fb64487b6e1 blastem.c --- a/blastem.c Mon May 02 18:29:29 2016 -0700 +++ b/blastem.c Mon May 02 21:06:12 2016 -0700 @@ -130,16 +130,10 @@ uint16_t read_dma_value(uint32_t address) { - //addresses here are word addresses (i.e. bit 0 corresponds to A1), so no need to do div by 2 - if (address < 0x200000) { - return cart[address]; - } else if(address >= 0x700000) { - return ram[address & 0x7FFF]; - } else { - uint16_t *ptr = get_native_pointer(address*2, (void **)genesis->m68k->mem_pointers, &genesis->m68k->options->gen); - if (ptr) { - return *ptr; - } + //addresses here are word addresses (i.e. bit 0 corresponds to A1), so no need to do multiply by 2 + uint16_t *ptr = get_native_pointer(address*2, (void **)genesis->m68k->mem_pointers, &genesis->m68k->options->gen); + if (ptr) { + return *ptr; } //TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area return 0; @@ -971,6 +965,7 @@ psg_free(gen->psg); free(gen->save_storage); free(gen->save_dir); + free(gen->lock_on); } void start_genesis(genesis_context *gen, char *statefile, uint8_t *debugger) @@ -1070,7 +1065,8 @@ char * romfname = NULL; FILE *address_log = NULL; char * statefile = NULL; - int rom_size; + int rom_size, lock_on_size; + uint16_t *lock_on = NULL; uint8_t * debuggerfun = NULL; uint8_t fullscreen = FULLSCREEN_DEFAULT, use_gl = 1; uint8_t debug_target = 0; @@ -1135,6 +1131,22 @@ case 'y': ym_log = 1; break; + case 'o': { + i++; + if (i >= argc) { + fatal_error("-o must be followed by a lock on cartridge filename\n"); + } + uint16_t *tmp = cart; + lock_on_size = load_rom(argv[i]); + if (lock_on_size) { + byteswap_rom(lock_on_size); + lock_on = cart; + } else { + fatal_error("Failed to load lock on cartridge %s\n", argv[i]); + } + cart = tmp; + break; + } case 'h': info_message( "Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n" @@ -1212,7 +1224,7 @@ (read_8_fun)io_read, (write_8_fun)io_write} }; tern_node *rom_db = load_rom_db(); - rom_info info = configure_rom(rom_db, cart, rom_size, base_map, sizeof(base_map)/sizeof(base_map[0])); + rom_info info = configure_rom(rom_db, cart, rom_size, lock_on, lock_on_size, base_map, sizeof(base_map)/sizeof(base_map[0])); byteswap_rom(rom_size); set_region(&info, force_version); update_title(info.name); @@ -1235,6 +1247,7 @@ } genesis = alloc_init_genesis(&info, fps, (ym_log && !menu) ? YM_OPT_WAVE_LOG : 0); + genesis->lock_on = lock_on; setup_saves(romfname, &info, genesis); if (menu) { menu_context = genesis; @@ -1266,7 +1279,7 @@ if (!(rom_size = load_rom(menu_context->next_rom))) { fatal_error("Failed to open %s for reading\n", menu_context->next_rom); } - info = configure_rom(rom_db, cart, rom_size, base_map, sizeof(base_map)/sizeof(base_map[0])); + info = configure_rom(rom_db, cart, rom_size, NULL, 0, base_map, sizeof(base_map)/sizeof(base_map[0])); byteswap_rom(rom_size); set_region(&info, force_version); update_title(info.name); diff -r 6c54d5a5c7c0 -r 5fb64487b6e1 blastem.h --- a/blastem.h Mon May 02 18:29:29 2016 -0700 +++ b/blastem.h Mon May 02 21:06:12 2016 -0700 @@ -27,6 +27,7 @@ psg_context *psg; genesis_context *next_context; uint16_t *cart; + uint16_t *lock_on; uint16_t *work_ram; uint8_t *zram; void *extra; diff -r 6c54d5a5c7c0 -r 5fb64487b6e1 rom.db --- a/rom.db Mon May 02 18:29:29 2016 -0700 +++ b/rom.db Mon May 02 21:06:12 2016 -0700 @@ -378,6 +378,19 @@ } } } +MK-1563 { + name Sonic & Knuckles + map { + 0 { + device ROM + last 1FFFFF + } + 200000 { + device LOCK-ON + last 3FFFFF + } + } +} T-48036 { name Ms. Pac-Man #Ms. Pac-Man doesn't like 6-button controllers diff -r 6c54d5a5c7c0 -r 5fb64487b6e1 romdb.c --- a/romdb.c Mon May 02 18:29:29 2016 -0700 +++ b/romdb.c Mon May 02 21:06:12 2016 -0700 @@ -580,8 +580,10 @@ typedef struct { rom_info *info; uint8_t *rom; + uint8_t *lock_on; tern_node *root; uint32_t rom_size; + uint32_t lock_on_size; int index; int num_els; uint16_t ptr_index; @@ -714,6 +716,14 @@ map->buffer = state->rom + offset; map->flags = MMAP_READ; map->mask = calc_mask(state->rom_size - offset, start, end); + } else if (!strcmp(dtype, "LOCK-ON")) { + if (!state->lock_on) { + //skip this entry if there is no lock on cartridge attached + return; + } + map->buffer = state->lock_on + offset; + map->flags = MMAP_READ; + map->mask = calc_mask(state->lock_on_size - offset, start, end); } else if (!strcmp(dtype, "EEPROM")) { process_eeprom_def(key, state); add_eeprom_map(node, start, end, state); @@ -797,12 +807,12 @@ map->write_16 = menu_write_w; map->read_16 = menu_read_w; } else { - fatal_error("Invalid device type for ROM DB map entry %d with address %s\n", state->index, key); + fatal_error("Invalid device type %s for ROM DB map entry %d with address %s\n", dtype, state->index, key); } state->index++; } -rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks) +rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, memmap_chunk const *base_map, uint32_t base_chunks) { uint8_t product_id[GAME_ID_LEN+1]; uint8_t *rom = vrom; @@ -855,7 +865,17 @@ info.eeprom_map = NULL; info.num_eeprom = 0; memset(info.map, 0, sizeof(memmap_chunk) * info.map_chunks); - map_iter_state state = {&info, rom, entry, rom_size, 0, info.map_chunks - base_chunks, 0}; + map_iter_state state = { + .info = &info, + .rom = rom, + .lock_on = lock_on, + .root = entry, + .rom_size = rom_size, + .lock_on_size = lock_on_size, + .index = 0, + .num_els = info.map_chunks - base_chunks, + .ptr_index = 0 + }; tern_foreach(map, map_iter_fun, &state); memcpy(info.map + state.index, base_map, sizeof(memmap_chunk) * base_chunks); } else { diff -r 6c54d5a5c7c0 -r 5fb64487b6e1 romdb.h --- a/romdb.h Mon May 02 18:29:29 2016 -0700 +++ b/romdb.h Mon May 02 21:06:12 2016 -0700 @@ -54,7 +54,7 @@ } rom_info; tern_node *load_rom_db(); -rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks); +rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, memmap_chunk const *base_map, uint32_t base_chunks); rom_info configure_rom_heuristics(uint8_t *rom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks); uint8_t translate_region_char(uint8_t c); void eeprom_init(eeprom_state *state, uint8_t *buffer, uint32_t size);