mirror of https://github.com/mgba-emu/mgba.git
parent
5a7d5766d0
commit
4101fe54c6
|
@ -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*);
|
||||
|
|
|
@ -258,6 +258,7 @@ 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)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct GBSerializedState {
|
||||
|
@ -388,15 +389,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];
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -102,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];
|
||||
|
@ -262,14 +257,13 @@ 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;
|
||||
switch (softwareRenderer->sgbCommandHeader >> 3) {
|
||||
case SGB_PAL_SET:
|
||||
softwareRenderer->sgbPacket[1] = data[9];
|
||||
|
@ -284,58 +278,47 @@ 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_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -212,9 +212,11 @@ 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);
|
||||
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 +243,10 @@ 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);
|
||||
|
||||
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 +271,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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -696,13 +703,13 @@ void GBVideoWriteSGBPacket(struct GBVideo* video, uint8_t* data) {
|
|||
case SGB_MLT_REG:
|
||||
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) {
|
||||
|
|
Loading…
Reference in New Issue