Merge branch 'master' (early part) into medusa

This commit is contained in:
Vicki Pfau 2021-06-11 02:15:06 -07:00
commit 243b1b1c26
24 changed files with 693 additions and 365 deletions

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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];

View File

@ -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

View File

@ -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) {

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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;

View File

@ -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) {

View File

@ -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 */

View File

@ -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 */

View File

@ -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)

View File

@ -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];
}

25
src/platform/qt/GameBoy.h Normal file
View File

@ -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

View File

@ -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 {

View File

@ -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
};

View File

@ -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">

View File

@ -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();

View File

@ -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*);

View File

@ -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>

View File

@ -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>