Merge branch 'master' into medusa
jump to
@@ -1,7 +1,7 @@
#!/bin/sh if [ $TRAVIS_OS_NAME = "osx" ]; then brew update - brew install qt5 ffmpeg sdl2 libedit libelf libpng libzip + brew install qt5 ffmpeg sdl2 libelf libpng libzip else sudo apt-get update sudo apt-get -y install libseccomp2
@@ -19,34 +19,65 @@ - DS Core: Add symbol loading
- DS Video: Simplify VRAM mapping 0.9.0: (Future) +Features: + - Add APNG recording Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation + - GBA BIOS: Implement dummy sound driver calls + - GBA BIOS: Improve HLE BIOS timing - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) + - GBA Memory: Improve gamepak prefetch timing + - GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319) + - GBA Video: Fix Hblank timing +Other fixes: + - Core: Ensure ELF regions can be written before trying + - Core: Fix ELF loading regression (fixes mgba.io/i/1669) + - Debugger: Don't skip undefined instructions when debugger attached + - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) +Misc: + - FFmpeg: Add looping option for GIF/APNG + - Qt: Renderer can be changed while a game is running + - Qt: Add hex index to palette view + - Qt: Add transformation matrix info to sprite view + +0.8.1: (2020-02-16) +Emulation fixes: + - GB Serialize: Fix timing bug loading channel 4 timing + - GBA: Fix multiboot entry point while skipping BIOS + - GBA BIOS: Fix undefined instruction HLE behavior + - GBA DMA: Fix invalid audio DMA parameters - GBA Memory: Misaligned SRAM writes are ignored - - GBA Memory: Improve gamepak prefetch timing - GBA Serialize: Fix serializing DMA transfer register - - GBA Serialize: Fix audio serialization for desynced FIFOs - GBA Serialize: Fix audio DMA timing deserialization - GBA Video: Fix OAM not invalidating after reset (fixes mgba.io/i/1630) - - GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319) - - GBA Video: Fix Hblank timing - GBA Video: Fix backdrop blending on lines without sprites (fixes mgba.io/i/1647) - GBA Video: Fix OpenGL sprite flag priority Other fixes: - Core: Fix race condition initializing thread proxy + - Core: Fix integer overflow in ELF loading + - FFmpeg: Fix crash when -strict -2 is needed for vcodec or container + - FFmpeg: Disallow recording video with no audio nor video + - GBA: Automatically skip BIOS for multiboot ROMs - Qt: Only dynamically reset video scale if a game is running - Qt: Fix race condition with proxied video events - - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) - Qt: Fix color selection in asset view (fixes mgba.io/i/1648) - Qt: Fix missing OSD messages - Qt: Fix crash unloading shaders - Qt: Fix toggled actions on gamepads (fixes mgba.io/i/1650) - Qt: Fix extraneous dialog (fixes mgba.io/i/1654) + - Qt: Fix window title not updating after shutting down game + - Qt: Fix GIF view not allowing manual filename entry + - Qt: Fix non-GB build (fixes mgba.io/i/1664) + - Qt: Fix pausing Qt Multimedia audio (fixes mgba.io/i/1643) + - Qt: Fix invalid names for modifier keys (fixes mgba.io/i/525) + - SDL: Refresh stale pointers after adding a joystick (fixes mgba.io/i/1622) - Util: Fix crash reading invalid ELFs + - VFS: Fix handle leak when double-mapping (fixes mgba.io/i/1659) Misc: - - Qt: Renderer can be changed while a game is running + - FFmpeg: Add more presets - Qt: Fix non-SDL build (fixes mgba.io/i/1656) + - SDL: Use DirectSound audio driver by default on Windows - Switch: Make OpenGL scale adjustable while running 0.8.0: (2020-01-21)
@@ -870,6 +870,9 @@ 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}) install(TARGETS ${BINARY_NAME} LIBRARY DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME} NAMELINK_SKIP ARCHIVE DESTINATION ${LIBDIR} RUNTIME DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME}) + if(BUILD_SHARED) + install(TARGETS ${BINARY_NAME} LIBRARY DESTINATION ${LIBDIR} COMPONENT ${BINARY_NAME}-dev NAMELINK_ONLY) + endif() if(UNIX AND NOT APPLE AND NOT HAIKU) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-16.png DESTINATION share/icons/hicolor/16x16/apps RENAME mgba.png COMPONENT lib${BINARY_NAME}) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-24.png DESTINATION share/icons/hicolor/24x24/apps RENAME mgba.png COMPONENT lib${BINARY_NAME})
@@ -20,15 +20,21 @@
#define SOCKET_FAILED(s) ((s) == INVALID_SOCKET) typedef SOCKET Socket; #else +#ifdef GEKKO +#include <network.h> +#else #include <arpa/inet.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <sys/socket.h> +#endif #include <errno.h> #include <fcntl.h> -#include <netinet/in.h> -#include <netinet/tcp.h> #include <sys/select.h> -#include <sys/socket.h> +#ifndef GEKKO #define INVALID_SOCKET (-1) +#endif #define SOCKET_FAILED(s) ((s) < 0) typedef int Socket; #endif@@ -70,6 +76,8 @@ socInit(SOCUBuffer, SOCU_BUFFERSIZE);
} #elif defined(__SWITCH__) socketInitializeDefault(); +#elif defined(GEKKO) + net_init(); #endif }@@ -82,6 +90,8 @@ free(SOCUBuffer);
SOCUBuffer = NULL; #elif defined(__SWITCH__) socketExit(); +#elif defined(GEKKO) + net_deinit(); #endif }@@ -104,6 +114,8 @@
static inline ssize_t SocketSend(Socket socket, const void* buffer, size_t size) { #ifdef _WIN32 return send(socket, (const char*) buffer, size, 0); +#elif defined(GEKKO) + return net_write(socket, buffer, size); #else return write(socket, buffer, size); #endif@@ -112,6 +124,8 @@
static inline ssize_t SocketRecv(Socket socket, void* buffer, size_t size) { #if defined(_WIN32) || defined(__SWITCH__) return recv(socket, (char*) buffer, size, 0); +#elif defined(GEKKO) + return net_read(socket, buffer, size); #else return read(socket, buffer, size); #endif@@ -120,13 +134,19 @@
static inline int SocketClose(Socket socket) { #ifdef _WIN32 return closesocket(socket) == 0; +#elif defined(GEKKO) + return net_close(socket) >= 0; #else return close(socket) >= 0; #endif } static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress) { +#ifdef GEKKO + Socket sock = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP); +#else Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +#endif if (SOCKET_FAILED(sock)) { return sock; }@@ -142,15 +162,23 @@ bindInfo.sin_addr.s_addr = INADDR_ANY;
#else bindInfo.sin_addr.s_addr = gethostid(); #endif +#ifdef GEKKO + err = net_bind(sock, (struct sockaddr*) &bindInfo, sizeof(bindInfo)); +#else err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); +#endif } else if (bindAddress->version == IPV4) { struct sockaddr_in bindInfo; memset(&bindInfo, 0, sizeof(bindInfo)); bindInfo.sin_family = AF_INET; bindInfo.sin_port = htons(port); bindInfo.sin_addr.s_addr = htonl(bindAddress->ipv4); +#ifdef GEKKO + err = net_bind(sock, (struct sockaddr*) &bindInfo, sizeof(bindInfo)); +#else err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); -#ifndef _3DS +#endif +#if !defined(_3DS) && !defined(GEKKO) } else { struct sockaddr_in6 bindInfo; memset(&bindInfo, 0, sizeof(bindInfo));@@ -168,7 +196,11 @@ return sock;
} static inline Socket SocketConnectTCP(int port, const struct Address* destinationAddress) { +#ifdef GEKKO + Socket sock = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP); +#else Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +#endif if (SOCKET_FAILED(sock)) { return sock; }@@ -179,15 +211,23 @@ struct sockaddr_in bindInfo;
memset(&bindInfo, 0, sizeof(bindInfo)); bindInfo.sin_family = AF_INET; bindInfo.sin_port = htons(port); +#ifdef GEKKO + err = net_connect(sock, (struct sockaddr*) &bindInfo, sizeof(bindInfo)); +#else err = connect(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); +#endif } else if (destinationAddress->version == IPV4) { struct sockaddr_in bindInfo; memset(&bindInfo, 0, sizeof(bindInfo)); bindInfo.sin_family = AF_INET; bindInfo.sin_port = htons(port); bindInfo.sin_addr.s_addr = htonl(destinationAddress->ipv4); +#ifdef GEKKO + err = net_connect(sock, (struct sockaddr*) &bindInfo, sizeof(bindInfo)); +#else err = connect(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); -#ifndef _3DS +#endif +#if !defined(_3DS) && !defined(GEKKO) } else { struct sockaddr_in6 bindInfo; memset(&bindInfo, 0, sizeof(bindInfo));@@ -206,12 +246,23 @@ return sock;
} static inline Socket SocketListen(Socket socket, int queueLength) { +#ifdef GEKKO + return net_listen(socket, queueLength); +#else return listen(socket, queueLength); +#endif } static inline Socket SocketAccept(Socket socket, struct Address* address) { if (!address) { +#ifdef GEKKO + struct sockaddr_in addrInfo; + memset(&addrInfo, 0, sizeof(addrInfo)); + socklen_t len = sizeof(addrInfo); + return net_accept(socket, (struct sockaddr*) &addrInfo, &len); +#else return accept(socket, 0, 0); +#endif } if (address->version == IPV4) { struct sockaddr_in addrInfo;@@ -219,8 +270,12 @@ memset(&addrInfo, 0, sizeof(addrInfo));
addrInfo.sin_family = AF_INET; addrInfo.sin_addr.s_addr = address->ipv4; socklen_t len = sizeof(addrInfo); +#ifdef GEKKO + return net_accept(socket, (struct sockaddr*) &addrInfo, &len); +#else return accept(socket, (struct sockaddr*) &addrInfo, &len); -#ifndef _3DS +#endif +#if !defined(_3DS) && !defined(GEKKO) } else { struct sockaddr_in6 addrInfo; memset(&addrInfo, 0, sizeof(addrInfo));@@ -238,7 +293,11 @@ #ifdef _WIN32
u_long unblocking = !blocking; return ioctlsocket(socket, FIONBIO, &unblocking) == NO_ERROR; #else +#ifdef GEKKO + int flags = net_fcntl(socket, F_GETFL, 0); +#else int flags = fcntl(socket, F_GETFL); +#endif if (flags == -1) { return 0; }@@ -247,12 +306,20 @@ flags &= ~O_NONBLOCK;
} else { flags |= O_NONBLOCK; } +#ifdef GEKKO + return net_fcntl(socket, F_SETFL, flags) >= 0; +#else return fcntl(socket, F_SETFL, flags) >= 0; +#endif #endif } static inline int SocketSetTCPPush(Socket socket, int push) { +#ifdef GEKKO + return net_setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*) &push, sizeof(int)) >= 0; +#else return setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*) &push, sizeof(int)) >= 0; +#endif } static inline int SocketPoll(size_t nSockets, Socket* reads, Socket* writes, Socket* errors, int64_t timeoutMillis) {@@ -304,7 +371,11 @@ ++maxFd;
struct timeval tv; tv.tv_sec = timeoutMillis / 1000; tv.tv_usec = (timeoutMillis % 1000) * 1000; +#ifdef GEKKO + int result = net_select(maxFd, &rset, &wset, &eset, timeoutMillis < 0 ? 0 : &tv); +#else int result = select(maxFd, &rset, &wset, &eset, timeoutMillis < 0 ? 0 : &tv); +#endif int r = 0; int w = 0; int e = 0;
@@ -208,6 +208,7 @@
void mCoreSetRTC(struct mCore* core, struct mRTCSource* rtc); void* mCoreGetMemoryBlock(struct mCore* core, uint32_t start, size_t* size); +void* mCoreGetMemoryBlockMasked(struct mCore* core, uint32_t start, size_t* size, uint32_t mask); #ifdef USE_ELF struct ELF;
@@ -176,6 +176,7 @@ enum mCoreMemoryBlockFlags {
mCORE_MEMORY_READ = 0x01, mCORE_MEMORY_WRITE = 0x02, mCORE_MEMORY_RW = 0x03, + mCORE_MEMORY_WORM = 0x04, mCORE_MEMORY_MAPPED = 0x10, mCORE_MEMORY_VIRTUAL = 0x20, };
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017 Jeffrey Pfau +/* Copyright (c) 2013-2019 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@@ -24,7 +24,6 @@ GB_KEY_LEFT = 5,
GB_KEY_UP = 6, GB_KEY_DOWN = 7, GB_KEY_MAX, - GB_KEY_NONE = -1 }; CXX_GUARD_END
@@ -14,6 +14,52 @@ #include <mgba/core/log.h>
mLOG_DECLARE_CATEGORY(GBA_BIOS); +enum GBASwi { + GBA_SWI_SOFT_RESET = 0x00, + GBA_SWI_REGISTER_RAM_RESET = 0x01, + GBA_SWI_HALT = 0x02, + GBA_SWI_STOP = 0x03, + GBA_SWI_INTR_WAIT = 0x04, + GBA_SWI_VBLANK_INTR_WAIT = 0x05, + GBA_SWI_DIV = 0x06, + GBA_SWI_DIV_ARM = 0x07, + GBA_SWI_SQRT = 0x08, + GBA_SWI_ARCTAN = 0x09, + GBA_SWI_ARCTAN2 = 0x0A, + GBA_SWI_CPU_SET = 0x0B, + GBA_SWI_CPU_FAST_SET = 0x0C, + GBA_SWI_GET_BIOS_CHECKSUM = 0x0D, + GBA_SWI_BG_AFFINE_SET = 0x0E, + GBA_SWI_OBJ_AFFINE_SET = 0x0F, + GBA_SWI_BIT_UNPACK = 0x10, + GBA_SWI_LZ77_UNCOMP_WRAM = 0x11, + GBA_SWI_LZ77_UNCOMP_VRAM = 0x12, + GBA_SWI_HUFFMAN_UNCOMP = 0x13, + GBA_SWI_RL_UNCOMP_WRAM = 0x14, + GBA_SWI_RL_UNCOMP_VRAM = 0x15, + GBA_SWI_DIFF_8BIT_UNFILTER_WRAM = 0x16, + GBA_SWI_DIFF_8BIT_UNFILTER_VRAM = 0x17, + GBA_SWI_DIFF_16BIT_UNFILTER = 0x18, + GBA_SWI_SOUND_BIAS = 0x19, + GBA_SWI_SOUND_DRIVER_INIT = 0x1A, + GBA_SWI_SOUND_DRIVER_MODE = 0x1B, + GBA_SWI_SOUND_DRIVER_MAIN = 0x1C, + GBA_SWI_SOUND_DRIVER_VSYNC = 0x1D, + GBA_SWI_SOUND_CHANNEL_CLEAR = 0x1E, + GBA_SWI_MIDI_KEY_2_FREQ = 0x1F, + GBA_SWI_MUSIC_PLAYER_OPEN = 0x20, + GBA_SWI_MUSIC_PLAYER_START = 0x21, + GBA_SWI_MUSIC_PLAYER_STOP = 0x22, + GBA_SWI_MUSIC_PLAYER_CONTINUE = 0x23, + GBA_SWI_MUSIC_PLAYER_FADE_OUT = 0x24, + GBA_SWI_MULTI_BOOT = 0x25, + GBA_SWI_HARD_RESET = 0x26, + GBA_SWI_CUSTOM_HALT = 0x27, + GBA_SWI_SOUND_DRIVER_VSYNC_OFF = 0x28, + GBA_SWI_SOUND_DRIVER_VSYNC_ON = 0x29, + GBA_SWI_SOUND_DRIVER_GET_JUMP_LIST = 0x2A, +}; + struct ARMCore; void GBASwi16(struct ARMCore* cpu, int immediate); void GBASwi32(struct ARMCore* cpu, int immediate);
@@ -351,11 +351,18 @@ core->rtc.override = RTC_CUSTOM_START;
} void* mCoreGetMemoryBlock(struct mCore* core, uint32_t start, size_t* size) { + return mCoreGetMemoryBlockMasked(core, start, size, mCORE_MEMORY_MAPPED); +} + +void* mCoreGetMemoryBlockMasked(struct mCore* core, uint32_t start, size_t* size, uint32_t mask) { const struct mCoreMemoryBlock* blocks; size_t nBlocks = core->listMemoryBlocks(core, &blocks); size_t i; for (i = 0; i < nBlocks; ++i) { if (!(blocks[i].flags & mCORE_MEMORY_MAPPED)) { + continue; + } + if (!(blocks[i].flags & mask)) { continue; } if (start < blocks[i].start) {@@ -381,9 +388,9 @@ size_t i;
for (i = 0; i < ELFProgramHeadersSize(&ph); ++i) { size_t bsize, esize; Elf32_Phdr* phdr = ELFProgramHeadersGetPointer(&ph, i); - void* block = mCoreGetMemoryBlock(core, phdr->p_paddr, &bsize); + void* block = mCoreGetMemoryBlockMasked(core, phdr->p_paddr, &bsize, mCORE_MEMORY_WRITE | mCORE_MEMORY_WORM); char* bytes = ELFBytes(elf, &esize); - if (block && bsize >= phdr->p_filesz && esize >= phdr->p_filesz + phdr->p_offset) { + if (block && bsize >= phdr->p_filesz && esize > phdr->p_offset && esize >= phdr->p_filesz + phdr->p_offset) { memcpy(block, &bytes[phdr->p_offset], phdr->p_filesz); } else { return false;
@@ -65,6 +65,7 @@ encoder->frameCycles = VIDEO_TOTAL_LENGTH;
encoder->cycles = GBA_ARM7TDMI_FREQUENCY; encoder->frameskip = 1; encoder->skipResidue = 0; + encoder->loop = false; encoder->ipixFormat = #ifdef COLOR_16_BIT #ifdef COLOR_5_6_5@@ -232,11 +233,15 @@ encoder->width = width > 0 ? width : GBA_VIDEO_HORIZONTAL_PIXELS;
encoder->height = height > 0 ? height : GBA_VIDEO_VERTICAL_PIXELS; } +void FFmpegEncoderSetLooping(struct FFmpegEncoder* encoder, bool loop) { + encoder->loop = loop; +} + bool FFmpegEncoderVerifyContainer(struct FFmpegEncoder* encoder) { AVOutputFormat* oformat = av_guess_format(encoder->containerFormat, 0, 0); AVCodec* acodec = avcodec_find_encoder_by_name(encoder->audioCodec); AVCodec* vcodec = avcodec_find_encoder_by_name(encoder->videoCodec); - if ((encoder->audioCodec && !acodec) || (encoder->videoCodec && !vcodec) || !oformat) { + if ((encoder->audioCodec && !acodec) || (encoder->videoCodec && !vcodec) || !oformat || (!acodec && !vcodec)) { return false; } if (encoder->audioCodec && !avformat_query_codec(oformat, acodec->id, FF_COMPLIANCE_EXPERIMENTAL)) {@@ -449,8 +454,11 @@ #else
encoder->sinkFrame = avcodec_alloc_frame(); #endif } - - if (avcodec_open2(encoder->video, vcodec, 0) < 0) { + AVDictionary* opts = 0; + av_dict_set(&opts, "strict", "-2", 0); + int res = avcodec_open2(encoder->video, vcodec, &opts); + av_dict_free(&opts); + if (res < 0) { FFmpegEncoderClose(encoder); return false; }@@ -470,7 +478,17 @@ avcodec_parameters_from_context(encoder->videoStream->codecpar, encoder->video);
#endif } - if (avio_open(&encoder->context->pb, outfile, AVIO_FLAG_WRITE) < 0 || avformat_write_header(encoder->context, 0) < 0) { + if (strcmp(encoder->containerFormat, "gif") == 0) { + av_opt_set(encoder->context->priv_data, "loop", encoder->loop ? "0" : "-1", 0); + } else if (strcmp(encoder->containerFormat, "apng") == 0) { + av_opt_set(encoder->context->priv_data, "plays", encoder->loop ? "0" : "1", 0); + } + + AVDictionary* opts = 0; + av_dict_set(&opts, "strict", "-2", 0); + bool res = avio_open(&encoder->context->pb, outfile, AVIO_FLAG_WRITE) < 0 || avformat_write_header(encoder->context, &opts) < 0; + av_dict_free(&opts); + if (res) { FFmpegEncoderClose(encoder); return false; }
@@ -82,6 +82,7 @@ unsigned frameCycles;
unsigned cycles; int frameskip; int skipResidue; + bool loop; int64_t currentVideoFrame; struct SwsContext* scaleContext; struct AVStream* videoStream;@@ -98,6 +99,7 @@ bool FFmpegEncoderSetAudio(struct FFmpegEncoder*, const char* acodec, unsigned abr);
bool FFmpegEncoderSetVideo(struct FFmpegEncoder*, const char* vcodec, unsigned vbr, int frameskip); bool FFmpegEncoderSetContainer(struct FFmpegEncoder*, const char* container); void FFmpegEncoderSetDimensions(struct FFmpegEncoder*, int width, int height); +void FFmpegEncoderSetLooping(struct FFmpegEncoder*, bool loop); bool FFmpegEncoderVerifyContainer(struct FFmpegEncoder*); bool FFmpegEncoderOpen(struct FFmpegEncoder*, const char* outfile); void FFmpegEncoderClose(struct FFmpegEncoder*);
@@ -1078,9 +1078,13 @@ LOAD_32LE(audio->ch4.lfsr, 0, &state->ch4.lfsr);
LOAD_32LE(audio->ch4.lastEvent, 0, &state->ch4.lastEvent); LOAD_32LE(when, 0, &state->ch4.nextEvent); if (audio->ch4.envelope.dead < 2 && audio->playingCh4) { - if (when - audio->ch4.lastEvent > (uint32_t) audio->sampleInterval) { + if (!audio->ch4.lastEvent) { // Back-compat: fake this value - audio->ch4.lastEvent = when - audio->sampleInterval; + uint32_t currentTime = mTimingCurrentTime(audio->timing); + int32_t cycles = audio->ch4.ratio ? 2 * audio->ch4.ratio : 1; + cycles <<= audio->ch4.frequency; + cycles *= 8 * audio->timingFactor; + audio->ch4.lastEvent = currentTime + (when & (cycles - 1)) - cycles; } mTimingSchedule(audio->timing, &audio->ch4Event, when); }
@@ -45,7 +45,7 @@ };
static const struct mCoreMemoryBlock _GBMemoryBlocks[] = { { -1, "mem", "All", "All", 0, 0x10000, 0x10000, mCORE_MEMORY_VIRTUAL }, - { GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED, 511, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 }, + { GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED, 511, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 }, { GB_REGION_VRAM, "vram", "VRAM", "Video RAM (8kiB)", GB_BASE_VRAM, GB_BASE_VRAM + GB_SIZE_VRAM, GB_SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { GB_REGION_EXTERNAL_RAM, "sram", "SRAM", "External RAM (8kiB)", GB_BASE_EXTERNAL_RAM, GB_BASE_EXTERNAL_RAM + GB_SIZE_EXTERNAL_RAM, GB_SIZE_EXTERNAL_RAM * 4, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 3 }, { GB_REGION_WORKING_RAM_BANK0, "wram", "WRAM", "Working RAM (8kiB)", GB_BASE_WORKING_RAM_BANK0, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 * 2 , GB_SIZE_WORKING_RAM_BANK0 * 2, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },@@ -56,7 +56,7 @@ };
static const struct mCoreMemoryBlock _GBCMemoryBlocks[] = { { -1, "mem", "All", "All", 0, 0x10000, 0x10000, mCORE_MEMORY_VIRTUAL }, - { GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED, 511, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 }, + { GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED, 511, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 }, { GB_REGION_VRAM, "vram", "VRAM", "Video RAM (8kiB)", GB_BASE_VRAM, GB_BASE_VRAM + GB_SIZE_VRAM, GB_SIZE_VRAM * 2, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 1 }, { GB_REGION_EXTERNAL_RAM, "sram", "SRAM", "External RAM (8kiB)", GB_BASE_EXTERNAL_RAM, GB_BASE_EXTERNAL_RAM + GB_SIZE_EXTERNAL_RAM, GB_SIZE_EXTERNAL_RAM * 4, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 3 }, { GB_REGION_WORKING_RAM_BANK0, "wram", "WRAM", "Working RAM (8kiB)", GB_BASE_WORKING_RAM_BANK0, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 * 2, GB_SIZE_WORKING_RAM_BANK0 * 8, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 7, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 },
@@ -16,13 +16,17 @@ static void _GBCLIDebuggerInit(struct CLIDebuggerSystem*);
static bool _GBCLIDebuggerCustom(struct CLIDebuggerSystem*); static void _frame(struct CLIDebugger*, struct CLIDebugVector*); +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 static void _load(struct CLIDebugger*, struct CLIDebugVector*); static void _save(struct CLIDebugger*, struct CLIDebugVector*); +#endif struct CLIDebuggerCommandSummary _GBCLIDebuggerCommands[] = { { "frame", _frame, "", "Frame advance" }, +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 { "load", _load, "*", "Load a savestate" }, { "save", _save, "*", "Save a savestate" }, +#endif { 0, 0, 0, 0 } };@@ -73,6 +77,7 @@ gbDebugger->frameAdvance = true;
gbDebugger->inVblank = GBRegisterSTATGetMode(((struct GB*) gbDebugger->core->board)->memory.io[REG_STAT]) == 1; } +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { struct CLIDebuggerBackend* be = debugger->backend; if (!dv || dv->type != CLIDV_INT_TYPE) {@@ -106,3 +111,4 @@ struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system;
mCoreSaveState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC | SAVESTATE_METADATA); } +#endif
@@ -1,4 +1,5 @@
-/* Copyright (c) 2013-2017 Jeffrey Pfau +/* Copyright (c) 2013-2019 Jeffrey Pfau +>>>>>>> master * * 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@@ -17,7 +18,7 @@ "Start",
"Right", "Left", "Up", - "Down" + "Down", }, .nKeys = GB_KEY_MAX, .hat = {
@@ -104,6 +104,8 @@ mCoreSyncConsumeAudio(audio->p->sync);
} void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info) { + info->reg = GBADMARegisterSetDestControl(info->reg, GBA_DMA_FIXED); + info->reg = GBADMARegisterSetWidth(info->reg, 1); switch (info->dest) { case BASE_IO | REG_FIFO_A_LO: audio->chA.dmaSource = number;@@ -129,8 +131,6 @@ } else {
audio->externalMixing = false; } } - info->reg = GBADMARegisterSetDestControl(info->reg, GBA_DMA_FIXED); - info->reg = GBADMARegisterSetWidth(info->reg, 1); } void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) {
@@ -424,43 +424,43 @@ ARMRaiseSWI(cpu);
return; } switch (immediate) { - case 0x0: + case GBA_SWI_SOFT_RESET: _SoftReset(gba); break; - case 0x1: + case GBA_SWI_REGISTER_RAM_RESET: _RegisterRamReset(gba); break; - case 0x2: - GBAHalt(gba); - break; - case 0x3: + case GBA_SWI_HALT: + ARMRaiseSWI(cpu); + return; + case GBA_SWI_STOP: GBAStop(gba); break; - case 0x05: + case GBA_SWI_VBLANK_INTR_WAIT: // VBlankIntrWait // Fall through: - case 0x04: + case GBA_SWI_INTR_WAIT: // IntrWait ARMRaiseSWI(cpu); - break; - case 0x6: + return; + case GBA_SWI_DIV: _Div(gba, cpu->gprs[0], cpu->gprs[1]); break; - case 0x7: + case GBA_SWI_DIV_ARM: _Div(gba, cpu->gprs[1], cpu->gprs[0]); break; - case 0x8: + case GBA_SWI_SQRT: cpu->gprs[0] = _Sqrt(cpu->gprs[0], &cpu->cycles); break; - case 0x9: + case GBA_SWI_ARCTAN: cpu->gprs[0] = _ArcTan(cpu->gprs[0], &cpu->gprs[1], &cpu->gprs[3], &cpu->cycles); break; - case 0xA: + case GBA_SWI_ARCTAN2: cpu->gprs[0] = (uint16_t) _ArcTan2(cpu->gprs[0], cpu->gprs[1], &cpu->gprs[1], &cpu->cycles); cpu->gprs[3] = 0x170; break; - case 0xB: - case 0xC: + case GBA_SWI_CPU_SET: + case GBA_SWI_CPU_FAST_SET: if (cpu->gprs[0] >> BASE_OFFSET < REGION_WORKING_RAM) { mLOG(GBA_BIOS, GAME_ERROR, "Cannot CpuSet from BIOS"); break;@@ -472,19 +472,19 @@ if (cpu->gprs[1] & (cpu->gprs[2] & (1 << 26) ? 3 : 1)) {
mLOG(GBA_BIOS, GAME_ERROR, "Misaligned CpuSet destination"); } ARMRaiseSWI(cpu); - break; - case 0xD: + return; + case GBA_SWI_GET_BIOS_CHECKSUM: cpu->gprs[0] = GBA_BIOS_CHECKSUM; cpu->gprs[1] = 1; cpu->gprs[3] = SIZE_BIOS; break; - case 0xE: + case GBA_SWI_BG_AFFINE_SET: _BgAffineSet(gba); break; - case 0xF: + case GBA_SWI_OBJ_AFFINE_SET: _ObjAffineSet(gba); break; - case 0x10: + case GBA_SWI_BIT_UNPACK: if (cpu->gprs[0] < BASE_WORKING_RAM) { mLOG(GBA_BIOS, GAME_ERROR, "Bad BitUnPack source"); break;@@ -500,8 +500,8 @@ _unBitPack(gba);
break; } break; - case 0x11: - case 0x12: + case GBA_SWI_LZ77_UNCOMP_WRAM: + case GBA_SWI_LZ77_UNCOMP_VRAM: if (cpu->gprs[0] < BASE_WORKING_RAM) { mLOG(GBA_BIOS, GAME_ERROR, "Bad LZ77 source"); break;@@ -513,11 +513,11 @@ // Fall through
case REGION_WORKING_RAM: case REGION_WORKING_IRAM: case REGION_VRAM: - _unLz77(gba, immediate == 0x11 ? 1 : 2); + _unLz77(gba, immediate == GBA_SWI_LZ77_UNCOMP_WRAM ? 1 : 2); break; } break; - case 0x13: + case GBA_SWI_HUFFMAN_UNCOMP: if (cpu->gprs[0] < BASE_WORKING_RAM) { mLOG(GBA_BIOS, GAME_ERROR, "Bad Huffman source"); break;@@ -533,8 +533,8 @@ _unHuffman(gba);
break; } break; - case 0x14: - case 0x15: + case GBA_SWI_RL_UNCOMP_WRAM: + case GBA_SWI_RL_UNCOMP_VRAM: if (cpu->gprs[0] < BASE_WORKING_RAM) { mLOG(GBA_BIOS, GAME_ERROR, "Bad RL source"); break;@@ -546,13 +546,13 @@ // Fall through
case REGION_WORKING_RAM: case REGION_WORKING_IRAM: case REGION_VRAM: - _unRl(gba, immediate == 0x14 ? 1 : 2); + _unRl(gba, immediate == GBA_SWI_RL_UNCOMP_WRAM ? 1 : 2); break; } break; - case 0x16: - case 0x17: - case 0x18: + case GBA_SWI_DIFF_8BIT_UNFILTER_WRAM: + case GBA_SWI_DIFF_8BIT_UNFILTER_VRAM: + case GBA_SWI_DIFF_16BIT_UNFILTER: if (cpu->gprs[0] < BASE_WORKING_RAM) { mLOG(GBA_BIOS, GAME_ERROR, "Bad UnFilter source"); break;@@ -564,17 +564,20 @@ // Fall through
case REGION_WORKING_RAM: case REGION_WORKING_IRAM: case REGION_VRAM: - _unFilter(gba, immediate == 0x18 ? 2 : 1, immediate == 0x16 ? 1 : 2); + _unFilter(gba, immediate == GBA_SWI_DIFF_16BIT_UNFILTER ? 2 : 1, immediate == GBA_SWI_DIFF_8BIT_UNFILTER_WRAM ? 1 : 2); break; } break; - case 0x19: + case GBA_SWI_SOUND_BIAS: // SoundBias is mostly meaningless here mLOG(GBA_BIOS, STUB, "Stub software interrupt: SoundBias (19)"); break; - case 0x1F: + case GBA_SWI_MIDI_KEY_2_FREQ: _MidiKey2Freq(gba); break; + case GBA_SWI_SOUND_DRIVER_GET_JUMP_LIST: + ARMRaiseSWI(cpu); + return; default: mLOG(GBA_BIOS, STUB, "Stub software interrupt: %02X", immediate); }
@@ -62,9 +62,9 @@ { REGION_IO, "io", "MMIO", "Memory-Mapped I/O", BASE_IO, BASE_IO + SIZE_IO, SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
{ REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, - { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, + { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, }; static const struct mCoreMemoryBlock _GBAMemoryBlocksSRAM[] = {@@ -76,9 +76,9 @@ { REGION_IO, "io", "MMIO", "Memory-Mapped I/O", BASE_IO, BASE_IO + SIZE_IO, SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
{ REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, - { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, + { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, { REGION_CART_SRAM, "sram", "SRAM", "Static RAM (64kiB)", BASE_CART_SRAM, BASE_CART_SRAM + SIZE_CART_SRAM, SIZE_CART_SRAM, true }, };@@ -91,9 +91,9 @@ { REGION_IO, "io", "MMIO", "Memory-Mapped I/O", BASE_IO, BASE_IO + SIZE_IO, SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
{ REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, - { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, + { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, { REGION_CART_SRAM, "sram", "Flash", "Flash Memory (64kiB)", BASE_CART_SRAM, BASE_CART_SRAM + SIZE_CART_FLASH512, SIZE_CART_FLASH512, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, };@@ -106,9 +106,9 @@ { REGION_IO, "io", "MMIO", "Memory-Mapped I/O", BASE_IO, BASE_IO + SIZE_IO, SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
{ REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, - { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, + { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, { REGION_CART_SRAM, "sram", "Flash", "Flash Memory (64kiB)", BASE_CART_SRAM, BASE_CART_SRAM + SIZE_CART_FLASH512, SIZE_CART_FLASH1M, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 1 }, };@@ -121,9 +121,9 @@ { REGION_IO, "io", "MMIO", "Memory-Mapped I/O", BASE_IO, BASE_IO + SIZE_IO, SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
{ REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, - { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, + { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, { REGION_CART_SRAM_MIRROR, "eeprom", "EEPROM", "EEPROM (8kiB)", 0, SIZE_CART_EEPROM, SIZE_CART_EEPROM, mCORE_MEMORY_RW }, };@@ -647,7 +647,7 @@ }
#endif ARMReset(core->cpu); - if (core->opts.skipBios && (gba->romVf || gba->memory.rom)) { + if ((core->opts.skipBios && (gba->romVf || gba->memory.rom)) || (gba->romVf && GBAIsMB(gba->romVf))) { GBASkipBIOS(core->board); } }
@@ -16,13 +16,17 @@ static void _GBACLIDebuggerInit(struct CLIDebuggerSystem*);
static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem*); static void _frame(struct CLIDebugger*, struct CLIDebugVector*); +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 static void _load(struct CLIDebugger*, struct CLIDebugVector*); static void _save(struct CLIDebugger*, struct CLIDebugVector*); +#endif struct CLIDebuggerCommandSummary _GBACLIDebuggerCommands[] = { { "frame", _frame, "", "Frame advance" }, +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 { "load", _load, "*", "Load a savestate" }, { "save", _save, "*", "Save a savestate" }, +#endif { 0, 0, 0, 0 } };@@ -72,6 +76,7 @@ gbaDebugger->frameAdvance = true;
gbaDebugger->inVblank = GBARegisterDISPSTATGetInVblank(((struct GBA*) gbaDebugger->core->board)->memory.io[REG_DISPSTAT >> 1]); } +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { struct CLIDebuggerBackend* be = debugger->backend; if (!dv || dv->type != CLIDV_INT_TYPE) {@@ -107,3 +112,4 @@ struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system;
mCoreSaveState(gbaDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC | SAVESTATE_METADATA); } +#endif
@@ -253,7 +253,7 @@ if (cpu->gprs[ARM_PC] == BASE_RESET + WORD_SIZE_ARM) {
if (gba->memory.rom) { cpu->gprs[ARM_PC] = BASE_CART0; } else { - cpu->gprs[ARM_PC] = BASE_WORKING_RAM; + cpu->gprs[ARM_PC] = BASE_WORKING_RAM + 0xC0; } gba->video.vcount = 0x7D; gba->memory.io[REG_VCOUNT >> 1] = 0x7D;@@ -741,11 +741,9 @@ .address = _ARMPCAddress(cpu),
.type.bp.opcode = opcode }; mDebuggerEnter(gba->debugger->d.p, DEBUGGER_ENTER_ILLEGAL_OP, &info); - } else -#endif - { - ARMRaiseUndefined(cpu); } +#endif + ARMRaiseUndefined(cpu); } void GBABreakpoint(struct ARMCore* cpu, int immediate) {
@@ -3,51 +3,74 @@
#include <mgba/internal/gba/memory.h> const uint8_t hleBios[SIZE_BIOS] = { - 0x06, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x0b, 0x00, 0x00, 0xea, + 0x06, 0x00, 0x00, 0xea, 0x66, 0x00, 0x00, 0xea, 0x0b, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe1, - 0x2c, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0x03, 0xa0, 0xe3, - 0x03, 0x10, 0xd0, 0xe5, 0xea, 0x00, 0x51, 0xe3, 0xf8, 0x01, 0x9f, 0x15, + 0x59, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0x03, 0xa0, 0xe3, + 0x03, 0x10, 0xd0, 0xe5, 0xea, 0x00, 0x51, 0xe3, 0x4c, 0x01, 0x9f, 0x15, 0x10, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1, 0x00, 0x00, 0x5d, 0xe3, 0x01, 0xd3, 0xa0, 0x03, 0x20, 0xd0, 0x4d, 0x02, - 0x00, 0x58, 0x2d, 0xe9, 0x02, 0xb0, 0x5e, 0xe5, 0x9c, 0xc0, 0xa0, 0xe3, + 0x00, 0x58, 0x2d, 0xe9, 0x02, 0xb0, 0x5e, 0xe5, 0xd4, 0xc0, 0xa0, 0xe3, 0x0b, 0xb1, 0x9c, 0xe7, 0x00, 0x00, 0x5b, 0xe3, 0x00, 0xc0, 0x4f, 0xe1, 0x00, 0x10, 0x2d, 0xe9, 0x80, 0xc0, 0x0c, 0xe2, 0x1f, 0xc0, 0x8c, 0xe3, - 0x0c, 0xf0, 0x29, 0xe1, 0x00, 0x40, 0x2d, 0xe9, 0x0f, 0xe0, 0xa0, 0xe1, - 0x1b, 0xff, 0x2f, 0x11, 0x00, 0x40, 0xbd, 0xe8, 0x93, 0xf0, 0x29, 0xe3, - 0x00, 0x10, 0xbd, 0xe8, 0x0c, 0xf0, 0x69, 0xe1, 0x00, 0x58, 0xbd, 0xe8, - 0x0e, 0xf0, 0xb0, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0xa0, 0xe3, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, - 0xd4, 0x01, 0x00, 0x00, 0x0f, 0x50, 0x2d, 0xe9, 0x01, 0x03, 0xa0, 0xe3, + 0x0c, 0xf0, 0x29, 0xe1, 0x00, 0x40, 0x2d, 0xe9, 0x00, 0x00, 0xa0, 0xe1, + 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, + 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, + 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, + 0x0f, 0xe0, 0xa0, 0xe1, 0x1b, 0xff, 0x2f, 0x11, 0x00, 0x00, 0xa0, 0xe1, + 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, + 0x00, 0x40, 0xbd, 0xe8, 0x93, 0xf0, 0x29, 0xe3, 0x00, 0x10, 0xbd, 0xe8, + 0x0c, 0xf0, 0x69, 0xe1, 0x00, 0x58, 0xbd, 0xe8, 0x0e, 0xf0, 0xb0, 0xe1, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0xa0, 0xe3, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb4, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xcc, 0x01, 0x00, 0x00, 0xc4, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0xc0, 0x00, 0x00, 0x02, 0x0f, 0x50, 0x2d, 0xe9, 0x01, 0x03, 0xa0, 0xe3, 0x00, 0xe0, 0x8f, 0xe2, 0x04, 0xf0, 0x10, 0xe5, 0x0f, 0x50, 0xbd, 0xe8, 0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x5e, 0xe5, - 0x01, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3, 0x0c, 0x40, 0x2d, 0xe9, - 0x01, 0xc3, 0xa0, 0xe3, 0x00, 0x00, 0x50, 0xe3, 0x00, 0x00, 0xa0, 0xe3, - 0x01, 0x20, 0xa0, 0xe3, 0x03, 0x00, 0x00, 0x0a, 0xb8, 0x30, 0x5c, 0xe1, - 0x01, 0x30, 0xc3, 0xe1, 0xb8, 0x30, 0x4c, 0xe1, 0x01, 0x03, 0xcc, 0xe5, - 0x08, 0x02, 0xcc, 0xe5, 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0x13, 0xe0, - 0x01, 0x30, 0x23, 0x10, 0xb8, 0x30, 0x4c, 0x11, 0x08, 0x22, 0xcc, 0xe5, - 0xf7, 0xff, 0xff, 0x0a, 0x0c, 0x80, 0xbd, 0xe8, 0x30, 0x40, 0x2d, 0xe9, - 0x02, 0x46, 0xa0, 0xe1, 0x00, 0xc0, 0xa0, 0xe1, 0x01, 0x50, 0xa0, 0xe1, - 0x01, 0x04, 0x12, 0xe3, 0x0f, 0x00, 0x00, 0x0a, 0x01, 0x03, 0x12, 0xe3, - 0x05, 0x00, 0x00, 0x0a, 0x24, 0x45, 0x85, 0xe0, 0x08, 0x00, 0xbc, 0xe8, - 0x04, 0x00, 0x55, 0xe1, 0x08, 0x00, 0xa5, 0xb8, 0xfc, 0xff, 0xff, 0xba, - 0x14, 0x00, 0x00, 0xea, 0x01, 0xc0, 0xcc, 0xe3, 0x01, 0x50, 0xc5, 0xe3, - 0xa4, 0x45, 0x85, 0xe0, 0xb0, 0x30, 0xdc, 0xe1, 0x04, 0x00, 0x55, 0xe1, - 0xb2, 0x30, 0xc5, 0xb0, 0xfc, 0xff, 0xff, 0xba, 0x0c, 0x00, 0x00, 0xea, - 0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a, 0x24, 0x45, 0x85, 0xe0, - 0x04, 0x00, 0x55, 0xe1, 0x08, 0x00, 0xbc, 0xb8, 0x08, 0x00, 0xa5, 0xb8, - 0xfb, 0xff, 0xff, 0xba, 0x04, 0x00, 0x00, 0xea, 0xa4, 0x45, 0x85, 0xe0, - 0x04, 0x00, 0x55, 0xe1, 0xb2, 0x30, 0xdc, 0xb0, 0xb2, 0x30, 0xc5, 0xb0, - 0xfb, 0xff, 0xff, 0xba, 0x17, 0x3e, 0xa0, 0xe3, 0x30, 0x80, 0xbd, 0xe8, - 0xf0, 0x47, 0x2d, 0xe9, 0x01, 0x04, 0x12, 0xe3, 0x02, 0x36, 0xa0, 0xe1, - 0x23, 0x25, 0x81, 0xe0, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x90, 0xe5, - 0x03, 0x40, 0xa0, 0xe1, 0x03, 0x50, 0xa0, 0xe1, 0x03, 0x60, 0xa0, 0xe1, - 0x03, 0x70, 0xa0, 0xe1, 0x03, 0x80, 0xa0, 0xe1, 0x03, 0x90, 0xa0, 0xe1, - 0x03, 0xa0, 0xa0, 0xe1, 0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xa1, 0xb8, - 0xfc, 0xff, 0xff, 0xba, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x51, 0xe1, - 0xf8, 0x07, 0xb0, 0xb8, 0xf8, 0x07, 0xa1, 0xb8, 0xfb, 0xff, 0xff, 0xba, - 0xf0, 0x87, 0xbd, 0xe8, 0xc0, 0x00, 0x00, 0x02 + 0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x04, 0xe0, 0xa0, 0x03, + 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x20, 0xa0, 0xe3, 0x01, 0xc3, 0xa0, 0xe3, + 0x01, 0x23, 0xcc, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0x01, 0x00, 0xa0, 0xe3, + 0x01, 0x10, 0xa0, 0xe3, 0x0c, 0x40, 0x2d, 0xe9, 0x01, 0xc3, 0xa0, 0xe3, + 0x00, 0x00, 0x50, 0xe3, 0x00, 0x00, 0xa0, 0xe3, 0x01, 0x20, 0xa0, 0xe3, + 0x03, 0x00, 0x00, 0x0a, 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0xc3, 0xe1, + 0xb8, 0x30, 0x4c, 0xe1, 0x01, 0x03, 0xcc, 0xe5, 0x08, 0x02, 0xcc, 0xe5, + 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0x13, 0xe0, 0x01, 0x30, 0x23, 0x10, + 0xb8, 0x30, 0x4c, 0x11, 0x08, 0x22, 0xcc, 0xe5, 0xf7, 0xff, 0xff, 0x0a, + 0x0c, 0x80, 0xbd, 0xe8, 0x30, 0x40, 0x2d, 0xe9, 0x02, 0x46, 0xa0, 0xe1, + 0x00, 0xc0, 0xa0, 0xe1, 0x01, 0x50, 0xa0, 0xe1, 0x01, 0x04, 0x12, 0xe3, + 0x0f, 0x00, 0x00, 0x0a, 0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a, + 0x24, 0x45, 0x85, 0xe0, 0x08, 0x00, 0xbc, 0xe8, 0x04, 0x00, 0x55, 0xe1, + 0x08, 0x00, 0xa5, 0xb8, 0xfc, 0xff, 0xff, 0xba, 0x14, 0x00, 0x00, 0xea, + 0x01, 0xc0, 0xcc, 0xe3, 0x01, 0x50, 0xc5, 0xe3, 0xa4, 0x45, 0x85, 0xe0, + 0xb0, 0x30, 0xdc, 0xe1, 0x04, 0x00, 0x55, 0xe1, 0xb2, 0x30, 0xc5, 0xb0, + 0xfc, 0xff, 0xff, 0xba, 0x0c, 0x00, 0x00, 0xea, 0x01, 0x03, 0x12, 0xe3, + 0x05, 0x00, 0x00, 0x0a, 0x24, 0x45, 0x85, 0xe0, 0x04, 0x00, 0x55, 0xe1, + 0x08, 0x00, 0xbc, 0xb8, 0x08, 0x00, 0xa5, 0xb8, 0xfb, 0xff, 0xff, 0xba, + 0x04, 0x00, 0x00, 0xea, 0xa4, 0x45, 0x85, 0xe0, 0x04, 0x00, 0x55, 0xe1, + 0xb2, 0x30, 0xdc, 0xb0, 0xb2, 0x30, 0xc5, 0xb0, 0xfb, 0xff, 0xff, 0xba, + 0x17, 0x3e, 0xa0, 0xe3, 0x30, 0x80, 0xbd, 0xe8, 0xf0, 0x47, 0x2d, 0xe9, + 0x01, 0x04, 0x12, 0xe3, 0x02, 0x36, 0xa0, 0xe1, 0x23, 0x25, 0x81, 0xe0, + 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x90, 0xe5, 0x03, 0x40, 0xa0, 0xe1, + 0x03, 0x50, 0xa0, 0xe1, 0x03, 0x60, 0xa0, 0xe1, 0x03, 0x70, 0xa0, 0xe1, + 0x03, 0x80, 0xa0, 0xe1, 0x03, 0x90, 0xa0, 0xe1, 0x03, 0xa0, 0xa0, 0xe1, + 0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xa1, 0xb8, 0xfc, 0xff, 0xff, 0xba, + 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xb0, 0xb8, + 0xf8, 0x07, 0xa1, 0xb8, 0xfb, 0xff, 0xff, 0xba, 0xf0, 0x87, 0xbd, 0xe8, + 0xf0, 0x07, 0x2d, 0xe9, 0x38, 0x10, 0x9f, 0xe5, 0x01, 0x30, 0xa0, 0xe1, + 0x01, 0x40, 0xa0, 0xe1, 0x01, 0x50, 0xa0, 0xe1, 0x01, 0x60, 0xa0, 0xe1, + 0x01, 0x70, 0xa0, 0xe1, 0x01, 0x80, 0xa0, 0xe1, 0x01, 0x90, 0xa0, 0xe1, + 0x01, 0xa0, 0xa0, 0xe1, 0xfa, 0x07, 0xa0, 0xe8, 0xfa, 0x07, 0xa0, 0xe8, + 0xfa, 0x07, 0xa0, 0xe8, 0xfa, 0x07, 0xa0, 0xe8, 0x00, 0x10, 0xa0, 0xe3, + 0xf0, 0x07, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0xb0, 0x01, 0x00, 0x00 };
@@ -40,8 +40,22 @@ and r12, #0x80
orr r12, #0x1F msr cpsr, r12 stmfd sp!, {lr} +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop mov lr, pc bxne r11 +nop +nop +nop +nop ldmfd sp!, {lr} msr cpsr, #0x93 ldmfd sp!, {r12}@@ -52,20 +66,51 @@ .word 0
.word 0xE3A02004 swiTable: -.word SoftReset -.word RegisterRamReset -.word Halt -.word Stop -.word IntrWait -.word VBlankIntrWait -.word Div -.word DivArm -.word Sqrt -.word ArcTan -.word ArcTan2 -.word CpuSet -.word CpuFastSet -@ ... The rest of this table isn't needed if the rest aren't implemented +.word SoftReset @ 0x00 +.word RegisterRamReset @ 0x01 +.word Halt @ 0x02 +.word Stop @ 0x03 +.word IntrWait @ 0x04 +.word VBlankIntrWait @ 0x05 +.word Div @ 0x06 +.word DivArm @ 0x07 +.word Sqrt @ 0x08 +.word ArcTan @ 0x09 +.word ArcTan2 @ 0x0A +.word CpuSet @ 0x0B +.word CpuFastSet @ 0x0C +.word GetBiosChecksum @ 0x0D +.word BgAffineSet @ 0x0E +.word ObjAffineSet @ 0x0F +.word BitUnPack @ 0x10 +.word Lz77UnCompWram @ 0x11 +.word Lz77UnCompVram @ 0x12 +.word HuffmanUnComp @ 0x13 +.word RlUnCompWram @ 0x14 +.word RlUnCompVram @ 0x15 +.word Diff8BitUnFilterWram @ 0x16 +.word Diff8BitUnFilterVram @ 0x17 +.word Diff16BitUnFilter @ 0x18 +.word SoundBias @ 0x19 +.word SoundDriverInit @ 0x1A +.word SoundDriverMode @ 0x1B +.word SoundDriverMain @ 0x1C +.word SoundDriverVsync @ 0x1D +.word SoundChannelClear @ 0x1E +.word MidiKey2Freq @ 0x1F +.word MusicPlayerOpen @ 0x20 +.word MusicPlayerStart @ 0x21 +.word MusicPlayerStop @ 0x22 +.word MusicPlayerContinue @ 0x23 +.word MusicPlayerFadeOut @ 0x24 +.word MultiBoot @ 0x25 +.word HardReset @ 0x26 +.word CustomHalt @ 0x27 +.word SoundDriverVsyncOff @ 0x28 +.word SoundDriverVsyncOn @ 0x29 +.word SoundDriverGetJumpList @ 0x2A + +.ltorg irqBase: stmfd sp!, {r0-r3, r12, lr}@@ -77,6 +122,59 @@ subs pc, lr, #4
.word 0 .word 0xE55EC002 +undefBase: +subs pc, lr, #4 +.word 0 +.word 0x03A0E004 + +@ Unimplemented +SoftReset: +RegisterRamReset: +Stop: +Div: +DivArm: +Sqrt: +ArcTan: +ArcTan2: +GetBiosChecksum: +BgAffineSet: +ObjAffineSet: +BitUnPack: +Lz77UnCompWram: +Lz77UnCompVram: +HuffmanUnComp: +RlUnCompWram: +RlUnCompVram: +Diff8BitUnFilterWram: +Diff8BitUnFilterVram: +Diff16BitUnFilter: +SoundBias: +SoundDriverInit: +SoundDriverMode: +SoundDriverMain: +SoundDriverVsync: +SoundChannelClear: +MidiKey2Freq: +MusicPlayerOpen: +MusicPlayerStart: +MusicPlayerStop: +MusicPlayerContinue: +MusicPlayerFadeOut: +MultiBoot: +HardReset: +CustomHalt: +SoundDriverVsyncOff: +SoundDriverVsyncOn: + +NopCall: +bx lr + +Halt: +mov r2, #0 +mov r12, #0x04000000 +strb r2, [r12, #0x301] +bx lr + VBlankIntrWait: mov r0, #1 mov r1, #1@@ -186,5 +284,24 @@ stmltia r1!, {r3-r10}
blt 0b 2: ldmfd sp!, {r4-r10, pc} + +SoundDriverGetJumpList: +stmfd sp!, {r4-r10} +ldr r1, =NopCall +mov r3, r1 +mov r4, r1 +mov r5, r1 +mov r6, r1 +mov r7, r1 +mov r8, r1 +mov r9, r1 +mov r10, r1 +stmia r0!, {r1, r3-r10} +stmia r0!, {r1, r3-r10} +stmia r0!, {r1, r3-r10} +stmia r0!, {r1, r3-r10} +mov r1, #0 +ldmfd sp!, {r4-r10} +bx lr .ltorg
@@ -369,6 +369,7 @@ video->event.callback = _startHdraw;
} else { video->event.callback = _startHblank; } + break; case 1: video->event.callback = _startHdraw; break;
@@ -25,10 +25,11 @@ connect(m_ui.stop, &QAbstractButton::clicked, this, &GIFView::stopRecording);
connect(m_ui.selectFile, &QAbstractButton::clicked, this, &GIFView::selectFile); connect(m_ui.filename, &QLineEdit::textChanged, this, &GIFView::setFilename); + connect(m_ui.fmtGif, &QAbstractButton::clicked, this, &GIFView::changeExtension); + connect(m_ui.fmtApng, &QAbstractButton::clicked, this, &GIFView::changeExtension); FFmpegEncoderInit(&m_encoder); FFmpegEncoderSetAudio(&m_encoder, nullptr, 0); - FFmpegEncoderSetContainer(&m_encoder, "gif"); } GIFView::~GIFView() {@@ -44,14 +45,24 @@ FFmpegEncoderSetDimensions(&m_encoder, size.width(), size.height());
} void GIFView::startRecording() { - FFmpegEncoderSetVideo(&m_encoder, "gif", 0, m_ui.frameskip->value()); + if (m_ui.fmtApng->isChecked()) { + FFmpegEncoderSetContainer(&m_encoder, "apng"); + FFmpegEncoderSetVideo(&m_encoder, "apng", 0, m_ui.frameskip->value()); + } else { + FFmpegEncoderSetContainer(&m_encoder, "gif"); + FFmpegEncoderSetVideo(&m_encoder, "gif", 0, m_ui.frameskip->value()); + } + FFmpegEncoderSetLooping(&m_encoder, m_ui.loop->isChecked()); if (!FFmpegEncoderOpen(&m_encoder, m_filename.toUtf8().constData())) { - LOG(QT, ERROR) << tr("Failed to open output GIF file: %1").arg(m_filename); + LOG(QT, ERROR) << tr("Failed to open output GIF or APNG file: %1").arg(m_filename); return; } m_ui.start->setEnabled(false); m_ui.stop->setEnabled(true); m_ui.frameskip->setEnabled(false); + m_ui.loop->setEnabled(false); + m_ui.fmtApng->setEnabled(false); + m_ui.fmtGif->setEnabled(false); emit recordingStarted(&m_encoder.d); }@@ -59,22 +70,45 @@ void GIFView::stopRecording() {
emit recordingStopped(); FFmpegEncoderClose(&m_encoder); m_ui.stop->setEnabled(false); - m_ui.start->setEnabled(true); + m_ui.start->setEnabled(!m_filename.isEmpty()); m_ui.frameskip->setEnabled(true); + m_ui.loop->setEnabled(true); + m_ui.fmtApng->setEnabled(true); + m_ui.fmtGif->setEnabled(true); } void GIFView::selectFile() { - QString filename = GBAApp::app()->getSaveFileName(this, tr("Select output file"), tr("Graphics Interchange Format (*.gif)")); - if (!filename.isEmpty()) { - m_ui.filename->setText(filename); - if (!FFmpegEncoderIsOpen(&m_encoder)) { - m_ui.start->setEnabled(true); + QString filename = GBAApp::app()->getSaveFileName(this, tr("Select output file"), tr("Graphics Interchange Format (*.gif);;Animated Portable Network Graphics (*.png *.apng)")); + m_ui.filename->setText(filename); +} + +void GIFView::setFilename(const QString& filename) { + m_filename = filename; + if (!FFmpegEncoderIsOpen(&m_encoder)) { + m_ui.start->setEnabled(!filename.isEmpty()); + if (filename.endsWith(".gif")) { + m_ui.fmtGif->setChecked(Qt::Checked); + } else if (filename.endsWith(".png") || filename.endsWith(".apng")) { + m_ui.fmtApng->setChecked(Qt::Checked); } } } -void GIFView::setFilename(const QString& fname) { - m_filename = fname; +void GIFView::changeExtension() { + if (m_filename.isEmpty()) { + return; + } + QString filename = m_filename; + int index = m_filename.lastIndexOf("."); + if (index >= 0) { + filename.truncate(index); + } + if (m_ui.fmtGif->isChecked()) { + filename += ".gif"; + } else if (m_ui.fmtApng->isChecked()) { + filename += ".png"; + } + m_ui.filename->setText(filename); } #endif
@@ -41,6 +41,7 @@
private slots: void selectFile(); void setFilename(const QString&); + void changeExtension(); private: Ui::GIFView m_ui;
@@ -7,47 +7,39 @@ <rect>
<x>0</x> <y>0</y> <width>392</width> - <height>220</height> + <height>262</height> </rect> </property> <property name="windowTitle"> - <string>Record GIF</string> + <string>Record GIF/APNG</string> </property> <layout class="QGridLayout" name="gridLayout_3"> <property name="sizeConstraint"> <enum>QLayout::SetFixedSize</enum> </property> - <item row="1" column="0"> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="1"> - <widget class="QLabel" name="label"> + <item row="2" column="0"> + <widget class="QRadioButton" name="fmtApng"> <property name="text"> - <string>Frameskip</string> + <string>APNG</string> </property> + <attribute name="buttonGroup"> + <string notr="true">format</string> + </attribute> </widget> </item> - <item row="1" column="2"> + <item row="2" column="2"> <widget class="QSpinBox" name="frameskip"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>9</number> + </property> <property name="value"> <number>2</number> - </property> - </widget> - </item> - <item row="2" column="0" colspan="3"> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="standardButtons"> - <set>QDialogButtonBox::Close</set> </property> </widget> </item>@@ -123,8 +115,55 @@ </widget>
</item> </layout> </item> + <item row="2" column="1"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Frameskip</string> + </property> + </widget> + </item> + <item row="3" column="0" colspan="3"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QRadioButton" name="fmtGif"> + <property name="text"> + <string>GIF</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <attribute name="buttonGroup"> + <string notr="true">format</string> + </attribute> + </widget> + </item> + <item row="1" column="1" colspan="2"> + <widget class="QCheckBox" name="loop"> + <property name="text"> + <string>Loop</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> </layout> </widget> + <tabstops> + <tabstop>filename</tabstop> + <tabstop>start</tabstop> + <tabstop>stop</tabstop> + <tabstop>selectFile</tabstop> + <tabstop>fmtGif</tabstop> + <tabstop>fmtApng</tabstop> + <tabstop>loop</tabstop> + <tabstop>frameskip</tabstop> + </tabstops> <resources/> <connections> <connection>@@ -144,4 +183,7 @@ </hint>
</hints> </connection> </connections> + <buttongroups> + <buttongroup name="format"/> + </buttongroups> </ui>
@@ -9,6 +9,7 @@ #include "GamepadAxisEvent.h"
#include "GamepadButtonEvent.h" #include "InputIndex.h" +#include <QCoreApplication> #include <QFontMetrics> #include <QKeyEvent>@@ -32,7 +33,35 @@ } else {
if (key < 0) { setText(tr("---")); } else { - setText(QKeySequence(key).toString(QKeySequence::NativeText)); + QKeySequence seq(key); + switch (key) { +#ifndef Q_OS_MAC + case Qt::Key_Shift: + setText(QCoreApplication::translate("QShortcut", "Shift")); + break; + case Qt::Key_Control: + setText(QCoreApplication::translate("QShortcut", "Control")); + break; + case Qt::Key_Alt: + setText(QCoreApplication::translate("QShortcut", "Alt")); + break; + case Qt::Key_Meta: + setText(QCoreApplication::translate("QShortcut", "Meta")); + break; +#endif + case Qt::Key_Super_L: + setText(tr("Super (L)")); + break; + case Qt::Key_Super_R: + setText(tr("Super (R)")); + break; + case Qt::Key_Menu: + setText(tr("Menu")); + break; + default: + setText(QKeySequence(key).toString(QKeySequence::NativeText)); + break; + } } } emit valueChanged(key);
@@ -16,11 +16,13 @@ #endif
using namespace QGBA; +#ifdef M_CORE_GB MultiplayerController::Player::Player(CoreController* coreController, GBSIOLockstepNode* node) : controller(coreController) , gbNode(node) { } +#endif #ifdef M_CORE_GBA MultiplayerController::Player::Player(CoreController* coreController, GBASIOLockstepNode* node)
@@ -44,6 +44,10 @@ m_ui.address->setFont(font);
m_ui.priority->setFont(font); m_ui.palette->setFont(font); m_ui.transform->setFont(font); + m_ui.xformPA->setFont(font); + m_ui.xformPB->setFont(font); + m_ui.xformPC->setFont(font); + m_ui.xformPD->setFont(font); m_ui.mode->setFont(font); connect(m_ui.tiles, &TilePainter::indexPressed, this, &ObjView::translateIndex);@@ -157,9 +161,23 @@ m_ui.doubleSize->setChecked(GBAObjAttributesAIsDoubleSize(obj->a) && GBAObjAttributesAIsTransformed(obj->a));
m_ui.mosaic->setChecked(GBAObjAttributesAIsMosaic(obj->a)); if (GBAObjAttributesAIsTransformed(obj->a)) { - m_ui.transform->setText(QString::number(GBAObjAttributesBGetMatIndex(obj->b))); + int mtxId = GBAObjAttributesBGetMatIndex(obj->b); + struct GBAOAMMatrix mat; + LOAD_16LE(mat.a, 0, &gba->video.oam.mat[mtxId].a); + LOAD_16LE(mat.b, 0, &gba->video.oam.mat[mtxId].b); + LOAD_16LE(mat.c, 0, &gba->video.oam.mat[mtxId].c); + LOAD_16LE(mat.d, 0, &gba->video.oam.mat[mtxId].d); + m_ui.transform->setText(QString::number(mtxId)); + m_ui.xformPA->setText(QString("%0").arg(mat.a / 256., 5, 'f', 2)); + m_ui.xformPB->setText(QString("%0").arg(mat.b / 256., 5, 'f', 2)); + m_ui.xformPC->setText(QString("%0").arg(mat.c / 256., 5, 'f', 2)); + m_ui.xformPD->setText(QString("%0").arg(mat.d / 256., 5, 'f', 2)); } else { m_ui.transform->setText(tr("Off")); + m_ui.xformPA->setText(tr("---")); + m_ui.xformPB->setText(tr("---")); + m_ui.xformPC->setText(tr("---")); + m_ui.xformPD->setText(tr("---")); } switch (GBAObjAttributesAGetMode(obj->a)) {@@ -230,6 +248,10 @@ m_ui.enabled->setChecked(newInfo.enabled);
m_ui.doubleSize->setChecked(false); m_ui.mosaic->setChecked(false); m_ui.transform->setText(tr("N/A")); + m_ui.xformPA->setText(tr("---")); + m_ui.xformPB->setText(tr("---")); + m_ui.xformPC->setText(tr("---")); + m_ui.xformPD->setText(tr("---")); m_ui.mode->setText(tr("N/A")); } #endif
@@ -13,7 +13,81 @@ </property>
<property name="windowTitle"> <string>Sprites</string> </property> - <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,1" columnstretch="0,0,1,1"> + <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,0" columnstretch="0,0,0,1"> + <item row="0" column="2" rowspan="4" colspan="2"> + <widget class="QFrame" name="frame"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item row="0" column="0" alignment="Qt::AlignHCenter|Qt::AlignVCenter"> + <widget class="QGBA::TilePainter" name="tiles" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>8</width> + <height>8</height> + </size> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="0" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QSpinBox" name="objId"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>127</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Address</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="address"> + <property name="text"> + <string>0x07000000</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + </layout> + </item> <item row="4" column="3"> <widget class="QPushButton" name="copyButton"> <property name="text">@@ -21,13 +95,49 @@ <string>Copy</string>
</property> </widget> </item> + <item row="1" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QSpinBox" name="magnification"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="suffix"> + <string>×</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>8</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Magnification</string> + </property> + </widget> + </item> + </layout> + </item> <item row="2" column="0"> <widget class="QGroupBox" name="groupBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="title"> <string>Geometry</string> </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QLabel" name="label">@@ -93,7 +203,14 @@ </widget>
</item> </layout> </item> - <item> + <item row="0" column="1" rowspan="2"> + <widget class="Line" name="line_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + </widget> + </item> + <item row="1" column="0"> <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> <widget class="QLabel" name="label_4">@@ -159,50 +276,86 @@ </widget>
</item> </layout> </item> + <item row="0" column="2" rowspan="2"> + <layout class="QGridLayout" name="gridLayout_5"> + <item row="0" column="3"> + <widget class="QLabel" name="xformPC"> + <property name="text"> + <string>+0.00</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="xformPA"> + <property name="text"> + <string>+1.00</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_10"> + <property name="text"> + <string>Matrix</string> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QLabel" name="xformPD"> + <property name="text"> + <string>+1.00</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <spacer name="horizontalSpacer_8"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="2"> + <widget class="QLabel" name="xformPB"> + <property name="text"> + <string>+0.00</string> + </property> + </widget> + </item> + </layout> + </item> </layout> </widget> </item> - <item row="0" column="2" rowspan="4" colspan="2"> - <widget class="QFrame" name="frame"> - <property name="frameShape"> - <enum>QFrame::StyledPanel</enum> + <item row="5" column="0" colspan="4"> + <widget class="QListWidget" name="objList"> + <property name="iconSize"> + <size> + <width>64</width> + <height>64</height> + </size> </property> - <layout class="QGridLayout" name="gridLayout_2"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item row="0" column="0" alignment="Qt::AlignHCenter|Qt::AlignVCenter"> - <widget class="QGBA::TilePainter" name="tiles" native="true"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>8</width> - <height>8</height> - </size> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="0" column="1" rowspan="5"> - <widget class="QGBA::AssetTile" name="tile"> - <property name="title"> - <string>Tile</string> + <property name="flow"> + <enum>QListView::LeftToRight</enum> + </property> + <property name="resizeMode"> + <enum>QListView::Adjust</enum> + </property> + <property name="gridSize"> + <size> + <width>64</width> + <height>96</height> + </size> + </property> + <property name="viewMode"> + <enum>QListView::IconMode</enum> + </property> + <property name="uniformItemSizes"> + <bool>true</bool> </property> </widget> </item>@@ -215,6 +368,12 @@ </widget>
</item> <item row="3" column="0" rowspan="2"> <widget class="QGroupBox" name="groupBox_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="title"> <string>Attributes</string> </property>@@ -517,98 +676,10 @@ </item>
</layout> </widget> </item> - <item row="0" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QSpinBox" name="objId"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximum"> - <number>127</number> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Address</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="address"> - <property name="text"> - <string>0x07000000</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - </layout> - </item> - <item row="1" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="QSpinBox" name="magnification"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="suffix"> - <string>×</string> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>8</number> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Magnification</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="5" column="0" colspan="4"> - <widget class="QListWidget" name="objList"> - <property name="iconSize"> - <size> - <width>64</width> - <height>64</height> - </size> - </property> - <property name="flow"> - <enum>QListView::LeftToRight</enum> - </property> - <property name="resizeMode"> - <enum>QListView::Adjust</enum> - </property> - <property name="gridSize"> - <size> - <width>64</width> - <height>96</height> - </size> - </property> - <property name="viewMode"> - <enum>QListView::IconMode</enum> - </property> - <property name="uniformItemSizes"> - <bool>true</bool> + <item row="0" column="1" rowspan="5"> + <widget class="QGBA::AssetTile" name="tile"> + <property name="title"> + <string>Tile</string> </property> </widget> </item>
@@ -120,7 +120,7 @@ uint32_t hexcode = (r << 19) | (g << 11) | (b << 3);
hexcode |= (hexcode >> 5) & 0x070707; m_ui.hexcode->setText(tr("#%0").arg(hexcode, 6, 16, QChar('0'))); m_ui.value->setText(tr("0x%0").arg(color, 4, 16, QChar('0'))); - m_ui.index->setText(tr("%0").arg(index, 3, 10, QChar('0'))); + m_ui.index->setText(tr("0x%0 (%1)").arg(index, 3, 16, QChar('0')).arg(index, 3, 10, QChar('0'))); m_ui.r->setText(tr("0x%0 (%1)").arg(r, 2, 16, QChar('0')).arg(r, 2, 10, QChar('0'))); m_ui.g->setText(tr("0x%0 (%1)").arg(g, 2, 16, QChar('0')).arg(g, 2, 10, QChar('0'))); m_ui.b->setText(tr("0x%0 (%1)").arg(b, 2, 16, QChar('0')).arg(b, 2, 10, QChar('0')));
@@ -6,7 +6,7 @@ <property name="geometry">
<rect> <x>0</x> <y>0</y> - <width>443</width> + <width>500</width> <height>397</height> </rect> </property>@@ -289,7 +289,7 @@ </item>
<item> <widget class="QLabel" name="index"> <property name="text"> - <string>000</string> + <string>0x000 (000)</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -112,6 +112,15 @@
void VideoView::updatePresets() { m_presets.clear(); + addPreset(m_ui.preset4K, { + .container = QString(), + .vcodec = QString(), + .acodec = QString(), + .vbr = 0, + .abr = 0, + .dims = maintainAspect(QSize(3840, 2160)) + }); + addPreset(m_ui.preset1080, { .container = QString(), .vcodec = QString(),@@ -173,6 +182,14 @@ addPreset(m_ui.presetWebM, {
.container = "WebM", .vcodec = "VP9", .acodec = "Opus", + .vbr = 800, + .abr = 128 + }); + + addPreset(m_ui.presetMP4, { + .container = "MP4", + .vcodec = "h.264", + .acodec = "AAC", .vbr = 800, .abr = 128 });
@@ -134,6 +134,13 @@ </attribute>
</widget> </item> <item> + <widget class="QRadioButton" name="presetMP4"> + <property name="text"> + <string>MP4</string> + </property> + </widget> + </item> + <item> <widget class="QRadioButton" name="presetLossless"> <property name="text"> <string>&Lossless</string>@@ -150,6 +157,13 @@ </layout>
</item> <item> <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QRadioButton" name="preset4K"> + <property name="text"> + <string>4K</string> + </property> + </widget> + </item> <item> <widget class="QRadioButton" name="preset1080"> <property name="text">@@ -289,6 +303,11 @@ <property name="text">
<string>FFV1</string> </property> </item> + <item> + <property name="text"> + <string>None</string> + </property> + </item> </widget> </item> <item>@@ -324,6 +343,11 @@ </item>
<item> <property name="text"> <string>Uncompressed</string> + </property> + </item> + <item> + <property name="text"> + <string>None</string> </property> </item> </widget>
@@ -871,7 +871,6 @@ for (Action* action : m_gameActions) {
action->setEnabled(false); } setWindowFilePath(QString()); - updateTitle(); detachWidget(m_display.get()); m_screenWidget->setCenteredAspectRatio(m_logo.width(), m_logo.height()); m_screenWidget->setDimensions(m_logo.width(), m_logo.height());@@ -900,6 +899,7 @@ }
m_display->stopDrawing(); m_controller.reset(); + updateTitle(); m_display->setVideoProxy({}); if (m_pendingClose) {@@ -1015,6 +1015,8 @@ m_audioProcessor->requestSampleRate(opts->sampleRate);
m_audioProcessor->start(); connect(m_controller.get(), &CoreController::stopping, m_audioProcessor.get(), &AudioProcessor::stop); connect(m_controller.get(), &CoreController::fastForwardChanged, m_audioProcessor.get(), &AudioProcessor::inputParametersChanged); + connect(m_controller.get(), &CoreController::paused, m_audioProcessor.get(), &AudioProcessor::pause); + connect(m_controller.get(), &CoreController::unpaused, m_audioProcessor.get(), &AudioProcessor::start); } void Window::changeRenderer() {@@ -1547,7 +1549,7 @@ #endif
#ifdef USE_FFMPEG addGameAction(tr("Record A/V..."), "recordOutput", this, &Window::openVideoWindow, "av"); - addGameAction(tr("Record GIF..."), "recordGIF", this, &Window::openGIFWindow, "av"); + addGameAction(tr("Record GIF/APNG..."), "recordGIF", this, &Window::openGIFWindow, "av"); #endif m_actions.addSeparator("av");
@@ -1441,7 +1441,7 @@ </message>
<message> <location filename="../BattleChipView.cpp" line="212"/> <source>Incompatible deck</source> - <translation>不兼容的卡组</translation> + <translation>卡组不兼容</translation> </message> <message> <location filename="../BattleChipView.cpp" line="213"/>@@ -1481,6 +1481,11 @@ <source>Add CodeBreaker</source>
<translation>添加 CodeBreaker</translation> </message> <message> + <location filename="../CheatsView.cpp" line="74"/> + <source>Add GameShark</source> + <translation>添加 GameShark</translation> + </message> + <message> <location filename="../CheatsView.cpp" line="80"/> <source>Add GameGenie</source> <translation>添加 GameGenie</translation>@@ -1495,24 +1500,24 @@ </context>
<context> <name>QGBA::CoreController</name> <message> - <location filename="../CoreController.cpp" line="593"/> + <location filename="../CoreController.cpp" line="589"/> <source>Failed to open save file: %1</source> - <translation>无法打开存档: %1</translation> + <translation>打开存档失败: %1</translation> </message> <message> - <location filename="../CoreController.cpp" line="622"/> + <location filename="../CoreController.cpp" line="618"/> <source>Failed to open game file: %1</source> - <translation>无法打开游戏文件: %1</translation> + <translation>打开游戏文件失败: %1</translation> </message> <message> <location filename="../CoreController.cpp" line="690"/> <source>Failed to open snapshot file for reading: %1</source> - <translation>无法读取快照文件: %1</translation> + <translation>读取快照文件失败: %1</translation> </message> <message> <location filename="../CoreController.cpp" line="706"/> <source>Failed to open snapshot file for writing: %1</source> - <translation>无法写入快照文件: %1</translation> + <translation>写入快照文件失败: %1</translation> </message> </context> <context>@@ -1520,7 +1525,7 @@ <name>QGBA::CoreManager</name>
<message> <location filename="../CoreManager.cpp" line="54"/> <source>Failed to open game file: %1</source> - <translation>无法打开游戏文件: %1</translation> + <translation>打开游戏文件失败: %1</translation> </message> </context> <context>@@ -1645,7 +1650,7 @@ <name>QGBA::GIFView</name>
<message> <location filename="../GIFView.cpp" line="49"/> <source>Failed to open output GIF file: %1</source> - <translation>无法打开输出的 GIF 文件: %1</translation> + <translation>打开输出 GIF 文件失败: %1</translation> </message> <message> <location filename="../GIFView.cpp" line="67"/>@@ -2612,7 +2617,7 @@ <location filename="../IOViewer.cpp" line="619"/>
<location filename="../IOViewer.cpp" line="664"/> <location filename="../IOViewer.cpp" line="709"/> <source>Increment and reload</source> - <translation>增量并重新加载</translation> + <translation>增量并重新载入</translation> </message> <message> <location filename="../IOViewer.cpp" line="576"/>@@ -3110,47 +3115,47 @@ </context>
<context> <name>QGBA::LogController</name> <message> - <location filename="../LogController.cpp" line="58"/> + <location filename="../LogController.cpp" line="68"/> <source>[%1] %2: %3</source> <translation>[%1] %2: %3</translation> </message> <message> - <location filename="../LogController.cpp" line="74"/> + <location filename="../LogController.cpp" line="79"/> <source>An error occurred</source> <translation>发生错误</translation> </message> <message> - <location filename="../LogController.cpp" line="145"/> + <location filename="../LogController.cpp" line="151"/> <source>DEBUG</source> <translation>DEBUG</translation> </message> <message> - <location filename="../LogController.cpp" line="147"/> + <location filename="../LogController.cpp" line="153"/> <source>STUB</source> <translation>STUB</translation> </message> <message> - <location filename="../LogController.cpp" line="149"/> + <location filename="../LogController.cpp" line="155"/> <source>INFO</source> <translation>INFO</translation> </message> <message> - <location filename="../LogController.cpp" line="151"/> + <location filename="../LogController.cpp" line="157"/> <source>WARN</source> <translation>WARN</translation> </message> <message> - <location filename="../LogController.cpp" line="153"/> + <location filename="../LogController.cpp" line="159"/> <source>ERROR</source> <translation>ERROR</translation> </message> <message> - <location filename="../LogController.cpp" line="155"/> + <location filename="../LogController.cpp" line="161"/> <source>FATAL</source> <translation>FATAL</translation> </message> <message> - <location filename="../LogController.cpp" line="157"/> + <location filename="../LogController.cpp" line="163"/> <source>GAME ERROR</source> <translation>GAME ERROR</translation> </message>@@ -3223,17 +3228,17 @@ </message>
<message> <location filename="../MapView.cpp" line="168"/> <location filename="../MapView.cpp" line="169"/> - <location filename="../MapView.cpp" line="213"/> + <location filename="../MapView.cpp" line="217"/> <source>N/A</source> <translation>无</translation> </message> <message> - <location filename="../MapView.cpp" line="256"/> + <location filename="../MapView.cpp" line="260"/> <source>Export map</source> <translation>导出映射</translation> </message> <message> - <location filename="../MapView.cpp" line="257"/> + <location filename="../MapView.cpp" line="261"/> <source>Portable Network Graphics (*.png)</source> <translation>便携式网络图形 (*.png)</translation> </message>@@ -3261,49 +3266,42 @@ <source>Load</source>
<translation>载入</translation> </message> <message> - <location filename="../MemoryModel.cpp" line="91"/> + <location filename="../MemoryModel.cpp" line="104"/> <source>All</source> <translation>全部</translation> </message> <message> - <location filename="../MemoryModel.cpp" line="136"/> + <location filename="../MemoryModel.cpp" line="149"/> <source>Load TBL</source> <translation>载入 TBL</translation> </message> <message> - <location filename="../MemoryModel.cpp" line="158"/> - <location filename="../MemoryModel.cpp" line="159"/> <location filename="../MemoryModel.cpp" line="203"/> - <source>N/A</source> - <translation>无</translation> - </message> - <message> - <location filename="../MemoryModel.cpp" line="190"/> <source>Save selected memory</source> <translation>保存所选内存</translation> </message> <message> - <location filename="../MemoryModel.cpp" line="196"/> + <location filename="../MemoryModel.cpp" line="209"/> <source>Failed to open output file: %1</source> - <translation>无法打开输出文件: %1</translation> + <translation>打开输出文件失败: %1</translation> </message> <message> - <location filename="../MemoryModel.cpp" line="204"/> + <location filename="../MemoryModel.cpp" line="217"/> <source>Load memory</source> <translation>载入内存</translation> </message> <message> - <location filename="../MemoryModel.cpp" line="210"/> + <location filename="../MemoryModel.cpp" line="223"/> <source>Failed to open input file: %1</source> - <translation>无法打开输入文件: %1</translation> + <translation>打开输入文件失败: %1</translation> </message> <message> - <location filename="../MemoryModel.cpp" line="326"/> + <location filename="../MemoryModel.cpp" line="339"/> <source>TBL</source> <translation>TBL</translation> </message> <message> - <location filename="../MemoryModel.cpp" line="326"/> + <location filename="../MemoryModel.cpp" line="339"/> <source>ISO-8859-1</source> <translation>ISO-8859-1</translation> </message>@@ -3334,49 +3332,49 @@ </context>
<context> <name>QGBA::ObjView</name> <message> - <location filename="../ObjView.cpp" line="150"/> - <location filename="../ObjView.cpp" line="224"/> + <location filename="../ObjView.cpp" line="151"/> + <location filename="../ObjView.cpp" line="225"/> <source>0x%0</source> <translation>0x%0</translation> </message> <message> - <location filename="../ObjView.cpp" line="161"/> + <location filename="../ObjView.cpp" line="162"/> <source>Off</source> <translation>关</translation> </message> <message> - <location filename="../ObjView.cpp" line="166"/> + <location filename="../ObjView.cpp" line="167"/> <source>Normal</source> <translation>一般</translation> </message> <message> - <location filename="../ObjView.cpp" line="169"/> + <location filename="../ObjView.cpp" line="170"/> <source>Trans</source> <translation>变换</translation> </message> <message> - <location filename="../ObjView.cpp" line="172"/> + <location filename="../ObjView.cpp" line="173"/> <source>OBJWIN</source> <translation>OBJWIN</translation> </message> <message> - <location filename="../ObjView.cpp" line="175"/> + <location filename="../ObjView.cpp" line="176"/> <source>Invalid</source> <translation>无效</translation> </message> <message> - <location filename="../ObjView.cpp" line="231"/> <location filename="../ObjView.cpp" line="232"/> + <location filename="../ObjView.cpp" line="233"/> <source>N/A</source> <translation>无</translation> </message> <message> - <location filename="../ObjView.cpp" line="257 "/> + <location filename="../ObjView.cpp" line="258"/> <source>Export sprite</source> <translation>导出精灵图</translation> </message> <message> - <location filename="../ObjView.cpp" line="258"/> + <location filename="../ObjView.cpp" line="259"/> <source>Portable Network Graphics (*.png)</source> <translation>便携式网络图形 (*.png)</translation> </message>@@ -3517,7 +3515,7 @@ <source>Select BIOS</source>
<translation>选择 BIOS</translation> </message> <message> - <location filename="../SettingsView.cpp" line="656"/> + <location filename="../SettingsView.cpp" line="662"/> <source>(%1×%2)</source> <translation>(%1×%2)</translation> </message>@@ -3525,12 +3523,12 @@ </context>
<context> <name>QGBA::ShaderSelector</name> <message> - <location filename="../ShaderSelector.cpp" line="54"/> + <location filename="../ShaderSelector.cpp" line="52"/> <source>No shader active</source> <translation>无活动的着色器</translation> </message> <message> - <location filename="../ShaderSelector.cpp" line="67"/> + <location filename="../ShaderSelector.cpp" line="65"/> <source>Load shader</source> <translation>载入着色器</translation> </message>@@ -3545,35 +3543,17 @@ <source>by %1</source>
<translation>由 %1</translation> </message> <message> - <location filename="../ShaderSelector.cpp" line="128"/> + <location filename="../ShaderSelector.cpp" line="124"/> <source>Preprocessing</source> - <translation>预处理</translation> + <translation>正在预处理</translation> </message> <message> - <location filename="../ShaderSelector.cpp" line="135"/> + <location filename="../ShaderSelector.cpp" line="131"/> <source>Pass %1</source> <translation>通道 %1</translation> </message> </context> <context> - <name>QGBA::ShortcutController</name> - <message> - <location filename="../ShortcutController.cpp" line="67"/> - <source>Action</source> - <translation>动作</translation> - </message> - <message> - <location filename="../ShortcutController.cpp" line="69"/> - <source>Keyboard</source> - <translation>键盘</translation> - </message> - <message> - <location filename="../ShortcutController.cpp" line="71"/> - <source>Gamepad</source> - <translation>游戏手柄</translation> - </message> -</context> -<context> <name>QGBA::TileView</name> <message> <location filename="../TileView.cpp" line="178"/>@@ -3591,126 +3571,126 @@ </context>
<context> <name>QGBA::VideoView</name> <message> - <location filename="../VideoView.cpp" line="212"/> + <location filename="../VideoView.cpp" line="216"/> <source>Failed to open output video file: %1</source> - <translation>无法打开输出视频文件: %1</translation> + <translation>打开输出视频文件失败: %1</translation> </message> <message> - <location filename="../VideoView.cpp" line="230"/> + <location filename="../VideoView.cpp" line="237"/> <source>Native (%0x%1)</source> <translation>原生 (%0x%1)</translation> </message> <message> - <location filename="../VideoView.cpp" line="245"/> + <location filename="../VideoView.cpp" line="252"/> <source>Select output file</source> - <translation>选取输出文件</translation> + <translation>选择输出文件</translation> </message> </context> <context> <name>QGBA::Window</name> <message> - <location filename="../Window.cpp" line="292"/> + <location filename="../Window.cpp" line="293"/> <source>Game Boy Advance ROMs (%1)</source> <translation>Game Boy Advance ROM (%1)</translation> </message> <message> - <location filename="../Window.cpp" line="309"/> + <location filename="../Window.cpp" line="310"/> <source>Game Boy ROMs (%1)</source> <translation>Game Boy ROM (%1)</translation> </message> <message> - <location filename="../Window.cpp" line="313"/> + <location filename="../Window.cpp" line="314"/> <source>All ROMs (%1)</source> <translation>所有 ROM (%1)</translation> </message> <message> - <location filename="../Window.cpp" line="314"/> + <location filename="../Window.cpp" line="315"/> <source>%1 Video Logs (*.mvl)</source> <translation>%1 视频日志 (*.mvl)</translation> </message> <message> - <location filename="../Window.cpp" line="329"/> + <location filename="../Window.cpp" line="330"/> <source>Archives (%1)</source> <translation>压缩文件 (%1)</translation> </message> <message> - <location filename="../Window.cpp" line="334"/> - <location filename="../Window.cpp" line="342"/> - <location filename="../Window.cpp" line="369"/> + <location filename="../Window.cpp" line="335"/> + <location filename="../Window.cpp" line="343"/> + <location filename="../Window.cpp" line="370"/> <source>Select ROM</source> <translation>选择 ROM</translation> </message> <message> - <location filename="../Window.cpp" line="360"/> + <location filename="../Window.cpp" line="361"/> <source>Select folder</source> <translation>选择文件夹</translation> </message> <message> - <location filename="../Window.cpp" line="377"/> + <location filename="../Window.cpp" line="378"/> <source>Game Boy Advance save files (%1)</source> <translation>Game Boy Advance 存档文件 (%1)</translation> </message> <message> - <location filename="../Window.cpp" line="378"/> - <location filename="../Window.cpp" line="439"/> - <location filename="../Window.cpp" line="446"/> + <location filename="../Window.cpp" line="379"/> + <location filename="../Window.cpp" line="440"/> + <location filename="../Window.cpp" line="447"/> <source>Select save</source> <translation>选择存档</translation> </message> <message> - <location filename="../Window.cpp" line="386"/> + <location filename="../Window.cpp" line="387"/> <source>mGBA savestate files (%1)</source> <translation>mGBA 即时存档文件 (%1)</translation> </message> <message> - <location filename="../Window.cpp" line="388"/> - <location filename="../Window.cpp" line="393"/> + <location filename="../Window.cpp" line="389"/> + <location filename="../Window.cpp" line="394"/> <source>Select savestate</source> <translation>选择即时存档</translation> </message> <message> - <location filename="../Window.cpp" line="415"/> + <location filename="../Window.cpp" line="416"/> <source>Select patch</source> <translation>选择补丁</translation> </message> <message> - <location filename="../Window.cpp" line="415"/> + <location filename="../Window.cpp" line="416"/> <source>Patches (*.ips *.ups *.bps)</source> <translation>补丁 (*.ips *.ups *.bps)</translation> </message> <message> - <location filename="../Window.cpp" line="432"/> + <location filename="../Window.cpp" line="433"/> <source>Select image</source> <translation>选择图片</translation> </message> <message> - <location filename="../Window.cpp" line="432"/> + <location filename="../Window.cpp" line="433"/> <source>Image file (*.png *.gif *.jpg *.jpeg);;All files (*)</source> <translation>图像文件 (*.png *.gif *.jpg *.jpeg);;所有文件 (*)</translation> </message> <message> - <location filename="../Window.cpp" line="439"/> - <location filename="../Window.cpp" line="446"/> + <location filename="../Window.cpp" line="440"/> + <location filename="../Window.cpp" line="447"/> <source>GameShark saves (*.sps *.xps)</source> <translation>GameShark 存档 (*.sps *.xps)</translation> </message> <message> - <location filename="../Window.cpp" line="473"/> + <location filename="../Window.cpp" line="474"/> <source>Select video log</source> <translation>选择视频日志</translation> </message> <message> - <location filename="../Window.cpp" line="473"/> + <location filename="../Window.cpp" line="474"/> <source>Video logs (*.mvl)</source> <translation>视频日志文件 (*.mvl)</translation> </message> <message> - <location filename="../Window.cpp" line="854"/> + <location filename="../Window.cpp" line="855"/> <source>Crash</source> <translation>崩溃</translation> </message> <message> - <location filename="../Window.cpp" line="855"/> + <location filename="../Window.cpp" line="856"/> <source>The game has crashed with the following error: %1</source>@@ -3719,578 +3699,578 @@
%1</translation> </message> <message> - <location filename="../Window.cpp" line="862"/> + <location filename="../Window.cpp" line="863"/> <source>Couldn't Load</source> <translation>无法载入</translation> </message> <message> - <location filename="../Window.cpp" line="863"/> + <location filename="../Window.cpp" line="864"/> <source>Could not load game. Are you sure it's in the correct format?</source> <translation>无法载入游戏。请确认游戏格式是否无误。</translation> </message> <message> - <location filename="../Window.cpp" line="876"/> + <location filename="../Window.cpp" line="877"/> <source>Unimplemented BIOS call</source> <translation>未实现的 BIOS 调用</translation> </message> <message> - <location filename="../Window.cpp" line="877"/> + <location filename="../Window.cpp" line="878"/> <source>This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience.</source> <translation>该游戏使用了尚未实现的 BIOS 调用。请使用官方 BIOS 以获得最佳游戏体验。</translation> </message> <message> - <location filename="../Window.cpp" line="964"/> + <location filename="../Window.cpp" line="976"/> <source>Really make portable?</source> <translation>确定进行程序便携化?</translation> </message> <message> - <location filename="../Window.cpp" line="965"/> + <location filename="../Window.cpp" line="977"/> <source>This will make the emulator load its configuration from the same directory as the executable. Do you want to continue?</source> - <translation>进行此操作后,模拟器将从模拟器可执行文件所在目录内加载模拟器配置。您想继续吗?</translation> + <translation>进行此操作后,模拟器将从模拟器可执行文件所在目录内载入模拟器配置。您想继续吗?</translation> </message> <message> - <location filename="../Window.cpp" line="977"/> + <location filename="../Window.cpp" line="989"/> <source>Restart needed</source> <translation>需要重新启动</translation> </message> <message> - <location filename="../Window.cpp" line="978"/> + <location filename="../Window.cpp" line="990"/> <source>Some changes will not take effect until the emulator is restarted.</source> <translation>更改将在模拟器下次启动时生效。</translation> </message> <message> - <location filename="../Window.cpp" line="1026"/> + <location filename="../Window.cpp" line="1038"/> <source> - Player %1 of %2</source> <translation> - 玩家 %1 共 %2</translation> </message> <message> - <location filename="../Window.cpp" line="1037"/> + <location filename="../Window.cpp" line="1049"/> <source>%1 - %2</source> <translation>%1 - %2</translation> </message> <message> - <location filename="../Window.cpp" line="1039"/> + <location filename="../Window.cpp" line="1051"/> <source>%1 - %2 - %3</source> <translation>%1 - %2 - %3</translation> </message> <message> - <location filename="../Window.cpp" line="1041"/> + <location filename="../Window.cpp" line="1053"/> <source>%1 - %2 (%3 fps) - %4</source> <translation>%1 - %2 (%3 fps) - %4</translation> </message> <message> - <location filename="../Window.cpp" line="1082"/> + <location filename="../Window.cpp" line="1094"/> <source>&File</source> <translation>文件(&F)</translation> </message> <message> - <location filename="../Window.cpp" line="1084"/> + <location filename="../Window.cpp" line="1096"/> <source>Load &ROM...</source> <translation>载入 ROM(&R)...</translation> </message> <message> - <location filename="../Window.cpp" line="1087"/> + <location filename="../Window.cpp" line="1099"/> <source>Load ROM in archive...</source> <translation>从压缩文件中载入 ROM...</translation> </message> <message> - <location filename="../Window.cpp" line="1088"/> + <location filename="../Window.cpp" line="1100"/> <source>Add folder to library...</source> <translation>将文件夹添加到库中...</translation> </message> <message> - <location filename="../Window.cpp" line="1091"/> + <location filename="../Window.cpp" line="1103"/> <source>Load alternate save...</source> - <translation>读取其他存档...</translation> + <translation>载入其他存档...</translation> </message> <message> - <location filename="../Window.cpp" line="1094"/> + <location filename="../Window.cpp" line="1106"/> <source>Load temporary save...</source> - <translation>读取临时存档...</translation> + <translation>载入临时存档...</translation> </message> <message> - <location filename="../Window.cpp" line="1098"/> + <location filename="../Window.cpp" line="1110"/> <source>Load &patch...</source> <translation>载入补丁文件(&P)...</translation> </message> <message> - <location filename="../Window.cpp" line="1101"/> + <location filename="../Window.cpp" line="1113"/> <source>Boot BIOS</source> <translation>引导 BIOS</translation> </message> <message> - <location filename="../Window.cpp" line="1106"/> + <location filename="../Window.cpp" line="1118"/> <source>Replace ROM...</source> <translation>替换 ROM...</translation> </message> <message> - <location filename="../Window.cpp" line="1105"/> + <location filename="../Window.cpp" line="1120"/> <source>ROM &info...</source> <translation>ROM 信息(&I)...</translation> </message> <message> - <location filename="../Window.cpp" line="1110"/> + <location filename="../Window.cpp" line="1122"/> <source>Recent</source> <translation>最近打开</translation> </message> <message> - <location filename="../Window.cpp" line="1113"/> + <location filename="../Window.cpp" line="1125"/> <source>Make portable</source> <translation>程序便携化</translation> </message> <message> - <location filename="../Window.cpp" line="1116"/> + <location filename="../Window.cpp" line="1128"/> <source>&Load state</source> - <translation>读取即时存档(&L)</translation> + <translation>载入即时存档(&L)</translation> </message> <message> - <location filename="../Window.cpp" line="1121"/> + <location filename="../Window.cpp" line="1133"/> <source>Load state file...</source> <translation>载入即时存档文件...</translation> </message> <message> - <location filename="../Window.cpp" line="1126"/> + <location filename="../Window.cpp" line="1138"/> <source>&Save state</source> <translation>保存即时存档(&S)</translation> </message> <message> - <location filename="../Window.cpp" line="1131"/> + <location filename="../Window.cpp" line="1143"/> <source>Save state file...</source> <translation>保存即时存档文件...</translation> </message> <message> - <location filename="../Window.cpp" line="1136"/> + <location filename="../Window.cpp" line="1148"/> <source>Quick load</source> <translation>快速读档</translation> </message> <message> - <location filename="../Window.cpp" line="1137"/> + <location filename="../Window.cpp" line="1149"/> <source>Quick save</source> <translation>快速存档</translation> </message> <message> - <location filename="../Window.cpp" line="1139"/> + <location filename="../Window.cpp" line="1151"/> <source>Load recent</source> <translation>载入最近</translation> </message> <message> - <location filename="../Window.cpp" line="1144"/> + <location filename="../Window.cpp" line="1156"/> <source>Save recent</source> <translation>保存最近</translation> </message> <message> - <location filename="../Window.cpp" line="1152"/> + <location filename="../Window.cpp" line="1164"/> <source>Undo load state</source> <translation>撤消读档</translation> </message> <message> - <location filename="../Window.cpp" line="1157"/> + <location filename="../Window.cpp" line="1169"/> <source>Undo save state</source> <translation>撤消存档</translation> </message> <message> - <location filename="../Window.cpp" line="1166"/> - <location filename="../Window.cpp" line="1171"/> + <location filename="../Window.cpp" line="1178"/> + <location filename="../Window.cpp" line="1183"/> <source>State &%1</source> <translation>即时存档 1(&1)</translation> </message> <message> - <location filename="../Window.cpp" line="1178"/> + <location filename="../Window.cpp" line="1190"/> <source>Load camera image...</source> - <translation>读取相机图片...</translation> + <translation>载入相机图片...</translation> </message> <message> - <location filename="../Window.cpp" line="1182"/> + <location filename="../Window.cpp" line="1194"/> <source>Import GameShark Save</source> <translation>导入 GameShark 存档</translation> </message> <message> - <location filename="../Window.cpp" line="1185"/> + <location filename="../Window.cpp" line="1197"/> <source>Export GameShark Save</source> <translation>导出 GameShark 存档</translation> </message> <message> - <location filename="../Window.cpp" line="1190"/> + <location filename="../Window.cpp" line="1202"/> <source>New multiplayer window</source> <translation>新建多人游戏窗口</translation> </message> <message> - <location filename="../Window.cpp" line="1198"/> + <location filename="../Window.cpp" line="1210"/> <source>About...</source> <translation>关于...</translation> </message> <message> - <location filename="../Window.cpp" line="1201"/> + <location filename="../Window.cpp" line="1213"/> <source>E&xit</source> <translation>退出(&X)</translation> </message> <message> - <location filename="../Window.cpp" line="1204"/> + <location filename="../Window.cpp" line="1216"/> <source>&Emulation</source> <translation>模拟(&E)</translation> </message> <message> - <location filename="../Window.cpp" line="1205"/> + <location filename="../Window.cpp" line="1217"/> <source>&Reset</source> <translation>重置(&R)</translation> </message> <message> - <location filename="../Window.cpp" line="1209"/> + <location filename="../Window.cpp" line="1221"/> <source>Sh&utdown</source> <translation>关机(&U)</translation> </message> <message> - <location filename="../Window.cpp" line="1213"/> + <location filename="../Window.cpp" line="1225"/> <source>Yank game pak</source> <translation>快速抽出游戏卡带</translation> </message> <message> - <location filename="../Window.cpp" line="1219"/> + <location filename="../Window.cpp" line="1231"/> <source>&Pause</source> <translation>暂停(&P)</translation> </message> <message> - <location filename="../Window.cpp" line="1228"/> + <location filename="../Window.cpp" line="1240"/> <source>&Next frame</source> <translation>下一帧(&N)</translation> </message> <message> - <location filename="../Window.cpp" line="1234"/> + <location filename="../Window.cpp" line="1246"/> <source>Fast forward (held)</source> <translation>快进 (长按)</translation> </message> <message> - <location filename="../Window.cpp" line="1240"/> + <location filename="../Window.cpp" line="1252"/> <source>&Fast forward</source> <translation>快进(&F)</translation> </message> <message> - <location filename="../Window.cpp" line="1244"/> + <location filename="../Window.cpp" line="1256"/> <source>Fast forward speed</source> <translation>快进速度</translation> </message> <message> - <location filename="../Window.cpp" line="1249"/> + <location filename="../Window.cpp" line="1261"/> <source>Unbounded</source> <translation>不限制</translation> </message> <message> - <location filename="../Window.cpp" line="1253"/> + <location filename="../Window.cpp" line="1265"/> <source>%0x</source> <translation>%0x</translation> </message> <message> - <location filename="../Window.cpp" line="1257"/> + <location filename="../Window.cpp" line="1269"/> <source>Rewind (held)</source> <translation>倒带 (长按)</translation> </message> <message> - <location filename="../Window.cpp" line="1264"/> + <location filename="../Window.cpp" line="1276"/> <source>Re&wind</source> <translation>倒带(&W)</translation> </message> <message> - <location filename="../Window.cpp" line="1269"/> + <location filename="../Window.cpp" line="1281"/> <source>Step backwards</source> <translation>步退</translation> </message> <message> - <location filename="../Window.cpp" line="1275"/> + <location filename="../Window.cpp" line="1287"/> <source>Sync to &video</source> <translation>视频同步(&V)</translation> </message> <message> - <location filename="../Window.cpp" line="1282"/> + <location filename="../Window.cpp" line="1294"/> <source>Sync to &audio</source> <translation>音频同步(&A)</translation> </message> <message> - <location filename="../Window.cpp" line="1290"/> + <location filename="../Window.cpp" line="1302"/> <source>Solar sensor</source> <translation>光线传感器</translation> </message> <message> - <location filename="../Window.cpp" line="1291"/> + <location filename="../Window.cpp" line="1303"/> <source>Increase solar level</source> <translation>增加光线级别</translation> </message> <message> - <location filename="../Window.cpp" line="1292"/> + <location filename="../Window.cpp" line="1304"/> <source>Decrease solar level</source> <translation>降低光线级别</translation> </message> <message> - <location filename="../Window.cpp" line="1293"/> + <location filename="../Window.cpp" line="1305"/> <source>Brightest solar level</source> <translation>光线级别为最亮</translation> </message> <message> - <location filename="../Window.cpp" line="1296"/> + <location filename="../Window.cpp" line="1308"/> <source>Darkest solar level</source> <translation>光线级别为最暗</translation> </message> <message> - <location filename="../Window.cpp" line="1302"/> + <location filename="../Window.cpp" line="1314"/> <source>Brightness %1</source> <translation>亮度 %1</translation> </message> <message> - <location filename="../Window.cpp" line="1308"/> + <location filename="../Window.cpp" line="1320"/> <source>Game Boy Printer...</source> <translation>Game Boy 打印机...</translation> </message> <message> - <location filename="../Window.cpp" line="1317"/> + <location filename="../Window.cpp" line="1329"/> <source>BattleChip Gate...</source> <translation>BattleChip Gate...</translation> </message> <message> - <location filename="../Window.cpp" line="1321"/> + <location filename="../Window.cpp" line="1333"/> <source>Audio/&Video</source> <translation>音频/视频(&V)</translation> </message> <message> - <location filename="../Window.cpp" line="1322"/> + <location filename="../Window.cpp" line="1334"/> <source>Frame size</source> <translation>帧率</translation> </message> <message> - <location filename="../Window.cpp" line="1324"/> + <location filename="../Window.cpp" line="1336"/> <source>%1×</source> <translation>%1×</translation> </message> <message> - <location filename="../Window.cpp" line="1349"/> + <location filename="../Window.cpp" line="1361"/> <source>Toggle fullscreen</source> <translation>切换全屏</translation> </message> <message> - <location filename="../Window.cpp" line="1352"/> + <location filename="../Window.cpp" line="1364"/> <source>Lock aspect ratio</source> <translation>锁定纵横比</translation> </message> <message> - <location filename="../Window.cpp" line="1364"/> + <location filename="../Window.cpp" line="1376"/> <source>Force integer scaling</source> <translation>强制整数缩放</translation> </message> <message> - <location filename="../Window.cpp" line="1376"/> + <location filename="../Window.cpp" line="1388"/> <source>Interframe blending</source> <translation>帧间混合</translation> </message> <message> - <location filename="../Window.cpp" line="1385"/> + <location filename="../Window.cpp" line="1397"/> <source>Bilinear filtering</source> <translation>双线性过滤</translation> </message> <message> - <location filename="../Window.cpp" line="1393"/> + <location filename="../Window.cpp" line="1406"/> <source>Frame&skip</source> <translation>跳帧(&S)</translation> </message> <message> - <location filename="../Window.cpp" line="1406"/> + <location filename="../Window.cpp" line="1419"/> <source>Mute</source> <translation>静音</translation> </message> <message> - <location filename="../Window.cpp" line="1413"/> + <location filename="../Window.cpp" line="1428"/> <source>FPS target</source> <translation>目标 FPS</translation> </message> <message> - <location filename="../Window.cpp" line="1421"/> + <location filename="../Window.cpp" line="1436"/> <source>Native (59.7275)</source> <translation>原生 (59.7275)</translation> </message> <message> - <location filename="../Window.cpp" line="1436"/> + <location filename="../Window.cpp" line="1451"/> <source>Take &screenshot</source> <translation>截图(&S)</translation> </message> <message> - <location filename="../Window.cpp" line="1442"/> + <location filename="../Window.cpp" line="1457"/> <source>Record A/V...</source> <translation>录制音频/视频...</translation> </message> <message> - <location filename="../Window.cpp" line="1443"/> + <location filename="../Window.cpp" line="1458"/> <source>Record GIF...</source> <translation>录制 GIF...</translation> </message> <message> - <location filename="../Window.cpp" line="1447"/> + <location filename="../Window.cpp" line="1462"/> <source>Video layers</source> <translation>视频图层</translation> </message> <message> - <location filename="../Window.cpp" line="1448"/> + <location filename="../Window.cpp" line="1463"/> <source>Audio channels</source> <translation>音频通道</translation> </message> <message> - <location filename="../Window.cpp" line="1450"/> + <location filename="../Window.cpp" line="1465"/> <source>Adjust layer placement...</source> <translation>调整图层布局...</translation> </message> <message> - <location filename="../Window.cpp" line="1452"/> + <location filename="../Window.cpp" line="1467"/> <source>&Tools</source> <translation>工具(&T)</translation> </message> <message> - <location filename="../Window.cpp" line="1453"/> + <location filename="../Window.cpp" line="1468"/> <source>View &logs...</source> <translation>查看日志(&L)...</translation> </message> <message> - <location filename="../Window.cpp" line="1455"/> + <location filename="../Window.cpp" line="1470"/> <source>Game &overrides...</source> <translation>覆盖游戏(&O)...</translation> </message> <message> - <location filename="../Window.cpp" line="1467"/> + <location filename="../Window.cpp" line="1482"/> <source>Game Pak sensors...</source> <translation>游戏卡带传感器...</translation> </message> <message> - <location filename="../Window.cpp" line="1478"/> + <location filename="../Window.cpp" line="1493"/> <source>&Cheats...</source> <translation>作弊码(&C)...</translation> </message> <message> - <location filename="../Window.cpp" line="1481"/> + <location filename="../Window.cpp" line="1496"/> <source>Settings...</source> <translation>设置...</translation> </message> <message> - <location filename="../Window.cpp" line="1485"/> + <location filename="../Window.cpp" line="1500"/> <source>Open debugger console...</source> <translation>打开调试器控制台...</translation> </message> <message> - <location filename="../Window.cpp" line="1487"/> + <location filename="../Window.cpp" line="1502"/> <source>Start &GDB server...</source> <translation>打开 GDB 服务器(&G)...</translation> </message> <message> - <location filename="../Window.cpp" line="1493"/> + <location filename="../Window.cpp" line="1508"/> <source>View &palette...</source> <translation>查看调色板(&P)...</translation> </message> <message> - <location filename="../Window.cpp" line="1494"/> + <location filename="../Window.cpp" line="1509"/> <source>View &sprites...</source> <translation>查看精灵图(&S)...</translation> </message> <message> - <location filename="../Window.cpp" line="1495"/> + <location filename="../Window.cpp" line="1510"/> <source>View &tiles...</source> <translation>查看瓷贴(&T)...</translation> </message> <message> - <location filename="../Window.cpp" line="1496"/> + <location filename="../Window.cpp" line="1511"/> <source>View &map...</source> <translation>查看映射(&M)...</translation> </message> <message> - <location filename="../Window.cpp" line="1499"/> + <location filename="../Window.cpp" line="1514"/> <source>&Frame inspector...</source> <translation>框架检查(&F)...</translation> </message> <message> - <location filename="../Window.cpp" line="1517"/> + <location filename="../Window.cpp" line="1532"/> <source>View memory...</source> <translation>查看内存...</translation> </message> <message> - <location filename="../Window.cpp" line="1518"/> + <location filename="../Window.cpp" line="1533"/> <source>Search memory...</source> <translation>搜索内存...</translation> </message> <message> - <location filename="../Window.cpp" line="1521"/> + <location filename="../Window.cpp" line="1536"/> <source>View &I/O registers...</source> <translation>查看 I/O 寄存器(&I)...</translation> </message> <message> - <location filename="../Window.cpp" line="1526"/> + <location filename="../Window.cpp" line="1541"/> <source>Record debug video log...</source> <translation>记录调试视频日志...</translation> </message> <message> - <location filename="../Window.cpp" line="1527"/> + <location filename="../Window.cpp" line="1542"/> <source>Stop debug video log</source> <translation>停止记录调试视频日志</translation> </message> <message> - <location filename="../Window.cpp" line="1615"/> + <location filename="../Window.cpp" line="1637"/> <source>Exit fullscreen</source> <translation>退出全屏</translation> </message> <message> - <location filename="../Window.cpp" line="1617"/> + <location filename="../Window.cpp" line="1639"/> <source>GameShark Button (held)</source> <translation>GameShark 键 (长按)</translation> </message> <message> - <location filename="../Window.cpp" line="1623"/> + <location filename="../Window.cpp" line="1645"/> <source>Autofire</source> <translation>连发</translation> </message> <message> - <location filename="../Window.cpp" line="1624"/> + <location filename="../Window.cpp" line="1646"/> <source>Autofire A</source> <translation>连发 A</translation> </message> <message> - <location filename="../Window.cpp" line="1629"/> + <location filename="../Window.cpp" line="1651"/> <source>Autofire B</source> <translation>连发 B</translation> </message> <message> - <location filename="../Window.cpp" line="1634"/> + <location filename="../Window.cpp" line="1656"/> <source>Autofire L</source> <translation>连发 L</translation> </message> <message> - <location filename="../Window.cpp" line="1639"/> + <location filename="../Window.cpp" line="1661"/> <source>Autofire R</source> <translation>连发 R</translation> </message> <message> - <location filename="../Window.cpp" line="1644"/> + <location filename="../Window.cpp" line="1666"/> <source>Autofire Start</source> <translation>连发 Start</translation> </message> <message> - <location filename="../Window.cpp" line="1649"/> + <location filename="../Window.cpp" line="1671"/> <source>Autofire Select</source> <translation>连发 Select</translation> </message> <message> - <location filename="../Window.cpp" line="1654"/> + <location filename="../Window.cpp" line="1676"/> <source>Autofire Up</source> <translation>连发 上</translation> </message> <message> - <location filename="../Window.cpp" line="1659"/> + <location filename="../Window.cpp" line="1681"/> <source>Autofire Right</source> <translation>连发 右</translation> </message> <message> - <location filename="../Window.cpp" line="1664"/> + <location filename="../Window.cpp" line="1686"/> <source>Autofire Down</source> <translation>连发 下</translation> </message> <message> - <location filename="../Window.cpp" line="1669"/> + <location filename="../Window.cpp" line="1691"/> <source>Autofire Left</source> <translation>连发 左</translation> </message> <message> - <location filename="../Window.cpp" line="1723"/> + <location filename="../Window.cpp" line="1745"/> <source>Clear</source> <translation>清除</translation> </message>@@ -4813,7 +4793,7 @@ </message>
<message> <location filename="../SettingsView.ui" line="845"/> <source>Preload entire ROM into memory</source> - <translation>将整个 ROM 预加载到内存中</translation> + <translation>将整个 ROM 预载到内存中</translation> </message> <message> <location filename="../SettingsView.ui" line="859"/>
@@ -46,7 +46,7 @@ set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libpixman-1.0" PARENT_SCOPE)
endif() if(WIN32) - list(APPEND SDL_LIBRARY imm32 version winmm) + list(APPEND SDL_LIBRARY imm32 setupapi version winmm) elseif(APPLE) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework AppKit -framework AudioUnit -framework Carbon -framework CoreAudio -framework AudioToolbox -framework ForceFeedback -framework IOKit") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE)
@@ -19,6 +19,11 @@
static void _mSDLAudioCallback(void* context, Uint8* data, int len); bool mSDLInitAudio(struct mSDLAudio* context, struct mCoreThread* threadContext) { +#if defined(_WIN32) && SDL_VERSION_ATLEAST(2, 0, 8) + if (!getenv("SDL_AUDIODRIVER")) { + _putenv_s("SDL_AUDIODRIVER", "directsound"); + } +#endif if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { mLOG(SDL_AUDIO, ERROR, "Could not initialize SDL sound system: %s", SDL_GetError()); return false;
@@ -348,6 +348,13 @@ SDL_Joystick* sdlJoystick = SDL_JoystickOpen(event.jdevice.which);
if (!sdlJoystick) { continue; } + ssize_t joysticks[MAX_PLAYERS]; + size_t i; + // Pointers can get invalidated, so we'll need to refresh them + for (i = 0; i < events->playersAttached && i < MAX_PLAYERS; ++i) { + joysticks[i] = events->players[i]->joystick ? SDL_JoystickListIndex(&events->joysticks, events->players[i]->joystick) : SIZE_MAX; + events->players[i]->joystick = NULL; + } struct SDL_JoystickCombo* joystick = SDL_JoystickListAppend(&events->joysticks); joystick->joystick = sdlJoystick; joystick->id = SDL_JoystickInstanceID(joystick->joystick);@@ -355,8 +362,12 @@ joystick->index = SDL_JoystickListSize(&events->joysticks) - 1;
#if SDL_VERSION_ATLEAST(2, 0, 0) joystick->haptic = SDL_HapticOpenFromJoystick(joystick->joystick); #endif + for (i = 0; i < events->playersAttached && i < MAX_PLAYERS; ++i) { + if (joysticks[i] != SIZE_MAX) { + events->players[i]->joystick = SDL_JoystickListGetPointer(&events->joysticks, joysticks[i]); + } + } - size_t i; #if SDL_VERSION_ATLEAST(2, 0, 0) char joystickName[34] = {0}; SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick->joystick), joystickName, sizeof(joystickName));
@@ -22,6 +22,14 @@ #endif
#ifdef __SWITCH__ #include <switch.h> #endif +#ifdef GEKKO +#include <fat.h> +#include <gccore.h> +#ifdef FIXED_ROM_BUFFER +uint32_t* romBuffer; +size_t romBufferSize; +#endif +#endif #include <errno.h> #include <fcntl.h>@@ -83,6 +91,29 @@ }
#elif defined(__SWITCH__) UNUSED(_mPerfShutdown); consoleInit(NULL); +#elif defined(GEKKO) + VIDEO_Init(); + VIDEO_SetBlack(true); + VIDEO_Flush(); + VIDEO_WaitVSync(); + + GXRModeObj* vmode = VIDEO_GetPreferredMode(0); + void* xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(vmode)); + console_init(xfb, 20, 20, vmode->fbWidth, vmode->xfbHeight, vmode->fbWidth * VI_DISPLAY_PIX_SZ); + + VIDEO_Configure(vmode); + VIDEO_SetNextFramebuffer(xfb); + VIDEO_SetBlack(false); + VIDEO_Flush(); + VIDEO_WaitVSync(); + VIDEO_WaitVSync(); + fatInitDefault(); + +#ifdef FIXED_ROM_BUFFER + romBufferSize = 0x02000000; + romBuffer = SYS_GetArena2Lo(); + SYS_SetArena2Lo((void*)((intptr_t) romBuffer + romBufferSize)); +#endif #else signal(SIGINT, _mPerfShutdown); #endif@@ -125,6 +156,8 @@ if (perfOpts.csv) {
puts("game_code,frames,duration,renderer"); #ifdef __SWITCH__ consoleUpdate(NULL); +#elif defined(GEKKO) + VIDEO_WaitVSync(); #endif } if (perfOpts.server) {@@ -145,6 +178,11 @@ gfxExit();
acExit(); #elif defined(__SWITCH__) consoleExit(NULL); +#elif defined(GEKKO) + VIDEO_SetBlack(true); + VIDEO_Flush(); + VIDEO_WaitVSync(); + VIDEO_WaitVSync(); #endif return didFail;
@@ -11,6 +11,7 @@
file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/wii/wii-*.c) list(APPEND OS_LIB wiiuse bte fat ogc) set(OS_SRC ${OS_SRC} PARENT_SCOPE) +set(OS_LIB ${OS_LIB} PARENT_SCOPE) source_group("Wii-specific code" FILES ${OS_SRC}) set(CORE_VFS_SRC ${CORE_VFS_SRC} PARENT_SCOPE) set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE)@@ -38,6 +39,16 @@ DEPENDS ${BINARY_NAME}.elf)
add_custom_target(run ${WIILOAD} ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.dol DEPENDS ${BINARY_NAME}.dol) + +if(BUILD_PERF) + add_custom_target(${BINARY_NAME}-perf.dol ALL + ${ELF2DOL} ../${BINARY_NAME}-perf ${BINARY_NAME}-perf.dol + DEPENDS ${BINARY_NAME}-perf) + + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}-perf.dol + DESTINATION . COMPONENT ${BINARY_NAME}-perf) +endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/meta.xml.in ${CMAKE_CURRENT_BINARY_DIR}/meta.xml)
@@ -262,7 +262,7 @@ memset(audioBuffer, 0, sizeof(audioBuffer));
#ifdef FIXED_ROM_BUFFER romBufferSize = SIZE_CART0; romBuffer = SYS_GetArena2Lo(); - SYS_SetArena2Lo((void*)((intptr_t) romBuffer + SIZE_CART0)); + SYS_SetArena2Lo((void*)((intptr_t) romBuffer + romBufferSize)); #endif #if !defined(COLOR_16_BIT) && !defined(COLOR_5_6_5)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015 Jeffrey Pfau +/* 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@@ -14,11 +14,23 @@ #else
#include <windows.h> #endif +#include <mgba-util/vector.h> + +#ifdef _WIN32 +struct HandleMappingTuple { + HANDLE handle; + void* mapping; +}; + +DECLARE_VECTOR(HandleMappingList, struct HandleMappingTuple); +DEFINE_VECTOR(HandleMappingList, struct HandleMappingTuple); +#endif + struct VFileFD { struct VFile d; int fd; #ifdef _WIN32 - HANDLE hMap; + struct HandleMappingList handles; #endif };@@ -74,12 +86,23 @@ vfd->d.unmap = _vfdUnmap;
vfd->d.truncate = _vfdTruncate; vfd->d.size = _vfdSize; vfd->d.sync = _vfdSync; +#ifdef _WIN32 + HandleMappingListInit(&vfd->handles, 4); +#endif return &vfd->d; } bool _vfdClose(struct VFile* vf) { struct VFileFD* vfd = (struct VFileFD*) vf; +#ifdef _WIN32 + size_t i; + for (i = 0; i < HandleMappingListSize(&vfd->handles); ++i) { + UnmapViewOfFile(HandleMappingListGetPointer(&vfd->handles, i)->mapping); + CloseHandle(HandleMappingListGetPointer(&vfd->handles, i)->handle); + } + HandleMappingListDeinit(&vfd->handles); +#endif if (close(vfd->fd) < 0) { return false; }@@ -134,16 +157,25 @@ fileSize = stat.st_size;
if (size > fileSize) { size = fileSize; } - vfd->hMap = CreateFileMapping((HANDLE) _get_osfhandle(vfd->fd), 0, createFlags, 0, size & 0xFFFFFFFF, 0); - return MapViewOfFile(vfd->hMap, mapFiles, 0, 0, size); + struct HandleMappingTuple tuple = {0}; + tuple.handle = CreateFileMapping((HANDLE) _get_osfhandle(vfd->fd), 0, createFlags, 0, size & 0xFFFFFFFF, 0); + tuple.mapping = MapViewOfFile(tuple.handle, mapFiles, 0, 0, size); + *HandleMappingListAppend(&vfd->handles) = tuple; + return tuple.mapping; } static void _vfdUnmap(struct VFile* vf, void* memory, size_t size) { UNUSED(size); struct VFileFD* vfd = (struct VFileFD*) vf; - UnmapViewOfFile(memory); - CloseHandle(vfd->hMap); - vfd->hMap = 0; + size_t i; + for (i = 0; i < HandleMappingListSize(&vfd->handles); ++i) { + if (HandleMappingListGetPointer(&vfd->handles, i)->mapping == memory) { + UnmapViewOfFile(memory); + CloseHandle(HandleMappingListGetPointer(&vfd->handles, i)->handle); + HandleMappingListShift(&vfd->handles, i, 1); + break; + } + } } #endif