Merge branch 'master' (early part) into medusa

This commit is contained in:
Vicki Pfau 2019-06-28 15:53:53 -07:00
commit b6db8581df
14 changed files with 211 additions and 120 deletions

View File

@ -70,6 +70,12 @@ Misc:
- PSP2: Use system enter key by default
- 3DS: Remove deprecated CSND interface
0.6.3: (2017-04-14)
Bugfixes:
- GB Audio: Revert unsigned audio changes
- GB Video: Fix bad merge (fixes mgba.io/i/1040)
- GBA Video: Fix OBJ blending regression (fixes mgba.io/i/1037)
0.6.2: (2017-04-03)
Bugfixes:
- Core: Fix ROM patches not being unloaded when disabled (fixes mgba.io/i/962)

View File

@ -920,7 +920,7 @@ if(BUILD_PERF)
target_link_libraries(${BINARY_NAME}-perf ${BINARY_NAME} ${PERF_LIB} ${OS_LIB})
set_target_properties(${BINARY_NAME}-perf PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}")
install(TARGETS ${BINARY_NAME}-perf DESTINATION bin COMPONENT ${BINARY_NAME}-perf)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tools/perf.py DESTINATION "${CMAKE_INSTALL_LIBDIR}/${BINARY_NAME}" COMPONENT ${BINARY_NAME}-perf)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tools/perf.py DESTINATION "${LIBDIR}/${BINARY_NAME}" COMPONENT ${BINARY_NAME}-perf)
endif()
if(BUILD_TEST)

View File

@ -13,6 +13,7 @@
.Nm medusa-emu-qt
.Op Fl 123456fg
.Op Fl b Ar biosfile
.Op Fl C Ar option Ns = Ns Ar value
.Op Fl l Ar loglevel
.Op Fl p Ar patchfile
.Op Fl s Ar n
@ -40,6 +41,11 @@ If this flag is omitted,
.Nm
will use the BIOS specified in the configuration file,
or a high\(hylevel emulated BIOS if none is specified.
.It Fl C Ar option Ns = Ns Ar value , Fl -config Ar option Ns = Ns Ar value
Override the given config
.Ar option
with
.Ar value .
.It Fl f
Start the emulator full\(hyscreen.
.It Fl g

View File

@ -13,6 +13,7 @@
.Nm medusa-emu
.Op Fl 123456dfg
.Op Fl b Ar biosfile
.Op Fl C Ar option Ns = Ns Ar value
.Op Fl c Ar cheatfile
.Op Fl l Ar loglevel
.Op Fl p Ar patchfile
@ -42,6 +43,11 @@ If this flag is omitted,
.Nm
will use the BIOS specified in the configuration file,
or a high\(hylevel emulated BIOS if none is specified.
.It Fl C Ar option Ns = Ns Ar value , Fl -config Ar option Ns = Ns Ar value
Override the given config
.Ar option
with
.Ar value .
.It Fl c Ar cheatfile , Fl -cheats Ar cheatfile
Apply cheat codes from
.Ar cheatfile .

View File

@ -62,7 +62,7 @@ enum GBSGBCommand {
SGB_PICON_EN,
SGB_DATA_SND,
SGB_DATA_TRN,
SGB_MLT_REG,
SGB_MLT_REQ,
SGB_JUMP,
SGB_CHR_TRN,
SGB_PCT_TRN,
@ -107,6 +107,8 @@ struct GB {
int sgbBit;
int currentSgbBits;
uint8_t sgbPacket[16];
uint8_t sgbControllers;
uint8_t sgbCurrentController;
struct mCoreCallbacksList coreCallbacks;
struct mAVStream* stream;

View File

@ -39,15 +39,9 @@ struct GBVideoSoftwareRenderer {
enum GBModel model;
int sgbTransfer;
uint8_t sgbPacket[16];
uint8_t sgbPacket[128];
uint8_t sgbCommandHeader;
int sgbPacketId;
int sgbDataSets;
uint8_t sgbPartialDataSet[15];
bool sgbBorders;
int sgbAttrX;
int sgbAttrY;
int sgbAttrDirection;
};
void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer*);

View File

@ -258,6 +258,9 @@ DECL_BITS(GBSerializedMemoryFlags, ActiveRtcReg, 5, 3);
DECL_BITFIELD(GBSerializedSGBFlags, uint32_t);
DECL_BITS(GBSerializedSGBFlags, P1Bits, 0, 2);
DECL_BITS(GBSerializedSGBFlags, RenderMode, 2, 2);
DECL_BITS(GBSerializedSGBFlags, BufferIndex, 4, 3);
DECL_BITS(GBSerializedSGBFlags, CurrentController, 7, 2);
DECL_BITS(GBSerializedSGBFlags, ReqControllers, 9, 2);
#pragma pack(push, 1)
struct GBSerializedState {
@ -388,15 +391,15 @@ struct GBSerializedState {
uint8_t vram[GB_SIZE_VRAM];
uint8_t wram[GB_SIZE_WORKING_RAM];
uint32_t reserved2[0xE0];
uint32_t reserved2[0xC4];
struct {
uint8_t attributes[90];
uint8_t command;
uint8_t bits;
GBSerializedSGBFlags flags;
uint8_t packet[16];
uint32_t reserved[4];
uint8_t inProgressPacket[16];
uint8_t packet[128];
uint8_t charRam[SGB_SIZE_CHAR_RAM];
uint8_t mapRam[SGB_SIZE_MAP_RAM];
uint8_t palRam[SGB_SIZE_PAL_RAM];

View File

@ -143,6 +143,8 @@ struct GBVideo {
int ocpIndex;
bool ocpIncrement;
uint8_t sgbCommandHeader;
int sgbBufferIndex;
uint8_t sgbPacketBuffer[128];
uint16_t dmgPalette[12];
uint16_t palette[64];

View File

@ -290,7 +290,9 @@ static void _GBCoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
struct GB* gb = core->board;
gb->stream = stream;
if (stream && stream->videoDimensionsChanged) {
stream->videoDimensionsChanged(stream, GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS);
unsigned width, height;
core->desiredVideoDimensions(core, &width, &height);
stream->videoDimensionsChanged(stream, width, height);
}
if (stream && stream->videoFrameRateChanged) {
stream->videoFrameRateChanged(stream, core->frameCycles(core), core->frequency(core));

View File

@ -446,6 +446,8 @@ void GBReset(struct LR35902Core* cpu) {
}
gb->sgbBit = -1;
gb->sgbControllers = 0;
gb->sgbCurrentController = 0;
gb->currentSgbBits = 0;
memset(gb->sgbPacket, 0, sizeof(gb->sgbPacket));

View File

@ -113,6 +113,9 @@ static void _writeSGBBits(struct GB* gb, int bits) {
return;
}
gb->currentSgbBits = bits;
if (bits == 3) {
gb->sgbCurrentController = (gb->sgbCurrentController + 1) & gb->sgbControllers;
}
if (gb->sgbBit == 128 && bits == 2) {
GBVideoWriteSGBPacket(&gb->video, gb->sgbPacket);
++gb->sgbBit;
@ -503,10 +506,13 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
static uint8_t _readKeys(struct GB* gb) {
uint8_t keys = *gb->keySource;
if (gb->sgbCurrentController != 0) {
keys = 0;
}
switch (gb->memory.io[REG_JOYP] & 0x30) {
case 0x30:
// TODO: Increment
keys = (gb->video.sgbCommandHeader >> 3) == SGB_MLT_REG ? 0xF : 0;
keys = (gb->video.sgbCommandHeader >> 3) == SGB_MLT_REQ ? 0xF - gb->sgbCurrentController : 0;
break;
case 0x20:
keys >>= 4;

View File

@ -81,18 +81,12 @@ static void _regenerateSGBBorder(struct GBVideoSoftwareRenderer* renderer) {
if (SGBBgAttributesIsXFlip(mapData)) {
for (i = 0; i < 8; ++i) {
colorSelector = (tileData[0] >> i & 0x1) << 0 | (tileData[1] >> i & 0x1) << 1 | (tileData[2] >> i & 0x1) << 2 | (tileData[3] >> i & 0x1) << 3;
// The first color of every palette is transparent
if (colorSelector) {
renderer->outputBuffer[base + i] = renderer->palette[paletteBase | colorSelector];
}
renderer->outputBuffer[base + i] = renderer->palette[paletteBase | colorSelector];
}
} else {
for (i = 7; i >= 0; --i) {
colorSelector = (tileData[0] >> i & 0x1) << 0 | (tileData[1] >> i & 0x1) << 1 | (tileData[2] >> i & 0x1) << 2 | (tileData[3] >> i & 0x1) << 3;
if (colorSelector) {
renderer->outputBuffer[base + 7 - i] = renderer->palette[paletteBase | colorSelector];
}
renderer->outputBuffer[base + 7 - i] = renderer->palette[paletteBase | colorSelector];
}
}
}
@ -108,12 +102,7 @@ static inline void _setAttribute(uint8_t* sgbAttributes, unsigned x, unsigned y,
static void _parseAttrBlock(struct GBVideoSoftwareRenderer* renderer, int start) {
uint8_t block[6];
if (start < 0) {
memcpy(block, renderer->sgbPartialDataSet, -start);
memcpy(&block[-start], renderer->sgbPacket, 6 + start);
} else {
memcpy(block, &renderer->sgbPacket[start], 6);
}
memcpy(block, &renderer->sgbPacket[start], 6);
unsigned x0 = block[2];
unsigned x1 = block[4];
unsigned y0 = block[3];
@ -268,14 +257,16 @@ static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* render
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
memcpy(softwareRenderer->sgbPacket, data, sizeof(softwareRenderer->sgbPacket));
int i;
if (!(softwareRenderer->sgbCommandHeader & 7)) {
softwareRenderer->sgbCommandHeader = data[0];
softwareRenderer->sgbPacketId = 0;
softwareRenderer->sgbTransfer = 0;
}
--softwareRenderer->sgbCommandHeader;
++softwareRenderer->sgbPacketId;
softwareRenderer->sgbCommandHeader = data[0];
softwareRenderer->sgbTransfer = 0;
int set;
int sets;
int attrX;
int attrY;
int attrDirection;
int pBefore;
int pAfter;
int pDiv;
switch (softwareRenderer->sgbCommandHeader >> 3) {
case SGB_PAL_SET:
softwareRenderer->sgbPacket[1] = data[9];
@ -290,58 +281,96 @@ static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* render
}
break;
case SGB_ATTR_BLK:
if (softwareRenderer->sgbPacketId == 1) {
softwareRenderer->sgbDataSets = softwareRenderer->sgbPacket[1];
i = 2;
} else {
i = (9 - softwareRenderer->sgbPacketId) % 3 * -2;
}
for (; i <= 10 && softwareRenderer->sgbDataSets; i += 6, --softwareRenderer->sgbDataSets) {
sets = softwareRenderer->sgbPacket[1];
i = 2;
for (; i < (softwareRenderer->sgbCommandHeader & 7) << 4 && sets; i += 6, --sets) {
_parseAttrBlock(softwareRenderer, i);
}
if (i < 16 && softwareRenderer->sgbDataSets) {
memcpy(softwareRenderer->sgbPartialDataSet, &softwareRenderer->sgbPacket[i], 16 - i);
break;
case SGB_ATTR_DIV:
pAfter = softwareRenderer->sgbPacket[1] & 3;
pBefore = (softwareRenderer->sgbPacket[1] >> 2) & 3;
pDiv = (softwareRenderer->sgbPacket[1] >> 4) & 3;
attrX = softwareRenderer->sgbPacket[2];
if (softwareRenderer->sgbPacket[1] & 0x40) {
if (attrX > GB_VIDEO_VERTICAL_PIXELS / 8) {
attrX = GB_VIDEO_VERTICAL_PIXELS / 8;
}
int j;
for (j = 0; j < attrX; ++j) {
for (i = 0; i < GB_VIDEO_HORIZONTAL_PIXELS / 8; ++i) {
_setAttribute(renderer->sgbAttributes, i, j, pBefore);
}
}
if (attrX < GB_VIDEO_VERTICAL_PIXELS / 8) {
for (i = 0; i < GB_VIDEO_HORIZONTAL_PIXELS / 8; ++i) {
_setAttribute(renderer->sgbAttributes, i, attrX, pDiv);
}
}
for (; j < GB_VIDEO_VERTICAL_PIXELS / 8; ++j) {
for (i = 0; i < GB_VIDEO_HORIZONTAL_PIXELS / 8; ++i) {
_setAttribute(renderer->sgbAttributes, i, j, pAfter);
}
}
} else {
if (attrX > GB_VIDEO_HORIZONTAL_PIXELS / 8) {
attrX = GB_VIDEO_HORIZONTAL_PIXELS / 8;
}
int j;
for (j = 0; j < attrX; ++j) {
for (i = 0; i < GB_VIDEO_HORIZONTAL_PIXELS / 8; ++i) {
_setAttribute(renderer->sgbAttributes, j, i, pBefore);
}
}
if (attrX < GB_VIDEO_HORIZONTAL_PIXELS / 8) {
for (i = 0; i < GB_VIDEO_VERTICAL_PIXELS / 8; ++i) {
_setAttribute(renderer->sgbAttributes, attrX, i, pDiv);
}
}
for (; j < GB_VIDEO_HORIZONTAL_PIXELS / 8; ++j) {
for (i = 0; i < GB_VIDEO_VERTICAL_PIXELS / 8; ++i) {
_setAttribute(renderer->sgbAttributes, j, i, pAfter);
}
}
}
break;
case SGB_ATTR_CHR:
if (softwareRenderer->sgbPacketId == 1) {
softwareRenderer->sgbAttrX = softwareRenderer->sgbPacket[1];
softwareRenderer->sgbAttrY = softwareRenderer->sgbPacket[2];
if (softwareRenderer->sgbAttrX >= GB_VIDEO_HORIZONTAL_PIXELS / 8) {
softwareRenderer->sgbAttrX = 0;
}
if (softwareRenderer->sgbAttrY >= GB_VIDEO_VERTICAL_PIXELS / 8) {
softwareRenderer->sgbAttrY = 0;
}
softwareRenderer->sgbDataSets = softwareRenderer->sgbPacket[3];
softwareRenderer->sgbDataSets |= softwareRenderer->sgbPacket[4] << 8;
softwareRenderer->sgbAttrDirection = softwareRenderer->sgbPacket[5];
i = 6;
} else {
i = 0;
attrX = softwareRenderer->sgbPacket[1];
attrY = softwareRenderer->sgbPacket[2];
if (attrX >= GB_VIDEO_HORIZONTAL_PIXELS / 8) {
attrX = 0;
}
for (; i < 16 && softwareRenderer->sgbDataSets; ++i) {
if (attrY >= GB_VIDEO_VERTICAL_PIXELS / 8) {
attrY = 0;
}
sets = softwareRenderer->sgbPacket[3];
sets |= softwareRenderer->sgbPacket[4] << 8;
attrDirection = softwareRenderer->sgbPacket[5];
i = 6;
for (; i < (softwareRenderer->sgbCommandHeader & 7) << 4 && sets; ++i) {
int j;
for (j = 0; j < 4 && softwareRenderer->sgbDataSets; ++j, --softwareRenderer->sgbDataSets) {
for (j = 0; j < 4 && sets; ++j, --sets) {
uint8_t p = softwareRenderer->sgbPacket[i] >> (6 - j * 2);
_setAttribute(renderer->sgbAttributes, softwareRenderer->sgbAttrX, softwareRenderer->sgbAttrY, p & 3);
if (softwareRenderer->sgbAttrDirection) {
++softwareRenderer->sgbAttrY;
if (softwareRenderer->sgbAttrY >= GB_VIDEO_VERTICAL_PIXELS / 8) {
softwareRenderer->sgbAttrY = 0;
++softwareRenderer->sgbAttrX;
_setAttribute(renderer->sgbAttributes, attrX, attrY, p & 3);
if (attrDirection) {
++attrY;
if (attrY >= GB_VIDEO_VERTICAL_PIXELS / 8) {
attrY = 0;
++attrX;
}
if (softwareRenderer->sgbAttrX >= GB_VIDEO_HORIZONTAL_PIXELS / 8) {
softwareRenderer->sgbAttrX = 0;
if (attrX >= GB_VIDEO_HORIZONTAL_PIXELS / 8) {
attrX = 0;
}
} else {
++softwareRenderer->sgbAttrX;
if (softwareRenderer->sgbAttrX >= GB_VIDEO_HORIZONTAL_PIXELS / 8) {
softwareRenderer->sgbAttrX = 0;
++softwareRenderer->sgbAttrY;
++attrX;
if (attrX >= GB_VIDEO_HORIZONTAL_PIXELS / 8) {
attrX = 0;
++attrY;
}
if (softwareRenderer->sgbAttrY >= GB_VIDEO_VERTICAL_PIXELS / 8) {
softwareRenderer->sgbAttrY = 0;
if (attrY >= GB_VIDEO_VERTICAL_PIXELS / 8) {
attrY = 0;
}
}
}
@ -349,23 +378,40 @@ static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* render
break;
case SGB_ATRC_EN:
if (softwareRenderer->sgbBorders) {
case SGB_MASK_EN:
if (softwareRenderer->sgbBorders && !renderer->sgbRenderMode) {
_regenerateSGBBorder(softwareRenderer);
}
break;
}
}
static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value) {
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
color_t color = mColorFrom555(value);
if (softwareRenderer->model == GB_MODEL_SGB && index < 0x10 && index && !(index & 3)) {
color = softwareRenderer->palette[0];
if (softwareRenderer->model == GB_MODEL_SGB) {
if (index < 0x10 && index && !(index & 3)) {
color = softwareRenderer->palette[0];
} else if (index >= 0x40 && !(index & 0xF)) {
color = softwareRenderer->palette[0];
}
}
softwareRenderer->palette[index] = color;
if (renderer->cache) {
mCacheSetWritePalette(renderer->cache, index, color);
}
if (softwareRenderer->model == GB_MODEL_SGB && !index && GBRegisterLCDCIsEnable(softwareRenderer->lcdc)) {
renderer->writePalette(renderer, 0x04, value);
renderer->writePalette(renderer, 0x08, value);
renderer->writePalette(renderer, 0x0C, value);
renderer->writePalette(renderer, 0x40, value);
renderer->writePalette(renderer, 0x50, value);
renderer->writePalette(renderer, 0x60, value);
renderer->writePalette(renderer, 0x70, value);
if (softwareRenderer->sgbBorders && !renderer->sgbRenderMode) {
_regenerateSGBBorder(softwareRenderer);
}
}
}
static void GBVideoSoftwareRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address) {
@ -580,7 +626,7 @@ static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer)
case SGB_PAL_TRN:
case SGB_CHR_TRN:
case SGB_PCT_TRN:
if (softwareRenderer->sgbTransfer > 0 && softwareRenderer->sgbBorders) {
if (softwareRenderer->sgbTransfer > 0 && softwareRenderer->sgbBorders && !renderer->sgbRenderMode) {
// Make sure every buffer sees this if we're multibuffering
_regenerateSGBBorder(softwareRenderer);
}

View File

@ -212,9 +212,13 @@ void GBSGBSerialize(struct GB* gb, struct GBSerializedState* state) {
GBSerializedSGBFlags flags = 0;
flags = GBSerializedSGBFlagsSetP1Bits(flags, gb->currentSgbBits);
flags = GBSerializedSGBFlagsSetRenderMode(flags, gb->video.renderer->sgbRenderMode);
flags = GBSerializedSGBFlagsSetBufferIndex(flags, gb->video.sgbBufferIndex);
flags = GBSerializedSGBFlagsSetReqControllers(flags, gb->sgbControllers);
flags = GBSerializedSGBFlagsSetCurrentController(flags, gb->sgbCurrentController);
STORE_32LE(flags, 0, &state->sgb.flags);
memcpy(state->sgb.packet, gb->sgbPacket, sizeof(state->sgb.packet));
memcpy(state->sgb.packet, gb->video.sgbPacketBuffer, sizeof(state->sgb.packet));
memcpy(state->sgb.inProgressPacket, gb->sgbPacket, sizeof(state->sgb.inProgressPacket));
if (gb->video.renderer->sgbCharRam) {
memcpy(state->sgb.charRam, gb->video.renderer->sgbCharRam, sizeof(state->sgb.charRam));
@ -241,8 +245,12 @@ void GBSGBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
LOAD_32LE(flags, 0, &state->sgb.flags);
gb->currentSgbBits = GBSerializedSGBFlagsGetP1Bits(flags);
gb->video.renderer->sgbRenderMode = GBSerializedSGBFlagsGetRenderMode(flags);
gb->video.sgbBufferIndex = GBSerializedSGBFlagsGetBufferIndex(flags);
gb->sgbControllers = GBSerializedSGBFlagsGetReqControllers(flags);
gb->sgbCurrentController = GBSerializedSGBFlagsGetCurrentController(flags);
memcpy(gb->sgbPacket, state->sgb.packet, sizeof(state->sgb.packet));
memcpy(gb->video.sgbPacketBuffer, state->sgb.packet, sizeof(state->sgb.packet));
memcpy(gb->sgbPacket, state->sgb.inProgressPacket, sizeof(state->sgb.inProgressPacket));
if (!gb->video.renderer->sgbCharRam) {
gb->video.renderer->sgbCharRam = anonymousMemoryMap(SGB_SIZE_CHAR_RAM);
@ -267,5 +275,4 @@ void GBSGBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
memcpy(gb->video.renderer->sgbAttributes, state->sgb.attributes, sizeof(state->sgb.attributes));
GBVideoWriteSGBPacket(&gb->video, (uint8_t[16]) { (SGB_ATRC_EN << 3) | 1, 0 });
GBVideoWriteSGBPacket(&gb->video, gb->sgbPacket);
}

View File

@ -113,6 +113,7 @@ void GBVideoReset(struct GBVideo* video) {
video->renderer->sgbAttributes = malloc(90 * 45);
memset(video->renderer->sgbAttributes, 0, 90 * 45);
video->sgbCommandHeader = 0;
video->sgbBufferIndex = 0;
}
video->palette[0] = video->dmgPalette[0];
@ -580,6 +581,7 @@ void GBVideoDisableCGB(struct GBVideo* video) {
void GBVideoWriteSGBPacket(struct GBVideo* video, uint8_t* data) {
int i;
if (!(video->sgbCommandHeader & 7)) {
video->sgbBufferIndex = 0;
if ((data[0] >> 3) > SGB_OBJ_TRN) {
video->sgbCommandHeader = 0;
return;
@ -587,20 +589,25 @@ void GBVideoWriteSGBPacket(struct GBVideo* video, uint8_t* data) {
video->sgbCommandHeader = data[0];
}
--video->sgbCommandHeader;
memcpy(&video->sgbPacketBuffer[video->sgbBufferIndex << 4], data, 16);
++video->sgbBufferIndex;
if (video->sgbCommandHeader & 7) {
return;
}
switch (video->sgbCommandHeader >> 3) {
case SGB_PAL01:
video->palette[0] = data[1] | (data[2] << 8);
video->palette[1] = data[3] | (data[4] << 8);
video->palette[2] = data[5] | (data[6] << 8);
video->palette[3] = data[7] | (data[8] << 8);
video->palette[0] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8);
video->palette[1] = video->sgbPacketBuffer[3] | (video->sgbPacketBuffer[4] << 8);
video->palette[2] = video->sgbPacketBuffer[5] | (video->sgbPacketBuffer[6] << 8);
video->palette[3] = video->sgbPacketBuffer[7] | (video->sgbPacketBuffer[8] << 8);
video->palette[4] = data[1] | (data[2] << 8);
video->palette[5] = data[9] | (data[10] << 8);
video->palette[6] = data[11] | (data[12] << 8);
video->palette[7] = data[13] | (data[14] << 8);
video->palette[4] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8);
video->palette[5] = video->sgbPacketBuffer[9] | (video->sgbPacketBuffer[10] << 8);
video->palette[6] = video->sgbPacketBuffer[11] | (video->sgbPacketBuffer[12] << 8);
video->palette[7] = video->sgbPacketBuffer[13] | (video->sgbPacketBuffer[14] << 8);
video->palette[8] = data[1] | (data[2] << 8);
video->palette[12] = data[1] | (data[2] << 8);
video->palette[8] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8);
video->palette[12] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8);
video->renderer->writePalette(video->renderer, 0, video->palette[0]);
video->renderer->writePalette(video->renderer, 1, video->palette[1]);
@ -614,13 +621,13 @@ void GBVideoWriteSGBPacket(struct GBVideo* video, uint8_t* data) {
video->renderer->writePalette(video->renderer, 12, video->palette[12]);
break;
case SGB_PAL23:
video->palette[9] = data[3] | (data[4] << 8);
video->palette[10] = data[5] | (data[6] << 8);
video->palette[11] = data[7] | (data[8] << 8);
video->palette[9] = video->sgbPacketBuffer[3] | (video->sgbPacketBuffer[4] << 8);
video->palette[10] = video->sgbPacketBuffer[5] | (video->sgbPacketBuffer[6] << 8);
video->palette[11] = video->sgbPacketBuffer[7] | (video->sgbPacketBuffer[8] << 8);
video->palette[13] = data[9] | (data[10] << 8);
video->palette[14] = data[11] | (data[12] << 8);
video->palette[15] = data[13] | (data[14] << 8);
video->palette[13] = video->sgbPacketBuffer[9] | (video->sgbPacketBuffer[10] << 8);
video->palette[14] = video->sgbPacketBuffer[11] | (video->sgbPacketBuffer[12] << 8);
video->palette[15] = video->sgbPacketBuffer[13] | (video->sgbPacketBuffer[14] << 8);
video->renderer->writePalette(video->renderer, 9, video->palette[9]);
video->renderer->writePalette(video->renderer, 10, video->palette[10]);
video->renderer->writePalette(video->renderer, 11, video->palette[11]);
@ -629,18 +636,18 @@ void GBVideoWriteSGBPacket(struct GBVideo* video, uint8_t* data) {
video->renderer->writePalette(video->renderer, 15, video->palette[15]);
break;
case SGB_PAL03:
video->palette[0] = data[1] | (data[2] << 8);
video->palette[1] = data[3] | (data[4] << 8);
video->palette[2] = data[5] | (data[6] << 8);
video->palette[3] = data[7] | (data[8] << 8);
video->palette[0] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8);
video->palette[1] = video->sgbPacketBuffer[3] | (video->sgbPacketBuffer[4] << 8);
video->palette[2] = video->sgbPacketBuffer[5] | (video->sgbPacketBuffer[6] << 8);
video->palette[3] = video->sgbPacketBuffer[7] | (video->sgbPacketBuffer[8] << 8);
video->palette[4] = data[1] | (data[2] << 8);
video->palette[8] = data[1] | (data[2] << 8);
video->palette[4] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8);
video->palette[8] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8);
video->palette[12] = data[1] | (data[2] << 8);
video->palette[13] = data[9] | (data[10] << 8);
video->palette[14] = data[11] | (data[12] << 8);
video->palette[15] = data[13] | (data[14] << 8);
video->palette[12] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8);
video->palette[13] = video->sgbPacketBuffer[9] | (video->sgbPacketBuffer[10] << 8);
video->palette[14] = video->sgbPacketBuffer[11] | (video->sgbPacketBuffer[12] << 8);
video->palette[15] = video->sgbPacketBuffer[13] | (video->sgbPacketBuffer[14] << 8);
video->renderer->writePalette(video->renderer, 0, video->palette[0]);
video->renderer->writePalette(video->renderer, 1, video->palette[1]);
video->renderer->writePalette(video->renderer, 2, video->palette[2]);
@ -653,13 +660,13 @@ void GBVideoWriteSGBPacket(struct GBVideo* video, uint8_t* data) {
video->renderer->writePalette(video->renderer, 15, video->palette[15]);
break;
case SGB_PAL12:
video->palette[5] = data[3] | (data[4] << 8);
video->palette[6] = data[5] | (data[6] << 8);
video->palette[7] = data[7] | (data[8] << 8);
video->palette[5] = video->sgbPacketBuffer[3] | (video->sgbPacketBuffer[4] << 8);
video->palette[6] = video->sgbPacketBuffer[5] | (video->sgbPacketBuffer[6] << 8);
video->palette[7] = video->sgbPacketBuffer[7] | (video->sgbPacketBuffer[8] << 8);
video->palette[9] = data[9] | (data[10] << 8);
video->palette[10] = data[11] | (data[12] << 8);
video->palette[11] = data[13] | (data[14] << 8);
video->palette[9] = video->sgbPacketBuffer[9] | (video->sgbPacketBuffer[10] << 8);
video->palette[10] = video->sgbPacketBuffer[11] | (video->sgbPacketBuffer[12] << 8);
video->palette[11] = video->sgbPacketBuffer[13] | (video->sgbPacketBuffer[14] << 8);
video->renderer->writePalette(video->renderer, 5, video->palette[5]);
video->renderer->writePalette(video->renderer, 6, video->palette[6]);
video->renderer->writePalette(video->renderer, 7, video->palette[7]);
@ -669,7 +676,7 @@ void GBVideoWriteSGBPacket(struct GBVideo* video, uint8_t* data) {
break;
case SGB_PAL_SET:
for (i = 0; i < 4; ++i) {
uint16_t entry = (data[2 + (i * 2)] << 8) | data[1 + (i * 2)];
uint16_t entry = (video->sgbPacketBuffer[2 + (i * 2)] << 8) | video->sgbPacketBuffer[1 + (i * 2)];
if (entry >= 0x200) {
mLOG(GB, STUB, "Unimplemented SGB palette overflow: %03X", entry);
continue;
@ -685,6 +692,7 @@ void GBVideoWriteSGBPacket(struct GBVideo* video, uint8_t* data) {
}
break;
case SGB_ATTR_BLK:
case SGB_ATTR_DIV:
case SGB_ATTR_CHR:
case SGB_PAL_TRN:
case SGB_ATRC_EN:
@ -693,16 +701,17 @@ void GBVideoWriteSGBPacket(struct GBVideo* video, uint8_t* data) {
case SGB_ATTR_TRN:
case SGB_ATTR_SET:
break;
case SGB_MLT_REG:
case SGB_MLT_REQ:
video->p->sgbControllers = video->sgbPacketBuffer[1] & 0x3;
return;
case SGB_MASK_EN:
video->renderer->sgbRenderMode = data[1] & 0x3;
video->renderer->sgbRenderMode = video->sgbPacketBuffer[1] & 0x3;
break;
default:
mLOG(GB, STUB, "Unimplemented SGB command: %02X", data[0] >> 3);
mLOG(GB, STUB, "Unimplemented SGB command: %02X", video->sgbPacketBuffer[0] >> 3);
return;
}
video->renderer->writeSGBPacket(video->renderer, data);
video->renderer->writeSGBPacket(video->renderer, video->sgbPacketBuffer);
}
static void GBVideoDummyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders) {