mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' (early part) into medusa
This commit is contained in:
commit
9b0d1bebb7
5
CHANGES
5
CHANGES
|
@ -83,6 +83,8 @@ Emulation fixes:
|
||||||
- GBA Video: Fix rare regression blending semitransparent sprites (fixes mgba.io/i/1876)
|
- GBA Video: Fix rare regression blending semitransparent sprites (fixes mgba.io/i/1876)
|
||||||
- GBA Video: Emulate sprite cycle limits in OpenGL renderer (fixes mgba.io/i/1635)
|
- GBA Video: Emulate sprite cycle limits in OpenGL renderer (fixes mgba.io/i/1635)
|
||||||
- GBA Video: Do not affect OBJ pixel priority when writing OBJWIN (fixes mgba.io/i/1890)
|
- GBA Video: Do not affect OBJ pixel priority when writing OBJWIN (fixes mgba.io/i/1890)
|
||||||
|
- GBA Video: Fix deferred blending when OBJWIN matches window (fixes mgba.io/i/1905)
|
||||||
|
- GBA Video: Fix mode 4 transparency in OpenGL (fixes mgba.io/i/1907)
|
||||||
- SM83: Emulate HALT bug
|
- SM83: Emulate HALT bug
|
||||||
Other fixes:
|
Other fixes:
|
||||||
- 3DS: Redo video sync to be more precise
|
- 3DS: Redo video sync to be more precise
|
||||||
|
@ -104,6 +106,9 @@ Other fixes:
|
||||||
- Qt: Add dummy English translation file (fixes mgba.io/i/1469)
|
- Qt: Add dummy English translation file (fixes mgba.io/i/1469)
|
||||||
- Qt: Fix Battle Chip view not displaying chips on some DPI settings
|
- Qt: Fix Battle Chip view not displaying chips on some DPI settings
|
||||||
- Qt: Fix camera image being upside-down sometimes (fixes mgba.io/i/829 again)
|
- Qt: Fix camera image being upside-down sometimes (fixes mgba.io/i/829 again)
|
||||||
|
- Qt: Fix drawing on macOS break when using OpenGL (fixes mgba.io/i/1899)
|
||||||
|
- Qt: Load/save bytes from memory viewer in the order visible (fixes mgba.io/i/1900)
|
||||||
|
- Qt: Fix stride changing when toggling SGB borders (fixes mgba.io/i/1898)
|
||||||
- mGUI: Fix closing down a game if an exit is signalled
|
- mGUI: Fix closing down a game if an exit is signalled
|
||||||
- mVL: Fix injecting accidentally draining non-injection buffer
|
- mVL: Fix injecting accidentally draining non-injection buffer
|
||||||
- SM83: Simplify register pair access on big endian
|
- SM83: Simplify register pair access on big endian
|
||||||
|
|
|
@ -17,9 +17,6 @@ struct GBVideoProxyRenderer {
|
||||||
struct GBVideoRenderer d;
|
struct GBVideoRenderer d;
|
||||||
struct GBVideoRenderer* backend;
|
struct GBVideoRenderer* backend;
|
||||||
struct mVideoLogger* logger;
|
struct mVideoLogger* logger;
|
||||||
|
|
||||||
struct GBObj objThisLine[40];
|
|
||||||
size_t oamMax;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void GBVideoProxyRendererCreate(struct GBVideoProxyRenderer* renderer, struct GBVideoRenderer* backend);
|
void GBVideoProxyRendererCreate(struct GBVideoProxyRenderer* renderer, struct GBVideoRenderer* backend);
|
||||||
|
|
|
@ -40,6 +40,9 @@ struct GBVideoSoftwareRenderer {
|
||||||
GBRegisterLCDC lcdc;
|
GBRegisterLCDC lcdc;
|
||||||
enum GBModel model;
|
enum GBModel model;
|
||||||
|
|
||||||
|
struct GBObj obj[10];
|
||||||
|
int objMax;
|
||||||
|
|
||||||
int16_t objOffsetX;
|
int16_t objOffsetX;
|
||||||
int16_t objOffsetY;
|
int16_t objOffsetY;
|
||||||
int16_t offsetScx;
|
int16_t offsetScx;
|
||||||
|
|
|
@ -77,7 +77,7 @@ struct GBVideoRenderer {
|
||||||
void (*writeVRAM)(struct GBVideoRenderer* renderer, uint16_t address);
|
void (*writeVRAM)(struct GBVideoRenderer* renderer, uint16_t address);
|
||||||
void (*writePalette)(struct GBVideoRenderer* renderer, int index, uint16_t value);
|
void (*writePalette)(struct GBVideoRenderer* renderer, int index, uint16_t value);
|
||||||
void (*writeOAM)(struct GBVideoRenderer* renderer, uint16_t oam);
|
void (*writeOAM)(struct GBVideoRenderer* renderer, uint16_t oam);
|
||||||
void (*drawRange)(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* objOnLine, size_t nObj);
|
void (*drawRange)(struct GBVideoRenderer* renderer, int startX, int endX, int y);
|
||||||
void (*finishScanline)(struct GBVideoRenderer* renderer, int y);
|
void (*finishScanline)(struct GBVideoRenderer* renderer, int y);
|
||||||
void (*finishFrame)(struct GBVideoRenderer* renderer);
|
void (*finishFrame)(struct GBVideoRenderer* renderer);
|
||||||
void (*enableSGBBorder)(struct GBVideoRenderer* renderer, bool enable);
|
void (*enableSGBBorder)(struct GBVideoRenderer* renderer, bool enable);
|
||||||
|
@ -139,7 +139,6 @@ struct GBVideo {
|
||||||
int vramCurrentBank;
|
int vramCurrentBank;
|
||||||
|
|
||||||
union GBOAM oam;
|
union GBOAM oam;
|
||||||
struct GBObj objThisLine[10];
|
|
||||||
int objMax;
|
int objMax;
|
||||||
|
|
||||||
int bcpIndex;
|
int bcpIndex;
|
||||||
|
|
|
@ -301,6 +301,12 @@ static void _GBCoreReloadConfigOption(struct mCore* core, const char* option, co
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (strcmp("sgb.borders", option) == 0) {
|
||||||
|
if (mCoreConfigGetIntValue(config, "sgb.borders", &fakeBool)) {
|
||||||
|
gb->video.sgbBorders = fakeBool;
|
||||||
|
gb->video.renderer->enableSGBBorder(gb->video.renderer, fakeBool);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBCoreDesiredVideoDimensions(const struct mCore* core, unsigned* width, unsigned* height) {
|
static void _GBCoreDesiredVideoDimensions(const struct mCore* core, unsigned* width, unsigned* height) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ static void GBVideoProxyRendererWriteSGBPacket(struct GBVideoRenderer* renderer,
|
||||||
static void GBVideoProxyRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address);
|
static void GBVideoProxyRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address);
|
||||||
static void GBVideoProxyRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam);
|
static void GBVideoProxyRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam);
|
||||||
static void GBVideoProxyRendererWritePalette(struct GBVideoRenderer* renderer, int address, uint16_t value);
|
static void GBVideoProxyRendererWritePalette(struct GBVideoRenderer* renderer, int address, uint16_t value);
|
||||||
static void GBVideoProxyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax);
|
static void GBVideoProxyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y);
|
||||||
static void GBVideoProxyRendererFinishScanline(struct GBVideoRenderer* renderer, int y);
|
static void GBVideoProxyRendererFinishScanline(struct GBVideoRenderer* renderer, int y);
|
||||||
static void GBVideoProxyRendererFinishFrame(struct GBVideoRenderer* renderer);
|
static void GBVideoProxyRendererFinishFrame(struct GBVideoRenderer* renderer);
|
||||||
static void GBVideoProxyRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable);
|
static void GBVideoProxyRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable);
|
||||||
|
@ -68,8 +68,6 @@ static void _reset(struct GBVideoProxyRenderer* proxyRenderer) {
|
||||||
memcpy(proxyRenderer->logger->oam, &proxyRenderer->d.oam->raw, GB_SIZE_OAM);
|
memcpy(proxyRenderer->logger->oam, &proxyRenderer->d.oam->raw, GB_SIZE_OAM);
|
||||||
memcpy(proxyRenderer->logger->vram, proxyRenderer->d.vram, GB_SIZE_VRAM);
|
memcpy(proxyRenderer->logger->vram, proxyRenderer->d.vram, GB_SIZE_VRAM);
|
||||||
|
|
||||||
proxyRenderer->oamMax = 0;
|
|
||||||
|
|
||||||
mVideoLoggerRendererReset(proxyRenderer->logger);
|
mVideoLoggerRendererReset(proxyRenderer->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +115,7 @@ void GBVideoProxyRendererDeinit(struct GBVideoRenderer* renderer) {
|
||||||
static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* item) {
|
static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* item) {
|
||||||
struct GBVideoProxyRenderer* proxyRenderer = logger->context;
|
struct GBVideoProxyRenderer* proxyRenderer = logger->context;
|
||||||
uint8_t sgbPacket[16];
|
uint8_t sgbPacket[16];
|
||||||
|
struct GBObj legacyBuffer[40];
|
||||||
switch (item->type) {
|
switch (item->type) {
|
||||||
case DIRTY_REGISTER:
|
case DIRTY_REGISTER:
|
||||||
proxyRenderer->backend->writeVideoRegister(proxyRenderer->backend, item->address, item->value);
|
proxyRenderer->backend->writeVideoRegister(proxyRenderer->backend, item->address, item->value);
|
||||||
|
@ -145,7 +144,7 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD
|
||||||
break;
|
break;
|
||||||
case DIRTY_RANGE:
|
case DIRTY_RANGE:
|
||||||
if (item->value < item->value2 && item->value2 <= GB_VIDEO_HORIZONTAL_PIXELS && item->address < GB_VIDEO_VERTICAL_PIXELS) {
|
if (item->value < item->value2 && item->value2 <= GB_VIDEO_HORIZONTAL_PIXELS && item->address < GB_VIDEO_VERTICAL_PIXELS) {
|
||||||
proxyRenderer->backend->drawRange(proxyRenderer->backend, item->value, item->value2, item->address, proxyRenderer->objThisLine, proxyRenderer->oamMax);
|
proxyRenderer->backend->drawRange(proxyRenderer->backend, item->value, item->value2, item->address);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DIRTY_FRAME:
|
case DIRTY_FRAME:
|
||||||
|
@ -154,12 +153,10 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD
|
||||||
case DIRTY_BUFFER:
|
case DIRTY_BUFFER:
|
||||||
switch (item->address) {
|
switch (item->address) {
|
||||||
case BUFFER_OAM:
|
case BUFFER_OAM:
|
||||||
proxyRenderer->oamMax = item->value2 / sizeof(struct GBObj);
|
if (item->value2 / sizeof(struct GBObj) > 40) {
|
||||||
if (proxyRenderer->oamMax > 40) {
|
|
||||||
proxyRenderer->oamMax = 0;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
logger->readData(logger, &proxyRenderer->objThisLine, item->value2, true);
|
logger->readData(logger, legacyBuffer, item->value2, true);
|
||||||
break;
|
break;
|
||||||
case BUFFER_SGB:
|
case BUFFER_SGB:
|
||||||
logger->readData(logger, sgbPacket, 16, true);
|
logger->readData(logger, sgbPacket, 16, true);
|
||||||
|
@ -228,12 +225,11 @@ void GBVideoProxyRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam
|
||||||
mVideoLoggerRendererWriteOAM(proxyRenderer->logger, oam, ((uint8_t*) proxyRenderer->d.oam->raw)[oam]);
|
mVideoLoggerRendererWriteOAM(proxyRenderer->logger, oam, ((uint8_t*) proxyRenderer->d.oam->raw)[oam]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBVideoProxyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax) {
|
void GBVideoProxyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y) {
|
||||||
struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer;
|
struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer;
|
||||||
if (!proxyRenderer->logger->block) {
|
if (!proxyRenderer->logger->block) {
|
||||||
proxyRenderer->backend->drawRange(proxyRenderer->backend, startX, endX, y, obj, oamMax);
|
proxyRenderer->backend->drawRange(proxyRenderer->backend, startX, endX, y);
|
||||||
}
|
}
|
||||||
mVideoLoggerWriteBuffer(proxyRenderer->logger, BUFFER_OAM, 0, oamMax * sizeof(*obj), obj);
|
|
||||||
mVideoLoggerRendererDrawRange(proxyRenderer->logger, startX, endX, y);
|
mVideoLoggerRendererDrawRange(proxyRenderer->logger, startX, endX, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* render
|
||||||
static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value);
|
static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value);
|
||||||
static void GBVideoSoftwareRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address);
|
static void GBVideoSoftwareRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address);
|
||||||
static void GBVideoSoftwareRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam);
|
static void GBVideoSoftwareRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam);
|
||||||
static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax);
|
static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y);
|
||||||
static void GBVideoSoftwareRendererFinishScanline(struct GBVideoRenderer* renderer, int y);
|
static void GBVideoSoftwareRendererFinishScanline(struct GBVideoRenderer* renderer, int y);
|
||||||
static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer);
|
static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer);
|
||||||
static void GBVideoSoftwareRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable);
|
static void GBVideoSoftwareRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable);
|
||||||
|
@ -499,7 +499,31 @@ static void GBVideoSoftwareRendererWriteOAM(struct GBVideoRenderer* renderer, ui
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax) {
|
static void _cleanOAM(struct GBVideoSoftwareRenderer* renderer, int y) {
|
||||||
|
// TODO: GBC differences
|
||||||
|
// TODO: Optimize
|
||||||
|
int spriteHeight = 8;
|
||||||
|
if (GBRegisterLCDCIsObjSize(renderer->lcdc)) {
|
||||||
|
spriteHeight = 16;
|
||||||
|
}
|
||||||
|
int o = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 40 && o < 10; ++i) {
|
||||||
|
uint8_t oy = renderer->d.oam->obj[i].y;
|
||||||
|
if (y < oy - 16 || y >= oy - 16 + spriteHeight) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// TODO: Sort
|
||||||
|
renderer->obj[o] = renderer->d.oam->obj[i];
|
||||||
|
++o;
|
||||||
|
if (o == 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
renderer->objMax = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y) {
|
||||||
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
|
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
|
||||||
softwareRenderer->lastY = y;
|
softwareRenderer->lastY = y;
|
||||||
softwareRenderer->lastX = endX;
|
softwareRenderer->lastX = endX;
|
||||||
|
@ -536,9 +560,12 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GBRegisterLCDCIsObjEnable(softwareRenderer->lcdc) && !softwareRenderer->d.disableOBJ) {
|
if (GBRegisterLCDCIsObjEnable(softwareRenderer->lcdc) && !softwareRenderer->d.disableOBJ) {
|
||||||
size_t i;
|
if (startX == 0) {
|
||||||
for (i = 0; i < oamMax; ++i) {
|
_cleanOAM(softwareRenderer, y);
|
||||||
GBVideoSoftwareRendererDrawObj(softwareRenderer, &obj[i], startX, endX, y);
|
}
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < softwareRenderer->objMax; ++i) {
|
||||||
|
GBVideoSoftwareRendererDrawObj(softwareRenderer, &softwareRenderer->obj[i], startX, endX, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -256,7 +256,6 @@ void GBSGBSerialize(struct GB* gb, struct GBSerializedState* state) {
|
||||||
if (gb->video.renderer->sgbAttributes) {
|
if (gb->video.renderer->sgbAttributes) {
|
||||||
memcpy(state->sgb.attributes, gb->video.renderer->sgbAttributes, sizeof(state->sgb.attributes));
|
memcpy(state->sgb.attributes, gb->video.renderer->sgbAttributes, sizeof(state->sgb.attributes));
|
||||||
}
|
}
|
||||||
gb->video.renderer->enableSGBBorder(gb->video.renderer, gb->video.sgbBorders);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBSGBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
|
void GBSGBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
|
||||||
|
|
|
@ -403,26 +403,18 @@ void _updateFrameCount(struct mTiming* timing, void* context, uint32_t cyclesLat
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _cleanOAM(struct GBVideo* video, int y) {
|
static void _cleanOAM(struct GBVideo* video, int y) {
|
||||||
// TODO: GBC differences
|
|
||||||
// TODO: Optimize
|
|
||||||
video->objMax = 0;
|
|
||||||
int spriteHeight = 8;
|
int spriteHeight = 8;
|
||||||
if (GBRegisterLCDCIsObjSize(video->p->memory.io[REG_LCDC])) {
|
if (GBRegisterLCDCIsObjSize(video->p->memory.io[REG_LCDC])) {
|
||||||
spriteHeight = 16;
|
spriteHeight = 16;
|
||||||
}
|
}
|
||||||
int o = 0;
|
int o = 0;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 40; ++i) {
|
for (i = 0; i < 40 && o < 10; ++i) {
|
||||||
uint8_t oy = video->oam.obj[i].y;
|
uint8_t oy = video->oam.obj[i].y;
|
||||||
if (y < oy - 16 || y >= oy - 16 + spriteHeight) {
|
if (y < oy - 16 || y >= oy - 16 + spriteHeight) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// TODO: Sort
|
|
||||||
video->objThisLine[o] = video->oam.obj[i];
|
|
||||||
++o;
|
++o;
|
||||||
if (o == 10) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
video->objMax = o;
|
video->objMax = o;
|
||||||
}
|
}
|
||||||
|
@ -442,7 +434,7 @@ void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate) {
|
||||||
oldX = 0;
|
oldX = 0;
|
||||||
}
|
}
|
||||||
if (video->frameskipCounter <= 0) {
|
if (video->frameskipCounter <= 0) {
|
||||||
video->renderer->drawRange(video->renderer, oldX, video->x, video->ly, video->objThisLine, video->objMax);
|
video->renderer->drawRange(video->renderer, oldX, video->x, video->ly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -391,7 +391,11 @@ static const char* const _renderMode4 =
|
||||||
" }\n"
|
" }\n"
|
||||||
" int address = charBase + (coord.x >> 8) + (coord.y >> 8) * size.x;\n"
|
" int address = charBase + (coord.x >> 8) + (coord.y >> 8) * size.x;\n"
|
||||||
" int twoEntries = texelFetch(vram, ivec2((address >> 1) & 255, address >> 9), 0).r;\n"
|
" int twoEntries = texelFetch(vram, ivec2((address >> 1) & 255, address >> 9), 0).r;\n"
|
||||||
" int paletteEntry = palette[(twoEntries >> (8 * (address & 1)) & 255)];\n"
|
" int entry = (twoEntries >> (8 * (address & 1))) & 255;\n"
|
||||||
|
" if (entry == 0) {\n"
|
||||||
|
" discard;\n"
|
||||||
|
" }\n"
|
||||||
|
" int paletteEntry = palette[entry];\n"
|
||||||
" color = vec4(PALETTE_ENTRY(paletteEntry), 1.);\n"
|
" color = vec4(PALETTE_ENTRY(paletteEntry), 1.);\n"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
|
|
|
@ -654,18 +654,19 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (softwareRenderer->forceTarget1 && (softwareRenderer->blendEffect == BLEND_DARKEN || softwareRenderer->blendEffect == BLEND_BRIGHTEN)) {
|
if (softwareRenderer->forceTarget1 && (softwareRenderer->blendEffect == BLEND_DARKEN || softwareRenderer->blendEffect == BLEND_BRIGHTEN)) {
|
||||||
uint32_t mask = FLAG_REBLEND | FLAG_IS_BACKGROUND;
|
|
||||||
uint32_t match = FLAG_REBLEND;
|
|
||||||
if (GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt)) {
|
|
||||||
mask |= FLAG_OBJWIN;
|
|
||||||
if (GBAWindowControlIsBlendEnable(softwareRenderer->objwin.packed)) {
|
|
||||||
match |= FLAG_OBJWIN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (w = 0; w < softwareRenderer->nWindows; ++w) {
|
for (w = 0; w < softwareRenderer->nWindows; ++w) {
|
||||||
int end = softwareRenderer->windows[w].endX;
|
int end = softwareRenderer->windows[w].endX;
|
||||||
if (!GBAWindowControlIsBlendEnable(softwareRenderer->windows[w].control.packed)) {
|
uint32_t mask = FLAG_REBLEND | FLAG_IS_BACKGROUND;
|
||||||
|
uint32_t match = FLAG_REBLEND;
|
||||||
|
bool objBlend = GBAWindowControlIsBlendEnable(softwareRenderer->objwin.packed);
|
||||||
|
bool winBlend = GBAWindowControlIsBlendEnable(softwareRenderer->windows[w].control.packed);
|
||||||
|
if (GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt) && objBlend != winBlend) {
|
||||||
|
mask |= FLAG_OBJWIN;
|
||||||
|
if (objBlend) {
|
||||||
|
match |= FLAG_OBJWIN;
|
||||||
|
}
|
||||||
|
} else if (!winBlend) {
|
||||||
x = end;
|
x = end;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,11 +267,23 @@ void CoreController::loadConfig(ConfigController* config) {
|
||||||
m_fastForwardMute = config->getOption("fastForwardMute", -1).toInt();
|
m_fastForwardMute = config->getOption("fastForwardMute", -1).toInt();
|
||||||
mCoreConfigCopyValue(&m_threadContext.core->config, config->config(), "volume");
|
mCoreConfigCopyValue(&m_threadContext.core->config, config->config(), "volume");
|
||||||
mCoreConfigCopyValue(&m_threadContext.core->config, config->config(), "mute");
|
mCoreConfigCopyValue(&m_threadContext.core->config, config->config(), "mute");
|
||||||
|
|
||||||
|
QSize sizeBefore = screenDimensions();
|
||||||
mCoreLoadForeignConfig(m_threadContext.core, config->config());
|
mCoreLoadForeignConfig(m_threadContext.core, config->config());
|
||||||
|
QSize sizeAfter = screenDimensions();
|
||||||
if (hasStarted()) {
|
if (hasStarted()) {
|
||||||
updateFastForward();
|
updateFastForward();
|
||||||
mCoreThreadRewindParamsChanged(&m_threadContext);
|
mCoreThreadRewindParamsChanged(&m_threadContext);
|
||||||
}
|
}
|
||||||
|
if (sizeBefore != sizeAfter) {
|
||||||
|
m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast<color_t*>(m_activeBuffer.data()), sizeAfter.width());
|
||||||
|
#ifdef M_CORE_GB
|
||||||
|
mCoreConfigSetIntValue(&m_threadContext.core->config, "sgb.borders", 0);
|
||||||
|
m_threadContext.core->reloadConfigOption(m_threadContext.core, "sgb.borders", nullptr);
|
||||||
|
mCoreConfigCopyValue(&m_threadContext.core->config, config->config(), "sgb.borders");
|
||||||
|
m_threadContext.core->reloadConfigOption(m_threadContext.core, "sgb.borders", nullptr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_DEBUGGERS
|
#ifdef USE_DEBUGGERS
|
||||||
|
|
|
@ -148,7 +148,9 @@ void DisplayGL::pauseDrawing() {
|
||||||
m_isDrawing = false;
|
m_isDrawing = false;
|
||||||
CoreController::Interrupter interrupter(m_context);
|
CoreController::Interrupter interrupter(m_context);
|
||||||
QMetaObject::invokeMethod(m_painter, "pause", Qt::BlockingQueuedConnection);
|
QMetaObject::invokeMethod(m_painter, "pause", Qt::BlockingQueuedConnection);
|
||||||
|
#ifndef Q_OS_MAC
|
||||||
setUpdatesEnabled(true);
|
setUpdatesEnabled(true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +159,9 @@ void DisplayGL::unpauseDrawing() {
|
||||||
m_isDrawing = true;
|
m_isDrawing = true;
|
||||||
CoreController::Interrupter interrupter(m_context);
|
CoreController::Interrupter interrupter(m_context);
|
||||||
QMetaObject::invokeMethod(m_painter, "unpause", Qt::BlockingQueuedConnection);
|
QMetaObject::invokeMethod(m_painter, "unpause", Qt::BlockingQueuedConnection);
|
||||||
|
#ifndef Q_OS_MAC
|
||||||
setUpdatesEnabled(false);
|
setUpdatesEnabled(false);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -246,7 +246,7 @@ QByteArray MemoryModel::serialize() {
|
||||||
for (uint32_t i = m_selection.first; i < m_selection.second; i += m_align) {
|
for (uint32_t i = m_selection.first; i < m_selection.second; i += m_align) {
|
||||||
quint16 datum = m_core->rawRead16(m_core, i, m_currentBank);
|
quint16 datum = m_core->rawRead16(m_core, i, m_currentBank);
|
||||||
char leDatum[2];
|
char leDatum[2];
|
||||||
STORE_16LE(datum, 0, (uint16_t*) leDatum);
|
STORE_16BE(datum, 0, (uint16_t*) leDatum);
|
||||||
bytes.append(leDatum, 2);
|
bytes.append(leDatum, 2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -254,7 +254,7 @@ QByteArray MemoryModel::serialize() {
|
||||||
for (uint32_t i = m_selection.first; i < m_selection.second; i += m_align) {
|
for (uint32_t i = m_selection.first; i < m_selection.second; i += m_align) {
|
||||||
quint32 datum = m_core->rawRead32(m_core, i, m_currentBank);
|
quint32 datum = m_core->rawRead32(m_core, i, m_currentBank);
|
||||||
char leDatum[4];
|
char leDatum[4];
|
||||||
STORE_32LE(datum, 0, (uint16_t*) leDatum);
|
STORE_32BE(datum, 0, (uint32_t*) leDatum);
|
||||||
bytes.append(leDatum, 4);
|
bytes.append(leDatum, 4);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -275,7 +275,7 @@ void MemoryModel::deserialize(const QByteArray& bytes) {
|
||||||
for (int i = 0; i < bytes.size(); i += m_align, addr += m_align) {
|
for (int i = 0; i < bytes.size(); i += m_align, addr += m_align) {
|
||||||
char leDatum[2]{ bytes[i], bytes[i + 1] };
|
char leDatum[2]{ bytes[i], bytes[i + 1] };
|
||||||
uint16_t datum;
|
uint16_t datum;
|
||||||
LOAD_16LE(datum, 0, leDatum);
|
LOAD_16BE(datum, 0, leDatum);
|
||||||
m_core->rawWrite16(m_core, addr, m_currentBank, datum);
|
m_core->rawWrite16(m_core, addr, m_currentBank, datum);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -283,7 +283,7 @@ void MemoryModel::deserialize(const QByteArray& bytes) {
|
||||||
for (int i = 0; i < bytes.size(); i += m_align, addr += m_align) {
|
for (int i = 0; i < bytes.size(); i += m_align, addr += m_align) {
|
||||||
char leDatum[4]{ bytes[i], bytes[i + 1], bytes[i + 2], bytes[i + 3] };
|
char leDatum[4]{ bytes[i], bytes[i + 1], bytes[i + 2], bytes[i + 3] };
|
||||||
uint32_t datum;
|
uint32_t datum;
|
||||||
LOAD_32LE(datum, 0, leDatum);
|
LOAD_32BE(datum, 0, leDatum);
|
||||||
m_core->rawWrite32(m_core, addr, m_currentBank, datum);
|
m_core->rawWrite32(m_core, addr, m_currentBank, datum);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -64,11 +64,17 @@ ArchitecturesInstallIn64BitMode=x64
|
||||||
ArchitecturesAllowed=x86 x64
|
ArchitecturesAllowed=x86 x64
|
||||||
|
|
||||||
[Languages]
|
[Languages]
|
||||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
|
||||||
Name: "french"; MessagesFile: "compiler:Languages\French.isl"
|
|
||||||
Name: "german"; MessagesFile: "compiler:Languages\German.isl"
|
Name: "german"; MessagesFile: "compiler:Languages\German.isl"
|
||||||
Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl"
|
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||||
Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
|
Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
|
||||||
|
Name: "french"; MessagesFile: "compiler:Languages\French.isl"
|
||||||
|
Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl"
|
||||||
|
Name: "japanese"; MessagesFile: "compiler:Languages\Japanese.isl"
|
||||||
|
Name: "korean"; MessagesFile: "compiler:Languages\Korean.isl"
|
||||||
|
Name: "dutch"; MessagesFile: "compiler:Languages\Dutch.isl"
|
||||||
|
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"
|
||||||
|
Name: "turkish"; MessagesFile: "compiler:Languages\Turkish.isl"
|
||||||
|
Name: "chinesesimplified"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"
|
||||||
|
|
||||||
[Tasks]
|
[Tasks]
|
||||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
|
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
|
||||||
|
@ -83,13 +89,13 @@ Source: "{#BinDir}\{#AppName2}-sdl.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "{#BinDir}\CHANGES.txt"; DestDir: "{app}\"; Flags: ignoreversion isreadme
|
Source: "{#BinDir}\CHANGES.txt"; DestDir: "{app}\"; Flags: ignoreversion isreadme
|
||||||
Source: "{#BinDir}\LICENSE.txt"; DestDir: "{app}\"; Flags: ignoreversion
|
Source: "{#BinDir}\LICENSE.txt"; DestDir: "{app}\"; Flags: ignoreversion
|
||||||
Source: "{#ResDir}\nointro.dat"; DestDir: "{app}\"; Flags: ignoreversion
|
Source: "{#ResDir}\nointro.dat"; DestDir: "{app}\"; Flags: ignoreversion
|
||||||
Source: "{#BinDir}\README.html"; DestDir: "{app}\"; Flags: ignoreversion isreadme; Languages: english italian spanish
|
Source: "{#BinDir}\README.html"; DestDir: "{app}\"; Flags: ignoreversion isreadme; Languages: not german
|
||||||
Source: "{#BinDir}\README_DE.html"; DestDir: "{app}\"; DestName: "LIESMICH.html"; Flags: ignoreversion isreadme; Languages: german
|
Source: "{#BinDir}\README_DE.html"; DestDir: "{app}\"; DestName: "LIESMICH.html"; Flags: ignoreversion isreadme; Languages: german
|
||||||
Source: "{#ResDir}\shaders\*"; DestDir: "{app}\shaders\"; Flags: ignoreversion recursesubdirs
|
Source: "{#ResDir}\shaders\*"; DestDir: "{app}\shaders\"; Flags: ignoreversion recursesubdirs
|
||||||
Source: "{#ResDir}\licenses\*"; DestDir: "{app}\licenses\"; Flags: ignoreversion recursesubdirs
|
Source: "{#ResDir}\licenses\*"; DestDir: "{app}\licenses\"; Flags: ignoreversion recursesubdirs
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
Name: "{commonstartmenu}\{#AppName}"; Filename: "{app}\{#AppName}.exe"
|
Name: "{commonstartmenu}\{#AppName}"; Filename: "{app}\{#AppName}.exe"; Check: not WizardNoIcons
|
||||||
Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppName}.exe"; Tasks: desktopicon
|
Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppName}.exe"; Tasks: desktopicon
|
||||||
|
|
||||||
[Run]
|
[Run]
|
||||||
|
@ -129,9 +135,15 @@ procedure InitializeWizard();
|
||||||
begin
|
begin
|
||||||
if ExpandConstant('{language}') = 'english' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
if ExpandConstant('{language}') = 'english' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
||||||
if ExpandConstant('{language}') = 'french' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
if ExpandConstant('{language}') = 'french' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
||||||
if ExpandConstant('{language}') = 'italian' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
if ExpandConstant('{language}') = 'german' then noReleaseWarning := 'Sie möchten eine Entwicklerversion von {#AppName} installieren.' + #13#10#13#10 + 'Entwicklerversionen können bislang noch nicht endeckte Fehler beinhalten. Bitte melden Sie alle Fehler, die Sie finden können, auf der GitHub-Projektseite.'; if ExpandConstant('{language}') = 'spanish' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
||||||
if ExpandConstant('{language}') = 'spanish' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
if ExpandConstant('{language}') = 'spanish' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
||||||
if ExpandConstant('{language}') = 'german' then noReleaseWarning := 'Sie möchten eine Entwicklerversion von {#AppName} installieren.' + #13#10#13#10 + 'Entwicklerversionen können bislang noch nicht endeckte Fehler beinhalten. Bitte melden Sie alle Fehler, die Sie finden können, auf der GitHub-Projektseite.';
|
if ExpandConstant('{language}') = 'italian' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
||||||
|
if ExpandConstant('{language}') = 'japanese' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
||||||
|
if ExpandConstant('{language}') = 'korean' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
||||||
|
if ExpandConstant('{language}') = 'dutch' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
||||||
|
if ExpandConstant('{language}') = 'russian' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
||||||
|
if ExpandConstant('{language}') = 'turkish' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
||||||
|
if ExpandConstant('{language}') = 'chinesesimplified' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.';
|
||||||
MsgBox(noReleaseWarning, mbInformation, MB_OK);
|
MsgBox(noReleaseWarning, mbInformation, MB_OK);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
Loading…
Reference in New Issue