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
6 changes: 5 additions & 1 deletion meka/compat.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,10 @@
Super Battletank Ok
Super Columns Ok
Super Columns (JP) Ok
Super Game Gear 73 in 1 [Sonic 2] *Ok
Super Game Gear 73 in 1 [Street Fighter 2] *Ok
Super GG 21 in 1 [Sonic Drift] [Gold & Yellow Label] *Ok
Super GG 30 in 1 [Sonic 2] [Gold & Yellow Label] *Ok
Super Golf (JP) Ok
Super Kick Off [SMS-GG] Ok
Superman - The Man of Steel Ok
Expand Down Expand Up @@ -1498,7 +1502,7 @@
Zoop (US) Ok
Zoop [Proto] (US) Ok
-----------------------------------------------------------------------------
517 games tested - 506 are "Ok" - Compatibility rate: 97.63%
521 games tested - 510 are "Ok" - Compatibility rate: 97.89%
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions meka/meka.nam
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,10 @@ GG b421c057 96BD12C62621B8D6 Striker/COUNTRY=EU/PRODUCT_NO=2551-50
GG 73d6745a 18CC99C9849C9901 Super Battletank/COUNTRY=US/PRODUCT_NO=1239
GG 8ba43af3 DAA4C785B7042952 Super Columns/COUNTRY=US,EU/PRODUCT_NO=2449,2449-50
GG 2a100717 E7260408CEC8EE63 Super Columns/COUNTRY=JP/PRODUCT_NO=G-3226
GG 5585010f ADC7A676E4A80ADA Super Game Gear 73 in 1 [Sonic 2]/EMU_MAPPER=33
GG ec7240f1 ADC7A676E4A80ADA Super Game Gear 73 in 1 [Street Fighter 2]/EMU_MAPPER=34
GG b0a898d4 61346F715403E054 Super GG 21 in 1 [Sonic Drift] [Gold & Yellow Label]/EMU_MAPPER=33
GG a60037d5 58B43BDEE1635740 Super GG 30 in 1 [Sonic 2] [Gold & Yellow Label]/EMU_MAPPER=33
GG 528cbbce FAE75543A7740E5E Super Golf/COUNTRY=JP/PRODUCT_NO=T-26017,T-26027
GG 73df5a15 43574420E8CF212A Superman - The Man of Steel/COUNTRY=EU/PRODUCT_NO=T-70068,70068-00
GG aa3f2172 0A5C6040EBCF152B Superman - The Man of Steel [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.
Expand Down
45 changes: 45 additions & 0 deletions meka/srcs/machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "tvtype.h"
#include "sound/fmunit.h"
#include "sound/psg.h"
#include "app_game.h"

//-----------------------------------------------------------------------------
// Data
Expand Down Expand Up @@ -196,6 +197,12 @@ 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_Super_73_in_1_FFFE_FFFF:
WrZ80 = WrZ80_NoHook = Write_Mapper_GG_Super_73_in_1_FFFE_FFFF;
break;
case MAPPER_GG_Super_73_in_1_8000_4000:
WrZ80 = WrZ80_NoHook = Write_Mapper_GG_Super_73_in_1_8000_4000;
break;
}
}

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

case MAPPER_GG_Super_73_in_1_FFFE_FFFF:
Map_8k_ROM(0, 0x00 & tsms.Pages_Mask_8k);
Map_8k_ROM(1, 0x01 & tsms.Pages_Mask_8k);
Map_8k_ROM(2, 0x02 & tsms.Pages_Mask_8k);
Map_8k_ROM(3, 0x03 & tsms.Pages_Mask_8k);
Map_8k_ROM(4, 0x00 & tsms.Pages_Mask_8k);
Map_8k_ROM(5, 0x01 & 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[2] = 1;
drv_set(DRV_GG);
gamebox_resize_all();
VDP_UpdateLineLimits();
Video_GameMode_UpdateBounds();
break;

case MAPPER_GG_Super_73_in_1_8000_4000:
Map_8k_ROM(0, 0x00 & tsms.Pages_Mask_8k);
Map_8k_ROM(1, 0x01 & tsms.Pages_Mask_8k);
Map_8k_ROM(2, 0x02 & tsms.Pages_Mask_8k);
Map_8k_ROM(3, 0x03 & tsms.Pages_Mask_8k);
Map_8k_ROM(4, 0x00 & tsms.Pages_Mask_8k);
Map_8k_ROM(5, 0x01 & 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] = 1;
drv_set(DRV_GG);
gamebox_resize_all();
VDP_UpdateLineLimits();
Video_GameMode_UpdateBounds();
break;

case MAPPER_SC3000_Survivors_Multicart:
g_machine.mapper_regs_count = 1;
for (int i = 0; i != MAPPER_REGS_MAX; i++)
Expand Down
139 changes: 139 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 @@ -952,6 +955,142 @@ WRITE_FUNC (Write_Mapper_SMS_Korean_MSX_32KB_2000)
Write_Error (Addr, Value);
}

