all repos — mgba @ b6db8581dfc625e527b2c7041193e996497a5ff7

mGBA Game Boy Advance Emulator

Merge branch 'master' (early part) into medusa
Vicki Pfau vi@endrift.com
Fri, 28 Jun 2019 15:53:53 -0700
commit

b6db8581dfc625e527b2c7041193e996497a5ff7

parent

7a67ed4ff95cc24a4303b5201f0f09bffcc0f673

M CHANGESCHANGES

@@ -70,6 +70,12 @@ - GBA Memory: 64 MiB GBA Video cartridge support

- 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)
M CMakeLists.txtCMakeLists.txt

@@ -920,7 +920,7 @@ add_executable(${BINARY_NAME}-perf ${PERF_SRC})

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)
M doc/medusa-emu-qt.6doc/medusa-emu-qt.6

@@ -13,6 +13,7 @@ .Sh SYNOPSIS

.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
M doc/medusa-emu.6doc/medusa-emu.6

@@ -13,6 +13,7 @@ .Sh SYNOPSIS

.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 .
M include/mgba/internal/gb/gb.hinclude/mgba/internal/gb/gb.h

@@ -62,7 +62,7 @@ SGB_TEST_EN,

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

int sgbBit; int currentSgbBits; uint8_t sgbPacket[16]; + uint8_t sgbControllers; + uint8_t sgbCurrentController; struct mCoreCallbacksList coreCallbacks; struct mAVStream* stream;
M include/mgba/internal/gb/renderers/software.hinclude/mgba/internal/gb/renderers/software.h

@@ -39,15 +39,9 @@ GBRegisterLCDC lcdc;

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*);
M include/mgba/internal/gb/serialize.hinclude/mgba/internal/gb/serialize.h

@@ -258,6 +258,9 @@

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

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];
M include/mgba/internal/gb/video.hinclude/mgba/internal/gb/video.h

@@ -143,6 +143,8 @@ bool bcpIncrement;

int ocpIndex; bool ocpIncrement; uint8_t sgbCommandHeader; + int sgbBufferIndex; + uint8_t sgbPacketBuffer[128]; uint16_t dmgPalette[12]; uint16_t palette[64];
M src/gb/core.csrc/gb/core.c

@@ -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));
M src/gb/gb.csrc/gb/gb.c

@@ -446,6 +446,8 @@ gb->yankedRomSize = 0;

} gb->sgbBit = -1; + gb->sgbControllers = 0; + gb->sgbCurrentController = 0; gb->currentSgbBits = 0; memset(gb->sgbPacket, 0, sizeof(gb->sgbPacket));
M src/gb/io.csrc/gb/io.c

@@ -113,6 +113,9 @@ if (bits == gb->currentSgbBits) {

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

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;
M src/gb/renderers/software.csrc/gb/renderers/software.c

@@ -81,18 +81,12 @@

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 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* renderer, uint8_t* data) {

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 @@ memcpy(renderer->sgbAttributes, &renderer->sgbAttributeFiles[set * 90], 90);

} 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_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; + 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); + } + } - if (softwareRenderer->sgbAttrY >= GB_VIDEO_VERTICAL_PIXELS / 8) { - softwareRenderer->sgbAttrY = 0; + for (; j < GB_VIDEO_VERTICAL_PIXELS / 8; ++j) { + for (i = 0; i < GB_VIDEO_HORIZONTAL_PIXELS / 8; ++i) { + _setAttribute(renderer->sgbAttributes, i, j, pAfter); + } } - softwareRenderer->sgbDataSets = softwareRenderer->sgbPacket[3]; - softwareRenderer->sgbDataSets |= softwareRenderer->sgbPacket[4] << 8; - softwareRenderer->sgbAttrDirection = softwareRenderer->sgbPacket[5]; - i = 6; } else { - i = 0; + 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: + 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,22 +378,39 @@ }

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

@@ -580,7 +626,7 @@ break;

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); }
M src/gb/serialize.csrc/gb/serialize.c

@@ -212,9 +212,13 @@

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

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 @@ memcpy(gb->video.renderer->sgbAttributeFiles, state->sgb.atfRam, sizeof(state->sgb.atfRam));

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); }
M src/gb/video.csrc/gb/video.c

@@ -113,6 +113,7 @@ video->renderer->sgbAttributeFiles = anonymousMemoryMap(SGB_SIZE_ATF_RAM);

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

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 @@ video->renderer->writePalette(video->renderer, 8, video->palette[8]);

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 @@ video->renderer->writePalette(video->renderer, 14, video->palette[14]);

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 @@ video->renderer->writePalette(video->renderer, 14, video->palette[14]);

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 @@ video->renderer->writePalette(video->renderer, 11, video->palette[11]);

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 @@ video->renderer->writePalette(video->renderer, i * 4 + 3, video->palette[i * 4 + 3]);

} 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 @@ case SGB_PCT_TRN:

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