mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' into optimization/idle-loop-detection
Conflicts: CHANGES src/gba/gba-overrides.c src/gba/gba-thread.h src/gba/gba.c
This commit is contained in:
commit
d49a9a84f7
16
CHANGES
16
CHANGES
|
@ -19,6 +19,7 @@ Features:
|
|||
- Save directory of last loaded file
|
||||
- Support BPS patches
|
||||
- Automatically detect and optimize out idle loops
|
||||
- Configurable game overrides
|
||||
Bugfixes:
|
||||
- Qt: Fix issue with set frame sizes being the wrong height
|
||||
- Qt: Fix emulator crashing when full screen if a game is not running
|
||||
|
@ -51,6 +52,17 @@ Bugfixes:
|
|||
- GBA Memory: Filter out top nybble of DMA addresses
|
||||
- Debugger: Fix binary print putting spaces between digits
|
||||
- GBA BIOS: Fix LZ77UnCompVram to use 16-bit loads from decompressed memory
|
||||
- GBA BIOS: Fix HuffUnComp to work when games pass an invalid bit length
|
||||
- GBA BIOS: Fix GetBiosChecksum to return the value of a real GBA, regardless of used BIOS
|
||||
- GBA Memory: Properly bounds-check VRAM accesses
|
||||
- GBA Memory: Fix initial DMA state
|
||||
- GBA BIOS: Fix BIOS prefetch after returning from an IRQ
|
||||
- GBA BIOS: Fix BIOS prefetch after reset
|
||||
- GBA Memory: Fix alignment of open bus 8- and 16-bit loads
|
||||
- GBA BIOS: Fix HuffUnComp boundary conditions
|
||||
- GBA Video: Fix mode 0 being able to read tiles above appropriate tile range
|
||||
- GBA Audio: Properly initialize audio FIFO channels
|
||||
- Util: Fix SOCKET_FAILED macro
|
||||
Misc:
|
||||
- Qt: Disable sync to video by default
|
||||
- GBA: Exit cleanly on FATAL if the port supports it
|
||||
|
@ -61,6 +73,10 @@ Misc:
|
|||
- GBA Memory: Implement 16- and 32-bit loads from SRAM
|
||||
- Qt: Clear active buttons when focus is lost
|
||||
- GBA Memory: Simplify memory API and use fixed bus width
|
||||
- GBA Video: Start video at the last scanline instead of the first
|
||||
- Debugger: Watchpoints now work on STM/LDM instructions
|
||||
- GBA: Improve accuracy of event timing
|
||||
- Debugger: Clean up GDB stub network interfacing
|
||||
|
||||
0.1.0: (2014-12-13)
|
||||
- Initial release
|
||||
|
|
|
@ -53,15 +53,39 @@ static void _gdbStubEntered(struct ARMDebugger* debugger, enum DebuggerEntryReas
|
|||
|
||||
static void _gdbStubPoll(struct ARMDebugger* debugger) {
|
||||
struct GDBStub* stub = (struct GDBStub*) debugger;
|
||||
while (stub->d.state == DEBUGGER_PAUSED) {
|
||||
if (!SOCKET_FAILED(stub->connection)) {
|
||||
if (!SocketSetBlocking(stub->connection, 1)) {
|
||||
GDBStubHangup(stub);
|
||||
return;
|
||||
}
|
||||
}
|
||||
GDBStubUpdate(stub);
|
||||
--stub->untilPoll;
|
||||
if (stub->untilPoll > 0) {
|
||||
return;
|
||||
}
|
||||
stub->untilPoll = GDB_STUB_INTERVAL;
|
||||
if (stub->shouldBlock) {
|
||||
stub->shouldBlock = false;
|
||||
if (!SocketSetBlocking(stub->socket, false)) {
|
||||
GDBStubHangup(stub);
|
||||
return;
|
||||
}
|
||||
if (!SOCKET_FAILED(stub->connection) && !SocketSetBlocking(stub->connection, false)) {
|
||||
GDBStubHangup(stub);
|
||||
return;
|
||||
}
|
||||
}
|
||||
GDBStubUpdate(stub);
|
||||
}
|
||||
|
||||
static void _gdbStubWait(struct ARMDebugger* debugger) {
|
||||
struct GDBStub* stub = (struct GDBStub*) debugger;
|
||||
if (!stub->shouldBlock) {
|
||||
stub->shouldBlock = true;
|
||||
if (!SocketSetBlocking(stub->socket, true)) {
|
||||
GDBStubHangup(stub);
|
||||
return;
|
||||
}
|
||||
if (!SOCKET_FAILED(stub->connection) && !SocketSetBlocking(stub->connection, true)) {
|
||||
GDBStubHangup(stub);
|
||||
return;
|
||||
}
|
||||
}
|
||||
GDBStubUpdate(stub);
|
||||
}
|
||||
|
||||
static void _ack(struct GDBStub* stub) {
|
||||
|
@ -169,7 +193,8 @@ static void _writeHostInfo(struct GDBStub* stub) {
|
|||
}
|
||||
|
||||
static void _continue(struct GDBStub* stub, const char* message) {
|
||||
stub->d.state = DEBUGGER_RUNNING;
|
||||
stub->d.state = DEBUGGER_CUSTOM;
|
||||
stub->untilPoll = GDB_STUB_INTERVAL;
|
||||
if (!SOCKET_FAILED(stub->connection)) {
|
||||
if (!SocketSetBlocking(stub->connection, 0)) {
|
||||
GDBStubHangup(stub);
|
||||
|
@ -441,9 +466,11 @@ void GDBStubCreate(struct GDBStub* stub) {
|
|||
stub->connection = INVALID_SOCKET;
|
||||
stub->d.init = 0;
|
||||
stub->d.deinit = _gdbStubDeinit;
|
||||
stub->d.paused = _gdbStubPoll;
|
||||
stub->d.paused = _gdbStubWait;
|
||||
stub->d.entered = _gdbStubEntered;
|
||||
stub->d.custom = _gdbStubPoll;
|
||||
stub->d.log = 0;
|
||||
stub->untilPoll = GDB_STUB_INTERVAL;
|
||||
}
|
||||
|
||||
int GDBStubListen(struct GDBStub* stub, int port, const struct Address* bindAddress) {
|
||||
|
@ -461,9 +488,6 @@ int GDBStubListen(struct GDBStub* stub, int port, const struct Address* bindAddr
|
|||
if (err) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (!SocketSetBlocking(stub->socket, 0)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
|
@ -501,9 +525,6 @@ void GDBStubUpdate(struct GDBStub* stub) {
|
|||
if (stub->connection == INVALID_SOCKET) {
|
||||
stub->connection = SocketAccept(stub->socket, 0);
|
||||
if (!SOCKET_FAILED(stub->connection)) {
|
||||
if (!SocketSetBlocking(stub->connection, 0)) {
|
||||
goto connectionLost;
|
||||
}
|
||||
ARMDebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED);
|
||||
} else if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
||||
return;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "util/socket.h"
|
||||
|
||||
#define GDB_STUB_MAX_LINE 1200
|
||||
#define GDB_STUB_INTERVAL 32
|
||||
|
||||
enum GDBStubAckState {
|
||||
GDB_ACK_PENDING = 0,
|
||||
|
@ -30,6 +31,9 @@ struct GDBStub {
|
|||
|
||||
Socket socket;
|
||||
Socket connection;
|
||||
|
||||
bool shouldBlock;
|
||||
int untilPoll;
|
||||
};
|
||||
|
||||
void GDBStubCreate(struct GDBStub*);
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
#include <string.h>
|
||||
|
||||
static bool _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width);
|
||||
static uint32_t _popcount32(unsigned bits) {
|
||||
bits = bits - ((bits >> 1) & 0x55555555);
|
||||
bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
|
||||
return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
|
||||
}
|
||||
|
||||
#define FIND_DEBUGGER(DEBUGGER, CPU) \
|
||||
{ \
|
||||
|
@ -40,12 +45,37 @@ static bool _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t addr
|
|||
return debugger->originalMemory.NAME(cpu, ARGS); \
|
||||
}
|
||||
|
||||
#define CREATE_MULTIPLE_WATCHPOINT_SHIM(NAME) \
|
||||
static uint32_t ARMDebuggerShim_ ## NAME (struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) { \
|
||||
struct ARMDebugger* debugger; \
|
||||
FIND_DEBUGGER(debugger, cpu); \
|
||||
uint32_t popcount = _popcount32(mask); \
|
||||
int offset = 4; \
|
||||
int base = address; \
|
||||
if (direction & LSM_D) { \
|
||||
offset = -4; \
|
||||
base -= (popcount << 2) - 4; \
|
||||
} \
|
||||
if (direction & LSM_B) { \
|
||||
base += offset; \
|
||||
} \
|
||||
unsigned i; \
|
||||
for (i = 0; i < popcount; ++i) { \
|
||||
if (_checkWatchpoints(debugger->watchpoints, base + 4 * i, 4)) { \
|
||||
ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT); \
|
||||
} \
|
||||
} \
|
||||
return debugger->originalMemory.NAME(cpu, address, mask, direction, cycleCounter); \
|
||||
}
|
||||
|
||||
CREATE_WATCHPOINT_SHIM(load32, 4, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
|
||||
CREATE_WATCHPOINT_SHIM(load16, 2, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
|
||||
CREATE_WATCHPOINT_SHIM(load8, 1, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
|
||||
CREATE_WATCHPOINT_SHIM(store32, 4, void, (struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter), address, value, cycleCounter)
|
||||
CREATE_WATCHPOINT_SHIM(store16, 2, void, (struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter), address, value, cycleCounter)
|
||||
CREATE_WATCHPOINT_SHIM(store8, 1, void, (struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter), address, value, cycleCounter)
|
||||
CREATE_MULTIPLE_WATCHPOINT_SHIM(loadMultiple)
|
||||
CREATE_MULTIPLE_WATCHPOINT_SHIM(storeMultiple)
|
||||
CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), address)
|
||||
|
||||
static bool _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width) {
|
||||
|
@ -66,6 +96,8 @@ void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger) {
|
|||
debugger->cpu->memory.load32 = ARMDebuggerShim_load32;
|
||||
debugger->cpu->memory.load16 = ARMDebuggerShim_load16;
|
||||
debugger->cpu->memory.load8 = ARMDebuggerShim_load8;
|
||||
debugger->cpu->memory.storeMultiple = ARMDebuggerShim_storeMultiple;
|
||||
debugger->cpu->memory.loadMultiple = ARMDebuggerShim_loadMultiple;
|
||||
debugger->cpu->memory.setActiveRegion = ARMDebuggerShim_setActiveRegion;
|
||||
}
|
||||
|
||||
|
@ -76,5 +108,7 @@ void ARMDebuggerRemoveMemoryShim(struct ARMDebugger* debugger) {
|
|||
debugger->cpu->memory.load32 = debugger->originalMemory.load32;
|
||||
debugger->cpu->memory.load16 = debugger->originalMemory.load16;
|
||||
debugger->cpu->memory.load8 = debugger->originalMemory.load8;
|
||||
debugger->cpu->memory.storeMultiple = debugger->originalMemory.storeMultiple;
|
||||
debugger->cpu->memory.loadMultiple = debugger->originalMemory.loadMultiple;
|
||||
debugger->cpu->memory.setActiveRegion = debugger->originalMemory.setActiveRegion;
|
||||
}
|
||||
|
|
|
@ -53,8 +53,8 @@ void GBAAudioReset(struct GBAAudio* audio) {
|
|||
audio->ch2 = (struct GBAAudioChannel2) { .envelope = { .nextStep = INT_MAX } };
|
||||
audio->ch3 = (struct GBAAudioChannel3) { .bank = { .bank = 0 } };
|
||||
audio->ch4 = (struct GBAAudioChannel4) { .envelope = { .nextStep = INT_MAX } };
|
||||
audio->chA.dmaSource = 0;
|
||||
audio->chB.dmaSource = 0;
|
||||
audio->chA.dmaSource = 1;
|
||||
audio->chB.dmaSource = 2;
|
||||
audio->chA.sample = 0;
|
||||
audio->chB.sample = 0;
|
||||
audio->eventDiff = 0;
|
||||
|
|
|
@ -215,7 +215,10 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
|
|||
ARMRaiseSWI(cpu);
|
||||
break;
|
||||
case 0xD:
|
||||
cpu->gprs[0] = GBAChecksum(gba->memory.bios, SIZE_BIOS);
|
||||
cpu->gprs[0] = GBA_BIOS_CHECKSUM;
|
||||
cpu->gprs[1] = 1;
|
||||
cpu->gprs[3] = SIZE_BIOS;
|
||||
break;
|
||||
case 0xE:
|
||||
_BgAffineSet(gba);
|
||||
break;
|
||||
|
@ -288,6 +291,7 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
|
|||
default:
|
||||
GBALog(gba, GBA_LOG_STUB, "Stub software interrupt: %02X", immediate);
|
||||
}
|
||||
gba->memory.biosPrefetch = 0xE3A02004;
|
||||
}
|
||||
|
||||
void GBASwi32(struct ARMCore* cpu, int immediate) {
|
||||
|
@ -385,12 +389,14 @@ static void _unHuffman(struct GBA* gba) {
|
|||
uint32_t header = cpu->memory.load32(cpu, source, 0);
|
||||
int remaining = header >> 8;
|
||||
int bits = header & 0xF;
|
||||
if (32 % bits) {
|
||||
if (bits == 0) {
|
||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Invalid Huffman bits");
|
||||
bits = 8;
|
||||
}
|
||||
if (32 % bits || bits == 1) {
|
||||
GBALog(gba, GBA_LOG_STUB, "Unimplemented unaligned Huffman");
|
||||
return;
|
||||
}
|
||||
int padding = (4 - remaining) & 0x3;
|
||||
remaining &= 0xFFFFFFFC;
|
||||
// We assume the signature byte (0x20) is correct
|
||||
int treesize = (cpu->memory.load8(cpu, source + 4, 0) << 1) + 1;
|
||||
int block = 0;
|
||||
|
@ -441,9 +447,6 @@ static void _unHuffman(struct GBA* gba) {
|
|||
}
|
||||
|
||||
}
|
||||
if (padding) {
|
||||
cpu->memory.store32(cpu, dest, block, 0);
|
||||
}
|
||||
cpu->gprs[0] = source;
|
||||
cpu->gprs[1] = dest;
|
||||
}
|
||||
|
|
|
@ -101,9 +101,10 @@ void GBAMemoryReset(struct GBA* gba) {
|
|||
memset(gba->memory.dma, 0, sizeof(gba->memory.dma));
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
gba->memory.dma[i].count = 0x10000;
|
||||
gba->memory.dma[i].count = 0x4000;
|
||||
gba->memory.dma[i].nextEvent = INT_MAX;
|
||||
}
|
||||
gba->memory.dma[3].count = 0x10000;
|
||||
gba->memory.activeDMA = -1;
|
||||
gba->memory.nextDMA = INT_MAX;
|
||||
gba->memory.eventDiff = 0;
|
||||
|
@ -300,7 +301,11 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
|
|||
++wait;
|
||||
|
||||
#define LOAD_VRAM \
|
||||
LOAD_32(value, address & 0x0001FFFF, gba->video.renderer->vram); \
|
||||
if ((address & 0x0001FFFF) < SIZE_VRAM) { \
|
||||
LOAD_32(value, address & 0x0001FFFF, gba->video.renderer->vram); \
|
||||
} else { \
|
||||
LOAD_32(value, address & 0x00017FFF, gba->video.renderer->vram); \
|
||||
} \
|
||||
++wait;
|
||||
|
||||
#define LOAD_OAM LOAD_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
|
||||
|
@ -388,14 +393,14 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
|||
LOAD_16(value, address, memory->bios);
|
||||
} else {
|
||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad BIOS Load16: 0x%08X", address);
|
||||
value = memory->biosPrefetch & 0xFFFF;
|
||||
LOAD_16(value, address & 2, &memory->biosPrefetch);
|
||||
}
|
||||
} else {
|
||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
|
||||
if (cpu->cycles >= cpu->nextEvent) {
|
||||
value = gba->bus & 0xFFFF;
|
||||
LOAD_16(value, address & 2, &gba->bus);
|
||||
} else {
|
||||
value = cpu->prefetch[1] & 0xFFFF;
|
||||
LOAD_16(value, address & 2, &cpu->prefetch[1]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -413,7 +418,11 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
|||
LOAD_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
|
||||
break;
|
||||
case REGION_VRAM:
|
||||
LOAD_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
|
||||
if ((address & 0x0001FFFF) < SIZE_VRAM) {
|
||||
LOAD_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
|
||||
} else {
|
||||
LOAD_16(value, address & 0x00017FFF, gba->video.renderer->vram);
|
||||
}
|
||||
break;
|
||||
case REGION_OAM:
|
||||
LOAD_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
|
||||
|
@ -451,9 +460,9 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
|||
default:
|
||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
|
||||
if (cpu->cycles >= cpu->nextEvent) {
|
||||
value = gba->bus;
|
||||
LOAD_16(value, address & 2, &gba->bus);
|
||||
} else {
|
||||
value = cpu->prefetch[1];
|
||||
LOAD_16(value, address & 2, &cpu->prefetch[1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -479,14 +488,14 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
|||
value = ((int8_t*) memory->bios)[address];
|
||||
} else {
|
||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad BIOS Load8: 0x%08X", address);
|
||||
value = memory->biosPrefetch;
|
||||
value = ((uint8_t*) &memory->biosPrefetch)[address & 3];
|
||||
}
|
||||
} else {
|
||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
|
||||
if (cpu->cycles >= cpu->nextEvent) {
|
||||
value = gba->bus;
|
||||
value = ((uint8_t*) &gba->bus)[address & 3];
|
||||
} else {
|
||||
value = cpu->prefetch[1];
|
||||
value = ((uint8_t*) &cpu->prefetch[1])[address & 3];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -504,7 +513,11 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
|||
value = ((int8_t*) gba->video.palette)[address & (SIZE_PALETTE_RAM - 1)];
|
||||
break;
|
||||
case REGION_VRAM:
|
||||
value = ((int8_t*) gba->video.renderer->vram)[address & 0x0001FFFF];
|
||||
if ((address & 0x0001FFFF) < SIZE_VRAM) {
|
||||
value = ((int8_t*) gba->video.renderer->vram)[address & 0x0001FFFF];
|
||||
} else {
|
||||
value = ((int8_t*) gba->video.renderer->vram)[address & 0x00017FFF];
|
||||
}
|
||||
break;
|
||||
case REGION_OAM:
|
||||
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load8: 0x%08X", address);
|
||||
|
@ -544,9 +557,9 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
|||
default:
|
||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
|
||||
if (cpu->cycles >= cpu->nextEvent) {
|
||||
value = gba->bus;
|
||||
value = ((uint8_t*) &gba->bus)[address & 3];
|
||||
} else {
|
||||
value = cpu->prefetch[1];
|
||||
value = ((uint8_t*) &cpu->prefetch[1])[address & 3];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -574,9 +587,9 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
|||
gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
|
||||
|
||||
#define STORE_VRAM \
|
||||
if ((address & OFFSET_MASK) < SIZE_VRAM) { \
|
||||
if ((address & 0x0001FFFF) < SIZE_VRAM) { \
|
||||
STORE_32(value, address & 0x0001FFFF, gba->video.renderer->vram); \
|
||||
} else if ((address & OFFSET_MASK) < 0x00020000) { \
|
||||
} else { \
|
||||
STORE_32(value, address & 0x00017FFF, gba->video.renderer->vram); \
|
||||
} \
|
||||
++wait;
|
||||
|
@ -663,9 +676,9 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle
|
|||
gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
|
||||
break;
|
||||
case REGION_VRAM:
|
||||
if ((address & OFFSET_MASK) < SIZE_VRAM) {
|
||||
if ((address & 0x0001FFFF) < SIZE_VRAM) {
|
||||
STORE_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
|
||||
} else if ((address & OFFSET_MASK) < 0x00020000) {
|
||||
} else {
|
||||
STORE_16(value, address & 0x00017FFF, gba->video.renderer->vram);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -40,6 +40,10 @@ void GBASerialize(struct GBA* gba, struct GBASerializedState* state) {
|
|||
memcpy(state->cpu.bankedRegisters, gba->cpu->bankedRegisters, 6 * 7 * sizeof(int32_t));
|
||||
memcpy(state->cpu.bankedSPSRs, gba->cpu->bankedSPSRs, 6 * sizeof(int32_t));
|
||||
|
||||
state->biosPrefetch = gba->memory.biosPrefetch;
|
||||
state->cpuPrefetch[0] = gba->cpu->prefetch[0];
|
||||
state->cpuPrefetch[1] = gba->cpu->prefetch[1];
|
||||
|
||||
GBAMemorySerialize(&gba->memory, state);
|
||||
GBAIOSerialize(gba, state);
|
||||
GBAVideoSerialize(&gba->video, state);
|
||||
|
@ -80,14 +84,29 @@ void GBADeserialize(struct GBA* gba, struct GBASerializedState* state) {
|
|||
memcpy(gba->cpu->bankedSPSRs, state->cpu.bankedSPSRs, 6 * sizeof(int32_t));
|
||||
gba->cpu->privilegeMode = gba->cpu->cpsr.priv;
|
||||
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
|
||||
if (state->biosPrefetch) {
|
||||
gba->memory.biosPrefetch = state->biosPrefetch;
|
||||
}
|
||||
if (gba->cpu->cpsr.t) {
|
||||
gba->cpu->executionMode = MODE_THUMB;
|
||||
LOAD_16(gba->cpu->prefetch[0], (gba->cpu->gprs[ARM_PC] - WORD_SIZE_THUMB) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
||||
LOAD_16(gba->cpu->prefetch[1], (gba->cpu->gprs[ARM_PC]) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
||||
if (state->cpuPrefetch[0] && state->cpuPrefetch[1]) {
|
||||
gba->cpu->prefetch[0] = state->cpuPrefetch[0] & 0xFFFF;
|
||||
gba->cpu->prefetch[1] = state->cpuPrefetch[1] & 0xFFFF;
|
||||
} else {
|
||||
// Maintain backwards compat
|
||||
LOAD_16(gba->cpu->prefetch[0], (gba->cpu->gprs[ARM_PC] - WORD_SIZE_THUMB) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
||||
LOAD_16(gba->cpu->prefetch[1], (gba->cpu->gprs[ARM_PC]) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
||||
}
|
||||
} else {
|
||||
gba->cpu->executionMode = MODE_ARM;
|
||||
LOAD_32(gba->cpu->prefetch[0], (gba->cpu->gprs[ARM_PC] - WORD_SIZE_ARM) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
||||
LOAD_32(gba->cpu->prefetch[1], (gba->cpu->gprs[ARM_PC]) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
||||
if (state->cpuPrefetch[0] && state->cpuPrefetch[1]) {
|
||||
gba->cpu->prefetch[0] = state->cpuPrefetch[0];
|
||||
gba->cpu->prefetch[1] = state->cpuPrefetch[1];
|
||||
} else {
|
||||
// Maintain backwards compat
|
||||
LOAD_32(gba->cpu->prefetch[0], (gba->cpu->gprs[ARM_PC] - WORD_SIZE_ARM) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
||||
LOAD_32(gba->cpu->prefetch[1], (gba->cpu->gprs[ARM_PC]) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
||||
}
|
||||
}
|
||||
|
||||
GBAMemoryDeserialize(&gba->memory, state);
|
||||
|
|
|
@ -150,7 +150,11 @@ extern const uint32_t GBA_SAVESTATE_MAGIC;
|
|||
* | 0x002C1 - 0x002C3: Flags
|
||||
* | bits 0 - 1: Tilt state machine
|
||||
* | bits 2 - 31: Reserved
|
||||
* 0x002C4 - 0x002FF: Reserved (leave zero)
|
||||
* 0x002C4 - 0x002F3: Reserved (leave zero)
|
||||
* 0x002F4 - 0x002FF: Prefetch
|
||||
* | 0x002F4 - 0x002F7: GBA BIOS bus prefetch
|
||||
* | 0x002F8 - 0x002FB: CPU prefecth (decode slot)
|
||||
* | 0x002FC - 0x002FF: CPU prefetch (fetch slot)
|
||||
* 0x00300 - 0x00303: Associated movie stream ID for record/replay (or 0 if no stream)
|
||||
* 0x00304 - 0x003FF: Reserved (leave zero)
|
||||
* 0x00400 - 0x007FF: I/O memory
|
||||
|
@ -267,7 +271,10 @@ struct GBASerializedState {
|
|||
unsigned : 22;
|
||||
} gpio;
|
||||
|
||||
uint32_t reservedGpio[15];
|
||||
uint32_t reservedGpio[12];
|
||||
|
||||
uint32_t biosPrefetch;
|
||||
uint32_t cpuPrefetch[2];
|
||||
|
||||
uint32_t associatedStreamId;
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ void GBAVideoInit(struct GBAVideo* video) {
|
|||
|
||||
void GBAVideoReset(struct GBAVideo* video) {
|
||||
video->dispstat = 0;
|
||||
video->vcount = 0;
|
||||
video->vcount = VIDEO_VERTICAL_TOTAL_PIXELS - 1;
|
||||
|
||||
video->lastHblank = 0;
|
||||
video->nextHblank = VIDEO_HDRAW_LENGTH;
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000;
|
||||
const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
|
||||
|
||||
static const size_t GBA_ROM_MAGIC_OFFSET = 2;
|
||||
static const uint8_t GBA_ROM_MAGIC[] = { 0x00, 0xEA };
|
||||
static const size_t GBA_ROM_MAGIC_OFFSET = 3;
|
||||
static const uint8_t GBA_ROM_MAGIC[] = { 0xEA };
|
||||
|
||||
static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component);
|
||||
static void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh);
|
||||
|
@ -145,7 +145,7 @@ void GBASkipBIOS(struct ARMCore* cpu) {
|
|||
static void GBAProcessEvents(struct ARMCore* cpu) {
|
||||
do {
|
||||
struct GBA* gba = (struct GBA*) cpu->master;
|
||||
int32_t cycles = cpu->cycles;
|
||||
int32_t cycles = cpu->nextEvent;
|
||||
int32_t nextEvent = INT_MAX;
|
||||
int32_t testEvent;
|
||||
|
||||
|
|
|
@ -1,55 +1,51 @@
|
|||
/* Copyright (c) 2013-2014 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 "hle-bios.h"
|
||||
|
||||
#include "gba-memory.h"
|
||||
|
||||
const uint8_t hleBios[SIZE_BIOS] = {
|
||||
0x06, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x05, 0x00, 0x00, 0xea,
|
||||
0x06, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x07, 0x00, 0x00, 0xea,
|
||||
0xfe, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe1,
|
||||
0x26, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0xf3, 0xa0, 0xe3,
|
||||
0x00, 0x00, 0x5d, 0xe3, 0x01, 0xd3, 0xa0, 0x03, 0x20, 0xd0, 0x4d, 0x02,
|
||||
0x00, 0x58, 0x2d, 0xe9, 0x02, 0xb0, 0x5e, 0xe5, 0x84, 0xc0, 0xa0, 0xe3,
|
||||
0x0b, 0xb1, 0x9c, 0xe7, 0x00, 0x00, 0x5b, 0xe3, 0x00, 0xc0, 0x4f, 0xe1,
|
||||
0x00, 0x10, 0x2d, 0xe9, 0x80, 0xc0, 0x0c, 0xe2, 0x1f, 0xc0, 0x8c, 0xe3,
|
||||
0x0c, 0xf0, 0x29, 0xe1, 0x00, 0x40, 0x2d, 0xe9, 0x0f, 0xe0, 0xa0, 0xe1,
|
||||
0x1b, 0xff, 0x2f, 0x11, 0x00, 0x40, 0xbd, 0xe8, 0x93, 0xf0, 0x29, 0xe3,
|
||||
0x00, 0x10, 0xbd, 0xe8, 0x0c, 0xf0, 0x69, 0xe1, 0x00, 0x58, 0xbd, 0xe8,
|
||||
0x0e, 0xf0, 0xb0, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0xa0, 0xe3,
|
||||
0x28, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0xf3, 0xa0, 0xe3,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1, 0x00, 0x00, 0x5d, 0xe3,
|
||||
0x01, 0xd3, 0xa0, 0x03, 0x20, 0xd0, 0x4d, 0x02, 0x00, 0x58, 0x2d, 0xe9,
|
||||
0x02, 0xb0, 0x5e, 0xe5, 0x8c, 0xc0, 0xa0, 0xe3, 0x0b, 0xb1, 0x9c, 0xe7,
|
||||
0x00, 0x00, 0x5b, 0xe3, 0x00, 0xc0, 0x4f, 0xe1, 0x00, 0x10, 0x2d, 0xe9,
|
||||
0x80, 0xc0, 0x0c, 0xe2, 0x1f, 0xc0, 0x8c, 0xe3, 0x0c, 0xf0, 0x29, 0xe1,
|
||||
0x00, 0x40, 0x2d, 0xe9, 0x0f, 0xe0, 0xa0, 0xe1, 0x1b, 0xff, 0x2f, 0x11,
|
||||
0x00, 0x40, 0xbd, 0xe8, 0x93, 0xf0, 0x29, 0xe3, 0x00, 0x10, 0xbd, 0xe8,
|
||||
0x0c, 0xf0, 0x69, 0xe1, 0x00, 0x58, 0xbd, 0xe8, 0x0e, 0xf0, 0xb0, 0xe1,
|
||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0xa0, 0xe3, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00,
|
||||
0xe8, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
|
||||
0xb0, 0x01, 0x00, 0x00, 0x0f, 0x50, 0x2d, 0xe9, 0x01, 0x03, 0xa0, 0xe3,
|
||||
0x00, 0xe0, 0x8f, 0xe2, 0x04, 0xf0, 0x10, 0xe5, 0x0f, 0x50, 0xbd, 0xe8,
|
||||
0x04, 0xf0, 0x5e, 0xe2, 0x01, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3,
|
||||
0x0c, 0x40, 0x2d, 0xe9, 0x01, 0xc3, 0xa0, 0xe3, 0x00, 0x00, 0x50, 0xe3,
|
||||
0x00, 0x00, 0xa0, 0xe3, 0x01, 0x20, 0xa0, 0xe3, 0x03, 0x00, 0x00, 0x0a,
|
||||
0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0xc3, 0xe1, 0xb8, 0x30, 0x4c, 0xe1,
|
||||
0x01, 0x03, 0xcc, 0xe5, 0x08, 0x02, 0xcc, 0xe5, 0xb8, 0x30, 0x5c, 0xe1,
|
||||
0x01, 0x30, 0x13, 0xe0, 0x01, 0x30, 0x23, 0x10, 0xb8, 0x30, 0x4c, 0x11,
|
||||
0x08, 0x22, 0xcc, 0xe5, 0xf7, 0xff, 0xff, 0x0a, 0x0c, 0x80, 0xbd, 0xe8,
|
||||
0x00, 0x40, 0x2d, 0xe9, 0x02, 0x36, 0xa0, 0xe1, 0x01, 0x04, 0x12, 0xe3,
|
||||
0x0f, 0x00, 0x00, 0x0a, 0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a,
|
||||
0x23, 0x35, 0x81, 0xe0, 0x04, 0x00, 0xb0, 0xe8, 0x03, 0x00, 0x51, 0xe1,
|
||||
0x04, 0x00, 0xa1, 0xb8, 0xfc, 0xff, 0xff, 0xba, 0x16, 0x00, 0x00, 0xea,
|
||||
0x01, 0x00, 0xc0, 0xe3, 0x01, 0x10, 0xc1, 0xe3, 0xa3, 0x35, 0x81, 0xe0,
|
||||
0xb0, 0x20, 0xd0, 0xe1, 0x03, 0x00, 0x51, 0xe1, 0xb2, 0x20, 0xc1, 0xb0,
|
||||
0xfc, 0xff, 0xff, 0xba, 0x0e, 0x00, 0x00, 0xea, 0x01, 0x03, 0x12, 0xe3,
|
||||
0x05, 0x00, 0x00, 0x0a, 0x23, 0x35, 0x81, 0xe0, 0x03, 0x00, 0x51, 0xe1,
|
||||
0x04, 0x00, 0xb0, 0xb8, 0x04, 0x00, 0xa1, 0xb8, 0xfb, 0xff, 0xff, 0xba,
|
||||
0x06, 0x00, 0x00, 0xea, 0xa3, 0x35, 0x81, 0xe0, 0x01, 0x00, 0xc0, 0xe3,
|
||||
0x01, 0x10, 0xc1, 0xe3, 0x03, 0x00, 0x51, 0xe1, 0xb2, 0x20, 0xd0, 0xb0,
|
||||
0xb2, 0x20, 0xc1, 0xb0, 0xfb, 0xff, 0xff, 0xba, 0x00, 0x80, 0xbd, 0xe8,
|
||||
0xf0, 0x47, 0x2d, 0xe9, 0x01, 0x04, 0x12, 0xe3, 0x02, 0x36, 0xa0, 0xe1,
|
||||
0x23, 0x25, 0x81, 0xe0, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x90, 0xe5,
|
||||
0x03, 0x40, 0xa0, 0xe1, 0x03, 0x50, 0xa0, 0xe1, 0x03, 0x60, 0xa0, 0xe1,
|
||||
0x03, 0x70, 0xa0, 0xe1, 0x03, 0x80, 0xa0, 0xe1, 0x03, 0x90, 0xa0, 0xe1,
|
||||
0x03, 0xa0, 0xa0, 0xe1, 0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xa1, 0xb8,
|
||||
0xfc, 0xff, 0xff, 0xba, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x51, 0xe1,
|
||||
0xf8, 0x07, 0xb0, 0xb8, 0xf8, 0x07, 0xa1, 0xb8, 0xfb, 0xff, 0xff, 0xba,
|
||||
0xf0, 0x87, 0xbd, 0xe8
|
||||
0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00,
|
||||
0x0f, 0x50, 0x2d, 0xe9, 0x01, 0x03, 0xa0, 0xe3, 0x00, 0xe0, 0x8f, 0xe2,
|
||||
0x04, 0xf0, 0x10, 0xe5, 0x0f, 0x50, 0xbd, 0xe8, 0x04, 0xf0, 0x5e, 0xe2,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x5e, 0xe5, 0x01, 0x00, 0xa0, 0xe3,
|
||||
0x01, 0x10, 0xa0, 0xe3, 0x0c, 0x40, 0x2d, 0xe9, 0x01, 0xc3, 0xa0, 0xe3,
|
||||
0x00, 0x00, 0x50, 0xe3, 0x00, 0x00, 0xa0, 0xe3, 0x01, 0x20, 0xa0, 0xe3,
|
||||
0x03, 0x00, 0x00, 0x0a, 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0xc3, 0xe1,
|
||||
0xb8, 0x30, 0x4c, 0xe1, 0x01, 0x03, 0xcc, 0xe5, 0x08, 0x02, 0xcc, 0xe5,
|
||||
0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0x13, 0xe0, 0x01, 0x30, 0x23, 0x10,
|
||||
0xb8, 0x30, 0x4c, 0x11, 0x08, 0x22, 0xcc, 0xe5, 0xf7, 0xff, 0xff, 0x0a,
|
||||
0x0c, 0x80, 0xbd, 0xe8, 0x00, 0x40, 0x2d, 0xe9, 0x02, 0x36, 0xa0, 0xe1,
|
||||
0x01, 0x04, 0x12, 0xe3, 0x0f, 0x00, 0x00, 0x0a, 0x01, 0x03, 0x12, 0xe3,
|
||||
0x05, 0x00, 0x00, 0x0a, 0x23, 0x35, 0x81, 0xe0, 0x04, 0x00, 0xb0, 0xe8,
|
||||
0x03, 0x00, 0x51, 0xe1, 0x04, 0x00, 0xa1, 0xb8, 0xfc, 0xff, 0xff, 0xba,
|
||||
0x16, 0x00, 0x00, 0xea, 0x01, 0x00, 0xc0, 0xe3, 0x01, 0x10, 0xc1, 0xe3,
|
||||
0xa3, 0x35, 0x81, 0xe0, 0xb0, 0x20, 0xd0, 0xe1, 0x03, 0x00, 0x51, 0xe1,
|
||||
0xb2, 0x20, 0xc1, 0xb0, 0xfc, 0xff, 0xff, 0xba, 0x0e, 0x00, 0x00, 0xea,
|
||||
0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a, 0x23, 0x35, 0x81, 0xe0,
|
||||
0x03, 0x00, 0x51, 0xe1, 0x04, 0x00, 0xb0, 0xb8, 0x04, 0x00, 0xa1, 0xb8,
|
||||
0xfb, 0xff, 0xff, 0xba, 0x06, 0x00, 0x00, 0xea, 0xa3, 0x35, 0x81, 0xe0,
|
||||
0x01, 0x00, 0xc0, 0xe3, 0x01, 0x10, 0xc1, 0xe3, 0x03, 0x00, 0x51, 0xe1,
|
||||
0xb2, 0x20, 0xd0, 0xb0, 0xb2, 0x20, 0xc1, 0xb0, 0xfb, 0xff, 0xff, 0xba,
|
||||
0x00, 0x80, 0xbd, 0xe8, 0xf0, 0x47, 0x2d, 0xe9, 0x01, 0x04, 0x12, 0xe3,
|
||||
0x02, 0x36, 0xa0, 0xe1, 0x23, 0x25, 0x81, 0xe0, 0x0b, 0x00, 0x00, 0x0a,
|
||||
0x00, 0x30, 0x90, 0xe5, 0x03, 0x40, 0xa0, 0xe1, 0x03, 0x50, 0xa0, 0xe1,
|
||||
0x03, 0x60, 0xa0, 0xe1, 0x03, 0x70, 0xa0, 0xe1, 0x03, 0x80, 0xa0, 0xe1,
|
||||
0x03, 0x90, 0xa0, 0xe1, 0x03, 0xa0, 0xa0, 0xe1, 0x02, 0x00, 0x51, 0xe1,
|
||||
0xf8, 0x07, 0xa1, 0xb8, 0xfc, 0xff, 0xff, 0xba, 0x03, 0x00, 0x00, 0xea,
|
||||
0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xb0, 0xb8, 0xf8, 0x07, 0xa1, 0xb8,
|
||||
0xfb, 0xff, 0xff, 0xba, 0xf0, 0x87, 0xbd, 0xe8
|
||||
};
|
||||
|
|
|
@ -18,6 +18,8 @@ b fiqBase
|
|||
|
||||
resetBase:
|
||||
mov pc, #0x8000000
|
||||
.word 0
|
||||
.word 0xE129F000
|
||||
|
||||
swiBase:
|
||||
cmp sp, #0
|
||||
|
@ -68,6 +70,8 @@ add lr, pc, #0
|
|||
ldr pc, [r0, #-4]
|
||||
ldmfd sp!, {r0-r3, r12, lr}
|
||||
subs pc, lr, #4
|
||||
.word 0
|
||||
.word 0xE55EC002
|
||||
|
||||
VBlankIntrWait:
|
||||
mov r0, #1
|
||||
|
|
|
@ -1010,6 +1010,10 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
|
|||
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \
|
||||
palette = &mainPalette[paletteData]; \
|
||||
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \
|
||||
if (UNLIKELY(charBase >= 0x10000)) { \
|
||||
pixel += 8; \
|
||||
continue; \
|
||||
} \
|
||||
LOAD_32(tileData, charBase, vram); \
|
||||
if (tileData) { \
|
||||
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
||||
|
@ -1058,35 +1062,43 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
|
|||
int end2 = end - 4; \
|
||||
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
||||
int shift = inX & 0x3; \
|
||||
if (end2 > outX) { \
|
||||
LOAD_32(tileData, charBase, vram); \
|
||||
tileData >>= 8 * shift; \
|
||||
shift = 0; \
|
||||
for (; outX < end2; ++outX, ++pixel) { \
|
||||
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
||||
if (LIKELY(charBase < 0x10000)) { \
|
||||
if (end2 > outX) { \
|
||||
LOAD_32(tileData, charBase, vram); \
|
||||
tileData >>= 8 * shift; \
|
||||
shift = 0; \
|
||||
for (; outX < end2; ++outX, ++pixel) { \
|
||||
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
LOAD_32(tileData, charBase + 4, vram); \
|
||||
tileData >>= 8 * shift; \
|
||||
for (; outX < end; ++outX, ++pixel) { \
|
||||
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
||||
if (LIKELY(charBase < 0x10000)) { \
|
||||
LOAD_32(tileData, charBase + 4, vram); \
|
||||
tileData >>= 8 * shift; \
|
||||
for (; outX < end; ++outX, ++pixel) { \
|
||||
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
int start = outX; \
|
||||
outX = end - 1; \
|
||||
pixel = &renderer->row[outX]; \
|
||||
if (end2 > start) { \
|
||||
LOAD_32(tileData, charBase, vram); \
|
||||
for (; outX >= end2; --outX, --pixel) { \
|
||||
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
||||
if (LIKELY(charBase < 0x10000)) { \
|
||||
if (end2 > start) { \
|
||||
LOAD_32(tileData, charBase, vram); \
|
||||
for (; outX >= end2; --outX, --pixel) { \
|
||||
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
||||
} \
|
||||
charBase += 4; \
|
||||
} \
|
||||
charBase += 4; \
|
||||
} \
|
||||
\
|
||||
LOAD_32(tileData, charBase, vram); \
|
||||
for (; outX >= renderer->start; --outX, --pixel) { \
|
||||
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
||||
if (LIKELY(charBase < 0x10000)) { \
|
||||
LOAD_32(tileData, charBase, vram); \
|
||||
for (; outX >= renderer->start; --outX, --pixel) { \
|
||||
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
||||
} \
|
||||
} \
|
||||
outX = end; \
|
||||
pixel = &renderer->row[outX]; \
|
||||
|
@ -1094,6 +1106,9 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
|
|||
|
||||
#define DRAW_BACKGROUND_MODE_0_TILE_PREFIX_256(BLEND, OBJWIN) \
|
||||
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
|
||||
if (UNLIKELY(charBase >= 0x10000)) { \
|
||||
return; \
|
||||
} \
|
||||
int end = mod8 - 4; \
|
||||
pixel = &renderer->row[outX]; \
|
||||
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
||||
|
@ -1139,6 +1154,10 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
|
|||
for (; tileX < tileEnd; ++tileX) { \
|
||||
BACKGROUND_TEXT_SELECT_CHARACTER; \
|
||||
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
|
||||
if (UNLIKELY(charBase >= 0x10000)) { \
|
||||
pixel += 8; \
|
||||
continue; \
|
||||
} \
|
||||
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
||||
LOAD_32(tileData, charBase, vram); \
|
||||
if (tileData) { \
|
||||
|
|
|
@ -112,46 +112,43 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents
|
|||
}
|
||||
return;
|
||||
}
|
||||
switch (event->keysym.sym) {
|
||||
case SDLK_F11:
|
||||
if (event->type == SDL_KEYDOWN && context->debugger) {
|
||||
ARMDebuggerEnter(context->debugger, DEBUGGER_ENTER_MANUAL);
|
||||
}
|
||||
if (event->keysym.sym == SDLK_TAB) {
|
||||
context->sync.audioWait = event->type != SDL_KEYDOWN;
|
||||
return;
|
||||
}
|
||||
if (event->type == SDL_KEYDOWN) {
|
||||
switch (event->keysym.sym) {
|
||||
case SDLK_F11:
|
||||
if (context->debugger) {
|
||||
ARMDebuggerEnter(context->debugger, DEBUGGER_ENTER_MANUAL);
|
||||
}
|
||||
return;
|
||||
#ifdef USE_PNG
|
||||
case SDLK_F12:
|
||||
if (event->type == SDL_KEYDOWN) {
|
||||
case SDLK_F12:
|
||||
GBAThreadInterrupt(context);
|
||||
GBAThreadTakeScreenshot(context);
|
||||
GBAThreadContinue(context);
|
||||
}
|
||||
return;
|
||||
return;
|
||||
#endif
|
||||
case SDLK_TAB:
|
||||
context->sync.audioWait = event->type != SDL_KEYDOWN;
|
||||
return;
|
||||
case SDLK_BACKSLASH:
|
||||
if (event->type == SDL_KEYDOWN) {
|
||||
case SDLK_BACKSLASH:
|
||||
GBAThreadPause(context);
|
||||
context->frameCallback = _pauseAfterFrame;
|
||||
GBAThreadUnpause(context);
|
||||
}
|
||||
return;
|
||||
case SDLK_LEFTBRACKET:
|
||||
GBAThreadInterrupt(context);
|
||||
GBARewind(context, 10);
|
||||
GBAThreadContinue(context);
|
||||
return;
|
||||
case SDLK_ESCAPE:
|
||||
GBAThreadInterrupt(context);
|
||||
if (context->gba->rr) {
|
||||
GBARRStopPlaying(context->gba->rr);
|
||||
GBARRStopRecording(context->gba->rr);
|
||||
}
|
||||
GBAThreadContinue(context);
|
||||
return;
|
||||
default:
|
||||
if (event->type == SDL_KEYDOWN) {
|
||||
return;
|
||||
case SDLK_BACKQUOTE:
|
||||
GBAThreadInterrupt(context);
|
||||
GBARewind(context, 10);
|
||||
GBAThreadContinue(context);
|
||||
return;
|
||||
case SDLK_ESCAPE:
|
||||
GBAThreadInterrupt(context);
|
||||
if (context->gba->rr) {
|
||||
GBARRStopPlaying(context->gba->rr);
|
||||
GBARRStopRecording(context->gba->rr);
|
||||
}
|
||||
GBAThreadContinue(context);
|
||||
return;
|
||||
default:
|
||||
if ((event->keysym.mod & GUI_MOD) && (event->keysym.mod & GUI_MOD) == event->keysym.mod) {
|
||||
switch (event->keysym.sym) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
|
@ -238,8 +235,8 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents
|
|||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -129,6 +129,9 @@ bool _BPSApplyPatch(struct Patch* patch, void* in, size_t inSize, void* out, siz
|
|||
if (_decodeLength(patch->vf) != outSize) {
|
||||
return false;
|
||||
}
|
||||
if (inSize > SSIZE_MAX || outSize > SSIZE_MAX) {
|
||||
return false;
|
||||
}
|
||||
size_t metadataLength = _decodeLength(patch->vf);
|
||||
patch->vf->seek(patch->vf, metadataLength, SEEK_CUR); // Skip metadata
|
||||
size_t writeLocation = 0;
|
||||
|
@ -153,7 +156,7 @@ bool _BPSApplyPatch(struct Patch* patch, void* in, size_t inSize, void* out, siz
|
|||
break;
|
||||
case 0x1:
|
||||
// TargetRead
|
||||
if (patch->vf->read(patch->vf, &writeBuffer[writeLocation], length) != length) {
|
||||
if (patch->vf->read(patch->vf, &writeBuffer[writeLocation], length) != (ssize_t) length) {
|
||||
return false;
|
||||
}
|
||||
outputChecksum = updateCrc32(outputChecksum, &writeBuffer[writeLocation], length);
|
||||
|
@ -167,7 +170,7 @@ bool _BPSApplyPatch(struct Patch* patch, void* in, size_t inSize, void* out, siz
|
|||
} else {
|
||||
readSourceLocation += readOffset >> 1;
|
||||
}
|
||||
if (readSourceLocation < 0 || readSourceLocation > inSize) {
|
||||
if (readSourceLocation < 0 || readSourceLocation > (ssize_t) inSize) {
|
||||
return false;
|
||||
}
|
||||
memmove(&writeBuffer[writeLocation], &readBuffer[readSourceLocation], length);
|
||||
|
@ -183,7 +186,7 @@ bool _BPSApplyPatch(struct Patch* patch, void* in, size_t inSize, void* out, siz
|
|||
} else {
|
||||
readTargetLocation += readOffset >> 1;
|
||||
}
|
||||
if (readTargetLocation < 0 || readTargetLocation > outSize) {
|
||||
if (readTargetLocation < 0 || readTargetLocation > (ssize_t) outSize) {
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < length; ++i) {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#define SOCKET_FAILED(s) (s) == INVALID_SOCKET
|
||||
#define SOCKET_FAILED(s) ((s) == INVALID_SOCKET)
|
||||
typedef SOCKET Socket;
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
|
@ -25,7 +25,7 @@ typedef SOCKET Socket;
|
|||
#include <sys/socket.h>
|
||||
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define SOCKET_FAILED(s) (s) < 0
|
||||
#define SOCKET_FAILED(s) ((s) < 0)
|
||||
typedef int Socket;
|
||||
#endif
|
||||
|
||||
|
@ -157,7 +157,7 @@ static inline int SocketClose(Socket socket) {
|
|||
return close(socket) >= 0;
|
||||
}
|
||||
|
||||
static inline int SocketSetBlocking(Socket socket, int blocking) {
|
||||
static inline int SocketSetBlocking(Socket socket, bool blocking) {
|
||||
#ifdef _WIN32
|
||||
u_long unblocking = !blocking;
|
||||
return ioctlsocket(socket, FIONBIO, &unblocking) == NO_ERROR;
|
||||
|
|
|
@ -76,7 +76,7 @@ class Suite(object):
|
|||
def collect_tests(self):
|
||||
roms = []
|
||||
for f in os.listdir(self.cwd):
|
||||
if f.endswith('.gba'):
|
||||
if f.endswith('.gba') or f.endswith('.zip'):
|
||||
roms.append(f)
|
||||
roms.sort()
|
||||
for rom in roms:
|
||||
|
|
Loading…
Reference in New Issue