mirror of https://github.com/mgba-emu/mgba.git
GB: Support for combo "Super Game Boy Color" SGB + GBC ROM hacks
This commit is contained in:
parent
c633d08076
commit
e00987ddeb
1
CHANGES
1
CHANGES
|
@ -3,6 +3,7 @@ Features:
|
|||
- Presets for Game Boy palettes
|
||||
- Tool for converting scanned pictures of e-Reader cards to raw dotcode data
|
||||
- Cheat code support in homebrew ports
|
||||
- Support for combo "Super Game Boy Color" SGB + GBC ROM hacks
|
||||
Emulation fixes:
|
||||
- GB Video: Clear VRAM on reset (fixes mgba.io/i/2152)
|
||||
- GBA Video: Revert scanline latching changes (fixes mgba.io/i/2153, mgba.io/i/2149)
|
||||
|
|
|
@ -17,8 +17,9 @@ enum GBModel {
|
|||
GB_MODEL_DMG = 0x00,
|
||||
GB_MODEL_SGB = 0x20,
|
||||
GB_MODEL_MGB = 0x40,
|
||||
GB_MODEL_SGB2 = 0x60,
|
||||
GB_MODEL_SGB2 = GB_MODEL_MGB | GB_MODEL_SGB,
|
||||
GB_MODEL_CGB = 0x80,
|
||||
GB_MODEL_SCGB = GB_MODEL_CGB | GB_MODEL_SGB,
|
||||
GB_MODEL_AGB = 0xC0
|
||||
};
|
||||
|
||||
|
|
|
@ -560,6 +560,7 @@ static void _GBCoreReset(struct mCore* core) {
|
|||
break;
|
||||
case GB_MODEL_CGB:
|
||||
case GB_MODEL_AGB:
|
||||
case GB_MODEL_SCGB:
|
||||
configPath = mCoreConfigGetValue(&core->config, "gbc.bios");
|
||||
break;
|
||||
default:
|
||||
|
@ -589,6 +590,7 @@ static void _GBCoreReset(struct mCore* core) {
|
|||
break;
|
||||
case GB_MODEL_CGB:
|
||||
case GB_MODEL_AGB:
|
||||
case GB_MODEL_SCGB:
|
||||
strncat(path, PATH_SEP "gbc_bios.bin", PATH_MAX - strlen(path));
|
||||
break;
|
||||
default:
|
||||
|
|
12
src/gb/gb.c
12
src/gb/gb.c
|
@ -546,6 +546,7 @@ void GBSkipBIOS(struct GB* gb) {
|
|||
cpu->b = 1;
|
||||
// Fall through
|
||||
case GB_MODEL_CGB:
|
||||
case GB_MODEL_SCGB:
|
||||
cpu->a = 0x11;
|
||||
if (gb->model == GB_MODEL_AGB) {
|
||||
cpu->f.packed = 0x00;
|
||||
|
@ -671,6 +672,7 @@ void GBDetectModel(struct GB* gb) {
|
|||
break;
|
||||
case GB_MODEL_AGB:
|
||||
case GB_MODEL_CGB:
|
||||
case GB_MODEL_SCGB:
|
||||
gb->audio.style = GB_AUDIO_CGB;
|
||||
break;
|
||||
}
|
||||
|
@ -932,11 +934,11 @@ void GBFrameEnded(struct GB* gb) {
|
|||
}
|
||||
|
||||
enum GBModel GBNameToModel(const char* model) {
|
||||
if (strcasecmp(model, "DMG") == 0) {
|
||||
if (strcasecmp(model, "DMG") == 0 || strcasecmp(model, "GB") == 0) {
|
||||
return GB_MODEL_DMG;
|
||||
} else if (strcasecmp(model, "CGB") == 0) {
|
||||
} else if (strcasecmp(model, "CGB") == 0 || strcasecmp(model, "GBC") == 0) {
|
||||
return GB_MODEL_CGB;
|
||||
} else if (strcasecmp(model, "AGB") == 0) {
|
||||
} else if (strcasecmp(model, "AGB") == 0 || strcasecmp(model, "GBA") == 0) {
|
||||
return GB_MODEL_AGB;
|
||||
} else if (strcasecmp(model, "SGB") == 0) {
|
||||
return GB_MODEL_SGB;
|
||||
|
@ -944,6 +946,8 @@ enum GBModel GBNameToModel(const char* model) {
|
|||
return GB_MODEL_MGB;
|
||||
} else if (strcasecmp(model, "SGB2") == 0) {
|
||||
return GB_MODEL_SGB2;
|
||||
} else if (strcasecmp(model, "SCGB") == 0 || strcasecmp(model, "SGBC") == 0) {
|
||||
return GB_MODEL_SCGB;
|
||||
}
|
||||
return GB_MODEL_AUTODETECT;
|
||||
}
|
||||
|
@ -962,6 +966,8 @@ const char* GBModelToName(enum GBModel model) {
|
|||
return "CGB";
|
||||
case GB_MODEL_AGB:
|
||||
return "AGB";
|
||||
case GB_MODEL_SCGB:
|
||||
return "SCGB";
|
||||
default:
|
||||
case GB_MODEL_AUTODETECT:
|
||||
return NULL;
|
||||
|
|
|
@ -629,7 +629,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
|
|||
int p = 0;
|
||||
switch (softwareRenderer->d.sgbRenderMode) {
|
||||
case 0:
|
||||
if (softwareRenderer->model & GB_MODEL_SGB) {
|
||||
if ((softwareRenderer->model & (GB_MODEL_SGB | GB_MODEL_CGB)) == GB_MODEL_SGB) {
|
||||
p = softwareRenderer->d.sgbAttributes[(startX >> 5) + 5 * (y >> 3)];
|
||||
p >>= 6 - ((x / 4) & 0x6);
|
||||
p &= 3;
|
||||
|
@ -639,7 +639,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
|
|||
row[x] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & OBJ_PRIO_MASK]];
|
||||
}
|
||||
for (; x + 7 < (endX & ~7); x += 8) {
|
||||
if (softwareRenderer->model & GB_MODEL_SGB) {
|
||||
if ((softwareRenderer->model & (GB_MODEL_SGB | GB_MODEL_CGB)) == GB_MODEL_SGB) {
|
||||
p = softwareRenderer->d.sgbAttributes[(x >> 5) + 5 * (y >> 3)];
|
||||
p >>= 6 - ((x / 4) & 0x6);
|
||||
p &= 3;
|
||||
|
@ -654,7 +654,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
|
|||
row[x + 6] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 6] & OBJ_PRIO_MASK]];
|
||||
row[x + 7] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 7] & OBJ_PRIO_MASK]];
|
||||
}
|
||||
if (softwareRenderer->model & GB_MODEL_SGB) {
|
||||
if ((softwareRenderer->model & (GB_MODEL_SGB | GB_MODEL_CGB)) == GB_MODEL_SGB) {
|
||||
p = softwareRenderer->d.sgbAttributes[(x >> 5) + 5 * (y >> 3)];
|
||||
p >>= 6 - ((x / 4) & 0x6);
|
||||
p &= 3;
|
||||
|
|
|
@ -238,7 +238,7 @@ void GBVideoSkipBIOS(struct GBVideo* video) {
|
|||
video->modeEvent.callback = _endMode1;
|
||||
|
||||
int32_t next;
|
||||
if (video->p->model == GB_MODEL_CGB) {
|
||||
if (video->p->model & GB_MODEL_CGB) {
|
||||
video->ly = GB_VIDEO_VERTICAL_PIXELS;
|
||||
video->p->memory.io[GB_REG_LY] = video->ly;
|
||||
video->stat = GBRegisterSTATClearLYC(video->stat);
|
||||
|
@ -536,9 +536,7 @@ void GBVideoWritePalette(struct GBVideo* video, uint16_t address, uint8_t value)
|
|||
video->renderer->writePalette(video->renderer, 9 * 4 + 3, video->palette[9 * 4 + 3]);
|
||||
break;
|
||||
}
|
||||
} else if (video->p->model & GB_MODEL_SGB) {
|
||||
video->renderer->writeVideoRegister(video->renderer, address, value);
|
||||
} else {
|
||||
} else if (video->p->model >= GB_MODEL_CGB) {
|
||||
switch (address) {
|
||||
case GB_REG_BCPD:
|
||||
if (video->mode != 3) {
|
||||
|
@ -579,6 +577,8 @@ void GBVideoWritePalette(struct GBVideo* video, uint16_t address, uint8_t value)
|
|||
video->p->memory.io[GB_REG_OCPD] = video->palette[8 * 4 + (video->ocpIndex >> 1)] >> (8 * (video->ocpIndex & 1));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
video->renderer->writeVideoRegister(video->renderer, address, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ static const QList<GBModel> s_gbModelList{
|
|||
GB_MODEL_SGB,
|
||||
GB_MODEL_CGB,
|
||||
GB_MODEL_AGB,
|
||||
GB_MODEL_SCGB,
|
||||
};
|
||||
|
||||
static const QList<GBMemoryBankControllerType> s_mbcList{
|
||||
|
@ -58,6 +59,7 @@ QString GameBoy::modelName(GBModel model) {
|
|||
s_gbModelNames[GB_MODEL_SGB2] = tr("Super Game Boy 2 (SGB)");
|
||||
s_gbModelNames[GB_MODEL_CGB] = tr("Game Boy Color (CGB)");
|
||||
s_gbModelNames[GB_MODEL_AGB] = tr("Game Boy Advance (AGB)");
|
||||
s_gbModelNames[GB_MODEL_SCGB] = tr("Super Game Boy Color (SGB + CGB)");
|
||||
}
|
||||
|
||||
return s_gbModelNames[model];
|
||||
|
|
Loading…
Reference in New Issue