mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' into medusa
This commit is contained in:
commit
154dd2e8e7
8
CHANGES
8
CHANGES
|
@ -49,6 +49,8 @@ Features:
|
|||
- Savestates now contain any RTC override data
|
||||
- Command line ability to override configuration values
|
||||
- Add option to allow preloading the entire ROM before running
|
||||
- GB: Video/audio channel enabling/disabling
|
||||
- Add option to lock video to integer scaling
|
||||
Bugfixes:
|
||||
- LR35902: Fix core never exiting with certain event patterns
|
||||
- GB Timer: Improve DIV reset behavior
|
||||
|
@ -73,6 +75,11 @@ Bugfixes:
|
|||
- GB: Fix flickering when screen is strobed quickly
|
||||
- FFmpeg: Fix overflow and general issues with audio encoding
|
||||
- Qt: Fix crash when changing audio settings after a game is closed
|
||||
- GBA BIOS: Fix ArcTan sign in HLE BIOS
|
||||
- GBA BIOS: Fix ArcTan2 sign in HLE BIOS (fixes mgba.io/i/689)
|
||||
- GBA Video: Don't update background scanline params in mode 0 (fixes mgba.io/i/377)
|
||||
- Qt: Ensure CLI backend is attached when submitting commands (fixes mgba.io/i/662)
|
||||
- Core: Fix crash with rewind if savestates shrink
|
||||
Misc:
|
||||
- SDL: Remove scancode key input
|
||||
- GBA Video: Clean up unused timers
|
||||
|
@ -126,6 +133,7 @@ Misc:
|
|||
- Qt: Add .gb/.gbc files to the extension list in Info.plist
|
||||
- Feature: Make -l option explicit
|
||||
- Core: Ability to enumerate and modify video and audio channels
|
||||
- Debugger: Make attaching a backend idempotent
|
||||
|
||||
medusa alpha 1: (2017-04-08)
|
||||
Features:
|
||||
|
|
|
@ -56,6 +56,11 @@ typedef intptr_t ssize_t;
|
|||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef PSP2
|
||||
// For PATH_MAX on modern toolchains
|
||||
#include <sys/syslimits.h>
|
||||
#endif
|
||||
|
||||
#ifndef SSIZE_MAX
|
||||
#define SSIZE_MAX ((ssize_t) (SIZE_MAX >> 1))
|
||||
#endif
|
||||
|
|
|
@ -42,6 +42,7 @@ struct mCoreOptions {
|
|||
int width;
|
||||
int height;
|
||||
bool lockAspectRatio;
|
||||
bool lockIntegerScaling;
|
||||
bool resampleVideo;
|
||||
bool suspendScreensaver;
|
||||
char* shader;
|
||||
|
|
|
@ -71,6 +71,10 @@ struct GBVideoRenderer {
|
|||
uint8_t* vram;
|
||||
union GBOAM* oam;
|
||||
struct mTileCache* cache;
|
||||
|
||||
bool disableBG;
|
||||
bool disableOBJ;
|
||||
bool disableWIN;
|
||||
};
|
||||
|
||||
DECL_BITFIELD(GBRegisterLCDC, uint8_t);
|
||||
|
|
|
@ -349,6 +349,9 @@ void mCoreConfigMap(const struct mCoreConfig* config, struct mCoreOptions* opts)
|
|||
if (_lookupIntValue(config, "lockAspectRatio", &fakeBool)) {
|
||||
opts->lockAspectRatio = fakeBool;
|
||||
}
|
||||
if (_lookupIntValue(config, "lockIntegerScaling", &fakeBool)) {
|
||||
opts->lockIntegerScaling = fakeBool;
|
||||
}
|
||||
if (_lookupIntValue(config, "resampleVideo", &fakeBool)) {
|
||||
opts->resampleVideo = fakeBool;
|
||||
}
|
||||
|
@ -396,6 +399,7 @@ void mCoreConfigLoadDefaults(struct mCoreConfig* config, const struct mCoreOptio
|
|||
ConfigurationSetIntValue(&config->defaultsTable, 0, "volume", opts->volume);
|
||||
ConfigurationSetIntValue(&config->defaultsTable, 0, "mute", opts->mute);
|
||||
ConfigurationSetIntValue(&config->defaultsTable, 0, "lockAspectRatio", opts->lockAspectRatio);
|
||||
ConfigurationSetIntValue(&config->defaultsTable, 0, "lockIntegerScaling", opts->lockIntegerScaling);
|
||||
ConfigurationSetIntValue(&config->defaultsTable, 0, "resampleVideo", opts->resampleVideo);
|
||||
ConfigurationSetIntValue(&config->defaultsTable, 0, "suspendScreensaver", opts->suspendScreensaver);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ void mCoreRewindAppend(struct mCoreRewindContext* context, struct mCore* core) {
|
|||
if (size2 > size) {
|
||||
context->currentState->truncate(context->currentState, size2);
|
||||
size = size2;
|
||||
} else if (size > size2) {
|
||||
nextState->truncate(nextState, size);
|
||||
}
|
||||
void* current = context->currentState->map(context->currentState, size, MAP_READ);
|
||||
void* next = nextState->map(nextState, size, MAP_READ);
|
||||
|
|
|
@ -751,6 +751,9 @@ void CLIDebuggerAttachSystem(struct CLIDebugger* debugger, struct CLIDebuggerSys
|
|||
}
|
||||
|
||||
void CLIDebuggerAttachBackend(struct CLIDebugger* debugger, struct CLIDebuggerBackend* backend) {
|
||||
if (debugger->backend == backend) {
|
||||
return;
|
||||
}
|
||||
if (debugger->backend && debugger->backend->deinit) {
|
||||
debugger->backend->deinit(debugger->backend);
|
||||
}
|
||||
|
|
|
@ -465,11 +465,13 @@ void DSAttachDebugger(struct DS* ds, struct mDebugger* debugger) {
|
|||
}
|
||||
|
||||
void DSDetachDebugger(struct DS* ds) {
|
||||
ds->debugger = NULL;
|
||||
ARMHotplugDetach(ds->ds7.cpu, CPU_COMPONENT_DEBUGGER);
|
||||
ARMHotplugDetach(ds->ds9.cpu, CPU_COMPONENT_DEBUGGER);
|
||||
if (ds->debugger) {
|
||||
ARMHotplugDetach(ds->ds7.cpu, CPU_COMPONENT_DEBUGGER);
|
||||
ARMHotplugDetach(ds->ds9.cpu, CPU_COMPONENT_DEBUGGER);
|
||||
}
|
||||
ds->ds7.cpu->components[CPU_COMPONENT_DEBUGGER] = NULL;
|
||||
ds->ds9.cpu->components[CPU_COMPONENT_DEBUGGER] = NULL;
|
||||
ds->debugger = NULL;
|
||||
}
|
||||
|
||||
bool DSLoadROM(struct DS* ds, struct VFile* vf) {
|
||||
|
|
|
@ -640,8 +640,8 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) {
|
|||
audio->lastRight = sampleRight;
|
||||
audio->clock += audio->sampleInterval;
|
||||
if (audio->clock >= CLOCKS_PER_BLIP_FRAME) {
|
||||
blip_end_frame(audio->left, audio->clock);
|
||||
blip_end_frame(audio->right, audio->clock);
|
||||
blip_end_frame(audio->left, CLOCKS_PER_BLIP_FRAME);
|
||||
blip_end_frame(audio->right, CLOCKS_PER_BLIP_FRAME);
|
||||
audio->clock -= CLOCKS_PER_BLIP_FRAME;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -629,7 +629,19 @@ static size_t _GBCoreListAudioChannels(const struct mCore* core, const struct mC
|
|||
|
||||
static void _GBCoreEnableVideoLayer(struct mCore* core, size_t id, bool enable) {
|
||||
struct GB* gb = core->board;
|
||||
// TODO
|
||||
switch (id) {
|
||||
case 0:
|
||||
gb->video.renderer->disableBG = !enable;
|
||||
break;
|
||||
case 1:
|
||||
gb->video.renderer->disableOBJ = !enable;
|
||||
break;
|
||||
case 2:
|
||||
gb->video.renderer->disableWIN = !enable;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _GBCoreEnableAudioChannel(struct mCore* core, size_t id, bool enable) {
|
||||
|
|
|
@ -49,6 +49,10 @@ void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer* renderer) {
|
|||
renderer->d.getPixels = GBVideoSoftwareRendererGetPixels;
|
||||
renderer->d.putPixels = GBVideoSoftwareRendererPutPixels;
|
||||
|
||||
renderer->d.disableBG = false;
|
||||
renderer->d.disableOBJ = false;
|
||||
renderer->d.disableWIN = false;
|
||||
|
||||
renderer->temporaryBuffer = 0;
|
||||
}
|
||||
|
||||
|
@ -128,9 +132,12 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
|
|||
if (GBRegisterLCDCIsTileMap(softwareRenderer->lcdc)) {
|
||||
maps += GB_SIZE_MAP;
|
||||
}
|
||||
if (softwareRenderer->d.disableBG) {
|
||||
memset(&softwareRenderer->row[startX], 0, endX - startX);
|
||||
}
|
||||
if (GBRegisterLCDCIsBgEnable(softwareRenderer->lcdc) || softwareRenderer->model >= GB_MODEL_CGB) {
|
||||
if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && softwareRenderer->wy <= y && endX >= softwareRenderer->wx - 7) {
|
||||
if (softwareRenderer->wx - 7 > 0) {
|
||||
if (softwareRenderer->wx - 7 > 0 && !softwareRenderer->d.disableBG) {
|
||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, softwareRenderer->wx - 7, softwareRenderer->scx, softwareRenderer->scy + y);
|
||||
}
|
||||
|
||||
|
@ -138,15 +145,17 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
|
|||
if (GBRegisterLCDCIsWindowTileMap(softwareRenderer->lcdc)) {
|
||||
maps += GB_SIZE_MAP;
|
||||
}
|
||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, softwareRenderer->wx - 7, endX, 7 - softwareRenderer->wx, softwareRenderer->currentWy);
|
||||
} else {
|
||||
if (!softwareRenderer->d.disableWIN) {
|
||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, softwareRenderer->wx - 7, endX, 7 - softwareRenderer->wx, softwareRenderer->currentWy);
|
||||
}
|
||||
} else if (!softwareRenderer->d.disableBG) {
|
||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx, softwareRenderer->scy + y);
|
||||
}
|
||||
} else {
|
||||
} else if (!softwareRenderer->d.disableBG) {
|
||||
memset(&softwareRenderer->row[startX], 0, endX - startX);
|
||||
}
|
||||
|
||||
if (GBRegisterLCDCIsObjEnable(softwareRenderer->lcdc)) {
|
||||
if (GBRegisterLCDCIsObjEnable(softwareRenderer->lcdc) && !softwareRenderer->d.disableOBJ) {
|
||||
size_t i;
|
||||
for (i = 0; i < oamMax; ++i) {
|
||||
GBVideoSoftwareRendererDrawObj(softwareRenderer, &obj[i], startX, endX, y);
|
||||
|
|
|
@ -297,8 +297,8 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) {
|
|||
audio->lastRight = sampleRight;
|
||||
audio->clock += audio->sampleInterval;
|
||||
if (audio->clock >= CLOCKS_PER_FRAME) {
|
||||
blip_end_frame(audio->psg.left, audio->clock);
|
||||
blip_end_frame(audio->psg.right, audio->clock);
|
||||
blip_end_frame(audio->psg.left, CLOCKS_PER_FRAME);
|
||||
blip_end_frame(audio->psg.right, CLOCKS_PER_FRAME);
|
||||
audio->clock -= CLOCKS_PER_FRAME;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -271,7 +271,7 @@ static void _Div(struct GBA* gba, int32_t num, int32_t denom) {
|
|||
}
|
||||
}
|
||||
|
||||
static int16_t _ArcTan(int16_t i) {
|
||||
static int16_t _ArcTan(int32_t i, int32_t* r1, int32_t* r3) {
|
||||
int32_t a = -((i * i) >> 14);
|
||||
int32_t b = ((0xA9 * a) >> 14) + 0x390;
|
||||
b = ((b * a) >> 14) + 0x91C;
|
||||
|
@ -280,10 +280,16 @@ static int16_t _ArcTan(int16_t i) {
|
|||
b = ((b * a) >> 14) + 0x2081;
|
||||
b = ((b * a) >> 14) + 0x3651;
|
||||
b = ((b * a) >> 14) + 0xA2F9;
|
||||
if (r1) {
|
||||
*r1 = a;
|
||||
}
|
||||
if (r3) {
|
||||
*r3 = b;
|
||||
}
|
||||
return (i * b) >> 16;
|
||||
}
|
||||
|
||||
static int16_t _ArcTan2(int16_t x, int16_t y) {
|
||||
static int16_t _ArcTan2(int32_t x, int32_t y, int32_t* r1) {
|
||||
if (!y) {
|
||||
if (x >= 0) {
|
||||
return 0;
|
||||
|
@ -299,21 +305,21 @@ static int16_t _ArcTan2(int16_t x, int16_t y) {
|
|||
if (y >= 0) {
|
||||
if (x >= 0) {
|
||||
if (x >= y) {
|
||||
return _ArcTan((y << 14)/ x);
|
||||
return _ArcTan((y << 14) / x, r1, NULL);
|
||||
}
|
||||
} else if (-x >= y) {
|
||||
return _ArcTan((y << 14) / x) + 0x8000;
|
||||
return _ArcTan((y << 14) / x, r1, NULL) + 0x8000;
|
||||
}
|
||||
return 0x4000 - _ArcTan((x << 14) / y);
|
||||
return 0x4000 - _ArcTan((x << 14) / y, r1, NULL);
|
||||
} else {
|
||||
if (x <= 0) {
|
||||
if (-x > -y) {
|
||||
return _ArcTan((y << 14) / x) + 0x8000;
|
||||
return _ArcTan((y << 14) / x, r1, NULL) + 0x8000;
|
||||
}
|
||||
} else if (x >= -y) {
|
||||
return _ArcTan((y << 14) / x) + 0x10000;
|
||||
return _ArcTan((y << 14) / x, r1, NULL) + 0x10000;
|
||||
}
|
||||
return 0xC000 - _ArcTan((x << 14) / y);
|
||||
return 0xC000 - _ArcTan((x << 14) / y, r1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,10 +362,11 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
|
|||
cpu->gprs[0] = sqrt((uint32_t) cpu->gprs[0]);
|
||||
break;
|
||||
case 0x9:
|
||||
cpu->gprs[0] = (uint16_t) _ArcTan(cpu->gprs[0]);
|
||||
cpu->gprs[0] = _ArcTan(cpu->gprs[0], &cpu->gprs[1], &cpu->gprs[3]);
|
||||
break;
|
||||
case 0xA:
|
||||
cpu->gprs[0] = (uint16_t) _ArcTan2(cpu->gprs[0], cpu->gprs[1]);
|
||||
cpu->gprs[0] = (uint16_t) _ArcTan2(cpu->gprs[0], cpu->gprs[1], &cpu->gprs[1]);
|
||||
cpu->gprs[3] = 0x170;
|
||||
break;
|
||||
case 0xB:
|
||||
case 0xC:
|
||||
|
|
|
@ -268,6 +268,7 @@ static void GBAProcessEvents(struct ARMCore* cpu) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
void GBAAttachDebugger(struct GBA* gba, struct mDebugger* debugger) {
|
||||
gba->debugger = (struct ARMDebugger*) debugger->platform;
|
||||
gba->debugger->setSoftwareBreakpoint = _setSoftwareBreakpoint;
|
||||
|
@ -277,10 +278,13 @@ void GBAAttachDebugger(struct GBA* gba, struct mDebugger* debugger) {
|
|||
}
|
||||
|
||||
void GBADetachDebugger(struct GBA* gba) {
|
||||
gba->debugger = 0;
|
||||
ARMHotplugDetach(gba->cpu, CPU_COMPONENT_DEBUGGER);
|
||||
gba->cpu->components[CPU_COMPONENT_DEBUGGER] = 0;
|
||||
if (gba->debugger) {
|
||||
ARMHotplugDetach(gba->cpu, CPU_COMPONENT_DEBUGGER);
|
||||
}
|
||||
gba->cpu->components[CPU_COMPONENT_DEBUGGER] = NULL;
|
||||
gba->debugger = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool GBALoadMB(struct GBA* gba, struct VFile* vf) {
|
||||
GBAUnloadROM(gba);
|
||||
|
|
|
@ -581,10 +581,12 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
|
|||
}
|
||||
}
|
||||
}
|
||||
softwareRenderer->bg[2].sx += softwareRenderer->bg[2].dmx;
|
||||
softwareRenderer->bg[2].sy += softwareRenderer->bg[2].dmy;
|
||||
softwareRenderer->bg[3].sx += softwareRenderer->bg[3].dmx;
|
||||
softwareRenderer->bg[3].sy += softwareRenderer->bg[3].dmy;
|
||||
if (GBARegisterDISPCNTGetMode(softwareRenderer->dispcnt) != 0) {
|
||||
softwareRenderer->bg[2].sx += softwareRenderer->bg[2].dmx;
|
||||
softwareRenderer->bg[2].sy += softwareRenderer->bg[2].dmy;
|
||||
softwareRenderer->bg[3].sx += softwareRenderer->bg[3].dmx;
|
||||
softwareRenderer->bg[3].sy += softwareRenderer->bg[3].dmy;
|
||||
}
|
||||
|
||||
GBAVideoSoftwareRendererPostprocessBuffer(softwareRenderer);
|
||||
|
||||
|
|
|
@ -67,6 +67,10 @@ static void mGLContextResized(struct VideoBackend* v, unsigned w, unsigned h) {
|
|||
drawH = w * v->height / v->width;
|
||||
}
|
||||
}
|
||||
if (v->lockIntegerScaling) {
|
||||
drawW -= drawW % v->width;
|
||||
drawH -= drawH % v->height;
|
||||
}
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glClearColor(0, 0, 0, 0);
|
||||
|
|
|
@ -171,6 +171,10 @@ static void mGLES2ContextResized(struct VideoBackend* v, unsigned w, unsigned h)
|
|||
drawH = w * v->height / v->width;
|
||||
}
|
||||
}
|
||||
if (v->lockIntegerScaling) {
|
||||
drawW -= drawW % v->width;
|
||||
drawH -= drawH % v->height;
|
||||
}
|
||||
glViewport(0, 0, v->width, v->height);
|
||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include <psp2/display.h>
|
||||
#include <psp2/kernel/processmgr.h>
|
||||
#include <psp2/kernel/threadmgr.h>
|
||||
#include <psp2/moduleinfo.h>
|
||||
#include <psp2/power.h>
|
||||
#include <psp2/sysmodule.h>
|
||||
#include <psp2/touch.h>
|
||||
|
@ -164,6 +163,7 @@ int main() {
|
|||
mPSP2MapKey(&runner.params.keyMap, SCE_CTRL_RIGHT, GUI_INPUT_RIGHT);
|
||||
mPSP2MapKey(&runner.params.keyMap, SCE_CTRL_SQUARE, mGUI_INPUT_SCREEN_MODE);
|
||||
|
||||
scePowerSetArmClockFrequency(444);
|
||||
mGUIRunloop(&runner);
|
||||
|
||||
vita2d_fini();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include <mgba-util/memory.h>
|
||||
#include <mgba-util/circle-buffer.h>
|
||||
#include <mgba-util/math.h>
|
||||
#include <mgba-util/ring-fifo.h>
|
||||
#include <mgba-util/threading.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
@ -31,7 +32,6 @@
|
|||
#include <psp2/gxm.h>
|
||||
#include <psp2/kernel/sysmem.h>
|
||||
#include <psp2/motion.h>
|
||||
#include <psp2/power.h>
|
||||
|
||||
#include <vita2d.h>
|
||||
|
||||
|
@ -63,8 +63,8 @@ bool frameLimiter = true;
|
|||
extern const uint8_t _binary_backdrop_png_start[];
|
||||
static vita2d_texture* backdrop = 0;
|
||||
|
||||
#define PSP2_SAMPLES 128
|
||||
#define PSP2_AUDIO_BUFFER_SIZE (PSP2_SAMPLES * 40)
|
||||
#define PSP2_SAMPLES 256
|
||||
#define PSP2_AUDIO_BUFFER_SIZE (PSP2_SAMPLES * 20)
|
||||
|
||||
static struct mPSP2AudioContext {
|
||||
struct RingFIFO buffer;
|
||||
|
@ -176,7 +176,6 @@ void mPSP2Setup(struct mGUIRunner* runner) {
|
|||
mCoreConfigSetDefaultIntValue(&runner->config, "threadedVideo", 1);
|
||||
mCoreLoadForeignConfig(runner->core, &runner->config);
|
||||
|
||||
scePowerSetArmClockFrequency(333);
|
||||
mPSP2MapKey(&runner->core->inputMap, SCE_CTRL_CROSS, GBA_KEY_A);
|
||||
mPSP2MapKey(&runner->core->inputMap, SCE_CTRL_CIRCLE, GBA_KEY_B);
|
||||
mPSP2MapKey(&runner->core->inputMap, SCE_CTRL_START, GBA_KEY_START);
|
||||
|
@ -193,8 +192,10 @@ void mPSP2Setup(struct mGUIRunner* runner) {
|
|||
desc = (struct mInputAxis) { GBA_KEY_RIGHT, GBA_KEY_LEFT, 192, 64 };
|
||||
mInputBindAxis(&runner->core->inputMap, PSP2_INPUT, 1, &desc);
|
||||
|
||||
tex = vita2d_create_empty_texture_format(256, 256, SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR);
|
||||
screenshot = vita2d_create_empty_texture_format(256, 256, SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR);
|
||||
unsigned width, height;
|
||||
runner->core->desiredVideoDimensions(runner->core, &width, &height);
|
||||
tex = vita2d_create_empty_texture_format(256, toPow2(height), SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR);
|
||||
screenshot = vita2d_create_empty_texture_format(256, toPow2(height), SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR);
|
||||
|
||||
outputBuffer = vita2d_texture_get_datap(tex);
|
||||
runner->core->setVideoBuffer(runner->core, outputBuffer, 256);
|
||||
|
@ -219,7 +220,6 @@ void mPSP2Setup(struct mGUIRunner* runner) {
|
|||
}
|
||||
|
||||
void mPSP2LoadROM(struct mGUIRunner* runner) {
|
||||
scePowerSetArmClockFrequency(444);
|
||||
float rate = 60.0f / 1.001f;
|
||||
sceDisplayGetRefreshRate(&rate);
|
||||
double ratio = GBAAudioCalculateRatio(1, rate, 1);
|
||||
|
@ -262,7 +262,6 @@ void mPSP2PrepareForFrame(struct mGUIRunner* runner) {
|
|||
blip_clear(runner->core->getAudioChannel(runner->core, 1));
|
||||
break;
|
||||
}
|
||||
sceKernelDelayThread(400);
|
||||
}
|
||||
blip_read_samples(runner->core->getAudioChannel(runner->core, 0), &samples[0].left, PSP2_SAMPLES, true);
|
||||
blip_read_samples(runner->core->getAudioChannel(runner->core, 1), &samples[0].right, PSP2_SAMPLES, true);
|
||||
|
@ -297,7 +296,6 @@ void mPSP2UnloadROM(struct mGUIRunner* runner) {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
scePowerSetArmClockFrequency(333);
|
||||
}
|
||||
|
||||
void mPSP2Paused(struct mGUIRunner* runner) {
|
||||
|
|
|
@ -2,8 +2,13 @@ find_program(PYTHON python)
|
|||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py)
|
||||
|
||||
get_property(INCLUDE_DIRECTORIES DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
|
||||
set(INCLUDE_FLAGS)
|
||||
foreach(DIR IN LISTS INCLUDE_DIRECTORIES)
|
||||
list(APPEND INCLUDE_FLAGS "-I${DIR}")
|
||||
endforeach()
|
||||
add_custom_command(OUTPUT build/lib/${BINARY_NAME}/__init__.py
|
||||
COMMAND BINDIR=${CMAKE_CURRENT_BINARY_DIR}/.. ${PYTHON} ${CMAKE_CURRENT_BINARY_DIR}/setup.py build --build-base ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMAND BINDIR=${CMAKE_CURRENT_BINARY_DIR}/.. CPPFLAGS="${INCLUDE_FLAGS}" ${PYTHON} ${CMAKE_CURRENT_BINARY_DIR}/setup.py build --build-base ${CMAKE_CURRENT_BINARY_DIR}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DEPENDS ${BINARY_NAME}
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/setup.py
|
||||
|
|
|
@ -38,8 +38,16 @@ void DebuggerConsoleController::enterLine(const QString& line) {
|
|||
m_cond.wakeOne();
|
||||
}
|
||||
|
||||
void DebuggerConsoleController::detach() {
|
||||
m_lines.append(QString());
|
||||
m_cond.wakeOne();
|
||||
DebuggerController::detach();
|
||||
}
|
||||
|
||||
void DebuggerConsoleController::attachInternal() {
|
||||
m_history.clear();
|
||||
mCore* core = m_gameController->thread()->core;
|
||||
CLIDebuggerAttachBackend(&m_cliDebugger, &m_backend.d);
|
||||
CLIDebuggerAttachSystem(&m_cliDebugger, core->cliDebuggerSystem(core));
|
||||
}
|
||||
|
||||
|
@ -60,6 +68,8 @@ void DebuggerConsoleController::init(struct CLIDebuggerBackend* be) {
|
|||
void DebuggerConsoleController::deinit(struct CLIDebuggerBackend* be) {
|
||||
Backend* consoleBe = reinterpret_cast<Backend*>(be);
|
||||
DebuggerConsoleController* self = consoleBe->self;
|
||||
self->m_lines.append(QString());
|
||||
self->m_cond.wakeOne();
|
||||
}
|
||||
|
||||
const char* DebuggerConsoleController::readLine(struct CLIDebuggerBackend* be, size_t* len) {
|
||||
|
@ -71,6 +81,9 @@ const char* DebuggerConsoleController::readLine(struct CLIDebuggerBackend* be, s
|
|||
self->m_cond.wait(&self->m_mutex);
|
||||
}
|
||||
self->m_last = self->m_lines.takeFirst().toUtf8();
|
||||
if (self->m_last.isEmpty()) {
|
||||
self->m_last = "\n";
|
||||
}
|
||||
*len = self->m_last.size();
|
||||
return self->m_last.constData();
|
||||
|
||||
|
@ -87,6 +100,9 @@ const char* DebuggerConsoleController::historyLast(struct CLIDebuggerBackend* be
|
|||
DebuggerConsoleController* self = consoleBe->self;
|
||||
GameController::Interrupter interrupter(self->m_gameController, true);
|
||||
QMutexLocker lock(&self->m_mutex);
|
||||
if (self->m_history.isEmpty()) {
|
||||
return "\n";
|
||||
}
|
||||
self->m_last = self->m_history.last().toUtf8();
|
||||
return self->m_last.constData();
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ signals:
|
|||
|
||||
public slots:
|
||||
void enterLine(const QString&);
|
||||
virtual void detach() override;
|
||||
|
||||
protected:
|
||||
virtual void attachInternal() override;
|
||||
|
|
|
@ -54,6 +54,7 @@ Display* Display::create(QWidget* parent) {
|
|||
Display::Display(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_lockAspectRatio(false)
|
||||
, m_lockIntegerScaling(false)
|
||||
, m_filter(false)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
|
@ -78,6 +79,10 @@ QSize Display::viewportSize() {
|
|||
ds.setHeight(s.width() * m_coreHeight / m_coreWidth);
|
||||
}
|
||||
}
|
||||
if (isIntegerScalingLocked()) {
|
||||
ds.setWidth(ds.width() - ds.width() % m_coreWidth);
|
||||
ds.setHeight(ds.height() - ds.height() % m_coreHeight);
|
||||
}
|
||||
return ds;
|
||||
}
|
||||
|
||||
|
@ -90,6 +95,10 @@ void Display::lockAspectRatio(bool lock) {
|
|||
m_messagePainter.resize(size(), m_lockAspectRatio, devicePixelRatio());
|
||||
}
|
||||
|
||||
void Display::lockIntegerScaling(bool lock) {
|
||||
m_lockIntegerScaling = lock;
|
||||
}
|
||||
|
||||
void Display::filter(bool filter) {
|
||||
m_filter = filter;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
static void setDriver(Driver driver) { s_driver = driver; }
|
||||
|
||||
bool isAspectRatioLocked() const { return m_lockAspectRatio; }
|
||||
bool isIntegerScalingLocked() const { return m_lockIntegerScaling; }
|
||||
bool isFiltered() const { return m_filter; }
|
||||
|
||||
virtual bool isDrawing() const = 0;
|
||||
|
@ -57,6 +58,7 @@ public slots:
|
|||
virtual void unpauseDrawing() = 0;
|
||||
virtual void forceDraw() = 0;
|
||||
virtual void lockAspectRatio(bool lock);
|
||||
virtual void lockIntegerScaling(bool lock);
|
||||
virtual void filter(bool filter);
|
||||
virtual void framePosted(const uint32_t*) = 0;
|
||||
virtual void setShaders(struct VDir*) = 0;
|
||||
|
@ -78,6 +80,7 @@ private:
|
|||
|
||||
MessagePainter m_messagePainter;
|
||||
bool m_lockAspectRatio;
|
||||
bool m_lockIntegerScaling;
|
||||
bool m_filter;
|
||||
QTimer m_mouseTimer;
|
||||
int m_coreWidth;
|
||||
|
|
|
@ -73,6 +73,8 @@ void DisplayGL::startDrawing(mCoreThread* thread) {
|
|||
mCoreSyncSetVideoSync(&m_context->sync, false);
|
||||
|
||||
lockAspectRatio(isAspectRatioLocked());
|
||||
lockIntegerScaling(isIntegerScalingLocked());
|
||||
|
||||
unsigned width, height;
|
||||
thread->core->desiredVideoDimensions(thread->core, &width, &height);
|
||||
setSystemDimensions(width, height);
|
||||
|
@ -140,6 +142,13 @@ void DisplayGL::lockAspectRatio(bool lock) {
|
|||
}
|
||||
}
|
||||
|
||||
void DisplayGL::lockIntegerScaling(bool lock) {
|
||||
Display::lockIntegerScaling(lock);
|
||||
if (m_drawThread) {
|
||||
QMetaObject::invokeMethod(m_painter, "lockIntegerScaling", Q_ARG(bool, lock));
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayGL::filter(bool filter) {
|
||||
Display::filter(filter);
|
||||
if (m_drawThread) {
|
||||
|
@ -294,6 +303,13 @@ void PainterGL::lockAspectRatio(bool lock) {
|
|||
}
|
||||
}
|
||||
|
||||
void PainterGL::lockIntegerScaling(bool lock) {
|
||||
m_backend->lockIntegerScaling = lock;
|
||||
if (m_started && !m_active) {
|
||||
forceDraw();
|
||||
}
|
||||
}
|
||||
|
||||
void PainterGL::filter(bool filter) {
|
||||
m_backend->filter = filter;
|
||||
if (m_started && !m_active) {
|
||||
|
|
|
@ -55,6 +55,7 @@ public slots:
|
|||
void unpauseDrawing() override;
|
||||
void forceDraw() override;
|
||||
void lockAspectRatio(bool lock) override;
|
||||
void lockIntegerScaling(bool lock) override;
|
||||
void filter(bool filter) override;
|
||||
void framePosted(const uint32_t*) override;
|
||||
void setShaders(struct VDir*) override;
|
||||
|
@ -96,6 +97,7 @@ public slots:
|
|||
void unpause();
|
||||
void resize(const QSize& size);
|
||||
void lockAspectRatio(bool lock);
|
||||
void lockIntegerScaling(bool lock);
|
||||
void filter(bool filter);
|
||||
|
||||
void setShaders(struct VDir*);
|
||||
|
|
|
@ -31,6 +31,11 @@ void DisplayQt::lockAspectRatio(bool lock) {
|
|||
update();
|
||||
}
|
||||
|
||||
void DisplayQt::lockIntegerScaling(bool lock) {
|
||||
Display::lockIntegerScaling(lock);
|
||||
update();
|
||||
}
|
||||
|
||||
void DisplayQt::filter(bool filter) {
|
||||
Display::filter(filter);
|
||||
update();
|
||||
|
|
|
@ -30,6 +30,7 @@ public slots:
|
|||
void unpauseDrawing() override { m_isDrawing = true; }
|
||||
void forceDraw() override { update(); }
|
||||
void lockAspectRatio(bool lock) override;
|
||||
void lockIntegerScaling(bool lock) override;
|
||||
void filter(bool filter) override;
|
||||
void framePosted(const uint32_t*) override;
|
||||
void setShaders(struct VDir*) override {}
|
||||
|
|
|
@ -623,6 +623,7 @@ void GameController::closeGame() {
|
|||
return;
|
||||
}
|
||||
|
||||
setDebugger(nullptr);
|
||||
if (mCoreThreadIsPaused(&m_threadContext)) {
|
||||
mCoreThreadUnpause(&m_threadContext);
|
||||
}
|
||||
|
|
|
@ -177,6 +177,7 @@ void SettingsView::updateConfig() {
|
|||
saveSetting("frameskip", m_ui.frameskip);
|
||||
saveSetting("fpsTarget", m_ui.fpsTarget);
|
||||
saveSetting("lockAspectRatio", m_ui.lockAspectRatio);
|
||||
saveSetting("lockIntegerScaling", m_ui.lockIntegerScaling);
|
||||
saveSetting("volume", m_ui.volume);
|
||||
saveSetting("mute", m_ui.mute);
|
||||
saveSetting("rewindEnable", m_ui.rewind);
|
||||
|
@ -260,6 +261,7 @@ void SettingsView::reloadConfig() {
|
|||
loadSetting("frameskip", m_ui.frameskip);
|
||||
loadSetting("fpsTarget", m_ui.fpsTarget);
|
||||
loadSetting("lockAspectRatio", m_ui.lockAspectRatio);
|
||||
loadSetting("lockIntegerScaling", m_ui.lockIntegerScaling);
|
||||
loadSetting("volume", m_ui.volume);
|
||||
loadSetting("mute", m_ui.mute);
|
||||
loadSetting("rewindEnable", m_ui.rewind);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>650</width>
|
||||
<height>450</height>
|
||||
<height>454</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -115,7 +115,7 @@
|
|||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="currentText" stdset="0">
|
||||
<property name="currentText">
|
||||
<string>1536</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
|
@ -181,7 +181,7 @@
|
|||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="currentText" stdset="0">
|
||||
<property name="currentText">
|
||||
<string>44100</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
|
@ -380,13 +380,20 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<item row="12" column="1">
|
||||
<widget class="QCheckBox" name="resampleVideo">
|
||||
<property name="text">
|
||||
<string>Bilinear filtering</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QCheckBox" name="lockIntegerScaling">
|
||||
<property name="text">
|
||||
<string>Force integer scaling</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="interface_2">
|
||||
|
|
|
@ -493,6 +493,7 @@ void Window::selectPatch() {
|
|||
|
||||
void Window::openView(QWidget* widget) {
|
||||
connect(this, SIGNAL(shutdown()), widget, SLOT(close()));
|
||||
connect(m_controller, SIGNAL(gameStopped(mCoreThread*)), widget, SLOT(close()));
|
||||
widget->setAttribute(Qt::WA_DeleteOnClose);
|
||||
widget->show();
|
||||
}
|
||||
|
@ -811,6 +812,39 @@ void Window::gameStarted(mCoreThread* context, const QString& fname) {
|
|||
m_hitUnimplementedBiosCall = false;
|
||||
m_fpsTimer.start();
|
||||
m_focusCheck.start();
|
||||
|
||||
m_controller->threadInterrupt();
|
||||
if (m_controller->isLoaded()) {
|
||||
mCore* core = m_controller->thread()->core;
|
||||
const mCoreChannelInfo* videoLayers;
|
||||
const mCoreChannelInfo* audioChannels;
|
||||
size_t nVideo = core->listVideoLayers(core, &videoLayers);
|
||||
size_t nAudio = core->listAudioChannels(core, &audioChannels);
|
||||
|
||||
if (nVideo) {
|
||||
for (size_t i = 0; i < nVideo; ++i) {
|
||||
QAction* action = new QAction(videoLayers[i].visibleName, m_videoLayers);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(true);
|
||||
connect(action, &QAction::triggered, [this, videoLayers, i](bool enable) {
|
||||
m_controller->setVideoLayerEnabled(videoLayers[i].id, enable);
|
||||
});
|
||||
m_videoLayers->addAction(action);
|
||||
}
|
||||
}
|
||||
if (nAudio) {
|
||||
for (size_t i = 0; i < nAudio; ++i) {
|
||||
QAction* action = new QAction(audioChannels[i].visibleName, m_audioChannels);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(true);
|
||||
connect(action, &QAction::triggered, [this, audioChannels, i](bool enable) {
|
||||
m_controller->setAudioChannelEnabled(audioChannels[i].id, enable);
|
||||
});
|
||||
m_audioChannels->addAction(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_controller->threadContinue();
|
||||
}
|
||||
|
||||
void Window::gameStopped() {
|
||||
|
@ -834,6 +868,9 @@ void Window::gameStopped() {
|
|||
m_screenWidget->setMinimumSize(m_display->minimumSize());
|
||||
|
||||
setMouseTracking(false);
|
||||
m_videoLayers->clear();
|
||||
m_audioChannels->clear();
|
||||
|
||||
m_fpsTimer.stop();
|
||||
m_focusCheck.stop();
|
||||
}
|
||||
|
@ -1301,6 +1338,14 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
}, this);
|
||||
m_config->updateOption("lockAspectRatio");
|
||||
|
||||
ConfigOption* lockIntegerScaling = m_config->addOption("lockIntegerScaling");
|
||||
lockIntegerScaling->addBoolean(tr("Force integer scaling"), avMenu);
|
||||
lockIntegerScaling->connect([this](const QVariant& value) {
|
||||
m_display->lockIntegerScaling(value.toBool());
|
||||
m_screenWidget->setLockIntegerScaling(value.toBool());
|
||||
}, this);
|
||||
m_config->updateOption("lockIntegerScaling");
|
||||
|
||||
ConfigOption* resampleVideo = m_config->addOption("resampleVideo");
|
||||
resampleVideo->addBoolean(tr("Bilinear filtering"), avMenu);
|
||||
resampleVideo->connect([this](const QVariant& value) {
|
||||
|
@ -1376,45 +1421,12 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
#endif
|
||||
|
||||
avMenu->addSeparator();
|
||||
QMenu* videoLayers = avMenu->addMenu(tr("Video layers"));
|
||||
m_inputModel->addMenu(videoLayers, avMenu);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
QAction* enableBg = new QAction(tr("Background %0").arg(i), videoLayers);
|
||||
enableBg->setCheckable(true);
|
||||
enableBg->setChecked(true);
|
||||
connect(enableBg, &QAction::triggered, [this, i](bool enable) { m_controller->setVideoLayerEnabled(i, enable); });
|
||||
addControlledAction(videoLayers, enableBg, QString("enableBG%0").arg(i));
|
||||
}
|
||||
m_videoLayers = avMenu->addMenu(tr("Video layers"));
|
||||
m_inputModel->addMenu(m_videoLayers, avMenu);
|
||||
|
||||
QAction* enableObj = new QAction(tr("OBJ (sprites)"), videoLayers);
|
||||
enableObj->setCheckable(true);
|
||||
enableObj->setChecked(true);
|
||||
connect(enableObj, &QAction::triggered, [this](bool enable) { m_controller->setVideoLayerEnabled(4, enable); });
|
||||
addControlledAction(videoLayers, enableObj, "enableOBJ");
|
||||
|
||||
QMenu* audioChannels = avMenu->addMenu(tr("Audio channels"));
|
||||
m_inputModel->addMenu(audioChannels, avMenu);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
QAction* enableCh = new QAction(tr("Channel %0").arg(i + 1), audioChannels);
|
||||
enableCh->setCheckable(true);
|
||||
enableCh->setChecked(true);
|
||||
connect(enableCh, &QAction::triggered, [this, i](bool enable) { m_controller->setAudioChannelEnabled(i, enable); });
|
||||
addControlledAction(audioChannels, enableCh, QString("enableCh%0").arg(i + 1));
|
||||
}
|
||||
|
||||
QAction* enableChA = new QAction(tr("Channel A"), audioChannels);
|
||||
enableChA->setCheckable(true);
|
||||
enableChA->setChecked(true);
|
||||
connect(enableChA, &QAction::triggered, [this, i](bool enable) { m_controller->setAudioChannelEnabled(4, enable); });
|
||||
addControlledAction(audioChannels, enableChA, QString("enableChA"));
|
||||
|
||||
QAction* enableChB = new QAction(tr("Channel B"), audioChannels);
|
||||
enableChB->setCheckable(true);
|
||||
enableChB->setChecked(true);
|
||||
connect(enableChB, &QAction::triggered, [this, i](bool enable) { m_controller->setAudioChannelEnabled(5, enable); });
|
||||
addControlledAction(audioChannels, enableChB, QString("enableChB"));
|
||||
m_audioChannels = avMenu->addMenu(tr("Audio channels"));
|
||||
m_inputModel->addMenu(m_audioChannels, avMenu);
|
||||
|
||||
QMenu* toolsMenu = menubar->addMenu(tr("&Tools"));
|
||||
m_inputModel->addMenu(toolsMenu);
|
||||
|
@ -1657,6 +1669,10 @@ void WindowBackground::setCenteredAspectRatio(int width, int height) {
|
|||
m_aspectHeight = height;
|
||||
}
|
||||
|
||||
void WindowBackground::setLockIntegerScaling(bool lock) {
|
||||
m_lockIntegerScaling = lock;
|
||||
}
|
||||
|
||||
void WindowBackground::paintEvent(QPaintEvent*) {
|
||||
const QPixmap* logo = pixmap();
|
||||
if (!logo) {
|
||||
|
@ -1680,6 +1696,10 @@ void WindowBackground::paintEvent(QPaintEvent*) {
|
|||
ds.setHeight(ds.width() * m_aspectHeight / m_aspectWidth);
|
||||
}
|
||||
}
|
||||
if (m_lockIntegerScaling) {
|
||||
ds.setWidth(ds.width() - ds.width() % m_aspectWidth);
|
||||
ds.setHeight(ds.height() - ds.height() % m_aspectHeight);
|
||||
}
|
||||
QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2);
|
||||
QRect full(origin, ds);
|
||||
painter.drawPixmap(full, *logo);
|
||||
|
|
|
@ -172,6 +172,8 @@ private:
|
|||
QTimer m_fpsTimer;
|
||||
QList<QString> m_mruFiles;
|
||||
QMenu* m_mruMenu;
|
||||
QMenu* m_videoLayers;
|
||||
QMenu* m_audioChannels;
|
||||
ShaderSelector* m_shaderView;
|
||||
bool m_fullscreenOnStart;
|
||||
QTimer m_focusCheck;
|
||||
|
@ -207,6 +209,7 @@ public:
|
|||
virtual QSize sizeHint() const override;
|
||||
void setLockAspectRatio(int width, int height);
|
||||
void setCenteredAspectRatio(int width, int height);
|
||||
void setLockIntegerScaling(bool lock);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent*) override;
|
||||
|
@ -216,6 +219,7 @@ private:
|
|||
bool m_centered;
|
||||
int m_aspectWidth;
|
||||
int m_aspectHeight;
|
||||
bool m_lockIntegerScaling;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ struct VideoBackend {
|
|||
|
||||
bool filter;
|
||||
bool lockAspectRatio;
|
||||
bool lockIntegerScaling;
|
||||
};
|
||||
|
||||
struct VideoShader {
|
||||
|
|
Loading…
Reference in New Issue