mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' (early part) into medusa
This commit is contained in:
commit
d026a5af75
1
CHANGES
1
CHANGES
|
@ -46,6 +46,7 @@ Other fixes:
|
|||
- GBA e-Reader: Fix bitmap short strip scanning
|
||||
- GBA Video: Fix mode 5 frame 1 caching (fixes mgba.io/i/2075)
|
||||
- GBA Video: Don't attempt to copy invalid registers when switching renderer
|
||||
- Qt: Fix crash when switching from high-resolution OpenGL renderer to software
|
||||
Misc:
|
||||
- Core: Truncate preloading ROMs that slightly exceed max size (fixes mgba.io/i/2093)
|
||||
- GBA: Default-enable VBA bug compat for Ruby and Emerald ROM hacks
|
||||
|
|
|
@ -573,7 +573,7 @@ if(USE_FFMPEG)
|
|||
endif()
|
||||
include_directories(AFTER ${FFMPEG_INCLUDE_DIRS} ${LIBAVCODEC_INCLUDE_DIRS} ${LIBAVFILTER_INCLUDE_DIRS} ${LIBAVFORMAT_INCLUDE_DIRS} ${LIBAVRESAMPLE_INCLUDE_DIRS} ${LIBAVUTIL_INCLUDE_DIRS} ${LIBSWRESAMPLE_INCLUDE_DIRS} ${LIBSWSCALE_INCLUDE_DIRS})
|
||||
link_directories(${FFMPEG_LIBRARY_DIRS} ${LIBAVCODEC_LIBRARY_DIRS} ${LIBAVFILTER_LIBRARY_DIRS} ${LIBAVFORMAT_LIBRARY_DIRS} ${LIBAVRESAMPLE_LIBRARY_DIRS} ${LIBAVUTIL_LIBRARY_DIRS} ${LIBSWRESAMPLE_LIBRARY_DIRS} ${LIBSWSCALE_LIBRARY_DIRS})
|
||||
list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-encoder.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-decoder.c")
|
||||
list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-encoder.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-decoder.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-scale.c")
|
||||
list(APPEND DEPENDENCY_LIB ${FFMPEG_LIBRARIES} ${LIBAVCODEC_LIBRARIES} ${LIBAVFILTER_LIBRARIES} ${LIBAVFORMAT_LIBRARIES} ${LIBAVRESAMPLE_LIBRARIES} ${LIBAVUTIL_LIBRARIES} ${LIBSWSCALE_LIBRARIES} ${LIBSWRESAMPLE_LIBRARIES})
|
||||
if(WIN32 AND NOT DEFINED VCPKG_TARGET_TRIPLET)
|
||||
list(APPEND DEPENDENCY_LIB bcrypt)
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/* Copyright (c) 2013-2021 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef CONVOLVE_H
|
||||
#define CONVOLVE_H
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
CXX_GUARD_START
|
||||
|
||||
struct ConvolutionKernel {
|
||||
float* kernel;
|
||||
size_t* dims;
|
||||
size_t rank;
|
||||
};
|
||||
|
||||
void ConvolutionKernelCreate(struct ConvolutionKernel* kernel, size_t rank, size_t* dims);
|
||||
void ConvolutionKernelDestroy(struct ConvolutionKernel* kernel);
|
||||
|
||||
void ConvolutionKernelFillRadial(struct ConvolutionKernel* kernel, bool normalize);
|
||||
void ConvolutionKernelFillCircle(struct ConvolutionKernel* kernel, bool normalize);
|
||||
|
||||
// TODO: Make image container struct?
|
||||
void Convolve1DPad0PackedS32(const int32_t* restrict src, int32_t* restrict dst, size_t length, const struct ConvolutionKernel* restrict kernel);
|
||||
|
||||
void Convolve2DClampPacked8(const uint8_t* restrict src, uint8_t* restrict dst, size_t width, size_t height, size_t stride, const struct ConvolutionKernel* restrict kernel);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
|
@ -164,6 +164,7 @@ enum mColorFormat {
|
|||
mCOLOR_BGRA5 = 0x08000,
|
||||
mCOLOR_RGB8 = 0x10000,
|
||||
mCOLOR_BGR8 = 0x20000,
|
||||
mCOLOR_L8 = 0x40000,
|
||||
|
||||
mCOLOR_ANY = -1
|
||||
};
|
||||
|
|
|
@ -98,7 +98,7 @@ struct GBASIOBattlechipGate {
|
|||
|
||||
void GBASIOBattlechipGateCreate(struct GBASIOBattlechipGate*);
|
||||
|
||||
void GBAEReaderQueueCard(struct GBA* gba, const void* data, size_t size);
|
||||
void GBACartEReaderQueueCard(struct GBA* gba, const void* data, size_t size);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ CXX_GUARD_START
|
|||
#include <mgba/internal/ds/timer.h>
|
||||
#include <mgba/internal/ds/video.h>
|
||||
#include <mgba/internal/ds/wifi.h>
|
||||
#include <mgba/internal/gba/hardware.h>
|
||||
#include <mgba/internal/gba/cart/gpio.h>
|
||||
|
||||
extern const uint32_t DS_ARM946ES_FREQUENCY;
|
||||
extern const uint32_t DS_ARM7TDMI_FREQUENCY;
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef GBA_EREADER_H
|
||||
#define GBA_EREADER_H
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
CXX_GUARD_START
|
||||
|
||||
struct GBACartridgeHardware;
|
||||
|
||||
#define EREADER_DOTCODE_STRIDE 1420
|
||||
#define EREADER_DOTCODE_SIZE (EREADER_DOTCODE_STRIDE * 40)
|
||||
#define EREADER_CARDS_MAX 16
|
||||
|
||||
DECL_BITFIELD(EReaderControl0, uint8_t);
|
||||
DECL_BIT(EReaderControl0, Data, 0);
|
||||
DECL_BIT(EReaderControl0, Clock, 1);
|
||||
DECL_BIT(EReaderControl0, Direction, 2);
|
||||
DECL_BIT(EReaderControl0, LedEnable, 3);
|
||||
DECL_BIT(EReaderControl0, Scan, 4);
|
||||
DECL_BIT(EReaderControl0, Phi, 5);
|
||||
DECL_BIT(EReaderControl0, PowerEnable, 6);
|
||||
DECL_BITFIELD(EReaderControl1, uint8_t);
|
||||
DECL_BIT(EReaderControl1, Scanline, 1);
|
||||
DECL_BIT(EReaderControl1, Unk1, 4);
|
||||
DECL_BIT(EReaderControl1, Voltage, 5);
|
||||
|
||||
enum EReaderStateMachine {
|
||||
EREADER_SERIAL_INACTIVE = 0,
|
||||
EREADER_SERIAL_STARTING,
|
||||
EREADER_SERIAL_BIT_0,
|
||||
EREADER_SERIAL_BIT_1,
|
||||
EREADER_SERIAL_BIT_2,
|
||||
EREADER_SERIAL_BIT_3,
|
||||
EREADER_SERIAL_BIT_4,
|
||||
EREADER_SERIAL_BIT_5,
|
||||
EREADER_SERIAL_BIT_6,
|
||||
EREADER_SERIAL_BIT_7,
|
||||
EREADER_SERIAL_END_BIT,
|
||||
};
|
||||
|
||||
enum EReaderCommand {
|
||||
EREADER_COMMAND_IDLE = 0, // TODO: Verify on hardware
|
||||
EREADER_COMMAND_WRITE_DATA = 1,
|
||||
EREADER_COMMAND_SET_INDEX = 0x22,
|
||||
EREADER_COMMAND_READ_DATA = 0x23,
|
||||
};
|
||||
|
||||
struct EReaderCard {
|
||||
void* data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct GBA;
|
||||
struct GBACartEReader {
|
||||
struct GBA* p;
|
||||
uint16_t data[44];
|
||||
uint8_t serial[92];
|
||||
uint16_t registerUnk;
|
||||
uint16_t registerReset;
|
||||
EReaderControl0 registerControl0;
|
||||
EReaderControl1 registerControl1;
|
||||
uint16_t registerLed;
|
||||
|
||||
// TODO: Serialize these
|
||||
enum EReaderStateMachine state;
|
||||
enum EReaderCommand command;
|
||||
uint8_t activeRegister;
|
||||
uint8_t byte;
|
||||
int scanX;
|
||||
int scanY;
|
||||
uint8_t* dots;
|
||||
struct EReaderCard cards[EREADER_CARDS_MAX];
|
||||
};
|
||||
|
||||
void GBACartEReaderInit(struct GBACartEReader* ereader);
|
||||
void GBACartEReaderDeinit(struct GBACartEReader* ereader);
|
||||
void GBACartEReaderWrite(struct GBACartEReader* ereader, uint32_t address, uint16_t value);
|
||||
void GBACartEReaderWriteFlash(struct GBACartEReader* ereader, uint32_t address, uint8_t value);
|
||||
uint16_t GBACartEReaderRead(struct GBACartEReader* ereader, uint32_t address);
|
||||
uint8_t GBACartEReaderReadFlash(struct GBACartEReader* ereader, uint32_t address);
|
||||
void GBACartEReaderScan(struct GBACartEReader* ereader, const void* data, size_t size);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
|
@ -16,10 +16,6 @@ CXX_GUARD_START
|
|||
|
||||
mLOG_DECLARE_CATEGORY(GBA_HW);
|
||||
|
||||
#define EREADER_DOTCODE_STRIDE 1420
|
||||
#define EREADER_DOTCODE_SIZE (EREADER_DOTCODE_STRIDE * 40)
|
||||
#define EREADER_CARDS_MAX 16
|
||||
|
||||
#define IS_GPIO_REGISTER(reg) ((reg) == GPIO_REG_DATA || (reg) == GPIO_REG_DIRECTION || (reg) == GPIO_REG_CONTROL)
|
||||
|
||||
struct GBARTCGenericSource {
|
||||
|
@ -99,57 +95,8 @@ struct GBARTC {
|
|||
uint8_t time[7];
|
||||
};
|
||||
|
||||
struct GBAGBPKeyCallback {
|
||||
struct mKeyCallback d;
|
||||
struct GBACartridgeHardware* p;
|
||||
};
|
||||
|
||||
struct GBAGBPSIODriver {
|
||||
struct GBASIODriver d;
|
||||
struct GBACartridgeHardware* p;
|
||||
};
|
||||
|
||||
DECL_BITFIELD(GPIOPin, uint16_t);
|
||||
|
||||
DECL_BITFIELD(EReaderControl0, uint8_t);
|
||||
DECL_BIT(EReaderControl0, Data, 0);
|
||||
DECL_BIT(EReaderControl0, Clock, 1);
|
||||
DECL_BIT(EReaderControl0, Direction, 2);
|
||||
DECL_BIT(EReaderControl0, LedEnable, 3);
|
||||
DECL_BIT(EReaderControl0, Scan, 4);
|
||||
DECL_BIT(EReaderControl0, Phi, 5);
|
||||
DECL_BIT(EReaderControl0, PowerEnable, 6);
|
||||
DECL_BITFIELD(EReaderControl1, uint8_t);
|
||||
DECL_BIT(EReaderControl1, Scanline, 1);
|
||||
DECL_BIT(EReaderControl1, Unk1, 4);
|
||||
DECL_BIT(EReaderControl1, Voltage, 5);
|
||||
|
||||
enum EReaderStateMachine {
|
||||
EREADER_SERIAL_INACTIVE = 0,
|
||||
EREADER_SERIAL_STARTING,
|
||||
EREADER_SERIAL_BIT_0,
|
||||
EREADER_SERIAL_BIT_1,
|
||||
EREADER_SERIAL_BIT_2,
|
||||
EREADER_SERIAL_BIT_3,
|
||||
EREADER_SERIAL_BIT_4,
|
||||
EREADER_SERIAL_BIT_5,
|
||||
EREADER_SERIAL_BIT_6,
|
||||
EREADER_SERIAL_BIT_7,
|
||||
EREADER_SERIAL_END_BIT,
|
||||
};
|
||||
|
||||
enum EReaderCommand {
|
||||
EREADER_COMMAND_IDLE = 0, // TODO: Verify on hardware
|
||||
EREADER_COMMAND_WRITE_DATA = 1,
|
||||
EREADER_COMMAND_SET_INDEX = 0x22,
|
||||
EREADER_COMMAND_READ_DATA = 0x23,
|
||||
};
|
||||
|
||||
struct EReaderCard {
|
||||
void* data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct GBACartridgeHardware {
|
||||
struct GBA* p;
|
||||
uint32_t devices;
|
||||
|
@ -171,30 +118,6 @@ struct GBACartridgeHardware {
|
|||
uint16_t tiltX;
|
||||
uint16_t tiltY;
|
||||
int tiltState;
|
||||
|
||||
unsigned gbpInputsPosted;
|
||||
int gbpTxPosition;
|
||||
struct mTimingEvent gbpNextEvent;
|
||||
struct GBAGBPKeyCallback gbpCallback;
|
||||
struct GBAGBPSIODriver gbpDriver;
|
||||
|
||||
uint16_t eReaderData[44];
|
||||
uint8_t eReaderSerial[92];
|
||||
uint16_t eReaderRegisterUnk;
|
||||
uint16_t eReaderRegisterReset;
|
||||
EReaderControl0 eReaderRegisterControl0;
|
||||
EReaderControl1 eReaderRegisterControl1;
|
||||
uint16_t eReaderRegisterLed;
|
||||
|
||||
// TODO: Serialize these
|
||||
enum EReaderStateMachine eReaderState;
|
||||
enum EReaderCommand eReaderCommand;
|
||||
uint8_t eReaderActiveRegister;
|
||||
uint8_t eReaderByte;
|
||||
int eReaderX;
|
||||
int eReaderY;
|
||||
uint8_t* eReaderDots;
|
||||
struct EReaderCard eReaderCards[EREADER_CARDS_MAX];
|
||||
};
|
||||
|
||||
void GBAHardwareInit(struct GBACartridgeHardware* gpio, uint16_t* gpioBase);
|
||||
|
@ -213,16 +136,7 @@ void GBAHardwareGPIOWrite(struct GBACartridgeHardware* gpio, uint32_t address, u
|
|||
void GBAHardwareTiltWrite(struct GBACartridgeHardware* gpio, uint32_t address, uint8_t value);
|
||||
uint8_t GBAHardwareTiltRead(struct GBACartridgeHardware* gpio, uint32_t address);
|
||||
|
||||
struct GBAVideo;
|
||||
void GBAHardwarePlayerUpdate(struct GBA* gba);
|
||||
bool GBAHardwarePlayerCheckScreen(const struct GBAVideo* video);
|
||||
|
||||
void GBAHardwareInitEReader(struct GBACartridgeHardware* hw);
|
||||
void GBAHardwareEReaderWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value);
|
||||
void GBAHardwareEReaderWriteFlash(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value);
|
||||
uint16_t GBAHardwareEReaderRead(struct GBACartridgeHardware* hw, uint32_t address);
|
||||
uint8_t GBAHardwareEReaderReadFlash(struct GBACartridgeHardware* hw, uint32_t address);
|
||||
void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, size_t size);
|
||||
void GBARTCGenericSourceInit(struct GBARTCGenericSource* rtc, struct GBA* gba);
|
||||
|
||||
struct GBASerializedState;
|
||||
void GBAHardwareSerialize(const struct GBACartridgeHardware* gpio, struct GBASerializedState* state);
|
|
@ -14,10 +14,11 @@ CXX_GUARD_START
|
|||
|
||||
#include <mgba/internal/arm/arm.h>
|
||||
#include <mgba/internal/gba/dma.h>
|
||||
#include <mgba/internal/gba/hardware.h>
|
||||
#include <mgba/internal/gba/savedata.h>
|
||||
#include <mgba/internal/gba/vfame.h>
|
||||
#include <mgba/internal/gba/matrix.h>
|
||||
#include <mgba/internal/gba/cart/ereader.h>
|
||||
#include <mgba/internal/gba/cart/gpio.h>
|
||||
#include <mgba/internal/gba/cart/matrix.h>
|
||||
#include <mgba/internal/gba/cart/vfame.h>
|
||||
|
||||
mLOG_DECLARE_CATEGORY(GBA_MEM);
|
||||
|
||||
|
@ -108,6 +109,7 @@ struct GBAMemory {
|
|||
struct GBASavedata savedata;
|
||||
struct GBAVFameCart vfame;
|
||||
struct GBAMatrix matrix;
|
||||
struct GBACartEReader ereader;
|
||||
size_t romSize;
|
||||
uint32_t romMask;
|
||||
uint16_t romID;
|
||||
|
|
|
@ -10,8 +10,9 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
#include <mgba/gba/interface.h>
|
||||
#include <mgba/core/log.h>
|
||||
#include <mgba/gba/interface.h>
|
||||
#include <mgba/internal/gba/sio/gbp.h>
|
||||
|
||||
#define MAX_GBAS 4
|
||||
|
||||
|
@ -69,6 +70,8 @@ struct GBASIO {
|
|||
|
||||
uint16_t rcnt;
|
||||
uint16_t siocnt;
|
||||
|
||||
struct GBASIOPlayer gbp;
|
||||
};
|
||||
|
||||
void GBASIOInit(struct GBASIO* sio);
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/* Copyright (c) 2013-2021 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef GBA_GBP_H
|
||||
#define GBA_GBP_H
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
CXX_GUARD_START
|
||||
|
||||
struct GBASIOPlayer;
|
||||
struct GBASIOPlayerKeyCallback {
|
||||
struct mKeyCallback d;
|
||||
struct GBASIOPlayer* p;
|
||||
};
|
||||
|
||||
struct GBASIOPlayer {
|
||||
struct GBASIODriver d;
|
||||
struct GBA* p;
|
||||
unsigned inputsPosted;
|
||||
int txPosition;
|
||||
struct mTimingEvent event;
|
||||
struct GBASIOPlayerKeyCallback callback;
|
||||
};
|
||||
|
||||
void GBASIOPlayerInit(struct GBASIOPlayer* gbp);
|
||||
void GBASIOPlayerReset(struct GBASIOPlayer* gbp);
|
||||
|
||||
struct GBAVideo;
|
||||
void GBASIOPlayerUpdate(struct GBA* gba);
|
||||
bool GBASIOPlayerCheckScreen(const struct GBAVideo* video);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
#include <mgba/core/interface.h>
|
||||
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/version.h>
|
||||
|
||||
|
@ -32,6 +34,54 @@ CXX_GUARD_START
|
|||
#define FFMPEG_USE_PACKET_UNREF
|
||||
#endif
|
||||
|
||||
static inline enum AVPixelFormat mColorFormatToFFmpegPixFmt(enum mColorFormat format) {
|
||||
switch (format) {
|
||||
#ifndef USE_LIBAV
|
||||
case mCOLOR_XRGB8:
|
||||
return AV_PIX_FMT_0RGB;
|
||||
case mCOLOR_XBGR8:
|
||||
return AV_PIX_FMT_0BGR;
|
||||
case mCOLOR_RGBX8:
|
||||
return AV_PIX_FMT_RGB0;
|
||||
case mCOLOR_BGRX8:
|
||||
return AV_PIX_FMT_BGR0;
|
||||
#else
|
||||
case mCOLOR_XRGB8:
|
||||
return AV_PIX_FMT_ARGB;
|
||||
case mCOLOR_XBGR8:
|
||||
return AV_PIX_FMT_ABGR;
|
||||
case mCOLOR_RGBX8:
|
||||
return AV_PIX_FMT_RGBA;
|
||||
case mCOLOR_BGRX8:
|
||||
return AV_PIX_FMT_BGRA;
|
||||
#endif
|
||||
case mCOLOR_ARGB8:
|
||||
return AV_PIX_FMT_ARGB;
|
||||
case mCOLOR_ABGR8:
|
||||
return AV_PIX_FMT_ABGR;
|
||||
case mCOLOR_RGBA8:
|
||||
return AV_PIX_FMT_RGBA;
|
||||
case mCOLOR_BGRA8:
|
||||
return AV_PIX_FMT_BGRA;
|
||||
case mCOLOR_RGB5:
|
||||
return AV_PIX_FMT_RGB555;
|
||||
case mCOLOR_BGR5:
|
||||
return AV_PIX_FMT_BGR555;
|
||||
case mCOLOR_RGB565:
|
||||
return AV_PIX_FMT_RGB565;
|
||||
case mCOLOR_BGR565:
|
||||
return AV_PIX_FMT_BGR565;
|
||||
case mCOLOR_RGB8:
|
||||
return AV_PIX_FMT_RGB24;
|
||||
case mCOLOR_BGR8:
|
||||
return AV_PIX_FMT_BGR24;
|
||||
case mCOLOR_L8:
|
||||
return AV_PIX_FMT_GRAY8;
|
||||
default:
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/* Copyright (c) 2013-2021 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "ffmpeg-scale.h"
|
||||
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
static const int _qualityToFlags[] = {
|
||||
SWS_POINT,
|
||||
SWS_FAST_BILINEAR,
|
||||
SWS_BILINEAR,
|
||||
SWS_BICUBIC,
|
||||
SWS_LANCZOS,
|
||||
SWS_SINC,
|
||||
};
|
||||
|
||||
void FFmpegScale(const void* input, int iwidth, int iheight, unsigned istride,
|
||||
void* output, int owidth, int oheight, unsigned ostride,
|
||||
enum mColorFormat format, int quality) {
|
||||
enum AVPixelFormat pixFormat = mColorFormatToFFmpegPixFmt(format);
|
||||
int flags;
|
||||
if (quality < 0) {
|
||||
quality = 0;
|
||||
} else if ((unsigned) quality >= sizeof(_qualityToFlags) / sizeof(_qualityToFlags[0])) {
|
||||
quality = sizeof(_qualityToFlags) / sizeof(_qualityToFlags[0]) - 1;
|
||||
}
|
||||
flags = _qualityToFlags[quality];
|
||||
|
||||
struct SwsContext* scaleContext = sws_getContext(iwidth, iheight, pixFormat,
|
||||
owidth, oheight, pixFormat,
|
||||
flags, 0, 0, 0);
|
||||
sws_scale(scaleContext, (const uint8_t* const*) &input, (const int*) &istride, 0, iheight, (uint8_t* const*) &output, (const int*) &ostride);
|
||||
sws_freeContext(scaleContext);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/* Copyright (c) 2013-2021 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef FFMPEG_SCALE
|
||||
#define FFMPEG_SCALE
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
CXX_GUARD_START
|
||||
|
||||
#include "feature/ffmpeg/ffmpeg-common.h"
|
||||
|
||||
void FFmpegScale(const void* input, int iwidth, int iheight, unsigned istride,
|
||||
void* output, int owidth, int oheight, unsigned ostride,
|
||||
enum mColorFormat format, int quality);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
|
@ -12,7 +12,7 @@ CXX_GUARD_START
|
|||
|
||||
#include <mgba/core/config.h>
|
||||
#include "feature/gui/remap.h"
|
||||
#include <mgba/internal/gba/hardware.h>
|
||||
#include <mgba/gba/interface.h>
|
||||
#include <mgba-util/circle-buffer.h>
|
||||
#include <mgba-util/gui.h>
|
||||
#include <mgba-util/threading.h>
|
||||
|
|
|
@ -3,19 +3,20 @@ set(SOURCE_FILES
|
|||
../gb/audio.c
|
||||
audio.c
|
||||
bios.c
|
||||
cart/ereader.c
|
||||
cart/gpio.c
|
||||
cart/matrix.c
|
||||
cart/vfame.c
|
||||
cheats.c
|
||||
cheats/codebreaker.c
|
||||
cheats/gameshark.c
|
||||
cheats/parv3.c
|
||||
core.c
|
||||
dma.c
|
||||
ereader.c
|
||||
gba.c
|
||||
hardware.c
|
||||
hle-bios.c
|
||||
input.c
|
||||
io.c
|
||||
matrix.c
|
||||
memory.c
|
||||
overrides.c
|
||||
renderers/cache-set.c
|
||||
|
@ -29,13 +30,13 @@ set(SOURCE_FILES
|
|||
serialize.c
|
||||
sharkport.c
|
||||
sio.c
|
||||
sio/gbp.c
|
||||
sio/joybus.c
|
||||
timer.c
|
||||
vfame.c
|
||||
video.c)
|
||||
|
||||
set(SIO_FILES
|
||||
sio/dolphin.c
|
||||
sio/joybus.c
|
||||
sio/lockstep.c)
|
||||
|
||||
set(EXTRA_FILES
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/internal/gba/hardware.h>
|
||||
#include <mgba/internal/gba/cart/ereader.h>
|
||||
|
||||
#include <mgba/internal/arm/macros.h>
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
|
@ -12,11 +12,12 @@
|
|||
|
||||
#define EREADER_BLOCK_SIZE 40
|
||||
|
||||
static void _eReaderReset(struct GBACartridgeHardware* hw);
|
||||
static void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value);
|
||||
static void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value);
|
||||
static void _eReaderReadData(struct GBACartridgeHardware* hw);
|
||||
static void _eReaderReset(struct GBACartEReader* ereader);
|
||||
static void _eReaderWriteControl0(struct GBACartEReader* ereader, uint8_t value);
|
||||
static void _eReaderWriteControl1(struct GBACartEReader* ereader, uint8_t value);
|
||||
static void _eReaderReadData(struct GBACartEReader* ereader);
|
||||
static void _eReaderReedSolomon(const uint8_t* input, uint8_t* output);
|
||||
static void _eReaderScanCard(struct GBACartEReader* ereader);
|
||||
|
||||
const int EREADER_NYBBLE_5BIT[16][5] = {
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
|
@ -161,30 +162,46 @@ static const uint8_t RS_GG[] = {
|
|||
};
|
||||
|
||||
|
||||
void GBAHardwareInitEReader(struct GBACartridgeHardware* hw) {
|
||||
hw->devices |= HW_EREADER;
|
||||
_eReaderReset(hw);
|
||||
void GBACartEReaderInit(struct GBACartEReader* ereader) {
|
||||
ereader->p->memory.hw.devices |= HW_EREADER;
|
||||
_eReaderReset(ereader);
|
||||
|
||||
if (hw->p->memory.savedata.data[0xD000] == 0xFF) {
|
||||
memset(&hw->p->memory.savedata.data[0xD000], 0, 0x1000);
|
||||
memcpy(&hw->p->memory.savedata.data[0xD000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE));
|
||||
if (ereader->p->memory.savedata.data[0xD000] == 0xFF) {
|
||||
memset(&ereader->p->memory.savedata.data[0xD000], 0, 0x1000);
|
||||
memcpy(&ereader->p->memory.savedata.data[0xD000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE));
|
||||
}
|
||||
if (hw->p->memory.savedata.data[0xE000] == 0xFF) {
|
||||
memset(&hw->p->memory.savedata.data[0xE000], 0, 0x1000);
|
||||
memcpy(&hw->p->memory.savedata.data[0xE000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE));
|
||||
if (ereader->p->memory.savedata.data[0xE000] == 0xFF) {
|
||||
memset(&ereader->p->memory.savedata.data[0xE000], 0, 0x1000);
|
||||
memcpy(&ereader->p->memory.savedata.data[0xE000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE));
|
||||
}
|
||||
}
|
||||
|
||||
void GBAHardwareEReaderWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
|
||||
void GBACartEReaderDeinit(struct GBACartEReader* ereader) {
|
||||
if (ereader->dots) {
|
||||
mappedMemoryFree(ereader->dots, EREADER_DOTCODE_SIZE);
|
||||
ereader->dots = NULL;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < EREADER_CARDS_MAX; ++i) {
|
||||
if (!ereader->cards[i].data) {
|
||||
continue;
|
||||
}
|
||||
free(ereader->cards[i].data);
|
||||
ereader->cards[i].data = NULL;
|
||||
ereader->cards[i].size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GBACartEReaderWrite(struct GBACartEReader* ereader, uint32_t address, uint16_t value) {
|
||||
address &= 0x700FF;
|
||||
switch (address >> 17) {
|
||||
case 0:
|
||||
hw->eReaderRegisterUnk = value & 0xF;
|
||||
ereader->registerUnk = value & 0xF;
|
||||
break;
|
||||
case 1:
|
||||
hw->eReaderRegisterReset = (value & 0x8A) | 4;
|
||||
ereader->registerReset = (value & 0x8A) | 4;
|
||||
if (value & 2) {
|
||||
_eReaderReset(hw);
|
||||
_eReaderReset(ereader);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
|
@ -195,54 +212,54 @@ void GBAHardwareEReaderWrite(struct GBACartridgeHardware* hw, uint32_t address,
|
|||
}
|
||||
}
|
||||
|
||||
void GBAHardwareEReaderWriteFlash(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) {
|
||||
void GBACartEReaderWriteFlash(struct GBACartEReader* ereader, uint32_t address, uint8_t value) {
|
||||
address &= 0xFFFF;
|
||||
switch (address) {
|
||||
case 0xFFB0:
|
||||
_eReaderWriteControl0(hw, value);
|
||||
_eReaderWriteControl0(ereader, value);
|
||||
break;
|
||||
case 0xFFB1:
|
||||
_eReaderWriteControl1(hw, value);
|
||||
_eReaderWriteControl1(ereader, value);
|
||||
break;
|
||||
case 0xFFB2:
|
||||
hw->eReaderRegisterLed &= 0xFF00;
|
||||
hw->eReaderRegisterLed |= value;
|
||||
ereader->registerLed &= 0xFF00;
|
||||
ereader->registerLed |= value;
|
||||
break;
|
||||
case 0xFFB3:
|
||||
hw->eReaderRegisterLed &= 0x00FF;
|
||||
hw->eReaderRegisterLed |= value << 8;
|
||||
ereader->registerLed &= 0x00FF;
|
||||
ereader->registerLed |= value << 8;
|
||||
break;
|
||||
default:
|
||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader write to flash: %04X:%02X", address, value);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t GBAHardwareEReaderRead(struct GBACartridgeHardware* hw, uint32_t address) {
|
||||
uint16_t GBACartEReaderRead(struct GBACartEReader* ereader, uint32_t address) {
|
||||
address &= 0x700FF;
|
||||
uint16_t value;
|
||||
switch (address >> 17) {
|
||||
case 0:
|
||||
return hw->eReaderRegisterUnk;
|
||||
return ereader->registerUnk;
|
||||
case 1:
|
||||
return hw->eReaderRegisterReset;
|
||||
return ereader->registerReset;
|
||||
case 2:
|
||||
if (address > 0x40088) {
|
||||
return 0;
|
||||
}
|
||||
LOAD_16(value, address & 0xFE, hw->eReaderData);
|
||||
LOAD_16(value, address & 0xFE, ereader->data);
|
||||
return value;
|
||||
}
|
||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader read: %05X", address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t GBAHardwareEReaderReadFlash(struct GBACartridgeHardware* hw, uint32_t address) {
|
||||
uint8_t GBACartEReaderReadFlash(struct GBACartEReader* ereader, uint32_t address) {
|
||||
address &= 0xFFFF;
|
||||
switch (address) {
|
||||
case 0xFFB0:
|
||||
return hw->eReaderRegisterControl0;
|
||||
return ereader->registerControl0;
|
||||
case 0xFFB1:
|
||||
return hw->eReaderRegisterControl1;
|
||||
return ereader->registerControl1;
|
||||
default:
|
||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader read from flash: %04X", address);
|
||||
return 0;
|
||||
|
@ -329,12 +346,12 @@ static void _eReaderReedSolomon(const uint8_t* input, uint8_t* output) {
|
|||
}
|
||||
}
|
||||
|
||||
void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, size_t size) {
|
||||
if (!hw->eReaderDots) {
|
||||
hw->eReaderDots = anonymousMemoryMap(EREADER_DOTCODE_SIZE);
|
||||
void GBACartEReaderScan(struct GBACartEReader* ereader, const void* data, size_t size) {
|
||||
if (!ereader->dots) {
|
||||
ereader->dots = anonymousMemoryMap(EREADER_DOTCODE_SIZE);
|
||||
}
|
||||
hw->eReaderX = -24;
|
||||
memset(hw->eReaderDots, 0, EREADER_DOTCODE_SIZE);
|
||||
ereader->scanX = -24;
|
||||
memset(ereader->dots, 0, EREADER_DOTCODE_SIZE);
|
||||
|
||||
uint8_t blockRS[44][0x10];
|
||||
uint8_t block0[0x30];
|
||||
|
@ -386,7 +403,7 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s
|
|||
size_t x;
|
||||
for (i = 0; i < 40; ++i) {
|
||||
const uint8_t* line = &cdata[(i + 2) * blocks];
|
||||
uint8_t* origin = &hw->eReaderDots[EREADER_DOTCODE_STRIDE * i + 200];
|
||||
uint8_t* origin = &ereader->dots[EREADER_DOTCODE_STRIDE * i + 200];
|
||||
for (x = 0; x < blocks; ++x) {
|
||||
uint8_t byte = line[x];
|
||||
if (x == 123) {
|
||||
|
@ -406,7 +423,7 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s
|
|||
}
|
||||
|
||||
for (i = 0; i < blocks + 1; ++i) {
|
||||
uint8_t* origin = &hw->eReaderDots[35 * i + 200];
|
||||
uint8_t* origin = &ereader->dots[35 * i + 200];
|
||||
_eReaderAnchor(&origin[EREADER_DOTCODE_STRIDE * 0]);
|
||||
_eReaderAnchor(&origin[EREADER_DOTCODE_STRIDE * 35]);
|
||||
_eReaderAddress(origin, base + i);
|
||||
|
@ -461,7 +478,7 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s
|
|||
size_t byteOffset = 0;
|
||||
for (i = 0; i < blocks; ++i) {
|
||||
uint8_t block[1040];
|
||||
uint8_t* origin = &hw->eReaderDots[35 * i + 200];
|
||||
uint8_t* origin = &ereader->dots[35 * i + 200];
|
||||
_eReaderAlignment(&origin[EREADER_DOTCODE_STRIDE * 2]);
|
||||
_eReaderAlignment(&origin[EREADER_DOTCODE_STRIDE * 37]);
|
||||
|
||||
|
@ -532,155 +549,132 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s
|
|||
}
|
||||
}
|
||||
|
||||
void _eReaderReset(struct GBACartridgeHardware* hw) {
|
||||
memset(hw->eReaderData, 0, sizeof(hw->eReaderData));
|
||||
hw->eReaderRegisterUnk = 0;
|
||||
hw->eReaderRegisterReset = 4;
|
||||
hw->eReaderRegisterControl0 = 0;
|
||||
hw->eReaderRegisterControl1 = 0x80;
|
||||
hw->eReaderRegisterLed = 0;
|
||||
hw->eReaderState = 0;
|
||||
hw->eReaderActiveRegister = 0;
|
||||
void _eReaderReset(struct GBACartEReader* ereader) {
|
||||
memset(ereader->data, 0, sizeof(ereader->data));
|
||||
ereader->registerUnk = 0;
|
||||
ereader->registerReset = 4;
|
||||
ereader->registerControl0 = 0;
|
||||
ereader->registerControl1 = 0x80;
|
||||
ereader->registerLed = 0;
|
||||
ereader->state = 0;
|
||||
ereader->activeRegister = 0;
|
||||
}
|
||||
|
||||
void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value) {
|
||||
void _eReaderWriteControl0(struct GBACartEReader* ereader, uint8_t value) {
|
||||
EReaderControl0 control = value & 0x7F;
|
||||
EReaderControl0 oldControl = hw->eReaderRegisterControl0;
|
||||
if (hw->eReaderState == EREADER_SERIAL_INACTIVE) {
|
||||
EReaderControl0 oldControl = ereader->registerControl0;
|
||||
if (ereader->state == EREADER_SERIAL_INACTIVE) {
|
||||
if (EReaderControl0IsClock(oldControl) && EReaderControl0IsData(oldControl) && !EReaderControl0IsData(control)) {
|
||||
hw->eReaderState = EREADER_SERIAL_STARTING;
|
||||
ereader->state = EREADER_SERIAL_STARTING;
|
||||
}
|
||||
} else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && EReaderControl0IsData(control)) {
|
||||
hw->eReaderState = EREADER_SERIAL_INACTIVE;
|
||||
ereader->state = EREADER_SERIAL_INACTIVE;
|
||||
|
||||
} else if (hw->eReaderState == EREADER_SERIAL_STARTING) {
|
||||
} else if (ereader->state == EREADER_SERIAL_STARTING) {
|
||||
if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && !EReaderControl0IsClock(control)) {
|
||||
hw->eReaderState = EREADER_SERIAL_BIT_0;
|
||||
hw->eReaderCommand = EREADER_COMMAND_IDLE;
|
||||
ereader->state = EREADER_SERIAL_BIT_0;
|
||||
ereader->command = EREADER_COMMAND_IDLE;
|
||||
}
|
||||
} else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsClock(control)) {
|
||||
mLOG(GBA_HW, DEBUG, "[e-Reader] Serial falling edge: %c %i", EReaderControl0IsDirection(control) ? '>' : '<', EReaderControl0GetData(control));
|
||||
// TODO: Improve direction control
|
||||
if (EReaderControl0IsDirection(control)) {
|
||||
hw->eReaderByte |= EReaderControl0GetData(control) << (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0));
|
||||
++hw->eReaderState;
|
||||
if (hw->eReaderState == EREADER_SERIAL_END_BIT) {
|
||||
mLOG(GBA_HW, DEBUG, "[e-Reader] Wrote serial byte: %02x", hw->eReaderByte);
|
||||
switch (hw->eReaderCommand) {
|
||||
ereader->byte |= EReaderControl0GetData(control) << (7 - (ereader->state - EREADER_SERIAL_BIT_0));
|
||||
++ereader->state;
|
||||
if (ereader->state == EREADER_SERIAL_END_BIT) {
|
||||
mLOG(GBA_HW, DEBUG, "[e-Reader] Wrote serial byte: %02x", ereader->byte);
|
||||
switch (ereader->command) {
|
||||
case EREADER_COMMAND_IDLE:
|
||||
hw->eReaderCommand = hw->eReaderByte;
|
||||
ereader->command = ereader->byte;
|
||||
break;
|
||||
case EREADER_COMMAND_SET_INDEX:
|
||||
hw->eReaderActiveRegister = hw->eReaderByte;
|
||||
hw->eReaderCommand = EREADER_COMMAND_WRITE_DATA;
|
||||
ereader->activeRegister = ereader->byte;
|
||||
ereader->command = EREADER_COMMAND_WRITE_DATA;
|
||||
break;
|
||||
case EREADER_COMMAND_WRITE_DATA:
|
||||
switch (hw->eReaderActiveRegister & 0x7F) {
|
||||
switch (ereader->activeRegister & 0x7F) {
|
||||
case 0:
|
||||
case 0x57:
|
||||
case 0x58:
|
||||
case 0x59:
|
||||
case 0x5A:
|
||||
// Read-only
|
||||
mLOG(GBA_HW, GAME_ERROR, "Writing to read-only e-Reader serial register: %02X", hw->eReaderActiveRegister);
|
||||
mLOG(GBA_HW, GAME_ERROR, "Writing to read-only e-Reader serial register: %02X", ereader->activeRegister);
|
||||
break;
|
||||
default:
|
||||
if ((hw->eReaderActiveRegister & 0x7F) > 0x5A) {
|
||||
mLOG(GBA_HW, GAME_ERROR, "Writing to non-existent e-Reader serial register: %02X", hw->eReaderActiveRegister);
|
||||
if ((ereader->activeRegister & 0x7F) > 0x5A) {
|
||||
mLOG(GBA_HW, GAME_ERROR, "Writing to non-existent e-Reader serial register: %02X", ereader->activeRegister);
|
||||
break;
|
||||
}
|
||||
hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] = hw->eReaderByte;
|
||||
ereader->serial[ereader->activeRegister & 0x7F] = ereader->byte;
|
||||
break;
|
||||
}
|
||||
++hw->eReaderActiveRegister;
|
||||
++ereader->activeRegister;
|
||||
break;
|
||||
default:
|
||||
mLOG(GBA_HW, ERROR, "Hit undefined state %02X in e-Reader state machine", hw->eReaderCommand);
|
||||
mLOG(GBA_HW, ERROR, "Hit undefined state %02X in e-Reader state machine", ereader->command);
|
||||
break;
|
||||
}
|
||||
hw->eReaderState = EREADER_SERIAL_BIT_0;
|
||||
hw->eReaderByte = 0;
|
||||
ereader->state = EREADER_SERIAL_BIT_0;
|
||||
ereader->byte = 0;
|
||||
}
|
||||
} else if (hw->eReaderCommand == EREADER_COMMAND_READ_DATA) {
|
||||
int bit = hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] >> (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0));
|
||||
} else if (ereader->command == EREADER_COMMAND_READ_DATA) {
|
||||
int bit = ereader->serial[ereader->activeRegister & 0x7F] >> (7 - (ereader->state - EREADER_SERIAL_BIT_0));
|
||||
control = EReaderControl0SetData(control, bit);
|
||||
++hw->eReaderState;
|
||||
if (hw->eReaderState == EREADER_SERIAL_END_BIT) {
|
||||
++hw->eReaderActiveRegister;
|
||||
mLOG(GBA_HW, DEBUG, "[e-Reader] Read serial byte: %02x", hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F]);
|
||||
++ereader->state;
|
||||
if (ereader->state == EREADER_SERIAL_END_BIT) {
|
||||
++ereader->activeRegister;
|
||||
mLOG(GBA_HW, DEBUG, "[e-Reader] Read serial byte: %02x", ereader->serial[ereader->activeRegister & 0x7F]);
|
||||
}
|
||||
}
|
||||
} else if (!EReaderControl0IsDirection(control)) {
|
||||
// Clear the error bit
|
||||
control = EReaderControl0ClearData(control);
|
||||
}
|
||||
hw->eReaderRegisterControl0 = control;
|
||||
ereader->registerControl0 = control;
|
||||
if (!EReaderControl0IsScan(oldControl) && EReaderControl0IsScan(control)) {
|
||||
if (hw->eReaderX > 1000) {
|
||||
if (hw->eReaderDots) {
|
||||
memset(hw->eReaderDots, 0, EREADER_DOTCODE_SIZE);
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < EREADER_CARDS_MAX; ++i) {
|
||||
if (!hw->eReaderCards[i].data) {
|
||||
continue;
|
||||
}
|
||||
GBAHardwareEReaderScan(hw, hw->eReaderCards[i].data, hw->eReaderCards[i].size);
|
||||
free(hw->eReaderCards[i].data);
|
||||
hw->eReaderCards[i].data = NULL;
|
||||
hw->eReaderCards[i].size = 0;
|
||||
break;
|
||||
}
|
||||
if (ereader->scanX > 1000) {
|
||||
_eReaderScanCard(ereader);
|
||||
}
|
||||
hw->eReaderX = 0;
|
||||
hw->eReaderY = 0;
|
||||
} else if (EReaderControl0IsLedEnable(control) && EReaderControl0IsScan(control) && !EReaderControl1IsScanline(hw->eReaderRegisterControl1)) {
|
||||
_eReaderReadData(hw);
|
||||
ereader->scanX = 0;
|
||||
ereader->scanY = 0;
|
||||
} else if (EReaderControl0IsLedEnable(control) && EReaderControl0IsScan(control) && !EReaderControl1IsScanline(ereader->registerControl1)) {
|
||||
_eReaderReadData(ereader);
|
||||
}
|
||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control0 write: %02X", value);
|
||||
}
|
||||
|
||||
void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value) {
|
||||
void _eReaderWriteControl1(struct GBACartEReader* ereader, uint8_t value) {
|
||||
EReaderControl1 control = (value & 0x32) | 0x80;
|
||||
hw->eReaderRegisterControl1 = control;
|
||||
if (EReaderControl0IsScan(hw->eReaderRegisterControl0) && !EReaderControl1IsScanline(control)) {
|
||||
++hw->eReaderY;
|
||||
if (hw->eReaderY == (hw->eReaderSerial[0x15] | (hw->eReaderSerial[0x14] << 8))) {
|
||||
hw->eReaderY = 0;
|
||||
if (hw->eReaderX < 3400) {
|
||||
hw->eReaderX += 210;
|
||||
ereader->registerControl1 = control;
|
||||
if (EReaderControl0IsScan(ereader->registerControl0) && !EReaderControl1IsScanline(control)) {
|
||||
++ereader->scanY;
|
||||
if (ereader->scanY == (ereader->serial[0x15] | (ereader->serial[0x14] << 8))) {
|
||||
ereader->scanY = 0;
|
||||
if (ereader->scanX < 3400) {
|
||||
ereader->scanX += 210;
|
||||
}
|
||||
}
|
||||
_eReaderReadData(hw);
|
||||
_eReaderReadData(ereader);
|
||||
}
|
||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control1 write: %02X", value);
|
||||
}
|
||||
|
||||
void _eReaderReadData(struct GBACartridgeHardware* hw) {
|
||||
memset(hw->eReaderData, 0, EREADER_BLOCK_SIZE);
|
||||
if (!hw->eReaderDots) {
|
||||
int i;
|
||||
for (i = 0; i < EREADER_CARDS_MAX; ++i) {
|
||||
if (!hw->eReaderCards[i].data) {
|
||||
continue;
|
||||
}
|
||||
GBAHardwareEReaderScan(hw, hw->eReaderCards[i].data, hw->eReaderCards[i].size);
|
||||
free(hw->eReaderCards[i].data);
|
||||
hw->eReaderCards[i].data = NULL;
|
||||
hw->eReaderCards[i].size = 0;
|
||||
break;
|
||||
}
|
||||
void _eReaderReadData(struct GBACartEReader* ereader) {
|
||||
memset(ereader->data, 0, EREADER_BLOCK_SIZE);
|
||||
if (!ereader->dots) {
|
||||
_eReaderScanCard(ereader);
|
||||
}
|
||||
if (hw->eReaderDots) {
|
||||
int y = hw->eReaderY - 10;
|
||||
if (ereader->dots) {
|
||||
int y = ereader->scanY - 10;
|
||||
if (y < 0 || y >= 120) {
|
||||
memset(hw->eReaderData, 0, EREADER_BLOCK_SIZE);
|
||||
memset(ereader->data, 0, EREADER_BLOCK_SIZE);
|
||||
} else {
|
||||
int i;
|
||||
uint8_t* origin = &hw->eReaderDots[EREADER_DOTCODE_STRIDE * (y / 3) + 16];
|
||||
uint8_t* origin = &ereader->dots[EREADER_DOTCODE_STRIDE * (y / 3) + 16];
|
||||
for (i = 0; i < 20; ++i) {
|
||||
uint16_t word = 0;
|
||||
int x = hw->eReaderX + i * 16;
|
||||
int x = ereader->scanX + i * 16;
|
||||
word |= origin[(x + 0) / 3] << 8;
|
||||
word |= origin[(x + 1) / 3] << 9;
|
||||
word |= origin[(x + 2) / 3] << 10;
|
||||
|
@ -697,29 +691,48 @@ void _eReaderReadData(struct GBACartridgeHardware* hw) {
|
|||
word |= origin[(x + 13) / 3] << 5;
|
||||
word |= origin[(x + 14) / 3] << 6;
|
||||
word |= origin[(x + 15) / 3] << 7;
|
||||
STORE_16(word, (19 - i) << 1, hw->eReaderData);
|
||||
STORE_16(word, (19 - i) << 1, ereader->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
hw->eReaderRegisterControl1 = EReaderControl1FillScanline(hw->eReaderRegisterControl1);
|
||||
if (EReaderControl0IsLedEnable(hw->eReaderRegisterControl0)) {
|
||||
uint16_t led = hw->eReaderRegisterLed * 2;
|
||||
ereader->registerControl1 = EReaderControl1FillScanline(ereader->registerControl1);
|
||||
if (EReaderControl0IsLedEnable(ereader->registerControl0)) {
|
||||
uint16_t led = ereader->registerLed * 2;
|
||||
if (led > 0x4000) {
|
||||
led = 0x4000;
|
||||
}
|
||||
GBARaiseIRQ(hw->p, IRQ_GAMEPAK, -led);
|
||||
GBARaiseIRQ(ereader->p, IRQ_GAMEPAK, -led);
|
||||
}
|
||||
}
|
||||
|
||||
void GBAEReaderQueueCard(struct GBA* gba, const void* data, size_t size) {
|
||||
|
||||
void _eReaderScanCard(struct GBACartEReader* ereader) {
|
||||
if (ereader->dots) {
|
||||
memset(ereader->dots, 0, EREADER_DOTCODE_SIZE);
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < EREADER_CARDS_MAX; ++i) {
|
||||
if (gba->memory.hw.eReaderCards[i].data) {
|
||||
if (!ereader->cards[i].data) {
|
||||
continue;
|
||||
}
|
||||
gba->memory.hw.eReaderCards[i].data = malloc(size);
|
||||
memcpy(gba->memory.hw.eReaderCards[i].data, data, size);
|
||||
gba->memory.hw.eReaderCards[i].size = size;
|
||||
GBACartEReaderScan(ereader, ereader->cards[i].data, ereader->cards[i].size);
|
||||
free(ereader->cards[i].data);
|
||||
ereader->cards[i].data = NULL;
|
||||
ereader->cards[i].size = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GBACartEReaderQueueCard(struct GBA* gba, const void* data, size_t size) {
|
||||
struct GBACartEReader* ereader = &gba->memory.ereader;
|
||||
int i;
|
||||
for (i = 0; i < EREADER_CARDS_MAX; ++i) {
|
||||
if (ereader->cards[i].data) {
|
||||
continue;
|
||||
}
|
||||
ereader->cards[i].data = malloc(size);
|
||||
memcpy(ereader->cards[i].data, data, size);
|
||||
ereader->cards[i].size = size;
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
||||
/* Copyright (c) 2013-2021 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/internal/gba/hardware.h>
|
||||
#include <mgba/internal/gba/cart/gpio.h>
|
||||
|
||||
#include <mgba/internal/arm/macros.h>
|
||||
#include <mgba/internal/gba/io.h>
|
||||
|
@ -29,10 +29,6 @@ static void _rumbleReadPins(struct GBACartridgeHardware* hw);
|
|||
|
||||
static void _lightReadPins(struct GBACartridgeHardware* hw);
|
||||
|
||||
static uint16_t _gbpRead(struct mKeyCallback*);
|
||||
static uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value);
|
||||
static void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate);
|
||||
|
||||
static const int RTC_BYTES[8] = {
|
||||
1, // Status register 1
|
||||
1, // Duty/alarm 1
|
||||
|
@ -46,22 +42,7 @@ static const int RTC_BYTES[8] = {
|
|||
|
||||
void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) {
|
||||
hw->gpioBase = base;
|
||||
hw->eReaderDots = NULL;
|
||||
memset(hw->eReaderCards, 0, sizeof(hw->eReaderCards));
|
||||
GBAHardwareClear(hw);
|
||||
|
||||
hw->gbpCallback.d.readKeys = _gbpRead;
|
||||
hw->gbpCallback.p = hw;
|
||||
hw->gbpDriver.d.init = 0;
|
||||
hw->gbpDriver.d.deinit = 0;
|
||||
hw->gbpDriver.d.load = 0;
|
||||
hw->gbpDriver.d.unload = 0;
|
||||
hw->gbpDriver.d.writeRegister = _gbpSioWriteRegister;
|
||||
hw->gbpDriver.p = hw;
|
||||
hw->gbpNextEvent.context = &hw->gbpDriver;
|
||||
hw->gbpNextEvent.name = "GBA SIO Game Boy Player";
|
||||
hw->gbpNextEvent.callback = _gbpSioProcessEvents;
|
||||
hw->gbpNextEvent.priority = 0x80;
|
||||
}
|
||||
|
||||
void GBAHardwareClear(struct GBACartridgeHardware* hw) {
|
||||
|
@ -69,24 +50,6 @@ void GBAHardwareClear(struct GBACartridgeHardware* hw) {
|
|||
hw->readWrite = GPIO_WRITE_ONLY;
|
||||
hw->pinState = 0;
|
||||
hw->direction = 0;
|
||||
|
||||
if (hw->eReaderDots) {
|
||||
mappedMemoryFree(hw->eReaderDots, EREADER_DOTCODE_SIZE);
|
||||
hw->eReaderDots = NULL;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < EREADER_CARDS_MAX; ++i) {
|
||||
if (!hw->eReaderCards[i].data) {
|
||||
continue;
|
||||
}
|
||||
free(hw->eReaderCards[i].data);
|
||||
hw->eReaderCards[i].data = NULL;
|
||||
hw->eReaderCards[i].size = 0;
|
||||
}
|
||||
|
||||
if (hw->p->sio.drivers.normal == &hw->gbpDriver.d) {
|
||||
GBASIOSetDriver(&hw->p->sio, 0, SIO_NORMAL_32);
|
||||
}
|
||||
}
|
||||
|
||||
void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
|
||||
|
@ -497,124 +460,10 @@ uint8_t GBAHardwareTiltRead(struct GBACartridgeHardware* hw, uint32_t address) {
|
|||
return 0xFF;
|
||||
}
|
||||
|
||||
// == Game Boy Player
|
||||
|
||||
static const uint8_t _logoPalette[] = {
|
||||
0xDF, 0xFF, 0x0C, 0x64, 0x0C, 0xE4, 0x2D, 0xE4, 0x4E, 0x64, 0x4E, 0xE4, 0x6E, 0xE4, 0xAF, 0x68,
|
||||
0xB0, 0xE8, 0xD0, 0x68, 0xF0, 0x68, 0x11, 0x69, 0x11, 0xE9, 0x32, 0x6D, 0x32, 0xED, 0x73, 0xED,
|
||||
0x93, 0x6D, 0x94, 0xED, 0xB4, 0x6D, 0xD5, 0xF1, 0xF5, 0x71, 0xF6, 0xF1, 0x16, 0x72, 0x57, 0x72,
|
||||
0x57, 0xF6, 0x78, 0x76, 0x78, 0xF6, 0x99, 0xF6, 0xB9, 0xF6, 0xD9, 0x76, 0xDA, 0xF6, 0x1B, 0x7B,
|
||||
0x1B, 0xFB, 0x3C, 0xFB, 0x5C, 0x7B, 0x7D, 0x7B, 0x7D, 0xFF, 0x9D, 0x7F, 0xBE, 0x7F, 0xFF, 0x7F,
|
||||
0x2D, 0x64, 0x8E, 0x64, 0x8F, 0xE8, 0xF1, 0xE8, 0x52, 0x6D, 0x73, 0x6D, 0xB4, 0xF1, 0x16, 0xF2,
|
||||
0x37, 0x72, 0x98, 0x76, 0xFA, 0x7A, 0xFA, 0xFA, 0x5C, 0xFB, 0xBE, 0xFF, 0xDE, 0x7F, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const uint32_t _logoHash = 0xEEDA6963;
|
||||
|
||||
static const uint32_t _gbpTxData[] = {
|
||||
0x0000494E, 0x0000494E,
|
||||
0xB6B1494E, 0xB6B1544E,
|
||||
0xABB1544E, 0xABB14E45,
|
||||
0xB1BA4E45, 0xB1BA4F44,
|
||||
0xB0BB4F44, 0xB0BB8002,
|
||||
0x10000010, 0x20000013,
|
||||
0x30000003
|
||||
};
|
||||
|
||||
bool GBAHardwarePlayerCheckScreen(const struct GBAVideo* video) {
|
||||
if (memcmp(video->palette, _logoPalette, sizeof(_logoPalette)) != 0) {
|
||||
return false;
|
||||
}
|
||||
uint32_t hash = hash32(&video->vram[0x4000], 0x4000, 0);
|
||||
return hash == _logoHash;
|
||||
}
|
||||
|
||||
void GBAHardwarePlayerUpdate(struct GBA* gba) {
|
||||
if (gba->memory.hw.devices & HW_GB_PLAYER) {
|
||||
if (GBAHardwarePlayerCheckScreen(&gba->video)) {
|
||||
++gba->memory.hw.gbpInputsPosted;
|
||||
gba->memory.hw.gbpInputsPosted %= 3;
|
||||
gba->keyCallback = &gba->memory.hw.gbpCallback.d;
|
||||
} else {
|
||||
// TODO: Save and restore
|
||||
gba->keyCallback = 0;
|
||||
}
|
||||
gba->memory.hw.gbpTxPosition = 0;
|
||||
return;
|
||||
}
|
||||
if (gba->keyCallback) {
|
||||
return;
|
||||
}
|
||||
if (GBAHardwarePlayerCheckScreen(&gba->video)) {
|
||||
gba->memory.hw.devices |= HW_GB_PLAYER;
|
||||
gba->memory.hw.gbpInputsPosted = 0;
|
||||
gba->keyCallback = &gba->memory.hw.gbpCallback.d;
|
||||
// TODO: Check if the SIO driver is actually used first
|
||||
GBASIOSetDriver(&gba->sio, &gba->memory.hw.gbpDriver.d, SIO_NORMAL_32);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t _gbpRead(struct mKeyCallback* callback) {
|
||||
struct GBAGBPKeyCallback* gbpCallback = (struct GBAGBPKeyCallback*) callback;
|
||||
if (gbpCallback->p->gbpInputsPosted == 2) {
|
||||
return 0xF0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
|
||||
struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
|
||||
if (address == REG_SIOCNT) {
|
||||
if (value & 0x0080) {
|
||||
uint32_t rx = gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] | (gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] << 16);
|
||||
if (gbp->p->gbpTxPosition < 12 && gbp->p->gbpTxPosition > 0) {
|
||||
// TODO: Check expected
|
||||
} else if (gbp->p->gbpTxPosition >= 12) {
|
||||
uint32_t mask = 0x33;
|
||||
// 0x00 = Stop
|
||||
// 0x11 = Hard Stop
|
||||
// 0x22 = Start
|
||||
if (gbp->p->p->rumble) {
|
||||
gbp->p->p->rumble->setRumble(gbp->p->p->rumble, (rx & mask) == 0x22);
|
||||
}
|
||||
}
|
||||
mTimingDeschedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent);
|
||||
mTimingSchedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent, 2048);
|
||||
}
|
||||
value &= 0x78FB;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) {
|
||||
UNUSED(timing);
|
||||
UNUSED(cyclesLate);
|
||||
struct GBAGBPSIODriver* gbp = user;
|
||||
uint32_t tx = 0;
|
||||
int txPosition = gbp->p->gbpTxPosition;
|
||||
if (txPosition > 16) {
|
||||
gbp->p->gbpTxPosition = 0;
|
||||
txPosition = 0;
|
||||
} else if (txPosition > 12) {
|
||||
txPosition = 12;
|
||||
}
|
||||
tx = _gbpTxData[txPosition];
|
||||
++gbp->p->gbpTxPosition;
|
||||
gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] = tx;
|
||||
gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] = tx >> 16;
|
||||
if (GBASIONormalIsIrq(gbp->d.p->siocnt)) {
|
||||
GBARaiseIRQ(gbp->p->p, IRQ_SIO, cyclesLate);
|
||||
}
|
||||
gbp->d.p->siocnt = GBASIONormalClearStart(gbp->d.p->siocnt);
|
||||
gbp->p->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt & ~0x0080;
|
||||
}
|
||||
|
||||
// == Serialization
|
||||
|
||||
void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) {
|
||||
GBASerializedHWFlags1 flags1 = 0;
|
||||
GBASerializedHWFlags2 flags2 = 0;
|
||||
flags1 = GBASerializedHWFlags1SetReadWrite(flags1, hw->readWrite);
|
||||
STORE_16(hw->pinState, 0, &state->hw.pinState);
|
||||
STORE_16(hw->direction, 0, &state->hw.pinDirection);
|
||||
|
@ -633,14 +482,19 @@ void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASeria
|
|||
flags1 = GBASerializedHWFlags1SetGyroEdge(flags1, hw->gyroEdge);
|
||||
STORE_16(hw->tiltX, 0, &state->hw.tiltSampleX);
|
||||
STORE_16(hw->tiltY, 0, &state->hw.tiltSampleY);
|
||||
flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState);
|
||||
flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter);
|
||||
state->hw.lightSample = hw->lightSample;
|
||||
flags1 = GBASerializedHWFlags1SetLightEdge(flags1, hw->lightEdge);
|
||||
flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->gbpInputsPosted);
|
||||
flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->gbpTxPosition);
|
||||
STORE_32(hw->gbpNextEvent.when - mTimingCurrentTime(&hw->p->timing), 0, &state->hw.gbpNextEvent);
|
||||
STORE_16(flags1, 0, &state->hw.flags1);
|
||||
|
||||
GBASerializedHWFlags2 flags2 = 0;
|
||||
flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState);
|
||||
flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter);
|
||||
|
||||
// GBP stuff is only here for legacy reasons
|
||||
flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->p->sio.gbp.inputsPosted);
|
||||
flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->p->sio.gbp.txPosition);
|
||||
STORE_32(hw->p->sio.gbp.event.when - mTimingCurrentTime(&hw->p->timing), 0, &state->hw.gbpNextEvent);
|
||||
|
||||
state->hw.flags2 = flags2;
|
||||
}
|
||||
|
||||
|
@ -669,15 +523,17 @@ void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASer
|
|||
hw->lightCounter = GBASerializedHWFlags1GetLightCounter(flags1);
|
||||
hw->lightSample = state->hw.lightSample;
|
||||
hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1);
|
||||
hw->gbpInputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2);
|
||||
hw->gbpTxPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2);
|
||||
|
||||
// GBP stuff is only here for legacy reasons
|
||||
hw->p->sio.gbp.inputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2);
|
||||
hw->p->sio.gbp.txPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2);
|
||||
|
||||
uint32_t when;
|
||||
LOAD_32(when, 0, &state->hw.gbpNextEvent);
|
||||
if (hw->devices & HW_GB_PLAYER) {
|
||||
GBASIOSetDriver(&hw->p->sio, &hw->gbpDriver.d, SIO_NORMAL_32);
|
||||
GBASIOSetDriver(&hw->p->sio, &hw->p->sio.gbp.d, SIO_NORMAL_32);
|
||||
if (hw->p->memory.io[REG_SIOCNT >> 1] & 0x0080) {
|
||||
mTimingSchedule(&hw->p->timing, &hw->gbpNextEvent, when);
|
||||
mTimingSchedule(&hw->p->timing, &hw->p->sio.gbp.event, when);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/internal/gba/matrix.h>
|
||||
#include <mgba/internal/gba/cart/matrix.h>
|
||||
|
||||
#include <mgba/internal/arm/macros.h>
|
||||
#include <mgba/internal/gba/gba.h>
|
|
@ -3,7 +3,7 @@
|
|||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/internal/gba/vfame.h>
|
||||
#include <mgba/internal/gba/cart/vfame.h>
|
||||
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
#include <mgba/internal/gba/memory.h>
|
|
@ -219,7 +219,7 @@ void GBAReset(struct ARMCore* cpu) {
|
|||
|
||||
// GB Player SIO control should not be engaged before detection, even if we already know it's GBP
|
||||
gba->memory.hw.devices &= ~HW_GB_PLAYER;
|
||||
if (gba->sio.drivers.normal == &gba->memory.hw.gbpDriver.d) {
|
||||
if (gba->sio.drivers.normal == &gba->sio.gbp.d) {
|
||||
GBASIOSetDriver(&gba->sio, NULL, SIO_NORMAL_32);
|
||||
}
|
||||
|
||||
|
@ -854,7 +854,7 @@ void GBAFrameEnded(struct GBA* gba) {
|
|||
}
|
||||
|
||||
if (gba->memory.hw.devices & (HW_GB_PLAYER | HW_GB_PLAYER_DETECTION)) {
|
||||
GBAHardwarePlayerUpdate(gba);
|
||||
GBASIOPlayerUpdate(gba);
|
||||
}
|
||||
|
||||
size_t c;
|
||||
|
|
|
@ -94,6 +94,10 @@ void GBAMemoryInit(struct GBA* gba) {
|
|||
|
||||
GBADMAInit(gba);
|
||||
GBAVFameInit(&gba->memory.vfame);
|
||||
|
||||
gba->memory.ereader.p = gba;
|
||||
gba->memory.ereader.dots = NULL;
|
||||
memset(gba->memory.ereader.cards, 0, sizeof(gba->memory.ereader.cards));
|
||||
}
|
||||
|
||||
void GBAMemoryDeinit(struct GBA* gba) {
|
||||
|
@ -107,6 +111,8 @@ void GBAMemoryDeinit(struct GBA* gba) {
|
|||
if (gba->memory.agbPrintBufferBackup) {
|
||||
mappedMemoryFree(gba->memory.agbPrintBufferBackup, SIZE_AGB_PRINT);
|
||||
}
|
||||
|
||||
GBACartEReaderDeinit(&gba->memory.ereader);
|
||||
}
|
||||
|
||||
void GBAMemoryReset(struct GBA* gba) {
|
||||
|
@ -588,7 +594,7 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
|||
if (memory->savedata.type == SAVEDATA_EEPROM || memory->savedata.type == SAVEDATA_EEPROM512) {
|
||||
value = GBASavedataReadEEPROM(&memory->savedata);
|
||||
} else if ((address & 0x0DFC0000) >= 0x0DF80000 && memory->hw.devices & HW_EREADER) {
|
||||
value = GBAHardwareEReaderRead(&memory->hw, address);
|
||||
value = GBACartEReaderRead(&memory->ereader, address);
|
||||
} else if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
|
||||
LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom);
|
||||
} else if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
|
||||
|
@ -704,7 +710,7 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
|||
break;
|
||||
}
|
||||
if (memory->hw.devices & HW_EREADER && (address & 0xE00FF80) >= 0xE00FF80) {
|
||||
value = GBAHardwareEReaderReadFlash(&memory->hw, address);
|
||||
value = GBACartEReaderReadFlash(&memory->ereader, address);
|
||||
} else if (memory->savedata.type == SAVEDATA_SRAM) {
|
||||
value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)];
|
||||
} else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
|
||||
|
@ -930,7 +936,6 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle
|
|||
if ((address & 0x00FFFFFF) >= AGB_PRINT_BASE) {
|
||||
uint32_t agbPrintAddr = address & 0x00FFFFFF;
|
||||
if (agbPrintAddr == AGB_PRINT_PROTECT) {
|
||||
bool wasProtected = memory->agbPrintProtect != 0x20;
|
||||
memory->agbPrintProtect = value;
|
||||
|
||||
if (!memory->agbPrintBuffer) {
|
||||
|
@ -966,7 +971,7 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle
|
|||
break;
|
||||
case REGION_CART2_EX:
|
||||
if ((address & 0x0DFC0000) >= 0x0DF80000 && memory->hw.devices & HW_EREADER) {
|
||||
GBAHardwareEReaderWrite(&memory->hw, address, value);
|
||||
GBACartEReaderWrite(&memory->ereader, address, value);
|
||||
break;
|
||||
} else if (memory->savedata.type == SAVEDATA_AUTODETECT) {
|
||||
mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
|
||||
|
@ -1053,7 +1058,7 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo
|
|||
}
|
||||
}
|
||||
if (memory->hw.devices & HW_EREADER && (address & 0xE00FF80) >= 0xE00FF80) {
|
||||
GBAHardwareEReaderWriteFlash(&memory->hw, address, value);
|
||||
GBACartEReaderWriteFlash(&memory->ereader, address, value);
|
||||
} else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
|
||||
GBASavedataWriteFlash(&memory->savedata, address, value);
|
||||
} else if (memory->savedata.type == SAVEDATA_SRAM) {
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#include <mgba/internal/gba/overrides.h>
|
||||
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
#include <mgba/internal/gba/hardware.h>
|
||||
#include <mgba/internal/gba/cart/ereader.h>
|
||||
#include <mgba/internal/gba/cart/gpio.h>
|
||||
|
||||
#include <mgba-util/configuration.h>
|
||||
|
||||
|
@ -347,7 +348,7 @@ void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* overri
|
|||
}
|
||||
|
||||
if (override->hardware & HW_EREADER) {
|
||||
GBAHardwareInitEReader(&gba->memory.hw);
|
||||
GBACartEReaderInit(&gba->memory.ereader);
|
||||
}
|
||||
|
||||
if (override->hardware & HW_GB_PLAYER_DETECTION) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
#include <mgba/internal/gba/io.h>
|
||||
#include <mgba/internal/gba/sio/gbp.h>
|
||||
|
||||
mLOG_DEFINE_CATEGORY(GBA_SIO, "GBA Serial I/O", "gba.sio");
|
||||
|
||||
|
@ -76,6 +77,10 @@ void GBASIOInit(struct GBASIO* sio) {
|
|||
sio->drivers.multiplayer = 0;
|
||||
sio->drivers.joybus = 0;
|
||||
sio->activeDriver = 0;
|
||||
|
||||
sio->gbp.p = sio->p;
|
||||
GBASIOPlayerInit(&sio->gbp);
|
||||
|
||||
GBASIOReset(sio);
|
||||
}
|
||||
|
||||
|
@ -103,6 +108,8 @@ void GBASIOReset(struct GBASIO* sio) {
|
|||
sio->mode = -1;
|
||||
sio->activeDriver = NULL;
|
||||
_switchMode(sio);
|
||||
|
||||
GBASIOPlayerReset(&sio->gbp);
|
||||
}
|
||||
|
||||
void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers) {
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
/* Copyright (c) 2013-2021 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/internal/gba/sio.h>
|
||||
|
||||
#include <mgba/internal/arm/macros.h>
|
||||
#include <mgba/internal/gba/io.h>
|
||||
#include <mgba/internal/gba/serialize.h>
|
||||
#include <mgba-util/formatting.h>
|
||||
#include <mgba-util/hash.h>
|
||||
#include <mgba-util/memory.h>
|
||||
|
||||
static uint16_t _gbpRead(struct mKeyCallback*);
|
||||
static uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value);
|
||||
static void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate);
|
||||
|
||||
static const uint8_t _logoPalette[] = {
|
||||
0xDF, 0xFF, 0x0C, 0x64, 0x0C, 0xE4, 0x2D, 0xE4, 0x4E, 0x64, 0x4E, 0xE4, 0x6E, 0xE4, 0xAF, 0x68,
|
||||
0xB0, 0xE8, 0xD0, 0x68, 0xF0, 0x68, 0x11, 0x69, 0x11, 0xE9, 0x32, 0x6D, 0x32, 0xED, 0x73, 0xED,
|
||||
0x93, 0x6D, 0x94, 0xED, 0xB4, 0x6D, 0xD5, 0xF1, 0xF5, 0x71, 0xF6, 0xF1, 0x16, 0x72, 0x57, 0x72,
|
||||
0x57, 0xF6, 0x78, 0x76, 0x78, 0xF6, 0x99, 0xF6, 0xB9, 0xF6, 0xD9, 0x76, 0xDA, 0xF6, 0x1B, 0x7B,
|
||||
0x1B, 0xFB, 0x3C, 0xFB, 0x5C, 0x7B, 0x7D, 0x7B, 0x7D, 0xFF, 0x9D, 0x7F, 0xBE, 0x7F, 0xFF, 0x7F,
|
||||
0x2D, 0x64, 0x8E, 0x64, 0x8F, 0xE8, 0xF1, 0xE8, 0x52, 0x6D, 0x73, 0x6D, 0xB4, 0xF1, 0x16, 0xF2,
|
||||
0x37, 0x72, 0x98, 0x76, 0xFA, 0x7A, 0xFA, 0xFA, 0x5C, 0xFB, 0xBE, 0xFF, 0xDE, 0x7F, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const uint32_t _logoHash = 0xEEDA6963;
|
||||
|
||||
static const uint32_t _gbpTxData[] = {
|
||||
0x0000494E, 0x0000494E,
|
||||
0xB6B1494E, 0xB6B1544E,
|
||||
0xABB1544E, 0xABB14E45,
|
||||
0xB1BA4E45, 0xB1BA4F44,
|
||||
0xB0BB4F44, 0xB0BB8002,
|
||||
0x10000010, 0x20000013,
|
||||
0x30000003
|
||||
};
|
||||
|
||||
void GBASIOPlayerInit(struct GBASIOPlayer* gbp) {
|
||||
gbp->callback.d.readKeys = _gbpRead;
|
||||
gbp->callback.p = gbp;
|
||||
gbp->d.init = 0;
|
||||
gbp->d.deinit = 0;
|
||||
gbp->d.load = 0;
|
||||
gbp->d.unload = 0;
|
||||
gbp->d.writeRegister = _gbpSioWriteRegister;
|
||||
gbp->event.context = gbp;
|
||||
gbp->event.name = "GBA SIO Game Boy Player";
|
||||
gbp->event.callback = _gbpSioProcessEvents;
|
||||
gbp->event.priority = 0x80;
|
||||
}
|
||||
|
||||
void GBASIOPlayerReset(struct GBASIOPlayer* gbp) {
|
||||
if (gbp->p->sio.drivers.normal == &gbp->d) {
|
||||
GBASIOSetDriver(&gbp->p->sio, NULL, SIO_NORMAL_32);
|
||||
}
|
||||
}
|
||||
|
||||
bool GBASIOPlayerCheckScreen(const struct GBAVideo* video) {
|
||||
if (memcmp(video->palette, _logoPalette, sizeof(_logoPalette)) != 0) {
|
||||
return false;
|
||||
}
|
||||
uint32_t hash = hash32(&video->vram[0x4000], 0x4000, 0);
|
||||
return hash == _logoHash;
|
||||
}
|
||||
|
||||
void GBASIOPlayerUpdate(struct GBA* gba) {
|
||||
if (gba->memory.hw.devices & HW_GB_PLAYER) {
|
||||
if (GBASIOPlayerCheckScreen(&gba->video)) {
|
||||
++gba->sio.gbp.inputsPosted;
|
||||
gba->sio.gbp.inputsPosted %= 3;
|
||||
gba->keyCallback = &gba->sio.gbp.callback.d;
|
||||
} else {
|
||||
// TODO: Save and restore
|
||||
gba->keyCallback = 0;
|
||||
}
|
||||
gba->sio.gbp.txPosition = 0;
|
||||
return;
|
||||
}
|
||||
if (gba->keyCallback) {
|
||||
return;
|
||||
}
|
||||
if (GBASIOPlayerCheckScreen(&gba->video)) {
|
||||
gba->memory.hw.devices |= HW_GB_PLAYER;
|
||||
gba->sio.gbp.inputsPosted = 0;
|
||||
gba->keyCallback = &gba->sio.gbp.callback.d;
|
||||
// TODO: Check if the SIO driver is actually used first
|
||||
GBASIOSetDriver(&gba->sio, &gba->sio.gbp.d, SIO_NORMAL_32);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t _gbpRead(struct mKeyCallback* callback) {
|
||||
struct GBASIOPlayerKeyCallback* gbpCallback = (struct GBASIOPlayerKeyCallback*) callback;
|
||||
if (gbpCallback->p->inputsPosted == 2) {
|
||||
return 0xF0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
|
||||
struct GBASIOPlayer* gbp = (struct GBASIOPlayer*) driver;
|
||||
if (address == REG_SIOCNT) {
|
||||
if (value & 0x0080) {
|
||||
uint32_t rx = gbp->p->memory.io[REG_SIODATA32_LO >> 1] | (gbp->p->memory.io[REG_SIODATA32_HI >> 1] << 16);
|
||||
if (gbp->txPosition < 12 && gbp->txPosition > 0) {
|
||||
// TODO: Check expected
|
||||
} else if (gbp->txPosition >= 12) {
|
||||
uint32_t mask = 0x33;
|
||||
// 0x00 = Stop
|
||||
// 0x11 = Hard Stop
|
||||
// 0x22 = Start
|
||||
if (gbp->p->rumble) {
|
||||
gbp->p->rumble->setRumble(gbp->p->rumble, (rx & mask) == 0x22);
|
||||
}
|
||||
}
|
||||
mTimingDeschedule(&gbp->p->timing, &gbp->event);
|
||||
mTimingSchedule(&gbp->p->timing, &gbp->event, 2048);
|
||||
}
|
||||
value &= 0x78FB;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) {
|
||||
UNUSED(timing);
|
||||
UNUSED(cyclesLate);
|
||||
struct GBASIOPlayer* gbp = user;
|
||||
uint32_t tx = 0;
|
||||
int txPosition = gbp->txPosition;
|
||||
if (txPosition > 16) {
|
||||
gbp->txPosition = 0;
|
||||
txPosition = 0;
|
||||
} else if (txPosition > 12) {
|
||||
txPosition = 12;
|
||||
}
|
||||
tx = _gbpTxData[txPosition];
|
||||
++gbp->txPosition;
|
||||
gbp->p->memory.io[REG_SIODATA32_LO >> 1] = tx;
|
||||
gbp->p->memory.io[REG_SIODATA32_HI >> 1] = tx >> 16;
|
||||
if (GBASIONormalIsIrq(gbp->d.p->siocnt)) {
|
||||
GBARaiseIRQ(gbp->p, IRQ_SIO, cyclesLate);
|
||||
}
|
||||
gbp->d.p->siocnt = GBASIONormalClearStart(gbp->d.p->siocnt);
|
||||
gbp->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt & ~0x0080;
|
||||
}
|
|
@ -800,7 +800,7 @@ void CoreController::scanCard(const QString& path) {
|
|||
|
||||
mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* thread) {
|
||||
CoreController* controller = static_cast<CoreController*>(thread->userData);
|
||||
GBAEReaderQueueCard(static_cast<GBA*>(thread->core->board), controller->m_eReaderData.constData(), controller->m_eReaderData.size());
|
||||
GBACartEReaderQueueCard(static_cast<GBA*>(thread->core->board), controller->m_eReaderData.constData(), controller->m_eReaderData.size());
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -371,6 +371,10 @@ void PainterGL::resizeContext() {
|
|||
m_interrupter.resume();
|
||||
|
||||
QSize size = m_context->screenDimensions();
|
||||
if (m_dims == size) {
|
||||
return;
|
||||
}
|
||||
dequeueAll();
|
||||
m_backend->setDimensions(m_backend, size.width(), size.height());
|
||||
}
|
||||
|
||||
|
@ -563,9 +567,6 @@ void PainterGL::dequeueAll() {
|
|||
m_free.append(buffer);
|
||||
}
|
||||
}
|
||||
if (buffer) {
|
||||
m_backend->postFrame(m_backend, buffer);
|
||||
}
|
||||
if (m_buffer) {
|
||||
m_free.append(m_buffer);
|
||||
m_buffer = nullptr;
|
||||
|
|
|
@ -142,7 +142,7 @@ private:
|
|||
QList<uint32_t*> m_free;
|
||||
QQueue<uint32_t*> m_queue;
|
||||
QAtomicInt m_lagging = 0;
|
||||
uint32_t* m_buffer;
|
||||
uint32_t* m_buffer = nullptr;
|
||||
QPainter m_painter;
|
||||
QMutex m_mutex;
|
||||
QWindow* m_surface;
|
||||
|
@ -158,6 +158,7 @@ private:
|
|||
VideoShader m_shader{};
|
||||
VideoBackend* m_backend = nullptr;
|
||||
QSize m_size;
|
||||
QSize m_dims;
|
||||
MessagePainter* m_messagePainter = nullptr;
|
||||
QElapsedTimer m_delayTimer;
|
||||
std::shared_ptr<VideoProxy> m_videoProxy;
|
||||
|
|
|
@ -48,7 +48,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../AboutScreen.ui" line="41"/>
|
||||
<source>Branch: <tt>{gitBranch}</tt><br/>Revision: <tt>{gitCommit}</tt></source>
|
||||
<translation>Branch: <tt>{gitBranch}</tt><br/>Revision: <tt>{gitCommit}</tt></translation>
|
||||
<translation>Zweig: <tt>{gitBranch}</tt><br/>Änderung: <tt>{gitCommit}</tt></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -513,7 +513,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../LogView.ui" line="78"/>
|
||||
<source>Fatal</source>
|
||||
<translation>Fatal</translation>
|
||||
<translation>Tödlich</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../LogView.ui" line="95"/>
|
||||
|
@ -541,7 +541,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../MapView.ui" line="14"/>
|
||||
<source>Maps</source>
|
||||
<translation>Maps</translation>
|
||||
<translation>Karten</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../MapView.ui" line="43"/>
|
||||
|
@ -767,7 +767,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../MemoryView.ui" line="208"/>
|
||||
<source>Signed Integer:</source>
|
||||
<translation>Signed Integer:</translation>
|
||||
<translation>Ganzzahl mit Vorzeichen:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../MemoryView.ui" line="229"/>
|
||||
|
@ -807,7 +807,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../MemoryView.ui" line="187"/>
|
||||
<source>Unsigned Integer:</source>
|
||||
<translation>Unsigned Integer:</translation>
|
||||
<translation>Ganzzahl ohne Vorzeichen:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -840,7 +840,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../ObjView.ui" line="386"/>
|
||||
<source>Transform</source>
|
||||
<translation>Transform</translation>
|
||||
<translation>Verwandeln</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ObjView.ui" line="406"/>
|
||||
|
@ -905,7 +905,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../ObjView.ui" line="576"/>
|
||||
<source>Mosaic</source>
|
||||
<translation>Mosaic</translation>
|
||||
<translation>Mosaik</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ObjView.ui" line="613"/>
|
||||
|
@ -920,7 +920,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../ObjView.ui" line="682"/>
|
||||
<source>Tile</source>
|
||||
<translation></translation>
|
||||
<translation>Kachel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ObjView.ui" line="137"/>
|
||||
|
@ -1550,7 +1550,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="65"/>
|
||||
<source>Swap green components</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Grüne Komponenten tauschen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="69"/>
|
||||
|
@ -1680,7 +1680,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<location filename="../IOViewer.cpp" line="211"/>
|
||||
<location filename="../IOViewer.cpp" line="220"/>
|
||||
<source>Fractional part</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Bruchteil</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="154"/>
|
||||
|
@ -1700,7 +1700,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<location filename="../IOViewer.cpp" line="212"/>
|
||||
<location filename="../IOViewer.cpp" line="221"/>
|
||||
<source>Integer part (low)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Ganzzahl-Anteil (tief)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="178"/>
|
||||
|
@ -1708,7 +1708,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<location filename="../IOViewer.cpp" line="216"/>
|
||||
<location filename="../IOViewer.cpp" line="225"/>
|
||||
<source>Integer part (high)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Ganzzahl-Anteil (hoch)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="229"/>
|
||||
|
@ -1978,19 +1978,19 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<location filename="../IOViewer.cpp" line="328"/>
|
||||
<location filename="../IOViewer.cpp" line="1099"/>
|
||||
<source>Sweep shifts</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Schwung-Verschiebungen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="329"/>
|
||||
<location filename="../IOViewer.cpp" line="1100"/>
|
||||
<source>Sweep subtract</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Schwung subtrahieren</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="330"/>
|
||||
<location filename="../IOViewer.cpp" line="1101"/>
|
||||
<source>Sweep time (in 1/128s)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Schwungzeit (in 1/128s)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="334"/>
|
||||
|
@ -2010,7 +2010,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<location filename="../IOViewer.cpp" line="1106"/>
|
||||
<location filename="../IOViewer.cpp" line="1129"/>
|
||||
<source>Duty cycle</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Auslastungsgrad</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="336"/>
|
||||
|
@ -2020,7 +2020,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<location filename="../IOViewer.cpp" line="1133"/>
|
||||
<location filename="../IOViewer.cpp" line="1182"/>
|
||||
<source>Envelope step time</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Hüllkurve-Schrittzeit</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="337"/>
|
||||
|
@ -2076,7 +2076,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="368"/>
|
||||
<source>Double-size wave table</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Doppelte Größe Wave-Table</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="369"/>
|
||||
|
@ -2140,7 +2140,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<location filename="../IOViewer.cpp" line="406"/>
|
||||
<location filename="../IOViewer.cpp" line="1189"/>
|
||||
<source>Register stages</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Register-Stufen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="407"/>
|
||||
|
@ -2158,7 +2158,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<location filename="../IOViewer.cpp" line="410"/>
|
||||
<location filename="../IOViewer.cpp" line="1193"/>
|
||||
<source>Shifter frequency</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Shifter-Frequenz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="418"/>
|
||||
|
@ -2226,12 +2226,12 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="437"/>
|
||||
<source>Loud channel A</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Lautkanal A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="438"/>
|
||||
<source>Loud channel B</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Lautkanal B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="439"/>
|
||||
|
@ -2325,7 +2325,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="466"/>
|
||||
<source>Bias</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Vorspannung</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="467"/>
|
||||
|
@ -2406,7 +2406,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<location filename="../IOViewer.cpp" line="1321"/>
|
||||
<location filename="../IOViewer.cpp" line="1322"/>
|
||||
<source>Sample</source>
|
||||
<translation>Sample</translation>
|
||||
<translation>Abtastwert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="561"/>
|
||||
|
@ -2568,7 +2568,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<location filename="../IOViewer.cpp" line="685"/>
|
||||
<location filename="../IOViewer.cpp" line="731"/>
|
||||
<source>Start timing</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Zeitpunkt des Starts</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="596"/>
|
||||
|
@ -2635,7 +2635,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<location filename="../IOViewer.cpp" line="689"/>
|
||||
<location filename="../IOViewer.cpp" line="735"/>
|
||||
<source>Audio FIFO</source>
|
||||
<translation>Audio FIFO</translation>
|
||||
<translation>Audio-FIFO</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="726"/>
|
||||
|
@ -2931,7 +2931,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1014"/>
|
||||
<source>PHI terminal</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>PHI-Terminal</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1015"/>
|
||||
|
@ -2942,17 +2942,17 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1016"/>
|
||||
<source>4.19MHz</source>
|
||||
<translation>4,19 MHz</translation>
|
||||
<translation>4,19 MHz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1017"/>
|
||||
<source>8.38MHz</source>
|
||||
<translation>8,38 MHz</translation>
|
||||
<translation>8,38 MHz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1018"/>
|
||||
<source>16.78MHz</source>
|
||||
<translation>16,78 MHz</translation>
|
||||
<translation>16,78 MHz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1020"/>
|
||||
|
@ -3007,7 +3007,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1049"/>
|
||||
<source>Transfer active</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Übertragung aktiv</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1067"/>
|
||||
|
@ -3023,65 +3023,65 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<location filename="../IOViewer.cpp" line="1092"/>
|
||||
<location filename="../IOViewer.cpp" line="1553"/>
|
||||
<source>LCD STAT</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>LCD STAT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1093"/>
|
||||
<location filename="../IOViewer.cpp" line="1554"/>
|
||||
<source>Timer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Timer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1094"/>
|
||||
<location filename="../IOViewer.cpp" line="1555"/>
|
||||
<source>Serial</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Serial</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1095"/>
|
||||
<location filename="../IOViewer.cpp" line="1556"/>
|
||||
<source>Joypad</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Gamepad</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1202"/>
|
||||
<source>Volume right</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Lautstärke rechts</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1203"/>
|
||||
<source>Output right</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Ausgabe rechts</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1204"/>
|
||||
<source>Volume left</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Lautstärke links</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1205"/>
|
||||
<source>Output left</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Ausgabe links</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1326"/>
|
||||
<source>Background enable/priority</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Hintergrund aktivieren/Priorität</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1327"/>
|
||||
<source>Enable sprites</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Sprites aktivieren</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1328"/>
|
||||
<source>Double-height sprites</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Doppelte Höhe Sprites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1329"/>
|
||||
<source>Background tile map</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Hintergrundkachelkarte</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1330"/>
|
||||
|
@ -3098,7 +3098,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1333"/>
|
||||
<source>Background tile data</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Hintergrundkacheldaten</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1334"/>
|
||||
|
@ -3113,12 +3113,12 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1337"/>
|
||||
<source>Enable window</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Fenster aktivieren</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1338"/>
|
||||
<source>Window tile map</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Fensterkachelkarte</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1342"/>
|
||||
|
@ -3133,7 +3133,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1347"/>
|
||||
<source>0: HBlank</source>
|
||||
<translation>HBlank</translation>
|
||||
<translation>0: HBlank</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1348"/>
|
||||
|
@ -3143,7 +3143,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1349"/>
|
||||
<source>2: OAM scan</source>
|
||||
<translation>2: OAM scan</translation>
|
||||
<translation>2: OAM-Überprüfung</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1350"/>
|
||||
|
@ -3153,75 +3153,75 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1352"/>
|
||||
<source>In LYC</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>In LYC</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1353"/>
|
||||
<source>Enable HBlank (mode 0) IRQ</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>HBlank aktivieren (Modus 0) IRQ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1354"/>
|
||||
<source>Enable VBlank (mode 1) IRQ</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>VBlank aktivieren (Modus 1) IRQ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1355"/>
|
||||
<source>Enable OAM (mode 2) IRQ</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>OAM aktivieren (Modus 2) IRQ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1356"/>
|
||||
<source>Enable LYC IRQ</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>LYC aktivieren IRQ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1368"/>
|
||||
<source>Current Y coordinate</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Aktuelle Y-Koordinate</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1372"/>
|
||||
<source>Comparison Y coordinate</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Vergleich Y-Koordinate</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1376"/>
|
||||
<source>Start upper byte</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Oberes Byte starten</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1380"/>
|
||||
<location filename="../IOViewer.cpp" line="1387"/>
|
||||
<location filename="../IOViewer.cpp" line="1394"/>
|
||||
<source>Color 0 shade</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Farbe 0 Farbton</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1381"/>
|
||||
<location filename="../IOViewer.cpp" line="1388"/>
|
||||
<location filename="../IOViewer.cpp" line="1395"/>
|
||||
<source>Color 1 shade</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Farbe 1 Farbton</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1382"/>
|
||||
<location filename="../IOViewer.cpp" line="1389"/>
|
||||
<location filename="../IOViewer.cpp" line="1396"/>
|
||||
<source>Color 2 shade</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Farbe 2 Farbton</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1383"/>
|
||||
<location filename="../IOViewer.cpp" line="1390"/>
|
||||
<location filename="../IOViewer.cpp" line="1397"/>
|
||||
<source>Color 3 shade</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Farbe 3 Farbton</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1411"/>
|
||||
<source>Prepare to switch speed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Zu Geschwindigkeit wechseln vorbereiten</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1412"/>
|
||||
|
@ -3236,22 +3236,22 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1440"/>
|
||||
<source>Length</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Länge</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1441"/>
|
||||
<source>Timing</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Timing</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1448"/>
|
||||
<source>Write bit</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Bit schreiben</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1449"/>
|
||||
<source>Read bit</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Bit lesen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1452"/>
|
||||
|
@ -3263,7 +3263,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<location filename="../IOViewer.cpp" line="1493"/>
|
||||
<location filename="../IOViewer.cpp" line="1505"/>
|
||||
<source>Current index</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Aktueller Index</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1494"/>
|
||||
|
@ -3286,17 +3286,17 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1517"/>
|
||||
<source>Sprite ordering</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Sprite-Anordnung</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1518"/>
|
||||
<source>OAM order</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>OAM-Anordnung</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1519"/>
|
||||
<source>x coordinate sorting</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>X-Koordinatensortierung</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1530"/>
|
||||
|
@ -4087,7 +4087,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../Window.cpp" line="410"/>
|
||||
<source>Patches (*.ips *.ups *.bps)</source>
|
||||
<translation>Patches (*.ips *.ups *.bps)</translation>
|
||||
<translation>Korrekturen (*.ips *.ups *.bps)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Window.cpp" line="434"/>
|
||||
|
@ -4980,12 +4980,12 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../SaveConverter.cpp" line="401"/>
|
||||
<source>little endian</source>
|
||||
<translation>little endian</translation>
|
||||
<translation>little-endian</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SaveConverter.cpp" line="404"/>
|
||||
<source>big endian</source>
|
||||
<translation>big endian</translation>
|
||||
<translation>big-endian</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SaveConverter.cpp" line="415"/>
|
||||
|
@ -5322,8 +5322,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../SettingsView.ui" line="444"/>
|
||||
<source>Force integer scaling</source>
|
||||
<translation>Erzwinge pixelgenaue Skalierung
|
||||
(Integer scaling)</translation>
|
||||
<translation>Erzwinge pixelgenaue Skalierung</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SettingsView.ui" line="458"/>
|
||||
|
@ -5384,8 +5383,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
|||
<message>
|
||||
<location filename="../SettingsView.ui" line="961"/>
|
||||
<source>Enable Game Boy Player features by default</source>
|
||||
<translation>Game Boy Player-Features
|
||||
standardmäßig aktivieren</translation>
|
||||
<translation>Game Boy Player-Features standardmäßig aktivieren</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SettingsView.ui" line="1858"/>
|
||||
|
@ -5430,8 +5428,7 @@ standardmäßig aktivieren</translation>
|
|||
<message>
|
||||
<location filename="../SettingsView.ui" line="592"/>
|
||||
<source>Show filename instead of ROM name in title bar</source>
|
||||
<translation>Dateinamen statt ROM-Namen in der
|
||||
Titelleiste anzeigen</translation>
|
||||
<translation>Dateinamen statt ROM-Namen in der Titelleiste anzeigen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SettingsView.ui" line="740"/>
|
||||
|
@ -5566,8 +5563,7 @@ Titelleiste anzeigen</translation>
|
|||
<message>
|
||||
<location filename="../SettingsView.ui" line="872"/>
|
||||
<source>Preload entire ROM into memory</source>
|
||||
<translation>ROM-Datei vollständig
|
||||
in Arbeitsspeicher vorladen</translation>
|
||||
<translation>ROM-Datei vollständig in Arbeitsspeicher vorladen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SettingsView.ui" line="1092"/>
|
||||
|
@ -5595,8 +5591,7 @@ in Arbeitsspeicher vorladen</translation>
|
|||
<message>
|
||||
<location filename="../SettingsView.ui" line="1101"/>
|
||||
<source>Use BIOS file if found</source>
|
||||
<translation>BIOS-Datei verwenden,
|
||||
wenn vorhanden</translation>
|
||||
<translation>BIOS-Datei verwenden, wenn vorhanden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SettingsView.ui" line="1111"/>
|
||||
|
@ -5733,12 +5728,12 @@ wenn vorhanden</translation>
|
|||
<message>
|
||||
<location filename="../SettingsView.ui" line="1305"/>
|
||||
<source>Screenshots</source>
|
||||
<translation>Screenshots</translation>
|
||||
<translation>Bildschirmfotos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SettingsView.ui" line="1353"/>
|
||||
<source>Patches</source>
|
||||
<translation>Patches</translation>
|
||||
<translation>Korrekturen</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -5807,7 +5802,7 @@ wenn vorhanden</translation>
|
|||
<message>
|
||||
<location filename="../TileView.ui" line="14"/>
|
||||
<source>Tiles</source>
|
||||
<translation>Tiles</translation>
|
||||
<translation>Kacheln</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../TileView.ui" line="20"/>
|
||||
|
|
|
@ -1862,27 +1862,27 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd.</translation>
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="288"/>
|
||||
<source>BG 0 target 1</source>
|
||||
<translation>BG 0 target 1</translation>
|
||||
<translation>BG 0 objetivo 1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="289"/>
|
||||
<source>BG 1 target 1</source>
|
||||
<translation>BG 1 target 1</translation>
|
||||
<translation>BG 1 objetivo 1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="290"/>
|
||||
<source>BG 2 target 1</source>
|
||||
<translation>BG 2 target 1</translation>
|
||||
<translation>BG 2 objetivo 1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="291"/>
|
||||
<source>BG 3 target 1</source>
|
||||
<translation>BG 3 target 1</translation>
|
||||
<translation>BG 3 objetivo 1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="292"/>
|
||||
<source>OBJ target 1</source>
|
||||
<translation>OBJ target 1</translation>
|
||||
<translation>OBJ objetivo 1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="293"/>
|
||||
|
@ -1917,27 +1917,27 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd.</translation>
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="300"/>
|
||||
<source>BG 0 target 2</source>
|
||||
<translation>BG 0 target 2</translation>
|
||||
<translation>BG 0 objetivo 2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="301"/>
|
||||
<source>BG 1 target 2</source>
|
||||
<translation>BG 1 target 2</translation>
|
||||
<translation>BG 1 objetivo 2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="302"/>
|
||||
<source>BG 2 target 2</source>
|
||||
<translation>BG 2 target 2</translation>
|
||||
<translation>BG 2 objetivo 2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="303"/>
|
||||
<source>BG 3 target 2</source>
|
||||
<translation>BG 3 target 2</translation>
|
||||
<translation>BG 3 objetivo 2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="304"/>
|
||||
<source>OBJ target 2</source>
|
||||
<translation>OBJ target 2</translation>
|
||||
<translation>OBJ objetivo 2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="305"/>
|
||||
|
@ -1947,12 +1947,12 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd.</translation>
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="309"/>
|
||||
<source>Blend A (target 1)</source>
|
||||
<translation>Mezcla A (target 1)</translation>
|
||||
<translation>Mezcla A (objetivo 1)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="310"/>
|
||||
<source>Blend B (target 2)</source>
|
||||
<translation>Mezcla B (target 2)</translation>
|
||||
<translation>Mezcla B (objetivo 2)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="314"/>
|
||||
|
@ -2044,7 +2044,7 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd.</translation>
|
|||
<location filename="../IOViewer.cpp" line="1171"/>
|
||||
<location filename="../IOViewer.cpp" line="1197"/>
|
||||
<source>Timed</source>
|
||||
<translation>Timed</translation>
|
||||
<translation>Cronometrado</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="344"/>
|
||||
|
@ -2620,7 +2620,7 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd.</translation>
|
|||
<location filename="../IOViewer.cpp" line="689"/>
|
||||
<location filename="../IOViewer.cpp" line="735"/>
|
||||
<source>Audio FIFO</source>
|
||||
<translation>Audio FIFO</translation>
|
||||
<translation>FIFO de audio</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="726"/>
|
||||
|
@ -2835,7 +2835,7 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd.</translation>
|
|||
<location filename="../IOViewer.cpp" line="956"/>
|
||||
<location filename="../IOViewer.cpp" line="973"/>
|
||||
<source>Keypad</source>
|
||||
<translation>Keypad</translation>
|
||||
<translation>Teclado numérico</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="957"/>
|
||||
|
@ -2916,7 +2916,7 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd.</translation>
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1014"/>
|
||||
<source>PHI terminal</source>
|
||||
<translation>PHI terminal</translation>
|
||||
<translation>Terminal PHI</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1015"/>
|
||||
|
|
|
@ -221,37 +221,37 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标
|
|||
<message>
|
||||
<location filename="../DolphinConnector.ui" line="14"/>
|
||||
<source>Connect to Dolphin</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>连接 Dolphin</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../DolphinConnector.ui" line="23"/>
|
||||
<source>Local computer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>本地电脑</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../DolphinConnector.ui" line="36"/>
|
||||
<source>IP address</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>IP 地址</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../DolphinConnector.ui" line="55"/>
|
||||
<source>Connect</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>连接</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../DolphinConnector.ui" line="68"/>
|
||||
<source>Disconnect</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>断开连接</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../DolphinConnector.ui" line="78"/>
|
||||
<source>Close</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>关闭</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../DolphinConnector.ui" line="90"/>
|
||||
<source>Reset on connect</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>连接时重置</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -2952,27 +2952,27 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标
|
|||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1034"/>
|
||||
<source>Right/A</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>右/A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1035"/>
|
||||
<source>Left/B</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>左/B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1036"/>
|
||||
<source>Up/Select</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>上/选择</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1037"/>
|
||||
<source>Down/Start</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>下/开始</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1038"/>
|
||||
<source>Active D-pad</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>活跃的方向键</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../IOViewer.cpp" line="1039"/>
|
||||
|
|
|
@ -2,6 +2,7 @@ include(ExportDirectory)
|
|||
set(SOURCE_FILES
|
||||
circle-buffer.c
|
||||
configuration.c
|
||||
convolve.c
|
||||
crc32.c
|
||||
elf-read.c
|
||||
export.c
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
/* Copyright (c) 2013-2021 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba-util/convolve.h>
|
||||
|
||||
void ConvolutionKernelCreate(struct ConvolutionKernel* kernel, size_t rank, size_t* dims) {
|
||||
kernel->rank = rank;
|
||||
kernel->dims = malloc(sizeof(kernel->dims[0]) * rank);
|
||||
size_t ksize = 1;
|
||||
size_t i;
|
||||
for (i = 0; i < rank; ++i) {
|
||||
kernel->dims[i] = dims[i];
|
||||
ksize *= dims[i];
|
||||
}
|
||||
kernel->kernel = calloc(ksize, sizeof(float));
|
||||
}
|
||||
|
||||
void ConvolutionKernelDestroy(struct ConvolutionKernel* kernel) {
|
||||
free(kernel->kernel);
|
||||
free(kernel->dims);
|
||||
kernel->kernel = NULL;
|
||||
kernel->dims = NULL;
|
||||
kernel->rank = 0;
|
||||
}
|
||||
|
||||
void ConvolutionKernelFillRadial(struct ConvolutionKernel* kernel, bool normalize) {
|
||||
if (kernel->rank != 2) {
|
||||
return;
|
||||
}
|
||||
float support;
|
||||
if (normalize) {
|
||||
support = 12.f / (M_PI * (kernel->dims[0] - 1) * (kernel->dims[1] - 1));
|
||||
} else {
|
||||
support = 1.f;
|
||||
}
|
||||
float wr = (kernel->dims[0] - 1) / 2.f;
|
||||
float hr = (kernel->dims[1] - 1) / 2.f;
|
||||
float* elem = kernel->kernel;
|
||||
size_t y;
|
||||
for (y = 0; y < kernel->dims[1]; ++y) {
|
||||
size_t x;
|
||||
for (x = 0; x < kernel->dims[0]; ++x) {
|
||||
float r = (1.f - hypotf((x - wr) / wr, (y - hr) / hr)) * support;
|
||||
*elem = fmaxf(0, r);
|
||||
++elem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConvolutionKernelFillCircle(struct ConvolutionKernel* kernel, bool normalize) {
|
||||
if (kernel->rank != 2) {
|
||||
return;
|
||||
}
|
||||
float support;
|
||||
if (normalize) {
|
||||
support = 4.f / (M_PI * (kernel->dims[0] - 1) * (kernel->dims[1] - 1));
|
||||
} else {
|
||||
support = 1.f;
|
||||
}
|
||||
float wr = (kernel->dims[0] - 1) / 2.f;
|
||||
float hr = (kernel->dims[1] - 1) / 2.f;
|
||||
float* elem = kernel->kernel;
|
||||
size_t y;
|
||||
for (y = 0; y < kernel->dims[1]; ++y) {
|
||||
size_t x;
|
||||
for (x = 0; x < kernel->dims[0]; ++x) {
|
||||
float r = hypotf((x - wr) / wr, (y - hr) / hr);
|
||||
*elem = r <= 1.f ? support : 0.f;
|
||||
++elem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Convolve1DPad0PackedS32(const int32_t* restrict src, int32_t* restrict dst, size_t length, const struct ConvolutionKernel* restrict kernel) {
|
||||
if (kernel->rank != 1) {
|
||||
return;
|
||||
}
|
||||
size_t kx2 = kernel->dims[0] / 2;
|
||||
size_t x;
|
||||
for (x = 0; x < length; ++x) {
|
||||
float sum = 0.f;
|
||||
size_t kx;
|
||||
for (kx = 0; kx < kernel->dims[0]; ++kx) {
|
||||
if (x + kx <= kx2) {
|
||||
continue;
|
||||
}
|
||||
size_t cx = x + kx - kx2;
|
||||
if (cx >= length) {
|
||||
continue;
|
||||
}
|
||||
sum += src[cx] * kernel->kernel[kx];
|
||||
}
|
||||
*dst = sum;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
|
||||
void Convolve2DClampPacked8(const uint8_t* restrict src, uint8_t* restrict dst, size_t width, size_t height, size_t stride, const struct ConvolutionKernel* restrict kernel) {
|
||||
if (kernel->rank != 2) {
|
||||
return;
|
||||
}
|
||||
size_t kx2 = kernel->dims[0] / 2;
|
||||
size_t ky2 = kernel->dims[1] / 2;
|
||||
size_t y;
|
||||
for (y = 0; y < height; ++y) {
|
||||
uint8_t* orow = &dst[y * stride];
|
||||
size_t x;
|
||||
for (x = 0; x < width; ++x) {
|
||||
float sum = 0.f;
|
||||
size_t ky;
|
||||
for (ky = 0; ky < kernel->dims[1]; ++ky) {
|
||||
size_t cy = 0;
|
||||
if (y + ky > ky2) {
|
||||
cy = y + ky - ky2;
|
||||
}
|
||||
if (cy >= height) {
|
||||
cy = height - 1;
|
||||
}
|
||||
const uint8_t* irow = &src[cy * stride];
|
||||
size_t kx;
|
||||
for (kx = 0; kx < kernel->dims[0]; ++kx) {
|
||||
size_t cx = 0;
|
||||
if (x + kx > kx2) {
|
||||
cx = x + kx - kx2;
|
||||
}
|
||||
if (cx >= width) {
|
||||
cx = width - 1;
|
||||
}
|
||||
sum += irow[cx] * kernel->kernel[ky * kernel->dims[0] + kx];
|
||||
}
|
||||
}
|
||||
*orow = sum;
|
||||
++orow;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue