mirror of https://github.com/mgba-emu/mgba.git
Qt: Add layer placement features
This commit is contained in:
parent
8ea524d9e6
commit
67a135e5e7
1
CHANGES
1
CHANGES
|
@ -49,6 +49,7 @@ Misc:
|
||||||
- GBA Memory: 64 MiB GBA Video cartridge support
|
- GBA Memory: 64 MiB GBA Video cartridge support
|
||||||
- PSP2: Use system enter key by default
|
- PSP2: Use system enter key by default
|
||||||
- 3DS: Remove deprecated CSND interface
|
- 3DS: Remove deprecated CSND interface
|
||||||
|
- Qt: Options to mess around with layer placement
|
||||||
|
|
||||||
0.6.3: (2017-04-14)
|
0.6.3: (2017-04-14)
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
|
|
@ -153,6 +153,7 @@ struct mCore {
|
||||||
size_t (*listAudioChannels)(const struct mCore*, const struct mCoreChannelInfo**);
|
size_t (*listAudioChannels)(const struct mCore*, const struct mCoreChannelInfo**);
|
||||||
void (*enableVideoLayer)(struct mCore*, size_t id, bool enable);
|
void (*enableVideoLayer)(struct mCore*, size_t id, bool enable);
|
||||||
void (*enableAudioChannel)(struct mCore*, size_t id, bool enable);
|
void (*enableAudioChannel)(struct mCore*, size_t id, bool enable);
|
||||||
|
void (*adjustVideoLayer)(struct mCore*, size_t id, int32_t x, int32_t y);
|
||||||
|
|
||||||
#ifndef MINIMAL_CORE
|
#ifndef MINIMAL_CORE
|
||||||
void (*startVideoLog)(struct mCore*, struct mVideoLogContext*);
|
void (*startVideoLog)(struct mCore*, struct mVideoLogContext*);
|
||||||
|
|
|
@ -38,6 +38,13 @@ struct GBVideoSoftwareRenderer {
|
||||||
GBRegisterLCDC lcdc;
|
GBRegisterLCDC lcdc;
|
||||||
enum GBModel model;
|
enum GBModel model;
|
||||||
|
|
||||||
|
int16_t objOffsetX;
|
||||||
|
int16_t objOffsetY;
|
||||||
|
int16_t offsetScx;
|
||||||
|
int16_t offsetScy;
|
||||||
|
int16_t offsetWx;
|
||||||
|
int16_t offsetWy;
|
||||||
|
|
||||||
int sgbTransfer;
|
int sgbTransfer;
|
||||||
uint8_t sgbPacket[128];
|
uint8_t sgbPacket[128];
|
||||||
uint8_t sgbCommandHeader;
|
uint8_t sgbCommandHeader;
|
||||||
|
|
|
@ -44,6 +44,8 @@ struct GBAVideoSoftwareBackground {
|
||||||
int32_t sy;
|
int32_t sy;
|
||||||
int yCache;
|
int yCache;
|
||||||
uint16_t mapCache[64];
|
uint16_t mapCache[64];
|
||||||
|
int32_t offsetX;
|
||||||
|
int32_t offsetY;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BlendEffect {
|
enum BlendEffect {
|
||||||
|
@ -159,6 +161,8 @@ struct GBAVideoSoftwareRenderer {
|
||||||
int oamDirty;
|
int oamDirty;
|
||||||
int oamMax;
|
int oamMax;
|
||||||
struct GBAVideoSoftwareSprite sprites[128];
|
struct GBAVideoSoftwareSprite sprites[128];
|
||||||
|
int16_t objOffsetX;
|
||||||
|
int16_t objOffsetY;
|
||||||
|
|
||||||
uint32_t scanlineDirty[5];
|
uint32_t scanlineDirty[5];
|
||||||
uint16_t nextIo[REG_SOUND1CNT_LO];
|
uint16_t nextIo[REG_SOUND1CNT_LO];
|
||||||
|
|
|
@ -791,13 +791,17 @@ static bool _GBCoreSavedataRestore(struct mCore* core, const void* sram, size_t
|
||||||
|
|
||||||
static size_t _GBCoreListVideoLayers(const struct mCore* core, const struct mCoreChannelInfo** info) {
|
static size_t _GBCoreListVideoLayers(const struct mCore* core, const struct mCoreChannelInfo** info) {
|
||||||
UNUSED(core);
|
UNUSED(core);
|
||||||
|
if (info) {
|
||||||
*info = _GBVideoLayers;
|
*info = _GBVideoLayers;
|
||||||
|
}
|
||||||
return sizeof(_GBVideoLayers) / sizeof(*_GBVideoLayers);
|
return sizeof(_GBVideoLayers) / sizeof(*_GBVideoLayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t _GBCoreListAudioChannels(const struct mCore* core, const struct mCoreChannelInfo** info) {
|
static size_t _GBCoreListAudioChannels(const struct mCore* core, const struct mCoreChannelInfo** info) {
|
||||||
UNUSED(core);
|
UNUSED(core);
|
||||||
|
if (info) {
|
||||||
*info = _GBAudioChannels;
|
*info = _GBAudioChannels;
|
||||||
|
}
|
||||||
return sizeof(_GBAudioChannels) / sizeof(*_GBAudioChannels);
|
return sizeof(_GBAudioChannels) / sizeof(*_GBAudioChannels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -832,6 +836,26 @@ static void _GBCoreEnableAudioChannel(struct mCore* core, size_t id, bool enable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _GBCoreAdjustVideoLayer(struct mCore* core, size_t id, int32_t x, int32_t y) {
|
||||||
|
struct GBCore* gbcore = (struct GBCore*) core;
|
||||||
|
switch (id) {
|
||||||
|
case 0:
|
||||||
|
gbcore->renderer.offsetScx = x;
|
||||||
|
gbcore->renderer.offsetScy = y;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
gbcore->renderer.offsetWx = x;
|
||||||
|
gbcore->renderer.offsetWy = y;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
gbcore->renderer.objOffsetX = x;
|
||||||
|
gbcore->renderer.objOffsetY = y;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef MINIMAL_CORE
|
#ifndef MINIMAL_CORE
|
||||||
static void _GBCoreStartVideoLog(struct mCore* core, struct mVideoLogContext* context) {
|
static void _GBCoreStartVideoLog(struct mCore* core, struct mVideoLogContext* context) {
|
||||||
struct GBCore* gbcore = (struct GBCore*) core;
|
struct GBCore* gbcore = (struct GBCore*) core;
|
||||||
|
@ -934,6 +958,7 @@ struct mCore* GBCoreCreate(void) {
|
||||||
core->listAudioChannels = _GBCoreListAudioChannels;
|
core->listAudioChannels = _GBCoreListAudioChannels;
|
||||||
core->enableVideoLayer = _GBCoreEnableVideoLayer;
|
core->enableVideoLayer = _GBCoreEnableVideoLayer;
|
||||||
core->enableAudioChannel = _GBCoreEnableAudioChannel;
|
core->enableAudioChannel = _GBCoreEnableAudioChannel;
|
||||||
|
core->adjustVideoLayer = _GBCoreAdjustVideoLayer;
|
||||||
#ifndef MINIMAL_CORE
|
#ifndef MINIMAL_CORE
|
||||||
core->startVideoLog = _GBCoreStartVideoLog;
|
core->startVideoLog = _GBCoreStartVideoLog;
|
||||||
core->endVideoLog = _GBCoreEndVideoLog;
|
core->endVideoLog = _GBCoreEndVideoLog;
|
||||||
|
|
|
@ -198,6 +198,13 @@ static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum G
|
||||||
softwareRenderer->sgbTransfer = 0;
|
softwareRenderer->sgbTransfer = 0;
|
||||||
softwareRenderer->sgbCommandHeader = 0;
|
softwareRenderer->sgbCommandHeader = 0;
|
||||||
softwareRenderer->sgbBorders = sgbBorders;
|
softwareRenderer->sgbBorders = sgbBorders;
|
||||||
|
softwareRenderer->objOffsetX = 0;
|
||||||
|
softwareRenderer->objOffsetY = 0;
|
||||||
|
softwareRenderer->offsetScx = 0;
|
||||||
|
softwareRenderer->offsetScy = 0;
|
||||||
|
softwareRenderer->offsetWx = 0;
|
||||||
|
softwareRenderer->offsetWy = 0;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 64; ++i) {
|
for (i = 0; i < 64; ++i) {
|
||||||
softwareRenderer->lookup[i] = i;
|
softwareRenderer->lookup[i] = i;
|
||||||
|
@ -471,7 +478,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
|
||||||
int wy = softwareRenderer->wy + softwareRenderer->currentWy;
|
int wy = softwareRenderer->wy + softwareRenderer->currentWy;
|
||||||
if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && wy <= y && endX >= softwareRenderer->wx - 7) {
|
if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && wy <= y && endX >= softwareRenderer->wx - 7) {
|
||||||
if (softwareRenderer->wx - 7 > 0 && !softwareRenderer->d.disableBG) {
|
if (softwareRenderer->wx - 7 > 0 && !softwareRenderer->d.disableBG) {
|
||||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, softwareRenderer->wx - 7, softwareRenderer->scx, softwareRenderer->scy + y);
|
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, softwareRenderer->wx - 7, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy);
|
||||||
}
|
}
|
||||||
|
|
||||||
maps = &softwareRenderer->d.vram[GB_BASE_MAP];
|
maps = &softwareRenderer->d.vram[GB_BASE_MAP];
|
||||||
|
@ -479,10 +486,10 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
|
||||||
maps += GB_SIZE_MAP;
|
maps += GB_SIZE_MAP;
|
||||||
}
|
}
|
||||||
if (!softwareRenderer->d.disableWIN) {
|
if (!softwareRenderer->d.disableWIN) {
|
||||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, softwareRenderer->wx - 7, endX, 7 - softwareRenderer->wx, y - wy);
|
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, softwareRenderer->wx - 7, endX, 7 - softwareRenderer->wx - softwareRenderer->offsetWx, y - wy - softwareRenderer->offsetWy);
|
||||||
}
|
}
|
||||||
} else if (!softwareRenderer->d.disableBG) {
|
} else if (!softwareRenderer->d.disableBG) {
|
||||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx, softwareRenderer->scy + y);
|
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy);
|
||||||
}
|
}
|
||||||
} else if (!softwareRenderer->d.disableBG) {
|
} else if (!softwareRenderer->d.disableBG) {
|
||||||
memset(&softwareRenderer->row[startX], 0, endX - startX);
|
memset(&softwareRenderer->row[startX], 0, endX - startX);
|
||||||
|
@ -778,15 +785,16 @@ static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int startX, int endX, int y) {
|
static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int startX, int endX, int y) {
|
||||||
int ix = obj->x - 8;
|
int objX = obj->x + renderer->objOffsetX;
|
||||||
|
int ix = objX - 8;
|
||||||
if (endX < ix || startX >= ix + 8) {
|
if (endX < ix || startX >= ix + 8) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (obj->x < endX) {
|
if (objX < endX) {
|
||||||
endX = obj->x;
|
endX = objX;
|
||||||
}
|
}
|
||||||
if (obj->x - 8 > startX) {
|
if (objX - 8 > startX) {
|
||||||
startX = obj->x - 8;
|
startX = objX - 8;
|
||||||
}
|
}
|
||||||
if (startX < 0) {
|
if (startX < 0) {
|
||||||
startX = 0;
|
startX = 0;
|
||||||
|
@ -794,14 +802,15 @@ static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* rende
|
||||||
uint8_t* data = renderer->d.vram;
|
uint8_t* data = renderer->d.vram;
|
||||||
int tileOffset = 0;
|
int tileOffset = 0;
|
||||||
int bottomY;
|
int bottomY;
|
||||||
|
int objY = obj->y + renderer->objOffsetY;
|
||||||
if (GBObjAttributesIsYFlip(obj->attr)) {
|
if (GBObjAttributesIsYFlip(obj->attr)) {
|
||||||
bottomY = 7 - ((y - obj->y - 16) & 7);
|
bottomY = 7 - ((y - objY - 16) & 7);
|
||||||
if (GBRegisterLCDCIsObjSize(renderer->lcdc) && y - obj->y < -8) {
|
if (GBRegisterLCDCIsObjSize(renderer->lcdc) && y - objY < -8) {
|
||||||
++tileOffset;
|
++tileOffset;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bottomY = (y - obj->y - 16) & 7;
|
bottomY = (y - objY - 16) & 7;
|
||||||
if (GBRegisterLCDCIsObjSize(renderer->lcdc) && y - obj->y >= -8) {
|
if (GBRegisterLCDCIsObjSize(renderer->lcdc) && y - objY >= -8) {
|
||||||
++tileOffset;
|
++tileOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -825,12 +834,12 @@ static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* rende
|
||||||
}
|
}
|
||||||
int bottomX;
|
int bottomX;
|
||||||
int x = startX;
|
int x = startX;
|
||||||
if ((x - obj->x) & 7) {
|
if ((x - objX) & 7) {
|
||||||
for (; x < endX; ++x) {
|
for (; x < endX; ++x) {
|
||||||
if (GBObjAttributesIsXFlip(obj->attr)) {
|
if (GBObjAttributesIsXFlip(obj->attr)) {
|
||||||
bottomX = (x - obj->x) & 7;
|
bottomX = (x - objX) & 7;
|
||||||
} else {
|
} else {
|
||||||
bottomX = 7 - ((x - obj->x) & 7);
|
bottomX = 7 - ((x - objX) & 7);
|
||||||
}
|
}
|
||||||
int objTile = obj->tile + tileOffset;
|
int objTile = obj->tile + tileOffset;
|
||||||
uint8_t tileDataLower = data[(objTile * 8 + bottomY) * 2];
|
uint8_t tileDataLower = data[(objTile * 8 + bottomY) * 2];
|
||||||
|
|
|
@ -795,13 +795,17 @@ static bool _GBACoreSavedataRestore(struct mCore* core, const void* sram, size_t
|
||||||
|
|
||||||
static size_t _GBACoreListVideoLayers(const struct mCore* core, const struct mCoreChannelInfo** info) {
|
static size_t _GBACoreListVideoLayers(const struct mCore* core, const struct mCoreChannelInfo** info) {
|
||||||
UNUSED(core);
|
UNUSED(core);
|
||||||
|
if (info) {
|
||||||
*info = _GBAVideoLayers;
|
*info = _GBAVideoLayers;
|
||||||
|
}
|
||||||
return sizeof(_GBAVideoLayers) / sizeof(*_GBAVideoLayers);
|
return sizeof(_GBAVideoLayers) / sizeof(*_GBAVideoLayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t _GBACoreListAudioChannels(const struct mCore* core, const struct mCoreChannelInfo** info) {
|
static size_t _GBACoreListAudioChannels(const struct mCore* core, const struct mCoreChannelInfo** info) {
|
||||||
UNUSED(core);
|
UNUSED(core);
|
||||||
|
if (info) {
|
||||||
*info = _GBAAudioChannels;
|
*info = _GBAAudioChannels;
|
||||||
|
}
|
||||||
return sizeof(_GBAAudioChannels) / sizeof(*_GBAAudioChannels);
|
return sizeof(_GBAAudioChannels) / sizeof(*_GBAAudioChannels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -841,6 +845,27 @@ static void _GBACoreEnableAudioChannel(struct mCore* core, size_t id, bool enabl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _GBACoreAdjustVideoLayer(struct mCore* core, size_t id, int32_t x, int32_t y) {
|
||||||
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
|
switch (id) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
gbacore->renderer.bg[id].offsetX = x;
|
||||||
|
gbacore->renderer.bg[id].offsetY = y;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
gbacore->renderer.objOffsetX = x;
|
||||||
|
gbacore->renderer.objOffsetY = y;
|
||||||
|
gbacore->renderer.oamDirty = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(gbacore->renderer.scanlineDirty, 0xFFFFFFFF, sizeof(gbacore->renderer.scanlineDirty));
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef MINIMAL_CORE
|
#ifndef MINIMAL_CORE
|
||||||
static void _GBACoreStartVideoLog(struct mCore* core, struct mVideoLogContext* context) {
|
static void _GBACoreStartVideoLog(struct mCore* core, struct mVideoLogContext* context) {
|
||||||
struct GBACore* gbacore = (struct GBACore*) core;
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
|
@ -946,6 +971,7 @@ struct mCore* GBACoreCreate(void) {
|
||||||
core->listAudioChannels = _GBACoreListAudioChannels;
|
core->listAudioChannels = _GBACoreListAudioChannels;
|
||||||
core->enableVideoLayer = _GBACoreEnableVideoLayer;
|
core->enableVideoLayer = _GBACoreEnableVideoLayer;
|
||||||
core->enableAudioChannel = _GBACoreEnableAudioChannel;
|
core->enableAudioChannel = _GBACoreEnableAudioChannel;
|
||||||
|
core->adjustVideoLayer = _GBACoreAdjustVideoLayer;
|
||||||
#ifndef MINIMAL_CORE
|
#ifndef MINIMAL_CORE
|
||||||
core->startVideoLog = _GBACoreStartVideoLog;
|
core->startVideoLog = _GBACoreStartVideoLog;
|
||||||
core->endVideoLog = _GBACoreEndVideoLog;
|
core->endVideoLog = _GBACoreEndVideoLog;
|
||||||
|
|
|
@ -446,13 +446,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y) {
|
void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y) {
|
||||||
int inX = (renderer->start + background->x) & 0x1FF;
|
int inX = (renderer->start + background->x - background->offsetX) & 0x1FF;
|
||||||
int length = renderer->end - renderer->start;
|
int length = renderer->end - renderer->start;
|
||||||
if (background->mosaic) {
|
if (background->mosaic) {
|
||||||
int mosaicV = GBAMosaicControlGetBgV(renderer->mosaic) + 1;
|
int mosaicV = GBAMosaicControlGetBgV(renderer->mosaic) + 1;
|
||||||
y -= y % mosaicV;
|
y -= y % mosaicV;
|
||||||
}
|
}
|
||||||
int inY = y + background->y;
|
int inY = y + background->y - background->offsetY;
|
||||||
uint16_t mapData;
|
uint16_t mapData;
|
||||||
|
|
||||||
unsigned yBase = inY & 0xF8;
|
unsigned yBase = inY & 0xF8;
|
||||||
|
|
|
@ -147,6 +147,7 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
|
||||||
}
|
}
|
||||||
int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23;
|
int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23;
|
||||||
x >>= 23;
|
x >>= 23;
|
||||||
|
x += renderer->objOffsetX;
|
||||||
uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1];
|
uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1];
|
||||||
bool align = GBAObjAttributesAIs256Color(sprite->a) && !GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt);
|
bool align = GBAObjAttributesAIs256Color(sprite->a) && !GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt);
|
||||||
unsigned charBase = (GBAObjAttributesCGetTile(sprite->c) & ~align) * 0x20;
|
unsigned charBase = (GBAObjAttributesCGetTile(sprite->c) & ~align) * 0x20;
|
||||||
|
@ -185,7 +186,7 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int inY = y - (int) GBAObjAttributesAGetY(sprite->a);
|
int inY = y - ((int) GBAObjAttributesAGetY(sprite->a) + renderer->objOffsetY);
|
||||||
int stride = GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? (width >> !GBAObjAttributesAIs256Color(sprite->a)) : 0x80;
|
int stride = GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? (width >> !GBAObjAttributesAIs256Color(sprite->a)) : 0x80;
|
||||||
|
|
||||||
uint32_t current;
|
uint32_t current;
|
||||||
|
|
|
@ -114,6 +114,9 @@ static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer) {
|
||||||
softwareRenderer->mosaic = 0;
|
softwareRenderer->mosaic = 0;
|
||||||
softwareRenderer->nextY = 0;
|
softwareRenderer->nextY = 0;
|
||||||
|
|
||||||
|
softwareRenderer->objOffsetX = 0;
|
||||||
|
softwareRenderer->objOffsetY = 0;
|
||||||
|
|
||||||
memset(softwareRenderer->scanlineDirty, 0xFFFFFFFF, sizeof(softwareRenderer->scanlineDirty));
|
memset(softwareRenderer->scanlineDirty, 0xFFFFFFFF, sizeof(softwareRenderer->scanlineDirty));
|
||||||
memset(softwareRenderer->cache, 0, sizeof(softwareRenderer->cache));
|
memset(softwareRenderer->cache, 0, sizeof(softwareRenderer->cache));
|
||||||
memset(softwareRenderer->nextIo, 0, sizeof(softwareRenderer->nextIo));
|
memset(softwareRenderer->nextIo, 0, sizeof(softwareRenderer->nextIo));
|
||||||
|
@ -142,6 +145,8 @@ static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer) {
|
||||||
bg->sx = 0;
|
bg->sx = 0;
|
||||||
bg->sy = 0;
|
bg->sy = 0;
|
||||||
bg->yCache = -1;
|
bg->yCache = -1;
|
||||||
|
bg->offsetX = 0;
|
||||||
|
bg->offsetY = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,8 +512,9 @@ static void _cleanOAM(struct GBAVideoSoftwareRenderer* renderer) {
|
||||||
height <<= GBAObjAttributesAGetDoubleSize(obj.a);
|
height <<= GBAObjAttributesAGetDoubleSize(obj.a);
|
||||||
}
|
}
|
||||||
if (GBAObjAttributesAGetY(obj.a) < VIDEO_VERTICAL_PIXELS || GBAObjAttributesAGetY(obj.a) + height >= VIDEO_VERTICAL_TOTAL_PIXELS) {
|
if (GBAObjAttributesAGetY(obj.a) < VIDEO_VERTICAL_PIXELS || GBAObjAttributesAGetY(obj.a) + height >= VIDEO_VERTICAL_TOTAL_PIXELS) {
|
||||||
renderer->sprites[oamMax].y = GBAObjAttributesAGetY(obj.a);
|
int y = GBAObjAttributesAGetY(obj.a) + renderer->objOffsetY;
|
||||||
renderer->sprites[oamMax].endY = GBAObjAttributesAGetY(obj.a) + height;
|
renderer->sprites[oamMax].y = y;
|
||||||
|
renderer->sprites[oamMax].endY = y + height;
|
||||||
renderer->sprites[oamMax].obj = obj;
|
renderer->sprites[oamMax].obj = obj;
|
||||||
++oamMax;
|
++oamMax;
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,7 @@ set(SOURCE_FILES
|
||||||
ObjView.cpp
|
ObjView.cpp
|
||||||
OverrideView.cpp
|
OverrideView.cpp
|
||||||
PaletteView.cpp
|
PaletteView.cpp
|
||||||
|
PlacementControl.cpp
|
||||||
PrinterView.cpp
|
PrinterView.cpp
|
||||||
RegisterView.cpp
|
RegisterView.cpp
|
||||||
ROMInfo.cpp
|
ROMInfo.cpp
|
||||||
|
@ -135,6 +136,7 @@ set(UI_FILES
|
||||||
ObjView.ui
|
ObjView.ui
|
||||||
OverrideView.ui
|
OverrideView.ui
|
||||||
PaletteView.ui
|
PaletteView.ui
|
||||||
|
PlacementControl.ui
|
||||||
PrinterView.ui
|
PrinterView.ui
|
||||||
ROMInfo.ui
|
ROMInfo.ui
|
||||||
SensorView.ui
|
SensorView.ui
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/* Copyright (c) 2013-2018 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 "PlacementControl.h"
|
||||||
|
|
||||||
|
#include "CoreController.h"
|
||||||
|
|
||||||
|
#include <QGridLayout>
|
||||||
|
|
||||||
|
#include <mgba/core/core.h>
|
||||||
|
|
||||||
|
using namespace QGBA;
|
||||||
|
|
||||||
|
PlacementControl::PlacementControl(std::shared_ptr<CoreController> controller, QWidget* parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, m_controller(controller)
|
||||||
|
{
|
||||||
|
m_ui.setupUi(this);
|
||||||
|
|
||||||
|
connect(m_ui.offsetX, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this](int x) {
|
||||||
|
adjustLayer(-1, x, m_ui.offsetY->value());
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_ui.offsetY, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this](int y) {
|
||||||
|
adjustLayer(-1, m_ui.offsetX->value(), y);
|
||||||
|
});
|
||||||
|
|
||||||
|
QGridLayout* grid = static_cast<QGridLayout*>(layout());
|
||||||
|
CoreController::Interrupter interrupter(m_controller);
|
||||||
|
const mCoreChannelInfo* info;
|
||||||
|
size_t nVideo = m_controller->thread()->core->listVideoLayers(m_controller->thread()->core, &info);
|
||||||
|
for (size_t i = 0; i < nVideo; ++i) {
|
||||||
|
QSpinBox* offsetX = new QSpinBox;
|
||||||
|
QSpinBox* offsetY = new QSpinBox;
|
||||||
|
|
||||||
|
offsetX->setWrapping(true);
|
||||||
|
offsetX->setMaximum(127);
|
||||||
|
offsetX->setMinimum(-128);
|
||||||
|
offsetX->setAccelerated(true);
|
||||||
|
|
||||||
|
offsetY->setWrapping(true);
|
||||||
|
offsetY->setMaximum(127);
|
||||||
|
offsetY->setMinimum(-128);
|
||||||
|
offsetY->setAccelerated(true);
|
||||||
|
|
||||||
|
m_layers.append(qMakePair(offsetX, offsetY));
|
||||||
|
int row = grid->rowCount();
|
||||||
|
grid->addWidget(new QLabel(QString(info[i].visibleName)), row, 0, Qt::AlignRight);
|
||||||
|
grid->addWidget(offsetX, row, 1);
|
||||||
|
grid->addWidget(offsetY, row, 2);
|
||||||
|
|
||||||
|
connect(offsetX, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this, i, offsetY](int x) {
|
||||||
|
adjustLayer(i, x, offsetY->value());
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(offsetY, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this, i, offsetX](int y) {
|
||||||
|
adjustLayer(i, offsetX->value(), y);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlacementControl::adjustLayer(int layer, int32_t x, int32_t y) {
|
||||||
|
CoreController::Interrupter interrupter(m_controller);
|
||||||
|
mCore* core = m_controller->thread()->core;
|
||||||
|
size_t nVideo = core->listVideoLayers(core, nullptr);
|
||||||
|
|
||||||
|
if (layer < 0) {
|
||||||
|
for (size_t i = 0; i < nVideo; ++i) {
|
||||||
|
core->adjustVideoLayer(core, i, x + m_layers[i].first->value(), y + m_layers[i].second->value());
|
||||||
|
}
|
||||||
|
} else if ((size_t) layer < nVideo) {
|
||||||
|
core->adjustVideoLayer(core, layer, x + m_ui.offsetX->value(), y + m_ui.offsetY->value());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* Copyright (c) 2013-2018 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 <QDialog>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "ui_PlacementControl.h"
|
||||||
|
|
||||||
|
namespace QGBA {
|
||||||
|
|
||||||
|
class CoreController;
|
||||||
|
|
||||||
|
class PlacementControl : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
PlacementControl(std::shared_ptr<CoreController>, QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void adjustLayer(int layer, int32_t x, int32_t y);
|
||||||
|
|
||||||
|
std::shared_ptr<CoreController> m_controller;
|
||||||
|
QList<QPair<QSpinBox*, QSpinBox*>> m_layers;
|
||||||
|
|
||||||
|
Ui::PlacementControl m_ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>PlacementControl</class>
|
||||||
|
<widget class="QDialog" name="PlacementControl">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>202</width>
|
||||||
|
<height>72</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Adjust placement</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="1" column="0" alignment="Qt::AlignRight">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>All</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QSpinBox" name="offsetX">
|
||||||
|
<property name="wrapping">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="accelerated">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-128</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>127</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QSpinBox" name="offsetY">
|
||||||
|
<property name="wrapping">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="accelerated">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-128</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>127</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" alignment="Qt::AlignRight">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Offset</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1" alignment="Qt::AlignHCenter">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>X</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2" alignment="Qt::AlignHCenter">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Y</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -42,6 +42,7 @@
|
||||||
#include "OverrideView.h"
|
#include "OverrideView.h"
|
||||||
#include "ObjView.h"
|
#include "ObjView.h"
|
||||||
#include "PaletteView.h"
|
#include "PaletteView.h"
|
||||||
|
#include "PlacementControl.h"
|
||||||
#include "PrinterView.h"
|
#include "PrinterView.h"
|
||||||
#include "ROMInfo.h"
|
#include "ROMInfo.h"
|
||||||
#include "SensorView.h"
|
#include "SensorView.h"
|
||||||
|
@ -1445,6 +1446,11 @@ void Window::setupMenu(QMenuBar* menubar) {
|
||||||
m_audioChannels = avMenu->addMenu(tr("Audio channels"));
|
m_audioChannels = avMenu->addMenu(tr("Audio channels"));
|
||||||
m_shortcutController->addMenu(m_audioChannels, avMenu);
|
m_shortcutController->addMenu(m_audioChannels, avMenu);
|
||||||
|
|
||||||
|
QAction* placementControl = new QAction(tr("Adjust layer placement..."), avMenu);
|
||||||
|
connect(placementControl, &QAction::triggered, openControllerTView<PlacementControl>());
|
||||||
|
m_gameActions.append(placementControl);
|
||||||
|
addControlledAction(avMenu, placementControl, "placementControl");
|
||||||
|
|
||||||
QMenu* toolsMenu = menubar->addMenu(tr("&Tools"));
|
QMenu* toolsMenu = menubar->addMenu(tr("&Tools"));
|
||||||
m_shortcutController->addMenu(toolsMenu);
|
m_shortcutController->addMenu(toolsMenu);
|
||||||
QAction* viewLogs = new QAction(tr("View &logs..."), toolsMenu);
|
QAction* viewLogs = new QAction(tr("View &logs..."), toolsMenu);
|
||||||
|
|
Loading…
Reference in New Issue