mirror of
https://github.com/libretro/mgba.git
synced 2024-11-23 16:10:01 +00:00
This commit is contained in:
commit
89aece49ce
3
CHANGES
3
CHANGES
@ -27,7 +27,7 @@ Features:
|
||||
- Undo-able savestate loading and saving
|
||||
- Controller profiles now store shortcut settings
|
||||
- Default controller profiles for several common controllers
|
||||
- Libretro now supports BIOS and rumble
|
||||
- Libretro now supports BIOS, rumble and solar sensor
|
||||
- Implement BIOS call Stop, for sleep mode
|
||||
Bugfixes:
|
||||
- ARM7: Fix SWI and IRQ timings
|
||||
@ -64,6 +64,7 @@ Bugfixes:
|
||||
- Qt: Fix a missing va_end call in the log handler lambda within the GameController constructor
|
||||
- GBA Cheats: Fix Pro Action Replay and GameShark issues when used together
|
||||
- Qt: Fix analog buttons not getting unmapped
|
||||
- GBA Video: Prevent tiles < 512 from being used in modes 3 - 5
|
||||
Misc:
|
||||
- Qt: Handle saving input settings better
|
||||
- Debugger: Free watchpoints in addition to breakpoints
|
||||
|
@ -21,6 +21,7 @@ set(BUILD_PERF OFF CACHE BOOL "Build performance profiling tool")
|
||||
set(BUILD_STATIC OFF CACHE BOOL "Build a static library")
|
||||
set(BUILD_SHARED ON CACHE BOOL "Build a shared library")
|
||||
set(BUILD_GL ON CACHE STRING "Build with OpenGL")
|
||||
set(BUILD_GLES2 OFF CACHE STRING "Build with OpenGL|ES 2")
|
||||
file(GLOB ARM_SRC ${CMAKE_SOURCE_DIR}/src/arm/*.c)
|
||||
file(GLOB GBA_SRC ${CMAKE_SOURCE_DIR}/src/gba/*.c)
|
||||
file(GLOB GBA_CHEATS_SRC ${CMAKE_SOURCE_DIR}/src/gba/cheats/*.c)
|
||||
@ -125,7 +126,14 @@ endif()
|
||||
if(BUILD_GL)
|
||||
find_package(OpenGL QUIET)
|
||||
if(NOT OPENGL_FOUND)
|
||||
set(BUILD_GL OFF)
|
||||
set(BUILD_GL OFF CACHE BOOL "OpenGL not found" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
if(BUILD_GLES2 AND NOT BUILD_RASPI)
|
||||
find_path(OPENGLES2_INCLUDE_DIR NAMES GLES2/gl2.h)
|
||||
find_library(OPENGLES2_LIBRARY NAMES GLESv2 GLESv2_CM)
|
||||
if(NOT OPENGLES2_INCLUDE_DIR OR NOT OPENGLES2_LIBRARY)
|
||||
set(BUILD_GLES2 OFF CACHE BOOL "OpenGL|ES 2 not found" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
find_feature(USE_FFMPEG "libavcodec;libavformat;libavresample;libavutil;libswscale")
|
||||
@ -176,6 +184,10 @@ if(BUILD_BBB OR BUILD_RASPI OR BUILD_PANDORA)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_RASPI)
|
||||
set(BUILD_GL OFF CACHE BOOL "OpenGL not supported" FORCE)
|
||||
endif()
|
||||
|
||||
if(BUILD_PANDORA)
|
||||
add_definitions(-DBUILD_PANDORA)
|
||||
endif()
|
||||
@ -366,6 +378,7 @@ endif()
|
||||
|
||||
if(BUILD_SHARED)
|
||||
add_library(${BINARY_NAME} SHARED ${SRC})
|
||||
set_target_properties(${BINARY_NAME} PROPERTIES SOVERSION ${LIB_VERSION_ABI})
|
||||
if(BUILD_STATIC)
|
||||
add_library(${BINARY_NAME}-static STATIC ${SRC})
|
||||
set_target_properties(${BINARY_NAME}-static PROPERTIES COMPILE_DEFINITIONS "${FEATURE_DEFINES}")
|
||||
@ -379,7 +392,7 @@ endif()
|
||||
add_dependencies(${BINARY_NAME} version-info)
|
||||
|
||||
target_link_libraries(${BINARY_NAME} ${DEBUGGER_LIB} ${DEPENDENCY_LIB} ${OS_LIB})
|
||||
install(TARGETS ${BINARY_NAME} DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME})
|
||||
install(TARGETS ${BINARY_NAME} LIBRARY DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME} NAMELINK_SKIP ARCHIVE DESTINATION ${LIBDIR} RUNTIME DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME})
|
||||
if(UNIX AND NOT APPLE)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/res/mgba-16.png DESTINATION share/icons/hicolor/16x16/apps RENAME mgba.png COMPONENT lib${BINARY_NAME})
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/res/mgba-24.png DESTINATION share/icons/hicolor/24x24/apps RENAME mgba.png COMPONENT lib${BINARY_NAME})
|
||||
@ -397,6 +410,10 @@ if(BUILD_GL)
|
||||
add_definitions(-DBUILD_GL)
|
||||
endif()
|
||||
|
||||
if(BUILD_GLES2)
|
||||
add_definitions(-DBUILD_GLES2)
|
||||
endif()
|
||||
|
||||
if(BUILD_LIBRETRO)
|
||||
file(GLOB RETRO_SRC ${CMAKE_SOURCE_DIR}/src/platform/libretro/*.c)
|
||||
add_library(${BINARY_NAME}_libretro SHARED ${CORE_SRC} ${RETRO_SRC})
|
||||
|
@ -126,8 +126,6 @@ Footnotes
|
||||
- OBJ window for modes 3, 4 and 5 ([Bug #5](http://mgba.io/b/5))
|
||||
- Mosaic for transformed OBJs ([Bug #9](http://mgba.io/b/9))
|
||||
- BIOS call RegisterRamReset is partially stubbed out ([Bug #141](http://mgba.io/b/141))
|
||||
- Game Pak prefetch ([Bug #195](http://mgba.io/b/195))
|
||||
- BIOS call Stop, for entering sleep mode ([Bug #199](http://mgba.io/b/199))
|
||||
|
||||
<a name="flashdetect">[2]</a> Flash memory size detection does not work in some cases. These can be configured at runtime, but filing a bug is recommended if such a case is encountered.
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 525 KiB After Width: | Height: | Size: 518 KiB |
@ -56,6 +56,8 @@ static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
|
||||
{ "b/a", _setBreakpointARM, CLIDVParse, "Set a software breakpoint as ARM" },
|
||||
{ "b/t", _setBreakpointThumb, CLIDVParse, "Set a software breakpoint as Thumb" },
|
||||
{ "break", _setBreakpoint, CLIDVParse, "Set a breakpoint" },
|
||||
{ "break/a", _setBreakpointARM, CLIDVParse, "Set a software breakpoint as ARM" },
|
||||
{ "break/t", _setBreakpointThumb, CLIDVParse, "Set a software breakpoint as Thumb" },
|
||||
{ "c", _continue, 0, "Continue execution" },
|
||||
{ "continue", _continue, 0, "Continue execution" },
|
||||
{ "d", _clearBreakpoint, CLIDVParse, "Delete a breakpoint" },
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "gba/serialize.h"
|
||||
#include "util/hash.h"
|
||||
|
||||
const int GBA_LUX_LEVELS[10] = { 5, 11, 18, 27, 42, 62, 84, 109, 139, 183 };
|
||||
|
||||
static void _readPins(struct GBACartridgeHardware* hw);
|
||||
static void _outputPins(struct GBACartridgeHardware* hw, unsigned pins);
|
||||
|
||||
|
@ -79,6 +79,8 @@ struct GBARotationSource {
|
||||
int32_t (*readGyroZ)(struct GBARotationSource*);
|
||||
};
|
||||
|
||||
extern const int GBA_LUX_LEVELS[10];
|
||||
|
||||
struct GBALuminanceSource {
|
||||
void (*sample)(struct GBALuminanceSource*);
|
||||
|
||||
|
@ -634,8 +634,12 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||
#define STORE_VRAM \
|
||||
if ((address & 0x0001FFFF) < SIZE_VRAM) { \
|
||||
STORE_32(value, address & 0x0001FFFC, gba->video.renderer->vram); \
|
||||
gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC) + 2); \
|
||||
gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC)); \
|
||||
} else { \
|
||||
STORE_32(value, address & 0x00017FFC, gba->video.renderer->vram); \
|
||||
gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC) + 2); \
|
||||
gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC)); \
|
||||
} \
|
||||
wait += waitstatesRegion[REGION_VRAM];
|
||||
|
||||
@ -728,8 +732,10 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle
|
||||
case REGION_VRAM:
|
||||
if ((address & 0x0001FFFF) < SIZE_VRAM) {
|
||||
STORE_16(value, address & 0x0001FFFE, gba->video.renderer->vram);
|
||||
gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
|
||||
} else {
|
||||
STORE_16(value, address & 0x00017FFE, gba->video.renderer->vram);
|
||||
gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x00017FFE);
|
||||
}
|
||||
break;
|
||||
case REGION_OAM:
|
||||
@ -794,8 +800,8 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo
|
||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
|
||||
break;
|
||||
}
|
||||
((int8_t*) gba->video.renderer->vram)[address & 0x1FFFE] = value;
|
||||
((int8_t*) gba->video.renderer->vram)[(address & 0x1FFFE) | 1] = value;
|
||||
gba->video.renderer->vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8);
|
||||
gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
|
||||
break;
|
||||
case REGION_OAM:
|
||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
|
||||
|
@ -116,6 +116,9 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
|
||||
x >>= 23;
|
||||
uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1];
|
||||
unsigned charBase = GBAObjAttributesCGetTile(sprite->c) * 0x20;
|
||||
if (GBARegisterDISPCNTGetMode(renderer->dispcnt) >= 3 && GBAObjAttributesCGetTile(sprite->c) < 512) {
|
||||
return 0;
|
||||
}
|
||||
int variant = renderer->target1Obj && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
|
||||
if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT) {
|
||||
int target2 = renderer->target2Bd << 4;
|
||||
|
@ -13,6 +13,7 @@
|
||||
static void GBAVideoSoftwareRendererInit(struct GBAVideoRenderer* renderer);
|
||||
static void GBAVideoSoftwareRendererDeinit(struct GBAVideoRenderer* renderer);
|
||||
static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer);
|
||||
static void GBAVideoSoftwareRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address);
|
||||
static void GBAVideoSoftwareRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam);
|
||||
static void GBAVideoSoftwareRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
|
||||
static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
|
||||
@ -46,6 +47,7 @@ void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) {
|
||||
renderer->d.reset = GBAVideoSoftwareRendererReset;
|
||||
renderer->d.deinit = GBAVideoSoftwareRendererDeinit;
|
||||
renderer->d.writeVideoRegister = GBAVideoSoftwareRendererWriteVideoRegister;
|
||||
renderer->d.writeVRAM = GBAVideoSoftwareRendererWriteVRAM;
|
||||
renderer->d.writeOAM = GBAVideoSoftwareRendererWriteOAM;
|
||||
renderer->d.writePalette = GBAVideoSoftwareRendererWritePalette;
|
||||
renderer->d.drawScanline = GBAVideoSoftwareRendererDrawScanline;
|
||||
@ -327,6 +329,11 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
|
||||
return value;
|
||||
}
|
||||
|
||||
static void GBAVideoSoftwareRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) {
|
||||
UNUSED(renderer);
|
||||
UNUSED(address);
|
||||
}
|
||||
|
||||
static void GBAVideoSoftwareRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam) {
|
||||
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
|
||||
softwareRenderer->oamDirty = 1;
|
||||
|
@ -17,6 +17,7 @@ static void GBAVideoDummyRendererInit(struct GBAVideoRenderer* renderer);
|
||||
static void GBAVideoDummyRendererReset(struct GBAVideoRenderer* renderer);
|
||||
static void GBAVideoDummyRendererDeinit(struct GBAVideoRenderer* renderer);
|
||||
static uint16_t GBAVideoDummyRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
|
||||
static void GBAVideoDummyRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address);
|
||||
static void GBAVideoDummyRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
|
||||
static void GBAVideoDummyRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam);
|
||||
static void GBAVideoDummyRendererDrawScanline(struct GBAVideoRenderer* renderer, int y);
|
||||
@ -47,6 +48,7 @@ static struct GBAVideoRenderer dummyRenderer = {
|
||||
.reset = GBAVideoDummyRendererReset,
|
||||
.deinit = GBAVideoDummyRendererDeinit,
|
||||
.writeVideoRegister = GBAVideoDummyRendererWriteVideoRegister,
|
||||
.writeVRAM = GBAVideoDummyRendererWriteVRAM,
|
||||
.writePalette = GBAVideoDummyRendererWritePalette,
|
||||
.writeOAM = GBAVideoDummyRendererWriteOAM,
|
||||
.drawScanline = GBAVideoDummyRendererDrawScanline,
|
||||
@ -222,6 +224,12 @@ static uint16_t GBAVideoDummyRendererWriteVideoRegister(struct GBAVideoRenderer*
|
||||
return value;
|
||||
}
|
||||
|
||||
static void GBAVideoDummyRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) {
|
||||
UNUSED(renderer);
|
||||
UNUSED(address);
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
static void GBAVideoDummyRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
|
||||
UNUSED(renderer);
|
||||
UNUSED(address);
|
||||
|
@ -161,6 +161,7 @@ struct GBAVideoRenderer {
|
||||
void (*deinit)(struct GBAVideoRenderer* renderer);
|
||||
|
||||
uint16_t (*writeVideoRegister)(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
|
||||
void (*writeVRAM)(struct GBAVideoRenderer* renderer, uint32_t address);
|
||||
void (*writePalette)(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
|
||||
void (*writeOAM)(struct GBAVideoRenderer* renderer, uint32_t oam);
|
||||
void (*drawScanline)(struct GBAVideoRenderer* renderer, int y);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "util/common.h"
|
||||
|
||||
#include "gba/gba.h"
|
||||
#include "gba/interface.h"
|
||||
#include "gba/renderers/video-software.h"
|
||||
#include "gba/serialize.h"
|
||||
#include "gba/supervisor/overrides.h"
|
||||
@ -18,6 +19,8 @@
|
||||
#define SAMPLES 1024
|
||||
#define RUMBLE_PWM 35
|
||||
|
||||
#define SOLAR_SENSOR_LEVEL "mgba_solar_sensor_level"
|
||||
|
||||
static retro_environment_t environCallback;
|
||||
static retro_video_refresh_t videoCallback;
|
||||
static retro_audio_sample_batch_t audioCallback;
|
||||
@ -31,6 +34,8 @@ static void GBARetroLog(struct GBAThread* thread, enum GBALogLevel level, const
|
||||
static void _postAudioBuffer(struct GBAAVStream*, struct GBAAudio* audio);
|
||||
static void _postVideoFrame(struct GBAAVStream*, struct GBAVideoRenderer* renderer);
|
||||
static void _setRumble(struct GBARumble* rumble, int enable);
|
||||
static uint8_t _readLux(struct GBALuminanceSource* lux);
|
||||
static void _updateLux(struct GBALuminanceSource* lux);
|
||||
|
||||
static struct GBA gba;
|
||||
static struct ARMCore cpu;
|
||||
@ -44,6 +49,8 @@ static struct GBAAVStream stream;
|
||||
static int rumbleLevel;
|
||||
static struct CircleBuffer rumbleHistory;
|
||||
static struct GBARumble rumble;
|
||||
static struct GBALuminanceSource lux;
|
||||
static int luxLevel;
|
||||
|
||||
unsigned retro_api_version(void) {
|
||||
return RETRO_API_VERSION;
|
||||
@ -51,6 +58,13 @@ unsigned retro_api_version(void) {
|
||||
|
||||
void retro_set_environment(retro_environment_t env) {
|
||||
environCallback = env;
|
||||
|
||||
struct retro_variable vars[] = {
|
||||
{ SOLAR_SENSOR_LEVEL, "Solar sensor level; 0|1|2|3|4|5|6|7|8|9|10" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
environCallback(RETRO_ENVIRONMENT_SET_VARIABLES, vars);
|
||||
}
|
||||
|
||||
void retro_set_video_refresh(retro_video_refresh_t video) {
|
||||
@ -119,7 +133,9 @@ void retro_init(void) {
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L" }
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "Brighten Solar Sensor" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "Darken Solar Sensor" }
|
||||
};
|
||||
environCallback(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, &inputDescriptors);
|
||||
|
||||
@ -134,6 +150,11 @@ void retro_init(void) {
|
||||
rumbleCallback = 0;
|
||||
}
|
||||
|
||||
luxLevel = 0;
|
||||
lux.readLuminance = _readLux;
|
||||
lux.sample = _updateLux;
|
||||
_updateLux(&lux);
|
||||
|
||||
struct retro_log_callback log;
|
||||
if (environCallback(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) {
|
||||
logCallback = log.log;
|
||||
@ -155,6 +176,7 @@ void retro_init(void) {
|
||||
if (rumbleCallback) {
|
||||
gba.rumble = &rumble;
|
||||
}
|
||||
gba.luminanceSource = &lux;
|
||||
rom = 0;
|
||||
|
||||
const char* sysDir = 0;
|
||||
@ -205,6 +227,26 @@ void retro_run(void) {
|
||||
keys |= (!!inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R)) << 8;
|
||||
keys |= (!!inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L)) << 9;
|
||||
|
||||
static bool wasAdjustingLux = false;
|
||||
if (wasAdjustingLux) {
|
||||
wasAdjustingLux = inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3) ||
|
||||
inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3);
|
||||
} else {
|
||||
if (inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3)) {
|
||||
++luxLevel;
|
||||
if (luxLevel > 10) {
|
||||
luxLevel = 10;
|
||||
}
|
||||
wasAdjustingLux = true;
|
||||
} else if (inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3)) {
|
||||
--luxLevel;
|
||||
if (luxLevel < 0) {
|
||||
luxLevel = 0;
|
||||
}
|
||||
wasAdjustingLux = true;
|
||||
}
|
||||
}
|
||||
|
||||
int frameCount = gba.video.frameCounter;
|
||||
while (gba.video.frameCounter == frameCount) {
|
||||
ARMRunLoop(&cpu);
|
||||
@ -405,3 +447,40 @@ static void _setRumble(struct GBARumble* rumble, int enable) {
|
||||
CircleBufferWrite8(&rumbleHistory, enable);
|
||||
rumbleCallback(0, RETRO_RUMBLE_STRONG, rumbleLevel * 0xFFFF / RUMBLE_PWM);
|
||||
}
|
||||
|
||||
static void _updateLux(struct GBALuminanceSource* lux) {
|
||||
UNUSED(lux);
|
||||
struct retro_variable var = {
|
||||
.key = SOLAR_SENSOR_LEVEL,
|
||||
.value = 0
|
||||
};
|
||||
|
||||
bool updated = false;
|
||||
if (!environCallback(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) || !updated) {
|
||||
return;
|
||||
}
|
||||
if (!environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || !var.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
char* end;
|
||||
int newLuxLevel = strtol(var.value, &end, 10);
|
||||
if (!*end) {
|
||||
if (newLuxLevel > 10) {
|
||||
luxLevel = 10;
|
||||
} else if (newLuxLevel < 0) {
|
||||
luxLevel = 0;
|
||||
} else {
|
||||
luxLevel = newLuxLevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t _readLux(struct GBALuminanceSource* lux) {
|
||||
UNUSED(lux);
|
||||
int value = 0x16;
|
||||
if (luxLevel > 0) {
|
||||
value += GBA_LUX_LEVELS[luxLevel - 1];
|
||||
}
|
||||
return 0xFF - value;
|
||||
}
|
||||
|
136
src/platform/opengl/gles2.c
Normal file
136
src/platform/opengl/gles2.c
Normal file
@ -0,0 +1,136 @@
|
||||
/* 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/. */
|
||||
#include "gles2.h"
|
||||
|
||||
#include "gba/video.h"
|
||||
|
||||
static const char* const _vertexShader =
|
||||
"attribute vec4 position;\n"
|
||||
"varying vec2 texCoord;\n"
|
||||
|
||||
"void main() {\n"
|
||||
" gl_Position = position;\n"
|
||||
" texCoord = (position.st + vec2(1.0, -1.0)) * vec2(0.46875, -0.3125);\n"
|
||||
"}";
|
||||
|
||||
static const char* const _fragmentShader =
|
||||
"varying vec2 texCoord;\n"
|
||||
"uniform sampler2D tex;\n"
|
||||
|
||||
"void main() {\n"
|
||||
" vec4 color = texture2D(tex, texCoord);\n"
|
||||
" color.a = 1.;\n"
|
||||
" gl_FragColor = color;"
|
||||
"}";
|
||||
|
||||
static const GLfloat _vertices[] = {
|
||||
-1.f, -1.f,
|
||||
-1.f, 1.f,
|
||||
1.f, 1.f,
|
||||
1.f, -1.f,
|
||||
};
|
||||
|
||||
static void GBAGLES2ContextInit(struct VideoBackend* v, WHandle handle) {
|
||||
UNUSED(handle);
|
||||
struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
|
||||
glGenTextures(1, &context->tex);
|
||||
glBindTexture(GL_TEXTURE_2D, context->tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
#ifdef COLOR_16_BIT
|
||||
#ifdef COLOR_5_6_5
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
|
||||
#endif
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
#endif
|
||||
|
||||
glShaderSource(context->fragmentShader, 1, (const GLchar**) &_fragmentShader, 0);
|
||||
glShaderSource(context->vertexShader, 1, (const GLchar**) &_vertexShader, 0);
|
||||
glAttachShader(context->program, context->vertexShader);
|
||||
glAttachShader(context->program, context->fragmentShader);
|
||||
char log[1024];
|
||||
glCompileShader(context->fragmentShader);
|
||||
glCompileShader(context->vertexShader);
|
||||
glGetShaderInfoLog(context->fragmentShader, 1024, 0, log);
|
||||
glGetShaderInfoLog(context->vertexShader, 1024, 0, log);
|
||||
glLinkProgram(context->program);
|
||||
glGetProgramInfoLog(context->program, 1024, 0, log);
|
||||
printf("%s\n", log);
|
||||
context->texLocation = glGetUniformLocation(context->program, "tex");
|
||||
context->positionLocation = glGetAttribLocation(context->program, "position");
|
||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||
}
|
||||
|
||||
static void GBAGLES2ContextDeinit(struct VideoBackend* v) {
|
||||
struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
|
||||
glDeleteTextures(1, &context->tex);
|
||||
}
|
||||
|
||||
static void GBAGLES2ContextResized(struct VideoBackend* v, int w, int h) {
|
||||
int drawW = w;
|
||||
int drawH = h;
|
||||
if (v->lockAspectRatio) {
|
||||
if (w * 2 > h * 3) {
|
||||
drawW = h * 3 / 2;
|
||||
} else if (w * 2 < h * 3) {
|
||||
drawH = w * 2 / 3;
|
||||
}
|
||||
}
|
||||
glViewport(0, 0, 240, 160);
|
||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glViewport((w - drawW) / 2, (h - drawH) / 2, drawW, drawH);
|
||||
}
|
||||
|
||||
static void GBAGLES2ContextClear(struct VideoBackend* v) {
|
||||
UNUSED(v);
|
||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void GBAGLES2ContextDrawFrame(struct VideoBackend* v) {
|
||||
struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
|
||||
glUseProgram(context->program);
|
||||
glUniform1i(context->texLocation, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, context->tex);
|
||||
glVertexAttribPointer(context->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, _vertices);
|
||||
glEnableVertexAttribArray(context->positionLocation);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
void GBAGLES2ContextPostFrame(struct VideoBackend* v, const void* frame) {
|
||||
struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
|
||||
glBindTexture(GL_TEXTURE_2D, context->tex);
|
||||
#ifdef COLOR_16_BIT
|
||||
#ifdef COLOR_5_6_5
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, frame);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frame);
|
||||
#endif
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, frame);
|
||||
#endif
|
||||
}
|
||||
|
||||
void GBAGLES2ContextCreate(struct GBAGLES2Context* context) {
|
||||
context->d.init = GBAGLES2ContextInit;
|
||||
context->d.deinit = GBAGLES2ContextDeinit;
|
||||
context->d.resized = GBAGLES2ContextResized;
|
||||
context->d.swap = 0;
|
||||
context->d.clear = GBAGLES2ContextClear;
|
||||
context->d.postFrame = GBAGLES2ContextPostFrame;
|
||||
context->d.drawFrame = GBAGLES2ContextDrawFrame;
|
||||
context->d.setMessage = 0;
|
||||
context->d.clearMessage = 0;
|
||||
}
|
27
src/platform/opengl/gles2.h
Normal file
27
src/platform/opengl/gles2.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* 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 GLES2_H
|
||||
#define GLES2_H
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#include "platform/video-backend.h"
|
||||
|
||||
struct GBAGLES2Context {
|
||||
struct VideoBackend d;
|
||||
|
||||
GLuint tex;
|
||||
GLuint fragmentShader;
|
||||
GLuint vertexShader;
|
||||
GLuint program;
|
||||
GLuint bufferObject;
|
||||
GLuint texLocation;
|
||||
GLuint positionLocation;
|
||||
};
|
||||
|
||||
void GBAGLES2ContextCreate(struct GBAGLES2Context*);
|
||||
|
||||
#endif
|
@ -186,7 +186,7 @@ static void _GBAPerfRunloop(struct GBAThread* context, int* frames, bool quiet)
|
||||
}
|
||||
}
|
||||
GBASyncWaitFrameEnd(&context->sync);
|
||||
if (*frames == duration) {
|
||||
if (duration > 0 && *frames == duration) {
|
||||
_GBAPerfShutdown(0);
|
||||
}
|
||||
if (_dispatchExiting) {
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef __FreeBSD__
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
@ -79,7 +79,7 @@ static inline int ThreadJoin(Thread thread) {
|
||||
static inline int ThreadSetName(const char* name) {
|
||||
#ifdef __APPLE__
|
||||
return pthread_setname_np(name);
|
||||
#elif defined(__FreeBSD__)
|
||||
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
pthread_set_name_np(pthread_self(), name);
|
||||
return 0;
|
||||
#else
|
||||
|
36
src/platform/qt/AboutScreen.cpp
Normal file
36
src/platform/qt/AboutScreen.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
/* 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/. */
|
||||
#include "AboutScreen.h"
|
||||
|
||||
#include "util/version.h"
|
||||
|
||||
#include <QPixmap>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
AboutScreen::AboutScreen(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
QPixmap logo(":/res/mgba-1024.png");
|
||||
logo = logo.scaled(m_ui.logo->minimumSize() * devicePixelRatio(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
logo.setDevicePixelRatio(devicePixelRatio());
|
||||
m_ui.logo->setPixmap(logo);
|
||||
|
||||
m_ui.projectName->setText(QLatin1String(projectName));
|
||||
m_ui.projectVersion->setText(QLatin1String(projectVersion));
|
||||
QString gitInfo = m_ui.gitInfo->text();
|
||||
gitInfo.replace("{gitBranch}", QLatin1String(gitBranch));
|
||||
gitInfo.replace("{gitCommit}", QLatin1String(gitCommit));
|
||||
m_ui.gitInfo->setText(gitInfo);
|
||||
QString description = m_ui.description->text();
|
||||
description.replace("{projectName}", QLatin1String(projectName));
|
||||
m_ui.description->setText(description);
|
||||
QString extraLinks = m_ui.extraLinks->text();
|
||||
extraLinks.replace("{gitBranch}", QLatin1String(gitBranch));
|
||||
m_ui.extraLinks->setText(extraLinks);
|
||||
}
|
27
src/platform/qt/AboutScreen.h
Normal file
27
src/platform/qt/AboutScreen.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* Copyright (c) 2013-2014 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 QGBA_ABOUT_SCREEN
|
||||
#define QGBA_ABOUT_SCREEN
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "ui_AboutScreen.h"
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class AboutScreen : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AboutScreen(QWidget* parent = nullptr);
|
||||
|
||||
private:
|
||||
Ui::AboutScreen m_ui;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
177
src/platform/qt/AboutScreen.ui
Normal file
177
src/platform/qt/AboutScreen.ui
Normal file
@ -0,0 +1,177 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AboutScreen</class>
|
||||
<widget class="QWidget" name="AboutScreen">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>565</width>
|
||||
<height>268</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>About</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetFixedSize</enum>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="projectName">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>36</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>{projectName}</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="4">
|
||||
<widget class="QLabel" name="copyright">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>© 2013 – 2015 Jeffrey Pfau — Game Boy Advance is a registered trademark of Nintendo Co., Ltd.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="projectVersion">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>{projectVersion}</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="6">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="logo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>256</width>
|
||||
<height>192</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>{logo}</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="description">
|
||||
<property name="text">
|
||||
<string>{projectName} is an open-source Game Boy Advance emulator</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="extraLinks">
|
||||
<property name="text">
|
||||
<string><a href="http://mgba.io/">Website</a> • <a href="https://forumsmgba.io/">Forums / Support</a> • <a href="https://github.com/mgba-emu/mgba/tree/{gitBranch}">Source</a> • <a href="https://github.com/mgba-emu/mgba/blob/{gitBranch}/LICENSE">License</a></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="gitInfo">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Branch: <tt>{gitBranch}</tt><br/>Revision: <tt>{gitCommit}</tt></string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -28,7 +28,9 @@ endif()
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
find_package(Qt5Multimedia)
|
||||
if(NOT WIN32 OR NOT BUILD_SDL)
|
||||
find_package(Qt5Multimedia)
|
||||
endif()
|
||||
find_package(Qt5OpenGL)
|
||||
find_package(Qt5Widgets)
|
||||
|
||||
@ -38,7 +40,13 @@ if(NOT Qt5OpenGL_FOUND OR NOT Qt5Widgets_FOUND OR NOT OPENGL_FOUND)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(BUILD_GL)
|
||||
list(APPEND PLATFORM_SRC ${PLATFORM_SRC} ${CMAKE_SOURCE_DIR}/src/platform/opengl/gl.c)
|
||||
endif()
|
||||
|
||||
if(BUILD_GLES2)
|
||||
list(APPEND PLATFORM_SRC ${PLATFORM_SRC} ${CMAKE_SOURCE_DIR}/src/platform/opengl/gles2.c)
|
||||
endif()
|
||||
|
||||
get_target_property(QT_TYPE Qt5::Core TYPE)
|
||||
if(QT_TYPE STREQUAL STATIC_LIBRARY)
|
||||
@ -47,6 +55,7 @@ if(QT_TYPE STREQUAL STATIC_LIBRARY)
|
||||
endif()
|
||||
|
||||
set(SOURCE_FILES
|
||||
AboutScreen.cpp
|
||||
AudioProcessor.cpp
|
||||
CheatsModel.cpp
|
||||
CheatsView.cpp
|
||||
@ -83,6 +92,7 @@ set(SOURCE_FILES
|
||||
VideoView.cpp)
|
||||
|
||||
qt5_wrap_ui(UI_FILES
|
||||
AboutScreen.ui
|
||||
CheatsView.ui
|
||||
GIFView.ui
|
||||
LoadSaveState.ui
|
||||
|
@ -135,7 +135,11 @@ PainterGL::PainterGL(QGLWidget* parent)
|
||||
, m_context(nullptr)
|
||||
, m_messagePainter(nullptr)
|
||||
{
|
||||
#ifdef BUILD_GL
|
||||
GBAGLContextCreate(&m_backend);
|
||||
#elif defined(BUILD_GLES2)
|
||||
GBAGLES2ContextCreate(&m_backend);
|
||||
#endif
|
||||
m_backend.d.swap = [](VideoBackend* v) {
|
||||
PainterGL* painter = static_cast<PainterGL*>(v->user);
|
||||
painter->m_gl->swapBuffers();
|
||||
|
@ -14,7 +14,11 @@
|
||||
#include <QTimer>
|
||||
|
||||
extern "C" {
|
||||
#ifdef BUILD_GL
|
||||
#include "platform/opengl/gl.h"
|
||||
#elif defined(BUILD_GLES2)
|
||||
#include "platform/opengl/gles2.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
struct GBAThread;
|
||||
@ -90,7 +94,11 @@ private:
|
||||
QGLWidget* m_gl;
|
||||
bool m_active;
|
||||
GBAThread* m_context;
|
||||
#ifdef BUILD_GL
|
||||
GBAGLContext m_backend;
|
||||
#elif defined(BUILD_GLES2)
|
||||
GBAGLES2Context m_backend;
|
||||
#endif
|
||||
QSize m_size;
|
||||
MessagePainter* m_messagePainter;
|
||||
};
|
||||
|
@ -29,8 +29,6 @@ extern "C" {
|
||||
using namespace QGBA;
|
||||
using namespace std;
|
||||
|
||||
const int GameController::LUX_LEVELS[10] = { 5, 11, 18, 27, 42, 62, 84, 109, 139, 183 };
|
||||
|
||||
GameController::GameController(QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_drawContext(new uint32_t[256 * 256])
|
||||
@ -794,7 +792,7 @@ void GameController::setLuminanceValue(uint8_t value) {
|
||||
value = std::max<int>(value - 0x16, 0);
|
||||
m_luxLevel = 10;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
if (value < LUX_LEVELS[i]) {
|
||||
if (value < GBA_LUX_LEVELS[i]) {
|
||||
m_luxLevel = i;
|
||||
break;
|
||||
}
|
||||
@ -806,7 +804,7 @@ void GameController::setLuminanceLevel(int level) {
|
||||
int value = 0x16;
|
||||
level = std::max(0, std::min(10, level));
|
||||
if (level > 0) {
|
||||
value += LUX_LEVELS[level - 1];
|
||||
value += GBA_LUX_LEVELS[level - 1];
|
||||
}
|
||||
setLuminanceValue(value);
|
||||
}
|
||||
|
@ -207,8 +207,6 @@ private:
|
||||
uint8_t m_luxValue;
|
||||
int m_luxLevel;
|
||||
|
||||
static const int LUX_LEVELS[10];
|
||||
|
||||
GBARTCGenericSource m_rtc;
|
||||
};
|
||||
|
||||
|
@ -208,9 +208,11 @@ void InputController::setPreferredGamepad(uint32_t type, const QString& device)
|
||||
|
||||
GBARumble* InputController::rumble() {
|
||||
#ifdef BUILD_SDL
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (m_playerAttached) {
|
||||
return &m_sdlPlayer.rumble.d;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
@ -497,19 +499,29 @@ bool InputController::hasPendingEvent(GBAKey key) const {
|
||||
return m_pendingEvents.contains(key);
|
||||
}
|
||||
|
||||
#if defined(BUILD_SDL) && SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
void InputController::suspendScreensaver() {
|
||||
#ifdef BUILD_SDL
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
GBASDLSuspendScreensaver(&s_sdlEvents);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputController::resumeScreensaver() {
|
||||
#ifdef BUILD_SDL
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
GBASDLResumeScreensaver(&s_sdlEvents);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputController::setScreensaverSuspendable(bool suspendable) {
|
||||
#ifdef BUILD_SDL
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
GBASDLSetScreensaverSuspendable(&s_sdlEvents, suspendable);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputController::stealFocus(QWidget* focus) {
|
||||
m_focusParent = focus;
|
||||
|
@ -87,12 +87,10 @@ signals:
|
||||
public slots:
|
||||
void testGamepad(int type);
|
||||
|
||||
#if defined(BUILD_SDL) && SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
// TODO: Move these to somewhere that makes sense
|
||||
void suspendScreensaver();
|
||||
void resumeScreensaver();
|
||||
void setScreensaverSuspendable(bool);
|
||||
#endif
|
||||
|
||||
private:
|
||||
void postPendingEvent(GBAKey);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <QPainter>
|
||||
#include <QStackedLayout>
|
||||
|
||||
#include "AboutScreen.h"
|
||||
#include "CheatsView.h"
|
||||
#include "ConfigController.h"
|
||||
#include "Display.h"
|
||||
@ -40,8 +41,8 @@ extern "C" {
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
#ifdef __WIN32
|
||||
// This is a macro everywhere except MinGW, it seems
|
||||
#if defined(__WIN32) || defined(__OpenBSD__)
|
||||
// This is a macro everywhere except MinGW and OpenBSD, it seems
|
||||
using std::isnan;
|
||||
#endif
|
||||
|
||||
@ -344,6 +345,11 @@ void Window::openMemoryWindow() {
|
||||
openView(memoryWindow);
|
||||
}
|
||||
|
||||
void Window::openAboutScreen() {
|
||||
AboutScreen* about = new AboutScreen();
|
||||
openView(about);
|
||||
}
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
void Window::openGamepadWindow() {
|
||||
const char* profile = m_inputController.profileForType(SDL_BINDING_BUTTON);
|
||||
@ -752,6 +758,14 @@ void Window::setupMenu(QMenuBar* menubar) {
|
||||
});
|
||||
addControlledAction(fileMenu, multiWindow, "multiWindow");
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
fileMenu->addSeparator();
|
||||
#endif
|
||||
|
||||
QAction* about = new QAction(tr("About"), fileMenu);
|
||||
connect(about, SIGNAL(triggered()), this, SLOT(openAboutScreen()));
|
||||
fileMenu->addAction(about);
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
addControlledAction(fileMenu, fileMenu->addAction(tr("E&xit"), this, SLOT(close()), QKeySequence::Quit), "quit");
|
||||
#endif
|
||||
@ -1214,11 +1228,11 @@ void WindowBackground::paintEvent(QPaintEvent*) {
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
painter.fillRect(QRect(QPoint(), size()), Qt::black);
|
||||
QSize s = size();
|
||||
QSize ds = s;
|
||||
if (s.width() * m_aspectHeight > s.height() * m_aspectWidth) {
|
||||
ds.setWidth(s.height() * m_aspectWidth / m_aspectHeight);
|
||||
} else if (s.width() * m_aspectHeight < s.height() * m_aspectWidth) {
|
||||
ds.setHeight(s.width() * m_aspectHeight / m_aspectWidth);
|
||||
QSize ds = s * 0.8;
|
||||
if (ds.width() * m_aspectHeight > ds.height() * m_aspectWidth) {
|
||||
ds.setWidth(ds.height() * m_aspectWidth / m_aspectHeight);
|
||||
} else if (ds.width() * m_aspectHeight < ds.height() * m_aspectWidth) {
|
||||
ds.setHeight(ds.width() * m_aspectHeight / m_aspectWidth);
|
||||
}
|
||||
QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2);
|
||||
QRect full(origin, ds);
|
||||
|
@ -82,6 +82,8 @@ public slots:
|
||||
void openPaletteWindow();
|
||||
void openMemoryWindow();
|
||||
|
||||
void openAboutScreen();
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
void openGamepadWindow();
|
||||
#endif
|
||||
|
@ -10,9 +10,11 @@
|
||||
#include <QtPlugin>
|
||||
#ifdef _WIN32
|
||||
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
|
||||
#ifdef BUILD_QT_MULTIMEDIA
|
||||
Q_IMPORT_PLUGIN(QWindowsAudioPlugin);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
QGBA::GBAApp application(argc, argv);
|
||||
|
@ -51,12 +51,14 @@ set(MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/main.c)
|
||||
|
||||
if(BUILD_RASPI)
|
||||
add_definitions(-DBUILD_RASPI)
|
||||
set(EGL_MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/egl-sdl.c)
|
||||
set(EGL_LIBRARY "-lEGL -lGLESv2 -lbcm_host")
|
||||
list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/opengl/gles2.c)
|
||||
list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/egl-sdl.c)
|
||||
set(OPENGLES2_LIBRARY "-lEGL -lGLESv2 -lbcm_host")
|
||||
set(BUILD_GLES2 ON CACHE BOOL "Using OpenGL|ES 2" FORCE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fgnu89-inline")
|
||||
add_executable(${BINARY_NAME}-rpi ${PLATFORM_SRC} ${MAIN_SRC} ${EGL_MAIN_SRC})
|
||||
add_executable(${BINARY_NAME}-rpi ${PLATFORM_SRC} ${MAIN_SRC})
|
||||
set_target_properties(${BINARY_NAME}-rpi PROPERTIES COMPILE_DEFINITIONS "${FEATURE_DEFINES}")
|
||||
target_link_libraries(${BINARY_NAME}-rpi ${BINARY_NAME} ${PLATFORM_LIBRARY} ${EGL_LIBRARY})
|
||||
target_link_libraries(${BINARY_NAME}-rpi ${BINARY_NAME} ${PLATFORM_LIBRARY} ${OPENGLES2_LIBRARY})
|
||||
install(TARGETS ${BINARY_NAME}-rpi DESTINATION bin COMPONENT ${BINARY_NAME}-rpi)
|
||||
endif()
|
||||
|
||||
@ -67,12 +69,12 @@ else()
|
||||
if(BUILD_GL)
|
||||
list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-sdl.c)
|
||||
list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/opengl/gl.c)
|
||||
include_directories(${OPENGL_INCLUDE_DIR})
|
||||
include_directories(${OPENGL_INCLUDE_DIR} ${OPENGLES2_INCLUDE_DIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_executable(${BINARY_NAME}-sdl WIN32 ${PLATFORM_SRC} ${MAIN_SRC})
|
||||
set_target_properties(${BINARY_NAME}-sdl PROPERTIES COMPILE_DEFINITIONS "${FEATURE_DEFINES}")
|
||||
target_link_libraries(${BINARY_NAME}-sdl ${BINARY_NAME} ${PLATFORM_LIBRARY} ${OPENGL_LIBRARY})
|
||||
target_link_libraries(${BINARY_NAME}-sdl ${BINARY_NAME} ${PLATFORM_LIBRARY} ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY})
|
||||
set_target_properties(${BINARY_NAME}-sdl PROPERTIES OUTPUT_NAME ${BINARY_NAME})
|
||||
install(TARGETS ${BINARY_NAME}-sdl DESTINATION bin COMPONENT ${BINARY_NAME}-sdl)
|
||||
|
@ -1,37 +1,26 @@
|
||||
/* Copyright (c) 2013-2014 Jeffrey Pfau
|
||||
/* 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/. */
|
||||
#include "main.h"
|
||||
|
||||
static const char* _vertexShader =
|
||||
"attribute vec4 position;\n"
|
||||
"varying vec2 texCoord;\n"
|
||||
static void _sdlSwap(struct VideoBackend* context) {
|
||||
UNUSED(context);
|
||||
SDL_GL_SwapBuffers();
|
||||
}
|
||||
|
||||
"void main() {\n"
|
||||
" gl_Position = position;\n"
|
||||
" texCoord = (position.st + vec2(1.0, -1.0)) * vec2(0.46875, -0.3125);\n"
|
||||
"}";
|
||||
static bool GBASDLGLES2Init(struct SDLSoftwareRenderer* renderer);
|
||||
static void GBASDLGLES2Runloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer);
|
||||
static void GBASDLGLES2Deinit(struct SDLSoftwareRenderer* renderer);
|
||||
|
||||
static const char* _fragmentShader =
|
||||
"varying vec2 texCoord;\n"
|
||||
"uniform sampler2D tex;\n"
|
||||
void GBASDLGLES2Create(struct SDLSoftwareRenderer* renderer) {
|
||||
renderer->init = GBASDLGLES2Init;
|
||||
renderer->deinit = GBASDLGLES2Deinit;
|
||||
renderer->runloop = GBASDLGLES2Runloop;
|
||||
}
|
||||
|
||||
"void main() {\n"
|
||||
" vec4 color = texture2D(tex, texCoord);\n"
|
||||
" color.a = 1.;\n"
|
||||
" gl_FragColor = color;"
|
||||
"}";
|
||||
|
||||
static const GLfloat _vertices[] = {
|
||||
-1.f, -1.f,
|
||||
-1.f, 1.f,
|
||||
1.f, 1.f,
|
||||
1.f, -1.f,
|
||||
};
|
||||
|
||||
bool GBASDLInit(struct SDLSoftwareRenderer* renderer) {
|
||||
bool GBASDLGLES2Init(struct SDLSoftwareRenderer* renderer) {
|
||||
bcm_host_init();
|
||||
renderer->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
int major, minor;
|
||||
@ -103,36 +92,19 @@ bool GBASDLInit(struct SDLSoftwareRenderer* renderer) {
|
||||
|
||||
renderer->d.outputBuffer = memalign(16, 256 * 256 * 4);
|
||||
renderer->d.outputBufferStride = 256;
|
||||
glGenTextures(1, &renderer->tex);
|
||||
glBindTexture(GL_TEXTURE_2D, renderer->tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
renderer->fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
renderer->vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
renderer->program = glCreateProgram();
|
||||
|
||||
glShaderSource(renderer->fragmentShader, 1, (const GLchar**) &_fragmentShader, 0);
|
||||
glShaderSource(renderer->vertexShader, 1, (const GLchar**) &_vertexShader, 0);
|
||||
glAttachShader(renderer->program, renderer->vertexShader);
|
||||
glAttachShader(renderer->program, renderer->fragmentShader);
|
||||
char log[1024];
|
||||
glCompileShader(renderer->fragmentShader);
|
||||
glCompileShader(renderer->vertexShader);
|
||||
glGetShaderInfoLog(renderer->fragmentShader, 1024, 0, log);
|
||||
glGetShaderInfoLog(renderer->vertexShader, 1024, 0, log);
|
||||
glLinkProgram(renderer->program);
|
||||
glGetProgramInfoLog(renderer->program, 1024, 0, log);
|
||||
printf("%s\n", log);
|
||||
renderer->texLocation = glGetUniformLocation(renderer->program, "tex");
|
||||
renderer->positionLocation = glGetAttribLocation(renderer->program, "position");
|
||||
glClearColor(1.f, 0.f, 0.f, 1.f);
|
||||
GBAGLES2ContextCreate(&renderer->gl);
|
||||
renderer->gl.d.user = renderer;
|
||||
renderer->gl.d.lockAspectRatio = renderer->lockAspectRatio;
|
||||
renderer->gl.d.filter = renderer->filter;
|
||||
renderer->gl.d.swap = _sdlSwap;
|
||||
renderer->gl.d.init(&renderer->gl.d, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GBASDLRunloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer) {
|
||||
void GBASDLGLES2Runloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer) {
|
||||
SDL_Event event;
|
||||
struct VideoBackend* v = &renderer->gl.d;
|
||||
|
||||
while (context->state < THREAD_EXITING) {
|
||||
while (SDL_PollEvent(&event)) {
|
||||
@ -140,27 +112,22 @@ void GBASDLRunloop(struct GBAThread* context, struct SDLSoftwareRenderer* render
|
||||
}
|
||||
|
||||
if (GBASyncWaitFrameStart(&context->sync, context->frameskip)) {
|
||||
glViewport(0, 0, 240, 160);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glUseProgram(renderer->program);
|
||||
glUniform1i(renderer->texLocation, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, renderer->tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, renderer->d.outputBuffer);
|
||||
glVertexAttribPointer(renderer->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, _vertices);
|
||||
glEnableVertexAttribArray(renderer->positionLocation);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glUseProgram(0);
|
||||
eglSwapBuffers(renderer->display, renderer->surface);
|
||||
v->postFrame(v, renderer->d.outputBuffer);
|
||||
}
|
||||
v->drawFrame(v);
|
||||
GBASyncWaitFrameEnd(&context->sync);
|
||||
eglSwapBuffers(renderer->display, renderer->surface);
|
||||
}
|
||||
}
|
||||
|
||||
void GBASDLDeinit(struct SDLSoftwareRenderer* renderer) {
|
||||
void GBASDLGLES2Deinit(struct SDLSoftwareRenderer* renderer) {
|
||||
if (renderer->gl.d.deinit) {
|
||||
renderer->gl.d.deinit(&renderer->gl.d);
|
||||
}
|
||||
eglMakeCurrent(renderer->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroySurface(renderer->display, renderer->surface);
|
||||
eglDestroyContext(renderer->display, renderer->context);
|
||||
eglTerminate(renderer->display);
|
||||
free(renderer->d.outputBuffer);
|
||||
bcm_host_deinit();
|
||||
}
|
||||
|
@ -86,6 +86,8 @@ int main(int argc, char** argv) {
|
||||
|
||||
#ifdef BUILD_GL
|
||||
GBASDLGLCreate(&renderer);
|
||||
#elif defined(BUILD_GLES2)
|
||||
GBASDLGLES2Create(&renderer);
|
||||
#else
|
||||
GBASDLSWCreate(&renderer);
|
||||
#endif
|
||||
|
@ -20,13 +20,16 @@
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
#include <SDL/SDL.h>
|
||||
#include <GLES2/gl2.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <bcm_host.h>
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_GLES2
|
||||
#include "platform/opengl/gles2.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_PIXMAN
|
||||
#include <pixman.h>
|
||||
#endif
|
||||
@ -69,13 +72,7 @@ struct SDLSoftwareRenderer {
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
EGL_DISPMANX_WINDOW_T window;
|
||||
GLuint tex;
|
||||
GLuint fragmentShader;
|
||||
GLuint vertexShader;
|
||||
GLuint program;
|
||||
GLuint bufferObject;
|
||||
GLuint texLocation;
|
||||
GLuint positionLocation;
|
||||
struct GBAGLES2Context gl;
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_PANDORA
|
||||
@ -90,4 +87,8 @@ void GBASDLSWCreate(struct SDLSoftwareRenderer* renderer);
|
||||
#ifdef BUILD_GL
|
||||
void GBASDLGLCreate(struct SDLSoftwareRenderer* renderer);
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_GLES2
|
||||
void GBASDLGLES2Create(struct SDLSoftwareRenderer* renderer);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -56,8 +56,8 @@ while [ $# -gt 0 ]; do
|
||||
sed -i~ "s/,$//g" deb-temp/DEBIAN/control
|
||||
sed -i~ "/^[^:]*: $/d" deb-temp/DEBIAN/control
|
||||
rm deb-temp/DEBIAN/control~
|
||||
chown -R 0:0 deb-temp
|
||||
chmod 600 deb-temp/DEBIAN/md5sums
|
||||
chmod 644 deb-temp/DEBIAN/md5sums
|
||||
chown -R root:root deb-temp
|
||||
dpkg-deb -b deb-temp $DEB
|
||||
rm -rf deb-temp
|
||||
shift
|
||||
|
Loading…
Reference in New Issue
Block a user