Merge branch 'master' (early part) into medusa

This commit is contained in:
Vicki Pfau 2020-06-17 22:32:17 -07:00
commit 393d4b4606
37 changed files with 759 additions and 559 deletions

19
CHANGES
View File

@ -25,8 +25,16 @@ Features:
Emulation fixes: Emulation fixes:
- ARM: Fix ALU reading PC after shifting - ARM: Fix ALU reading PC after shifting
- ARM: Fix STR storing PC after address calculation - ARM: Fix STR storing PC after address calculation
- ARM: Fix timing on Thumb shift instructions
- GB: Fix GBC game registers after skipping BIOS
- GB MBC: Support 4MB MBC30 ROMs (fixes mgba.io/i/1713)
- GB Video: Fix state after skipping BIOS (fixes mgba.io/i/1715 and mgba.io/i/1716)
- GB Video: Fix BGPS value after skipping BIOS (fixes mgba.io/i/1717)
- GBA: Add missing RTC overrides for Legendz games
- GBA: Fix timing advancing too quickly in rare cases
- GBA BIOS: Implement dummy sound driver calls - GBA BIOS: Implement dummy sound driver calls
- GBA BIOS: Improve HLE BIOS timing - GBA BIOS: Improve HLE BIOS timing
- GBA BIOS: Reset renderer when RegisterRamReset called (fixes mgba.io/i/1756)
- GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320)
- GBA Memory: Improve gamepak prefetch timing - GBA Memory: Improve gamepak prefetch timing
- GBA SIO: Fix Multiplayer busy bit - GBA SIO: Fix Multiplayer busy bit
@ -35,7 +43,14 @@ Emulation fixes:
- GBA Timers: Fix deserializing count-up timers - GBA Timers: Fix deserializing count-up timers
- GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319) - GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319)
- GBA Video: Fix Hblank timing - GBA Video: Fix Hblank timing
- GBA Video: Fix mosaic objects drawing past the end (fixes mgba.io/i/1702)
- GBA Video: Fix disabling OBJWIN in GL renderer (fixes mgba.io/i/1759)
- GBA Video: Add missing parts of 256-color mode 0 mosaic (fixes mgba.io/1701)
- GBA Video: Fix double-size OBJ wrapping in GL renderer (fixes mgba.io/1712)
Other fixes: Other fixes:
- All: Improve export headers (fixes mgba.io/i/1738)
- ARM Debugger: Clear low bit on breakpoint addresses (fixes mgba.io/i/1764)
- CMake: Always use devkitPro toolchain when applicable (fixes mgba.io/i/1755)
- Core: Ensure ELF regions can be written before trying - Core: Ensure ELF regions can be written before trying
- Core: Fix ELF loading regression (fixes mgba.io/i/1669) - Core: Fix ELF loading regression (fixes mgba.io/i/1669)
- Core: Fix crash modifying hash table entry (fixes mgba.io/i/1673) - Core: Fix crash modifying hash table entry (fixes mgba.io/i/1673)
@ -44,8 +59,12 @@ Other fixes:
- Debugger: Don't skip undefined instructions when debugger attached - Debugger: Don't skip undefined instructions when debugger attached
- Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642)
- Qt: Fix OpenGL 2.1 support (fixes mgba.io/i/1678) - Qt: Fix OpenGL 2.1 support (fixes mgba.io/i/1678)
- Qt: Fix static compilation in MinGW (fixes mgba.io/i/1769)
Misc: Misc:
- 3DS: Clean up legacy initialization (fixes mgba.io/i/1768)
- Debugger: Keep track of global cycle count
- FFmpeg: Add looping option for GIF/APNG - FFmpeg: Add looping option for GIF/APNG
- GBA Serialize: Only flunk BIOS check if official BIOS was expected
- Qt: Renderer can be changed while a game is running - Qt: Renderer can be changed while a game is running
- Qt: Add hex index to palette view - Qt: Add hex index to palette view
- Qt: Add transformation matrix info to sprite view - Qt: Add transformation matrix info to sprite view

View File

@ -9,14 +9,17 @@ if(POLICY CMP0072)
endif() endif()
project(medusa) project(medusa)
set(BINARY_NAME medusa-emu CACHE INTERNAL "Name of output binaries") set(BINARY_NAME medusa-emu CACHE INTERNAL "Name of output binaries")
set(CMAKE_C_STANDARD 99)
if(NOT MSVC) if(NOT MSVC)
set(GCC_STD "c99") set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
if(SWITCH) if(SWITCH)
set(GCC_STD "gnu11") set(CMAKE_C_STANDARD 11)
elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_COMPILER_VERSION VERSION_LESS "4.3") set(CMAKE_C_EXTENSIONS ON)
set(GCC_STD "gnu99") elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.3")
set(CMAKE_C_EXTENSIONS ON)
endif() endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-missing-field-initializers -std=${GCC_STD}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-missing-field-initializers")
else() else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146")
endif() endif()
@ -174,9 +177,9 @@ endif()
if(WIN32) if(WIN32)
set(WIN32_VERSION "${LIB_VERSION_MAJOR},${LIB_VERSION_MINOR},${LIB_VERSION_PATCH}") set(WIN32_VERSION "${LIB_VERSION_MAJOR},${LIB_VERSION_MINOR},${LIB_VERSION_PATCH}")
add_definitions(-D_WIN32_WINNT=0x0600) add_definitions(-D_WIN32_WINNT=0x0600)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
if(MSVC) if(MSVC)
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN) add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
add_definitions(-D_UNICODE -DUNICODE) add_definitions(-D_UNICODE -DUNICODE)
else() else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -municode") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -municode")
@ -848,6 +851,7 @@ if(NOT SKIP_LIBRARY)
if(BUILD_SHARED) if(BUILD_SHARED)
add_library(${BINARY_NAME} SHARED ${SRC} ${VFS_SRC}) add_library(${BINARY_NAME} SHARED ${SRC} ${VFS_SRC})
set(EXPORT_DEFINES MGBA_DLL)
if(BUILD_STATIC) if(BUILD_STATIC)
add_library(${BINARY_NAME}-static STATIC ${SRC}) add_library(${BINARY_NAME}-static STATIC ${SRC})
target_include_directories(${BINARY_NAME}-static BEFORE PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}/include) target_include_directories(${BINARY_NAME}-static BEFORE PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}/include)
@ -861,12 +865,10 @@ if(NOT SKIP_LIBRARY)
endif() endif()
target_include_directories(${BINARY_NAME} BEFORE PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}/include) target_include_directories(${BINARY_NAME} BEFORE PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}/include)
set_target_properties(${BINARY_NAME} PROPERTIES VERSION ${LIB_VERSION_STRING} SOVERSION ${LIB_VERSION_ABI} COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}" COMPILE_OPTIONS "${FEATURE_FLAGS}") set_target_properties(${BINARY_NAME} PROPERTIES VERSION ${LIB_VERSION_STRING} SOVERSION ${LIB_VERSION_ABI} COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES};${EXPORT_DEFINES}" COMPILE_OPTIONS "${FEATURE_FLAGS}")
add_dependencies(${BINARY_NAME} version-info) add_dependencies(${BINARY_NAME} version-info)
include(GenerateExportHeader)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/mgba-util) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/mgba-util)
generate_export_header(${BINARY_NAME} BASE_NAME MGBA STATIC_DEFINE BUILD_STATIC EXPORT_FILE_NAME ${CMAKE_CURRENT_BINARY_DIR}/include/mgba-util/dllexports.h)
target_link_libraries(${BINARY_NAME} ${DEBUGGER_LIB} ${DEPENDENCY_LIB} ${OS_LIB}) target_link_libraries(${BINARY_NAME} ${DEBUGGER_LIB} ${DEPENDENCY_LIB} ${OS_LIB})
install(TARGETS ${BINARY_NAME} LIBRARY DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME} NAMELINK_SKIP ARCHIVE DESTINATION ${LIBDIR} RUNTIME DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME}) install(TARGETS ${BINARY_NAME} LIBRARY DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME} NAMELINK_SKIP ARCHIVE DESTINATION ${LIBDIR} RUNTIME DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME})

