diff --git a/Cocoa/GBMemoryByteArray.m b/Cocoa/GBMemoryByteArray.m index 32526ad..a89c2ff 100644 --- a/Cocoa/GBMemoryByteArray.m +++ b/Cocoa/GBMemoryByteArray.m @@ -60,8 +60,6 @@ addr += 0x8000; break; case GBMemoryExternalRAM: - bank_backup = gb->mbc_ram_bank; - gb->mbc_ram_bank = self.selectedBank; addr += 0xA000; break; case GBMemoryRAM: @@ -86,7 +84,6 @@ gb->cgb_vram_bank = bank_backup; break; case GBMemoryExternalRAM: - gb->mbc_ram_bank = bank_backup; break; case GBMemoryRAM: gb->cgb_ram_bank = bank_backup; @@ -133,8 +130,6 @@ addr += 0x8000; break; case GBMemoryExternalRAM: - bank_backup = gb->mbc_ram_bank; - gb->mbc_ram_bank = self.selectedBank; addr += 0xA000; break; case GBMemoryRAM: @@ -163,7 +158,6 @@ gb->cgb_vram_bank = bank_backup; break; case GBMemoryExternalRAM: - gb->mbc_ram_bank = bank_backup; break; case GBMemoryRAM: gb->cgb_ram_bank = bank_backup; diff --git a/Core/apu.c b/Core/apu.c index 7e7ab31..845d105 100644 --- a/Core/apu.c +++ b/Core/apu.c @@ -33,16 +33,16 @@ bool GB_apu_is_DAC_enabled(GB_gameboy_t *gb, unsigned index) switch (index) { case GB_SQUARE_1: - return gb->io_registers[GB_IO_NR12] & 0xF8; + return gb->io_registers[GB_IO_NR12] & 0x8F; case GB_SQUARE_2: - return gb->io_registers[GB_IO_NR22] & 0xF8; + return gb->io_registers[GB_IO_NR22] & 0x8F; case GB_WAVE: return gb->apu.wave_channel.enable; case GB_NOISE: - return gb->io_registers[GB_IO_NR42] & 0xF8; + return gb->io_registers[GB_IO_NR42] & 0x8F; } return false; @@ -258,7 +258,7 @@ static void update_square_sample(GB_gameboy_t *gb, unsigned index) DMG, MGB or SGB/2 */ static void nrx2_glitch(uint8_t *volume, uint8_t value, uint8_t old_value) { - if (value & 8) { + if (value & 0x80) { (*volume)++; } @@ -266,11 +266,11 @@ static void nrx2_glitch(uint8_t *volume, uint8_t value, uint8_t old_value) *volume = 0x10 - *volume; } - if ((value & 7) && !(old_value & 7) && *volume && !(value & 8)) { + if ((value & 0x70) && !(old_value & 0x70) && *volume && !(value & 0x80)) { (*volume)--; } - if ((old_value & 7) && (value & 8)) { + if ((old_value & 0x70) && (value & 0x880)) { (*volume)--; } @@ -281,7 +281,7 @@ static void tick_square_envelope(GB_gameboy_t *gb, enum GB_CHANNELS index) { uint8_t nrx2 = gb->io_registers[index == GB_SQUARE_1? GB_IO_NR12 : GB_IO_NR22]; - if (gb->apu.square_channels[index].volume_countdown || (nrx2 & 7)) { + if (gb->apu.square_channels[index].volume_countdown || (nrx2 & 0x70)) { if (!gb->apu.square_channels[index].volume_countdown || !--gb->apu.square_channels[index].volume_countdown) { if (gb->cgb_double_speed) { if (index == GB_SQUARE_1) { @@ -292,15 +292,15 @@ static void tick_square_envelope(GB_gameboy_t *gb, enum GB_CHANNELS index) } } - if ((nrx2 & 8) && gb->apu.square_channels[index].current_volume < 0xF) { + if ((nrx2 & 0x80) && gb->apu.square_channels[index].current_volume < 0xF) { gb->apu.square_channels[index].current_volume++; } - else if (!(nrx2 & 8) && gb->apu.square_channels[index].current_volume > 0) { + else if (!(nrx2 & 0x80) && gb->apu.square_channels[index].current_volume > 0) { gb->apu.square_channels[index].current_volume--; } - gb->apu.square_channels[index].volume_countdown = nrx2 & 7; + gb->apu.square_channels[index].volume_countdown = (nrx2 >> 4) & 7; if (gb->apu.is_active[index]) { update_square_sample(gb, index); @@ -313,20 +313,20 @@ static void tick_noise_envelope(GB_gameboy_t *gb) { uint8_t nr42 = gb->io_registers[GB_IO_NR42]; - if (gb->apu.noise_channel.volume_countdown || (nr42 & 7)) { + if (gb->apu.noise_channel.volume_countdown || (nr42 & 0x70)) { if (!gb->apu.noise_channel.volume_countdown || !--gb->apu.noise_channel.volume_countdown) { if (gb->cgb_double_speed) { gb->apu.pcm_mask[0] &= (gb->apu.noise_channel.current_volume << 2) | 0x1F; } - if ((nr42 & 8) && gb->apu.noise_channel.current_volume < 0xF) { + if ((nr42 & 0x80) && gb->apu.noise_channel.current_volume < 0xF) { gb->apu.noise_channel.current_volume++; } - else if (!(nr42 & 8) && gb->apu.noise_channel.current_volume > 0) { + else if (!(nr42 & 0x80) && gb->apu.noise_channel.current_volume > 0) { gb->apu.noise_channel.current_volume--; } - gb->apu.noise_channel.volume_countdown = nr42 & 7; + gb->apu.noise_channel.volume_countdown = (nr42 >> 4) & 7; if (gb->apu.is_active[GB_NOISE]) { update_sample(gb, GB_NOISE, @@ -360,7 +360,7 @@ void GB_apu_div_event(GB_gameboy_t *gb) } } - if (gb->apu.is_active[GB_NOISE] && gb->apu.noise_channel.volume_countdown == 0 && (gb->io_registers[GB_IO_NR42] & 7)) { + if (gb->apu.is_active[GB_NOISE] && gb->apu.noise_channel.volume_countdown == 0 && (gb->io_registers[GB_IO_NR42] & 0x70)) { tick_noise_envelope(gb); } } @@ -579,17 +579,17 @@ uint8_t GB_apu_read(GB_gameboy_t *gb, uint8_t reg) return value; } - static const char read_mask[GB_IO_WAV_END - GB_IO_NR10 + 1] = { - /* NRX0 NRX1 NRX2 NRX3 NRX4 */ - 0x80, 0x3F, 0x00, 0xFF, 0xBF, // NR1X - 0xFF, 0x3F, 0x00, 0xFF, 0xBF, // NR2X + static const char read_mask[GB_IO_NR51 - GB_IO_NR10 + 1] = { + 0x80, 0x00, 0x3F, 0xFF, 0xBF, // NR1X + 0x3F, 0xFF, 0x00, 0xFF, 0xBF, // NR2X 0x7F, 0xFF, 0x9F, 0xFF, 0xBF, // NR3X - 0xFF, 0xFF, 0x00, 0x00, 0xBF, // NR4X - 0x00, 0x00, 0x70, 0xFF, 0xFF, // NR5X - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Unused + 0xFF, // "NR40" // Wave RAM - 0, /* ... */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0xFF, 0x00, 0x00, 0xBF, // NR4X + 0x00, 0x00, 0x70, // NR5X }; if (reg >= GB_IO_WAV_START && reg <= GB_IO_WAV_END && gb->apu.is_active[GB_WAVE]) { @@ -695,11 +695,11 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) case GB_IO_NR12: case GB_IO_NR22: { unsigned index = reg == GB_IO_NR22? GB_SQUARE_2: GB_SQUARE_1; - if (((value & 0x7) == 0) && ((gb->io_registers[reg] & 0x7) != 0)) { + if ((((value >> 4) & 0x7) == 0) && (((gb->io_registers[reg] >> 4) & 0x7) != 0)) { /* Envelope disabled */ gb->apu.square_channels[index].volume_countdown = 0; } - if ((value & 0xF8) == 0) { + if ((value & 0x8F) == 0) { /* This disables the DAC */ gb->io_registers[reg] = value; gb->apu.is_active[index] = false; @@ -756,7 +756,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) /* Timing quirk: if already active, sound starts 2 (2MHz) ticks earlier.*/ gb->apu.square_channels[index].sample_countdown = (gb->apu.square_channels[index].sample_length ^ 0x7FF) * 2 + 4 - gb->apu.lf_div; } - gb->apu.square_channels[index].current_volume = gb->io_registers[index == GB_SQUARE_1 ? GB_IO_NR12 : GB_IO_NR22] >> 4; + gb->apu.square_channels[index].current_volume = gb->io_registers[index == GB_SQUARE_1 ? GB_IO_NR12 : GB_IO_NR22] & 0xF; /* The volume changes caused by NRX4 sound start take effect instantly (i.e. the effect the previously started sound). The playback itself is not instant which is why we don't update the sample for other @@ -765,9 +765,9 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) update_square_sample(gb, index); } - gb->apu.square_channels[index].volume_countdown = gb->io_registers[index == GB_SQUARE_1 ? GB_IO_NR12 : GB_IO_NR22] & 7; + gb->apu.square_channels[index].volume_countdown = (gb->io_registers[index == GB_SQUARE_1 ? GB_IO_NR12 : GB_IO_NR22] >> 4) & 7; - if ((gb->io_registers[index == GB_SQUARE_1 ? GB_IO_NR12 : GB_IO_NR22] & 0xF8) != 0 && !gb->apu.is_active[index]) { + if ((gb->io_registers[index == GB_SQUARE_1 ? GB_IO_NR12 : GB_IO_NR22] & 0x8F) != 0 && !gb->apu.is_active[index]) { gb->apu.is_active[index] = true; update_sample(gb, index, 0, 0); /* We use the highest bit in current_sample_index to mark this sample is not actually playing yet, */ @@ -915,11 +915,11 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) } case GB_IO_NR42: { - if (((value & 0x7) == 0) && ((gb->io_registers[reg] & 0x7) != 0)) { + if (((value & 0x70) == 0) && ((gb->io_registers[reg] & 0x70) != 0)) { /* Envelope disabled */ gb->apu.noise_channel.volume_countdown = 0; } - if ((value & 0xF8) == 0) { + if ((value & 0x8F) == 0) { /* This disables the DAC */ gb->io_registers[reg] = value; gb->apu.is_active[GB_NOISE] = false; @@ -936,10 +936,10 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) } case GB_IO_NR43: { - gb->apu.noise_channel.narrow = value & 8; - unsigned divisor = (value & 0x07) << 1; + gb->apu.noise_channel.narrow = value & 0x80; + unsigned divisor = (value & 0x70) << 1; if (!divisor) divisor = 1; - gb->apu.noise_channel.sample_length = (divisor << (value >> 4)) - 1; + gb->apu.noise_channel.sample_length = (divisor << (value & 0xF)) - 1; /* Todo: changing the frequency sometimes delays the next sample. This is probably due to how the frequency is actually calculated in the noise channel, which is probably diff --git a/Core/debugger.c b/Core/debugger.c index c27acd3..89265d6 100644 --- a/Core/debugger.c +++ b/Core/debugger.c @@ -80,8 +80,6 @@ static uint16_t bank_for_addr(GB_gameboy_t *gb, uint16_t addr) typedef struct { uint16_t rom0_bank; uint16_t rom_bank; - uint8_t mbc_ram_bank; - bool mbc_ram_enable; uint8_t ram_bank; uint8_t vram_bank; } banking_state_t; @@ -90,8 +88,6 @@ static inline void save_banking_state(GB_gameboy_t *gb, banking_state_t *state) { state->rom0_bank = gb->mbc_rom0_bank; state->rom_bank = gb->mbc_rom_bank; - state->mbc_ram_bank = gb->mbc_ram_bank; - state->mbc_ram_enable = gb->mbc_ram_enable; state->ram_bank = gb->cgb_ram_bank; state->vram_bank = gb->cgb_vram_bank; } @@ -101,8 +97,6 @@ static inline void restore_banking_state(GB_gameboy_t *gb, banking_state_t *stat gb->mbc_rom0_bank = state->rom0_bank; gb->mbc_rom_bank = state->rom_bank; - gb->mbc_ram_bank = state->mbc_ram_bank; - gb->mbc_ram_enable = state->mbc_ram_enable; gb->cgb_ram_bank = state->ram_bank; gb->cgb_vram_bank = state->vram_bank; } @@ -111,8 +105,6 @@ static inline void switch_banking_state(GB_gameboy_t *gb, uint16_t bank) { gb->mbc_rom0_bank = bank; gb->mbc_rom_bank = bank; - gb->mbc_ram_bank = bank; - gb->mbc_ram_enable = true; if (GB_is_cgb(gb)) { gb->cgb_ram_bank = bank & 7; gb->cgb_vram_bank = bank & 1; @@ -1530,58 +1522,8 @@ static bool mbc(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugg return true; } - const GB_cartridge_t *cartridge = gb->cartridge_type; - - if (cartridge->has_ram) { - GB_log(gb, "Cartridge includes%s RAM: $%x bytes\n", cartridge->has_battery? " battery-backed": "", gb->mbc_ram_size); - } - else { - GB_log(gb, "No cartridge RAM\n"); - } - - if (cartridge->mbc_type) { - if (gb->is_mbc30) { - GB_log(gb, "MBC30\n"); - } - else { - static const char *const mapper_names[] = { - [GB_MBC1] = "MBC1", - [GB_MBC2] = "MBC2", - [GB_MBC3] = "MBC3", - [GB_MBC5] = "MBC5", - [GB_HUC1] = "HUC-1", - [GB_HUC3] = "HUC-3", - }; - GB_log(gb, "%s\n", mapper_names[cartridge->mbc_type]); - } - GB_log(gb, "Current mapped ROM bank: %x\n", gb->mbc_rom_bank); - if (cartridge->has_ram) { - GB_log(gb, "Current mapped RAM bank: %x\n", gb->mbc_ram_bank); - if (gb->cartridge_type->mbc_type != GB_HUC1) { - GB_log(gb, "RAM is curently %s\n", gb->mbc_ram_enable? "enabled" : "disabled"); - } - } - if (cartridge->mbc_type == GB_MBC1 && gb->mbc1_wiring == GB_STANDARD_MBC1_WIRING) { - GB_log(gb, "MBC1 banking mode is %s\n", gb->mbc1.mode == 1 ? "RAM" : "ROM"); - } - if (cartridge->mbc_type == GB_MBC1 && gb->mbc1_wiring == GB_MBC1M_WIRING) { - GB_log(gb, "MBC1 uses MBC1M wiring. \n"); - GB_log(gb, "Current mapped ROM0 bank: %x\n", gb->mbc_rom0_bank); - GB_log(gb, "MBC1 multicart banking mode is %s\n", gb->mbc1.mode == 1 ? "enabled" : "disabled"); - } - - } - else { - GB_log(gb, "No MBC\n"); - } - - if (cartridge->has_rumble) { - GB_log(gb, "Cart contains a Rumble Pak\n"); - } - - if (cartridge->has_rtc) { - GB_log(gb, "Cart contains a real time clock\n"); - } + GB_log(gb, "Current mapped ROM bank: %x\n", gb->mbc_rom_bank); + GB_log(gb, "Current mapped ROM0 bank: %x\n", gb->mbc_rom0_bank); return true; } @@ -1662,13 +1604,13 @@ static bool lcd(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugg GB_log(gb, "LCDC:\n"); GB_log(gb, " LCD enabled: %s\n",(gb->io_registers[GB_IO_LCDC] & 128)? "Enabled" : "Disabled"); GB_log(gb, " %s: %s\n", (gb->cgb_mode? "Sprite priority flags" : "Background and Window"), - (gb->io_registers[GB_IO_LCDC] & 1)? "Enabled" : "Disabled"); - GB_log(gb, " Objects: %s\n", (gb->io_registers[GB_IO_LCDC] & 2)? "Enabled" : "Disabled"); - GB_log(gb, " Object size: %s\n", (gb->io_registers[GB_IO_LCDC] & 4)? "8x16" : "8x8"); - GB_log(gb, " Background tilemap: %s\n", (gb->io_registers[GB_IO_LCDC] & 8)? "$9C00" : "$9800"); + (gb->io_registers[GB_IO_LCDC] & 64)? "Enabled" : "Disabled"); + GB_log(gb, " Objects: %s\n", (gb->io_registers[GB_IO_LCDC] & 1)? "Enabled" : "Disabled"); + GB_log(gb, " Object size: %s\n", (gb->io_registers[GB_IO_LCDC] & 2)? "8x16" : "8x8"); + GB_log(gb, " Background tilemap: %s\n", (gb->io_registers[GB_IO_LCDC] & 4)? "$9C00" : "$9800"); GB_log(gb, " Background and Window Tileset: %s\n", (gb->io_registers[GB_IO_LCDC] & 16)? "$8000" : "$8800"); GB_log(gb, " Window: %s\n", (gb->io_registers[GB_IO_LCDC] & 32)? "Enabled" : "Disabled"); - GB_log(gb, " Window tilemap: %s\n", (gb->io_registers[GB_IO_LCDC] & 64)? "$9C00" : "$9800"); + GB_log(gb, " Window tilemap: %s\n", (gb->io_registers[GB_IO_LCDC] & 8)? "$9C00" : "$9800"); GB_log(gb, "\nSTAT:\n"); static const char *modes[] = {"Mode 0, H-Blank", "Mode 1, V-Blank", "Mode 2, OAM", "Mode 3, Rendering"}; diff --git a/Core/display.c b/Core/display.c index 2eb8c42..2af702c 100644 --- a/Core/display.c +++ b/Core/display.c @@ -415,7 +415,7 @@ static void add_object_from_index(GB_gameboy_t *gb, unsigned index) /* This reverse sorts the visible objects by location and priority */ GB_object_t *objects = (GB_object_t *) &gb->oam; - bool height_16 = (gb->io_registers[GB_IO_LCDC] & 4) != 0; + bool height_16 = (gb->io_registers[GB_IO_LCDC] & 2) != 0; signed y = objects[index].y - 16; if (y <= gb->current_line && y + (height_16? 16 : 8) > gb->current_line) { unsigned j = 0; @@ -443,7 +443,7 @@ static void render_pixel_if_possible(GB_gameboy_t *gb) if (fifo_size(&gb->oam_fifo)) { oam_fifo_item = fifo_pop(&gb->oam_fifo); - if (oam_fifo_item->pixel && (gb->io_registers[GB_IO_LCDC] & 2)) { + if (oam_fifo_item->pixel && (gb->io_registers[GB_IO_LCDC] & 1)) { draw_oam = true; bg_priority |= oam_fifo_item->bg_priority; } @@ -461,7 +461,7 @@ static void render_pixel_if_possible(GB_gameboy_t *gb) /* Mixing */ - if ((gb->io_registers[GB_IO_LCDC] & 0x1) == 0) { + if ((gb->io_registers[GB_IO_LCDC] & 0x40) == 0) { if (gb->cgb_mode) { bg_priority = false; } @@ -583,10 +583,10 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb) } /* Todo: Verified for DMG (Tested: SGB2), CGB timing is wrong. */ - if (gb->io_registers[GB_IO_LCDC] & 0x08 && !gb->wx_triggered) { + if (gb->io_registers[GB_IO_LCDC] & 0x04 && !gb->wx_triggered) { map = 0x1C00; } - else if (gb->io_registers[GB_IO_LCDC] & 0x40 && gb->wx_triggered) { + else if (gb->io_registers[GB_IO_LCDC] & 0x8 && gb->wx_triggered) { map = 0x1C00; } @@ -715,7 +715,7 @@ static uint16_t get_object_line_address(GB_gameboy_t *gb, const GB_object_t *obj object = &blocked; } - bool height_16 = (gb->io_registers[GB_IO_LCDC] & 4) != 0; /* Todo: Which T-cycle actually reads this? */ + bool height_16 = (gb->io_registers[GB_IO_LCDC] & 2) != 0; /* Todo: Which T-cycle actually reads this? */ uint8_t tile_y = (gb->current_line - object->y) & (height_16? 0xF : 7); if (object->flags & 0x40) { /* Flip Y */ @@ -1044,7 +1044,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) gb->during_object_fetch = true; while (gb->n_visible_objs != 0 && - (gb->io_registers[GB_IO_LCDC] & 2 || GB_is_cgb(gb)) && + (gb->io_registers[GB_IO_LCDC] & 1 || GB_is_cgb(gb)) && gb->obj_comparators[gb->n_visible_objs - 1] == (uint8_t)(gb->position_in_line + 8)) { while (gb->fetcher_state < 5 || fifo_size(&gb->bg_fifo) == 0) { @@ -1376,7 +1376,7 @@ void GB_draw_tilemap(GB_gameboy_t *gb, uint32_t *dest, GB_palette_type_t palette break; } - if (map_type == GB_MAP_9C00 || (map_type == GB_MAP_AUTO && gb->io_registers[GB_IO_LCDC] & 0x08)) { + if (map_type == GB_MAP_9C00 || (map_type == GB_MAP_AUTO && gb->io_registers[GB_IO_LCDC] & 0x04)) { map = 0x1c00; } @@ -1425,7 +1425,7 @@ void GB_draw_tilemap(GB_gameboy_t *gb, uint32_t *dest, GB_palette_type_t palette uint8_t GB_get_oam_info(GB_gameboy_t *gb, GB_oam_info_t *dest, uint8_t *sprite_height) { uint8_t count = 0; - *sprite_height = (gb->io_registers[GB_IO_LCDC] & 4) ? 16:8; + *sprite_height = (gb->io_registers[GB_IO_LCDC] & 2) ? 16:8; uint8_t oam_to_dest_index[40] = {0,}; for (unsigned y = 0; y < LINES; y++) { GB_object_t *sprite = (GB_object_t *) &gb->oam; diff --git a/Core/gb.c b/Core/gb.c index 7325d79..df1b207 100644 --- a/Core/gb.c +++ b/Core/gb.c @@ -161,7 +161,6 @@ void GB_init(GB_gameboy_t *gb, GB_model_t model) gb->input_callback = default_input_callback; gb->async_input_callback = default_async_input_callback; #endif - gb->cartridge_type = &GB_cart_defs[0]; // Default cartridge type gb->clock_multiplier = 1.0; if (model & GB_MODEL_NO_SFC_BIT) { @@ -187,9 +186,6 @@ void GB_free(GB_gameboy_t *gb) if (gb->vram) { free(gb->vram); } - if (gb->mbc_ram) { - free(gb->mbc_ram); - } if (gb->rom) { free(gb->rom); } @@ -245,7 +241,6 @@ void GB_borrow_sgb_border(GB_gameboy_t *gb) if (!gb->boot_rom_load_callback) return; // Can't borrow a border without this callback GB_gameboy_t sgb; GB_init(&sgb, GB_MODEL_SGB); - sgb.cartridge_type = gb->cartridge_type; sgb.rom = gb->rom; sgb.rom_size = gb->rom_size; sgb.turbo = true; @@ -301,7 +296,6 @@ int GB_load_rom(GB_gameboy_t *gb, const char *path) memset(gb->rom, 0xFF, gb->rom_size); /* Pad with 0xFFs */ fread(gb->rom, 1, gb->rom_size, f); fclose(f); - GB_configure_cart(gb); return 0; } @@ -483,44 +477,7 @@ done:; memset(gb->rom + gb->rom_size, 0, needed_size - gb->rom_size); gb->rom_size = needed_size; } - - GB_configure_cart(gb); - - // Fix a common wrong MBC error - if (gb->rom[0x147] == 3) { // MBC1 + RAM + Battery - bool needs_fix = false; - if (gb->rom_size >= 0x21 * 0x4000) { - for (unsigned i = 0x20 * 0x4000; i < 0x21 * 0x4000; i++) { - if (gb->rom[i]) { - needs_fix = true; - break; - } - } - } - if (!needs_fix && gb->rom_size >= 0x41 * 0x4000) { - for (unsigned i = 0x40 * 0x4000; i < 0x41 * 0x4000; i++) { - if (gb->rom[i]) { - needs_fix = true; - break; - } - } - } - if (!needs_fix && gb->rom_size >= 0x61 * 0x4000) { - for (unsigned i = 0x60 * 0x4000; i < 0x61 * 0x4000; i++) { - if (gb->rom[i]) { - needs_fix = true; - break; - } - } - } - if (needs_fix) { - gb->rom[0x147] = 0x10; // MBC3 + RTC + RAM + Battery - GB_configure_cart(gb); - gb->rom[0x147] = 0x3; - GB_log(gb, "ROM claims to use MBC1 but appears to require MBC3 or 5, assuming MBC3.\n"); - } - } - + if (old_rom) { free(old_rom); } @@ -553,7 +510,6 @@ void GB_load_rom_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t siz gb->rom = malloc(gb->rom_size); memset(gb->rom, 0xff, gb->rom_size); memcpy(gb->rom, buffer, size); - GB_configure_cart(gb); } typedef struct { @@ -596,351 +552,27 @@ typedef union { int GB_save_battery_size(GB_gameboy_t *gb) { - if (!gb->cartridge_type->has_battery) return 0; // Nothing to save. - if (gb->mbc_ram_size == 0 && !gb->cartridge_type->has_rtc) return 0; /* Claims to have battery, but has no RAM or RTC */ - - if (gb->cartridge_type->mbc_type == GB_HUC3) { - return gb->mbc_ram_size + sizeof(GB_huc3_rtc_time_t); - } - GB_rtc_save_t rtc_save_size; - return gb->mbc_ram_size + (gb->cartridge_type->has_rtc ? sizeof(rtc_save_size.vba64) : 0); + return 0; } int GB_save_battery_to_buffer(GB_gameboy_t *gb, uint8_t *buffer, size_t size) { - if (!gb->cartridge_type->has_battery) return 0; // Nothing to save. - if (gb->mbc_ram_size == 0 && !gb->cartridge_type->has_rtc) return 0; /* Claims to have battery, but has no RAM or RTC */ - - if (size < GB_save_battery_size(gb)) return EIO; - - memcpy(buffer, gb->mbc_ram, gb->mbc_ram_size); - - if (gb->cartridge_type->mbc_type == GB_HUC3) { - buffer += gb->mbc_ram_size; - -#ifdef GB_BIG_ENDIAN - GB_huc3_rtc_time_t rtc_save = { - __builtin_bswap64(gb->last_rtc_second), - __builtin_bswap16(gb->huc3_minutes), - __builtin_bswap16(gb->huc3_days), - __builtin_bswap16(gb->huc3_alarm_minutes), - __builtin_bswap16(gb->huc3_alarm_days), - gb->huc3_alarm_enabled, - }; -#else - GB_huc3_rtc_time_t rtc_save = { - gb->last_rtc_second, - gb->huc3_minutes, - gb->huc3_days, - gb->huc3_alarm_minutes, - gb->huc3_alarm_days, - gb->huc3_alarm_enabled, - }; -#endif - memcpy(buffer, &rtc_save, sizeof(rtc_save)); - } - else if (gb->cartridge_type->has_rtc) { - GB_rtc_save_t rtc_save = {{{{0,}},},}; - rtc_save.vba64.rtc_real.seconds = gb->rtc_real.seconds; - rtc_save.vba64.rtc_real.minutes = gb->rtc_real.minutes; - rtc_save.vba64.rtc_real.hours = gb->rtc_real.hours; - rtc_save.vba64.rtc_real.days = gb->rtc_real.days; - rtc_save.vba64.rtc_real.high = gb->rtc_real.high; - rtc_save.vba64.rtc_latched.seconds = gb->rtc_latched.seconds; - rtc_save.vba64.rtc_latched.minutes = gb->rtc_latched.minutes; - rtc_save.vba64.rtc_latched.hours = gb->rtc_latched.hours; - rtc_save.vba64.rtc_latched.days = gb->rtc_latched.days; - rtc_save.vba64.rtc_latched.high = gb->rtc_latched.high; -#ifdef GB_BIG_ENDIAN - rtc_save.vba64.last_rtc_second = __builtin_bswap64(gb->last_rtc_second); -#else - rtc_save.vba64.last_rtc_second = gb->last_rtc_second; -#endif - memcpy(buffer + gb->mbc_ram_size, &rtc_save.vba64, sizeof(rtc_save.vba64)); - } - - errno = 0; - return errno; + return 0; } int GB_save_battery(GB_gameboy_t *gb, const char *path) { - if (!gb->cartridge_type->has_battery) return 0; // Nothing to save. - if (gb->mbc_ram_size == 0 && !gb->cartridge_type->has_rtc) return 0; /* Claims to have battery, but has no RAM or RTC */ - FILE *f = fopen(path, "wb"); - if (!f) { - GB_log(gb, "Could not open battery save: %s.\n", strerror(errno)); - return errno; - } - - if (fwrite(gb->mbc_ram, 1, gb->mbc_ram_size, f) != gb->mbc_ram_size) { - fclose(f); - return EIO; - } - if (gb->cartridge_type->mbc_type == GB_HUC3) { -#ifdef GB_BIG_ENDIAN - GB_huc3_rtc_time_t rtc_save = { - __builtin_bswap64(gb->last_rtc_second), - __builtin_bswap16(gb->huc3_minutes), - __builtin_bswap16(gb->huc3_days), - __builtin_bswap16(gb->huc3_alarm_minutes), - __builtin_bswap16(gb->huc3_alarm_days), - gb->huc3_alarm_enabled, - }; -#else - GB_huc3_rtc_time_t rtc_save = { - gb->last_rtc_second, - gb->huc3_minutes, - gb->huc3_days, - gb->huc3_alarm_minutes, - gb->huc3_alarm_days, - gb->huc3_alarm_enabled, - }; -#endif - - if (fwrite(&rtc_save, sizeof(rtc_save), 1, f) != 1) { - fclose(f); - return EIO; - } - } - else if (gb->cartridge_type->has_rtc) { - GB_rtc_save_t rtc_save = {{{{0,}},},}; - rtc_save.vba64.rtc_real.seconds = gb->rtc_real.seconds; - rtc_save.vba64.rtc_real.minutes = gb->rtc_real.minutes; - rtc_save.vba64.rtc_real.hours = gb->rtc_real.hours; - rtc_save.vba64.rtc_real.days = gb->rtc_real.days; - rtc_save.vba64.rtc_real.high = gb->rtc_real.high; - rtc_save.vba64.rtc_latched.seconds = gb->rtc_latched.seconds; - rtc_save.vba64.rtc_latched.minutes = gb->rtc_latched.minutes; - rtc_save.vba64.rtc_latched.hours = gb->rtc_latched.hours; - rtc_save.vba64.rtc_latched.days = gb->rtc_latched.days; - rtc_save.vba64.rtc_latched.high = gb->rtc_latched.high; -#ifdef GB_BIG_ENDIAN - rtc_save.vba64.last_rtc_second = __builtin_bswap64(gb->last_rtc_second); -#else - rtc_save.vba64.last_rtc_second = gb->last_rtc_second; -#endif - if (fwrite(&rtc_save.vba64, 1, sizeof(rtc_save.vba64), f) != sizeof(rtc_save.vba64)) { - fclose(f); - return EIO; - } - - } - - errno = 0; - fclose(f); - return errno; + return 0; } void GB_load_battery_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t size) { - memcpy(gb->mbc_ram, buffer, MIN(gb->mbc_ram_size, size)); - if (size <= gb->mbc_ram_size) { - goto reset_rtc; - } - - if (gb->cartridge_type->mbc_type == GB_HUC3) { - GB_huc3_rtc_time_t rtc_save; - if (size - gb->mbc_ram_size < sizeof(rtc_save)) { - goto reset_rtc; - } - memcpy(&rtc_save, buffer + gb->mbc_ram_size, sizeof(rtc_save)); -#ifdef GB_BIG_ENDIAN - gb->last_rtc_second = __builtin_bswap64(rtc_save.last_rtc_second); - gb->huc3_minutes = __builtin_bswap16(rtc_save.minutes); - gb->huc3_days = __builtin_bswap16(rtc_save.days); - gb->huc3_alarm_minutes = __builtin_bswap16(rtc_save.alarm_minutes); - gb->huc3_alarm_days = __builtin_bswap16(rtc_save.alarm_days); - gb->huc3_alarm_enabled = rtc_save.alarm_enabled; -#else - gb->last_rtc_second = rtc_save.last_rtc_second; - gb->huc3_minutes = rtc_save.minutes; - gb->huc3_days = rtc_save.days; - gb->huc3_alarm_minutes = rtc_save.alarm_minutes; - gb->huc3_alarm_days = rtc_save.alarm_days; - gb->huc3_alarm_enabled = rtc_save.alarm_enabled; -#endif - if (gb->last_rtc_second > time(NULL)) { - /* We must reset RTC here, or it will not advance. */ - goto reset_rtc; - } - return; - } - - GB_rtc_save_t rtc_save; - memcpy(&rtc_save, buffer + gb->mbc_ram_size, MIN(sizeof(rtc_save), size)); - switch (size - gb->mbc_ram_size) { - case sizeof(rtc_save.sameboy_legacy): - memcpy(&gb->rtc_real, &rtc_save.sameboy_legacy.rtc_real, sizeof(gb->rtc_real)); - memcpy(&gb->rtc_latched, &rtc_save.sameboy_legacy.rtc_real, sizeof(gb->rtc_real)); - gb->last_rtc_second = rtc_save.sameboy_legacy.last_rtc_second; - break; - - case sizeof(rtc_save.vba32): - gb->rtc_real.seconds = rtc_save.vba32.rtc_real.seconds; - gb->rtc_real.minutes = rtc_save.vba32.rtc_real.minutes; - gb->rtc_real.hours = rtc_save.vba32.rtc_real.hours; - gb->rtc_real.days = rtc_save.vba32.rtc_real.days; - gb->rtc_real.high = rtc_save.vba32.rtc_real.high; - gb->rtc_latched.seconds = rtc_save.vba32.rtc_latched.seconds; - gb->rtc_latched.minutes = rtc_save.vba32.rtc_latched.minutes; - gb->rtc_latched.hours = rtc_save.vba32.rtc_latched.hours; - gb->rtc_latched.days = rtc_save.vba32.rtc_latched.days; - gb->rtc_latched.high = rtc_save.vba32.rtc_latched.high; -#ifdef GB_BIG_ENDIAN - gb->last_rtc_second = __builtin_bswap32(rtc_save.vba32.last_rtc_second); -#else - gb->last_rtc_second = rtc_save.vba32.last_rtc_second; -#endif - break; - - case sizeof(rtc_save.vba64): - gb->rtc_real.seconds = rtc_save.vba64.rtc_real.seconds; - gb->rtc_real.minutes = rtc_save.vba64.rtc_real.minutes; - gb->rtc_real.hours = rtc_save.vba64.rtc_real.hours; - gb->rtc_real.days = rtc_save.vba64.rtc_real.days; - gb->rtc_real.high = rtc_save.vba64.rtc_real.high; - gb->rtc_latched.seconds = rtc_save.vba64.rtc_latched.seconds; - gb->rtc_latched.minutes = rtc_save.vba64.rtc_latched.minutes; - gb->rtc_latched.hours = rtc_save.vba64.rtc_latched.hours; - gb->rtc_latched.days = rtc_save.vba64.rtc_latched.days; - gb->rtc_latched.high = rtc_save.vba64.rtc_latched.high; -#ifdef GB_BIG_ENDIAN - gb->last_rtc_second = __builtin_bswap64(rtc_save.vba64.last_rtc_second); -#else - gb->last_rtc_second = rtc_save.vba64.last_rtc_second; -#endif - break; - - default: - goto reset_rtc; - } - if (gb->last_rtc_second > time(NULL)) { - /* We must reset RTC here, or it will not advance. */ - goto reset_rtc; - } - - if (gb->last_rtc_second < 852076800) { /* 1/1/97. There weren't any RTC games that time, - so if the value we read is lower it means it wasn't - really RTC data. */ - goto reset_rtc; - } - goto exit; -reset_rtc: - gb->last_rtc_second = time(NULL); - gb->rtc_real.high |= 0x80; /* This gives the game a hint that the clock should be reset. */ - gb->huc3_days = 0xFFFF; - gb->huc3_minutes = 0xFFF; - gb->huc3_alarm_enabled = false; -exit: return; } /* Loading will silently stop if the format is incomplete */ void GB_load_battery(GB_gameboy_t *gb, const char *path) { - FILE *f = fopen(path, "rb"); - if (!f) { - return; - } - - if (fread(gb->mbc_ram, 1, gb->mbc_ram_size, f) != gb->mbc_ram_size) { - goto reset_rtc; - } - - if (gb->cartridge_type->mbc_type == GB_HUC3) { - GB_huc3_rtc_time_t rtc_save; - if (fread(&rtc_save, sizeof(rtc_save), 1, f) != 1) { - goto reset_rtc; - } -#ifdef GB_BIG_ENDIAN - gb->last_rtc_second = __builtin_bswap64(rtc_save.last_rtc_second); - gb->huc3_minutes = __builtin_bswap16(rtc_save.minutes); - gb->huc3_days = __builtin_bswap16(rtc_save.days); - gb->huc3_alarm_minutes = __builtin_bswap16(rtc_save.alarm_minutes); - gb->huc3_alarm_days = __builtin_bswap16(rtc_save.alarm_days); - gb->huc3_alarm_enabled = rtc_save.alarm_enabled; -#else - gb->last_rtc_second = rtc_save.last_rtc_second; - gb->huc3_minutes = rtc_save.minutes; - gb->huc3_days = rtc_save.days; - gb->huc3_alarm_minutes = rtc_save.alarm_minutes; - gb->huc3_alarm_days = rtc_save.alarm_days; - gb->huc3_alarm_enabled = rtc_save.alarm_enabled; -#endif - if (gb->last_rtc_second > time(NULL)) { - /* We must reset RTC here, or it will not advance. */ - goto reset_rtc; - } - return; - } - - GB_rtc_save_t rtc_save; - switch (fread(&rtc_save, 1, sizeof(rtc_save), f)) { - case sizeof(rtc_save.sameboy_legacy): - memcpy(&gb->rtc_real, &rtc_save.sameboy_legacy.rtc_real, sizeof(gb->rtc_real)); - memcpy(&gb->rtc_latched, &rtc_save.sameboy_legacy.rtc_real, sizeof(gb->rtc_real)); - gb->last_rtc_second = rtc_save.sameboy_legacy.last_rtc_second; - break; - - case sizeof(rtc_save.vba32): - gb->rtc_real.seconds = rtc_save.vba32.rtc_real.seconds; - gb->rtc_real.minutes = rtc_save.vba32.rtc_real.minutes; - gb->rtc_real.hours = rtc_save.vba32.rtc_real.hours; - gb->rtc_real.days = rtc_save.vba32.rtc_real.days; - gb->rtc_real.high = rtc_save.vba32.rtc_real.high; - gb->rtc_latched.seconds = rtc_save.vba32.rtc_latched.seconds; - gb->rtc_latched.minutes = rtc_save.vba32.rtc_latched.minutes; - gb->rtc_latched.hours = rtc_save.vba32.rtc_latched.hours; - gb->rtc_latched.days = rtc_save.vba32.rtc_latched.days; - gb->rtc_latched.high = rtc_save.vba32.rtc_latched.high; -#ifdef GB_BIG_ENDIAN - gb->last_rtc_second = __builtin_bswap32(rtc_save.vba32.last_rtc_second); -#else - gb->last_rtc_second = rtc_save.vba32.last_rtc_second; -#endif - break; - - case sizeof(rtc_save.vba64): - gb->rtc_real.seconds = rtc_save.vba64.rtc_real.seconds; - gb->rtc_real.minutes = rtc_save.vba64.rtc_real.minutes; - gb->rtc_real.hours = rtc_save.vba64.rtc_real.hours; - gb->rtc_real.days = rtc_save.vba64.rtc_real.days; - gb->rtc_real.high = rtc_save.vba64.rtc_real.high; - gb->rtc_latched.seconds = rtc_save.vba64.rtc_latched.seconds; - gb->rtc_latched.minutes = rtc_save.vba64.rtc_latched.minutes; - gb->rtc_latched.hours = rtc_save.vba64.rtc_latched.hours; - gb->rtc_latched.days = rtc_save.vba64.rtc_latched.days; - gb->rtc_latched.high = rtc_save.vba64.rtc_latched.high; -#ifdef GB_BIG_ENDIAN - gb->last_rtc_second = __builtin_bswap64(rtc_save.vba64.last_rtc_second); -#else - gb->last_rtc_second = rtc_save.vba64.last_rtc_second; -#endif - break; - - default: - goto reset_rtc; - } - if (gb->last_rtc_second > time(NULL)) { - /* We must reset RTC here, or it will not advance. */ - goto reset_rtc; - } - - if (gb->last_rtc_second < 852076800) { /* 1/1/97. There weren't any RTC games that time, - so if the value we read is lower it means it wasn't - really RTC data. */ - goto reset_rtc; - } - goto exit; -reset_rtc: - gb->last_rtc_second = time(NULL); - gb->rtc_real.high |= 0x80; /* This gives the game a hint that the clock should be reset. */ - gb->huc3_days = 0xFFFF; - gb->huc3_minutes = 0xFFF; - gb->huc3_alarm_enabled = false; -exit: - fclose(f); return; } @@ -964,7 +596,6 @@ uint8_t GB_run(GB_gameboy_t *gb) gb->cycles_since_run = 0; GB_cpu_run(gb); if (gb->vblank_just_occured) { - GB_rtc_run(gb); GB_debugger_handle_async_commands(gb); GB_rewind_push(gb); } @@ -1361,7 +992,6 @@ static void request_boot_rom(GB_gameboy_t *gb) void GB_reset(GB_gameboy_t *gb) { - uint32_t mbc_ram_size = gb->mbc_ram_size; GB_model_t model = gb->model; memset(gb, 0, (size_t)GB_GET_SECTION((GB_gameboy_t *) 0, unsaved)); gb->model = model; @@ -1371,7 +1001,6 @@ void GB_reset(GB_gameboy_t *gb) gb->last_rtc_second = time(NULL); gb->cgb_ram_bank = 1; gb->io_registers[GB_IO_JOYP] = 0xCF; - gb->mbc_ram_size = mbc_ram_size; if (GB_is_cgb(gb)) { gb->ram_size = 0x1000 * 8; gb->vram_size = 0x2000 * 2; @@ -1474,9 +1103,9 @@ void *GB_get_direct_access(GB_gameboy_t *gb, GB_direct_access_t access, size_t * *bank = gb->cgb_ram_bank; return gb->ram; case GB_DIRECT_ACCESS_CART_RAM: - *size = gb->mbc_ram_size; - *bank = gb->mbc_ram_bank; - return gb->mbc_ram; + *size = 0; + *bank = 0; + return NULL; case GB_DIRECT_ACCESS_VRAM: *size = gb->vram_size; *bank = gb->cgb_vram_bank; @@ -1609,11 +1238,5 @@ void GB_set_boot_rom_load_callback(GB_gameboy_t *gb, GB_boot_rom_load_callback_t unsigned GB_time_to_alarm(GB_gameboy_t *gb) { - if (gb->cartridge_type->mbc_type != GB_HUC3) return 0; - if (!gb->huc3_alarm_enabled) return 0; - if (!(gb->huc3_alarm_days & 0x2000)) return 0; - unsigned current_time = (gb->huc3_days & 0x1FFF) * 24 * 60 * 60 + gb->huc3_minutes * 60 + (time(NULL) % 60); - unsigned alarm_time = (gb->huc3_alarm_days & 0x1FFF) * 24 * 60 * 60 + gb->huc3_alarm_minutes * 60; - if (current_time > alarm_time) return 0; - return alarm_time - current_time; + return 0; } diff --git a/Core/gb.h b/Core/gb.h index c42af4b..ecb5138 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -13,7 +13,6 @@ #include "debugger.h" #include "display.h" #include "joypad.h" -#include "mbc.h" #include "memory.h" #include "printer.h" #include "timing.h" @@ -128,66 +127,52 @@ typedef enum { #define GB_MAX_IR_QUEUE 256 enum { - /* Joypad and Serial */ - GB_IO_JOYP = 0x00, // Joypad (R/W) - GB_IO_SB = 0x01, // Serial transfer data (R/W) - GB_IO_SC = 0x02, // Serial Transfer Control (R/W) - /* Missing */ + GB_IO_JOYP = 0x00, + GB_IO_SB = 0x01, + GB_IO_SC = 0x02, + GB_IO_DIV = 0x04, + GB_IO_TIMA = 0x05, + GB_IO_TMA = 0x06, + GB_IO_TAC = 0x07, + GB_IO_IF = 0x0F, + GB_IO_LCDC = 0x10, + GB_IO_STAT = 0x11, + GB_IO_SCY = 0x12, + GB_IO_SCX = 0x13, + GB_IO_OBP0 = 0x14, + GB_IO_OBP1 = 0x15, + GB_IO_WY = 0x16, + GB_IO_WX = 0x17, + GB_IO_LY = 0x18, + GB_IO_LYC = 0x19, + GB_IO_DMA = 0x1A, + GB_IO_BGP = 0x1B, + GB_IO_NR10 = 0x20, + GB_IO_NR12 = 0x21, + GB_IO_NR11 = 0x22, + GB_IO_NR13 = 0x23, + GB_IO_NR14 = 0x24, + GB_IO_NR21 = 0x25, + GB_IO_NR22 = 0x27, + GB_IO_NR23 = 0x28, + GB_IO_NR24 = 0x29, + GB_IO_NR30 = 0x2A, + GB_IO_NR31 = 0x2B, + GB_IO_NR32 = 0x2C, + GB_IO_NR33 = 0x2D, + GB_IO_NR34 = 0x2E, + GB_IO_WAV_START = 0x30, + GB_IO_WAV_END = 0x3F, + GB_IO_NR41 = 0x40, + GB_IO_NR43 = 0x41, + GB_IO_NR42 = 0x42, + GB_IO_NR44 = 0x43, + GB_IO_NR50 = 0x44, + GB_IO_NR52 = 0x45, + GB_IO_NR51 = 0x46, + GB_IO_IE = 0xFF, - /* Timers */ - GB_IO_DIV = 0x04, // Divider Register (R/W) - GB_IO_TIMA = 0x05, // Timer counter (R/W) - GB_IO_TMA = 0x06, // Timer Modulo (R/W) - GB_IO_TAC = 0x07, // Timer Control (R/W) - - /* Missing */ - - GB_IO_IF = 0x0f, // Interrupt Flag (R/W) - - /* Sound */ - GB_IO_NR10 = 0x10, // Channel 1 Sweep register (R/W) - GB_IO_NR11 = 0x11, // Channel 1 Sound length/Wave pattern duty (R/W) - GB_IO_NR12 = 0x12, // Channel 1 Volume Envelope (R/W) - GB_IO_NR13 = 0x13, // Channel 1 Frequency lo (Write Only) - GB_IO_NR14 = 0x14, // Channel 1 Frequency hi (R/W) - /* NR20 does not exist */ - GB_IO_NR21 = 0x16, // Channel 2 Sound Length/Wave Pattern Duty (R/W) - GB_IO_NR22 = 0x17, // Channel 2 Volume Envelope (R/W) - GB_IO_NR23 = 0x18, // Channel 2 Frequency lo data (W) - GB_IO_NR24 = 0x19, // Channel 2 Frequency hi data (R/W) - GB_IO_NR30 = 0x1a, // Channel 3 Sound on/off (R/W) - GB_IO_NR31 = 0x1b, // Channel 3 Sound Length - GB_IO_NR32 = 0x1c, // Channel 3 Select output level (R/W) - GB_IO_NR33 = 0x1d, // Channel 3 Frequency's lower data (W) - GB_IO_NR34 = 0x1e, // Channel 3 Frequency's higher data (R/W) - /* NR40 does not exist */ - GB_IO_NR41 = 0x20, // Channel 4 Sound Length (R/W) - GB_IO_NR42 = 0x21, // Channel 4 Volume Envelope (R/W) - GB_IO_NR43 = 0x22, // Channel 4 Polynomial Counter (R/W) - GB_IO_NR44 = 0x23, // Channel 4 Counter/consecutive, Inital (R/W) - GB_IO_NR50 = 0x24, // Channel control / ON-OFF / Volume (R/W) - GB_IO_NR51 = 0x25, // Selection of Sound output terminal (R/W) - GB_IO_NR52 = 0x26, // Sound on/off - - /* Missing */ - - GB_IO_WAV_START = 0x30, // Wave pattern start - GB_IO_WAV_END = 0x3f, // Wave pattern end - - /* Graphics */ - GB_IO_LCDC = 0x40, // LCD Control (R/W) - GB_IO_STAT = 0x41, // LCDC Status (R/W) - GB_IO_SCY = 0x42, // Scroll Y (R/W) - GB_IO_SCX = 0x43, // Scroll X (R/W) - GB_IO_LY = 0x44, // LCDC Y-Coordinate (R) - GB_IO_LYC = 0x45, // LY Compare (R/W) - GB_IO_DMA = 0x46, // DMA Transfer and Start Address (W) - GB_IO_BGP = 0x47, // BG Palette Data (R/W) - Non CGB Mode Only - GB_IO_OBP0 = 0x48, // Object Palette 0 Data (R/W) - Non CGB Mode Only - GB_IO_OBP1 = 0x49, // Object Palette 1 Data (R/W) - Non CGB Mode Only - GB_IO_WY = 0x4a, // Window Y Position (R/W) - GB_IO_WX = 0x4b, // Window X Position minus 7 (R/W) // Has some undocumented compatibility flags written at boot. // Unfortunately it is not readable or writable after boot has finished, so research of this // register is quite limited. The value written to this register, however, can be controlled @@ -396,9 +381,6 @@ struct GB_gameboy_internal_s { /* MBC */ GB_SECTION(mbc, uint16_t mbc_rom_bank; - uint8_t mbc_ram_bank; - uint32_t mbc_ram_size; - bool mbc_ram_enable; union { struct { uint8_t bank_low:5; @@ -556,19 +538,12 @@ struct GB_gameboy_internal_s { /* ROM */ uint8_t *rom; uint32_t rom_size; - const GB_cartridge_t *cartridge_type; - enum { - GB_STANDARD_MBC1_WIRING, - GB_MBC1M_WIRING, - } mbc1_wiring; - bool is_mbc30; unsigned pending_cycles; /* Various RAMs */ uint8_t *ram; uint8_t *vram; - uint8_t *mbc_ram; /* I/O */ uint32_t *screen; diff --git a/Core/mbc.c b/Core/mbc.c deleted file mode 100644 index 2259681..0000000 --- a/Core/mbc.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include -#include -#include "gb.h" - -const GB_cartridge_t GB_cart_defs[256] = { - // From http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header#0147_-_Cartridge_Type - /* MBC SUBTYPE RAM BAT. RTC RUMB. */ - { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 00h ROM ONLY - { GB_MBC1 , GB_STANDARD_MBC, false, false, false, false}, // 01h MBC1 - { GB_MBC1 , GB_STANDARD_MBC, true , false, false, false}, // 02h MBC1+RAM - { GB_MBC1 , GB_STANDARD_MBC, true , true , false, false}, // 03h MBC1+RAM+BATTERY - [5] = - { GB_MBC2 , GB_STANDARD_MBC, true , false, false, false}, // 05h MBC2 - { GB_MBC2 , GB_STANDARD_MBC, true , true , false, false}, // 06h MBC2+BATTERY - [8] = - { GB_NO_MBC, GB_STANDARD_MBC, true , false, false, false}, // 08h ROM+RAM - { GB_NO_MBC, GB_STANDARD_MBC, true , true , false, false}, // 09h ROM+RAM+BATTERY - [0xB] = - /* Todo: Not supported yet */ - { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Bh MMM01 - { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Ch MMM01+RAM - { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Dh MMM01+RAM+BATTERY - [0xF] = - { GB_MBC3 , GB_STANDARD_MBC, false, true, true , false}, // 0Fh MBC3+TIMER+BATTERY - { GB_MBC3 , GB_STANDARD_MBC, true , true, true , false}, // 10h MBC3+TIMER+RAM+BATTERY - { GB_MBC3 , GB_STANDARD_MBC, false, false, false, false}, // 11h MBC3 - { GB_MBC3 , GB_STANDARD_MBC, true , false, false, false}, // 12h MBC3+RAM - { GB_MBC3 , GB_STANDARD_MBC, true , true , false, false}, // 13h MBC3+RAM+BATTERY - [0x19] = - { GB_MBC5 , GB_STANDARD_MBC, false, false, false, false}, // 19h MBC5 - { GB_MBC5 , GB_STANDARD_MBC, true , false, false, false}, // 1Ah MBC5+RAM - { GB_MBC5 , GB_STANDARD_MBC, true , true , false, false}, // 1Bh MBC5+RAM+BATTERY - { GB_MBC5 , GB_STANDARD_MBC, false, false, false, true }, // 1Ch MBC5+RUMBLE - { GB_MBC5 , GB_STANDARD_MBC, true , false, false, true }, // 1Dh MBC5+RUMBLE+RAM - { GB_MBC5 , GB_STANDARD_MBC, true , true , false, true }, // 1Eh MBC5+RUMBLE+RAM+BATTERY - [0xFC] = - { GB_MBC5 , GB_CAMERA , true , true , false, false}, // FCh POCKET CAMERA - { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // FDh BANDAI TAMA5 (Todo: Not supported) - { GB_HUC3 , GB_STANDARD_MBC, true , true , true, false}, // FEh HuC3 - { GB_HUC1 , GB_STANDARD_MBC, true , true , false, false}, // FFh HuC1+RAM+BATTERY -}; - -void GB_update_mbc_mappings(GB_gameboy_t *gb) -{ - switch (gb->cartridge_type->mbc_type) { - case GB_NO_MBC: return; - case GB_MBC1: - switch (gb->mbc1_wiring) { - case GB_STANDARD_MBC1_WIRING: - gb->mbc_rom_bank = gb->mbc1.bank_low | (gb->mbc1.bank_high << 5); - if (gb->mbc1.mode == 0) { - gb->mbc_ram_bank = 0; - gb->mbc_rom0_bank = 0; - } - else { - gb->mbc_ram_bank = gb->mbc1.bank_high; - gb->mbc_rom0_bank = gb->mbc1.bank_high << 5; - } - if ((gb->mbc_rom_bank & 0x1F) == 0) { - gb->mbc_rom_bank++; - } - break; - case GB_MBC1M_WIRING: - gb->mbc_rom_bank = (gb->mbc1.bank_low & 0xF) | (gb->mbc1.bank_high << 4); - if (gb->mbc1.mode == 0) { - gb->mbc_ram_bank = 0; - gb->mbc_rom0_bank = 0; - } - else { - gb->mbc_rom0_bank = gb->mbc1.bank_high << 4; - gb->mbc_ram_bank = 0; - } - if ((gb->mbc1.bank_low & 0x1F) == 0) { - gb->mbc_rom_bank++; - } - break; - } - break; - case GB_MBC2: - gb->mbc_rom_bank = gb->mbc2.rom_bank; - if ((gb->mbc_rom_bank & 0xF) == 0) { - gb->mbc_rom_bank = 1; - } - break; - case GB_MBC3: - gb->mbc_rom_bank = gb->mbc3.rom_bank; - gb->mbc_ram_bank = gb->mbc3.ram_bank; - if (!gb->is_mbc30) { - gb->mbc_rom_bank &= 0x7F; - } - if (gb->mbc_rom_bank == 0) { - gb->mbc_rom_bank = 1; - } - break; - case GB_MBC5: - gb->mbc_rom_bank = gb->mbc5.rom_bank_low | (gb->mbc5.rom_bank_high << 8); - gb->mbc_ram_bank = gb->mbc5.ram_bank; - break; - case GB_HUC1: - if (gb->huc1.mode == 0) { - gb->mbc_rom_bank = gb->huc1.bank_low | (gb->mbc1.bank_high << 6); - gb->mbc_ram_bank = 0; - } - else { - gb->mbc_rom_bank = gb->huc1.bank_low; - gb->mbc_ram_bank = gb->huc1.bank_high; - } - break; - case GB_HUC3: - gb->mbc_rom_bank = gb->huc3.rom_bank; - gb->mbc_ram_bank = gb->huc3.ram_bank; - break; - } -} - -void GB_configure_cart(GB_gameboy_t *gb) -{ - gb->cartridge_type = &GB_cart_defs[gb->rom[0x147]]; - - if (gb->rom[0x147] == 0 && gb->rom_size > 0x8000) { - GB_log(gb, "ROM header reports no MBC, but file size is over 32Kb. Assuming cartridge uses MBC3.\n"); - gb->cartridge_type = &GB_cart_defs[0x11]; - } - else if (gb->rom[0x147] != 0 && memcmp(gb->cartridge_type, &GB_cart_defs[0], sizeof(GB_cart_defs[0])) == 0) { - GB_log(gb, "Cartridge type %02x is not yet supported.\n", gb->rom[0x147]); - } - - if (gb->cartridge_type->has_ram) { - if (gb->cartridge_type->mbc_type == GB_MBC2) { - gb->mbc_ram_size = 0x200; - } - else { - static const unsigned ram_sizes[256] = {0, 0x800, 0x2000, 0x8000, 0x20000, 0x10000}; - gb->mbc_ram_size = ram_sizes[gb->rom[0x149]]; - } - - if (gb->mbc_ram_size) { - gb->mbc_ram = malloc(gb->mbc_ram_size); - } - - /* Todo: Some games assume unintialized MBC RAM is 0xFF. It this true for all cartridges types? */ - memset(gb->mbc_ram, 0xFF, gb->mbc_ram_size); - } - - /* MBC1 has at least 3 types of wiring (We currently support two (Standard and 4bit-MBC1M) of these). - See http://forums.nesdev.com/viewtopic.php?f=20&t=14099 */ - - /* Attempt to "guess" wiring */ - if (gb->cartridge_type->mbc_type == GB_MBC1) { - if (gb->rom_size >= 0x44000 && memcmp(gb->rom + 0x104, gb->rom + 0x40104, 0x30) == 0) { - gb->mbc1_wiring = GB_MBC1M_WIRING; - } - } - - /* Detect MBC30 */ - if (gb->cartridge_type->mbc_type == GB_MBC3) { - if (gb->rom_size > 0x200000 || gb->mbc_ram_size > 0x8000) { - gb->is_mbc30 = true; - } - } - - /* Set MBC5's bank to 1 correctly */ - if (gb->cartridge_type->mbc_type == GB_MBC5) { - gb->mbc5.rom_bank_low = 1; - } -} diff --git a/Core/mbc.h b/Core/mbc.h deleted file mode 100644 index 6a23300..0000000 --- a/Core/mbc.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef MBC_h -#define MBC_h -#include "gb_struct_def.h" -#include - -typedef struct { - enum { - GB_NO_MBC, - GB_MBC1, - GB_MBC2, - GB_MBC3, - GB_MBC5, - GB_HUC1, - GB_HUC3, - } mbc_type; - enum { - GB_STANDARD_MBC, - GB_CAMERA, - } mbc_subtype; - bool has_ram; - bool has_battery; - bool has_rtc; - bool has_rumble; -} GB_cartridge_t; - -#ifdef GB_INTERNAL -extern const GB_cartridge_t GB_cart_defs[256]; -void GB_update_mbc_mappings(GB_gameboy_t *gb); -void GB_configure_cart(GB_gameboy_t *gb); -#endif - -#endif /* MBC_h */ diff --git a/Core/memory.c b/Core/memory.c index f73209e..87dd1f3 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -56,9 +56,6 @@ void GB_trigger_oam_bug(GB_gameboy_t *gb, uint16_t address) gb->oam[gb->accessed_oam_row + 1] = bitwise_glitch(gb->oam[gb->accessed_oam_row + 1], gb->oam[gb->accessed_oam_row - 7], gb->oam[gb->accessed_oam_row - 3]); - for (unsigned i = 2; i < 8; i++) { - gb->oam[gb->accessed_oam_row + i] = gb->oam[gb->accessed_oam_row - 8 + i]; - } } } } @@ -120,14 +117,6 @@ static bool effective_ir_input(GB_gameboy_t *gb) static uint8_t read_rom(GB_gameboy_t *gb, uint16_t addr) { - if (addr < 0x100 && !gb->boot_rom_finished) { - return gb->boot_rom[addr]; - } - - if (addr >= 0x200 && addr < 0x900 && GB_is_cgb(gb) && !gb->boot_rom_finished) { - return gb->boot_rom[addr]; - } - if (!gb->rom_size) { return 0xFF; } @@ -163,65 +152,7 @@ static uint8_t read_vram(GB_gameboy_t *gb, uint16_t addr) static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr) { - if (gb->cartridge_type->mbc_type == GB_HUC3) { - switch (gb->huc3_mode) { - case 0xC: // RTC read - if (gb->huc3_access_flags == 0x2) { - return 1; - } - return gb->huc3_read; - case 0xD: // RTC status - return 1; - case 0xE: // IR mode - return effective_ir_input(gb); // TODO: What are the other bits? - default: - GB_log(gb, "Unsupported HuC-3 mode %x read: %04x\n", gb->huc3_mode, addr); - return 1; // TODO: What happens in this case? - case 0: // TODO: R/O RAM? (or is it disabled?) - case 0xA: // RAM - break; - } - } - - if ((!gb->mbc_ram_enable) && - gb->cartridge_type->mbc_subtype != GB_CAMERA && - gb->cartridge_type->mbc_type != GB_HUC1 && - gb->cartridge_type->mbc_type != GB_HUC3) { - return 0xFF; - } - - if (gb->cartridge_type->mbc_type == GB_HUC1 && gb->huc1.ir_mode) { - return 0xc0 | effective_ir_input(gb); - } - - if (gb->cartridge_type->has_rtc && gb->cartridge_type->mbc_type != GB_HUC3 && - gb->mbc3_rtc_mapped && gb->mbc_ram_bank <= 4) { - /* RTC read */ - gb->rtc_latched.high |= ~0xC1; /* Not all bytes in RTC high are used. */ - return gb->rtc_latched.data[gb->mbc_ram_bank]; - } - - if (gb->camera_registers_mapped) { - return GB_camera_read_register(gb, addr); - } - - if (!gb->mbc_ram || !gb->mbc_ram_size) { - return 0xFF; - } - - if (gb->cartridge_type->mbc_subtype == GB_CAMERA && gb->mbc_ram_bank == 0 && addr >= 0xa100 && addr < 0xaf00) { - return GB_camera_read_image(gb, addr - 0xa100); - } - - uint8_t effective_bank = gb->mbc_ram_bank; - if (gb->cartridge_type->mbc_type == GB_MBC3 && !gb->is_mbc30) { - effective_bank &= 0x3; - } - uint8_t ret = gb->mbc_ram[((addr & 0x1FFF) + effective_bank * 0x2000) & (gb->mbc_ram_size - 1)]; - if (gb->cartridge_type->mbc_type == GB_MBC2) { - ret |= 0xF0; - } - return ret; + return 0xFF; } static uint8_t read_ram(GB_gameboy_t *gb, uint16_t addr) @@ -442,7 +373,7 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr) case GB_IO_UNKNOWN5: return GB_is_cgb(gb)? gb->io_registers[addr & 0xFF] | 0x8F : 0xFF; default: - if ((addr & 0xFF) >= GB_IO_NR10 && (addr & 0xFF) <= GB_IO_WAV_END) { + if ((addr & 0xFF) >= GB_IO_NR10 && (addr & 0xFF) <= GB_IO_NR51) { return GB_apu_read(gb, addr & 0xFF); } return 0xFF; @@ -493,75 +424,9 @@ uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr) static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) { - switch (gb->cartridge_type->mbc_type) { - case GB_NO_MBC: return; - case GB_MBC1: - switch (addr & 0xF000) { - case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break; - case 0x2000: case 0x3000: gb->mbc1.bank_low = value; break; - case 0x4000: case 0x5000: gb->mbc1.bank_high = value; break; - case 0x6000: case 0x7000: gb->mbc1.mode = value; break; - } - break; - case GB_MBC2: - switch (addr & 0x4100) { - case 0x0000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break; - case 0x0100: gb->mbc2.rom_bank = value; break; - } - break; - case GB_MBC3: - switch (addr & 0xF000) { - case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break; - case 0x2000: case 0x3000: gb->mbc3.rom_bank = value; break; - case 0x4000: case 0x5000: - gb->mbc3.ram_bank = value; - gb->mbc3_rtc_mapped = value & 8; - break; - case 0x6000: case 0x7000: - if (!gb->rtc_latch && (value & 1)) { /* Todo: verify condition is correct */ - memcpy(&gb->rtc_latched, &gb->rtc_real, sizeof(gb->rtc_real)); - } - gb->rtc_latch = value & 1; - break; - } - break; - case GB_MBC5: - switch (addr & 0xF000) { - case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break; - case 0x2000: gb->mbc5.rom_bank_low = value; break; - case 0x3000: gb->mbc5.rom_bank_high = value; break; - case 0x4000: case 0x5000: - if (gb->cartridge_type->has_rumble) { - if (!!(value & 8) != gb->rumble_state) { - gb->rumble_state = !gb->rumble_state; - } - value &= 7; - } - gb->mbc5.ram_bank = value; - gb->camera_registers_mapped = (value & 0x10) && gb->cartridge_type->mbc_subtype == GB_CAMERA; - break; - } - break; - case GB_HUC1: - switch (addr & 0xF000) { - case 0x0000: case 0x1000: gb->huc1.ir_mode = (value & 0xF) == 0xE; break; - case 0x2000: case 0x3000: gb->huc1.bank_low = value; break; - case 0x4000: case 0x5000: gb->huc1.bank_high = value; break; - case 0x6000: case 0x7000: gb->huc1.mode = value; break; - } - break; - case GB_HUC3: - switch (addr & 0xF000) { - case 0x0000: case 0x1000: - gb->huc3_mode = value & 0xF; - gb->mbc_ram_enable = gb->huc3_mode == 0xA; - break; - case 0x2000: case 0x3000: gb->huc3.rom_bank = value; break; - case 0x4000: case 0x5000: gb->huc3.ram_bank = value; break; - } - break; + if (addr == 0x0001) { + gb->mbc_rom_bank = value; } - GB_update_mbc_mappings(gb); } static void write_vram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) @@ -586,135 +451,12 @@ static void write_vram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) gb->vram[(addr & 0x1FFF) + (uint16_t) gb->cgb_vram_bank * 0x2000] = value; } -static bool huc3_write(GB_gameboy_t *gb, uint8_t value) -{ - switch (gb->huc3_mode) { - case 0xB: // RTC Write - switch (value >> 4) { - case 1: - if (gb->huc3_access_index < 3) { - gb->huc3_read = (gb->huc3_minutes >> (gb->huc3_access_index * 4)) & 0xF; - } - else if (gb->huc3_access_index < 7) { - gb->huc3_read = (gb->huc3_days >> ((gb->huc3_access_index - 3) * 4)) & 0xF; - } - else { - // GB_log(gb, "Attempting to read from unsupported HuC-3 register: %03x\n", gb->huc3_access_index); - } - gb->huc3_access_index++; - break; - case 2: - case 3: - if (gb->huc3_access_index < 3) { - gb->huc3_minutes &= ~(0xF << (gb->huc3_access_index * 4)); - gb->huc3_minutes |= ((value & 0xF) << (gb->huc3_access_index * 4)); - } - else if (gb->huc3_access_index < 7) { - gb->huc3_days &= ~(0xF << ((gb->huc3_access_index - 3) * 4)); - gb->huc3_days |= ((value & 0xF) << ((gb->huc3_access_index - 3) * 4)); - } - else if (gb->huc3_access_index >= 0x58 && gb->huc3_access_index <= 0x5a) { - gb->huc3_alarm_minutes &= ~(0xF << ((gb->huc3_access_index - 0x58) * 4)); - gb->huc3_alarm_minutes |= ((value & 0xF) << ((gb->huc3_access_index - 0x58) * 4)); - } - else if (gb->huc3_access_index >= 0x5b && gb->huc3_access_index <= 0x5e) { - gb->huc3_alarm_days &= ~(0xF << ((gb->huc3_access_index - 0x5b) * 4)); - gb->huc3_alarm_days |= ((value & 0xF) << ((gb->huc3_access_index - 0x5b) * 4)); - } - else if (gb->huc3_access_index == 0x5f) { - gb->huc3_alarm_enabled = value & 1; - } - else { - // GB_log(gb, "Attempting to write %x to unsupported HuC-3 register: %03x\n", value & 0xF, gb->huc3_access_index); - } - if ((value >> 4) == 3) { - gb->huc3_access_index++; - } - break; - case 4: - gb->huc3_access_index &= 0xF0; - gb->huc3_access_index |= value & 0xF; - break; - case 5: - gb->huc3_access_index &= 0x0F; - gb->huc3_access_index |= (value & 0xF) << 4; - break; - case 6: - gb->huc3_access_flags = (value & 0xF); - break; - - default: - break; - } - - return true; - case 0xD: // RTC status - // Not sure what writes here mean, they're always 0xFE - return true; - case 0xE: { // IR mode - bool old_input = effective_ir_input(gb); - gb->cart_ir = value & 1; - bool new_input = effective_ir_input(gb); - if (new_input != old_input) { - if (gb->infrared_callback) { - gb->infrared_callback(gb, new_input, gb->cycles_since_ir_change); - } - gb->cycles_since_ir_change = 0; - } - return true; - } - case 0xC: - return true; - default: - return false; - case 0: // Disabled - case 0xA: // RAM - return false; - } -} - static void write_mbc_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) { - if (gb->cartridge_type->mbc_type == GB_HUC3) { - if (huc3_write(gb, value)) return; + if (addr == 0xb000) { + gb->mbc_rom0_bank = value * 2; + gb->mbc_rom_bank = value * 2 + 1; } - - if (gb->camera_registers_mapped) { - GB_camera_write_register(gb, addr, value); - return; - } - - if ((!gb->mbc_ram_enable) - && gb->cartridge_type->mbc_type != GB_HUC1) return; - - if (gb->cartridge_type->mbc_type == GB_HUC1 && gb->huc1.ir_mode) { - bool old_input = effective_ir_input(gb); - gb->cart_ir = value & 1; - bool new_input = effective_ir_input(gb); - if (new_input != old_input) { - if (gb->infrared_callback) { - gb->infrared_callback(gb, new_input, gb->cycles_since_ir_change); - } - gb->cycles_since_ir_change = 0; - } - return; - } - - if (gb->cartridge_type->has_rtc && gb->mbc3_rtc_mapped && gb->mbc_ram_bank <= 4) { - gb->rtc_latched.data[gb->mbc_ram_bank] = gb->rtc_real.data[gb->mbc_ram_bank] = value; - return; - } - - if (!gb->mbc_ram || !gb->mbc_ram_size) { - return; - } - - uint8_t effective_bank = gb->mbc_ram_bank; - if (gb->cartridge_type->mbc_type == GB_MBC3 && !gb->is_mbc30) { - effective_bank &= 0x3; - } - - gb->mbc_ram[((addr & 0x1FFF) + effective_bank * 0x2000) & (gb->mbc_ram_size - 1)] = value; } static void write_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) @@ -1121,7 +863,7 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) } default: - if ((addr & 0xFF) >= GB_IO_NR10 && (addr & 0xFF) <= GB_IO_WAV_END) { + if ((addr & 0xFF) >= GB_IO_NR10 && (addr & 0xFF) <= GB_IO_NR51) { GB_apu_write(gb, addr & 0xFF, value); return; } diff --git a/Core/rumble.c b/Core/rumble.c index 8cbe20d..cb45ba5 100644 --- a/Core/rumble.c +++ b/Core/rumble.c @@ -15,13 +15,7 @@ void GB_handle_rumble(GB_gameboy_t *gb) if (gb->rumble_mode == GB_RUMBLE_DISABLED) { return; } - if (gb->cartridge_type->has_rumble) { - if (gb->rumble_on_cycles + gb->rumble_off_cycles) { - gb->rumble_callback(gb, gb->rumble_on_cycles / (double)(gb->rumble_on_cycles + gb->rumble_off_cycles)); - gb->rumble_on_cycles = gb->rumble_off_cycles = 0; - } - } - else if (gb->rumble_mode == GB_RUMBLE_ALL_GAMES) { + if (gb->rumble_mode == GB_RUMBLE_ALL_GAMES) { unsigned volume = (gb->io_registers[GB_IO_NR50] & 7) + 1 + ((gb->io_registers[GB_IO_NR50] >> 4) & 7) + 1; unsigned ch4_volume = volume * (!!(gb->io_registers[GB_IO_NR51] & 8) + !!(gb->io_registers[GB_IO_NR51] & 0x80)); unsigned ch1_volume = volume * (!!(gb->io_registers[GB_IO_NR51] & 1) + !!(gb->io_registers[GB_IO_NR51] & 0x10)); diff --git a/Core/save_state.c b/Core/save_state.c index 827cf57..c9c1c1f 100644 --- a/Core/save_state.c +++ b/Core/save_state.c @@ -40,10 +40,6 @@ int GB_save_state(GB_gameboy_t *gb, const char *path) if (!dump_section(f, gb->sgb, sizeof(*gb->sgb))) goto error; } - if (fwrite(gb->mbc_ram, 1, gb->mbc_ram_size, f) != gb->mbc_ram_size) { - goto error; - } - if (fwrite(gb->ram, 1, gb->ram_size, f) != gb->ram_size) { goto error; } @@ -73,7 +69,6 @@ size_t GB_get_save_state_size(GB_gameboy_t *gb) + GB_SECTION_SIZE(rtc ) + sizeof(uint32_t) + GB_SECTION_SIZE(video ) + sizeof(uint32_t) + (GB_is_hle_sgb(gb)? sizeof(*gb->sgb) + sizeof(uint32_t) : 0) - + gb->mbc_ram_size + gb->ram_size + gb->vram_size; } @@ -109,7 +104,6 @@ void GB_save_state_to_buffer(GB_gameboy_t *gb, uint8_t *buffer) } - buffer_write(gb->mbc_ram, gb->mbc_ram_size, &buffer); buffer_write(gb->ram, gb->ram_size, &buffer); buffer_write(gb->vram, gb->vram_size, &buffer); } @@ -168,11 +162,6 @@ static bool verify_and_update_state_compatibility(GB_gameboy_t *gb, GB_gameboy_t return false; } - if (gb->mbc_ram_size < save->mbc_ram_size) { - GB_log(gb, "The save state has non-matching MBC RAM size.\n"); - return false; - } - if (gb->vram_size != save->vram_size) { GB_log(gb, "The save state has non-matching VRAM size. Try changing the emulated model.\n"); return false; @@ -265,13 +254,7 @@ int GB_load_state(GB_gameboy_t *gb, const char *path) if (GB_is_hle_sgb(gb)) { if (!read_section(f, gb->sgb, sizeof(*gb->sgb), false)) goto error; } - - memset(gb->mbc_ram + save.mbc_ram_size, 0xFF, gb->mbc_ram_size - save.mbc_ram_size); - if (fread(gb->mbc_ram, 1, save.mbc_ram_size, f) != save.mbc_ram_size) { - fclose(f); - return EIO; - } - + if (fread(gb->ram, 1, gb->ram_size, f) != gb->ram_size) { fclose(f); return EIO; @@ -385,12 +368,7 @@ int GB_load_state_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t le if (GB_is_hle_sgb(gb)) { if (!buffer_read_section(&buffer, &length, gb->sgb, sizeof(*gb->sgb), false)) return -1; } - - memset(gb->mbc_ram + save.mbc_ram_size, 0xFF, gb->mbc_ram_size - save.mbc_ram_size); - if (buffer_read(gb->mbc_ram, save.mbc_ram_size, &buffer, &length) != save.mbc_ram_size) { - return -1; - } - + if (buffer_read(gb->ram, gb->ram_size, &buffer, &length) != gb->ram_size) { return -1; } diff --git a/Core/timing.c b/Core/timing.c index 965ba27..fcfcd2b 100644 --- a/Core/timing.c +++ b/Core/timing.c @@ -276,52 +276,3 @@ void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac) } } } - -void GB_rtc_run(GB_gameboy_t *gb) -{ - if (gb->cartridge_type->mbc_type == GB_HUC3) { - time_t current_time = time(NULL); - while (gb->last_rtc_second / 60 < current_time / 60) { - gb->last_rtc_second += 60; - gb->huc3_minutes++; - if (gb->huc3_minutes == 60 * 24) { - gb->huc3_days++; - gb->huc3_minutes = 0; - } - } - return; - } - - if ((gb->rtc_real.high & 0x40) == 0) { /* is timer running? */ - time_t current_time = time(NULL); - - while (gb->last_rtc_second + 60 * 60 * 24 < current_time) { - gb->last_rtc_second += 60 * 60 * 24; - if (++gb->rtc_real.days == 0) { - if (gb->rtc_real.high & 1) { /* Bit 8 of days*/ - gb->rtc_real.high |= 0x80; /* Overflow bit */ - } - gb->rtc_real.high ^= 1; - } - } - - while (gb->last_rtc_second < current_time) { - gb->last_rtc_second++; - if (++gb->rtc_real.seconds == 60) { - gb->rtc_real.seconds = 0; - if (++gb->rtc_real.minutes == 60) { - gb->rtc_real.minutes = 0; - if (++gb->rtc_real.hours == 24) { - gb->rtc_real.hours = 0; - if (++gb->rtc_real.days == 0) { - if (gb->rtc_real.high & 1) { /* Bit 8 of days*/ - gb->rtc_real.high |= 0x80; /* Overflow bit */ - } - gb->rtc_real.high ^= 1; - } - } - } - } - } - } -} diff --git a/Core/timing.h b/Core/timing.h index d4fa07f..07e0473 100644 --- a/Core/timing.h +++ b/Core/timing.h @@ -4,7 +4,6 @@ #ifdef GB_INTERNAL void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles); -void GB_rtc_run(GB_gameboy_t *gb); void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac); bool GB_timing_sync_turbo(GB_gameboy_t *gb); /* Returns true if should skip frame */ void GB_timing_sync(GB_gameboy_t *gb); diff --git a/Misc/registers.sym b/Misc/registers.sym index 3b31b74..62bb320 100644 --- a/Misc/registers.sym +++ b/Misc/registers.sym @@ -6,62 +6,42 @@ 00:FF06 IO_TMA 00:FF07 IO_TAC 00:FF0F IO_IF -00:FF10 IO_NR10 -00:FF11 IO_NR11 -00:FF12 IO_NR12 -00:FF13 IO_NR13 -00:FF14 IO_NR14 -00:FF16 IO_NR21 -00:FF17 IO_NR22 -00:FF18 IO_NR23 -00:FF19 IO_NR24 -00:FF1A IO_NR30 -00:FF1B IO_NR31 -00:FF1C IO_NR32 -00:FF1D IO_NR33 -00:FF1E IO_NR34 -00:FF20 IO_NR41 -00:FF21 IO_NR42 -00:FF22 IO_NR43 -00:FF23 IO_NR44 -00:FF24 IO_NR50 -00:FF25 IO_NR51 -00:FF26 IO_NR52 +00:FF10 IO_LCDC +00:FF11 IO_STAT +00:FF12 IO_SCY +00:FF13 IO_SCX +00:FF14 IO_OBP0 +00:FF15 IO_OBP1 +00:FF16 IO_WY +00:FF17 IO_WX +00:FF18 IO_LY +00:FF19 IO_LYC +00:FF1A IO_DMA +00:FF1B IO_BGP +00:FF20 IO_NR10 +00:FF21 IO_NR12 +00:FF22 IO_NR11 +00:FF23 IO_NR13 +00:FF24 IO_NR14 +00:FF25 IO_NR21 +00:FF27 IO_NR22 +00:FF28 IO_NR23 +00:FF29 IO_NR24 +00:FF2A IO_NR30 +00:FF2B IO_NR31 +00:FF2C IO_NR32 +00:FF2D IO_NR33 +00:FF2E IO_NR34 00:FF30 IO_WAV_START 00:FF3F IO_WAV_END -00:FF40 IO_LCDC -00:FF41 IO_STAT -00:FF42 IO_SCY -00:FF43 IO_SCX -00:FF44 IO_LY -00:FF45 IO_LYC -00:FF46 IO_DMA -00:FF47 IO_BGP -00:FF48 IO_OBP0 -00:FF49 IO_OBP1 -00:FF4A IO_WY -00:FF4B IO_WX +00:FF40 IO_NR41 +00:FF41 IO_NR43 +00:FF42 IO_NR42 +00:FF43 IO_NR44 +00:FF44 IO_NR50 +00:FF45 IO_NR52 +00:FF46 IO_NR51 00:FF4C IO_KEY0 00:FF4D IO_KEY1 00:FF4F IO_VBK -00:FF50 IO_BANK -00:FF51 IO_HDMA1 -00:FF52 IO_HDMA2 -00:FF53 IO_HDMA3 -00:FF54 IO_HDMA4 -00:FF55 IO_HDMA5 -00:FF56 IO_RP -00:FF68 IO_BGPI -00:FF69 IO_BGPD -00:FF6A IO_OBPI -00:FF6B IO_OBPD -00:FF6C IO_OPRI -00:FF70 IO_SVBK -00:FF72 IO_UNKNOWN2 -00:FF73 IO_UNKNOWN3 -00:FF74 IO_UNKNOWN4 -00:FF75 IO_UNKNOWN5 -00:FF76 IO_PCM_12 -00:FF77 IO_PCM_34 -00:FF7F IO_UNKNOWN8 00:FFFF IO_IE