Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mapper #53 MAPPER_GG_Real_24_in_1_FFFE_0000_FFFF for "Real 24 in 1 [Sonic II] (Unl)" #120

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion meka/compat.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1334,6 +1334,7 @@
Quiz Gear Fight!!, The (JP) Ok
Rastan Saga [SMS-GG] (JP) Ok
R.C. Grand Prix [SMS-GG] Ok
Real 24 in 1 [Sonic II] *Ok
Revenge of Drancon Ok
Riddick Rowe Boxing (US) Ok
Riddick Rowe Boxing (JP) Ok
Expand Down Expand Up @@ -1502,7 +1503,7 @@
Zoop (US) Ok
Zoop [Proto] (US) Ok
-----------------------------------------------------------------------------
517 games tested - 506 are "Ok" - Compatibility rate: 97.63%
518 games tested - 507 are "Ok" - Compatibility rate: 97.88%
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions meka/meka.nam
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,7 @@ GG 8e54ee04 E463A36AE4D522D1 Puzzle Bobble/COUNTRY=JP/PRODUCT_NO=T-11047
GG 6c451ee1 2A50C584823D710D Quest for the Shaven Yak Starring Ren Hoëk & Stimpy/COUNTRY=US,EU/PRODUCT_NO=2519
GG 736cdb76 70BA6E9D99C81B4F Quiz Gear Fight!!, The/COUNTRY=JP/PRODUCT_NO=G-3367
GG 6dc3295e D56E2790AD1DEE4E R.B.I. Baseball '94/COUNTRY=US/PRODUCT_NO=T-48168 301073-0161
GG de6471e8 0E01DB0FE65FBA08 Real 24 in 1 [Sonic II]/EMU_MAPPER=53
GG 03e9c607 EACA76A0EF9F1D8B Revenge of Drancon/NAME_BR=Wonder Boy/COUNTRY=US,BR/PRODUCT_NO=2302,012080/COMMENT=US version of "Wonder Boy", with a different title.
GG 38d8ec56 46EF1611B14E079E Riddick Bowe Boxing/COUNTRY=US/PRODUCT_NO=T-22028
GG a45fffb7 45EF1710B24D079F Riddick Bowe Boxing/COUNTRY=JP/PRODUCT_NO=T-22027
Expand Down
20 changes: 20 additions & 0 deletions meka/srcs/machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ void Machine_Set_Handler_MemRW(void)
case MAPPER_SMS_Korean_MSX_SMS_8000:
WrZ80 = WrZ80_NoHook = Write_Mapper_SMS_Korean_MSX_SMS_8000;
break;
case MAPPER_GG_Real_24_in_1_FFFE_0000_FFFF:
WrZ80 = WrZ80_NoHook = Write_Mapper_GG_Real_24_in_1_FFFE_0000_FFFF;
break;
}
}

Expand Down Expand Up @@ -502,6 +505,23 @@ void Machine_Set_Mapping (void)
g_machine.mapper_regs[i] = 0;
break;

case MAPPER_GG_Real_24_in_1_FFFE_0000_FFFF:
Map_8k_ROM(0, 0 & tsms.Pages_Mask_8k);
Map_8k_ROM(1, 1 & tsms.Pages_Mask_8k);
Map_8k_ROM(2, 2 & tsms.Pages_Mask_8k);
Map_8k_ROM(3, 3 & tsms.Pages_Mask_8k);
Map_8k_ROM(4, 4 & tsms.Pages_Mask_8k);
Map_8k_ROM(5, 5 & tsms.Pages_Mask_8k);
Map_8k_RAM(6, 0);
Map_8k_RAM(7, 0);
g_machine.mapper_regs_count = 3;
for (int i = 0; i != MAPPER_REGS_MAX; i++)
g_machine.mapper_regs[i] = 0;
g_machine.mapper_regs[1] = 2;
g_machine.mapper_regs[2] = 1;
drv_set(DRV_GG);
break;

case MAPPER_SC3000_Survivors_Multicart:
g_machine.mapper_regs_count = 1;
for (int i = 0; i != MAPPER_REGS_MAX; i++)
Expand Down
80 changes: 80 additions & 0 deletions meka/srcs/mappers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
#include "shared.h"
#include "mappers.h"
#include "eeprom.h"
#include "vdp.h"
#include "video.h"
#include "app_game.h"

