GB Video: Ability to disable SGB borders

This commit is contained in:
Vicki Pfau 2017-08-05 08:52:09 -07:00
parent f0686a3b78
commit 558055277f
9 changed files with 127 additions and 97 deletions

View File

@ -42,6 +42,7 @@ struct GBVideoSoftwareRenderer {
int sgbPacketId; int sgbPacketId;
int sgbDataSets; int sgbDataSets;
uint8_t sgbPartialDataSet[15]; uint8_t sgbPartialDataSet[15];
bool sgbBorders;
}; };
void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer*); void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer*);

View File

@ -67,7 +67,7 @@ union GBOAM {
struct mTileCache; struct mTileCache;
struct GBVideoRenderer { struct GBVideoRenderer {
void (*init)(struct GBVideoRenderer* renderer, enum GBModel model); void (*init)(struct GBVideoRenderer* renderer, enum GBModel model, bool borders);
void (*deinit)(struct GBVideoRenderer* renderer); void (*deinit)(struct GBVideoRenderer* renderer);
uint8_t (*writeVideoRegister)(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value); uint8_t (*writeVideoRegister)(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
@ -148,6 +148,8 @@ struct GBVideo {
uint16_t dmgPalette[4]; uint16_t dmgPalette[4];
uint16_t palette[64]; uint16_t palette[64];
bool sgbBorders;
int32_t frameCounter; int32_t frameCounter;
int frameskip; int frameskip;
int frameskipCounter; int frameskipCounter;

View File

@ -187,6 +187,11 @@ static void _GBCoreLoadConfig(struct mCore* core, const struct mCoreConfig* conf
mCoreConfigCopyValue(&core->config, config, "sgb.model"); mCoreConfigCopyValue(&core->config, config, "sgb.model");
mCoreConfigCopyValue(&core->config, config, "cgb.model"); mCoreConfigCopyValue(&core->config, config, "cgb.model");
int fakeBool;
if (mCoreConfigGetIntValue(config, "sgb.borders", &fakeBool)) {
gb->video.sgbBorders = fakeBool;
}
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
struct GBCore* gbcore = (struct GBCore*) core; struct GBCore* gbcore = (struct GBCore*) core;
gbcore->overrides = mCoreConfigGetOverridesConst(config); gbcore->overrides = mCoreConfigGetOverridesConst(config);
@ -195,7 +200,7 @@ static void _GBCoreLoadConfig(struct mCore* core, const struct mCoreConfig* conf
static void _GBCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) { static void _GBCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
struct GB* gb = core->board; struct GB* gb = core->board;
if (!gb || gb->model != GB_MODEL_SGB) { if (!gb || gb->model != GB_MODEL_SGB || !gb->video.sgbBorders) {
*width = GB_VIDEO_HORIZONTAL_PIXELS; *width = GB_VIDEO_HORIZONTAL_PIXELS;
*height = GB_VIDEO_VERTICAL_PIXELS; *height = GB_VIDEO_VERTICAL_PIXELS;
} else { } else {

View File

@ -12,7 +12,7 @@
#define BUFFER_OAM 1 #define BUFFER_OAM 1
#define BUFFER_SGB 2 #define BUFFER_SGB 2
static void GBVideoProxyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model); static void GBVideoProxyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders);
static void GBVideoProxyRendererDeinit(struct GBVideoRenderer* renderer); static void GBVideoProxyRendererDeinit(struct GBVideoRenderer* renderer);
static uint8_t GBVideoProxyRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value); static uint8_t GBVideoProxyRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
static void GBVideoProxyRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data); static void GBVideoProxyRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data);
@ -96,12 +96,12 @@ void GBVideoProxyRendererUnshim(struct GBVideo* video, struct GBVideoProxyRender
mVideoLoggerRendererDeinit(renderer->logger); mVideoLoggerRendererDeinit(renderer->logger);
} }
void GBVideoProxyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model) { void GBVideoProxyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders) {
struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer; struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer;
_init(proxyRenderer); _init(proxyRenderer);
proxyRenderer->backend->init(proxyRenderer->backend, model); proxyRenderer->backend->init(proxyRenderer->backend, model, borders);
} }
void GBVideoProxyRendererDeinit(struct GBVideoRenderer* renderer) { void GBVideoProxyRendererDeinit(struct GBVideoRenderer* renderer) {

View File

@ -10,7 +10,7 @@
#include <mgba-util/math.h> #include <mgba-util/math.h>
#include <mgba-util/memory.h> #include <mgba-util/memory.h>
static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum GBModel model); static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders);
static void GBVideoSoftwareRendererDeinit(struct GBVideoRenderer* renderer); static void GBVideoSoftwareRendererDeinit(struct GBVideoRenderer* renderer);
static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value); static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data); static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data);
@ -28,7 +28,7 @@ static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* rende
static void _clearScreen(struct GBVideoSoftwareRenderer* renderer) { static void _clearScreen(struct GBVideoSoftwareRenderer* renderer) {
size_t sgbOffset = 0; size_t sgbOffset = 0;
if (renderer->model == GB_MODEL_SGB) { if (renderer->model == GB_MODEL_SGB && renderer->sgbBorders) {
sgbOffset = renderer->outputBufferStride * 40 + 48; sgbOffset = renderer->outputBufferStride * 40 + 48;
} }
int y; int y;
@ -166,7 +166,7 @@ void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer* renderer) {
renderer->temporaryBuffer = 0; renderer->temporaryBuffer = 0;
} }
static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum GBModel model) { static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool sgbBorders) {
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
softwareRenderer->lcdc = 0; softwareRenderer->lcdc = 0;
softwareRenderer->scy = 0; softwareRenderer->scy = 0;
@ -177,6 +177,7 @@ static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum G
softwareRenderer->model = model; softwareRenderer->model = model;
softwareRenderer->sgbTransfer = 0; softwareRenderer->sgbTransfer = 0;
softwareRenderer->sgbCommandHeader = 0; softwareRenderer->sgbCommandHeader = 0;
softwareRenderer->sgbBorders = sgbBorders;
int i; int i;
for (i = 0; i < 64; ++i) { for (i = 0; i < 64; ++i) {
softwareRenderer->lookup[i] = i; softwareRenderer->lookup[i] = i;
@ -271,7 +272,9 @@ static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* render
} }
break; break;
case SGB_ATRC_EN: case SGB_ATRC_EN:
_regenerateSGBBorder(softwareRenderer); if (softwareRenderer->sgbBorders) {
_regenerateSGBBorder(softwareRenderer);
}
break; break;
} }
} }
@ -334,11 +337,11 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
} }
size_t sgbOffset = 0; size_t sgbOffset = 0;
if (softwareRenderer->model == GB_MODEL_SGB) { if (softwareRenderer->model == GB_MODEL_SGB && softwareRenderer->sgbBorders) {
sgbOffset = softwareRenderer->outputBufferStride * 40 + 48; sgbOffset = softwareRenderer->outputBufferStride * 40 + 48;
} }
color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y + sgbOffset]; color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y + sgbOffset];
int x; int x = startX;
int p = 0; int p = 0;
switch (softwareRenderer->d.sgbRenderMode) { switch (softwareRenderer->d.sgbRenderMode) {
case 0: case 0:
@ -348,7 +351,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
p &= 3; p &= 3;
p <<= 2; p <<= 2;
} }
for (x = startX; x < ((startX + 7) & ~7) && x < endX; ++x) { for (; x < ((startX + 7) & ~7) && x < endX; ++x) {
row[x] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & 0x7F]]; row[x] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & 0x7F]];
} }
for (; x + 7 < (endX & ~7); x += 8) { for (; x + 7 < (endX & ~7); x += 8) {
@ -380,7 +383,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
case 1: case 1:
break; break;
case 2: case 2:
for (x = startX; x < ((startX + 7) & ~7) && x < endX; ++x) { for (; x < ((startX + 7) & ~7) && x < endX; ++x) {
row[x] = 0; row[x] = 0;
} }
for (; x + 7 < (endX & ~7); x += 8) { for (; x + 7 < (endX & ~7); x += 8) {
@ -398,7 +401,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
} }
break; break;
case 3: case 3:
for (x = startX; x < ((startX + 7) & ~7) && x < endX; ++x) { for (; x < ((startX + 7) & ~7) && x < endX; ++x) {
row[x] = softwareRenderer->palette[0]; row[x] = softwareRenderer->palette[0];
} }
for (; x + 7 < (endX & ~7); x += 8) { for (; x + 7 < (endX & ~7); x += 8) {
@ -498,7 +501,7 @@ static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer)
case SGB_PAL_TRN: case SGB_PAL_TRN:
case SGB_CHR_TRN: case SGB_CHR_TRN:
case SGB_PCT_TRN: case SGB_PCT_TRN:
if (softwareRenderer->sgbTransfer > 0) { if (softwareRenderer->sgbTransfer > 0 && softwareRenderer->sgbBorders) {
// Make sure every buffer sees this if we're multibuffering // Make sure every buffer sees this if we're multibuffering
_regenerateSGBBorder(softwareRenderer); _regenerateSGBBorder(softwareRenderer);
} }

View File

@ -15,7 +15,7 @@
#include <mgba-util/memory.h> #include <mgba-util/memory.h>
static void GBVideoDummyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model); static void GBVideoDummyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders);
static void GBVideoDummyRendererDeinit(struct GBVideoRenderer* renderer); static void GBVideoDummyRendererDeinit(struct GBVideoRenderer* renderer);
static uint8_t GBVideoDummyRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value); static uint8_t GBVideoDummyRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
static void GBVideoDummyRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data); static void GBVideoDummyRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data);
@ -72,6 +72,8 @@ void GBVideoInit(struct GBVideo* video) {
video->dmgPalette[2] = 0x294A; video->dmgPalette[2] = 0x294A;
video->dmgPalette[3] = 0x0000; video->dmgPalette[3] = 0x0000;
video->sgbBorders = true;
video->renderer->sgbCharRam = NULL; video->renderer->sgbCharRam = NULL;
video->renderer->sgbMapRam = NULL; video->renderer->sgbMapRam = NULL;
video->renderer->sgbPalRam = NULL; video->renderer->sgbPalRam = NULL;
@ -122,7 +124,7 @@ void GBVideoReset(struct GBVideo* video) {
video->palette[9 * 4 + 3] = video->dmgPalette[3]; video->palette[9 * 4 + 3] = video->dmgPalette[3];
video->renderer->deinit(video->renderer); video->renderer->deinit(video->renderer);
video->renderer->init(video->renderer, video->p->model); video->renderer->init(video->renderer, video->p->model, video->sgbBorders);
video->renderer->writePalette(video->renderer, 0, video->palette[0]); video->renderer->writePalette(video->renderer, 0, video->palette[0]);
video->renderer->writePalette(video->renderer, 1, video->palette[1]); video->renderer->writePalette(video->renderer, 1, video->palette[1]);
@ -174,7 +176,7 @@ void GBVideoAssociateRenderer(struct GBVideo* video, struct GBVideoRenderer* ren
renderer->sgbAttributes = video->renderer->sgbAttributes; renderer->sgbAttributes = video->renderer->sgbAttributes;
video->renderer = renderer; video->renderer = renderer;
renderer->vram = video->vram; renderer->vram = video->vram;
video->renderer->init(video->renderer, video->p->model); video->renderer->init(video->renderer, video->p->model, video->sgbBorders);
} }
static bool _statIRQAsserted(struct GBVideo* video, GBRegisterSTAT stat) { static bool _statIRQAsserted(struct GBVideo* video, GBRegisterSTAT stat) {
@ -676,9 +678,10 @@ void GBVideoWriteSGBPacket(struct GBVideo* video, uint8_t* data) {
video->renderer->writeSGBPacket(video->renderer, data); video->renderer->writeSGBPacket(video->renderer, data);
} }
static void GBVideoDummyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model) { static void GBVideoDummyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders) {
UNUSED(renderer); UNUSED(renderer);
UNUSED(model); UNUSED(model);
UNUSED(borders);
// Nothing to do // Nothing to do
} }
@ -833,5 +836,5 @@ void GBVideoDeserialize(struct GBVideo* video, const struct GBSerializedState* s
GBVideoSwitchBank(video, video->vramCurrentBank); GBVideoSwitchBank(video, video->vramCurrentBank);
video->renderer->deinit(video->renderer); video->renderer->deinit(video->renderer);
video->renderer->init(video->renderer, video->p->model); video->renderer->init(video->renderer, video->p->model, video->sgbBorders);
} }

