Merge branch 'master' into medusa

This commit is contained in:
Vicki Pfau 2017-01-31 14:41:02 -08:00
commit 896749ede9
21 changed files with 1001 additions and 582 deletions

View File

@ -22,6 +22,7 @@ Bugfixes:
- LR35902: Fix pc overflowing current region off-by-one - LR35902: Fix pc overflowing current region off-by-one
- GB MBC: Fix ROM bank overflows getting set to bank 0 - GB MBC: Fix ROM bank overflows getting set to bank 0
- Qt: Fix timing issues on high refresh rate monitors - Qt: Fix timing issues on high refresh rate monitors
- GBA Savedata: Fix savedata unmasking (fixes mgba.io/i/441)
Misc: Misc:
- SDL: Remove scancode key input - SDL: Remove scancode key input
- GBA Video: Clean up unused timers - GBA Video: Clean up unused timers
@ -59,7 +60,6 @@ Misc:
- SDL: Automatically map controllers when plugged in - SDL: Automatically map controllers when plugged in
- Qt: Automatically load controller profile when plugged in - Qt: Automatically load controller profile when plugged in
- OpenGL: Add xBR-lv2 shader - OpenGL: Add xBR-lv2 shader
- ARM: Overhaul PSR bit access
0.5.2: (2016-12-31) 0.5.2: (2016-12-31)
Bugfixes: Bugfixes:

View File

@ -173,12 +173,6 @@ typedef intptr_t ssize_t;
ATTRIBUTE_UNUSED static inline TYPE TYPE ## Fill ## FIELD (TYPE src) { \ ATTRIBUTE_UNUSED static inline TYPE TYPE ## Fill ## FIELD (TYPE src) { \
return FILL_BITS(src, (START), (START) + (SIZE)); \ return FILL_BITS(src, (START), (START) + (SIZE)); \
} \ } \
ATTRIBUTE_UNUSED static inline TYPE TYPE ## OrUnsafe ## FIELD (TYPE src, TYPE bits) { \
return (src | ((bits) << (START))); \
} \
ATTRIBUTE_UNUSED static inline TYPE TYPE ## Or ## FIELD (TYPE src, TYPE bits) { \
return (src | (((bits) << (START)) & MAKE_MASK(START, (START) + (SIZE)))); \
} \
ATTRIBUTE_UNUSED static inline TYPE TYPE ## Set ## FIELD (TYPE src, TYPE bits) { \ ATTRIBUTE_UNUSED static inline TYPE TYPE ## Set ## FIELD (TYPE src, TYPE bits) { \
return INS_BITS(src, (START), (START) + (SIZE), bits); \ return INS_BITS(src, (START), (START) + (SIZE), bits); \
} \ } \

View File