// Mapper #33
// Super Game Gear 73 in 1 [Sonic 2]
WRITE_FUNC(Write_Mapper_GG_Super_73_in_1_FFFE_FFFF)
{
if ((Addr == 0xFFFE) || (Addr == 0xFFFF)) // Configurable segment -----------------------------------------------
{
if (Addr == 0xFFFE) {
g_machine.mapper_regs[2] = Value;
} else if (Addr == 0xFFFF) {
g_machine.mapper_regs[1] = Value;
}
if (! (g_machine.mapper_regs[0] & 0x40)) {
// "menu" mapping mode
if (g_machine.mapper_regs[2] & 0x40) {
// high-part mapper write
g_machine.mapper_regs[0] = (g_machine.mapper_regs[2] & 0x08) ? 0x80 : 0x00; // SMS-GG mode flag
// upper two bits of MAPBASE
g_machine.mapper_regs[0] &= ~0x30;
g_machine.mapper_regs[0] |= (g_machine.mapper_regs[2] & 0x06) << 3;
} else {
// low-part mapper write (lower four bits of MAPBASE)
g_machine.mapper_regs[0] &= ~0x0F;
g_machine.mapper_regs[0] |= (g_machine.mapper_regs[2] & 0x1E) >> 1;
}
if (g_machine.mapper_regs[1] & 0x40) {
// switch to "game" mapping mode
g_machine.mapper_regs[0] |= 0x40;
g_machine.mapper_regs[1] = 0;
g_machine.mapper_regs[2] = 1;
}
}
unsigned int mapbase_16k = 0;
unsigned int page_4000_offset_16k = 1;
unsigned int page_8000_offset_16k = 0;
bool game_mapping_mode = g_machine.mapper_regs[0] & 0x40;
if (game_mapping_mode) {
mapbase_16k = (g_machine.mapper_regs[0] & 0x3F) * 2;
page_4000_offset_16k = g_machine.mapper_regs[2];
page_8000_offset_16k = g_machine.mapper_regs[1];
}
Map_8k_ROM(0, (mapbase_16k * 2) & tsms.Pages_Mask_8k);
Map_8k_ROM(1, (mapbase_16k * 2 + 1) & tsms.Pages_Mask_8k);
Map_8k_ROM(2, ((mapbase_16k + page_4000_offset_16k) * 2) & tsms.Pages_Mask_8k);
Map_8k_ROM(3, ((mapbase_16k + page_4000_offset_16k) * 2 + 1) & tsms.Pages_Mask_8k);
Map_8k_ROM(4, ((mapbase_16k + page_8000_offset_16k) * 2) & tsms.Pages_Mask_8k);
Map_8k_ROM(5, ((mapbase_16k + page_8000_offset_16k) * 2 + 1) & tsms.Pages_Mask_8k);
bool sms_gg_mode_active = g_machine.mapper_regs[0] & 0x80;
if (sms_gg_mode_active) {
drv_set(DRV_SMS);
} else {
drv_set(DRV_GG);
}
gamebox_resize_all();
VDP_UpdateLineLimits();
Video_GameMode_UpdateBounds();
//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);
}

// Mapper #34
// Super Game Gear 73 in 1 [Street Fighter 2]
WRITE_FUNC(Write_Mapper_GG_Super_73_in_1_8000_4000)
{
if ((Addr == 0x8000) || (Addr == 0x4000)) // Configurable segment -----------------------------------------------
{
if (Addr == 0x8000) {
g_machine.mapper_regs[2] = Value;
} else if (Addr == 0x4000) {
g_machine.mapper_regs[1] = Value;
}
if (! (g_machine.mapper_regs[0] & 0x40)) {
// "menu" mapping mode
if (g_machine.mapper_regs[2] & 0x40) {
// high-part mapper write
g_machine.mapper_regs[0] = (g_machine.mapper_regs[2] & 0x08) ? 0x80 : 0x00; // SMS-GG mode flag
// upper two bits of MAPBASE
g_machine.mapper_regs[0] &= ~0x30;
g_machine.mapper_regs[0] |= (g_machine.mapper_regs[2] & 0x06) << 3;
} else {
// low-part mapper write (lower four bits of MAPBASE)
g_machine.mapper_regs[0] &= ~0x0F;
g_machine.mapper_regs[0] |= (g_machine.mapper_regs[2] & 0x1E) >> 1;
}
if (g_machine.mapper_regs[1] & 0x40) {
// switch to "game" mapping mode
g_machine.mapper_regs[0] |= 0x40;
g_machine.mapper_regs[2] = 0;
g_machine.mapper_regs[1] = 1;
}
}
unsigned int mapbase_16k = 0;
unsigned int page_4000_offset_16k = 1;
unsigned int page_8000_offset_16k = 0;
bool game_mapping_mode = g_machine.mapper_regs[0] & 0x40;
if (game_mapping_mode) {
mapbase_16k = (g_machine.mapper_regs[0] & 0x3F) * 2;
page_4000_offset_16k = g_machine.mapper_regs[1];
page_8000_offset_16k = g_machine.mapper_regs[2];
}
Map_8k_ROM(0, (mapbase_16k * 2) & tsms.Pages_Mask_8k);
Map_8k_ROM(1, (mapbase_16k * 2 + 1) & tsms.Pages_Mask_8k);
Map_8k_ROM(2, ((mapbase_16k + page_4000_offset_16k) * 2) & tsms.Pages_Mask_8k);
Map_8k_ROM(3, ((mapbase_16k + page_4000_offset_16k) * 2 + 1) & tsms.Pages_Mask_8k);
Map_8k_ROM(4, ((mapbase_16k + page_8000_offset_16k) * 2) & tsms.Pages_Mask_8k);
Map_8k_ROM(5, ((mapbase_16k + page_8000_offset_16k) * 2 + 1) & tsms.Pages_Mask_8k);
bool sms_gg_mode_active = g_machine.mapper_regs[0] & 0x80;
if (sms_gg_mode_active) {
drv_set(DRV_SMS);
} else {
drv_set(DRV_GG);
}
gamebox_resize_all();
VDP_UpdateLineLimits();
Video_GameMode_UpdateBounds();
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
4 changes: 4 additions & 0 deletions meka/srcs/mappers.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
#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_Super_73_in_1_FFFE_FFFF (33) // Registers at 0xFFFE and 0xFFFF (Super Game Gear 73 in 1 [Sonic 2])
#define MAPPER_GG_Super_73_in_1_8000_4000 (34) // Registers at 0x8000 and 0x4000 (Super Game Gear 73 in 1 [Street Fighter 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 +98,8 @@ 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_Super_73_in_1_FFFE_FFFF);
WRITE_FUNC (Write_Mapper_GG_Super_73_in_1_8000_4000);
//-----------------------------------------------------------------------------
void Out_SC3000_SurvivorsMulticarts_DataWrite(u8 v);

Expand Down
23 changes: 20 additions & 3 deletions meka/srcs/saves.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,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 @@ -144,13 +145,25 @@ void Load_Game_Fixup(void)
case MAPPER_SMS_Korean_MSX_32KB_2000:
WrZ80_NoHook(0x2000, g_machine.mapper_regs[0]);
break;
case MAPPER_GG_Super_73_in_1_FFFE_FFFF:
WrZ80_NoHook(0xFFFF, g_machine.mapper_regs[1]);
WrZ80_NoHook(0xFFFE, g_machine.mapper_regs[2]);
sms_gg_mode_in_mapper = true;
break;
case MAPPER_GG_Super_73_in_1_8000_4000:
WrZ80_NoHook(0x4000, g_machine.mapper_regs[1]);
WrZ80_NoHook(0x8000, g_machine.mapper_regs[2]);
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 @@ -339,6 +352,8 @@ 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_Super_73_in_1_FFFE_FFFF:
case MAPPER_GG_Super_73_in_1_8000_4000:
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 +533,8 @@ 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_Super_73_in_1_FFFE_FFFF:
case MAPPER_GG_Super_73_in_1_8000_4000:
default:
fread (RAM, 0x2000, 1, f); // Do not use g_driver->ram because of g_driver video mode change
break;
Expand Down