//-----------------------------------------------------------------------------
// Data
Expand Down Expand Up @@ -989,6 +992,83 @@ WRITE_FUNC (Write_Mapper_SMS_Korean_MSX_SMS_8000)
Write_Error (Addr, Value);
}

// Mapper #53
// Real 24 in 1 [Sonic II] (Unl)
WRITE_FUNC (Write_Mapper_GG_Real_24_in_1_FFFE_0000_FFFF) {
if ((Addr == 0x0000) || (Addr == 0xFFFE) || (Addr == 0xFFFF)) { // Configurable segment -----------------------------------------------
// mapper register allocation:
// 0: 0x0000: outer paging configuration and SMS-GG mode
// - bit 0x80: set when mapping the second megabyte, clear otherwise
// - bit 0x40: set when activating SMS-GG mode, clear otherwise
// - bits 0x3F: 32KB base page for outer page selection
//
// For paging to work, the base page must be in an eligible region and
// all paging-modifiable bits of the 32KB base page must be set
//
// 16KB paging mask bits:
// - 0x10: when base page bit 0x08 is set and base page > 0x30
// - 0x08: when base page bit 0x04 is set and base page > 0x20
// - 0x04: when base page bit 0x02 is set and base page > 0x14
// - 0x02: when base page bit 0x01 is set and base page > 0x12
// - 0x01: always available
//
// 1: 0xFFFF: 16KB paging offset for region 0x8000..0xBFFF (restricted by 16KB paging mask)
// 2: 0xFFFE: 16KB paging offset for region 0x4000..0x7FFF (restricted by 16KB paging mask)

if (Addr == 0x0000) {
g_machine.mapper_regs[0] |= Value;
bool sms_gg_mode = (g_machine.mapper_regs[0] & 0x40) ? true : false;
if (sms_gg_mode) {
drv_set(DRV_SMS);
} else {
drv_set(DRV_GG);
}
gamebox_resize_all();
VDP_UpdateLineLimits();
Video_GameMode_UpdateBounds();
} else if (Addr == 0xFFFF) {
g_machine.mapper_regs[1] = Value;
} else if (Addr == 0xFFFE) {
if (Value & 0x80) {
// 0xB0 is written at startup, no idea what it means
} else {
g_machine.mapper_regs[2] = Value;
}
}

unsigned int base_page_32k = (g_machine.mapper_regs[0] & 0x3F) | ((g_machine.mapper_regs[0] & 0x80) >> 2);
unsigned int paging_mask_16k = 0x01 | (2 * (
((base_page_32k > 0x12) ? (base_page_32k & 0x01) : 0x00)
| ((base_page_32k > 0x14) ? (base_page_32k & 0x02) : 0x00)
| ((base_page_32k > 0x20) ? (base_page_32k & 0x04) : 0x00)
| ((base_page_32k > 0x30) ? (base_page_32k & 0x08) : 0x00)));
unsigned int base_page_16k = (2 * base_page_32k) & ~paging_mask_16k;
unsigned int page_8000_offset_16k = g_machine.mapper_regs[1] & paging_mask_16k;
unsigned int page_4000_offset_16k = g_machine.mapper_regs[2] & paging_mask_16k;

Map_8k_ROM(0, ((base_page_16k * 2) | 0) & tsms.Pages_Mask_8k);
Map_8k_ROM(1, ((base_page_16k * 2) | 1) & tsms.Pages_Mask_8k);
Map_8k_ROM(2, (((base_page_16k | page_4000_offset_16k) * 2) | 0) & tsms.Pages_Mask_8k);
Map_8k_ROM(3, (((base_page_16k | page_4000_offset_16k) * 2) | 1) & tsms.Pages_Mask_8k);
Map_8k_ROM(4, (((base_page_16k | page_8000_offset_16k) * 2) | 0) & tsms.Pages_Mask_8k);
Map_8k_ROM(5, (((base_page_16k | page_8000_offset_16k) * 2) | 1) & tsms.Pages_Mask_8k);

if (Addr == 0x0000) {
// no RAM mirroring for register 0x0000
return;
}
}

switch (Addr >> 13)
{
// RAM [0xC000] = [0xE000] ------------------------------------------------
case 6: Mem_Pages[6][Addr] = Value; return;
case 7: Mem_Pages[7][Addr] = Value; return;
}

Write_Error (Addr, Value);
}