View File

@ -295,6 +295,7 @@ void SettingsView::updateConfig() {
saveSetting("gb.bios", m_ui.gbBios); saveSetting("gb.bios", m_ui.gbBios);
saveSetting("gbc.bios", m_ui.gbcBios); saveSetting("gbc.bios", m_ui.gbcBios);
saveSetting("sgb.bios", m_ui.sgbBios); saveSetting("sgb.bios", m_ui.sgbBios);
saveSetting("sgb.borders", m_ui.sgbBorders);
saveSetting("useBios", m_ui.useBios); saveSetting("useBios", m_ui.useBios);
saveSetting("skipBios", m_ui.skipBios); saveSetting("skipBios", m_ui.skipBios);
saveSetting("audioBuffers", m_ui.audioBufferSize); saveSetting("audioBuffers", m_ui.audioBufferSize);
@ -410,6 +411,7 @@ void SettingsView::reloadConfig() {
loadSetting("gb.bios", m_ui.gbBios); loadSetting("gb.bios", m_ui.gbBios);
loadSetting("gbc.bios", m_ui.gbcBios); loadSetting("gbc.bios", m_ui.gbcBios);
loadSetting("sgb.bios", m_ui.sgbBios); loadSetting("sgb.bios", m_ui.sgbBios);
loadSetting("sgb.borders", m_ui.sgbBorders, true);
loadSetting("useBios", m_ui.useBios); loadSetting("useBios", m_ui.useBios);
loadSetting("skipBios", m_ui.skipBios); loadSetting("skipBios", m_ui.skipBios);
loadSetting("audioBuffers", m_ui.audioBufferSize); loadSetting("audioBuffers", m_ui.audioBufferSize);
@ -529,9 +531,9 @@ void SettingsView::saveSetting(const char* key, const QVariant& field) {
m_controller->updateOption(key); m_controller->updateOption(key);
} }
void SettingsView::loadSetting(const char* key, QAbstractButton* field) { void SettingsView::loadSetting(const char* key, QAbstractButton* field, bool defaultVal) {
QString option = loadSetting(key); QString option = loadSetting(key);
field->setChecked(!option.isNull() && option != "0"); field->setChecked((!option.isNull() && option != "0") || defaultVal);
} }
void SettingsView::loadSetting(const char* key, QComboBox* field) { void SettingsView::loadSetting(const char* key, QComboBox* field) {

View File

@ -69,7 +69,7 @@ private:
void saveSetting(const char* key, const QSpinBox*); void saveSetting(const char* key, const QSpinBox*);
void saveSetting(const char* key, const QVariant&); void saveSetting(const char* key, const QVariant&);
void loadSetting(const char* key, QAbstractButton*); void loadSetting(const char* key, QAbstractButton*, bool defaultVal = false);
void loadSetting(const char* key, QComboBox*); void loadSetting(const char* key, QComboBox*);
void loadSetting(const char* key, QDoubleSpinBox*); void loadSetting(const char* key, QDoubleSpinBox*);
void loadSetting(const char* key, QLineEdit*); void loadSetting(const char* key, QLineEdit*);

View File

@ -1098,14 +1098,86 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_32">
<property name="text">
<string>Super Game Boy model</string>
</property>
</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>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_33">
<property name="text">
<string>Game Boy Color model</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="cgbModel">
<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>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_28"> <widget class="QLabel" name="label_28">
<property name="text"> <property name="text">
<string>Default colors:</string> <string>Default colors:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_9"> <layout class="QHBoxLayout" name="horizontalLayout_9">
<item> <item>
<widget class="QFrame" name="color0"> <widget class="QFrame" name="color0">
@ -1185,21 +1257,28 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="4" column="0" colspan="2"> <item row="5" column="1">
<widget class="QCheckBox" name="sgbBorders">
<property name="text">
<string>Super Game Boy borders</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="Line" name="line_11"> <widget class="Line" name="line_11">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0"> <item row="7" column="0">
<widget class="QLabel" name="label_27"> <widget class="QLabel" name="label_27">
<property name="text"> <property name="text">
<string>Camera driver:</string> <string>Camera driver:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="7" column="1">
<widget class="QComboBox" name="cameraDriver"> <widget class="QComboBox" name="cameraDriver">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -1209,78 +1288,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="3" column="0" colspan="2">
<widget class="QLabel" name="label_32"> <widget class="Line" name="line_12">
<property name="text"> <property name="orientation">
<string>Super Game Boy model</string> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="label_33">
<property name="text">
<string>Game Boy Color model</string>
</property>
</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>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="cgbModel">
<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>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>