Skip to content
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 @@ -1140,6 +1140,7 @@
Gear Stadium Heiseiban (JP) Ok
Gear Works Ok
George Foreman's KO Boxing Ok
GG 48 in 1 [Doraemon 2] *Ok
GG Aleste (JP) Ok
GG Portrait - Pai Chen (JP) Ok
GG Portrait - Yuuki Akira (JP) Ok
Expand Down Expand Up @@ -1498,7 +1499,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 @@ -1035,6 +1035,7 @@ GG 0e300223 27BA4F0E3A5DBF6C Gear Stadium/COUNTRY=JP/PRODUCT_NO=T-14037/COMME
GG a0530664 08ADE585B8DA024D Gear Stadium Heiseiban/COUNTRY=JP/PRODUCT_NO=T-14077
GG e9a2efb4 F9F734AF23CDB28B Gear Works/COUNTRY=US/PRODUCT_NO=T-93058
GG 58b44585 C92745E46E995090 George Foreman's KO Boxing/COUNTRY=US,EU/PRODUCT_NO=T-81038,T-81038-50
GG 3394aaea F07FEFF54F0A7CD8 GG 48 in 1 [Doraemon 2]/EMU_MAPPER=48
GG 1b80a75b 682713F64A0AAD67 GG Aleste/COUNTRY=JP/PRODUCT_NO=T-66017
GG 695cc120 FCC991E880B52D60 GG Portrait - Pai Chen/COUNTRY=JP/PRODUCT_NO=G-3387
GG 51159f8f 5D96967FEE1C49A5 GG Portrait - Yuuki Akira/COUNTRY=JP/PRODUCT_NO=G-3386
Expand Down
19 changes: 19 additions & 0 deletions meka/srcs/machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ void Machine_Set_Handler_MemRW(void)
case MAPPER_SMS_Korean_MSX_32KB_2000:
WrZ80 = WrZ80_NoHook = Write_Mapper_SMS_Korean_MSX_32KB_2000;
break;
case MAPPER_GG_48_in_1_FFF8_FFF9_FFFE_FFFF:
WrZ80 = WrZ80_NoHook = Write_Mapper_GG_48_in_1_FFF8_FFF9_FFFE_FFFF;
break;
}
}

Expand Down Expand Up @@ -485,6 +488,22 @@ void Machine_Set_Mapping (void)
g_machine.mapper_regs[0] = 0;
break;

case MAPPER_GG_48_in_1_FFF8_FFF9_FFFE_FFFF:
g_machine.mapper_regs_count = 4;
for (int i = 0; i != MAPPER_REGS_MAX; i++)
g_machine.mapper_regs[i] = 0;
g_machine.mapper_regs[0] = 0x1F;
g_machine.mapper_regs[3] = 1;
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, 0 & tsms.Pages_Mask_8k);
Map_8k_ROM(5, 1 & tsms.Pages_Mask_8k);
Map_8k_RAM(6, 0);
Map_8k_RAM(7, 0);
break;

case MAPPER_SC3000_Survivors_Multicart:
g_machine.mapper_regs_count = 1;
for (int i = 0; i != MAPPER_REGS_MAX; i++)
Expand Down
78 changes: 78 additions & 0 deletions meka/srcs/mappers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,84 @@ WRITE_FUNC (Write_Mapper_SMS_Korean_MSX_32KB_2000)
Write_Error (Addr, Value);
}

