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
|
- Save directory of last loaded file
|
||||||
- Support BPS patches
|
- Support BPS patches
|
||||||
- Automatically detect and optimize out idle loops
|
- Automatically detect and optimize out idle loops
|
||||||
|
- Configurable game overrides
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
- Qt: Fix issue with set frame sizes being the wrong height
|
- Qt: Fix issue with set frame sizes being the wrong height
|
||||||
- Qt: Fix emulator crashing when full screen if a game is not running
|
- 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
|
- GBA Memory: Filter out top nybble of DMA addresses
|
||||||
- Debugger: Fix binary print putting spaces between digits
|
- Debugger: Fix binary print putting spaces between digits
|
||||||
- GBA BIOS: Fix LZ77UnCompVram to use 16-bit loads from decompressed memory
|
- 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:
|
Misc:
|
||||||
- Qt: Disable sync to video by default
|
- Qt: Disable sync to video by default
|
||||||
- GBA: Exit cleanly on FATAL if the port supports it
|
- 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
|
- GBA Memory: Implement 16- and 32-bit loads from SRAM
|
||||||
- Qt: Clear active buttons when focus is lost
|
- Qt: Clear active buttons when focus is lost
|
||||||
- GBA Memory: Simplify memory API and use fixed bus width
|
- 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)
|
0.1.0: (2014-12-13)
|
||||||
- Initial release
|
- Initial release
|
||||||
|
|
|
@ -53,15 +53,39 @@ static void _gdbStubEntered(struct ARMDebugger* debugger, enum DebuggerEntryReas
|
||||||
|
|
||||||
static void _gdbStubPoll(struct ARMDebugger* debugger) {
|
static void _gdbStubPoll(struct ARMDebugger* debugger) {
|
||||||
struct GDBStub* stub = (struct GDBStub*) debugger;
|
struct GDBStub* stub = (struct GDBStub*) debugger;
|
||||||
while (stub->d.state == DEBUGGER_PAUSED) {
|
--stub->untilPoll;
|
||||||
if (!SOCKET_FAILED(stub->connection)) {
|
if (stub->untilPoll > 0) {
|
||||||
if (!SocketSetBlocking(stub->connection, 1)) {
|
return;
|
||||||
GDBStubHangup(stub);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GDBStubUpdate(stub);
|
|
||||||
}
|
}
|
||||||
|
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) {
|
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) {
|
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 (!SOCKET_FAILED(stub->connection)) {
|
||||||
if (!SocketSetBlocking(stub->connection, 0)) {
|
if (!SocketSetBlocking(stub->connection, 0)) {
|
||||||
GDBStubHangup(stub);
|
GDBStubHangup(stub);
|
||||||
|
@ -441,9 +466,11 @@ void GDBStubCreate(struct GDBStub* stub) {
|
||||||
stub->connection = INVALID_SOCKET;
|
stub->connection = INVALID_SOCKET;
|
||||||
stub->d.init = 0;
|
stub->d.init = 0;
|
||||||
stub->d.deinit = _gdbStubDeinit;
|
stub->d.deinit = _gdbStubDeinit;
|
||||||
stub->d.paused = _gdbStubPoll;
|
stub->d.paused = _gdbStubWait;
|
||||||
stub->d.entered = _gdbStubEntered;
|
stub->d.entered = _gdbStubEntered;
|
||||||
|
stub->d.custom = _gdbStubPoll;
|
||||||
stub->d.log = 0;
|
stub->d.log = 0;
|
||||||
|
stub->untilPoll = GDB_STUB_INTERVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GDBStubListen(struct GDBStub* stub, int port, const struct Address* bindAddress) {
|
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) {
|
if (err) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (!SocketSetBlocking(stub->socket, 0)) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -501,9 +525,6 @@ void GDBStubUpdate(struct GDBStub* stub) {
|
||||||
if (stub->connection == INVALID_SOCKET) {
|
if (stub->connection == INVALID_SOCKET) {
|
||||||
stub->connection = SocketAccept(stub->socket, 0);
|
stub->connection = SocketAccept(stub->socket, 0);
|
||||||
if (!SOCKET_FAILED(stub->connection)) {
|
if (!SOCKET_FAILED(stub->connection)) {
|
||||||
if (!SocketSetBlocking(stub->connection, 0)) {
|
|
||||||
goto connectionLost;
|
|
||||||
}
|
|
||||||
ARMDebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED);
|
ARMDebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED);
|
||||||
} else if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
} else if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "util/socket.h"
|
#include "util/socket.h"
|
||||||
|
|
||||||
#define GDB_STUB_MAX_LINE 1200
|
#define GDB_STUB_MAX_LINE 1200
|
||||||
|
#define GDB_STUB_INTERVAL 32
|
||||||
|
|
||||||
enum GDBStubAckState {
|
enum GDBStubAckState {
|
||||||
GDB_ACK_PENDING = 0,
|
GDB_ACK_PENDING = 0,
|
||||||
|
@ -30,6 +31,9 @@ struct GDBStub {
|
||||||
|
|
||||||
Socket socket;
|
Socket socket;
|
||||||
Socket connection;
|
Socket connection;
|
||||||
|
|
||||||
|
bool shouldBlock;
|
||||||
|
int untilPoll;
|
||||||
};
|
};
|
||||||
|
|
||||||
void GDBStubCreate(struct GDBStub*);
|
void GDBStubCreate(struct GDBStub*);
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static bool _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width);
|
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) \
|
#define FIND_DEBUGGER(DEBUGGER, CPU) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -40,12 +45,37 @@ static bool _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t addr
|
||||||
return debugger->originalMemory.NAME(cpu, ARGS); \
|
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(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(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(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(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(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_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)
|
CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), address)
|
||||||
|
|
||||||
static bool _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width) {
|
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.load32 = ARMDebuggerShim_load32;
|
||||||
debugger->cpu->memory.load16 = ARMDebuggerShim_load16;
|
debugger->cpu->memory.load16 = ARMDebuggerShim_load16;
|
||||||
debugger->cpu->memory.load8 = ARMDebuggerShim_load8;
|
debugger->cpu->memory.load8 = ARMDebuggerShim_load8;
|
||||||
|
debugger->cpu->memory.storeMultiple = ARMDebuggerShim_storeMultiple;
|
||||||
|
debugger->cpu->memory.loadMultiple = ARMDebuggerShim_loadMultiple;
|
||||||
debugger->cpu->memory.setActiveRegion = ARMDebuggerShim_setActiveRegion;
|
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.load32 = debugger->originalMemory.load32;
|
||||||
debugger->cpu->memory.load16 = debugger->originalMemory.load16;
|
debugger->cpu->memory.load16 = debugger->originalMemory.load16;
|
||||||
debugger->cpu->memory.load8 = debugger->originalMemory.load8;
|
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;
|
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->ch2 = (struct GBAAudioChannel2) { .envelope = { .nextStep = INT_MAX } };
|
||||||
audio->ch3 = (struct GBAAudioChannel3) { .bank = { .bank = 0 } };
|
audio->ch3 = (struct GBAAudioChannel3) { .bank = { .bank = 0 } };
|
||||||
audio->ch4 = (struct GBAAudioChannel4) { .envelope = { .nextStep = INT_MAX } };
|
audio->ch4 = (struct GBAAudioChannel4) { .envelope = { .nextStep = INT_MAX } };
|
||||||
audio->chA.dmaSource = 0;
|
audio->chA.dmaSource = 1;
|
||||||
audio->chB.dmaSource = 0;
|
audio->chB.dmaSource = 2;
|
||||||
audio->chA.sample = 0;
|
audio->chA.sample = 0;
|
||||||
audio->chB.sample = 0;
|
audio->chB.sample = 0;
|
||||||
audio->eventDiff = 0;
|
audio->eventDiff = 0;
|
||||||
|
|
|
@ -215,7 +215,10 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
|
||||||
ARMRaiseSWI(cpu);
|
ARMRaiseSWI(cpu);
|
||||||
break;
|
break;
|
||||||
case 0xD:
|
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:
|
case 0xE:
|
||||||
_BgAffineSet(gba);
|
_BgAffineSet(gba);
|
||||||
break;
|
break;
|
||||||
|
@ -288,6 +291,7 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
|
||||||
default:
|
default:
|
||||||
GBALog(gba, GBA_LOG_STUB, "Stub software interrupt: %02X", immediate);
|
GBALog(gba, GBA_LOG_STUB, "Stub software interrupt: %02X", immediate);
|
||||||
}
|
}
|
||||||
|
gba->memory.biosPrefetch = 0xE3A02004;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBASwi32(struct ARMCore* cpu, int immediate) {
|
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);
|
uint32_t header = cpu->memory.load32(cpu, source, 0);
|
||||||
int remaining = header >> 8;
|
int remaining = header >> 8;
|
||||||
int bits = header & 0xF;
|
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");
|
GBALog(gba, GBA_LOG_STUB, "Unimplemented unaligned Huffman");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int padding = (4 - remaining) & 0x3;
|
|
||||||
remaining &= 0xFFFFFFFC;
|
|
||||||
// We assume the signature byte (0x20) is correct
|
// We assume the signature byte (0x20) is correct
|
||||||
int treesize = (cpu->memory.load8(cpu, source + 4, 0) << 1) + 1;
|
int treesize = (cpu->memory.load8(cpu, source + 4, 0) << 1) + 1;
|
||||||
int block = 0;
|
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[0] = source;
|
||||||
cpu->gprs[1] = dest;
|
cpu->gprs[1] = dest;
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,9 +101,10 @@ void GBAMemoryReset(struct GBA* gba) {
|
||||||
memset(gba->memory.dma, 0, sizeof(gba->memory.dma));
|
memset(gba->memory.dma, 0, sizeof(gba->memory.dma));
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 4; ++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[i].nextEvent = INT_MAX;
|
||||||
}
|
}
|
||||||
|
gba->memory.dma[3].count = 0x10000;
|
||||||
gba->memory.activeDMA = -1;
|
gba->memory.activeDMA = -1;
|
||||||
gba->memory.nextDMA = INT_MAX;
|
gba->memory.nextDMA = INT_MAX;
|
||||||
gba->memory.eventDiff = 0;
|
gba->memory.eventDiff = 0;
|
||||||
|
@ -300,7 +301,11 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
|
||||||
++wait;
|
++wait;
|
||||||
|
|
||||||
#define LOAD_VRAM \
|
#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;
|
++wait;
|
||||||
|
|
||||||
#define LOAD_OAM LOAD_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
|
#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);
|
LOAD_16(value, address, memory->bios);
|
||||||
} else {
|
} else {
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad BIOS Load16: 0x%08X", address);
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad BIOS Load16: 0x%08X", address);
|
||||||
value = memory->biosPrefetch & 0xFFFF;
|
LOAD_16(value, address & 2, &memory->biosPrefetch);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
|
||||||
if (cpu->cycles >= cpu->nextEvent) {
|
if (cpu->cycles >= cpu->nextEvent) {
|
||||||
value = gba->bus & 0xFFFF;
|
LOAD_16(value, address & 2, &gba->bus);
|
||||||
} else {
|
} else {
|
||||||
value = cpu->prefetch[1] & 0xFFFF;
|
LOAD_16(value, address & 2, &cpu->prefetch[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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);
|
LOAD_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
|
||||||
break;
|
break;
|
||||||
case REGION_VRAM:
|
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;
|
break;
|
||||||
case REGION_OAM:
|
case REGION_OAM:
|
||||||
LOAD_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
|
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:
|
default:
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
|
||||||
if (cpu->cycles >= cpu->nextEvent) {
|
if (cpu->cycles >= cpu->nextEvent) {
|
||||||
value = gba->bus;
|
LOAD_16(value, address & 2, &gba->bus);
|
||||||
} else {
|
} else {
|
||||||
value = cpu->prefetch[1];
|
LOAD_16(value, address & 2, &cpu->prefetch[1]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -479,14 +488,14 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
value = ((int8_t*) memory->bios)[address];
|
value = ((int8_t*) memory->bios)[address];
|
||||||
} else {
|
} else {
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad BIOS Load8: 0x%08X", address);
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad BIOS Load8: 0x%08X", address);
|
||||||
value = memory->biosPrefetch;
|
value = ((uint8_t*) &memory->biosPrefetch)[address & 3];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
|
||||||
if (cpu->cycles >= cpu->nextEvent) {
|
if (cpu->cycles >= cpu->nextEvent) {
|
||||||
value = gba->bus;
|
value = ((uint8_t*) &gba->bus)[address & 3];
|
||||||
} else {
|
} else {
|
||||||
value = cpu->prefetch[1];
|
value = ((uint8_t*) &cpu->prefetch[1])[address & 3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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)];
|
value = ((int8_t*) gba->video.palette)[address & (SIZE_PALETTE_RAM - 1)];
|
||||||
break;
|
break;
|
||||||
case REGION_VRAM:
|
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;
|
break;
|
||||||
case REGION_OAM:
|
case REGION_OAM:
|
||||||
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load8: 0x%08X", address);
|
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:
|
default:
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
|
||||||
if (cpu->cycles >= cpu->nextEvent) {
|
if (cpu->cycles >= cpu->nextEvent) {
|
||||||
value = gba->bus;
|
value = ((uint8_t*) &gba->bus)[address & 3];
|
||||||
} else {
|
} else {
|
||||||
value = cpu->prefetch[1];
|
value = ((uint8_t*) &cpu->prefetch[1])[address & 3];
|
||||||
}
|
}
|
||||||
break;
|
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);
|
gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
|
||||||
|
|
||||||
#define STORE_VRAM \
|
#define STORE_VRAM \
|
||||||
if ((address & OFFSET_MASK) < SIZE_VRAM) { \
|
if ((address & 0x0001FFFF) < SIZE_VRAM) { \
|
||||||
STORE_32(value, address & 0x0001FFFF, gba->video.renderer->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); \
|
STORE_32(value, address & 0x00017FFF, gba->video.renderer->vram); \
|
||||||
} \
|
} \
|
||||||
++wait;
|
++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);
|
gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
|
||||||
break;
|
break;
|
||||||
case REGION_VRAM:
|
case REGION_VRAM:
|
||||||
if ((address & OFFSET_MASK) < SIZE_VRAM) {
|
if ((address & 0x0001FFFF) < SIZE_VRAM) {
|
||||||
STORE_16(value, address & 0x0001FFFF, gba->video.renderer->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);
|
STORE_16(value, address & 0x00017FFF, gba->video.renderer->vram);
|
||||||
}
|
}
|
||||||
break;
|
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.bankedRegisters, gba->cpu->bankedRegisters, 6 * 7 * sizeof(int32_t));
|
||||||
memcpy(state->cpu.bankedSPSRs, gba->cpu->bankedSPSRs, 6 * 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);
|
GBAMemorySerialize(&gba->memory, state);
|
||||||
GBAIOSerialize(gba, state);
|
GBAIOSerialize(gba, state);
|
||||||
GBAVideoSerialize(&gba->video, 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));
|
memcpy(gba->cpu->bankedSPSRs, state->cpu.bankedSPSRs, 6 * sizeof(int32_t));
|
||||||
gba->cpu->privilegeMode = gba->cpu->cpsr.priv;
|
gba->cpu->privilegeMode = gba->cpu->cpsr.priv;
|
||||||
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
|
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
|
||||||
|
if (state->biosPrefetch) {
|
||||||
|
gba->memory.biosPrefetch = state->biosPrefetch;
|
||||||
|
}
|
||||||
if (gba->cpu->cpsr.t) {
|
if (gba->cpu->cpsr.t) {
|
||||||
gba->cpu->executionMode = MODE_THUMB;
|
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);
|
if (state->cpuPrefetch[0] && state->cpuPrefetch[1]) {
|
||||||
LOAD_16(gba->cpu->prefetch[1], (gba->cpu->gprs[ARM_PC]) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
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 {
|
} else {
|
||||||
gba->cpu->executionMode = MODE_ARM;
|
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);
|
if (state->cpuPrefetch[0] && state->cpuPrefetch[1]) {
|
||||||
LOAD_32(gba->cpu->prefetch[1], (gba->cpu->gprs[ARM_PC]) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
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);
|
GBAMemoryDeserialize(&gba->memory, state);
|
||||||
|
|
|
@ -150,7 +150,11 @@ extern const uint32_t GBA_SAVESTATE_MAGIC;
|
||||||
* | 0x002C1 - 0x002C3: Flags
|
* | 0x002C1 - 0x002C3: Flags
|
||||||
* | bits 0 - 1: Tilt state machine
|
* | bits 0 - 1: Tilt state machine
|
||||||
* | bits 2 - 31: Reserved
|
* | 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)
|
* 0x00300 - 0x00303: Associated movie stream ID for record/replay (or 0 if no stream)
|
||||||
* 0x00304 - 0x003FF: Reserved (leave zero)
|
* 0x00304 - 0x003FF: Reserved (leave zero)
|
||||||
* 0x00400 - 0x007FF: I/O memory
|
* 0x00400 - 0x007FF: I/O memory
|
||||||
|
@ -267,7 +271,10 @@ struct GBASerializedState {
|
||||||
unsigned : 22;
|
unsigned : 22;
|
||||||
} gpio;
|
} gpio;
|
||||||
|
|
||||||
uint32_t reservedGpio[15];
|
uint32_t reservedGpio[12];
|
||||||
|
|
||||||
|
uint32_t biosPrefetch;
|
||||||
|
uint32_t cpuPrefetch[2];
|
||||||
|
|
||||||
uint32_t associatedStreamId;
|
uint32_t associatedStreamId;
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ void GBAVideoInit(struct GBAVideo* video) {
|
||||||
|
|
||||||
void GBAVideoReset(struct GBAVideo* video) {
|
void GBAVideoReset(struct GBAVideo* video) {
|
||||||
video->dispstat = 0;
|
video->dispstat = 0;
|
||||||
video->vcount = 0;
|
video->vcount = VIDEO_VERTICAL_TOTAL_PIXELS - 1;
|
||||||
|
|
||||||
video->lastHblank = 0;
|
video->lastHblank = 0;
|
||||||
video->nextHblank = VIDEO_HDRAW_LENGTH;
|
video->nextHblank = VIDEO_HDRAW_LENGTH;
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000;
|
const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000;
|
||||||
const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
|
const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
|
||||||
|
|
||||||
static const size_t GBA_ROM_MAGIC_OFFSET = 2;
|
static const size_t GBA_ROM_MAGIC_OFFSET = 3;
|
||||||
static const uint8_t GBA_ROM_MAGIC[] = { 0x00, 0xEA };
|
static const uint8_t GBA_ROM_MAGIC[] = { 0xEA };
|
||||||
|
|
||||||
static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component);
|
static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component);
|
||||||
static void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh);
|
static void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh);
|
||||||
|
@ -145,7 +145,7 @@ void GBASkipBIOS(struct ARMCore* cpu) {
|
||||||
static void GBAProcessEvents(struct ARMCore* cpu) {
|
static void GBAProcessEvents(struct ARMCore* cpu) {
|
||||||
do {
|
do {
|
||||||
struct GBA* gba = (struct GBA*) cpu->master;
|
struct GBA* gba = (struct GBA*) cpu->master;
|
||||||
int32_t cycles = cpu->cycles;
|
int32_t cycles = cpu->nextEvent;
|
||||||
int32_t nextEvent = INT_MAX;
|
int32_t nextEvent = INT_MAX;
|
||||||
int32_t testEvent;
|
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 "hle-bios.h"
|
||||||
|
|
||||||
#include "gba-memory.h"
|
#include "gba-memory.h"
|
||||||
|
|
||||||
const uint8_t hleBios[SIZE_BIOS] = {
|
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,
|
0xfe, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe1,
|
||||||
0x26, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0xf3, 0xa0, 0xe3,
|
0x28, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0xf3, 0xa0, 0xe3,
|
||||||
0x00, 0x00, 0x5d, 0xe3, 0x01, 0xd3, 0xa0, 0x03, 0x20, 0xd0, 0x4d, 0x02,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1, 0x00, 0x00, 0x5d, 0xe3,
|
||||||
0x00, 0x58, 0x2d, 0xe9, 0x02, 0xb0, 0x5e, 0xe5, 0x84, 0xc0, 0xa0, 0xe3,
|
0x01, 0xd3, 0xa0, 0x03, 0x20, 0xd0, 0x4d, 0x02, 0x00, 0x58, 0x2d, 0xe9,
|
||||||
0x0b, 0xb1, 0x9c, 0xe7, 0x00, 0x00, 0x5b, 0xe3, 0x00, 0xc0, 0x4f, 0xe1,
|
0x02, 0xb0, 0x5e, 0xe5, 0x8c, 0xc0, 0xa0, 0xe3, 0x0b, 0xb1, 0x9c, 0xe7,
|
||||||
0x00, 0x10, 0x2d, 0xe9, 0x80, 0xc0, 0x0c, 0xe2, 0x1f, 0xc0, 0x8c, 0xe3,
|
0x00, 0x00, 0x5b, 0xe3, 0x00, 0xc0, 0x4f, 0xe1, 0x00, 0x10, 0x2d, 0xe9,
|
||||||
0x0c, 0xf0, 0x29, 0xe1, 0x00, 0x40, 0x2d, 0xe9, 0x0f, 0xe0, 0xa0, 0xe1,
|
0x80, 0xc0, 0x0c, 0xe2, 0x1f, 0xc0, 0x8c, 0xe3, 0x0c, 0xf0, 0x29, 0xe1,
|
||||||
0x1b, 0xff, 0x2f, 0x11, 0x00, 0x40, 0xbd, 0xe8, 0x93, 0xf0, 0x29, 0xe3,
|
0x00, 0x40, 0x2d, 0xe9, 0x0f, 0xe0, 0xa0, 0xe1, 0x1b, 0xff, 0x2f, 0x11,
|
||||||
0x00, 0x10, 0xbd, 0xe8, 0x0c, 0xf0, 0x69, 0xe1, 0x00, 0x58, 0xbd, 0xe8,
|
0x00, 0x40, 0xbd, 0xe8, 0x93, 0xf0, 0x29, 0xe3, 0x00, 0x10, 0xbd, 0xe8,
|
||||||
0x0e, 0xf0, 0xb0, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0xa0, 0xe3,
|
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, 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, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00,
|
||||||
0xb0, 0x01, 0x00, 0x00, 0x0f, 0x50, 0x2d, 0xe9, 0x01, 0x03, 0xa0, 0xe3,
|
0x0f, 0x50, 0x2d, 0xe9, 0x01, 0x03, 0xa0, 0xe3, 0x00, 0xe0, 0x8f, 0xe2,
|
||||||
0x00, 0xe0, 0x8f, 0xe2, 0x04, 0xf0, 0x10, 0xe5, 0x0f, 0x50, 0xbd, 0xe8,
|
0x04, 0xf0, 0x10, 0xe5, 0x0f, 0x50, 0xbd, 0xe8, 0x04, 0xf0, 0x5e, 0xe2,
|
||||||
0x04, 0xf0, 0x5e, 0xe2, 0x01, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3,
|
0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x5e, 0xe5, 0x01, 0x00, 0xa0, 0xe3,
|
||||||
0x0c, 0x40, 0x2d, 0xe9, 0x01, 0xc3, 0xa0, 0xe3, 0x00, 0x00, 0x50, 0xe3,
|
0x01, 0x10, 0xa0, 0xe3, 0x0c, 0x40, 0x2d, 0xe9, 0x01, 0xc3, 0xa0, 0xe3,
|
||||||
0x00, 0x00, 0xa0, 0xe3, 0x01, 0x20, 0xa0, 0xe3, 0x03, 0x00, 0x00, 0x0a,
|
0x00, 0x00, 0x50, 0xe3, 0x00, 0x00, 0xa0, 0xe3, 0x01, 0x20, 0xa0, 0xe3,
|
||||||
0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0xc3, 0xe1, 0xb8, 0x30, 0x4c, 0xe1,
|
0x03, 0x00, 0x00, 0x0a, 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0xc3, 0xe1,
|
||||||
0x01, 0x03, 0xcc, 0xe5, 0x08, 0x02, 0xcc, 0xe5, 0xb8, 0x30, 0x5c, 0xe1,
|
0xb8, 0x30, 0x4c, 0xe1, 0x01, 0x03, 0xcc, 0xe5, 0x08, 0x02, 0xcc, 0xe5,
|
||||||
0x01, 0x30, 0x13, 0xe0, 0x01, 0x30, 0x23, 0x10, 0xb8, 0x30, 0x4c, 0x11,
|
0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0x13, 0xe0, 0x01, 0x30, 0x23, 0x10,
|
||||||
0x08, 0x22, 0xcc, 0xe5, 0xf7, 0xff, 0xff, 0x0a, 0x0c, 0x80, 0xbd, 0xe8,
|
0xb8, 0x30, 0x4c, 0x11, 0x08, 0x22, 0xcc, 0xe5, 0xf7, 0xff, 0xff, 0x0a,
|
||||||
0x00, 0x40, 0x2d, 0xe9, 0x02, 0x36, 0xa0, 0xe1, 0x01, 0x04, 0x12, 0xe3,
|
0x0c, 0x80, 0xbd, 0xe8, 0x00, 0x40, 0x2d, 0xe9, 0x02, 0x36, 0xa0, 0xe1,
|
||||||
0x0f, 0x00, 0x00, 0x0a, 0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a,
|
0x01, 0x04, 0x12, 0xe3, 0x0f, 0x00, 0x00, 0x0a, 0x01, 0x03, 0x12, 0xe3,
|
||||||
0x23, 0x35, 0x81, 0xe0, 0x04, 0x00, 0xb0, 0xe8, 0x03, 0x00, 0x51, 0xe1,
|
0x05, 0x00, 0x00, 0x0a, 0x23, 0x35, 0x81, 0xe0, 0x04, 0x00, 0xb0, 0xe8,
|
||||||
0x04, 0x00, 0xa1, 0xb8, 0xfc, 0xff, 0xff, 0xba, 0x16, 0x00, 0x00, 0xea,
|
0x03, 0x00, 0x51, 0xe1, 0x04, 0x00, 0xa1, 0xb8, 0xfc, 0xff, 0xff, 0xba,
|
||||||
0x01, 0x00, 0xc0, 0xe3, 0x01, 0x10, 0xc1, 0xe3, 0xa3, 0x35, 0x81, 0xe0,
|
0x16, 0x00, 0x00, 0xea, 0x01, 0x00, 0xc0, 0xe3, 0x01, 0x10, 0xc1, 0xe3,
|
||||||
0xb0, 0x20, 0xd0, 0xe1, 0x03, 0x00, 0x51, 0xe1, 0xb2, 0x20, 0xc1, 0xb0,
|
0xa3, 0x35, 0x81, 0xe0, 0xb0, 0x20, 0xd0, 0xe1, 0x03, 0x00, 0x51, 0xe1,
|
||||||
0xfc, 0xff, 0xff, 0xba, 0x0e, 0x00, 0x00, 0xea, 0x01, 0x03, 0x12, 0xe3,
|
0xb2, 0x20, 0xc1, 0xb0, 0xfc, 0xff, 0xff, 0xba, 0x0e, 0x00, 0x00, 0xea,
|
||||||
0x05, 0x00, 0x00, 0x0a, 0x23, 0x35, 0x81, 0xe0, 0x03, 0x00, 0x51, 0xe1,
|
0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a, 0x23, 0x35, 0x81, 0xe0,
|
||||||
0x04, 0x00, 0xb0, 0xb8, 0x04, 0x00, 0xa1, 0xb8, 0xfb, 0xff, 0xff, 0xba,
|
0x03, 0x00, 0x51, 0xe1, 0x04, 0x00, 0xb0, 0xb8, 0x04, 0x00, 0xa1, 0xb8,
|
||||||
0x06, 0x00, 0x00, 0xea, 0xa3, 0x35, 0x81, 0xe0, 0x01, 0x00, 0xc0, 0xe3,
|
0xfb, 0xff, 0xff, 0xba, 0x06, 0x00, 0x00, 0xea, 0xa3, 0x35, 0x81, 0xe0,
|
||||||
0x01, 0x10, 0xc1, 0xe3, 0x03, 0x00, 0x51, 0xe1, 0xb2, 0x20, 0xd0, 0xb0,
|
0x01, 0x00, 0xc0, 0xe3, 0x01, 0x10, 0xc1, 0xe3, 0x03, 0x00, 0x51, 0xe1,
|
||||||
0xb2, 0x20, 0xc1, 0xb0, 0xfb, 0xff, 0xff, 0xba, 0x00, 0x80, 0xbd, 0xe8,
|
0xb2, 0x20, 0xd0, 0xb0, 0xb2, 0x20, 0xc1, 0xb0, 0xfb, 0xff, 0xff, 0xba,
|
||||||
0xf0, 0x47, 0x2d, 0xe9, 0x01, 0x04, 0x12, 0xe3, 0x02, 0x36, 0xa0, 0xe1,
|
0x00, 0x80, 0xbd, 0xe8, 0xf0, 0x47, 0x2d, 0xe9, 0x01, 0x04, 0x12, 0xe3,
|
||||||
0x23, 0x25, 0x81, 0xe0, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x90, 0xe5,
|
0x02, 0x36, 0xa0, 0xe1, 0x23, 0x25, 0x81, 0xe0, 0x0b, 0x00, 0x00, 0x0a,
|
||||||
0x03, 0x40, 0xa0, 0xe1, 0x03, 0x50, 0xa0, 0xe1, 0x03, 0x60, 0xa0, 0xe1,
|
0x00, 0x30, 0x90, 0xe5, 0x03, 0x40, 0xa0, 0xe1, 0x03, 0x50, 0xa0, 0xe1,
|
||||||
0x03, 0x70, 0xa0, 0xe1, 0x03, 0x80, 0xa0, 0xe1, 0x03, 0x90, 0xa0, 0xe1,
|
0x03, 0x60, 0xa0, 0xe1, 0x03, 0x70, 0xa0, 0xe1, 0x03, 0x80, 0xa0, 0xe1,
|
||||||
0x03, 0xa0, 0xa0, 0xe1, 0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xa1, 0xb8,
|
0x03, 0x90, 0xa0, 0xe1, 0x03, 0xa0, 0xa0, 0xe1, 0x02, 0x00, 0x51, 0xe1,
|
||||||
0xfc, 0xff, 0xff, 0xba, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x51, 0xe1,
|
0xf8, 0x07, 0xa1, 0xb8, 0xfc, 0xff, 0xff, 0xba, 0x03, 0x00, 0x00, 0xea,
|
||||||
0xf8, 0x07, 0xb0, 0xb8, 0xf8, 0x07, 0xa1, 0xb8, 0xfb, 0xff, 0xff, 0xba,
|
0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xb0, 0xb8, 0xf8, 0x07, 0xa1, 0xb8,
|
||||||
0xf0, 0x87, 0xbd, 0xe8
|
0xfb, 0xff, 0xff, 0xba, 0xf0, 0x87, 0xbd, 0xe8
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,8 @@ b fiqBase
|
||||||
|
|
||||||
resetBase:
|
resetBase:
|
||||||
mov pc, #0x8000000
|
mov pc, #0x8000000
|
||||||
|
.word 0
|
||||||
|
.word 0xE129F000
|
||||||
|
|
||||||
swiBase:
|
swiBase:
|
||||||
cmp sp, #0
|
cmp sp, #0
|
||||||
|
@ -68,6 +70,8 @@ add lr, pc, #0
|
||||||
ldr pc, [r0, #-4]
|
ldr pc, [r0, #-4]
|
||||||
ldmfd sp!, {r0-r3, r12, lr}
|
ldmfd sp!, {r0-r3, r12, lr}
|
||||||
subs pc, lr, #4
|
subs pc, lr, #4
|
||||||
|
.word 0
|
||||||
|
.word 0xE55EC002
|
||||||
|
|
||||||
VBlankIntrWait:
|
VBlankIntrWait:
|
||||||
mov r0, #1
|
mov r0, #1
|
||||||
|
|
|
@ -1010,6 +1010,10 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
|
||||||
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \
|
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \
|
||||||
palette = &mainPalette[paletteData]; \
|
palette = &mainPalette[paletteData]; \
|
||||||
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \
|
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \
|
||||||
|
if (UNLIKELY(charBase >= 0x10000)) { \
|
||||||
|
pixel += 8; \
|
||||||
|
continue; \
|
||||||
|
} \
|
||||||
LOAD_32(tileData, charBase, vram); \
|
LOAD_32(tileData, charBase, vram); \
|
||||||
if (tileData) { \
|
if (tileData) { \
|
||||||
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
||||||
|
@ -1058,35 +1062,43 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
|
||||||
int end2 = end - 4; \
|
int end2 = end - 4; \
|
||||||
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
||||||
int shift = inX & 0x3; \
|
int shift = inX & 0x3; \
|
||||||
if (end2 > outX) { \
|
if (LIKELY(charBase < 0x10000)) { \
|
||||||
LOAD_32(tileData, charBase, vram); \
|
if (end2 > outX) { \
|
||||||
tileData >>= 8 * shift; \
|
LOAD_32(tileData, charBase, vram); \
|
||||||
shift = 0; \
|
tileData >>= 8 * shift; \
|
||||||
for (; outX < end2; ++outX, ++pixel) { \
|
shift = 0; \
|
||||||
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
for (; outX < end2; ++outX, ++pixel) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
LOAD_32(tileData, charBase + 4, vram); \
|
if (LIKELY(charBase < 0x10000)) { \
|
||||||
tileData >>= 8 * shift; \
|
LOAD_32(tileData, charBase + 4, vram); \
|
||||||
for (; outX < end; ++outX, ++pixel) { \
|
tileData >>= 8 * shift; \
|
||||||
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
for (; outX < end; ++outX, ++pixel) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
int start = outX; \
|
int start = outX; \
|
||||||
outX = end - 1; \
|
outX = end - 1; \
|
||||||
pixel = &renderer->row[outX]; \
|
pixel = &renderer->row[outX]; \
|
||||||
if (end2 > start) { \
|
if (LIKELY(charBase < 0x10000)) { \
|
||||||
LOAD_32(tileData, charBase, vram); \
|
if (end2 > start) { \
|
||||||
for (; outX >= end2; --outX, --pixel) { \
|
LOAD_32(tileData, charBase, vram); \
|
||||||
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
for (; outX >= end2; --outX, --pixel) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
||||||
|
} \
|
||||||
|
charBase += 4; \
|
||||||
} \
|
} \
|
||||||
charBase += 4; \
|
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
LOAD_32(tileData, charBase, vram); \
|
if (LIKELY(charBase < 0x10000)) { \
|
||||||
for (; outX >= renderer->start; --outX, --pixel) { \
|
LOAD_32(tileData, charBase, vram); \
|
||||||
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
for (; outX >= renderer->start; --outX, --pixel) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
outX = end; \
|
outX = end; \
|
||||||
pixel = &renderer->row[outX]; \
|
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) \
|
#define DRAW_BACKGROUND_MODE_0_TILE_PREFIX_256(BLEND, OBJWIN) \
|
||||||
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
|
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
|
||||||
|
if (UNLIKELY(charBase >= 0x10000)) { \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
int end = mod8 - 4; \
|
int end = mod8 - 4; \
|
||||||
pixel = &renderer->row[outX]; \
|
pixel = &renderer->row[outX]; \
|
||||||
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
||||||
|
@ -1139,6 +1154,10 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
|
||||||
for (; tileX < tileEnd; ++tileX) { \
|
for (; tileX < tileEnd; ++tileX) { \
|
||||||
BACKGROUND_TEXT_SELECT_CHARACTER; \
|
BACKGROUND_TEXT_SELECT_CHARACTER; \
|
||||||
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
|
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
|
||||||
|
if (UNLIKELY(charBase >= 0x10000)) { \
|
||||||
|
pixel += 8; \
|
||||||
|
continue; \
|
||||||
|
} \
|
||||||
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
||||||
LOAD_32(tileData, charBase, vram); \
|
LOAD_32(tileData, charBase, vram); \
|
||||||
if (tileData) { \
|
if (tileData) { \
|
||||||
|
|
|
@ -112,46 +112,43 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (event->keysym.sym) {
|
if (event->keysym.sym == SDLK_TAB) {
|
||||||
case SDLK_F11:
|
context->sync.audioWait = event->type != SDL_KEYDOWN;
|
||||||
if (event->type == SDL_KEYDOWN && context->debugger) {
|
|
||||||
ARMDebuggerEnter(context->debugger, DEBUGGER_ENTER_MANUAL);
|
|
||||||
}
|
|
||||||
return;
|
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
|
#ifdef USE_PNG
|
||||||
case SDLK_F12:
|
case SDLK_F12:
|
||||||
if (event->type == SDL_KEYDOWN) {
|
|
||||||
GBAThreadInterrupt(context);
|
GBAThreadInterrupt(context);
|
||||||
GBAThreadTakeScreenshot(context);
|
GBAThreadTakeScreenshot(context);
|
||||||
GBAThreadContinue(context);
|
GBAThreadContinue(context);
|
||||||
}
|
return;
|
||||||
return;
|
|
||||||
#endif
|
#endif
|
||||||
case SDLK_TAB:
|
case SDLK_BACKSLASH:
|
||||||
context->sync.audioWait = event->type != SDL_KEYDOWN;
|
|
||||||
return;
|
|
||||||
case SDLK_BACKSLASH:
|
|
||||||
if (event->type == SDL_KEYDOWN) {
|
|
||||||
GBAThreadPause(context);
|
GBAThreadPause(context);
|
||||||
context->frameCallback = _pauseAfterFrame;
|
context->frameCallback = _pauseAfterFrame;
|
||||||
GBAThreadUnpause(context);
|
GBAThreadUnpause(context);
|
||||||
}
|
return;
|
||||||
return;
|
case SDLK_BACKQUOTE:
|
||||||
case SDLK_LEFTBRACKET:
|
GBAThreadInterrupt(context);
|
||||||
GBAThreadInterrupt(context);
|
GBARewind(context, 10);
|
||||||
GBARewind(context, 10);
|
GBAThreadContinue(context);
|
||||||
GBAThreadContinue(context);
|
return;
|
||||||
return;
|
case SDLK_ESCAPE:
|
||||||
case SDLK_ESCAPE:
|
GBAThreadInterrupt(context);
|
||||||
GBAThreadInterrupt(context);
|
if (context->gba->rr) {
|
||||||
if (context->gba->rr) {
|
GBARRStopPlaying(context->gba->rr);
|
||||||
GBARRStopPlaying(context->gba->rr);
|
GBARRStopRecording(context->gba->rr);
|
||||||
GBARRStopRecording(context->gba->rr);
|
}
|
||||||
}
|
GBAThreadContinue(context);
|
||||||
GBAThreadContinue(context);
|
return;
|
||||||
return;
|
default:
|
||||||
default:
|
|
||||||
if (event->type == SDL_KEYDOWN) {
|
|
||||||
if ((event->keysym.mod & GUI_MOD) && (event->keysym.mod & GUI_MOD) == event->keysym.mod) {
|
if ((event->keysym.mod & GUI_MOD) && (event->keysym.mod & GUI_MOD) == event->keysym.mod) {
|
||||||
switch (event->keysym.sym) {
|
switch (event->keysym.sym) {
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
|
@ -238,8 +235,8 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents
|
||||||
break;
|
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) {
|
if (_decodeLength(patch->vf) != outSize) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (inSize > SSIZE_MAX || outSize > SSIZE_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
size_t metadataLength = _decodeLength(patch->vf);
|
size_t metadataLength = _decodeLength(patch->vf);
|
||||||
patch->vf->seek(patch->vf, metadataLength, SEEK_CUR); // Skip metadata
|
patch->vf->seek(patch->vf, metadataLength, SEEK_CUR); // Skip metadata
|
||||||
size_t writeLocation = 0;
|
size_t writeLocation = 0;
|
||||||
|
@ -153,7 +156,7 @@ bool _BPSApplyPatch(struct Patch* patch, void* in, size_t inSize, void* out, siz
|
||||||
break;
|
break;
|
||||||
case 0x1:
|
case 0x1:
|
||||||
// TargetRead
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
outputChecksum = updateCrc32(outputChecksum, &writeBuffer[writeLocation], length);
|
outputChecksum = updateCrc32(outputChecksum, &writeBuffer[writeLocation], length);
|
||||||
|
@ -167,7 +170,7 @@ bool _BPSApplyPatch(struct Patch* patch, void* in, size_t inSize, void* out, siz
|
||||||
} else {
|
} else {
|
||||||
readSourceLocation += readOffset >> 1;
|
readSourceLocation += readOffset >> 1;
|
||||||
}
|
}
|
||||||
if (readSourceLocation < 0 || readSourceLocation > inSize) {
|
if (readSourceLocation < 0 || readSourceLocation > (ssize_t) inSize) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memmove(&writeBuffer[writeLocation], &readBuffer[readSourceLocation], length);
|
memmove(&writeBuffer[writeLocation], &readBuffer[readSourceLocation], length);
|
||||||
|
@ -183,7 +186,7 @@ bool _BPSApplyPatch(struct Patch* patch, void* in, size_t inSize, void* out, siz
|
||||||
} else {
|
} else {
|
||||||
readTargetLocation += readOffset >> 1;
|
readTargetLocation += readOffset >> 1;
|
||||||
}
|
}
|
||||||
if (readTargetLocation < 0 || readTargetLocation > outSize) {
|
if (readTargetLocation < 0 || readTargetLocation > (ssize_t) outSize) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (i = 0; i < length; ++i) {
|
for (i = 0; i < length; ++i) {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
|
|
||||||
#define SOCKET_FAILED(s) (s) == INVALID_SOCKET
|
#define SOCKET_FAILED(s) ((s) == INVALID_SOCKET)
|
||||||
typedef SOCKET Socket;
|
typedef SOCKET Socket;
|
||||||
#else
|
#else
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -25,7 +25,7 @@ typedef SOCKET Socket;
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#define INVALID_SOCKET (-1)
|
#define INVALID_SOCKET (-1)
|
||||||
#define SOCKET_FAILED(s) (s) < 0
|
#define SOCKET_FAILED(s) ((s) < 0)
|
||||||
typedef int Socket;
|
typedef int Socket;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ static inline int SocketClose(Socket socket) {
|
||||||
return close(socket) >= 0;
|
return close(socket) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int SocketSetBlocking(Socket socket, int blocking) {
|
static inline int SocketSetBlocking(Socket socket, bool blocking) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
u_long unblocking = !blocking;
|
u_long unblocking = !blocking;
|
||||||
return ioctlsocket(socket, FIONBIO, &unblocking) == NO_ERROR;
|
return ioctlsocket(socket, FIONBIO, &unblocking) == NO_ERROR;
|
||||||
|
|
|
@ -76,7 +76,7 @@ class Suite(object):
|
||||||
def collect_tests(self):
|
def collect_tests(self):
|
||||||
roms = []
|
roms = []
|
||||||
for f in os.listdir(self.cwd):
|
for f in os.listdir(self.cwd):
|
||||||
if f.endswith('.gba'):
|
if f.endswith('.gba') or f.endswith('.zip'):
|
||||||
roms.append(f)
|
roms.append(f)
|
||||||
roms.sort()
|
roms.sort()
|
||||||
for rom in roms:
|
for rom in roms:
|
||||||
|
|
Loading…
Reference in New Issue