@ -68,15 +68,33 @@ enum LSMDirection {
struct ARMCore; struct ARMCore;
DECL_BITFIELD(ARMPSR, uint32_t); union PSR {
DECL_BITS(ARMPSR, Priv, 0, 5); struct {
DECL_BIT(ARMPSR, T, 5); #if defined(__POWERPC__) || defined(__PPC__)
DECL_BIT(ARMPSR, F, 6); unsigned n : 1;
DECL_BIT(ARMPSR, I, 7); unsigned z : 1;
DECL_BIT(ARMPSR, V, 28); unsigned c : 1;
DECL_BIT(ARMPSR, C, 29); unsigned v : 1;
DECL_BIT(ARMPSR, Z, 30); unsigned unused : 20;
DECL_BIT(ARMPSR, N, 31); unsigned i : 1;
unsigned f : 1;
unsigned t : 1;
unsigned priv : 5;
#else
unsigned priv : 5;
unsigned t : 1;
unsigned f : 1;
unsigned i : 1;
unsigned unused : 20;
unsigned v : 1;
unsigned c : 1;
unsigned z : 1;
unsigned n : 1;
#endif
};
int32_t packed;
};
struct ARMMemory { struct ARMMemory {
uint32_t (*load32)(struct ARMCore*, uint32_t address, int* cycleCounter); uint32_t (*load32)(struct ARMCore*, uint32_t address, int* cycleCounter);
@ -199,8 +217,8 @@ struct ARMCP15 {
struct ARMCore { struct ARMCore {
int32_t gprs[16]; int32_t gprs[16];
ARMPSR cpsr; union PSR cpsr;
ARMPSR spsr; union PSR spsr;
int32_t cycles; int32_t cycles;
int32_t nextEvent; int32_t nextEvent;

View File

@ -10,20 +10,20 @@
#include "arm.h" #include "arm.h"
#define ARM_COND_EQ (ARMPSRIsZ(cpu->cpsr)) #define ARM_COND_EQ (cpu->cpsr.z)
#define ARM_COND_NE (!ARMPSRIsZ(cpu->cpsr)) #define ARM_COND_NE (!cpu->cpsr.z)
#define ARM_COND_CS (ARMPSRIsC(cpu->cpsr)) #define ARM_COND_CS (cpu->cpsr.c)
#define ARM_COND_CC (!ARMPSRIsC(cpu->cpsr)) #define ARM_COND_CC (!cpu->cpsr.c)
#define ARM_COND_MI (ARMPSRIsN(cpu->cpsr)) #define ARM_COND_MI (cpu->cpsr.n)
#define ARM_COND_PL (!ARMPSRIsN(cpu->cpsr)) #define ARM_COND_PL (!cpu->cpsr.n)
#define ARM_COND_VS (ARMPSRIsV(cpu->cpsr)) #define ARM_COND_VS (cpu->cpsr.v)
#define ARM_COND_VC (!ARMPSRIsV(cpu->cpsr)) #define ARM_COND_VC (!cpu->cpsr.v)
#define ARM_COND_HI (ARMPSRIsC(cpu->cpsr) && !ARMPSRIsZ(cpu->cpsr)) #define ARM_COND_HI (cpu->cpsr.c && !cpu->cpsr.z)
#define ARM_COND_LS (!ARMPSRIsC(cpu->cpsr) || ARMPSRIsZ(cpu->cpsr)) #define ARM_COND_LS (!cpu->cpsr.c || cpu->cpsr.z)
#define ARM_COND_GE (!ARMPSRIsN(cpu->cpsr) == !ARMPSRIsV(cpu->cpsr)) #define ARM_COND_GE (!cpu->cpsr.n == !cpu->cpsr.v)
#define ARM_COND_LT (!ARMPSRIsN(cpu->cpsr) != !ARMPSRIsV(cpu->cpsr)) #define ARM_COND_LT (!cpu->cpsr.n != !cpu->cpsr.v)
#define ARM_COND_GT (!ARMPSRIsZ(cpu->cpsr) && !ARMPSRIsN(cpu->cpsr) == !ARMPSRIsV(cpu->cpsr)) #define ARM_COND_GT (!cpu->cpsr.z && !cpu->cpsr.n == !cpu->cpsr.v)
#define ARM_COND_LE (ARMPSRIsZ(cpu->cpsr) || !ARMPSRIsN(cpu->cpsr) != !ARMPSRIsV(cpu->cpsr)) #define ARM_COND_LE (cpu->cpsr.z || !cpu->cpsr.n != !cpu->cpsr.v)
#define ARM_COND_AL 1 #define ARM_COND_AL 1
#define ARM_SIGN(I) ((I) >> 31) #define ARM_SIGN(I) ((I) >> 31)
@ -31,8 +31,7 @@
#define ARM_SXT_16(I) (((int16_t) (I) << 16) >> 16) #define ARM_SXT_16(I) (((int16_t) (I) << 16) >> 16)
#define ARM_UXT_64(I) (uint64_t)(uint32_t) (I) #define ARM_UXT_64(I) (uint64_t)(uint32_t) (I)
#define ARM_CARRY_FROM(M, N, D) (UINT_MAX - (uint32_t) (M) < (uint32_t) (N)) #define ARM_CARRY_FROM(M, N, D) (((uint32_t) (M) >> 31) + ((uint32_t) (N) >> 31) > ((uint32_t) (D) >> 31))
#define ARM_CARRY_FROM_CARRY(M, N, D, C) (((uint32_t) (M) >> 31) + ((uint32_t) (N) >> 31) > ((uint32_t) (D) >> 31))
#define ARM_BORROW_FROM(M, N, D) (((uint32_t) (M)) >= ((uint32_t) (N))) #define ARM_BORROW_FROM(M, N, D) (((uint32_t) (M)) >= ((uint32_t) (N)))
#define ARM_BORROW_FROM_CARRY(M, N, D, C) (ARM_UXT_64(M) >= (ARM_UXT_64(N)) + (uint64_t) (C)) #define ARM_BORROW_FROM_CARRY(M, N, D, C) (ARM_UXT_64(M) >= (ARM_UXT_64(N)) + (uint64_t) (C))
#define ARM_V_ADDITION(M, N, D) (!(ARM_SIGN((M) ^ (N))) && (ARM_SIGN((M) ^ (D))) && (ARM_SIGN((N) ^ (D)))) #define ARM_V_ADDITION(M, N, D) (!(ARM_SIGN((M) ^ (N))) && (ARM_SIGN((M) ^ (D))) && (ARM_SIGN((N) ^ (D))))
@ -84,23 +83,24 @@ static inline void _ARMSetMode(struct ARMCore* cpu, enum ExecutionMode execution
cpu->executionMode = executionMode; cpu->executionMode = executionMode;
switch (executionMode) { switch (executionMode) {
case MODE_ARM: case MODE_ARM:
cpu->cpsr = ARMPSRClearT(cpu->cpsr); cpu->cpsr.t = 0;
break; break;
case MODE_THUMB: case MODE_THUMB:
cpu->cpsr = ARMPSRFillT(cpu->cpsr); cpu->cpsr.t = 1;
} }
cpu->nextEvent = cpu->cycles; cpu->nextEvent = cpu->cycles;
} }
static inline void _ARMReadCPSR(struct ARMCore* cpu) { static inline void _ARMReadCPSR(struct ARMCore* cpu) {
_ARMSetMode(cpu, ARMPSRGetT(cpu->cpsr)); _ARMSetMode(cpu, cpu->cpsr.t);
ARMSetPrivilegeMode(cpu, ARMPSRGetPriv(cpu->cpsr)); ARMSetPrivilegeMode(cpu, cpu->cpsr.priv);
cpu->irqh.readCPSR(cpu); cpu->irqh.readCPSR(cpu);
} }
static inline uint32_t _ARMPCAddress(struct ARMCore* cpu) { static inline uint32_t _ARMPCAddress(struct ARMCore* cpu) {
int instructionLength; int instructionLength;
if (ARMPSRIsT(cpu->cpsr)) { enum ExecutionMode mode = cpu->cpsr.t;
if (mode == MODE_ARM) {
instructionLength = WORD_SIZE_ARM; instructionLength = WORD_SIZE_ARM;
} else { } else {
instructionLength = WORD_SIZE_THUMB; instructionLength = WORD_SIZE_THUMB;

View File

@ -11,7 +11,6 @@
CXX_GUARD_START CXX_GUARD_START
#include <mgba/core/core.h> #include <mgba/core/core.h>
#include <mgba/internal/arm/arm.h>
#include <mgba/internal/gba/gba.h> #include <mgba/internal/gba/gba.h>
#include <mgba/internal/gb/serialize.h> #include <mgba/internal/gb/serialize.h>
@ -238,8 +237,8 @@ struct GBASerializedState {
struct { struct {
int32_t gprs[16]; int32_t gprs[16];
ARMPSR cpsr; union PSR cpsr;
ARMPSR spsr; union PSR spsr;
int32_t cycles; int32_t cycles;
int32_t nextEvent; int32_t nextEvent;

View File

@ -40,8 +40,8 @@ void ARMSetPrivilegeMode(struct ARMCore* cpu, enum PrivilegeMode mode) {
cpu->gprs[ARM_SP] = cpu->bankedRegisters[newBank][0]; cpu->gprs[ARM_SP] = cpu->bankedRegisters[newBank][0];
cpu->gprs[ARM_LR] = cpu->bankedRegisters[newBank][1]; cpu->gprs[ARM_LR] = cpu->bankedRegisters[newBank][1];
cpu->bankedSPSRs[oldBank] = cpu->spsr; cpu->bankedSPSRs[oldBank] = cpu->spsr.packed;
cpu->spsr = cpu->bankedSPSRs[newBank]; cpu->spsr.packed = cpu->bankedSPSRs[newBank];
} }
cpu->privilegeMode = mode; cpu->privilegeMode = mode;
} }
@ -132,8 +132,8 @@ void ARMReset(struct ARMCore* cpu) {
} }
cpu->privilegeMode = MODE_SYSTEM; cpu->privilegeMode = MODE_SYSTEM;
cpu->cpsr = MODE_SYSTEM; cpu->cpsr.packed = MODE_SYSTEM;
cpu->spsr = 0; cpu->spsr.packed = 0;
cpu->shifterOperand = 0; cpu->shifterOperand = 0;
cpu->shifterCarryOut = 0; cpu->shifterCarryOut = 0;
@ -152,10 +152,10 @@ void ARMReset(struct ARMCore* cpu) {
} }
void ARMRaiseIRQ(struct ARMCore* cpu) { void ARMRaiseIRQ(struct ARMCore* cpu) {
if (ARMPSRIsI(cpu->cpsr)) { if (cpu->cpsr.i) {
return; return;
} }
ARMPSR cpsr = cpu->cpsr; union PSR cpsr = cpu->cpsr;
int instructionWidth; int instructionWidth;
if (cpu->executionMode == MODE_THUMB) { if (cpu->executionMode == MODE_THUMB) {
instructionWidth = WORD_SIZE_THUMB; instructionWidth = WORD_SIZE_THUMB;
@ -163,7 +163,7 @@ void ARMRaiseIRQ(struct ARMCore* cpu) {
instructionWidth = WORD_SIZE_ARM; instructionWidth = WORD_SIZE_ARM;
} }
ARMSetPrivilegeMode(cpu, MODE_IRQ); ARMSetPrivilegeMode(cpu, MODE_IRQ);
cpu->cpsr = ARMPSRSetPriv(cpu->cpsr, MODE_IRQ); cpu->cpsr.priv = MODE_IRQ;
cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth + WORD_SIZE_ARM; cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth + WORD_SIZE_ARM;
cpu->gprs[ARM_PC] = BASE_IRQ; cpu->gprs[ARM_PC] = BASE_IRQ;
if (ARMControlRegIsVE(cpu->cp15.r1.c0)) { if (ARMControlRegIsVE(cpu->cp15.r1.c0)) {
@ -173,12 +173,12 @@ void ARMRaiseIRQ(struct ARMCore* cpu) {
ARM_WRITE_PC; ARM_WRITE_PC;
_ARMSetMode(cpu, MODE_ARM); _ARMSetMode(cpu, MODE_ARM);
cpu->spsr = cpsr; cpu->spsr = cpsr;
cpu->cpsr = ARMPSRFillI(cpu->cpsr); cpu->cpsr.i = 1;
cpu->cycles += currentCycles; cpu->cycles += currentCycles;
} }
void ARMRaiseSWI(struct ARMCore* cpu) { void ARMRaiseSWI(struct ARMCore* cpu) {
ARMPSR cpsr = cpu->cpsr; union PSR cpsr = cpu->cpsr;
int instructionWidth; int instructionWidth;
if (cpu->executionMode == MODE_THUMB) { if (cpu->executionMode == MODE_THUMB) {
instructionWidth = WORD_SIZE_THUMB; instructionWidth = WORD_SIZE_THUMB;
@ -186,7 +186,7 @@ void ARMRaiseSWI(struct ARMCore* cpu) {
instructionWidth = WORD_SIZE_ARM; instructionWidth = WORD_SIZE_ARM;
} }
ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR); ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
cpu->cpsr = ARMPSRSetPriv(cpu->cpsr, MODE_SUPERVISOR); cpu->cpsr.priv = MODE_SUPERVISOR;
cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth; cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth;
cpu->gprs[ARM_PC] = BASE_SWI; cpu->gprs[ARM_PC] = BASE_SWI;
if (ARMControlRegIsVE(cpu->cp15.r1.c0)) { if (ARMControlRegIsVE(cpu->cp15.r1.c0)) {
@ -196,12 +196,12 @@ void ARMRaiseSWI(struct ARMCore* cpu) {
ARM_WRITE_PC; ARM_WRITE_PC;
_ARMSetMode(cpu, MODE_ARM); _ARMSetMode(cpu, MODE_ARM);
cpu->spsr = cpsr; cpu->spsr = cpsr;
cpu->cpsr = ARMPSRFillI(cpu->cpsr); cpu->cpsr.i = 1;
cpu->cycles += currentCycles; cpu->cycles += currentCycles;
} }
void ARMRaiseUndefined(struct ARMCore* cpu) { void ARMRaiseUndefined(struct ARMCore* cpu) {
ARMPSR cpsr = cpu->cpsr; union PSR cpsr = cpu->cpsr;
int instructionWidth; int instructionWidth;
if (cpu->executionMode == MODE_THUMB) { if (cpu->executionMode == MODE_THUMB) {
instructionWidth = WORD_SIZE_THUMB; instructionWidth = WORD_SIZE_THUMB;
@ -209,7 +209,7 @@ void ARMRaiseUndefined(struct ARMCore* cpu) {
instructionWidth = WORD_SIZE_ARM; instructionWidth = WORD_SIZE_ARM;
} }
ARMSetPrivilegeMode(cpu, MODE_UNDEFINED); ARMSetPrivilegeMode(cpu, MODE_UNDEFINED);
cpu->cpsr = ARMPSRSetPriv(cpu->cpsr, MODE_UNDEFINED); cpu->cpsr.priv = MODE_UNDEFINED;
cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth; cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth;
cpu->gprs[ARM_PC] = BASE_UNDEF; cpu->gprs[ARM_PC] = BASE_UNDEF;
if (ARMControlRegIsVE(cpu->cp15.r1.c0)) { if (ARMControlRegIsVE(cpu->cp15.r1.c0)) {
@ -219,7 +219,7 @@ void ARMRaiseUndefined(struct ARMCore* cpu) {
ARM_WRITE_PC; ARM_WRITE_PC;
_ARMSetMode(cpu, MODE_ARM); _ARMSetMode(cpu, MODE_ARM);
cpu->spsr = cpsr; cpu->spsr = cpsr;
cpu->cpsr = ARMPSRFillI(cpu->cpsr); cpu->cpsr.i = 1;
cpu->cycles += currentCycles; cpu->cycles += currentCycles;
} }

View File

@ -37,15 +37,15 @@ static struct CLIDebuggerCommandSummary _armCommands[] = {
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
static inline void _printPSR(struct CLIDebuggerBackend* be, ARMPSR psr) { static inline void _printPSR(struct CLIDebuggerBackend* be, union PSR psr) {
be->printf(be, "%08X [%c%c%c%c%c%c%c]\n", psr, be->printf(be, "%08X [%c%c%c%c%c%c%c]\n", psr.packed,
ARMPSRIsN(psr) ? 'N' : '-', psr.n ? 'N' : '-',
ARMPSRIsZ(psr) ? 'Z' : '-', psr.z ? 'Z' : '-',
ARMPSRIsC(psr) ? 'C' : '-', psr.c ? 'C' : '-',
ARMPSRIsV(psr) ? 'V' : '-', psr.v ? 'V' : '-',
ARMPSRIsI(psr) ? 'I' : '-', psr.i ? 'I' : '-',
ARMPSRIsF(psr) ? 'F' : '-', psr.f ? 'F' : '-',
ARMPSRIsT(psr) ? 'T' : '-'); psr.t ? 'T' : '-');
} }
static void _disassemble(struct CLIDebuggerSystem* debugger, struct CLIDebugVector* dv) { static void _disassemble(struct CLIDebuggerSystem* debugger, struct CLIDebugVector* dv) {
@ -136,7 +136,7 @@ static void _printStatus(struct CLIDebuggerSystem* debugger) {
} }
_printPSR(be, cpu->cpsr); _printPSR(be, cpu->cpsr);
int instructionLength; int instructionLength;
enum ExecutionMode mode = ARMPSRIsT(cpu->cpsr); enum ExecutionMode mode = cpu->cpsr.t;
if (mode == MODE_ARM) { if (mode == MODE_ARM) {
instructionLength = WORD_SIZE_ARM; instructionLength = WORD_SIZE_ARM;
} else { } else {
@ -196,11 +196,11 @@ static uint32_t _lookupPlatformIdentifier(struct CLIDebuggerSystem* debugger, co
return cpu->gprs[ARM_PC]; return cpu->gprs[ARM_PC];
} }
if (strcmp(name, "cpsr") == 0) { if (strcmp(name, "cpsr") == 0) {
return cpu->cpsr; return cpu->cpsr.packed;
} }
// TODO: test if mode has SPSR // TODO: test if mode has SPSR
if (strcmp(name, "spsr") == 0) { if (strcmp(name, "spsr") == 0) {
return cpu->spsr; return cpu->spsr.packed;
} }
if (name[0] == 'r' && name[1] >= '0' && name[1] <= '9') { if (name[0] == 'r' && name[1] >= '0' && name[1] <= '9') {
int reg = atoi(&name[1]); int reg = atoi(&name[1]);

View File

@ -26,7 +26,7 @@ static struct ARMDebugBreakpoint* _lookupBreakpoint(struct ARMDebugBreakpointLis
static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform* d) { static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
struct ARMDebugger* debugger = (struct ARMDebugger*) d; struct ARMDebugger* debugger = (struct ARMDebugger*) d;
int instructionLength; int instructionLength;
enum ExecutionMode mode = ARMPSRIsT(debugger->cpu->cpsr); enum ExecutionMode mode = debugger->cpu->cpsr.t;
if (mode == MODE_ARM) { if (mode == MODE_ARM) {
instructionLength = WORD_SIZE_ARM; instructionLength = WORD_SIZE_ARM;
} else { } else {

View File

@ -31,7 +31,7 @@ static inline void _shiftLSL(struct ARMCore* cpu, uint32_t opcode) {
} }
if (!shift) { if (!shift) {
cpu->shifterOperand = shiftVal; cpu->shifterOperand = shiftVal;
cpu->shifterCarryOut = ARMPSRGetC(cpu->cpsr); cpu->shifterCarryOut = cpu->cpsr.c;
} else if (shift < 32) { } else if (shift < 32) {
cpu->shifterOperand = shiftVal << shift; cpu->shifterOperand = shiftVal << shift;
cpu->shifterCarryOut = (shiftVal >> (32 - shift)) & 1; cpu->shifterCarryOut = (shiftVal >> (32 - shift)) & 1;
@ -46,7 +46,7 @@ static inline void _shiftLSL(struct ARMCore* cpu, uint32_t opcode) {
int immediate = (opcode & 0x00000F80) >> 7; int immediate = (opcode & 0x00000F80) >> 7;
if (!immediate) { if (!immediate) {
cpu->shifterOperand = cpu->gprs[rm]; cpu->shifterOperand = cpu->gprs[rm];
cpu->shifterCarryOut = ARMPSRGetC(cpu->cpsr); cpu->shifterCarryOut = cpu->cpsr.c;
} else { } else {
cpu->shifterOperand = cpu->gprs[rm] << immediate; cpu->shifterOperand = cpu->gprs[rm] << immediate;
cpu->shifterCarryOut = (cpu->gprs[rm] >> (32 - immediate)) & 1; cpu->shifterCarryOut = (cpu->gprs[rm] >> (32 - immediate)) & 1;
@ -70,7 +70,7 @@ static inline void _shiftLSR(struct ARMCore* cpu, uint32_t opcode) {
} }
if (!shift) { if (!shift) {
cpu->shifterOperand = shiftVal; cpu->shifterOperand = shiftVal;
cpu->shifterCarryOut = ARMPSRGetC(cpu->cpsr); cpu->shifterCarryOut = cpu->cpsr.c;
} else if (shift < 32) { } else if (shift < 32) {
cpu->shifterOperand = shiftVal >> shift; cpu->shifterOperand = shiftVal >> shift;
cpu->shifterCarryOut = (shiftVal >> (shift - 1)) & 1; cpu->shifterCarryOut = (shiftVal >> (shift - 1)) & 1;
@ -109,7 +109,7 @@ static inline void _shiftASR(struct ARMCore* cpu, uint32_t opcode) {
} }
if (!shift) { if (!shift) {
cpu->shifterOperand = shiftVal; cpu->shifterOperand = shiftVal;
cpu->shifterCarryOut = ARMPSRGetC(cpu->cpsr); cpu->shifterCarryOut = cpu->cpsr.c;
} else if (shift < 32) { } else if (shift < 32) {
cpu->shifterOperand = shiftVal >> shift; cpu->shifterOperand = shiftVal >> shift;
cpu->shifterCarryOut = (shiftVal >> (shift - 1)) & 1; cpu->shifterCarryOut = (shiftVal >> (shift - 1)) & 1;
@ -149,7 +149,7 @@ static inline void _shiftROR(struct ARMCore* cpu, uint32_t opcode) {
int rotate = shift & 0x1F; int rotate = shift & 0x1F;
if (!shift) { if (!shift) {
cpu->shifterOperand = shiftVal; cpu->shifterOperand = shiftVal;
cpu->shifterCarryOut = ARMPSRGetC(cpu->cpsr); cpu->shifterCarryOut = cpu->cpsr.c;
} else if (rotate) { } else if (rotate) {
cpu->shifterOperand = ROR(shiftVal, rotate); cpu->shifterOperand = ROR(shiftVal, rotate);
cpu->shifterCarryOut = (shiftVal >> (rotate - 1)) & 1; cpu->shifterCarryOut = (shiftVal >> (rotate - 1)) & 1;
@ -164,7 +164,7 @@ static inline void _shiftROR(struct ARMCore* cpu, uint32_t opcode) {
cpu->shifterCarryOut = (cpu->gprs[rm] >> (immediate - 1)) & 1; cpu->shifterCarryOut = (cpu->gprs[rm] >> (immediate - 1)) & 1;
} else { } else {
// RRX // RRX
cpu->shifterOperand = (ARMPSRGetC(cpu->cpsr) << 31) | (((uint32_t) cpu->gprs[rm]) >> 1); cpu->shifterOperand = (cpu->cpsr.c << 31) | (((uint32_t) cpu->gprs[rm]) >> 1);
cpu->shifterCarryOut = cpu->gprs[rm] & 0x00000001; cpu->shifterCarryOut = cpu->gprs[rm] & 0x00000001;
} }
} }
@ -175,7 +175,7 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) {
int immediate = opcode & 0x000000FF; int immediate = opcode & 0x000000FF;
if (!rotate) { if (!rotate) {
cpu->shifterOperand = immediate; cpu->shifterOperand = immediate;
cpu->shifterCarryOut = ARMPSRGetC(cpu->cpsr); cpu->shifterCarryOut = cpu->cpsr.c;
} else { } else {
cpu->shifterOperand = ROR(immediate, rotate); cpu->shifterOperand = ROR(immediate, rotate);
cpu->shifterCarryOut = ARM_SIGN(cpu->shifterOperand); cpu->shifterCarryOut = ARM_SIGN(cpu->shifterOperand);
@ -186,76 +186,51 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) {
// Beware pre-processor antics // Beware pre-processor antics
#define ARM_ADDITION_S(M, N, D) \ #define ARM_ADDITION_S(M, N, D) \
if (rd == ARM_PC && _ARMModeHasSPSR(ARMPSRGetPriv(cpu->cpsr))) { \ if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \
cpu->cpsr = cpu->spsr; \ cpu->cpsr = cpu->spsr; \
_ARMReadCPSR(cpu); \ _ARMReadCPSR(cpu); \
} else { \ } else { \
ARMPSR cpsr = 0; \ cpu->cpsr.n = ARM_SIGN(D); \
cpsr = ARMPSROrUnsafeN(cpsr, ARM_SIGN(D)); \ cpu->cpsr.z = !(D); \
cpsr = ARMPSROrUnsafeZ(cpsr, !(D)); \ cpu->cpsr.c = ARM_CARRY_FROM(M, N, D); \
cpsr = ARMPSROrUnsafeC(cpsr, ARM_CARRY_FROM(M, N, D)); \ cpu->cpsr.v = ARM_V_ADDITION(M, N, D); \
cpsr = ARMPSROrUnsafeV(cpsr, ARM_V_ADDITION(M, N, D)); \
cpu->cpsr = (cpu->cpsr & (0x0FFFFFFF)) | cpsr; \
}
#define ARM_ADDITION_CARRY_S(M, N, D, C) \
if (rd == ARM_PC && _ARMModeHasSPSR(ARMPSRGetPriv(cpu->cpsr))) { \
cpu->cpsr = cpu->spsr; \
_ARMReadCPSR(cpu); \
} else { \
ARMPSR cpsr = 0; \
cpsr = ARMPSROrUnsafeN(cpsr, ARM_SIGN(D)); \
cpsr = ARMPSROrUnsafeZ(cpsr, !(D)); \
cpsr = ARMPSROrUnsafeC(cpsr, ARM_CARRY_FROM_CARRY(M, N, D, C)); \
cpsr = ARMPSROrUnsafeV(cpsr, ARM_V_ADDITION(M, N, D)); \
cpu->cpsr = (cpu->cpsr & (0x0FFFFFFF)) | cpsr; \
} }
#define ARM_SUBTRACTION_S(M, N, D) \ #define ARM_SUBTRACTION_S(M, N, D) \
if (rd == ARM_PC && _ARMModeHasSPSR(ARMPSRGetPriv(cpu->cpsr))) { \ if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \
cpu->cpsr = cpu->spsr; \ cpu->cpsr = cpu->spsr; \
_ARMReadCPSR(cpu); \ _ARMReadCPSR(cpu); \
} else { \ } else { \
ARMPSR cpsr = 0; \ cpu->cpsr.n = ARM_SIGN(D); \
cpsr = ARMPSROrUnsafeN(cpsr, ARM_SIGN(D)); \ cpu->cpsr.z = !(D); \
cpsr = ARMPSROrUnsafeZ(cpsr, !(D)); \ cpu->cpsr.c = ARM_BORROW_FROM(M, N, D); \
cpsr = ARMPSROrUnsafeC(cpsr, ARM_BORROW_FROM(M, N, D)); \ cpu->cpsr.v = ARM_V_SUBTRACTION(M, N, D); \
cpsr = ARMPSROrUnsafeV(cpsr, ARM_V_SUBTRACTION(M, N, D)); \
cpu->cpsr = (cpu->cpsr & (0x0FFFFFFF)) | cpsr; \
} }
#define ARM_SUBTRACTION_CARRY_S(M, N, D, C) \ #define ARM_SUBTRACTION_CARRY_S(M, N, D, C) \
if (rd == ARM_PC && _ARMModeHasSPSR(ARMPSRGetPriv(cpu->cpsr))) { \ if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \
cpu->cpsr = cpu->spsr; \ cpu->cpsr = cpu->spsr; \
_ARMReadCPSR(cpu); \ _ARMReadCPSR(cpu); \
} else { \ } else { \
ARMPSR cpsr = 0; \ cpu->cpsr.n = ARM_SIGN(D); \
cpsr = ARMPSROrUnsafeN(cpsr, ARM_SIGN(D)); \ cpu->cpsr.z = !(D); \
cpsr = ARMPSROrUnsafeZ(cpsr, !(D)); \ cpu->cpsr.c = ARM_BORROW_FROM_CARRY(M, N, D, C); \
cpsr = ARMPSROrUnsafeC(cpsr, ARM_BORROW_FROM_CARRY(M, N, D, C)); \ cpu->cpsr.v = ARM_V_SUBTRACTION(M, N, D); \
cpsr = ARMPSROrUnsafeV(cpsr, ARM_V_SUBTRACTION(M, N, D)); \
cpu->cpsr = (cpu->cpsr & (0x0FFFFFFF)) | cpsr; \
} }
#define ARM_NEUTRAL_S(M, N, D) \ #define ARM_NEUTRAL_S(M, N, D) \
if (rd == ARM_PC && _ARMModeHasSPSR(ARMPSRGetPriv(cpu->cpsr))) { \ if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \
cpu->cpsr = cpu->spsr; \ cpu->cpsr = cpu->spsr; \
_ARMReadCPSR(cpu); \ _ARMReadCPSR(cpu); \
} else { \ } else { \
ARMPSR cpsr = 0; \ cpu->cpsr.n = ARM_SIGN(D); \
cpsr = ARMPSROrUnsafeN(cpsr, ARM_SIGN(D)); \ cpu->cpsr.z = !(D); \
cpsr = ARMPSROrUnsafeZ(cpsr, !(D)); \ cpu->cpsr.c = cpu->shifterCarryOut; \
cpsr = ARMPSROrUnsafeC(cpsr, cpu->shifterCarryOut); \
cpu->cpsr = (cpu->cpsr & (0x1FFFFFFF)) | cpsr; \
} }
#define ARM_NEUTRAL_HI_S(DLO, DHI) \ #define ARM_NEUTRAL_HI_S(DLO, DHI) \
{ \ cpu->cpsr.n = ARM_SIGN(DHI); \
ARMPSR cpsr = 0; \ cpu->cpsr.z = !((DHI) | (DLO));
cpsr = ARMPSROrUnsafeN(cpsr, ARM_SIGN(DHI)); \
cpsr = ARMPSROrUnsafeZ(cpsr, !((DHI) | (DLO))); \
cpu->cpsr = (cpu->cpsr & (0x3FFFFFFF)) | cpsr; \
}
#define ADDR_MODE_2_I_TEST (opcode & 0x00000F80) #define ADDR_MODE_2_I_TEST (opcode & 0x00000F80)
#define ADDR_MODE_2_I ((opcode & 0x00000F80) >> 7) #define ADDR_MODE_2_I ((opcode & 0x00000F80) >> 7)
@ -273,7 +248,7 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) {
#define ADDR_MODE_2_LSL (cpu->gprs[rm] << ADDR_MODE_2_I) #define ADDR_MODE_2_LSL (cpu->gprs[rm] << ADDR_MODE_2_I)
#define ADDR_MODE_2_LSR (ADDR_MODE_2_I_TEST ? ((uint32_t) cpu->gprs[rm]) >> ADDR_MODE_2_I : 0) #define ADDR_MODE_2_LSR (ADDR_MODE_2_I_TEST ? ((uint32_t) cpu->gprs[rm]) >> ADDR_MODE_2_I : 0)
#define ADDR_MODE_2_ASR (ADDR_MODE_2_I_TEST ? ((int32_t) cpu->gprs[rm]) >> ADDR_MODE_2_I : ((int32_t) cpu->gprs[rm]) >> 31) #define ADDR_MODE_2_ASR (ADDR_MODE_2_I_TEST ? ((int32_t) cpu->gprs[rm]) >> ADDR_MODE_2_I : ((int32_t) cpu->gprs[rm]) >> 31)
#define ADDR_MODE_2_ROR (ADDR_MODE_2_I_TEST ? ROR(cpu->gprs[rm], ADDR_MODE_2_I) : (ARMPSRGetC(cpu->cpsr) << 31) | (((uint32_t) cpu->gprs[rm]) >> 1)) #define ADDR_MODE_2_ROR (ADDR_MODE_2_I_TEST ? ROR(cpu->gprs[rm], ADDR_MODE_2_I) : (cpu->cpsr.c << 31) | (((uint32_t) cpu->gprs[rm]) >> 1))
#define ADDR_MODE_3_ADDRESS ADDR_MODE_2_ADDRESS #define ADDR_MODE_3_ADDRESS ADDR_MODE_2_ADDRESS
#define ADDR_MODE_3_RN ADDR_MODE_2_RN #define ADDR_MODE_3_RN ADDR_MODE_2_RN
@ -479,9 +454,9 @@ DEFINE_ALU_INSTRUCTION_ARM(ADD, ARM_ADDITION_S(n, cpu->shifterOperand, cpu->gprs
int32_t n = cpu->gprs[rn]; int32_t n = cpu->gprs[rn];
cpu->gprs[rd] = n + cpu->shifterOperand;) cpu->gprs[rd] = n + cpu->shifterOperand;)
DEFINE_ALU_INSTRUCTION_ARM(ADC, ARM_ADDITION_CARRY_S(n, cpu->shifterOperand, cpu->gprs[rd], ARMPSRGetC(cpu->cpsr)), DEFINE_ALU_INSTRUCTION_ARM(ADC, ARM_ADDITION_S(n, cpu->shifterOperand, cpu->gprs[rd]),
int32_t n = cpu->gprs[rn]; int32_t n = cpu->gprs[rn];
cpu->gprs[rd] = n + cpu->shifterOperand + ARMPSRGetC(cpu->cpsr);) cpu->gprs[rd] = n + cpu->shifterOperand + cpu->cpsr.c;)
DEFINE_ALU_INSTRUCTION_ARM(AND, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), DEFINE_ALU_INSTRUCTION_ARM(AND, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]),
cpu->gprs[rd] = cpu->gprs[rn] & cpu->shifterOperand;) cpu->gprs[rd] = cpu->gprs[rn] & cpu->shifterOperand;)
@ -511,13 +486,13 @@ DEFINE_ALU_INSTRUCTION_ARM(RSB, ARM_SUBTRACTION_S(cpu->shifterOperand, n, cpu->g
int32_t n = cpu->gprs[rn]; int32_t n = cpu->gprs[rn];
cpu->gprs[rd] = cpu->shifterOperand - n;) cpu->gprs[rd] = cpu->shifterOperand - n;)
DEFINE_ALU_INSTRUCTION_ARM(RSC, ARM_SUBTRACTION_CARRY_S(cpu->shifterOperand, n, cpu->gprs[rd], !ARMPSRIsC(cpu->cpsr)), DEFINE_ALU_INSTRUCTION_ARM(RSC, ARM_SUBTRACTION_CARRY_S(cpu->shifterOperand, n, cpu->gprs[rd], !cpu->cpsr.c),
int32_t n = cpu->gprs[rn]; int32_t n = cpu->gprs[rn];
cpu->gprs[rd] = cpu->shifterOperand - n - !ARMPSRIsC(cpu->cpsr);) cpu->gprs[rd] = cpu->shifterOperand - n - !cpu->cpsr.c;)
DEFINE_ALU_INSTRUCTION_ARM(SBC, ARM_SUBTRACTION_CARRY_S(n, cpu->shifterOperand, cpu->gprs[rd], !ARMPSRIsC(cpu->cpsr)), DEFINE_ALU_INSTRUCTION_ARM(SBC, ARM_SUBTRACTION_CARRY_S(n, cpu->shifterOperand, cpu->gprs[rd], !cpu->cpsr.c),
int32_t n = cpu->gprs[rn]; int32_t n = cpu->gprs[rn];
cpu->gprs[rd] = n - cpu->shifterOperand - !ARMPSRIsC(cpu->cpsr);) cpu->gprs[rd] = n - cpu->shifterOperand - !cpu->cpsr.c;)
DEFINE_ALU_INSTRUCTION_ARM(SUB, ARM_SUBTRACTION_S(n, cpu->shifterOperand, cpu->gprs[rd]), DEFINE_ALU_INSTRUCTION_ARM(SUB, ARM_SUBTRACTION_S(n, cpu->shifterOperand, cpu->gprs[rd]),
int32_t n = cpu->gprs[rn]; int32_t n = cpu->gprs[rn];
@ -740,14 +715,14 @@ DEFINE_INSTRUCTION_ARM(MSR,
int32_t operand = cpu->gprs[opcode & 0x0000000F]; int32_t operand = cpu->gprs[opcode & 0x0000000F];
int32_t mask = (c ? 0x000000FF : 0) | (f ? 0xFF000000 : 0); int32_t mask = (c ? 0x000000FF : 0) | (f ? 0xFF000000 : 0);
if (mask & PSR_USER_MASK) { if (mask & PSR_USER_MASK) {
cpu->cpsr = (cpu->cpsr & ~PSR_USER_MASK) | (operand & PSR_USER_MASK); cpu->cpsr.packed = (cpu->cpsr.packed & ~PSR_USER_MASK) | (operand & PSR_USER_MASK);
} }
if (mask & PSR_STATE_MASK) { if (mask & PSR_STATE_MASK) {
cpu->cpsr = (cpu->cpsr & ~PSR_STATE_MASK) | (operand & PSR_STATE_MASK); cpu->cpsr.packed = (cpu->cpsr.packed & ~PSR_STATE_MASK) | (operand & PSR_STATE_MASK);
} }
if (cpu->privilegeMode != MODE_USER && (mask & PSR_PRIV_MASK)) { if (cpu->privilegeMode != MODE_USER && (mask & PSR_PRIV_MASK)) {
ARMSetPrivilegeMode(cpu, (enum PrivilegeMode) ((operand & 0x0000000F) | 0x00000010)); ARMSetPrivilegeMode(cpu, (enum PrivilegeMode) ((operand & 0x0000000F) | 0x00000010));
cpu->cpsr = (cpu->cpsr & ~PSR_PRIV_MASK) | (operand & PSR_PRIV_MASK); cpu->cpsr.packed = (cpu->cpsr.packed & ~PSR_PRIV_MASK) | (operand & PSR_PRIV_MASK);
} }
_ARMReadCPSR(cpu); _ARMReadCPSR(cpu);
if (cpu->executionMode == MODE_THUMB) { if (cpu->executionMode == MODE_THUMB) {
@ -764,15 +739,15 @@ DEFINE_INSTRUCTION_ARM(MSRR,
int32_t operand = cpu->gprs[opcode & 0x0000000F]; int32_t operand = cpu->gprs[opcode & 0x0000000F];
int32_t mask = (c ? 0x000000FF : 0) | (f ? 0xFF000000 : 0); int32_t mask = (c ? 0x000000FF : 0) | (f ? 0xFF000000 : 0);
mask &= PSR_USER_MASK | PSR_PRIV_MASK | PSR_STATE_MASK; mask &= PSR_USER_MASK | PSR_PRIV_MASK | PSR_STATE_MASK;
cpu->spsr = (cpu->spsr & ~mask) | (operand & mask) | 0x00000010;) cpu->spsr.packed = (cpu->spsr.packed & ~mask) | (operand & mask) | 0x00000010;)
DEFINE_INSTRUCTION_ARM(MRS, \ DEFINE_INSTRUCTION_ARM(MRS, \
int rd = (opcode >> 12) & 0xF; \ int rd = (opcode >> 12) & 0xF; \
cpu->gprs[rd] = cpu->cpsr;) cpu->gprs[rd] = cpu->cpsr.packed;)
DEFINE_INSTRUCTION_ARM(MRSR, \ DEFINE_INSTRUCTION_ARM(MRSR, \
int rd = (opcode >> 12) & 0xF; \ int rd = (opcode >> 12) & 0xF; \
cpu->gprs[rd] = cpu->spsr;) cpu->gprs[rd] = cpu->spsr.packed;)
DEFINE_INSTRUCTION_ARM(MSRI, DEFINE_INSTRUCTION_ARM(MSRI,
int c = opcode & 0x00010000; int c = opcode & 0x00010000;
@ -781,14 +756,14 @@ DEFINE_INSTRUCTION_ARM(MSRI,
int32_t operand = ROR(opcode & 0x000000FF, rotate); int32_t operand = ROR(opcode & 0x000000FF, rotate);
int32_t mask = (c ? 0x000000FF : 0) | (f ? 0xFF000000 : 0); int32_t mask = (c ? 0x000000FF : 0) | (f ? 0xFF000000 : 0);
if (mask & PSR_USER_MASK) { if (mask & PSR_USER_MASK) {
cpu->cpsr = (cpu->cpsr & ~PSR_USER_MASK) | (operand & PSR_USER_MASK); cpu->cpsr.packed = (cpu->cpsr.packed & ~PSR_USER_MASK) | (operand & PSR_USER_MASK);
} }
if (mask & PSR_STATE_MASK) { if (mask & PSR_STATE_MASK) {
cpu->cpsr = (cpu->cpsr & ~PSR_STATE_MASK) | (operand & PSR_STATE_MASK); cpu->cpsr.packed = (cpu->cpsr.packed & ~PSR_STATE_MASK) | (operand & PSR_STATE_MASK);
} }
if (cpu->privilegeMode != MODE_USER && (mask & PSR_PRIV_MASK)) { if (cpu->privilegeMode != MODE_USER && (mask & PSR_PRIV_MASK)) {
ARMSetPrivilegeMode(cpu, (enum PrivilegeMode) ((operand & 0x0000000F) | 0x00000010)); ARMSetPrivilegeMode(cpu, (enum PrivilegeMode) ((operand & 0x0000000F) | 0x00000010));
cpu->cpsr = (cpu->cpsr & ~PSR_PRIV_MASK) | (operand & PSR_PRIV_MASK); cpu->cpsr.packed = (cpu->cpsr.packed & ~PSR_PRIV_MASK) | (operand & PSR_PRIV_MASK);
} }
_ARMReadCPSR(cpu); _ARMReadCPSR(cpu);
if (cpu->executionMode == MODE_THUMB) { if (cpu->executionMode == MODE_THUMB) {
@ -806,7 +781,7 @@ DEFINE_INSTRUCTION_ARM(MSRRI,
int32_t operand = ROR(opcode & 0x000000FF, rotate); int32_t operand = ROR(opcode & 0x000000FF, rotate);
int32_t mask = (c ? 0x000000FF : 0) | (f ? 0xFF000000 : 0); int32_t mask = (c ? 0x000000FF : 0) | (f ? 0xFF000000 : 0);
mask &= PSR_USER_MASK | PSR_PRIV_MASK | PSR_STATE_MASK; mask &= PSR_USER_MASK | PSR_PRIV_MASK | PSR_STATE_MASK;
cpu->spsr = (cpu->spsr & ~mask) | (operand & mask) | 0x00000010;) cpu->spsr.packed = (cpu->spsr.packed & ~mask) | (operand & mask) | 0x00000010;)
DEFINE_INSTRUCTION_ARM(SWI, cpu->irqh.swi32(cpu, opcode & 0xFFFFFF)) DEFINE_INSTRUCTION_ARM(SWI, cpu->irqh.swi32(cpu, opcode & 0xFFFFFF))

View File

@ -12,42 +12,20 @@
// Beware pre-processor insanity // Beware pre-processor insanity
#define THUMB_ADDITION_S(M, N, D) \ #define THUMB_ADDITION_S(M, N, D) \
{ \ cpu->cpsr.n = ARM_SIGN(D); \
ARMPSR cpsr = 0; \ cpu->cpsr.z = !(D); \
cpsr = ARMPSROrUnsafeN(cpsr, ARM_SIGN(D)); \ cpu->cpsr.c = ARM_CARRY_FROM(M, N, D); \
cpsr = ARMPSROrUnsafeZ(cpsr, !(D)); \ cpu->cpsr.v = ARM_V_ADDITION(M, N, D);
cpsr = ARMPSROrUnsafeC(cpsr, ARM_CARRY_FROM(M, N, D)); \
cpsr = ARMPSROrUnsafeV(cpsr, ARM_V_ADDITION(M, N, D)); \
cpu->cpsr = (cpu->cpsr & (0x0FFFFFFF)) | cpsr; \
}
#define THUMB_ADDITION_CARRY_S(M, N, D, C) \
{ \
ARMPSR cpsr = 0; \
cpsr = ARMPSROrUnsafeN(cpsr, ARM_SIGN(D)); \
cpsr = ARMPSROrUnsafeZ(cpsr, !(D)); \
cpsr = ARMPSROrUnsafeC(cpsr, ARM_CARRY_FROM_CARRY(M, N, D, C)); \
cpsr = ARMPSROrUnsafeV(cpsr, ARM_V_ADDITION(M, N, D)); \
cpu->cpsr = (cpu->cpsr & (0x0FFFFFFF)) | cpsr; \
}
#define THUMB_SUBTRACTION_S(M, N, D) \ #define THUMB_SUBTRACTION_S(M, N, D) \
{ \ cpu->cpsr.n = ARM_SIGN(D); \
ARMPSR cpsr = 0; \ cpu->cpsr.z = !(D); \
cpsr = ARMPSROrUnsafeN(cpsr, ARM_SIGN(D)); \ cpu->cpsr.c = ARM_BORROW_FROM(M, N, D); \
cpsr = ARMPSROrUnsafeZ(cpsr, !(D)); \ cpu->cpsr.v = ARM_V_SUBTRACTION(M, N, D);
cpsr = ARMPSROrUnsafeC(cpsr, ARM_BORROW_FROM(M, N, D)); \
cpsr = ARMPSROrUnsafeV(cpsr, ARM_V_SUBTRACTION(M, N, D)); \
cpu->cpsr = (cpu->cpsr & (0x0FFFFFFF)) | cpsr; \
}
#define THUMB_NEUTRAL_S(M, N, D) \ #define THUMB_NEUTRAL_S(M, N, D) \
{ \ cpu->cpsr.n = ARM_SIGN(D); \
ARMPSR cpsr = 0; \ cpu->cpsr.z = !(D);
cpsr = ARMPSROrUnsafeN(cpsr, ARM_SIGN(D)); \
cpsr = ARMPSROrUnsafeZ(cpsr, !(D)); \
cpu->cpsr = (cpu->cpsr & (0x3FFFFFFF)) | cpsr; \
}
#define THUMB_ADDITION(D, M, N) \ #define THUMB_ADDITION(D, M, N) \
int n = N; \ int n = N; \
@ -87,31 +65,31 @@ DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LSL1,
if (!immediate) { if (!immediate) {
cpu->gprs[rd] = cpu->gprs[rm]; cpu->gprs[rd] = cpu->gprs[rm];
} else { } else {
cpu->cpsr = ARMPSRSetC(cpu->cpsr, (cpu->gprs[rm] >> (32 - immediate)) & 1); cpu->cpsr.c = (cpu->gprs[rm] >> (32 - immediate)) & 1;
cpu->gprs[rd] = cpu->gprs[rm] << immediate; cpu->gprs[rd] = cpu->gprs[rm] << immediate;
} }
THUMB_NEUTRAL_S( , , cpu->gprs[rd]);) THUMB_NEUTRAL_S( , , cpu->gprs[rd]);)
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LSR1, DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LSR1,
if (!immediate) { if (!immediate) {
cpu->cpsr = ARMPSRSetC(cpu->cpsr, ARM_SIGN(cpu->gprs[rm])); cpu->cpsr.c = ARM_SIGN(cpu->gprs[rm]);
cpu->gprs[rd] = 0; cpu->gprs[rd] = 0;
} else { } else {
cpu->cpsr = ARMPSRSetC(cpu->cpsr, (cpu->gprs[rm] >> (immediate - 1)) & 1); cpu->cpsr.c = (cpu->gprs[rm] >> (immediate - 1)) & 1;
cpu->gprs[rd] = ((uint32_t) cpu->gprs[rm]) >> immediate; cpu->gprs[rd] = ((uint32_t) cpu->gprs[rm]) >> immediate;
} }
THUMB_NEUTRAL_S( , , cpu->gprs[rd]);) THUMB_NEUTRAL_S( , , cpu->gprs[rd]);)
DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(ASR1, DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(ASR1,
if (!immediate) { if (!immediate) {
cpu->cpsr = ARMPSRSetC(cpu->cpsr, ARM_SIGN(cpu->gprs[rm])); cpu->cpsr.c = ARM_SIGN(cpu->gprs[rm]);
if (ARMPSRIsC(cpu->cpsr)) { if (cpu->cpsr.c) {
cpu->gprs[rd] = 0xFFFFFFFF; cpu->gprs[rd] = 0xFFFFFFFF;
} else { } else {
cpu->gprs[rd] = 0; cpu->gprs[rd] = 0;
} }
} else { } else {
cpu->cpsr = ARMPSRSetC(cpu->cpsr, (cpu->gprs[rm] >> (immediate - 1)) & 1); cpu->cpsr.c = (cpu->gprs[rm] >> (immediate - 1)) & 1;
cpu->gprs[rd] = cpu->gprs[rm] >> immediate; cpu->gprs[rd] = cpu->gprs[rm] >> immediate;
} }
THUMB_NEUTRAL_S( , , cpu->gprs[rd]);) THUMB_NEUTRAL_S( , , cpu->gprs[rd]);)
@ -166,13 +144,13 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(LSL2,
int rs = cpu->gprs[rn] & 0xFF; int rs = cpu->gprs[rn] & 0xFF;
if (rs) { if (rs) {
if (rs < 32) { if (rs < 32) {
cpu->cpsr = ARMPSRSetC(cpu->cpsr, (cpu->gprs[rd] >> (32 - rs)) & 1); cpu->cpsr.c = (cpu->gprs[rd] >> (32 - rs)) & 1;
cpu->gprs[rd] <<= rs; cpu->gprs[rd] <<= rs;
} else { } else {
if (rs > 32) { if (rs > 32) {
cpu->cpsr = ARMPSRClearC(cpu->cpsr); cpu->cpsr.c = 0;
} else { } else {
cpu->cpsr = ARMPSRSetC(cpu->cpsr, cpu->gprs[rd] & 0x00000001); cpu->cpsr.c = cpu->gprs[rd] & 0x00000001;
} }
cpu->gprs[rd] = 0; cpu->gprs[rd] = 0;
} }
@ -183,13 +161,13 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(LSR2,
int rs = cpu->gprs[rn] & 0xFF; int rs = cpu->gprs[rn] & 0xFF;
if (rs) { if (rs) {
if (rs < 32) { if (rs < 32) {
cpu->cpsr = ARMPSRSetC(cpu->cpsr, (cpu->gprs[rd] >> (rs - 1)) & 1); cpu->cpsr.c = (cpu->gprs[rd] >> (rs - 1)) & 1;
cpu->gprs[rd] = (uint32_t) cpu->gprs[rd] >> rs; cpu->gprs[rd] = (uint32_t) cpu->gprs[rd] >> rs;
} else { } else {
if (rs > 32) { if (rs > 32) {
cpu->cpsr = ARMPSRClearC(cpu->cpsr); cpu->cpsr.c = 0;
} else { } else {
cpu->cpsr = ARMPSRSetC(cpu->cpsr, ARM_SIGN(cpu->gprs[rd])); cpu->cpsr.c = ARM_SIGN(cpu->gprs[rd]);
} }
cpu->gprs[rd] = 0; cpu->gprs[rd] = 0;
} }
@ -200,11 +178,11 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ASR2,
int rs = cpu->gprs[rn] & 0xFF; int rs = cpu->gprs[rn] & 0xFF;
if (rs) { if (rs) {
if (rs < 32) { if (rs < 32) {
cpu->cpsr = ARMPSRSetC(cpu->cpsr, (cpu->gprs[rd] >> (rs - 1)) & 1); cpu->cpsr.c = (cpu->gprs[rd] >> (rs - 1)) & 1;
cpu->gprs[rd] >>= rs; cpu->gprs[rd] >>= rs;
} else { } else {
cpu->cpsr = ARMPSRSetC(cpu->cpsr, ARM_SIGN(cpu->gprs[rd])); cpu->cpsr.c = ARM_SIGN(cpu->gprs[rd]);
if (ARMPSRIsC(cpu->cpsr)) { if (cpu->cpsr.c) {
cpu->gprs[rd] = 0xFFFFFFFF; cpu->gprs[rd] = 0xFFFFFFFF;
} else { } else {
cpu->gprs[rd] = 0; cpu->gprs[rd] = 0;
@ -216,11 +194,11 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ASR2,
DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ADC, DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ADC,
int n = cpu->gprs[rn]; int n = cpu->gprs[rn];
int d = cpu->gprs[rd]; int d = cpu->gprs[rd];
cpu->gprs[rd] = d + n + ARMPSRGetC(cpu->cpsr); cpu->gprs[rd] = d + n + cpu->cpsr.c;
THUMB_ADDITION_CARRY_S(d, n, cpu->gprs[rd], ARMPSRGetC(cpu->cpsr));) THUMB_ADDITION_S(d, n, cpu->gprs[rd]);)
DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(SBC, DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(SBC,
int n = cpu->gprs[rn] + !ARMPSRIsC(cpu->cpsr); int n = cpu->gprs[rn] + !cpu->cpsr.c;
int d = cpu->gprs[rd]; int d = cpu->gprs[rd];
cpu->gprs[rd] = d - n; cpu->gprs[rd] = d - n;
THUMB_SUBTRACTION_S(d, n, cpu->gprs[rd]);) THUMB_SUBTRACTION_S(d, n, cpu->gprs[rd]);)
@ -229,10 +207,10 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ROR,
if (rs) { if (rs) {
int r4 = rs & 0x1F; int r4 = rs & 0x1F;
if (r4 > 0) { if (r4 > 0) {
cpu->cpsr = ARMPSRSetC(cpu->cpsr, (cpu->gprs[rd] >> (r4 - 1)) & 1); cpu->cpsr.c = (cpu->gprs[rd] >> (r4 - 1)) & 1;
cpu->gprs[rd] = ROR(cpu->gprs[rd], r4); cpu->gprs[rd] = ROR(cpu->gprs[rd], r4);
} else { } else {
cpu->cpsr = ARMPSRSetC(cpu->cpsr, ARM_SIGN(cpu->gprs[rd])); cpu->cpsr.c = ARM_SIGN(cpu->gprs[rd]);
} }
} }
THUMB_NEUTRAL_S( , , cpu->gprs[rd]);) THUMB_NEUTRAL_S( , , cpu->gprs[rd]);)

View File

@ -325,7 +325,7 @@ static void _readGPRs(struct GDBStub* stub, const char* message) {
_int2hex32(cpu->gprs[r], &stub->outgoing[i]); _int2hex32(cpu->gprs[r], &stub->outgoing[i]);
i += 8; i += 8;
} }
_int2hex32(cpu->gprs[ARM_PC] - (ARMPSRIsT(cpu->cpsr) ? WORD_SIZE_THUMB : WORD_SIZE_ARM), &stub->outgoing[i]); _int2hex32(cpu->gprs[ARM_PC] - (cpu->cpsr.t ? WORD_SIZE_THUMB : WORD_SIZE_ARM), &stub->outgoing[i]);
i += 8; i += 8;
stub->outgoing[i] = 0; stub->outgoing[i] = 0;
@ -359,7 +359,7 @@ static void _writeRegister(struct GDBStub* stub, const char* message) {
} }
} }
} else if (reg == 0x19) { } else if (reg == 0x19) {
cpu->cpsr = value; cpu->cpsr.packed = value;
} else { } else {
stub->outgoing[0] = '\0'; stub->outgoing[0] = '\0';
_sendMessage(stub); _sendMessage(stub);
@ -379,7 +379,7 @@ static void _readRegister(struct GDBStub* stub, const char* message) {
if (reg < 0x10) { if (reg < 0x10) {
value = cpu->gprs[reg]; value = cpu->gprs[reg];
} else if (reg == 0x19) { } else if (reg == 0x19) {
value = cpu->cpsr; value = cpu->cpsr.packed;
} else { } else {
stub->outgoing[0] = '\0'; stub->outgoing[0] = '\0';
_sendMessage(stub); _sendMessage(stub);

View File

@ -261,7 +261,7 @@ static void DS9ProcessEvents(struct ARMCore* cpu) {
static void DSProcessEvents(struct DSCommon* dscore) { static void DSProcessEvents(struct DSCommon* dscore) {
struct ARMCore* cpu = dscore->cpu; struct ARMCore* cpu = dscore->cpu;
struct DS* ds = dscore->p; struct DS* ds = dscore->p;
if (dscore->springIRQ && !ARMPSRGetI(cpu->cpsr)) { if (dscore->springIRQ && !cpu->cpsr.i) {
ARMRaiseIRQ(cpu); ARMRaiseIRQ(cpu);
dscore->springIRQ = 0; dscore->springIRQ = 0;
} }

View File

@ -25,11 +25,11 @@ static void _unBitPack(struct GBA* gba);
static void _SoftReset(struct GBA* gba) { static void _SoftReset(struct GBA* gba) {
struct ARMCore* cpu = gba->cpu; struct ARMCore* cpu = gba->cpu;
ARMSetPrivilegeMode(cpu, MODE_IRQ); ARMSetPrivilegeMode(cpu, MODE_IRQ);
cpu->spsr = 0; cpu->spsr.packed = 0;
cpu->gprs[ARM_LR] = 0; cpu->gprs[ARM_LR] = 0;
cpu->gprs[ARM_SP] = SP_BASE_IRQ; cpu->gprs[ARM_SP] = SP_BASE_IRQ;
ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR); ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
cpu->spsr = 0; cpu->spsr.packed = 0;
cpu->gprs[ARM_LR] = 0; cpu->gprs[ARM_LR] = 0;
cpu->gprs[ARM_SP] = SP_BASE_SUPERVISOR; cpu->gprs[ARM_SP] = SP_BASE_SUPERVISOR;
ARMSetPrivilegeMode(cpu, MODE_SYSTEM); ARMSetPrivilegeMode(cpu, MODE_SYSTEM);

View File

@ -227,7 +227,7 @@ static void GBAProcessEvents(struct ARMCore* cpu) {
gba->bus |= cpu->prefetch[1] << 16; gba->bus |= cpu->prefetch[1] << 16;
} }
if (gba->springIRQ && !ARMPSRIsI(cpu->cpsr)) { if (gba->springIRQ && !cpu->cpsr.i) {
ARMRaiseIRQ(cpu); ARMRaiseIRQ(cpu);
gba->springIRQ = 0; gba->springIRQ = 0;
} }

View File

@ -160,39 +160,35 @@ size_t GBASavedataSize(struct GBASavedata* savedata) {
} }
bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in) { bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in) {
if (savedata->vf) { if (savedata->data) {
if (!in && savedata->type != SAVEDATA_FORCE_NONE) {
return false;
}
ssize_t size = GBASavedataSize(savedata);
in->seek(in, 0, SEEK_SET);
return in->read(in, savedata->data, size) == size;
} else if (savedata->vf) {
off_t read = 0; off_t read = 0;
uint8_t buffer[2048]; uint8_t buffer[2048];
memset(buffer, 0xFF, sizeof(buffer));
savedata->vf->seek(savedata->vf, 0, SEEK_SET);
while (savedata->vf->seek(savedata->vf, 0, SEEK_CUR) < savedata->vf->size(savedata->vf)) {
savedata->vf->write(savedata->vf, buffer, sizeof(buffer));
}
savedata->vf->seek(savedata->vf, 0, SEEK_SET); savedata->vf->seek(savedata->vf, 0, SEEK_SET);
if (in) { if (in) {
in->seek(in, 0, SEEK_SET);
do { do {
read = in->read(in, buffer, sizeof(buffer)); read = in->read(in, buffer, sizeof(buffer));
read = savedata->vf->write(savedata->vf, buffer, read); read = savedata->vf->write(savedata->vf, buffer, read);
} while (read == sizeof(buffer)); } while (read == sizeof(buffer));
} }
memset(buffer, 0xFF, sizeof(buffer));
ssize_t fsize = savedata->vf->size(savedata->vf);
ssize_t pos = savedata->vf->seek(savedata->vf, 0, SEEK_CUR);
while (fsize - pos >= (ssize_t) sizeof(buffer)) {
savedata->vf->write(savedata->vf, buffer, sizeof(buffer));
pos = savedata->vf->seek(savedata->vf, 0, SEEK_CUR);
}
if (fsize - pos > 0) {
savedata->vf->write(savedata->vf, buffer, fsize - pos);
}
return read >= 0; return read >= 0;
} else if (savedata->data) {
if (!in && savedata->type != SAVEDATA_FORCE_NONE) {
return false;
}
switch (savedata->type) {
case SAVEDATA_SRAM:
return in->read(in, savedata->data, SIZE_CART_SRAM) == SIZE_CART_SRAM;
case SAVEDATA_FLASH512:
return in->read(in, savedata->data, SIZE_CART_FLASH512) == SIZE_CART_FLASH512;
case SAVEDATA_FLASH1M:
return in->read(in, savedata->data, SIZE_CART_FLASH1M) == SIZE_CART_FLASH1M;
case SAVEDATA_EEPROM:
return in->read(in, savedata->data, SIZE_CART_EEPROM) == SIZE_CART_EEPROM;
case SAVEDATA_AUTODETECT:
case SAVEDATA_FORCE_NONE:
return true;
}
} }
return true; return true;
} }
@ -560,8 +556,9 @@ void _flashSwitchBank(struct GBASavedata* savedata, int bank) {
mLOG(GBA_SAVE, DEBUG, "Performing flash bank switch to bank %i", bank); mLOG(GBA_SAVE, DEBUG, "Performing flash bank switch to bank %i", bank);
savedata->currentBank = &savedata->data[bank << 16]; savedata->currentBank = &savedata->data[bank << 16];
if (bank > 0 && savedata->type == SAVEDATA_FLASH512) { if (bank > 0 && savedata->type == SAVEDATA_FLASH512) {
mLOG(GBA_SAVE, INFO, "Updating flash chip from 512kb to 1Mb");
savedata->type = SAVEDATA_FLASH1M; savedata->type = SAVEDATA_FLASH1M;
if (savedata->vf) { if (savedata->vf && savedata->vf->size(savedata->vf) == SIZE_CART_FLASH512) {
savedata->vf->truncate(savedata->vf, SIZE_CART_FLASH1M); savedata->vf->truncate(savedata->vf, SIZE_CART_FLASH1M);
memset(&savedata->data[SIZE_CART_FLASH512], 0xFF, SIZE_CART_FLASH512); memset(&savedata->data[SIZE_CART_FLASH512], 0xFF, SIZE_CART_FLASH512);
} }

View File

@ -42,8 +42,8 @@ void GBASerialize(struct GBA* gba, struct GBASerializedState* state) {
for (i = 0; i < 16; ++i) { for (i = 0; i < 16; ++i) {
STORE_32(gba->cpu->gprs[i], i * sizeof(state->cpu.gprs[0]), state->cpu.gprs); STORE_32(gba->cpu->gprs[i], i * sizeof(state->cpu.gprs[0]), state->cpu.gprs);
} }
STORE_32(gba->cpu->cpsr, 0, &state->cpu.cpsr); STORE_32(gba->cpu->cpsr.packed, 0, &state->cpu.cpsr.packed);
STORE_32(gba->cpu->spsr, 0, &state->cpu.spsr); STORE_32(gba->cpu->spsr.packed, 0, &state->cpu.spsr.packed);
STORE_32(gba->cpu->cycles, 0, &state->cpu.cycles); STORE_32(gba->cpu->cycles, 0, &state->cpu.cycles);
STORE_32(gba->cpu->nextEvent, 0, &state->cpu.nextEvent); STORE_32(gba->cpu->nextEvent, 0, &state->cpu.nextEvent);
for (i = 0; i < 6; ++i) { for (i = 0; i < 6; ++i) {
@ -151,8 +151,8 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
for (i = 0; i < 16; ++i) { for (i = 0; i < 16; ++i) {
LOAD_32(gba->cpu->gprs[i], i * sizeof(gba->cpu->gprs[0]), state->cpu.gprs); LOAD_32(gba->cpu->gprs[i], i * sizeof(gba->cpu->gprs[0]), state->cpu.gprs);
} }
LOAD_32(gba->cpu->cpsr, 0, &state->cpu.cpsr); LOAD_32(gba->cpu->cpsr.packed, 0, &state->cpu.cpsr.packed);
LOAD_32(gba->cpu->spsr, 0, &state->cpu.spsr); LOAD_32(gba->cpu->spsr.packed, 0, &state->cpu.spsr.packed);
LOAD_32(gba->cpu->cycles, 0, &state->cpu.cycles); LOAD_32(gba->cpu->cycles, 0, &state->cpu.cycles);
LOAD_32(gba->cpu->nextEvent, 0, &state->cpu.nextEvent); LOAD_32(gba->cpu->nextEvent, 0, &state->cpu.nextEvent);
for (i = 0; i < 6; ++i) { for (i = 0; i < 6; ++i) {
@ -162,13 +162,13 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
} }
LOAD_32(gba->cpu->bankedSPSRs[i], i * sizeof(gba->cpu->bankedSPSRs[0]), state->cpu.bankedSPSRs); LOAD_32(gba->cpu->bankedSPSRs[i], i * sizeof(gba->cpu->bankedSPSRs[0]), state->cpu.bankedSPSRs);
} }
gba->cpu->privilegeMode = ARMPSRGetPriv(gba->cpu->cpsr); 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) { if (state->biosPrefetch) {
LOAD_32(gba->memory.biosPrefetch, 0, &state->biosPrefetch); LOAD_32(gba->memory.biosPrefetch, 0, &state->biosPrefetch);
} }
LOAD_32(gba->memory.lastPrefetchedPc, 0, &state->lastPrefetchedPc); LOAD_32(gba->memory.lastPrefetchedPc, 0, &state->lastPrefetchedPc);
if (ARMPSRIsT(gba->cpu->cpsr)) { if (gba->cpu->cpsr.t) {
gba->cpu->executionMode = MODE_THUMB; gba->cpu->executionMode = MODE_THUMB;
if (state->cpuPrefetch[0] && state->cpuPrefetch[1]) { if (state->cpuPrefetch[0] && state->cpuPrefetch[1]) {
LOAD_32(gba->cpu->prefetch[0], 0, state->cpuPrefetch); LOAD_32(gba->cpu->prefetch[0], 0, state->cpuPrefetch);

View File

@ -236,7 +236,7 @@ if(Qt5LinguistTools_FOUND)
qt5_add_translation(TRANSLATION_FILES ${TS_FILES}) qt5_add_translation(TRANSLATION_FILES ${TS_FILES})
endif() endif()
add_custom_command(OUTPUT ${TRANSLATION_QRC} add_custom_command(OUTPUT ${TRANSLATION_QRC}
COMMAND ${CMAKE_COMMAND} -DTRANSLATION_QRC:FILEPATH="${TRANSLATION_QRC}" -DTRANSLATION_FILES="${TRANSLATION_FILES}" -P "${CMAKE_CURRENT_SOURCE_DIR}/ts.cmake" COMMAND ${CMAKE_COMMAND} -DTRANSLATION_QRC:FILEPATH="${TRANSLATION_QRC}" -DQM_BASE="${CMAKE_CURRENT_BINARY_DIR}" -P "${CMAKE_CURRENT_SOURCE_DIR}/ts.cmake"
DEPENDS ${TRANSLATION_FILES}) DEPENDS ${TRANSLATION_FILES})
qt5_add_resources(TRANSLATION_RESOURCES ${TRANSLATION_QRC}) qt5_add_resources(TRANSLATION_RESOURCES ${TRANSLATION_QRC})
list(APPEND RESOURCES ${TRANSLATION_RESOURCES}) list(APPEND RESOURCES ${TRANSLATION_RESOURCES})

View File

@ -525,11 +525,11 @@ void GameController::loadBIOS(int platform, const QString& path) {
if (m_bios == path) { if (m_bios == path) {
return; return;
} }
if (m_gameOpen && this->platform() == platform) { if (!m_bios.isNull() && m_gameOpen && this->platform() == platform) {
closeGame(); closeGame();
m_bios = path; m_bios = path;
openGame(); openGame();
} else if (!m_gameOpen) { } else if (!m_gameOpen || m_bios.isNull()) {
m_bios = path; m_bios = path;
} }
} }

View File

@ -6,6 +6,11 @@
#include "GBAApp.h" #include "GBAApp.h"
#include "Window.h" #include "Window.h"
#include <QLibraryInfo>
#include <QTranslator>
#include <mgba/core/version.h>
#ifdef QT_STATIC #ifdef QT_STATIC
#include <QtPlugin> #include <QtPlugin>
#ifdef _WIN32 #ifdef _WIN32
@ -18,5 +23,16 @@ Q_IMPORT_PLUGIN(QWindowsAudioPlugin);
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
QGBA::GBAApp application(argc, argv); QGBA::GBAApp application(argc, argv);
QLocale locale = QLocale::system();
QTranslator qtTranslator;
qtTranslator.load(locale, "qt", "_", QLibraryInfo::location(QLibraryInfo::TranslationsPath));
application.installTranslator(&qtTranslator);
QTranslator langTranslator;
langTranslator.load(locale, binaryName, "-", ":/translations/");
application.installTranslator(&langTranslator);
return application.exec(); return application.exec();
} }

View File

@ -1,5 +1,8 @@
file(GLOB TRANSLATION_FILES "${QM_BASE}/*.qm")
file(WRITE ${TRANSLATION_QRC} "<RCC>\n\t<qresource prefix=\"/translations/\">\n") file(WRITE ${TRANSLATION_QRC} "<RCC>\n\t<qresource prefix=\"/translations/\">\n")
message(STATUS ${TRANSLATION_FILES})
foreach(TS ${TRANSLATION_FILES}) foreach(TS ${TRANSLATION_FILES})
message(STATUS ${TS})
get_filename_component(TS_BASE "${TS}" NAME) get_filename_component(TS_BASE "${TS}" NAME)
file(APPEND ${TRANSLATION_QRC} "\t\t<file>${TS_BASE}</file>\n") file(APPEND ${TRANSLATION_QRC} "\t\t<file>${TS_BASE}</file>\n")
endforeach() endforeach()

File diff suppressed because it is too large Load Diff