// Based on MSX ASCII 8KB mapper? http://bifi.msxnet.org/msxnet/tech/megaroms.html#ascii8
// - This mapper requires 4 registers to save bank switching state.
// However, all other mappers so far used only 3 registers, stored as 3 bytes.
Expand Down
2 changes: 2 additions & 0 deletions meka/srcs/mappers.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#define MAPPER_SMS_Korean_MD_FFFA (26) // Registers at 0xFFFA and 0xFFFF (Game Jiphap 30 Hap [SMS-MD])
#define MAPPER_SMS_Korean_MSX_32KB_2000 (27) // Register at 0x2000 (2 Hap in 1 (Moai-ui bomul, David-2))
#define MAPPER_SMS_Korean_MSX_SMS_8000 (40) // Register at 0x8000 with 8KB granularity and both MSX and SMS game support (Zemina Best 88 [MISSING 64K])
#define MAPPER_GG_Real_24_in_1_FFFE_0000_FFFF (53) // Registers at 0xFFFE, 0x0000, 0xFFFF (Real 24 in 1 [Sonic II])

#define READ_FUNC(_NAME) u8 _NAME(register u16 Addr)
#define WRITE_FUNC(_NAME) void _NAME(register u16 Addr, register u8 Value)
Expand Down Expand Up @@ -98,6 +99,7 @@ WRITE_FUNC (Write_Mapper_SMS_Korean_MD_FFF5);
WRITE_FUNC (Write_Mapper_SMS_Korean_MD_FFFA);
WRITE_FUNC (Write_Mapper_SMS_Korean_MSX_32KB_2000);
WRITE_FUNC (Write_Mapper_SMS_Korean_MSX_SMS_8000);
WRITE_FUNC (Write_Mapper_GG_Real_24_in_1_FFFE_0000_FFFF);
//-----------------------------------------------------------------------------
void Out_SC3000_SurvivorsMulticarts_DataWrite(u8 v);

Expand Down
19 changes: 16 additions & 3 deletions meka/srcs/saves.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "vmachine.h"
#include "sound/fmunit.h"
#include "sound/psg.h"
#include "video.h"
#include "app_game.h"

//-----------------------------------------------------------------------------
// Functions
Expand All @@ -26,6 +28,7 @@ void Load_Game_Fixup(void)
{
int i;
u8 b;
bool sms_gg_mode_in_mapper = false;

// CPU
#ifdef MARAT_Z80
Expand Down Expand Up @@ -151,13 +154,21 @@ void Load_Game_Fixup(void)
WrZ80_NoHook(0x8000, mapper_page);
}
break;
case MAPPER_GG_Real_24_in_1_FFFE_0000_FFFF:
// this will restore every other piece of mapper state by side-effect;
// this will also configure SMS-GG mode if needed
WrZ80_NoHook(0x0000, g_machine.mapper_regs[0]);
sms_gg_mode_in_mapper = true;
break;
}
}

// VDP/Graphic related
tsms.VDP_Video_Change |= VDP_VIDEO_CHANGE_ALL;
VDP_UpdateLineLimits();
// FALSE!!! // tsms.VDP_Line = 224;
if (!sms_gg_mode_in_mapper) {
tsms.VDP_Video_Change |= VDP_VIDEO_CHANGE_ALL;
VDP_UpdateLineLimits();
// FALSE!!! // tsms.VDP_Line = 224;
}

// Rewrite all VDP registers (we can do that since it has zero side-effect)
for (i = 0; i < 16; i ++)
Expand Down Expand Up @@ -347,6 +358,7 @@ int Save_Game_MSV(FILE *f)
case MAPPER_SMS_Korean_MD_FFFA:
case MAPPER_SMS_Korean_MSX_32KB_2000:
case MAPPER_SMS_Korean_MSX_SMS_8000:
case MAPPER_GG_Real_24_in_1_FFFE_0000_FFFF:
default:
fwrite (RAM, 0x2000, 1, f); // Do not use g_driver->ram because of g_driver video mode change
break;
Expand Down Expand Up @@ -527,6 +539,7 @@ int Load_Game_MSV(FILE *f)
case MAPPER_SMS_Korean_MD_FFFA:
case MAPPER_SMS_Korean_MSX_32KB_2000:
case MAPPER_SMS_Korean_MSX_SMS_8000:
case MAPPER_GG_Real_24_in_1_FFFE_0000_FFFF:
default:
fread (RAM, 0x2000, 1, f); // Do not use g_driver->ram because of g_driver video mode change
break;
Expand Down