mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' (early part) into medusa
This commit is contained in:
commit
243b1b1c26
8
CHANGES
8
CHANGES
|
@ -36,9 +36,10 @@ Misc:
|
|||
0.9.0: (Future)
|
||||
Features:
|
||||
- e-Reader card scanning
|
||||
- Add WebP and APNG recording
|
||||
- Add mute option in homebrew ports
|
||||
- Add status indicators for fast-forward and mute in homebrew ports
|
||||
- WebP and APNG recording
|
||||
- Separate overrides for GBC games that can also run on SGB or regular GB
|
||||
- Mute option in homebrew ports
|
||||
- Status indicators for fast-forward and mute in homebrew ports
|
||||
- Support for unlicensed Pokemon Jade/Diamond Game Boy mapper
|
||||
- Support for unlicensed BBD Game Boy mapper
|
||||
- Support for unlicensed Hitek Game Boy mapper
|
||||
|
@ -68,6 +69,7 @@ Emulation fixes:
|
|||
- GBA Hardware: Fix GB Player detection on big endian platforms
|
||||
- GBA Memory: Improve gamepak prefetch timing
|
||||
- GBA Memory: Stall on VRAM access in mode 2 (fixes mgba.io/i/190)
|
||||
- GBA Memory: Improve robustness of Matrix memory support
|
||||
- GBA SIO: Fix copying Normal mode transfer values
|
||||
- GBA SIO: Fix Normal mode being totally broken (fixes mgba.io/i/1800)
|
||||
- GBA SIO: Fix deseralizing SIO registers
|
||||
|
|
|
@ -91,6 +91,7 @@ struct mCoreCallbacks {
|
|||
void (*coreCrashed)(void* context);
|
||||
void (*sleep)(void* context);
|
||||
void (*keysRead)(void* context);
|
||||
void (*savedataUpdated)(void* context);
|
||||
};
|
||||
|
||||
DECLARE_VECTOR(mCoreCallbacksList, struct mCoreCallbacks);
|
||||
|
|
|
@ -59,6 +59,8 @@ bool GBIsBIOS(struct VFile* vf);
|
|||
enum GBModel GBNameToModel(const char*);
|
||||
const char* GBModelToName(enum GBModel);
|
||||
|
||||
int GBValidModels(const uint8_t* bank0);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,19 +10,26 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
#define GBA_MATRIX_MAPPINGS_MAX 16
|
||||
|
||||
struct GBAMatrix {
|
||||
uint32_t cmd;
|
||||
uint32_t paddr;
|
||||
uint32_t vaddr;
|
||||
uint32_t size;
|
||||
|
||||
uint32_t mappings[GBA_MATRIX_MAPPINGS_MAX];
|
||||
};
|
||||
|
||||
struct GBA;
|
||||
struct GBAMemory;
|
||||
void GBAMatrixReset(struct GBA*);
|
||||
void GBAMatrixWrite(struct GBA*, uint32_t address, uint32_t value);
|
||||
void GBAMatrixWrite16(struct GBA*, uint32_t address, uint16_t value);
|
||||
|
||||
struct GBASerializedState;
|
||||
void GBAMatrixSerialize(const struct GBA* memory, struct GBASerializedState* state);
|
||||
void GBAMatrixDeserialize(struct GBA* memory, const struct GBASerializedState* state);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -331,7 +331,12 @@ struct GBASerializedState {
|
|||
uint32_t dmaTransferRegister;
|
||||
uint32_t dmaBlockPC;
|
||||
|
||||
uint32_t reservedHardware[4];
|
||||
struct {
|
||||
uint32_t cmd;
|
||||
uint32_t paddr;
|
||||
uint32_t vaddr;
|
||||
uint32_t size;
|
||||
} matrix;
|
||||
|
||||
struct {
|
||||
uint8_t type;
|
||||
|
@ -356,7 +361,9 @@ struct GBASerializedState {
|
|||
uint32_t nextIrq;
|
||||
int32_t biosStall;
|
||||
|
||||
uint32_t reserved[54];
|
||||
uint32_t matrixMappings[16];
|
||||
|
||||
uint32_t reserved[38];
|
||||
|
||||
uint16_t io[SIZE_IO >> 1];
|
||||
uint16_t pram[SIZE_PALETTE_RAM >> 1];
|
||||
|
|
|
@ -230,6 +230,8 @@ static void _GBCoreLoadConfig(struct mCore* core, const struct mCoreConfig* conf
|
|||
mCoreConfigCopyValue(&core->config, config, "gb.model");
|
||||
mCoreConfigCopyValue(&core->config, config, "sgb.model");
|
||||
mCoreConfigCopyValue(&core->config, config, "cgb.model");
|
||||
mCoreConfigCopyValue(&core->config, config, "cgb.hybridModel");
|
||||
mCoreConfigCopyValue(&core->config, config, "cgb.sgbModel");
|
||||
mCoreConfigCopyValue(&core->config, config, "useCgbColors");
|
||||
mCoreConfigCopyValue(&core->config, config, "allowOpposingDirections");
|
||||
|
||||
|
@ -449,20 +451,43 @@ static void _GBCoreReset(struct mCore* core) {
|
|||
if (GBOverrideFind(gbcore->overrides, &override) || (doColorOverride && GBOverrideColorFind(&override))) {
|
||||
GBOverrideApply(gb, &override);
|
||||
}
|
||||
}
|
||||
|
||||
const char* modelGB = mCoreConfigGetValue(&core->config, "gb.model");
|
||||
const char* modelCGB = mCoreConfigGetValue(&core->config, "cgb.model");
|
||||
const char* modelSGB = mCoreConfigGetValue(&core->config, "sgb.model");
|
||||
if (modelGB || modelCGB || modelSGB) {
|
||||
GBDetectModel(gb);
|
||||
if (gb->model == GB_MODEL_DMG && modelGB) {
|
||||
gb->model = GBNameToModel(modelGB);
|
||||
} else if ((gb->model & GB_MODEL_CGB) && modelCGB) {
|
||||
gb->model = GBNameToModel(modelCGB);
|
||||
} else if ((gb->model & GB_MODEL_SGB) && modelSGB) {
|
||||
const char* modelCGB = mCoreConfigGetValue(&core->config, "cgb.model");
|
||||
const char* modelCGBHybrid = mCoreConfigGetValue(&core->config, "cgb.hybridModel");
|
||||
const char* modelCGBSGB = mCoreConfigGetValue(&core->config, "cgb.sgbModel");
|
||||
if (modelGB || modelCGB || modelSGB || modelCGBHybrid || modelCGBSGB) {
|
||||
int models = GBValidModels(gb->memory.rom);
|
||||
switch (models) {
|
||||
case GB_MODEL_SGB | GB_MODEL_MGB:
|
||||
if (modelSGB) {
|
||||
gb->model = GBNameToModel(modelSGB);
|
||||
}
|
||||
break;
|
||||
case GB_MODEL_MGB:
|
||||
if (modelGB) {
|
||||
gb->model = GBNameToModel(modelGB);
|
||||
}
|
||||
break;
|
||||
case GB_MODEL_MGB | GB_MODEL_CGB:
|
||||
if (modelCGBHybrid) {
|
||||
gb->model = GBNameToModel(modelCGBHybrid);
|
||||
}
|
||||
break;
|
||||
case GB_MODEL_SGB | GB_MODEL_CGB: // TODO: Do these even exist?
|
||||
case GB_MODEL_MGB | GB_MODEL_SGB | GB_MODEL_CGB:
|
||||
if (modelCGBSGB) {
|
||||
gb->model = GBNameToModel(modelCGBSGB);
|
||||
}
|
||||
break;
|
||||
case GB_MODEL_CGB:
|
||||
if (modelCGB) {
|
||||
gb->model = GBNameToModel(modelCGB);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
|
|
24
src/gb/gb.c
24
src/gb/gb.c
|
@ -247,6 +247,14 @@ void GBSramClean(struct GB* gb, uint32_t frameCount) {
|
|||
} else {
|
||||
mLOG(GB_MEM, INFO, "Savedata failed to sync!");
|
||||
}
|
||||
|
||||
size_t c;
|
||||
for (c = 0; c < mCoreCallbacksListSize(&gb->coreCallbacks); ++c) {
|
||||
struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gb->coreCallbacks, c);
|
||||
if (callbacks->savedataUpdated) {
|
||||
callbacks->savedataUpdated(callbacks->context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -648,6 +656,22 @@ void GBDetectModel(struct GB* gb) {
|
|||
}
|
||||
}
|
||||
|
||||
int GBValidModels(const uint8_t* bank0) {
|
||||
const struct GBCartridge* cart = (const struct GBCartridge*) &bank0[0x100];
|
||||
int models;
|
||||
if (cart->cgb == 0x80) {
|
||||
models = GB_MODEL_CGB | GB_MODEL_MGB;
|
||||
} else if (cart->cgb == 0xC0) {
|
||||
models = GB_MODEL_CGB;
|
||||
} else {
|
||||
models = GB_MODEL_MGB;
|
||||
}
|
||||
if (cart->sgb == 0x03 && cart->oldLicensee == 0x33) {
|
||||
models |= GB_MODEL_SGB;
|
||||
}
|
||||
return models;
|
||||
}
|
||||
|
||||
void GBUpdateIRQs(struct GB* gb) {
|
||||
int irqs = gb->memory.ie & gb->memory.io[REG_IF] & 0x1F;
|
||||
if (!irqs) {
|
||||
|
|
|
@ -815,6 +815,7 @@ void GBAFrameStarted(struct GBA* gba) {
|
|||
}
|
||||
|
||||
void GBAFrameEnded(struct GBA* gba) {
|
||||
int wasDirty = gba->memory.savedata.dirty;
|
||||
GBASavedataClean(&gba->memory.savedata, gba->video.frameCounter);
|
||||
|
||||
if (gba->cpu->components && gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]) {
|
||||
|
@ -845,6 +846,9 @@ void GBAFrameEnded(struct GBA* gba) {
|
|||
if (callbacks->videoFrameEnded) {
|
||||
callbacks->videoFrameEnded(callbacks->context);
|
||||
}
|
||||
if (callbacks->savedataUpdated && wasDirty && !gba->memory.savedata.dirty) {
|
||||
callbacks->savedataUpdated(callbacks->context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,25 +8,42 @@
|
|||
#include <mgba/internal/arm/macros.h>
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
#include <mgba/internal/gba/memory.h>
|
||||
#include <mgba/internal/gba/serialize.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
static void _remapMatrix(struct GBA* gba) {
|
||||
if (gba->memory.matrix.vaddr & 0xFFFFE1FF) {
|
||||
mLOG(GBA_MEM, ERROR, "Invalid Matrix mapping: %08X", gba->memory.matrix.vaddr);
|
||||
return;
|
||||
}
|
||||
if (gba->memory.matrix.size & 0xFFFFE1FF) {
|
||||
mLOG(GBA_MEM, ERROR, "Invalid Matrix size: %08X", gba->memory.matrix.size);
|
||||
return;
|
||||
}
|
||||
if ((gba->memory.matrix.vaddr + gba->memory.matrix.size - 1) & 0xFFFFE000) {
|
||||
mLOG(GBA_MEM, ERROR, "Invalid Matrix mapping end: %08X", gba->memory.matrix.vaddr + gba->memory.matrix.size);
|
||||
return;
|
||||
}
|
||||
int start = (gba->memory.matrix.vaddr >> 9) & 0x1F;
|
||||
int size = (gba->memory.matrix.size >> 9) & 0x1F;
|
||||
int i;
|
||||
for (i = 0; i < size; ++i) {
|
||||
gba->memory.matrix.mappings[start + i] = gba->memory.matrix.paddr + (i << 9);
|
||||
}
|
||||
|
||||
gba->romVf->seek(gba->romVf, gba->memory.matrix.paddr, SEEK_SET);
|
||||
gba->romVf->read(gba->romVf, &gba->memory.rom[gba->memory.matrix.vaddr >> 2], gba->memory.matrix.size);
|
||||
}
|
||||
|
||||
void GBAMatrixReset(struct GBA* gba) {
|
||||
gba->memory.matrix.paddr = 0x200;
|
||||
memset(gba->memory.matrix.mappings, 0, sizeof(gba->memory.matrix.mappings));
|
||||
gba->memory.matrix.size = 0x1000;
|
||||
|
||||
gba->memory.matrix.vaddr = 0;
|
||||
_remapMatrix(gba);
|
||||
gba->memory.matrix.vaddr = 0x1000;
|
||||
_remapMatrix(gba);
|
||||
|
||||
gba->memory.matrix.paddr = 0;
|
||||
gba->memory.matrix.vaddr = 0;
|
||||
gba->memory.matrix.size = 0x100;
|
||||
_remapMatrix(gba);
|
||||
gba->memory.matrix.paddr = 0x200;
|
||||
gba->memory.matrix.vaddr = 0x1000;
|
||||
_remapMatrix(gba);
|
||||
}
|
||||
|
||||
|
@ -51,6 +68,10 @@ void GBAMatrixWrite(struct GBA* gba, uint32_t address, uint32_t value) {
|
|||
gba->memory.matrix.vaddr = value & 0x007FFFFF;
|
||||
return;
|
||||
case 0xC:
|
||||
if (value == 0) {
|
||||
mLOG(GBA_MEM, ERROR, "Rejecting Matrix write for size 0");
|
||||
return;
|
||||
}
|
||||
gba->memory.matrix.size = value << 9;
|
||||
return;
|
||||
}
|
||||
|
@ -73,3 +94,39 @@ void GBAMatrixWrite16(struct GBA* gba, uint32_t address, uint16_t value) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GBAMatrixSerialize(const struct GBA* gba, struct GBASerializedState* state) {
|
||||
STORE_32(gba->memory.matrix.cmd, 0, &state->matrix.cmd);
|
||||
STORE_32(gba->memory.matrix.paddr, 0, &state->matrix.paddr);
|
||||
STORE_32(gba->memory.matrix.vaddr, 0, &state->matrix.vaddr);
|
||||
STORE_32(gba->memory.matrix.size, 0, &state->matrix.size);
|
||||
|
||||
if (GBA_MATRIX_MAPPINGS_MAX != 16) {
|
||||
mLOG(GBA_MEM, ERROR, "Matrix memory serialization is broken!");
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
STORE_32(gba->memory.matrix.mappings[i], i << 2, state->matrixMappings);
|
||||
}
|
||||
}
|
||||
|
||||
void GBAMatrixDeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
||||
if (GBA_MATRIX_MAPPINGS_MAX != 16) {
|
||||
mLOG(GBA_MEM, ERROR, "Matrix memory deserialization is broken!");
|
||||
}
|
||||
gba->memory.matrix.size = 0x200;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
LOAD_32(gba->memory.matrix.mappings[i], i << 2, state->matrixMappings);
|
||||
gba->memory.matrix.paddr = gba->memory.matrix.mappings[i];
|
||||
gba->memory.matrix.vaddr = i << 9;
|
||||
_remapMatrix(gba);
|
||||
}
|
||||
|
||||
LOAD_32(gba->memory.matrix.cmd, 0, &state->matrix.cmd);
|
||||
LOAD_32(gba->memory.matrix.paddr, 0, &state->matrix.paddr);
|
||||
LOAD_32(gba->memory.matrix.vaddr, 0, &state->matrix.vaddr);
|
||||
LOAD_32(gba->memory.matrix.size, 0, &state->matrix.size);
|
||||
}
|
||||
|
|
|
@ -534,16 +534,14 @@ void GBASavedataClean(struct GBASavedata* savedata, uint32_t frameCount) {
|
|||
if (savedata->dirty & SAVEDATA_DIRT_NEW) {
|
||||
savedata->dirtAge = frameCount;
|
||||
savedata->dirty &= ~SAVEDATA_DIRT_NEW;
|
||||
if (!(savedata->dirty & SAVEDATA_DIRT_SEEN)) {
|
||||
savedata->dirty |= SAVEDATA_DIRT_SEEN;
|
||||
}
|
||||
} else if ((savedata->dirty & SAVEDATA_DIRT_SEEN) && frameCount - savedata->dirtAge > CLEANUP_THRESHOLD) {
|
||||
if (savedata->maskWriteback) {
|
||||
GBASavedataUnmask(savedata);
|
||||
}
|
||||
savedata->dirty = 0;
|
||||
if (savedata->mapMode & MAP_WRITE) {
|
||||
size_t size = GBASavedataSize(savedata);
|
||||
savedata->dirty = 0;
|
||||
if (savedata->data && savedata->vf->sync(savedata->vf, savedata->data, size)) {
|
||||
mLOG(GBA_SAVE, INFO, "Savedata synced");
|
||||
} else {
|
||||
|
|
|
@ -76,6 +76,10 @@ void GBASerialize(struct GBA* gba, struct GBASerializedState* state) {
|
|||
GBAVideoSerialize(&gba->video, state);
|
||||
GBAAudioSerialize(&gba->audio, state);
|
||||
GBASavedataSerialize(&gba->memory.savedata, state);
|
||||
|
||||
if (gba->memory.matrix.size) {
|
||||
GBAMatrixSerialize(gba, state);
|
||||
}
|
||||
}
|
||||
|
||||
bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
||||
|
@ -196,6 +200,10 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
|||
GBAAudioDeserialize(&gba->audio, state);
|
||||
GBASavedataDeserialize(&gba->memory.savedata, state);
|
||||
|
||||
if (gba->memory.matrix.size) {
|
||||
GBAMatrixDeserialize(gba, state);
|
||||
}
|
||||
|
||||
gba->timing.reroot = gba->timing.root;
|
||||
gba->timing.root = NULL;
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ static void _reloadSettings(void) {
|
|||
};
|
||||
|
||||
struct retro_variable var;
|
||||
#ifdef M_CORE_GB
|
||||
enum GBModel model;
|
||||
const char* modelName;
|
||||
|
||||
|
@ -101,6 +102,7 @@ static void _reloadSettings(void) {
|
|||
mCoreConfigSetDefaultValue(&core->config, "sgb.model", modelName);
|
||||
mCoreConfigSetDefaultValue(&core->config, "cgb.model", modelName);
|
||||
}
|
||||
#endif
|
||||
|
||||
var.key = "mgba_use_bios";
|
||||
var.value = 0;
|
||||
|
@ -114,21 +116,18 @@ static void _reloadSettings(void) {
|
|||
opts.skipBios = strcmp(var.value, "ON") == 0;
|
||||
}
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
var.key = "mgba_sgb_borders";
|
||||
var.value = 0;
|
||||
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "ON") == 0) {
|
||||
mCoreConfigSetDefaultIntValue(&core->config, "sgb.borders", true);
|
||||
} else {
|
||||
mCoreConfigSetDefaultIntValue(&core->config, "sgb.borders", false);
|
||||
}
|
||||
mCoreConfigSetDefaultIntValue(&core->config, "sgb.borders", strcmp(var.value, "ON") == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
var.key = "mgba_frameskip";
|
||||
var.value = 0;
|
||||
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
opts.frameskip = strtol(var.value, NULL, 10);
|
||||
|
||||
}
|
||||
|
||||
var.key = "mgba_idle_optimization";
|
||||
|
@ -179,7 +178,11 @@ void retro_set_input_state(retro_input_state_t input) {
|
|||
|
||||
void retro_get_system_info(struct retro_system_info* info) {
|
||||
info->need_fullpath = false;
|
||||
info->valid_extensions = "gba|gb|gbc";
|
||||
#ifdef M_CORE_GB
|
||||
info->valid_extensions = "gba|gb|gbc|sgb";
|
||||
#else
|
||||
info->valid_extensions = "gba";
|
||||
#endif
|
||||
info->library_version = projectVersion;
|
||||
info->library_name = projectName;
|
||||
info->block_extract = false;
|
||||
|
@ -288,25 +291,15 @@ void retro_run(void) {
|
|||
.value = 0
|
||||
};
|
||||
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
struct GBA* gba = core->board;
|
||||
struct GB* gb = core->board;
|
||||
switch (core->platform(core)) {
|
||||
case PLATFORM_GBA:
|
||||
gba->allowOpposingDirections = strcmp(var.value, "yes") == 0;
|
||||
break;
|
||||
case PLATFORM_GB:
|
||||
gb->allowOpposingDirections = strcmp(var.value, "yes") == 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mCoreConfigSetIntValue(&core->config, "allowOpposingDirections", strcmp(var.value, "yes") == 0);
|
||||
core->reloadConfigOption(core, "allowOpposingDirections", NULL);
|
||||
}
|
||||
|
||||
var.key = "mgba_frameskip";
|
||||
var.value = 0;
|
||||
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
mCoreConfigSetUIntValue(&core->config, "frameskip", strtol(var.value, NULL, 10));
|
||||
mCoreLoadConfig(core);
|
||||
mCoreConfigSetIntValue(&core->config, "frameskip", strtol(var.value, NULL, 10));
|
||||
core->reloadConfigOption(core, "frameskip", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -443,6 +436,102 @@ static void _setupMaps(struct mCore* core) {
|
|||
environCallback(RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS, &yes);
|
||||
}
|
||||
#endif
|
||||
#ifdef M_CORE_GB
|
||||
if (core->platform(core) == PLATFORM_GB) {
|
||||
struct GB* gb = core->board;
|
||||
struct retro_memory_descriptor descs[11];
|
||||
struct retro_memory_map mmaps;
|
||||
|
||||
memset(descs, 0, sizeof(descs));
|
||||
size_t savedataSize = retro_get_memory_size(RETRO_MEMORY_SAVE_RAM);
|
||||
|
||||
unsigned i = 0;
|
||||
|
||||
/* Map ROM */
|
||||
descs[i].ptr = gb->memory.rom;
|
||||
descs[i].start = GB_BASE_CART_BANK0;
|
||||
descs[i].len = GB_SIZE_CART_BANK0;
|
||||
descs[i].flags = RETRO_MEMDESC_CONST;
|
||||
i++;
|
||||
|
||||
descs[i].ptr = gb->memory.rom;
|
||||
descs[i].offset = GB_SIZE_CART_BANK0;
|
||||
descs[i].start = GB_BASE_CART_BANK1;
|
||||
descs[i].len = GB_SIZE_CART_BANK0;
|
||||
descs[i].flags = RETRO_MEMDESC_CONST;
|
||||
i++;
|
||||
|
||||
/* Map VRAM */
|
||||
descs[i].ptr = gb->video.vram;
|
||||
descs[i].start = GB_BASE_VRAM;
|
||||
descs[i].len = GB_SIZE_VRAM_BANK0;
|
||||
i++;
|
||||
|
||||
/* Map working RAM */
|
||||
descs[i].ptr = gb->memory.wram;
|
||||
descs[i].start = GB_BASE_WORKING_RAM_BANK0;
|
||||
descs[i].len = GB_SIZE_WORKING_RAM_BANK0;
|
||||
i++;
|
||||
|
||||
descs[i].ptr = gb->memory.wram;
|
||||
descs[i].offset = GB_SIZE_WORKING_RAM_BANK0;
|
||||
descs[i].start = GB_BASE_WORKING_RAM_BANK1;
|
||||
descs[i].len = GB_SIZE_WORKING_RAM_BANK0;
|
||||
i++;
|
||||
|
||||
/* Map OAM */
|
||||
descs[i].ptr = &gb->video.oam; /* video.oam is a structure */
|
||||
descs[i].start = GB_BASE_OAM;
|
||||
descs[i].len = GB_SIZE_OAM;
|
||||
descs[i].select = 0xFFFFFF60;
|
||||
i++;
|
||||
|
||||
/* Map mmapped I/O */
|
||||
descs[i].ptr = gb->memory.io;
|
||||
descs[i].start = GB_BASE_IO;
|
||||
descs[i].len = GB_SIZE_IO;
|
||||
i++;
|
||||
|
||||
/* Map High RAM */
|
||||
descs[i].ptr = gb->memory.hram;
|
||||
descs[i].start = GB_BASE_HRAM;
|
||||
descs[i].len = GB_SIZE_HRAM;
|
||||
descs[i].select = 0xFFFFFF80;
|
||||
i++;
|
||||
|
||||
/* Map IE Register */
|
||||
descs[i].ptr = &gb->memory.ie;
|
||||
descs[i].start = GB_BASE_IE;
|
||||
descs[i].len = 1;
|
||||
i++;
|
||||
|
||||
/* Map External RAM */
|
||||
if (gb->memory.sram) {
|
||||
descs[i].ptr = gb->memory.sram;
|
||||
descs[i].start = GB_BASE_EXTERNAL_RAM;
|
||||
descs[i].len = savedataSize;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (gb->model >= GB_MODEL_CGB) {
|
||||
/* Map working RAM */
|
||||
/* banks 2-7 of wram mapped in virtual address so it can be
|
||||
* accessed without bank switching, GBC only */
|
||||
descs[i].ptr = gb->memory.wram + 0x2000;
|
||||
descs[i].start = 0x10000;
|
||||
descs[i].len = GB_SIZE_WORKING_RAM - 0x2000;
|
||||
descs[i].select = 0xFFFFA000;
|
||||
i++;
|
||||
}
|
||||
|
||||
mmaps.descriptors = descs;
|
||||
mmaps.num_descriptors = i;
|
||||
|
||||
bool yes = true;
|
||||
environCallback(RETRO_ENVIRONMENT_SET_MEMORY_MAPS, &mmaps);
|
||||
environCallback(RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS, &yes);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void retro_reset(void) {
|
||||
|
|
|
@ -190,7 +190,7 @@ struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = {
|
|||
NULL, /* RETRO_LANGUAGE_FRENCH */
|
||||
NULL, /* RETRO_LANGUAGE_SPANISH */
|
||||
NULL, /* RETRO_LANGUAGE_GERMAN */
|
||||
NULL, /* RETRO_LANGUAGE_ITALIAN */
|
||||
option_defs_it, /* RETRO_LANGUAGE_ITALIAN */
|
||||
NULL, /* RETRO_LANGUAGE_DUTCH */
|
||||
NULL, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */
|
||||
NULL, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */
|
||||
|
|
|
@ -47,6 +47,135 @@ extern "C" {
|
|||
|
||||
/* RETRO_LANGUAGE_ITALIAN */
|
||||
|
||||
struct retro_core_option_definition option_defs_it[] = {
|
||||
{
|
||||
"mgba_solar_sensor_level",
|
||||
"Livello Sensore Solare",
|
||||
"Imposta l'intensità solare dell'ambiente. Può essere usato dai giochi che includono un sensore solare nelle loro cartucce, es.: la serie Boktai.",
|
||||
{
|
||||
{ "0", NULL },
|
||||
{ "1", NULL },
|
||||
{ "2", NULL },
|
||||
{ "3", NULL },
|
||||
{ "4", NULL },
|
||||
{ "5", NULL },
|
||||
{ "6", NULL },
|
||||
{ "7", NULL },
|
||||
{ "8", NULL },
|
||||
{ "9", NULL },
|
||||
{ "10", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"0"
|
||||
},
|
||||
{
|
||||
"mgba_allow_opposing_directions",
|
||||
"Permetti Input Direzionali Opposti",
|
||||
"Attivando questa funzionalità ti permette di premere / alternare velocemente / tenere premuti entrambe le direzioni destra e sinistra (oppure su e giù) allo stesso momento. Potrebbe causare dei glitch di movimento.",
|
||||
{
|
||||
{ "no", "Disabilitato" },
|
||||
{ "yes", "Abilitato" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"no"
|
||||
},
|
||||
{
|
||||
"mgba_gb_model",
|
||||
"Modello Game Boy (richiede riavvio)",
|
||||
"Esegue il contenuto caricato con un modello specifico di Game Boy. 'Rivela Automaticamente' selezionerà il modello più appropriato per il gioco attuale.",
|
||||
{
|
||||
{ "Autodetect", "Rivela Automaticamente" },
|
||||
{ "Game Boy", NULL },
|
||||
{ "Super Game Boy", NULL },
|
||||
{ "Game Boy Color", NULL },
|
||||
{ "Game Boy Advance", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"Autodetect"
|
||||
},
|
||||
{
|
||||
"mgba_use_bios",
|
||||
"Usa il File BIOS se Presente (richiede riavvio)",
|
||||
"Usa il BIOS/bootloader ufficiale per hardware emulato, se presente nella cartella di sistema di RetroArch.",
|
||||
{
|
||||
{ "ON", NULL },
|
||||
{ "OFF", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"ON"
|
||||
},
|
||||
{
|
||||
"mgba_skip_bios",
|
||||
"Salta Intro BIOS (richiede riavvio)",
|
||||
"Salta il filmato del logo di avvio se si usa un BIOS/bootloader ufficiale. Questa impostazione è ignorata se 'Usa il file BIOS se presente' è disabilitato.",
|
||||
{
|
||||
{ "OFF", NULL },
|
||||
{ "ON", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"OFF"
|
||||
},
|
||||
{
|
||||
"mgba_sgb_borders",
|
||||
"Utilizza i Bordi Super Game Boy (richiede riavvio)",
|
||||
"Visualizza i bordi del Super Game Boy quando apri un gioco potenziato dal Super Game Boy.",
|
||||
{
|
||||
{ "ON", NULL },
|
||||
{ "OFF", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"ON"
|
||||
},
|
||||
{
|
||||
"mgba_idle_optimization",
|
||||
"Rimozione Idle Loop",
|
||||
"Riduce il carico del sistema ottimizzando gli 'idle-loops' - sezione del codice dove non accade nulla, ma la CPU lavora a velocità massima. Migliora le prestazioni, è consigliato abilitarlo su hardware di bassa fascia.",
|
||||
{
|
||||
{ "Remove Known", "Rimuovi Conosciuti" },
|
||||
{ "Detect and Remove", "Rileva e Rimuovi" },
|
||||
{ "Don't Remove", "Non Rimuovere" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"Remove Known"
|
||||
},
|
||||
{
|
||||
"mgba_frameskip",
|
||||
"Salta Frame",
|
||||
"Salta dei frame per migliorare le prestazioni a costo della fluidità dell'immagine. Il valore impostato qui è il numero dei frame rimosso dopo che un frame sia stato renderizzato - ovvero '0' = 60fps, '1' = 30fps, '2' = 15fps, ecc.",
|
||||
{
|
||||
{ "0", NULL },
|
||||
{ "1", NULL },
|
||||
{ "2", NULL },
|
||||
{ "3", NULL },
|
||||
{ "4", NULL },
|
||||
{ "5", NULL },
|
||||
{ "6", NULL },
|
||||
{ "7", NULL },
|
||||
{ "8", NULL },
|
||||
{ "9", NULL },
|
||||
{ "10", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"0"
|
||||
},
|
||||
#if defined(COLOR_16_BIT) && defined(COLOR_5_6_5)
|
||||
{
|
||||
"mgba_color_correction",
|
||||
"Correzione Colore",
|
||||
"Regola i colori per corrispondere lo schermo di GBA/GBC reali.",
|
||||
{
|
||||
{ "OFF", NULL },
|
||||
{ "GBA", "Game Boy Advance" },
|
||||
{ "GBC", "Game Boy Color" },
|
||||
{ "Auto", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"OFF"
|
||||
},
|
||||
#endif
|
||||
{ NULL, NULL, NULL, {{0}}, NULL },
|
||||
};
|
||||
|
||||
/* RETRO_LANGUAGE_DUTCH */
|
||||
|
||||
/* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */
|
||||
|
|
|
@ -16,7 +16,7 @@ if(BUILD_SDL)
|
|||
endif()
|
||||
|
||||
if(POLICY CMP0071)
|
||||
cmake_policy(SET CMP0071 OLD)
|
||||
cmake_policy(SET CMP0071 NEW)
|
||||
endif()
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
@ -157,6 +157,7 @@ set(GBA_SRC
|
|||
GBAOverride.cpp)
|
||||
|
||||
set(GB_SRC
|
||||
GameBoy.cpp
|
||||
GBOverride.cpp
|
||||
PrinterView.cpp)
|
||||
|
||||
|
@ -303,7 +304,7 @@ if(QT_STATIC)
|
|||
if(CMAKE_CROSSCOMPILING)
|
||||
set(QWINDOWS_DEPS Qt5EventDispatcherSupport Qt5FontDatabaseSupport Qt5ThemeSupport Qt5WindowsUIAutomationSupport)
|
||||
endif()
|
||||
list(APPEND QT_LIBRARIES Qt5::QWindowsIntegrationPlugin ${QWINDOWS_DEPS} dwmapi uxtheme imm32 -static-libgcc -static-libstdc++)
|
||||
list(APPEND QT_LIBRARIES Qt5::QWindowsIntegrationPlugin ${QWINDOWS_DEPS} amstrmid dwmapi uxtheme imm32 -static-libgcc -static-libstdc++)
|
||||
set_target_properties(Qt5::Core PROPERTIES INTERFACE_LINK_LIBRARIES "${QTPCRE};version;winmm;ssl;crypto;ws2_32;iphlpapi;crypt32;userenv;netapi32;wtsapi32")
|
||||
set_target_properties(Qt5::Gui PROPERTIES INTERFACE_LINK_LIBRARIES ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY})
|
||||
elseif(APPLE)
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/* Copyright (c) 2013-2020 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "GameBoy.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QMap>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
static const QList<GBModel> s_gbModelList{
|
||||
GB_MODEL_DMG,
|
||||
GB_MODEL_SGB,
|
||||
GB_MODEL_CGB,
|
||||
GB_MODEL_AGB,
|
||||
};
|
||||
|
||||
static const QList<GBMemoryBankControllerType> s_mbcList{
|
||||
GB_MBC_NONE,
|
||||
GB_MBC1,
|
||||
GB_MBC2,
|
||||
GB_MBC3,
|
||||
GB_MBC3_RTC,
|
||||
GB_MBC5,
|
||||
GB_MBC5_RUMBLE,
|
||||
GB_MBC6,
|
||||
GB_MBC7,
|
||||
GB_MMM01,
|
||||
GB_POCKETCAM,
|
||||
GB_TAMA5,
|
||||
GB_HuC1,
|
||||
GB_HuC3,
|
||||
GB_UNL_WISDOM_TREE,
|
||||
GB_UNL_BBD,
|
||||
GB_UNL_HITEK,
|
||||
GB_UNL_PKJD,
|
||||
};
|
||||
|
||||
static QMap<GBModel, QString> s_gbModelNames;
|
||||
static QMap<GBMemoryBankControllerType, QString> s_mbcNames;
|
||||
|
||||
static QString tr(const char* str) {
|
||||
return QCoreApplication::translate("Game Boy", str);
|
||||
}
|
||||
|
||||
QList<GBModel> GameBoy::modelList() {
|
||||
return s_gbModelList;
|
||||
}
|
||||
|
||||
QString GameBoy::modelName(GBModel model) {
|
||||
if (s_gbModelNames.isEmpty()) {
|
||||
s_gbModelNames[GB_MODEL_AUTODETECT] = tr("Autodetect");
|
||||
s_gbModelNames[GB_MODEL_DMG] = tr("Game Boy (DMG)");
|
||||
s_gbModelNames[GB_MODEL_MGB] = tr("Game Boy Pocket (MGB)");
|
||||
s_gbModelNames[GB_MODEL_SGB] = tr("Super Game Boy (SGB)");
|
||||
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)");
|
||||
}
|
||||
|
||||
return s_gbModelNames[model];
|
||||
}
|
||||
|
||||
QList<GBMemoryBankControllerType> GameBoy::mbcList() {
|
||||
return s_mbcList;
|
||||
}
|
||||
|
||||
QString GameBoy::mbcName(GBMemoryBankControllerType mbc) {
|
||||
if (s_mbcNames.isEmpty()) {
|
||||
s_mbcNames[GB_MBC_AUTODETECT] = tr("Autodetect");
|
||||
s_mbcNames[GB_MBC_NONE] = tr("ROM Only");
|
||||
s_mbcNames[GB_MBC1] = tr("MBC1");
|
||||
s_mbcNames[GB_MBC2] = tr("MBC2");
|
||||
s_mbcNames[GB_MBC3] = tr("MBC3");
|
||||
s_mbcNames[GB_MBC3_RTC] = tr("MBC3 + RTC");
|
||||
s_mbcNames[GB_MBC5] = tr("MBC5");
|
||||
s_mbcNames[GB_MBC5_RUMBLE] = tr("MBC5 + Rumble");
|
||||
s_mbcNames[GB_MBC6] = tr("MBC6");
|
||||
s_mbcNames[GB_MBC7] = tr("MBC7 (Tilt)");
|
||||
s_mbcNames[GB_MMM01] = tr("MMM01");
|
||||
s_mbcNames[GB_HuC1] = tr("HuC-1");
|
||||
s_mbcNames[GB_HuC3] = tr("HuC-3");
|
||||
s_mbcNames[GB_POCKETCAM] = tr("Pocket Cam");
|
||||
s_mbcNames[GB_TAMA5] = tr("TAMA5");
|
||||
s_mbcNames[GB_UNL_WISDOM_TREE] = tr("Wisdom Tree");
|
||||
s_mbcNames[GB_UNL_PKJD] = tr("Pokémon Jade/Diamond");
|
||||
s_mbcNames[GB_UNL_BBD] = tr("BBD");
|
||||
s_mbcNames[GB_UNL_HITEK] = tr("Hitek");
|
||||
}
|
||||
|
||||
return s_mbcNames[mbc];
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/* Copyright (c) 2013-2020 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#pragma once
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
#include <mgba/gb/interface.h>
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
namespace GameBoy {
|
||||
QList<GBModel> modelList();
|
||||
QString modelName(GBModel);
|
||||
|
||||
QList<GBMemoryBankControllerType> mbcList();
|
||||
QString mbcName(GBMemoryBankControllerType);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
|
@ -6,6 +6,7 @@
|
|||
#include "OverrideView.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QStandardItemModel>
|
||||
|
||||
#include "ConfigController.h"
|
||||
#include "CoreController.h"
|
||||
|
@ -16,53 +17,17 @@
|
|||
#endif
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
#include "GameBoy.h"
|
||||
#include "GBOverride.h"
|
||||
#include <mgba/internal/gb/gb.h>
|
||||
#endif
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
QList<enum GBModel> OverrideView::s_gbModelList;
|
||||
QList<enum GBMemoryBankControllerType> OverrideView::s_mbcList;
|
||||
#endif
|
||||
|
||||
OverrideView::OverrideView(ConfigController* config, QWidget* parent)
|
||||
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
|
||||
, m_config(config)
|
||||
{
|
||||
#ifdef M_CORE_GB
|
||||
if (s_mbcList.isEmpty()) {
|
||||
// NB: Keep in sync with OverrideView.ui
|
||||
s_mbcList.append(GB_MBC_AUTODETECT);
|
||||
s_mbcList.append(GB_MBC_NONE);
|
||||
s_mbcList.append(GB_MBC1);
|
||||
s_mbcList.append(GB_MBC2);
|
||||
s_mbcList.append(GB_MBC3);
|
||||
s_mbcList.append(GB_MBC3_RTC);
|
||||
s_mbcList.append(GB_MBC5);
|
||||
s_mbcList.append(GB_MBC5_RUMBLE);
|
||||
s_mbcList.append(GB_MBC6);
|
||||
s_mbcList.append(GB_MBC7);
|
||||
s_mbcList.append(GB_MMM01);
|
||||
s_mbcList.append(GB_POCKETCAM);
|
||||
s_mbcList.append(GB_TAMA5);
|
||||
s_mbcList.append(GB_HuC1);
|
||||
s_mbcList.append(GB_HuC3);
|
||||
s_mbcList.append(GB_UNL_WISDOM_TREE);
|
||||
s_mbcList.append(GB_UNL_BBD);
|
||||
s_mbcList.append(GB_UNL_HITEK);
|
||||
s_mbcList.append(GB_UNL_PKJD);
|
||||
}
|
||||
if (s_gbModelList.isEmpty()) {
|
||||
// NB: Keep in sync with OverrideView.ui
|
||||
s_gbModelList.append(GB_MODEL_AUTODETECT);
|
||||
s_gbModelList.append(GB_MODEL_DMG);
|
||||
s_gbModelList.append(GB_MODEL_SGB);
|
||||
s_gbModelList.append(GB_MODEL_CGB);
|
||||
s_gbModelList.append(GB_MODEL_AGB);
|
||||
}
|
||||
#endif
|
||||
m_ui.setupUi(this);
|
||||
|
||||
connect(m_ui.hwAutodetect, &QAbstractButton::toggled, [this] (bool enabled) {
|
||||
|
@ -74,6 +39,33 @@ OverrideView::OverrideView(ConfigController* config, QWidget* parent)
|
|||
});
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
m_ui.gbModel->setItemData(0, GB_MODEL_AUTODETECT);
|
||||
m_ui.mbc->setItemData(0, GB_MBC_AUTODETECT);
|
||||
|
||||
for (auto model : GameBoy::modelList()) {
|
||||
m_ui.gbModel->addItem(GameBoy::modelName(model), model);
|
||||
}
|
||||
|
||||
QStandardItemModel* model = static_cast<QStandardItemModel*>(m_ui.mbc->model());
|
||||
int bitsSeen = 0;
|
||||
for (auto mbc : GameBoy::mbcList()) {
|
||||
int mbcValue = static_cast<int>(mbc);
|
||||
if ((mbcValue & ~bitsSeen) & 0x001) {
|
||||
m_ui.mbc->addItem(tr("Official MBCs"), -2);
|
||||
model->item(m_ui.mbc->count() - 1)->setFlags(Qt::NoItemFlags);
|
||||
}
|
||||
if ((mbcValue & ~bitsSeen) & 0x010) {
|
||||
m_ui.mbc->addItem(tr("Licensed MBCs"), -3);
|
||||
model->item(m_ui.mbc->count() - 1)->setFlags(Qt::NoItemFlags);
|
||||
}
|
||||
if ((mbcValue & ~bitsSeen) & 0x200) {
|
||||
m_ui.mbc->addItem(tr("Unlicensed MBCs"), -4);
|
||||
model->item(m_ui.mbc->count() - 1)->setFlags(Qt::NoItemFlags);
|
||||
}
|
||||
bitsSeen |= mbcValue;
|
||||
m_ui.mbc->addItem(GameBoy::mbcName(mbc), mbc);
|
||||
}
|
||||
|
||||
m_colorPickers[0] = ColorPicker(m_ui.color0, QColor(0xF8, 0xF8, 0xF8));
|
||||
m_colorPickers[1] = ColorPicker(m_ui.color1, QColor(0xA8, 0xA8, 0xA8));
|
||||
m_colorPickers[2] = ColorPicker(m_ui.color2, QColor(0x50, 0x50, 0x50));
|
||||
|
@ -190,8 +182,8 @@ void OverrideView::updateOverrides() {
|
|||
#ifdef M_CORE_GB
|
||||
if (m_ui.tabWidget->currentWidget() == m_ui.tabGB) {
|
||||
std::unique_ptr<GBOverride> gb(new GBOverride);
|
||||
gb->override.mbc = s_mbcList[m_ui.mbc->currentIndex()];
|
||||
gb->override.model = s_gbModelList[m_ui.gbModel->currentIndex()];
|
||||
gb->override.mbc = static_cast<GBMemoryBankControllerType>(m_ui.mbc->currentData().toInt());
|
||||
gb->override.model = static_cast<GBModel>(m_ui.gbModel->currentData().toInt());
|
||||
bool hasColor = false;
|
||||
for (int i = 0; i < 12; ++i) {
|
||||
gb->override.gbColors[i] = m_gbColors[i];
|
||||
|
@ -240,13 +232,13 @@ void OverrideView::gameStarted() {
|
|||
case PLATFORM_GB: {
|
||||
m_ui.tabWidget->setCurrentWidget(m_ui.tabGB);
|
||||
GB* gb = static_cast<GB*>(thread->core->board);
|
||||
int mbc = s_mbcList.indexOf(gb->memory.mbcType);
|
||||
if (mbc >= 0) {
|
||||
m_ui.mbc->setCurrentIndex(mbc);
|
||||
int index = m_ui.mbc->findData(gb->memory.mbcType);
|
||||
if (index >= 0) {
|
||||
m_ui.mbc->setCurrentIndex(index);
|
||||
} else {
|
||||
m_ui.mbc->setCurrentIndex(0);
|
||||
}
|
||||
int model = s_gbModelList.indexOf(gb->model);
|
||||
int model = m_ui.gbModel->findData(gb->model);
|
||||
if (model >= 0) {
|
||||
m_ui.gbModel->setCurrentIndex(model);
|
||||
} else {
|
||||
|
|
|
@ -55,9 +55,6 @@ private:
|
|||
#ifdef M_CORE_GB
|
||||
uint32_t m_gbColors[12]{};
|
||||
ColorPicker m_colorPickers[12];
|
||||
|
||||
static QList<enum GBModel> s_gbModelList;
|
||||
static QList<enum GBMemoryBankControllerType> s_mbcList;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -248,26 +248,6 @@
|
|||
<string>Autodetect</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game Boy (DMG)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Super Game Boy (SGB)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game Boy Color (CGB)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game Boy Advance (AGB)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
|
@ -284,96 +264,6 @@
|
|||
<string>Autodetect</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MBC1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MBC2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MBC3</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MBC3 + RTC</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MBC5</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MBC5 + Rumble</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MBC6</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MBC7</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MMM01</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Pocket Cam</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>TAMA5</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>HuC-1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>HuC-3</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Wisdom Tree (Unlicensed)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>BBD (Unlicensed)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Hitek (Unlicensed)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Pokémon Jade/Diamond (Unlicensed)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
|
|
|
@ -14,16 +14,16 @@
|
|||
#include "ShaderSelector.h"
|
||||
#include "ShortcutView.h"
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
#include "GameBoy.h"
|
||||
#endif
|
||||
|
||||
#include <mgba/core/serialize.h>
|
||||
#include <mgba/core/version.h>
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
QList<enum GBModel> SettingsView::s_gbModelList;
|
||||
#endif
|
||||
|
||||
SettingsView::SettingsView(ConfigController* controller, InputController* inputController, LogController* logController, QWidget* parent)
|
||||
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
|
||||
, m_controller(controller)
|
||||
|
@ -33,14 +33,19 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
m_ui.setupUi(this);
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
if (s_gbModelList.isEmpty()) {
|
||||
// NB: Keep in sync with SettingsView.ui
|
||||
s_gbModelList.append(GB_MODEL_AUTODETECT);
|
||||
s_gbModelList.append(GB_MODEL_DMG);
|
||||
s_gbModelList.append(GB_MODEL_SGB);
|
||||
s_gbModelList.append(GB_MODEL_CGB);
|
||||
s_gbModelList.append(GB_MODEL_AGB);
|
||||
for (auto model : GameBoy::modelList()) {
|
||||
m_ui.gbModel->addItem(GameBoy::modelName(model), model);
|
||||
m_ui.sgbModel->addItem(GameBoy::modelName(model), model);
|
||||
m_ui.cgbModel->addItem(GameBoy::modelName(model), model);
|
||||
m_ui.cgbHybridModel->addItem(GameBoy::modelName(model), model);
|
||||
m_ui.cgbSgbModel->addItem(GameBoy::modelName(model), model);
|
||||
}
|
||||
|
||||
m_ui.gbModel->setCurrentIndex(m_ui.gbModel->findData(GB_MODEL_DMG));
|
||||
m_ui.sgbModel->setCurrentIndex(m_ui.gbModel->findData(GB_MODEL_SGB));
|
||||
m_ui.cgbModel->setCurrentIndex(m_ui.gbModel->findData(GB_MODEL_CGB));
|
||||
m_ui.cgbHybridModel->setCurrentIndex(m_ui.gbModel->findData(GB_MODEL_CGB));
|
||||
m_ui.cgbSgbModel->setCurrentIndex(m_ui.gbModel->findData(GB_MODEL_CGB));
|
||||
#endif
|
||||
|
||||
reloadConfig();
|
||||
|
@ -505,14 +510,30 @@ void SettingsView::updateConfig() {
|
|||
m_logModel.logger()->logToStdout(m_ui.logToStdout->isChecked());
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
GBModel modelGB = s_gbModelList[m_ui.gbModel->currentIndex()];
|
||||
m_controller->setOption("gb.model", GBModelToName(modelGB));
|
||||
QVariant modelGB = m_ui.gbModel->currentData();
|
||||
if (modelGB.isValid()) {
|
||||
m_controller->setOption("gb.model", GBModelToName(static_cast<GBModel>(modelGB.toInt())));
|
||||
}
|
||||
|
||||
GBModel modelSGB = s_gbModelList[m_ui.sgbModel->currentIndex()];
|
||||
m_controller->setOption("sgb.model", GBModelToName(modelSGB));
|
||||
QVariant modelSGB = m_ui.sgbModel->currentData();
|
||||
if (modelSGB.isValid()) {
|
||||
m_controller->setOption("sgb.model", GBModelToName(static_cast<GBModel>(modelSGB.toInt())));
|
||||
}
|
||||
|
||||
GBModel modelCGB = s_gbModelList[m_ui.cgbModel->currentIndex()];
|
||||
m_controller->setOption("cgb.model", GBModelToName(modelCGB));
|
||||
QVariant modelCGB = m_ui.cgbModel->currentData();
|
||||
if (modelCGB.isValid()) {
|
||||
m_controller->setOption("cgb.model", GBModelToName(static_cast<GBModel>(modelCGB.toInt())));
|
||||
}
|
||||
|
||||
QVariant modelCGBHybrid = m_ui.cgbHybridModel->currentData();
|
||||
if (modelCGBHybrid.isValid()) {
|
||||
m_controller->setOption("cgb.hybridModel", GBModelToName(static_cast<GBModel>(modelCGBHybrid.toInt())));
|
||||
}
|
||||
|
||||
QVariant modelCGBSGB = m_ui.cgbSgbModel->currentData();
|
||||
if (modelCGBSGB.isValid()) {
|
||||
m_controller->setOption("cgb.sgbModel", GBModelToName(static_cast<GBModel>(modelCGBSGB.toInt())));
|
||||
}
|
||||
|
||||
for (int colorId = 0; colorId < 12; ++colorId) {
|
||||
if (!(m_gbColors[colorId] & 0xFF000000)) {
|
||||
|
@ -640,23 +661,37 @@ void SettingsView::reloadConfig() {
|
|||
QString modelGB = m_controller->getOption("gb.model");
|
||||
if (!modelGB.isNull()) {
|
||||
GBModel model = GBNameToModel(modelGB.toUtf8().constData());
|
||||
int index = s_gbModelList.indexOf(model);
|
||||
int index = m_ui.gbModel->findData(model);
|
||||
m_ui.gbModel->setCurrentIndex(index >= 0 ? index : 0);
|
||||
}
|
||||
|
||||
QString modelSGB = m_controller->getOption("sgb.model");
|
||||
if (!modelSGB.isNull()) {
|
||||
GBModel model = GBNameToModel(modelSGB.toUtf8().constData());
|
||||
int index = s_gbModelList.indexOf(model);
|
||||
int index = m_ui.sgbModel->findData(model);
|
||||
m_ui.sgbModel->setCurrentIndex(index >= 0 ? index : 0);
|
||||
}
|
||||
|
||||
QString modelCGB = m_controller->getOption("cgb.model");
|
||||
if (!modelCGB.isNull()) {
|
||||
GBModel model = GBNameToModel(modelCGB.toUtf8().constData());
|
||||
int index = s_gbModelList.indexOf(model);
|
||||
int index = m_ui.cgbModel->findData(model);
|
||||
m_ui.cgbModel->setCurrentIndex(index >= 0 ? index : 0);
|
||||
}
|
||||
|
||||
QString modelCGBHybrid = m_controller->getOption("cgb.hybridModel");
|
||||
if (!modelCGBHybrid.isNull()) {
|
||||
GBModel model = GBNameToModel(modelCGBHybrid.toUtf8().constData());
|
||||
int index = m_ui.cgbHybridModel->findData(model);
|
||||
m_ui.cgbHybridModel->setCurrentIndex(index >= 0 ? index : 0);
|
||||
}
|
||||
|
||||
QString modelCGBSGB = m_controller->getOption("cgb.sgbModel");
|
||||
if (!modelCGBSGB.isNull()) {
|
||||
GBModel model = GBNameToModel(modelCGBSGB.toUtf8().constData());
|
||||
int index = m_ui.cgbSgbModel->findData(model);
|
||||
m_ui.cgbSgbModel->setCurrentIndex(index >= 0 ? index : 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
int hwaccelVideo = m_controller->getOption("hwaccelVideo", 0).toInt();
|
||||
|
|
|
@ -61,7 +61,6 @@ private:
|
|||
#ifdef M_CORE_GB
|
||||
uint32_t m_gbColors[12]{};
|
||||
ColorPicker m_colorPickers[12];
|
||||
static QList<enum GBModel> s_gbModelList;
|
||||
#endif
|
||||
|
||||
void saveSetting(const char* key, const QAbstractButton*);
|
||||
|
|
|
@ -1545,38 +1545,12 @@
|
|||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_29">
|
||||
<property name="text">
|
||||
<string>Game Boy model:</string>
|
||||
<string>Game Boy-only model:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="gbModel">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Autodetect</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game Boy (DMG)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Super Game Boy (SGB)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game Boy Color (CGB)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game Boy Advance (AGB)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="gbModel"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_32">
|
||||
|
@ -1586,85 +1560,40 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="sgbModel">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Autodetect</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game Boy (DMG)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Super Game Boy (SGB)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game Boy Color (CGB)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game Boy Advance (AGB)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="sgbModel"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_33">
|
||||
<property name="text">
|
||||
<string>Game Boy Color model:</string>
|
||||
<string>Game Boy Color-only model:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="cgbModel">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Autodetect</string>
|
||||
</property>
|
||||
<widget class="QComboBox" name="cgbModel"/>
|
||||
</item>
|
||||
<item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_38">
|
||||
<property name="text">
|
||||
<string>Game Boy (DMG)</string>
|
||||
<string>Game Boy/Game Boy Color model:</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Super Game Boy (SGB)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game Boy Color (CGB)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game Boy Advance (AGB)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="Line" name="line_12">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="text">
|
||||
<string>Default BG colors:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="6" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<widget class="QFrame" name="color0">
|
||||
|
@ -1744,7 +1673,14 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_69">
|
||||
<property name="text">
|
||||
<string>Default sprite colors 1:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_15">
|
||||
<item>
|
||||
<widget class="QFrame" name="color4">
|
||||
|
@ -1824,38 +1760,14 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_70">
|
||||
<property name="text">
|
||||
<string>Default sprite colors 2:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QCheckBox" name="sgbBorders">
|
||||
<property name="text">
|
||||
<string>Super Game Boy borders</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<widget class="Line" name="line_11">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_27">
|
||||
<property name="text">
|
||||
<string>Camera driver:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QComboBox" name="cameraDriver">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_37">
|
||||
<item>
|
||||
<widget class="QFrame" name="color8">
|
||||
|
@ -1935,35 +1847,52 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_69">
|
||||
<property name="text">
|
||||
<string>Default sprite colors 1:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_70">
|
||||
<property name="text">
|
||||
<string>Default sprite colors 2:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="9" column="1">
|
||||
<widget class="QCheckBox" name="useCgbColors">
|
||||
<property name="text">
|
||||
<string>Use GBC colors in GB games</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="10" column="1">
|
||||
<widget class="QCheckBox" name="sgbBorders">
|
||||
<property name="text">
|
||||
<string>Super Game Boy borders</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0" colspan="2">
|
||||
<widget class="Line" name="line_11">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_27">
|
||||
<property name="text">
|
||||
<string>Camera driver:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QComboBox" name="cameraDriver">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="label_35">
|
||||
<property name="text">
|
||||
<string>Camera:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<item row="13" column="1">
|
||||
<widget class="QComboBox" name="camera">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
|
@ -1976,6 +1905,19 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="cgbHybridModel"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_39">
|
||||
<property name="text">
|
||||
<string>Super Game Boy/Game Boy Color model:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="cgbSgbModel"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="kr" sourcelanguage="en_US">
|
||||
<TS version="2.1" language="ko" sourcelanguage="en_US">
|
||||
<context>
|
||||
<name>AboutScreen</name>
|
||||
<message>
|
||||
|
|
Loading…
Reference in New Issue