// Mapper #48
// GG 48 in 1 [Doraemon 2]
WRITE_FUNC (Write_Mapper_GG_48_in_1_FFF8_FFF9_FFFE_FFFF)
{
// Mapper register allocations:
// - Mode and mask: g_machine.mapper_regs[0]
// Bits 0xE0: configuration mode
// - 0x00: not in configuration mode
// - 0x80: expecting paging mask [step 1]
// - 0x40: expecting lower 5 bits of base page [step 2]
// - 0x20: expecting upper 3 bits of base page [step 3]
// - 0xE0: not expecting further configuration bytes
// Bits 0x1F: 16KB paging mask
// - Base page: g_machine.mapper_regs[1]
// Bits 0xFF: 16KB base page
// - Upper Sega paging register: g_machine.mapper_regs[2]
// Bits 0x1F: 16KB page offset for region 0x8000..0xBFFF
// - Lower Sega paging register: g_machine.mapper_regs[3]
// Bits 0x1F: 16KB page offset for region 0x4000..0x7FFF
if ((Addr == 0xFFF8) || (Addr == 0xFFF9) || (Addr == 0xFFFE) || (Addr == 0xFFFF)) // Configurable segment -----------------------------------------------
{
if (Addr == 0xFFF8) {
// lock mapper
g_machine.mapper_regs[0] &= 0x1F;
if (Value & 0x10) {
// unlock mapper, expect paging mask next
g_machine.mapper_regs[0] |= 0x80;
}
} else if (Addr == 0xFFF9) {
if ((g_machine.mapper_regs[0] & 0xE0) == 0x80) {
// expecting paging mask
g_machine.mapper_regs[0] &= 0xE0;
g_machine.mapper_regs[0] |= Value & 0x1F;
// expect lower 5 bits of base page next
g_machine.mapper_regs[0] &= 0x1F;
g_machine.mapper_regs[0] |= 0x40;
} else if ((g_machine.mapper_regs[0] & 0xE0) == 0x40) {
// expecting lower 5 bits of base page
g_machine.mapper_regs[1] &= 0xE0;
g_machine.mapper_regs[1] |= Value & 0x1F;
// expect upper 3 bits of base page next
g_machine.mapper_regs[0] &= 0x1F;
g_machine.mapper_regs[0] |= 0x20;
} else if (((g_machine.mapper_regs[0] & 0xE0) == 0x20) && ((Value & 0x18) == 0x18)) {
// expecting upper 3 bits of base page
g_machine.mapper_regs[1] &= 0x1F;
g_machine.mapper_regs[1] |= (Value & 0x07) << 5;
// subsequent writes to 0xFFF9 ignored
g_machine.mapper_regs[0] &= 0x1F;
g_machine.mapper_regs[0] |= 0xE0;
}
} else if (Addr == 0xFFFF) {
g_machine.mapper_regs[2] = Value;
} else if (Addr == 0xFFFE) {
g_machine.mapper_regs[3] = Value;
}
unsigned int paging_mask = g_machine.mapper_regs[0] & 0x1F;
unsigned int base_page_16k = g_machine.mapper_regs[1];
unsigned int upper_page_16k = base_page_16k + (g_machine.mapper_regs[2] & paging_mask);
unsigned int lower_page_16k = base_page_16k + (g_machine.mapper_regs[3] & paging_mask);
Map_8k_ROM(0, (base_page_16k * 2) & tsms.Pages_Mask_8k);
Map_8k_ROM(1, ((base_page_16k * 2) | 1) & tsms.Pages_Mask_8k);
Map_8k_ROM(2, (lower_page_16k * 2) & tsms.Pages_Mask_8k);
Map_8k_ROM(3, ((lower_page_16k * 2) | 1) & tsms.Pages_Mask_8k);
Map_8k_ROM(4, (upper_page_16k * 2) & tsms.Pages_Mask_8k);
Map_8k_ROM(5, ((upper_page_16k * 2) | 1) & tsms.Pages_Mask_8k);
}

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 @@ -50,6 +50,7 @@
#define MAPPER_SMS_Korean_MD_FFF5 (25) // Registers at 0xFFF5 and 0xFFFF (Jaemiissneun Game Mo-eumjip 42/65 Hap [SMS-MD], Pigu Wang Hap ~ Jaemiiss-neun Game Mo-eumjip [SMS-MD])
#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_GG_48_in_1_FFF8_FFF9_FFFE_FFFF (48) // Registers at 0xFFF8, 0xFFF9, 0xFFFE, 0xFFFF (GG 48 in 1 [Doraemon 2])

#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 @@ -96,6 +97,7 @@ WRITE_FUNC (Write_Mapper_SMS_Korean_MD_FFF0);
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_GG_48_in_1_FFF8_FFF9_FFFE_FFFF);
//-----------------------------------------------------------------------------
void Out_SC3000_SurvivorsMulticarts_DataWrite(u8 v);

Expand Down
8 changes: 8 additions & 0 deletions meka/srcs/saves.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ void Load_Game_Fixup(void)
case MAPPER_SMS_Korean_MSX_32KB_2000:
WrZ80_NoHook(0x2000, g_machine.mapper_regs[0]);
break;
case MAPPER_GG_48_in_1_FFF8_FFF9_FFFE_FFFF:
// Re-writing these registers will have the side-effect of
// re-applying all the rest of the memory mapper state too
WrZ80_NoHook(0xFFFF, g_machine.mapper_regs[2]);
WrZ80_NoHook(0xFFFE, g_machine.mapper_regs[3]);
break;
}
}

Expand Down Expand Up @@ -339,6 +345,7 @@ int Save_Game_MSV(FILE *f)
case MAPPER_SMS_Korean_MD_FFF5:
case MAPPER_SMS_Korean_MD_FFFA:
case MAPPER_SMS_Korean_MSX_32KB_2000:
case MAPPER_GG_48_in_1_FFF8_FFF9_FFFE_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 @@ -518,6 +525,7 @@ int Load_Game_MSV(FILE *f)
case MAPPER_SMS_Korean_MD_FFF5:
case MAPPER_SMS_Korean_MD_FFFA:
case MAPPER_SMS_Korean_MSX_32KB_2000:
case MAPPER_GG_48_in_1_FFF8_FFF9_FFFE_FFFF:
default:
fread (RAM, 0x2000, 1, f); // Do not use g_driver->ram because of g_driver video mode change
break;
Expand Down