View File

@ -144,6 +144,8 @@ This will produce a `build-win32` directory with the build products. Replace `mg
- mgba/ubuntu:bionic - mgba/ubuntu:bionic
- mgba/ubuntu:cosmic - mgba/ubuntu:cosmic
- mgba/ubuntu:disco - mgba/ubuntu:disco
- mgba/ubuntu:eoan
- mgba/ubuntu:focal
- mgba/vita - mgba/vita
- mgba/wii - mgba/wii
- mgba/windows:w32 - mgba/windows:w32

View File

@ -126,6 +126,8 @@ Dieser Befehl erzeugt ein Verzeichnis `build-win32` mit den erzeugten Programmda
- mgba/ubuntu:bionic - mgba/ubuntu:bionic
- mgba/ubuntu:cosmic - mgba/ubuntu:cosmic
- mgba/ubuntu:disco - mgba/ubuntu:disco
- mgba/ubuntu:eoan
- mgba/ubuntu:focal
- mgba/vita - mgba/vita
- mgba/wii - mgba/wii
- mgba/windows:w32 - mgba/windows:w32

View File

@ -65,12 +65,7 @@ typedef intptr_t ssize_t;
#include <sys/syslimits.h> #include <sys/syslimits.h>
#endif #endif
#ifndef MGBA_STANDALONE
#include <mgba-util/dllexports.h> #include <mgba-util/dllexports.h>
#else
#define MGBA_EXPORT
#define MGBA_NO_EXPORT
#endif
#ifndef SSIZE_MAX #ifndef SSIZE_MAX
#define SSIZE_MAX ((ssize_t) (SIZE_MAX >> 1)) #define SSIZE_MAX ((ssize_t) (SIZE_MAX >> 1))

View File

@ -0,0 +1,19 @@
/* Copyright (c) 2013-2020 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/. */
#ifndef MGBA_EXPORT_H
#define MGBA_EXPORT_H
#if defined(BUILD_STATIC) || !defined(_MSC_VER) || defined(MGBA_STANDALONE)
#define MGBA_EXPORT
#else
#ifdef MGBA_DLL
#define MGBA_EXPORT __declspec(dllexport)
#else
#define MGBA_EXPORT __declspec(dllimport)
#endif
#endif
#endif

View File

@ -25,6 +25,7 @@ struct mTiming {
struct mTimingEvent* root; struct mTimingEvent* root;
struct mTimingEvent* reroot; struct mTimingEvent* reroot;
uint64_t globalCycles;
uint32_t masterCycles; uint32_t masterCycles;
int32_t* relativeCycles; int32_t* relativeCycles;
int32_t* nextEvent; int32_t* nextEvent;
@ -38,6 +39,7 @@ void mTimingDeschedule(struct mTiming* timing, struct mTimingEvent*);
bool mTimingIsScheduled(const struct mTiming* timing, const struct mTimingEvent*); bool mTimingIsScheduled(const struct mTiming* timing, const struct mTimingEvent*);
int32_t mTimingTick(struct mTiming* timing, int32_t cycles); int32_t mTimingTick(struct mTiming* timing, int32_t cycles);
int32_t mTimingCurrentTime(const struct mTiming* timing); int32_t mTimingCurrentTime(const struct mTiming* timing);
uint64_t mTimingGlobalTime(const struct mTiming* timing);
int32_t mTimingNextEvent(struct mTiming* timing); int32_t mTimingNextEvent(struct mTiming* timing);
int32_t mTimingUntil(const struct mTiming* timing, const struct mTimingEvent*); int32_t mTimingUntil(const struct mTiming* timing, const struct mTimingEvent*);

View File

@ -10,11 +10,7 @@
extern "C" { extern "C" {
#endif #endif
#ifdef MGBA_STANDALONE
#define MGBA_EXPORT
#else
#include <mgba-util/dllexports.h> #include <mgba-util/dllexports.h>
#endif
extern MGBA_EXPORT const char* const gitCommit; extern MGBA_EXPORT const char* const gitCommit;
extern MGBA_EXPORT const char* const gitCommitShort; extern MGBA_EXPORT const char* const gitCommitShort;

View File

@ -70,7 +70,7 @@ struct ARMCore;
union PSR { union PSR {
struct { struct {
#if defined(__POWERPC__) || defined(__PPC__) #if defined(__BIG_ENDIAN__)
unsigned n : 1; unsigned n : 1;
unsigned z : 1; unsigned z : 1;
unsigned c : 1; unsigned c : 1;

View File

@ -84,7 +84,7 @@ enum GBIORegisters {
REG_WX = 0x4B, REG_WX = 0x4B,
// CGB // CGB
REG_UNK4C = 0x4C, REG_KEY0 = 0x4C,
REG_KEY1 = 0x4D, REG_KEY1 = 0x4D,
REG_VBK = 0x4F, REG_VBK = 0x4F,
REG_HDMA1 = 0x51, REG_HDMA1 = 0x51,
@ -97,7 +97,7 @@ enum GBIORegisters {
REG_BCPD = 0x69, REG_BCPD = 0x69,
REG_OCPS = 0x6A, REG_OCPS = 0x6A,
REG_OCPD = 0x6B, REG_OCPD = 0x6B,
REG_UNK6C = 0x6C, REG_OPRI = 0x6C,
REG_SVBK = 0x70, REG_SVBK = 0x70,
REG_UNK72 = 0x72, REG_UNK72 = 0x72,
REG_UNK73 = 0x73, REG_UNK73 = 0x73,

View File

@ -155,7 +155,8 @@ mLOG_DECLARE_CATEGORY(GB_STATE);
* | bit 4: Is HDMA active? * | bit 4: Is HDMA active?
* | bits 5 - 7: Active RTC register * | bits 5 - 7: Active RTC register
* | 0x00196 - 0x00197: Reserved (leave zero) * | 0x00196 - 0x00197: Reserved (leave zero)
* 0x00198 - 0x0025F: Reserved (leave zero) * 0x00198 - 0x0019F: Global cycle counter
* 0x001A0 - 0x0025F: Reserved (leave zero)
* 0x00260 - 0x002FF: OAM * 0x00260 - 0x002FF: OAM
* 0x00300 - 0x0037F: I/O memory * 0x00300 - 0x0037F: I/O memory
* 0x00380 - 0x003FE: HRAM * 0x00380 - 0x003FE: HRAM
@ -388,7 +389,9 @@ struct GBSerializedState {
uint16_t reserved; uint16_t reserved;
} memory; } memory;
uint32_t reserved[50]; uint64_t globalCycles;
uint32_t reserved[48];
uint8_t oam[GB_SIZE_OAM]; uint8_t oam[GB_SIZE_OAM];

View File

@ -161,6 +161,7 @@ void GBVideoInit(struct GBVideo* video);
void GBVideoReset(struct GBVideo* video); void GBVideoReset(struct GBVideo* video);
void GBVideoDeinit(struct GBVideo* video); void GBVideoDeinit(struct GBVideo* video);
void GBVideoAssociateRenderer(struct GBVideo* video, struct GBVideoRenderer* renderer); void GBVideoAssociateRenderer(struct GBVideo* video, struct GBVideoRenderer* renderer);
void GBVideoSkipBIOS(struct GBVideo* video);
void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate); void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate);
void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value); void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value);

View File

@ -193,7 +193,8 @@ mLOG_DECLARE_CATEGORY(GBA_STATE);
* | 0x002F4 - 0x002F7: GBA BIOS bus prefetch * | 0x002F4 - 0x002F7: GBA BIOS bus prefetch
* | 0x002F8 - 0x002FB: CPU prefecth (decode slot) * | 0x002F8 - 0x002FB: CPU prefecth (decode slot)
* | 0x002FC - 0x002FF: CPU prefetch (fetch slot) * | 0x002FC - 0x002FF: CPU prefetch (fetch slot)
* 0x00300 - 0x00317: Reserved (leave zero) * 0x00300 - 0x0030F: Reserved (leave zero)
* 0x00310 - 0x00317: Global cycle counter
* 0x00318 - 0x0031B: Last prefetched program counter * 0x00318 - 0x0031B: Last prefetched program counter
* 0x0031C - 0x0031F: Miscellaneous flags * 0x0031C - 0x0031F: Miscellaneous flags
* | bit 0: Is CPU halted? * | bit 0: Is CPU halted?
@ -326,8 +327,9 @@ struct GBASerializedState {
uint32_t biosPrefetch; uint32_t biosPrefetch;
uint32_t cpuPrefetch[2]; uint32_t cpuPrefetch[2];
uint32_t reservedCpu[6]; uint32_t reservedCpu[4];
uint64_t globalCycles;
uint32_t lastPrefetchedPc; uint32_t lastPrefetchedPc;
GBASerializedMiscFlags miscFlags; GBASerializedMiscFlags miscFlags;
uint32_t nextIrq; uint32_t nextIrq;

View File

@ -6,6 +6,7 @@
#include <mgba/internal/arm/debugger/cli-debugger.h> #include <mgba/internal/arm/debugger/cli-debugger.h>
#include <mgba/core/core.h> #include <mgba/core/core.h>
#include <mgba/core/timing.h>
#include <mgba/internal/arm/debugger/debugger.h> #include <mgba/internal/arm/debugger/debugger.h>
#include <mgba/internal/arm/debugger/memory-debugger.h> #include <mgba/internal/arm/debugger/memory-debugger.h>
#include <mgba/internal/arm/decoder.h> #include <mgba/internal/arm/decoder.h>
@ -138,6 +139,7 @@ static void _printStatus(struct CLIDebuggerSystem* debugger) {
} }
be->printf(be, "cpsr: "); be->printf(be, "cpsr: ");
_printPSR(be, cpu->cpsr); _printPSR(be, cpu->cpsr);
be->printf(be, "Cycle: %" PRIu64 "\n", mTimingGlobalTime(debugger->p->d.core->timing));
int instructionLength; int instructionLength;
enum ExecutionMode mode = cpu->cpsr.t; enum ExecutionMode mode = cpu->cpsr.t;
if (mode == MODE_ARM) { if (mode == MODE_ARM) {

View File

@ -171,7 +171,7 @@ ssize_t ARMDebuggerSetSoftwareBreakpoint(struct mDebuggerPlatform* d, uint32_t a
ssize_t id = debugger->nextId; ssize_t id = debugger->nextId;
++debugger->nextId; ++debugger->nextId;
breakpoint->d.id = id; breakpoint->d.id = id;
breakpoint->d.address = address; breakpoint->d.address = address & ~1; // Clear Thumb bit since it's not part of a valid address
breakpoint->d.segment = -1; breakpoint->d.segment = -1;
breakpoint->d.condition = NULL; breakpoint->d.condition = NULL;
breakpoint->d.type = BREAKPOINT_SOFTWARE; breakpoint->d.type = BREAKPOINT_SOFTWARE;
@ -187,6 +187,7 @@ static ssize_t ARMDebuggerSetBreakpoint(struct mDebuggerPlatform* d, const struc
ssize_t id = debugger->nextId; ssize_t id = debugger->nextId;
++debugger->nextId; ++debugger->nextId;
breakpoint->d = *info; breakpoint->d = *info;
breakpoint->d.address &= ~1; // Clear Thumb bit since it's not part of a valid address
breakpoint->d.id = id; breakpoint->d.id = id;
if (info->type == BREAKPOINT_SOFTWARE) { if (info->type == BREAKPOINT_SOFTWARE) {
// TODO // TODO

View File

@ -157,6 +157,7 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(LSL2,
cpu->gprs[rd] = 0; cpu->gprs[rd] = 0;
} }
} }
++currentCycles;
THUMB_NEUTRAL_S( , , cpu->gprs[rd])) THUMB_NEUTRAL_S( , , cpu->gprs[rd]))
DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(LSR2, DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(LSR2,
@ -174,6 +175,7 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(LSR2,
cpu->gprs[rd] = 0; cpu->gprs[rd] = 0;
} }
} }
++currentCycles;
THUMB_NEUTRAL_S( , , cpu->gprs[rd])) THUMB_NEUTRAL_S( , , cpu->gprs[rd]))
DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ASR2, DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ASR2,
@ -191,6 +193,7 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ASR2,
} }
} }
} }
++currentCycles;
THUMB_NEUTRAL_S( , , cpu->gprs[rd])) THUMB_NEUTRAL_S( , , cpu->gprs[rd]))
DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ADC, DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ADC,
@ -215,6 +218,7 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ROR,
cpu->cpsr.c = ARM_SIGN(cpu->gprs[rd]); cpu->cpsr.c = ARM_SIGN(cpu->gprs[rd]);
} }
} }
++currentCycles;
THUMB_NEUTRAL_S( , , cpu->gprs[rd]);) THUMB_NEUTRAL_S( , , cpu->gprs[rd]);)
DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(TST, int32_t aluOut = cpu->gprs[rd] & cpu->gprs[rn]; THUMB_NEUTRAL_S(cpu->gprs[rd], cpu->gprs[rn], aluOut)) DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(TST, int32_t aluOut = cpu->gprs[rd] & cpu->gprs[rn]; THUMB_NEUTRAL_S(cpu->gprs[rd], cpu->gprs[rn], aluOut))
DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(NEG, THUMB_SUBTRACTION(cpu->gprs[rd], 0, cpu->gprs[rn])) DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(NEG, THUMB_SUBTRACTION(cpu->gprs[rd], 0, cpu->gprs[rn]))

View File

@ -8,6 +8,7 @@
void mTimingInit(struct mTiming* timing, int32_t* relativeCycles, int32_t* nextEvent) { void mTimingInit(struct mTiming* timing, int32_t* relativeCycles, int32_t* nextEvent) {
timing->root = NULL; timing->root = NULL;
timing->reroot = NULL; timing->reroot = NULL;
timing->globalCycles = 0;
timing->masterCycles = 0; timing->masterCycles = 0;
timing->relativeCycles = relativeCycles; timing->relativeCycles = relativeCycles;
timing->nextEvent = nextEvent; timing->nextEvent = nextEvent;
@ -20,6 +21,7 @@ void mTimingDeinit(struct mTiming* timing) {
void mTimingClear(struct mTiming* timing) { void mTimingClear(struct mTiming* timing) {
timing->root = NULL; timing->root = NULL;
timing->reroot = NULL; timing->reroot = NULL;
timing->globalCycles = 0;
timing->masterCycles = 0; timing->masterCycles = 0;
} }
@ -103,6 +105,10 @@ int32_t mTimingCurrentTime(const struct mTiming* timing) {
return timing->masterCycles + *timing->relativeCycles; return timing->masterCycles + *timing->relativeCycles;
} }
uint64_t mTimingGlobalTime(const struct mTiming* timing) {
return timing->globalCycles + *timing->relativeCycles;
}
int32_t mTimingNextEvent(struct mTiming* timing) { int32_t mTimingNextEvent(struct mTiming* timing) {
struct mTimingEvent* next = timing->root; struct mTimingEvent* next = timing->root;
if (!next) { if (!next) {

View File

@ -460,13 +460,13 @@ void GBReset(struct SM83Core* cpu) {
GBVideoReset(&gb->video); GBVideoReset(&gb->video);
GBTimerReset(&gb->timer); GBTimerReset(&gb->timer);
GBIOReset(gb);
if (!gb->biosVf) { if (!gb->biosVf) {
GBSkipBIOS(gb); GBSkipBIOS(gb);
} else { } else {
mTimingSchedule(&gb->timing, &gb->timer.event, 0); mTimingSchedule(&gb->timing, &gb->timer.event, 0);
} }
GBIOReset(gb);
GBAudioReset(&gb->audio); GBAudioReset(&gb->audio);
GBSIOReset(&gb->sio); GBSIOReset(&gb->sio);
@ -478,6 +478,7 @@ void GBReset(struct SM83Core* cpu) {
void GBSkipBIOS(struct GB* gb) { void GBSkipBIOS(struct GB* gb) {
struct SM83Core* cpu = gb->cpu; struct SM83Core* cpu = gb->cpu;
const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
int nextDiv = 0; int nextDiv = 0;
switch (gb->model) { switch (gb->model) {
@ -539,9 +540,15 @@ void GBSkipBIOS(struct GB* gb) {
cpu->a = 0x11; cpu->a = 0x11;
cpu->f.packed = 0x80; cpu->f.packed = 0x80;
cpu->c = 0; cpu->c = 0;
cpu->e = 0x08;
cpu->h = 0; cpu->h = 0;
cpu->l = 0x7C; if (cart->cgb & 0x80) {
cpu->d = 0xFF;
cpu->e = 0x56;
cpu->l = 0x0D;
} else {
cpu->e = 0x08;
cpu->l = 0x7C;
}
gb->timer.internalDiv = 0x1EA; gb->timer.internalDiv = 0x1EA;
nextDiv = 0xC; nextDiv = 0xC;
break; break;
@ -554,6 +561,7 @@ void GBSkipBIOS(struct GB* gb) {
mTimingSchedule(&gb->timing, &gb->timer.event, 0); mTimingSchedule(&gb->timing, &gb->timer.event, 0);
GBIOWrite(gb, REG_LCDC, 0x91); GBIOWrite(gb, REG_LCDC, 0x91);
GBVideoSkipBIOS(&gb->video);
if (gb->biosVf) { if (gb->biosVf) {
GBUnmapBIOS(gb); GBUnmapBIOS(gb);
@ -666,6 +674,9 @@ void GBProcessEvents(struct SM83Core* cpu) {
int32_t nextEvent; int32_t nextEvent;
cpu->cycles = 0; cpu->cycles = 0;
#ifdef USE_DEBUGGERS
gb->timing.globalCycles += cycles;
#endif
cpu->nextEvent = INT_MAX; cpu->nextEvent = INT_MAX;
nextEvent = cycles; nextEvent = cycles;

View File

@ -53,6 +53,7 @@ MGBA_EXPORT const char* const GBIORegisterNames[] = {
[REG_OBP1] = "OBP1", [REG_OBP1] = "OBP1",
[REG_WY] = "WY", [REG_WY] = "WY",
[REG_WX] = "WX", [REG_WX] = "WX",
[REG_KEY0] = "KEY0",
[REG_KEY1] = "KEY1", [REG_KEY1] = "KEY1",
[REG_VBK] = "VBK", [REG_VBK] = "VBK",
[REG_HDMA1] = "HDMA1", [REG_HDMA1] = "HDMA1",
@ -65,6 +66,7 @@ MGBA_EXPORT const char* const GBIORegisterNames[] = {
[REG_BCPD] = "BCPD", [REG_BCPD] = "BCPD",
[REG_OCPS] = "OCPS", [REG_OCPS] = "OCPS",
[REG_OCPD] = "OCPD", [REG_OCPD] = "OCPD",
[REG_OPRI] = "OPRI",
[REG_SVBK] = "SVBK", [REG_SVBK] = "SVBK",
[REG_IE] = "IE", [REG_IE] = "IE",
}; };
@ -99,7 +101,7 @@ static const uint8_t _registerMask[] = {
[REG_VBK] = 0xFE, [REG_VBK] = 0xFE,
[REG_OCPS] = 0x40, [REG_OCPS] = 0x40,
[REG_BCPS] = 0x40, [REG_BCPS] = 0x40,
[REG_UNK6C] = 0xFE, [REG_OPRI] = 0xFE,
[REG_SVBK] = 0xF8, [REG_SVBK] = 0xF8,
[REG_IE] = 0xE0, [REG_IE] = 0xE0,
}; };
@ -200,10 +202,10 @@ void GBIOReset(struct GB* gb) {
GBIOWrite(gb, REG_WY, 0x00); GBIOWrite(gb, REG_WY, 0x00);
GBIOWrite(gb, REG_WX, 0x00); GBIOWrite(gb, REG_WX, 0x00);
if (gb->model & GB_MODEL_CGB) { if (gb->model & GB_MODEL_CGB) {
GBIOWrite(gb, REG_UNK4C, 0); GBIOWrite(gb, REG_KEY0, 0);
GBIOWrite(gb, REG_JOYP, 0xFF); GBIOWrite(gb, REG_JOYP, 0xFF);
GBIOWrite(gb, REG_VBK, 0); GBIOWrite(gb, REG_VBK, 0);
GBIOWrite(gb, REG_BCPS, 0); GBIOWrite(gb, REG_BCPS, 0x80);
GBIOWrite(gb, REG_OCPS, 0); GBIOWrite(gb, REG_OCPS, 0);
GBIOWrite(gb, REG_SVBK, 1); GBIOWrite(gb, REG_SVBK, 1);
GBIOWrite(gb, REG_HDMA1, 0xFF); GBIOWrite(gb, REG_HDMA1, 0xFF);
@ -462,7 +464,7 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
break; break;
} }
GBUnmapBIOS(gb); GBUnmapBIOS(gb);
if (gb->model >= GB_MODEL_CGB && gb->memory.io[REG_UNK4C] < 0x80) { if (gb->model >= GB_MODEL_CGB && gb->memory.io[REG_KEY0] < 0x80) {
gb->model = GB_MODEL_DMG; gb->model = GB_MODEL_DMG;
GBVideoDisableCGB(&gb->video); GBVideoDisableCGB(&gb->video);
} }
@ -474,7 +476,7 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
default: default:
if (gb->model >= GB_MODEL_CGB) { if (gb->model >= GB_MODEL_CGB) {
switch (address) { switch (address) {
case REG_UNK4C: case REG_KEY0:
break; break;
case REG_KEY1: case REG_KEY1:
value &= 0x1; value &= 0x1;

View File

@ -518,7 +518,7 @@ static uint8_t _GBMBC2Read(struct GBMemory* memory, uint16_t address) {
void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) { void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) {
struct GBMemory* memory = &gb->memory; struct GBMemory* memory = &gb->memory;
int bank = value & 0x7F; int bank = value;
switch (address >> 13) { switch (address >> 13) {
case 0x0: case 0x0:
switch (value) { switch (value) {
@ -536,6 +536,9 @@ void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) {
} }
break; break;
case 0x1: case 0x1:
if (gb->memory.romSize < GB_SIZE_CART_BANK0 * 0x80) {
bank &= 0x7F;
}
if (!bank) { if (!bank) {
++bank; ++bank;
} }

View File

@ -23,6 +23,7 @@ void GBSerialize(struct GB* gb, struct GBSerializedState* state) {
STORE_32LE(GB_SAVESTATE_MAGIC + GB_SAVESTATE_VERSION, 0, &state->versionMagic); STORE_32LE(GB_SAVESTATE_MAGIC + GB_SAVESTATE_VERSION, 0, &state->versionMagic);
STORE_32LE(gb->romCrc32, 0, &state->romCrc32); STORE_32LE(gb->romCrc32, 0, &state->romCrc32);
STORE_32LE(gb->timing.masterCycles, 0, &state->masterCycles); STORE_32LE(gb->timing.masterCycles, 0, &state->masterCycles);
STORE_64LE(gb->timing.globalCycles, 0, &state->globalCycles);
if (gb->memory.rom) { if (gb->memory.rom) {
memcpy(state->title, ((struct GBCartridge*) &gb->memory.rom[0x100])->titleLong, sizeof(state->title)); memcpy(state->title, ((struct GBCartridge*) &gb->memory.rom[0x100])->titleLong, sizeof(state->title));
@ -150,6 +151,7 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
} }
mTimingClear(&gb->timing); mTimingClear(&gb->timing);
LOAD_32LE(gb->timing.masterCycles, 0, &state->masterCycles); LOAD_32LE(gb->timing.masterCycles, 0, &state->masterCycles);
LOAD_64LE(gb->timing.globalCycles, 0, &state->globalCycles);
gb->cpu->a = state->cpu.a; gb->cpu->a = state->cpu.a;
gb->cpu->f.packed = state->cpu.f; gb->cpu->f.packed = state->cpu.f;

View File

@ -214,6 +214,30 @@ static bool _statIRQAsserted(GBRegisterSTAT stat) {
return false; return false;
} }
void GBVideoSkipBIOS(struct GBVideo* video) {
video->mode = 1;
video->modeEvent.callback = _endMode1;
int32_t next;
if (video->p->model == GB_MODEL_CGB) {
video->ly = GB_VIDEO_VERTICAL_PIXELS;
video->p->memory.io[REG_LY] = video->ly;
video->stat = GBRegisterSTATClearLYC(video->stat);
next = 20;
} else {
video->ly = GB_VIDEO_VERTICAL_TOTAL_PIXELS;
video->p->memory.io[REG_LY] = 0;
next = 56;
}
video->stat = GBRegisterSTATSetMode(video->stat, video->mode);
video->p->memory.io[REG_IF] |= (1 << GB_IRQ_VBLANK);
GBUpdateIRQs(video->p);
video->p->memory.io[REG_STAT] = video->stat;
mTimingDeschedule(&video->p->timing, &video->modeEvent);
mTimingSchedule(&video->p->timing, &video->modeEvent, next);
}
void _endMode0(struct mTiming* timing, void* context, uint32_t cyclesLate) { void _endMode0(struct mTiming* timing, void* context, uint32_t cyclesLate) {
struct GBVideo* video = context; struct GBVideo* video = context;
if (video->frameskipCounter <= 0) { if (video->frameskipCounter <= 0) {

View File

@ -177,6 +177,9 @@ static void _RegisterRamReset(struct GBA* gba) {
cpu->memory.store16(cpu, BASE_IO | 0x204, 0, 0); cpu->memory.store16(cpu, BASE_IO | 0x204, 0, 0);
cpu->memory.store16(cpu, BASE_IO | 0x208, 0, 0); cpu->memory.store16(cpu, BASE_IO | 0x208, 0, 0);
} }
if (registers & 0x9C) {
gba->video.renderer->reset(gba->video.renderer);
}
} }
static void _BgAffineSet(struct GBA* gba) { static void _BgAffineSet(struct GBA* gba) {

View File

@ -277,12 +277,15 @@ static void GBAProcessEvents(struct ARMCore* cpu) {
do { do {
int32_t cycles = cpu->cycles; int32_t cycles = cpu->cycles;
cpu->cycles = 0; cpu->cycles = 0;
#ifdef USE_DEBUGGERS
gba->timing.globalCycles += cycles;
#endif
#ifndef NDEBUG #ifndef NDEBUG
if (cycles < 0) { if (cycles < 0) {
mLOG(GBA, FATAL, "Negative cycles passed: %i", cycles); mLOG(GBA, FATAL, "Negative cycles passed: %i", cycles);
} }
#endif #endif
nextEvent = mTimingTick(&gba->timing, nextEvent + cycles); nextEvent = mTimingTick(&gba->timing, cycles < nextEvent ? nextEvent : cycles);
} while (gba->cpuBlocked); } while (gba->cpuBlocked);
cpu->nextEvent = nextEvent; cpu->nextEvent = nextEvent;

View File

@ -71,6 +71,13 @@ static const struct GBACartridgeOverride _overrides[] = {
// Koro Koro Puzzle - Happy Panechu! // Koro Koro Puzzle - Happy Panechu!
{ "KHPJ", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE, false }, { "KHPJ", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE, false },
// Legendz - Yomigaeru Shiren no Shima
{ "BLJJ", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false },
{ "BLJK", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false },
// Legendz - Sign of Nekuromu
{ "BLVJ", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false },
// Mega Man Battle Network // Mega Man Battle Network
{ "AREE", SAVEDATA_SRAM, HW_NONE, 0x800032E, false }, { "AREE", SAVEDATA_SRAM, HW_NONE, 0x800032E, false },

View File

@ -1640,10 +1640,6 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
unsigned charBase = (BASE_TILE >> 1) + (GBAObjAttributesCGetTile(sprite->c) & ~align) * 0x10; unsigned charBase = (BASE_TILE >> 1) + (GBAObjAttributesCGetTile(sprite->c) & ~align) * 0x10;
int stride = GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? (width >> 3) : (0x20 >> GBAObjAttributesAGet256Color(sprite->a)); int stride = GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? (width >> 3) : (0x20 >> GBAObjAttributesAGet256Color(sprite->a));
if (spriteY + height >= 256) {
spriteY -= 256;
}
int totalWidth = width; int totalWidth = width;
int totalHeight = height; int totalHeight = height;
if (GBAObjAttributesAIsTransformed(sprite->a) && GBAObjAttributesAIsDoubleSize(sprite->a)) { if (GBAObjAttributesAIsTransformed(sprite->a) && GBAObjAttributesAIsDoubleSize(sprite->a)) {
@ -1651,6 +1647,10 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
totalHeight <<= 1; totalHeight <<= 1;
} }
if (spriteY + totalHeight >= 256) {
spriteY -= 256;
}
const struct GBAVideoGLShader* shader = &renderer->objShader[GBAObjAttributesAGet256Color(sprite->a)]; const struct GBAVideoGLShader* shader = &renderer->objShader[GBAObjAttributesAGet256Color(sprite->a)];
const GLuint* uniforms = shader->uniforms; const GLuint* uniforms = shader->uniforms;
glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_OBJ]); glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_OBJ]);
@ -1710,7 +1710,9 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
glUniform4i(uniforms[GBA_GL_OBJ_MOSAIC], 0, 0, 0, 0); glUniform4i(uniforms[GBA_GL_OBJ_MOSAIC], 0, 0, 0, 0);
} }
glStencilFunc(GL_ALWAYS, 1, 1); glStencilFunc(GL_ALWAYS, 1, 1);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4); if (GBAObjAttributesAGetMode(sprite->a) != OBJ_MODE_OBJWIN || GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt)) {
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
shader = &renderer->objShader[2]; shader = &renderer->objShader[2];
uniforms = shader->uniforms; uniforms = shader->uniforms;

View File

@ -473,8 +473,57 @@
} }
#define DRAW_BACKGROUND_MODE_0_MOSAIC_256EXT(BLEND, OBJWIN) \ #define DRAW_BACKGROUND_MODE_0_MOSAIC_256EXT(BLEND, OBJWIN) \
x = inX & 7; \
if (mosaicWait) { \
int baseX = x - (mosaicH - mosaicWait); \
if (baseX < 0) { \
int disturbX = (16 + baseX) >> 3; \
inX -= disturbX << 3; \
localX = tileX * 8 + inX; \
BACKGROUND_TEXT_SELECT_CHARACTER; \
localY = inY & 0x7; \
if (GBA_TEXT_MAP_VFLIP(mapData)) { \
localY = 7 - localY; \
} \
baseX -= disturbX << 3; \
inX += disturbX << 3; \
} else { \
localX = tileX * 8 + inX; \
BACKGROUND_TEXT_SELECT_CHARACTER; \
localY = inY & 0x7; \
if (GBA_TEXT_MAP_VFLIP(mapData)) { \
localY = 7 - localY; \
} \
} \
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
if (UNLIKELY(charBase >= 0x10000)) { \
carryData = 0; \
} else { \
vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \
LOAD_32(tileData, charBase, vram); \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
if (x >= 4) { \
LOAD_32(tileData, charBase + 4, vram); \
tileData >>= (x - 4) * 8; \
} else { \
LOAD_32(tileData, charBase, vram); \
tileData >>= x * 8; \
} \
} else { \
if (x >= 4) { \
LOAD_32(tileData, charBase, vram); \
tileData >>= (7 - x) * 8; \
} else { \
LOAD_32(tileData, charBase + 4, vram); \
tileData >>= (3 - x) * 8; \
} \
} \
tileData &= 0xFF; \
carryData = tileData; \
} \
} \
localX = tileX * 8 + inX; \ localX = tileX * 8 + inX; \
for (; tileX < tileEnd; ++tileX) { \ for (; length; ++tileX) { \
mapData = background->mapCache[(localX >> 3) & 0x3F]; \ mapData = background->mapCache[(localX >> 3) & 0x3F]; \
localX += 8; \ localX += 8; \
localY = inY & 0x7; \ localY = inY & 0x7; \
@ -484,7 +533,7 @@
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \ vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \
tileData = carryData; \ tileData = carryData; \
for (x = 0; x < 8; ++x) { \ for (x = 0; x < 8 && length; ++x, --length) { \
if (!mosaicWait) { \ if (!mosaicWait) { \
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 8; \ paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 8; \
palette = &mainPalette[paletteData]; \ palette = &mainPalette[paletteData]; \

View File

@ -326,7 +326,7 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
int mosaicH = 1; int mosaicH = 1;
if (GBAObjAttributesAIsMosaic(sprite->a)) { if (GBAObjAttributesAIsMosaic(sprite->a)) {
mosaicH = GBAMosaicControlGetObjH(renderer->mosaic) + 1; mosaicH = GBAMosaicControlGetObjH(renderer->mosaic) + 1;
if (condition % mosaicH) { if (condition != end && condition % mosaicH) {
condition += mosaicH - (condition % mosaicH); condition += mosaicH - (condition % mosaicH);
} }
} }

View File

@ -6,6 +6,7 @@
#include <mgba/internal/gba/serialize.h> #include <mgba/internal/gba/serialize.h>
#include <mgba/internal/arm/macros.h> #include <mgba/internal/arm/macros.h>
#include <mgba/internal/gba/bios.h>
#include <mgba/internal/gba/io.h> #include <mgba/internal/gba/io.h>
#include <mgba-util/memory.h> #include <mgba-util/memory.h>
@ -28,6 +29,7 @@ void GBASerialize(struct GBA* gba, struct GBASerializedState* state) {
STORE_32(gba->biosChecksum, 0, &state->biosChecksum); STORE_32(gba->biosChecksum, 0, &state->biosChecksum);
STORE_32(gba->romCrc32, 0, &state->romCrc32); STORE_32(gba->romCrc32, 0, &state->romCrc32);
STORE_32(gba->timing.masterCycles, 0, &state->masterCycles); STORE_32(gba->timing.masterCycles, 0, &state->masterCycles);
STORE_64LE(gba->timing.globalCycles, 0, &state->globalCycles);
if (gba->memory.rom) { if (gba->memory.rom) {
state->id = ((struct GBACartridge*) gba->memory.rom)->id; state->id = ((struct GBACartridge*) gba->memory.rom)->id;
@ -93,7 +95,7 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
mLOG(GBA_STATE, WARN, "Savestate created using a different version of the BIOS: expected %08X, got %08X", gba->biosChecksum, ucheck); mLOG(GBA_STATE, WARN, "Savestate created using a different version of the BIOS: expected %08X, got %08X", gba->biosChecksum, ucheck);
uint32_t pc; uint32_t pc;
LOAD_32(pc, ARM_PC * sizeof(state->cpu.gprs[0]), state->cpu.gprs); LOAD_32(pc, ARM_PC * sizeof(state->cpu.gprs[0]), state->cpu.gprs);
if (pc < SIZE_BIOS && pc >= 0x20) { if ((ucheck == GBA_BIOS_CHECKSUM || gba->biosChecksum == GBA_BIOS_CHECKSUM) && pc < SIZE_BIOS && pc >= 0x20) {
error = true; error = true;
} }
} }
@ -128,6 +130,7 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
} }
mTimingClear(&gba->timing); mTimingClear(&gba->timing);
LOAD_32(gba->timing.masterCycles, 0, &state->masterCycles); LOAD_32(gba->timing.masterCycles, 0, &state->masterCycles);
LOAD_64LE(gba->timing.globalCycles, 0, &state->globalCycles);
size_t i; size_t i;
for (i = 0; i < 16; ++i) { for (i = 0; i < 16; ++i) {

View File

@ -7,7 +7,7 @@ find_program(BANNERTOOL bannertool)
find_program(MAKEROM makerom) find_program(MAKEROM makerom)
find_program(PICASSO picasso) find_program(PICASSO picasso)
find_program(RAW2C raw2c) find_program(RAW2C raw2c)
find_program(STRIP ${cross_prefix}strip) set(STRIP "${cross_prefix_path}strip" CACHE INTERNAL "symbol stripper")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format" PARENT_SCOPE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format" PARENT_SCOPE)
set(OS_DEFINES COLOR_16_BIT COLOR_5_6_5 IOAPI_NO_64) set(OS_DEFINES COLOR_16_BIT COLOR_5_6_5 IOAPI_NO_64)

View File

@ -1,92 +1,31 @@
/* This code is mostly from ctrulib, which contains the following license: /* Copyright (c) 2013-2020 Jeffrey Pfau
*
This software is provided 'as-is', without any express or implied * This Source Code Form is subject to the terms of the Mozilla Public
warranty. In no event will the authors be held liable for any damages * License, v. 2.0. If a copy of the MPL was not distributed with this
arising from the use of this software. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <3ds/archive.h>
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
* The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in
a product, an acknowledgment in the product documentation would be
appreciated but is not required.
* Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
* This notice may not be removed or altered from any source distribution.
*/
#include <3ds/types.h>
#include <3ds/srv.h>
#include <3ds/gfx.h>
#include <3ds/sdmc.h>
#include <3ds/services/apt.h>
#include <3ds/services/fs.h>
#include <3ds/services/hid.h>
#include <3ds/svc.h>
#include <mgba-util/common.h> #include <mgba-util/common.h>
extern char* fake_heap_start; u32 __ctru_heap_size = 0x02400000;
extern char* fake_heap_end; u32 __ctru_linear_heap_size = 0x01400000;
extern u32 __ctru_linear_heap;
extern u32 __ctru_heap;
extern u32 __ctru_heap_size;
extern u32 __ctru_linear_heap_size;
static u32 __custom_heap_size = 0x02400000;
static u32 __custom_linear_heap_size = 0x01400000;
uint32_t* romBuffer = NULL; uint32_t* romBuffer = NULL;
size_t romBufferSize; size_t romBufferSize;
FS_Archive sdmcArchive; FS_Archive sdmcArchive;
bool allocateRomBuffer(void) { __attribute__((constructor)) static void init(void) {
if (romBuffer) { FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
return true;
}
romBuffer = malloc(0x02000000); romBuffer = malloc(0x02000000);
if (romBuffer) { if (romBuffer) {
romBufferSize = 0x02000000; romBufferSize = 0x02000000;
return true; return;
} }
romBuffer = malloc(0x01000000); romBuffer = malloc(0x01000000);
if (romBuffer) { if (romBuffer) {
romBufferSize = 0x01000000; romBufferSize = 0x01000000;
return true; return;
} }
return false;
}
void __system_allocateHeaps() {
u32 tmp=0;
__ctru_heap_size = __custom_heap_size;
__ctru_linear_heap_size = __custom_linear_heap_size;
// Allocate the application heap
__ctru_heap = 0x08000000;
svcControlMemory(&tmp, __ctru_heap, 0x0, __ctru_heap_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE);
// Allocate the linear heap
svcControlMemory(&__ctru_linear_heap, 0x0, 0x0, __ctru_linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
// Set up newlib heap
fake_heap_start = (char*)__ctru_heap;
fake_heap_end = fake_heap_start + __ctru_heap_size;
}
void __appInit(void) {
// Initialize services
srvInit();
aptInit();
hidInit();
fsInit();
sdmcInit();
FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
allocateRomBuffer();
} }

View File

@ -109,8 +109,6 @@ static bool sgbCrop = false;
static aptHookCookie cookie; static aptHookCookie cookie;
static bool core2; static bool core2;
extern bool allocateRomBuffer(void);
static bool _initGpu(void) { static bool _initGpu(void) {
if (!C3D_Init(C3D_DEFAULT_CMDBUF_SIZE)) { if (!C3D_Init(C3D_DEFAULT_CMDBUF_SIZE)) {
return false; return false;
@ -124,7 +122,7 @@ static bool _initGpu(void) {
return false; return false;
} }
if (!C3D_TexInitVRAM(&upscaleBufferTex, 512, 512, GPU_RB_RGB8)) { if (!C3D_TexInitVRAM(&upscaleBufferTex, 512, 512, GPU_RGB8)) {
return false; return false;
} }
upscaleBuffer = C3D_RenderTargetCreateFromTex(&upscaleBufferTex, GPU_TEXFACE_2D, 0, 0); upscaleBuffer = C3D_RenderTargetCreateFromTex(&upscaleBufferTex, GPU_TEXFACE_2D, 0, 0);
@ -810,10 +808,6 @@ int main() {
camera.bufferSize = 0; camera.bufferSize = 0;
camera.cam = SELECT_IN1; camera.cam = SELECT_IN1;
if (!allocateRomBuffer()) {
return 1;
}
aptHook(&cookie, _aptHook, 0); aptHook(&cookie, _aptHook, 0);
ptmuInit(); ptmuInit();

View File

@ -8,24 +8,27 @@ set(CMAKE_SYSTEM_NAME Generic CACHE INTERNAL "system name")
function(create_devkit DEVKIT) function(create_devkit DEVKIT)
if(DEFINED ENV{DEVKIT${DEVKIT}}) if(DEFINED ENV{DEVKIT${DEVKIT}})
set(DEVKIT${DEVKIT} $ENV{DEVKIT${DEVKIT}} PARENT_SCOPE) set(DEVKIT${DEVKIT} $ENV{DEVKIT${DEVKIT}})
else() else()
set(DEVKIT${DEVKIT} ${DEVKITPRO}/devkit${DEVKIT} PARENT_SCOPE) set(DEVKIT${DEVKIT} ${DEVKITPRO}/devkit${DEVKIT})
endif() endif()
set(DEVKIT${DEVKIT} "${DEVKIT${DEVKIT}}" PARENT_SCOPE)
set(CMAKE_PROGRAM_PATH ${DEVKIT${DEVKIT}}/bin CACHE INTERNAL "program path") set(CMAKE_PROGRAM_PATH "${DEVKIT${DEVKIT}}/bin" CACHE INTERNAL "program path")
set(cross_prefix_path "${CMAKE_PROGRAM_PATH}/${cross_prefix}")
set(cross_prefix_path "${cross_prefix_path}" PARENT_SCOPE)
set(extension) set(extension)
if (CMAKE_HOST_WIN32) if (CMAKE_HOST_WIN32)
set(extension .exe) set(extension .exe)
endif() endif()
find_program(CMAKE_AR ${cross_prefix}gcc-ar${extension}) set(CMAKE_AR "${cross_prefix_path}gcc-ar${extension}" CACHE INTERNAL "archiver")
find_program(CMAKE_RANLIB ${cross_prefix}gcc-ranlib${extension}) set(CMAKE_RANLIB "${cross_prefix_path}gcc-ranlib${extension}" CACHE INTERNAL "archiver")
find_program(CMAKE_C_COMPILER ${cross_prefix}gcc${extension}) set(CMAKE_C_COMPILER "${cross_prefix_path}gcc${extension}" CACHE INTERNAL "c compiler")
find_program(CMAKE_CXX_COMPILER ${cross_prefix}g++${extension}) set(CMAKE_CXX_COMPILER "${cross_prefix_path}g++${extension}" CACHE INTERNAL "cxx compiler")
find_program(CMAKE_ASM_COMPILER ${cross_prefix}gcc${extension}) set(CMAKE_ASM_COMPILER "${cross_prefix_path}gcc${extension}" CACHE INTERNAL "assembler")
find_program(CMAKE_LINKER ${cross_prefix}ld${extension}) set(CMAKE_LINKER "${cross_prefix_path}ld${extension}" CACHE INTERNAL "linker")
set(CMAKE_C_FLAGS ${inc_flags} CACHE INTERNAL "c compiler flags") set(CMAKE_C_FLAGS ${inc_flags} CACHE INTERNAL "c compiler flags")
set(CMAKE_ASM_FLAGS ${inc_flags} CACHE INTERNAL "assembler flags") set(CMAKE_ASM_FLAGS ${inc_flags} CACHE INTERNAL "assembler flags")
set(CMAKE_CXX_FLAGS ${inc_flags} CACHE INTERNAL "cxx compiler flags") set(CMAKE_CXX_FLAGS ${inc_flags} CACHE INTERNAL "cxx compiler flags")
@ -38,4 +41,4 @@ function(create_devkit DEVKIT)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY CACHE INTERNAL "") set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY CACHE INTERNAL "")
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY CACHE INTERNAL "") set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY CACHE INTERNAL "")
set(PKG_CONFIG_EXECUTABLE "/dev/null" CACHE INTERNAL "" FORCE) set(PKG_CONFIG_EXECUTABLE "/dev/null" CACHE INTERNAL "" FORCE)
endfunction() endfunction()

View File

@ -292,7 +292,10 @@ endif()
if(QT_STATIC) if(QT_STATIC)
find_library(QTPCRE NAMES qtpcre2 qtpcre) find_library(QTPCRE NAMES qtpcre2 qtpcre)
if(WIN32) if(WIN32)
list(APPEND QT_LIBRARIES qwindows dwmapi imm32 uxtheme Qt5EventDispatcherSupport Qt5FontDatabaseSupport Qt5ThemeSupport Qt5WindowsUIAutomationSupport) if(CMAKE_CROSSCOMPILING)
set(QWINDOWS_DEPS Qt5EventDispatcherSupport Qt5FontDatabaseSupport Qt5ThemeSupport Qt5WindowsUIAutomationSupport)
endif()
list(APPEND QT_LIBRARIES Qt5::QWindowsIntegrationPlugin ${QWINDOWS_DEPS} dwmapi uxtheme imm32 -static-libgcc -static-libstdc++)
set_target_properties(Qt5::Core PROPERTIES INTERFACE_LINK_LIBRARIES "${QTPCRE};version;winmm;ssl;crypto;ws2_32;iphlpapi;crypt32;userenv;netapi32;wtsapi32") set_target_properties(Qt5::Core PROPERTIES INTERFACE_LINK_LIBRARIES "${QTPCRE};version;winmm;ssl;crypto;ws2_32;iphlpapi;crypt32;userenv;netapi32;wtsapi32")
set_target_properties(Qt5::Gui PROPERTIES INTERFACE_LINK_LIBRARIES ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY}) set_target_properties(Qt5::Gui PROPERTIES INTERFACE_LINK_LIBRARIES ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY})
elseif(APPLE) elseif(APPLE)

File diff suppressed because it is too large Load Diff

View File

@ -58,10 +58,6 @@ struct PerfOpts {
bool server; bool server;
}; };
#ifdef _3DS
extern bool allocateRomBuffer(void);
FS_Archive sdmcArchive;
#endif
#ifdef __SWITCH__ #ifdef __SWITCH__
TimeType __nx_time_type = TimeType_LocalSystemClock; TimeType __nx_time_type = TimeType_LocalSystemClock;
#endif #endif
@ -85,9 +81,6 @@ int main(int argc, char** argv) {
gfxInitDefault(); gfxInitDefault();
osSetSpeedupEnable(true); osSetSpeedupEnable(true);
consoleInit(GFX_BOTTOM, NULL); consoleInit(GFX_BOTTOM, NULL);
if (!allocateRomBuffer()) {
return 1;
}
#elif defined(__SWITCH__) #elif defined(__SWITCH__)
UNUSED(_mPerfShutdown); UNUSED(_mPerfShutdown);
consoleInit(NULL); consoleInit(NULL);

View File

@ -6,6 +6,7 @@
#include <mgba/internal/sm83/debugger/cli-debugger.h> #include <mgba/internal/sm83/debugger/cli-debugger.h>
#include <mgba/core/core.h> #include <mgba/core/core.h>
#include <mgba/core/timing.h>
#include <mgba/internal/debugger/cli-debugger.h> #include <mgba/internal/debugger/cli-debugger.h>
#include <mgba/internal/sm83/decoder.h> #include <mgba/internal/sm83/decoder.h>
#include <mgba/internal/sm83/debugger/debugger.h> #include <mgba/internal/sm83/debugger/debugger.h>
@ -88,6 +89,7 @@ static void _printStatus(struct CLIDebuggerSystem* debugger) {
be->printf(be, "H: %02X L: %02X (HL: %04X)\n", cpu->h, cpu->l, cpu->hl); be->printf(be, "H: %02X L: %02X (HL: %04X)\n", cpu->h, cpu->l, cpu->hl);
be->printf(be, "PC: %04X SP: %04X\n", cpu->pc, cpu->sp); be->printf(be, "PC: %04X SP: %04X\n", cpu->pc, cpu->sp);
_printFlags(be, cpu->f); _printFlags(be, cpu->f);
be->printf(be, "T-cycle: %" PRIu64 "\n", mTimingGlobalTime(debugger->p->d.core->timing));
struct SM83Debugger* platDebugger = (struct SM83Debugger*) debugger->p->d.platform; struct SM83Debugger* platDebugger = (struct SM83Debugger*) debugger->p->d.platform;
size_t i; size_t i;