Compare commits
12 Commits
Author | SHA1 | Date |
---|---|---|
lif | c76bd2ae46 | |
lif | 492f1bf7b2 | |
lif | 04ff0f1ec5 | |
lif | 5a80a5783e | |
lif | 164f4528f0 | |
lif | 5d632a2943 | |
lif | 2eb14f09e1 | |
lif | a687f0bed0 | |
lif | e93e222c52 | |
lif | b798e4727f | |
lif | 00c45406de | |
lif | 1a331e8853 |
|
@ -1,11 +1,15 @@
|
||||||
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OSX deployment version" FORCE)
|
||||||
|
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "OSX target CPU architectures" FORCE)
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.9)
|
cmake_minimum_required(VERSION 3.9)
|
||||||
project(cgbwebcam)
|
project(cgbwebcam)
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
# i think SDL should be setting this
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
|
# i think SDL should be setting this
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "-framework AVFoundation")
|
set(CMAKE_EXE_LINKER_FLAGS "-framework AVFoundation")
|
||||||
|
set(SDL_CPU_X64 ON)
|
||||||
|
set(SDL_CPU_ARM64 ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SDL_STATIC ON)
|
set(SDL_STATIC ON)
|
||||||
|
@ -39,9 +43,26 @@ add_subdirectory(mgba)
|
||||||
include_directories(SDL/include)
|
include_directories(SDL/include)
|
||||||
include_directories(mgba/include)
|
include_directories(mgba/include)
|
||||||
|
|
||||||
#set_source_files_properties(main.c PROPERTIES COMPILE_FLAGS "-Wall -Werror -pedantic -std=c89")
|
set_source_files_properties(main.c PROPERTIES COMPILE_FLAGS "-Wall -Werror -pedantic -std=c99 -Wno-extra-semi")
|
||||||
|
|
||||||
add_executable(cgbwebcam main.c)
|
if(APPLE)
|
||||||
|
set(cgbwebcam_ICON ${CMAKE_SOURCE_DIR}/cmake/cgbwebcam.icns)
|
||||||
|
set_source_files_properties(${cgbwebcam_ICON} PROPERTIES
|
||||||
|
MACOSX_PACKAGE_LOCATION "Resources")
|
||||||
|
add_executable(cgbwebcam MACOSX_BUNDLE main.c ${cgbwebcam_ICON})
|
||||||
|
set_target_properties(cgbwebcam PROPERTIES
|
||||||
|
BUNDLE True
|
||||||
|
MACOSX_BUNDLE_GUI_IDENTIFIER "net.hell-labs.cgbwebcam"
|
||||||
|
MACOSX_BUNDLE_BUNDLE_NAME "cgbwebcam"
|
||||||
|
MACOSX_BUNDLE_BUNDLE_VERSION "0.1"
|
||||||
|
MACOSX_BUNDLE_SHORT_VERSION_STRING "0.1"
|
||||||
|
MACOSX_BUNDLE_ICON_FILE cgbwebcam.icns
|
||||||
|
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/Templates/Info.plist
|
||||||
|
# OSX_ARCHITECTURES "x86_64;arm64"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
add_executable(cgbwebcam main.c)
|
||||||
|
endif()
|
||||||
target_link_libraries(cgbwebcam SDL3-static mgba)
|
target_link_libraries(cgbwebcam SDL3-static mgba)
|
||||||
|
|
||||||
include(CheckIPOSupported)
|
include(CheckIPOSupported)
|
||||||
|
|
|
@ -14,9 +14,9 @@ _build/cgbwebcam gbcamera.gb # provide your own rom, of course
|
||||||
### for windows
|
### for windows
|
||||||
just point visual studio at the CMakeLists.txt, apparently that's a thing it supports now.
|
just point visual studio at the CMakeLists.txt, apparently that's a thing it supports now.
|
||||||
|
|
||||||
make sure you provide the gbcamera rom as `argv[1]`.
|
|
||||||
|
|
||||||
### for everyone again
|
### for everyone again
|
||||||
|
you may provide the gbcamera rom either as `argv[1]` or by selecting it from a file selection dialog.
|
||||||
|
|
||||||
when running, the inputs are
|
when running, the inputs are
|
||||||
- arrow keys = dpad
|
- arrow keys = dpad
|
||||||
- z = a
|
- z = a
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0"> <dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>${MACOSX_BUNDLE_EXECUTABLE}</string>
|
||||||
|
<key>CFBundleGetInfoString</key>
|
||||||
|
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>${MACOSX_BUNDLE_ICON}</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleLongVersionString</key>
|
||||||
|
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
|
||||||
|
<key>CSResourcesFileMapped</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>cgbwebcam requires access to your camera in order to simulate the Gameboy Camera's sensor.</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Binary file not shown.
346
main.c
346
main.c
|
@ -1,6 +1,7 @@
|
||||||
#define SDL_MAIN_USE_CALLBACKS 1
|
#define SDL_MAIN_USE_CALLBACKS 1
|
||||||
#include "SDL3/SDL_blendmode.h"
|
#include "SDL3/SDL_blendmode.h"
|
||||||
#include "SDL3/SDL_camera.h"
|
#include "SDL3/SDL_camera.h"
|
||||||
|
#include "SDL3/SDL_dialog.h"
|
||||||
#include "SDL3/SDL_error.h"
|
#include "SDL3/SDL_error.h"
|
||||||
#include "SDL3/SDL_events.h"
|
#include "SDL3/SDL_events.h"
|
||||||
#include "SDL3/SDL_init.h"
|
#include "SDL3/SDL_init.h"
|
||||||
|
@ -18,6 +19,7 @@
|
||||||
#include "mgba/core/core.h"
|
#include "mgba/core/core.h"
|
||||||
#include "mgba/core/interface.h"
|
#include "mgba/core/interface.h"
|
||||||
#include "mgba/feature/commandline.h"
|
#include "mgba/feature/commandline.h"
|
||||||
|
#include "mgba/internal/gb/video.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -33,22 +35,38 @@
|
||||||
#error "unknown pixel format"
|
#error "unknown pixel format"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static SDL_Texture* textures[NUM_CHANNELS] = { NULL, NULL, NULL };
|
/* state that must be accessible by libmgba camera callbacks */
|
||||||
static bool texture_updated = false;
|
|
||||||
static SDL_CameraID front_camera = 0;
|
|
||||||
static SDL_CameraID back_camera = 0;
|
|
||||||
static SDL_Surface* scaled = NULL;
|
static SDL_Surface* scaled = NULL;
|
||||||
static SDL_Surface* filtered[NUM_CHANNELS] = { NULL, NULL, NULL };
|
static SDL_Surface* filtered[NUM_CHANNELS] = { NULL, NULL, NULL };
|
||||||
static SDL_Surface* screens[NUM_CHANNELS] = { NULL, NULL, NULL };
|
|
||||||
|
|
||||||
static struct mCore* cores[NUM_CHANNELS] = { NULL, NULL, NULL };
|
enum DialogState {
|
||||||
static unsigned keys = 0;
|
DIALOG_NEVER = 0,
|
||||||
|
DIALOG_OPENED,
|
||||||
|
DIALOG_CLOSED,
|
||||||
|
};
|
||||||
|
|
||||||
struct AppState {
|
struct AppState {
|
||||||
SDL_Camera* camera;
|
SDL_Camera* camera;
|
||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
SDL_Renderer* renderer;
|
SDL_Renderer* renderer;
|
||||||
|
|
||||||
|
/* indices used by SelectCamera */
|
||||||
int cam_idx, spec_idx;
|
int cam_idx, spec_idx;
|
||||||
|
|
||||||
|
/* used by FlipCamera */
|
||||||
|
SDL_CameraID front_camera;
|
||||||
|
SDL_CameraID back_camera;
|
||||||
|
|
||||||
|
bool texture_updated;
|
||||||
|
SDL_Texture* textures[NUM_CHANNELS];
|
||||||
|
SDL_Surface* screens[NUM_CHANNELS];
|
||||||
|
|
||||||
|
enum DialogState dialog_state;
|
||||||
|
struct mArguments args;
|
||||||
|
struct mCore* cores[NUM_CHANNELS];
|
||||||
|
|
||||||
|
/* GB button presses fed to mgba */
|
||||||
|
unsigned keys;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mColorFormat pixfmt_sdl_to_mgba(uint32_t sdl_fmt) {
|
enum mColorFormat pixfmt_sdl_to_mgba(uint32_t sdl_fmt) {
|
||||||
|
@ -72,6 +90,21 @@ enum mColorFormat pixfmt_sdl_to_mgba(uint32_t sdl_fmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SDL_DialogFileFilter DIALOG_FILENAME_FILTER[] = {
|
||||||
|
{ "Gameboy Camera ROM (*.gb, *.sgb)", "gb;sgb" },
|
||||||
|
{ "", "" },
|
||||||
|
{ NULL, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
static void SDLCALL dialog_callback(void* userdata, const char* const* files, int filter) {
|
||||||
|
struct AppState* st = (struct AppState*)userdata;
|
||||||
|
if (files && *files) {
|
||||||
|
SDL_Log("\nSelected: %s", *files);
|
||||||
|
st->args.fname = strdup(*files);
|
||||||
|
}
|
||||||
|
st->dialog_state = DIALOG_CLOSED;
|
||||||
|
}
|
||||||
|
|
||||||
void myStartRequestImageRed(struct mImageSource* self, unsigned w, unsigned h, int colorFormats) {
|
void myStartRequestImageRed(struct mImageSource* self, unsigned w, unsigned h, int colorFormats) {
|
||||||
SDL_DestroySurface(scaled);
|
SDL_DestroySurface(scaled);
|
||||||
SDL_DestroySurface(filtered[0]);
|
SDL_DestroySurface(filtered[0]);
|
||||||
|
@ -165,6 +198,7 @@ bool SelectCamera(struct AppState* st) {
|
||||||
SDL_RenderDebugText(renderer, 4, 4, "connect a camera");
|
SDL_RenderDebugText(renderer, 4, 4, "connect a camera");
|
||||||
|
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SDL_CameraID device = devices[st->cam_idx];
|
const SDL_CameraID device = devices[st->cam_idx];
|
||||||
|
@ -178,6 +212,11 @@ bool SelectCamera(struct AppState* st) {
|
||||||
int formats_len = 0;
|
int formats_len = 0;
|
||||||
|
|
||||||
SDL_CameraSpec** formats = SDL_GetCameraSupportedFormats(device, &formats_len);
|
SDL_CameraSpec** formats = SDL_GetCameraSupportedFormats(device, &formats_len);
|
||||||
|
if (!formats) {
|
||||||
|
SDL_Log("SDL_GetCameraSupportedFormats failed: %s", SDL_GetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (st->spec_idx >= formats_len) {
|
if (st->spec_idx >= formats_len) {
|
||||||
st->spec_idx = 0;
|
st->spec_idx = 0;
|
||||||
} else if (st->spec_idx < 0) {
|
} else if (st->spec_idx < 0) {
|
||||||
|
@ -190,10 +229,10 @@ bool SelectCamera(struct AppState* st) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (position == SDL_CAMERA_POSITION_FRONT_FACING) {
|
if (position == SDL_CAMERA_POSITION_FRONT_FACING) {
|
||||||
front_camera = device;
|
st->front_camera = device;
|
||||||
posstr = "[frontfacing]";
|
posstr = "[frontfacing]";
|
||||||
} else if (position == SDL_CAMERA_POSITION_BACK_FACING) {
|
} else if (position == SDL_CAMERA_POSITION_BACK_FACING) {
|
||||||
back_camera = device;
|
st->back_camera = device;
|
||||||
posstr = "[backfacing]";
|
posstr = "[backfacing]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +244,6 @@ bool SelectCamera(struct AppState* st) {
|
||||||
snprintf(snprintfbuf, sizeof(snprintfbuf), "%d. %s", st->cam_idx, posstr);
|
snprintf(snprintfbuf, sizeof(snprintfbuf), "%d. %s", st->cam_idx, posstr);
|
||||||
SDL_RenderDebugText(renderer, 8, 16, snprintfbuf);
|
SDL_RenderDebugText(renderer, 8, 16, snprintfbuf);
|
||||||
SDL_RenderDebugText(renderer, 4, 28, name);
|
SDL_RenderDebugText(renderer, 4, 28, name);
|
||||||
SDL_free((void*)name);
|
|
||||||
|
|
||||||
SDL_RenderDebugText(renderer, 4, 52, "mode: (left/right)");
|
SDL_RenderDebugText(renderer, 4, 52, "mode: (left/right)");
|
||||||
snprintf(
|
snprintf(
|
||||||
|
@ -244,13 +282,7 @@ bool SelectCamera(struct AppState* st) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_AppResult SDL_AppInit(void** appstate, int argc, char *argv[]) {
|
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
||||||
int i;
|
|
||||||
unsigned w, h;
|
|
||||||
|
|
||||||
struct mArguments args;
|
|
||||||
bool parsed = mArgumentsParse(&args, argc, argv, NULL, 0);
|
|
||||||
|
|
||||||
struct AppState* st = malloc(sizeof(struct AppState));
|
struct AppState* st = malloc(sizeof(struct AppState));
|
||||||
memset(st, 0, sizeof(struct AppState));
|
memset(st, 0, sizeof(struct AppState));
|
||||||
*appstate = st;
|
*appstate = st;
|
||||||
|
@ -258,6 +290,8 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char *argv[]) {
|
||||||
/* Enable standard application logging */
|
/* Enable standard application logging */
|
||||||
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
|
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
|
||||||
|
|
||||||
|
bool parsed = mArgumentsParse(&st->args, argc, argv, NULL, 0);
|
||||||
|
|
||||||
if (!parsed) {
|
if (!parsed) {
|
||||||
SDL_Log("Couldn't parse arguments");
|
SDL_Log("Couldn't parse arguments");
|
||||||
return SDL_APP_FAILURE;
|
return SDL_APP_FAILURE;
|
||||||
|
@ -273,40 +307,12 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char *argv[]) {
|
||||||
gb_img_src[2].startRequestImage = myStartRequestImageBlue;
|
gb_img_src[2].startRequestImage = myStartRequestImageBlue;
|
||||||
gb_img_src[2].stopRequestImage = myStopRequestImageBlue;
|
gb_img_src[2].stopRequestImage = myStopRequestImageBlue;
|
||||||
|
|
||||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
|
||||||
struct mCore* core = mCoreFind(args.fname);
|
|
||||||
if (!core || !core->init(core)) {
|
|
||||||
SDL_Log("Couldn't initialize mgba core!");
|
|
||||||
return SDL_APP_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mCoreLoadFile(core, args.fname)) {
|
|
||||||
SDL_Log("Failed to load ROM");
|
|
||||||
return SDL_APP_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
mCoreConfigInit(&core->config, NULL);
|
|
||||||
/*mCoreConfigLoad(&core->config);*/
|
|
||||||
|
|
||||||
mArgumentsApply(&args, NULL, 0, &core->config);
|
|
||||||
mCoreConfigSetDefaultValue(&core->config, "idleOptimization", "detect");
|
|
||||||
mCoreConfigSetDefaultValue(&core->config, "frameskip", "4");
|
|
||||||
mCoreConfigSetDefaultValue(&core->config, "sgb.borders", "0");
|
|
||||||
|
|
||||||
mCoreLoadConfig(core);
|
|
||||||
|
|
||||||
cores[i] = core;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* without loss of generality */
|
|
||||||
cores[0]->desiredVideoDimensions(cores[0], &w, &h);
|
|
||||||
|
|
||||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_CAMERA)) {
|
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_CAMERA)) {
|
||||||
SDL_Log("Couldn't initialize SDL3: %s", SDL_GetError());
|
SDL_Log("Couldn't initialize SDL3: %s", SDL_GetError());
|
||||||
return SDL_APP_FAILURE;
|
return SDL_APP_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
st->window = SDL_CreateWindow("cgbwebcam", w, h, SDL_WINDOW_RESIZABLE);
|
st->window = SDL_CreateWindow("cgbwebcam", GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS, SDL_WINDOW_RESIZABLE);
|
||||||
if (!st->window) {
|
if (!st->window) {
|
||||||
SDL_Log("Couldn't create window: %s", SDL_GetError());
|
SDL_Log("Couldn't create window: %s", SDL_GetError());
|
||||||
return SDL_APP_FAILURE;
|
return SDL_APP_FAILURE;
|
||||||
|
@ -320,58 +326,6 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char *argv[]) {
|
||||||
|
|
||||||
SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE);
|
SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE);
|
||||||
|
|
||||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
|
||||||
int j;
|
|
||||||
struct mCore* core = cores[i];
|
|
||||||
SDL_Texture* texture;
|
|
||||||
SDL_Surface* screen = SDL_CreateSurface(w, h, SCREEN_FMT);
|
|
||||||
|
|
||||||
core->setVideoBuffer(core, screen->pixels, screen->pitch / BYTES_PER_PIXEL);
|
|
||||||
screens[i] = screen;
|
|
||||||
|
|
||||||
/* Create texture with appropriate format */
|
|
||||||
texture = SDL_CreateTextureFromSurface(st->renderer, screens[0]);
|
|
||||||
if (!texture) {
|
|
||||||
SDL_Log("Couldn't create texture: %s", SDL_GetError());
|
|
||||||
return SDL_APP_FAILURE;
|
|
||||||
}
|
|
||||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_ADD);
|
|
||||||
textures[i] = texture;
|
|
||||||
|
|
||||||
core->setPeripheral(core, mPERIPH_IMAGE_SOURCE, &gb_img_src[i]);
|
|
||||||
|
|
||||||
core->reset(core);
|
|
||||||
|
|
||||||
core->setKeys(core, 0);
|
|
||||||
for (j = 0; j < 600; j++) {
|
|
||||||
core->runFrame(core);
|
|
||||||
}
|
|
||||||
core->setKeys(core, 1); /* title screen */
|
|
||||||
core->runFrame(core);
|
|
||||||
core->setKeys(core, 0);
|
|
||||||
for (j = 0; j < 25; j++) {
|
|
||||||
core->runFrame(core);
|
|
||||||
}
|
|
||||||
core->setKeys(core, 1); /* select 'shoot' */
|
|
||||||
core->runFrame(core);
|
|
||||||
core->setKeys(core, 0);
|
|
||||||
for (j = 0; j < 75; j++) {
|
|
||||||
core->runFrame(core);
|
|
||||||
}
|
|
||||||
core->setKeys(core, 1); /* select 'shoot' again */
|
|
||||||
core->runFrame(core);
|
|
||||||
core->setKeys(core, 0);
|
|
||||||
for (j = 0; j < 100; j++) {
|
|
||||||
core->runFrame(core);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Log("prepared core %d", i);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SetTextureColorMod(textures[0], 255, 0, 0);
|
|
||||||
SDL_SetTextureColorMod(textures[1], 0, 255, 0);
|
|
||||||
SDL_SetTextureColorMod(textures[2], 0, 0, 255);
|
|
||||||
|
|
||||||
return SDL_APP_CONTINUE; /* start the main app loop. */
|
return SDL_APP_CONTINUE; /* start the main app loop. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,10 +338,10 @@ static SDL_AppResult FlipCamera(struct AppState* st) {
|
||||||
if (st->camera) {
|
if (st->camera) {
|
||||||
const SDL_CameraID current = SDL_GetCameraID(st->camera);
|
const SDL_CameraID current = SDL_GetCameraID(st->camera);
|
||||||
SDL_CameraID nextcam = 0;
|
SDL_CameraID nextcam = 0;
|
||||||
if (current == front_camera) {
|
if (current == st->front_camera) {
|
||||||
nextcam = back_camera;
|
nextcam = st->back_camera;
|
||||||
} else if (current == back_camera) {
|
} else if (current == st->back_camera) {
|
||||||
nextcam = front_camera;
|
nextcam = st->front_camera;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextcam) {
|
if (nextcam) {
|
||||||
|
@ -415,7 +369,7 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case SDL_EVENT_QUIT:
|
case SDL_EVENT_QUIT:
|
||||||
SDL_Log("Quit!");
|
SDL_Log("Quit!");
|
||||||
return false;
|
return SDL_APP_SUCCESS;
|
||||||
|
|
||||||
case SDL_EVENT_KEY_DOWN:
|
case SDL_EVENT_KEY_DOWN:
|
||||||
switch (event->key.key) {
|
switch (event->key.key) {
|
||||||
|
@ -438,6 +392,8 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
|
@ -446,14 +402,14 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
|
||||||
switch (sym) {
|
switch (sym) {
|
||||||
case SDLK_ESCAPE: case SDLK_AC_BACK: return SDL_APP_SUCCESS;
|
case SDLK_ESCAPE: case SDLK_AC_BACK: return SDL_APP_SUCCESS;
|
||||||
case SDLK_SPACE: FlipCamera(st); break;
|
case SDLK_SPACE: FlipCamera(st); break;
|
||||||
case SDLK_UP: keys |= 0x40; break;
|
case SDLK_UP: st->keys |= 0x40; break;
|
||||||
case SDLK_DOWN: keys |= 0x80; break;
|
case SDLK_DOWN: st->keys |= 0x80; break;
|
||||||
case SDLK_LEFT: keys |= 0x20; break;
|
case SDLK_LEFT: st->keys |= 0x20; break;
|
||||||
case SDLK_RIGHT: keys |= 0x10; break;
|
case SDLK_RIGHT: st->keys |= 0x10; break;
|
||||||
case SDLK_A: case SDLK_Z: keys |= 1; break;
|
case SDLK_A: case SDLK_Z: st->keys |= 1; break;
|
||||||
case SDLK_B: case SDLK_X: keys |= 2; break;
|
case SDLK_B: case SDLK_X: st->keys |= 2; break;
|
||||||
case SDLK_RETURN: keys |= 8; break;
|
case SDLK_RETURN: st->keys |= 8; break;
|
||||||
case SDLK_BACKSPACE: keys |= 4; break;
|
case SDLK_BACKSPACE: st->keys |= 4; break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -461,14 +417,14 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
|
||||||
case SDL_EVENT_KEY_UP: {
|
case SDL_EVENT_KEY_UP: {
|
||||||
const SDL_Keycode sym = event->key.key;
|
const SDL_Keycode sym = event->key.key;
|
||||||
switch (sym) {
|
switch (sym) {
|
||||||
case SDLK_UP: keys &= ~0x40; break;
|
case SDLK_UP: st->keys &= ~0x40; break;
|
||||||
case SDLK_DOWN: keys &= ~0x80; break;
|
case SDLK_DOWN: st->keys &= ~0x80; break;
|
||||||
case SDLK_LEFT: keys &= ~0x20; break;
|
case SDLK_LEFT: st->keys &= ~0x20; break;
|
||||||
case SDLK_RIGHT: keys &= ~0x10; break;
|
case SDLK_RIGHT: st->keys &= ~0x10; break;
|
||||||
case SDLK_A: case SDLK_Z: keys &= ~1; break;
|
case SDLK_A: case SDLK_Z: st->keys &= ~1; break;
|
||||||
case SDLK_B: case SDLK_X: keys &= ~2; break;
|
case SDLK_B: case SDLK_X: st->keys &= ~2; break;
|
||||||
case SDLK_RETURN: keys &= ~8; break;
|
case SDLK_RETURN: st->keys &= ~8; break;
|
||||||
case SDLK_BACKSPACE: keys &= ~4; break;
|
case SDLK_BACKSPACE: st->keys &= ~4; break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -495,10 +451,10 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
|
||||||
SDL_Log("Camera denied!");
|
SDL_Log("Camera denied!");
|
||||||
return SDL_APP_FAILURE;
|
return SDL_APP_FAILURE;
|
||||||
|
|
||||||
/*
|
|
||||||
case SDL_EVENT_WINDOW_RESIZED: {
|
case SDL_EVENT_WINDOW_RESIZED: {
|
||||||
|
st->texture_updated = false;
|
||||||
|
/*
|
||||||
Sint32 winw = event->window.data1, winh = event->window.data2;
|
Sint32 winw = event->window.data1, winh = event->window.data2;
|
||||||
SDL_UpdateWindowSurface(window);
|
|
||||||
if (TODO: need to correct aspect ratio?) {
|
if (TODO: need to correct aspect ratio?) {
|
||||||
if (!SDL_SetWindowSize(window, winw/2, winh)) {
|
if (!SDL_SetWindowSize(window, winw/2, winh)) {
|
||||||
SDL_Log("Failed to resize window to %dx%d: %s", winw, winh, SDL_GetError());
|
SDL_Log("Failed to resize window to %dx%d: %s", winw, winh, SDL_GetError());
|
||||||
|
@ -507,9 +463,9 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
|
||||||
SDL_Log("Resized window to %dx%d", winw, winh);
|
SDL_Log("Resized window to %dx%d", winw, winh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -521,6 +477,113 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
|
||||||
SDL_AppResult SDL_AppIterate(void* appstate) {
|
SDL_AppResult SDL_AppIterate(void* appstate) {
|
||||||
struct AppState* st = (struct AppState*)appstate;
|
struct AppState* st = (struct AppState*)appstate;
|
||||||
|
|
||||||
|
if (!st->cores[0]) {
|
||||||
|
unsigned w, h;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!st->args.fname) {
|
||||||
|
switch (st->dialog_state) {
|
||||||
|
case DIALOG_NEVER:
|
||||||
|
SDL_Log("Select your Gameboy Camera ROM dump...");
|
||||||
|
st->dialog_state = DIALOG_OPENED;
|
||||||
|
SDL_ShowOpenFileDialog(dialog_callback, st, st->window, DIALOG_FILENAME_FILTER, 1, NULL, false);
|
||||||
|
/* evil fallthrough */
|
||||||
|
case DIALOG_OPENED:
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
|
case DIALOG_CLOSED:
|
||||||
|
SDL_Log("Must provide a Gameboy Camera ROM");
|
||||||
|
/* evil fallthrough */
|
||||||
|
default:
|
||||||
|
return SDL_APP_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||||
|
struct mCore* core = mCoreFind(st->args.fname);
|
||||||
|
if (!core || !core->init(core)) {
|
||||||
|
SDL_Log("Couldn't initialize mgba core!");
|
||||||
|
return SDL_APP_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mCoreLoadFile(core, st->args.fname)) {
|
||||||
|
SDL_Log("Failed to load ROM");
|
||||||
|
return SDL_APP_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCoreConfigInit(&core->config, NULL);
|
||||||
|
/*mCoreConfigLoad(&core->config);*/
|
||||||
|
|
||||||
|
mArgumentsApply(&st->args, NULL, 0, &core->config);
|
||||||
|
mCoreConfigSetDefaultValue(&core->config, "idleOptimization", "detect");
|
||||||
|
mCoreConfigSetDefaultValue(&core->config, "frameskip", "4");
|
||||||
|
mCoreConfigSetDefaultValue(&core->config, "sgb.borders", "0");
|
||||||
|
|
||||||
|
mCoreLoadConfig(core);
|
||||||
|
|
||||||
|
st->cores[i] = core;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* without loss of generality */
|
||||||
|
st->cores[0]->desiredVideoDimensions(st->cores[0], &w, &h);
|
||||||
|
SDL_SetWindowSize(st->window, w, h);
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||||
|
int j;
|
||||||
|
struct mCore* core = st->cores[i];
|
||||||
|
SDL_Texture* texture;
|
||||||
|
SDL_Surface* screen = SDL_CreateSurface(w, h, SCREEN_FMT);
|
||||||
|
|
||||||
|
core->setVideoBuffer(core, screen->pixels, screen->pitch / BYTES_PER_PIXEL);
|
||||||
|
st->screens[i] = screen;
|
||||||
|
|
||||||
|
/* Create texture with appropriate format */
|
||||||
|
texture = SDL_CreateTextureFromSurface(st->renderer, st->screens[0]);
|
||||||
|
if (!texture) {
|
||||||
|
SDL_Log("Couldn't create texture: %s", SDL_GetError());
|
||||||
|
return SDL_APP_FAILURE;
|
||||||
|
}
|
||||||
|
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_ADD);
|
||||||
|
st->textures[i] = texture;
|
||||||
|
|
||||||
|
core->setPeripheral(core, mPERIPH_IMAGE_SOURCE, &gb_img_src[i]);
|
||||||
|
|
||||||
|
core->reset(core);
|
||||||
|
|
||||||
|
core->setKeys(core, 0);
|
||||||
|
for (j = 0; j < 600; j++) {
|
||||||
|
core->runFrame(core);
|
||||||
|
}
|
||||||
|
core->setKeys(core, 1); /* title screen */
|
||||||
|
core->runFrame(core);
|
||||||
|
core->setKeys(core, 0);
|
||||||
|
for (j = 0; j < 25; j++) {
|
||||||
|
core->runFrame(core);
|
||||||
|
}
|
||||||
|
core->setKeys(core, 1); /* select 'shoot' */
|
||||||
|
core->runFrame(core);
|
||||||
|
core->setKeys(core, 0);
|
||||||
|
for (j = 0; j < 75; j++) {
|
||||||
|
core->runFrame(core);
|
||||||
|
}
|
||||||
|
core->setKeys(core, 1); /* select 'shoot' again */
|
||||||
|
core->runFrame(core);
|
||||||
|
core->setKeys(core, 0);
|
||||||
|
for (j = 0; j < 100; j++) {
|
||||||
|
core->runFrame(core);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Log("prepared core %d", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetTextureColorMod(st->textures[0], 255, 0, 0);
|
||||||
|
SDL_SetTextureColorMod(st->textures[1], 0, 255, 0);
|
||||||
|
SDL_SetTextureColorMod(st->textures[2], 0, 0, 255);
|
||||||
|
|
||||||
|
/* weird bug on OSX, shows file browser twice if unfocused when selecting camera */
|
||||||
|
SDL_RaiseWindow(st->window);
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (st->camera == NULL) {
|
if (st->camera == NULL) {
|
||||||
if (!SelectCamera(st)) {
|
if (!SelectCamera(st)) {
|
||||||
SDL_Log("Failed to show camera device menu: %s", SDL_GetError());
|
SDL_Log("Failed to show camera device menu: %s", SDL_GetError());
|
||||||
|
@ -530,7 +593,7 @@ SDL_AppResult SDL_AppIterate(void* appstate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Renderer* renderer = st->renderer;
|
SDL_Renderer* renderer = st->renderer;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
static int since_last_present = 0;
|
static int since_last_present = 0;
|
||||||
|
|
||||||
|
@ -545,7 +608,7 @@ SDL_AppResult SDL_AppIterate(void* appstate) {
|
||||||
int w = srcrect.h * dstrect.w / dstrect.h;
|
int w = srcrect.h * dstrect.w / dstrect.h;
|
||||||
|
|
||||||
/*SDL_Log("new frame %d x %d %s", frame->w, frame->h, SDL_GetPixelFormatName(frame->format->format));*/
|
/*SDL_Log("new frame %d x %d %s", frame->w, frame->h, SDL_GetPixelFormatName(frame->format->format));*/
|
||||||
texture_updated = false;
|
st->texture_updated = false;
|
||||||
|
|
||||||
if (w <= srcrect.w) {
|
if (w <= srcrect.w) {
|
||||||
srcrect.x = (srcrect.w - w) / 2;
|
srcrect.x = (srcrect.w - w) / 2;
|
||||||
|
@ -572,26 +635,26 @@ SDL_AppResult SDL_AppIterate(void* appstate) {
|
||||||
|
|
||||||
if (since_last_present < FRAMESKIP_LIMIT) {
|
if (since_last_present < FRAMESKIP_LIMIT) {
|
||||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||||
struct mCore* core = cores[i];
|
struct mCore* core = st->cores[i];
|
||||||
core->setKeys(core, keys);
|
core->setKeys(core, st->keys);
|
||||||
core->runFrame(core);
|
core->runFrame(core);
|
||||||
}
|
}
|
||||||
/*hack*/
|
/*hack*/
|
||||||
if (keys && since_last_present < FRAMESKIP_LIMIT - 8) {
|
if (st->keys && since_last_present < FRAMESKIP_LIMIT - 8) {
|
||||||
since_last_present = FRAMESKIP_LIMIT - 8;
|
since_last_present = FRAMESKIP_LIMIT - 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!texture_updated) {
|
if (!st->texture_updated) {
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
/* Update SDL_Texture with last video frame (only once per new frame) */
|
/* Update SDL_Texture with last video frame (only once per new frame) */
|
||||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||||
SDL_Surface* screen = screens[i];
|
SDL_Surface* screen = st->screens[i];
|
||||||
SDL_Texture* texture = textures[i];
|
SDL_Texture* texture = st->textures[i];
|
||||||
SDL_UpdateTexture(texture, NULL, screen->pixels, screen->pitch);
|
SDL_UpdateTexture(texture, NULL, screen->pixels, screen->pitch);
|
||||||
texture_updated = true;
|
st->texture_updated = true;
|
||||||
SDL_RenderTexture(renderer, texture, NULL, NULL);
|
SDL_RenderTexture(renderer, texture, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,13 +663,13 @@ SDL_AppResult SDL_AppIterate(void* appstate) {
|
||||||
} else {
|
} else {
|
||||||
since_last_present++;
|
since_last_present++;
|
||||||
if (since_last_present >= FRAMESKIP_LIMIT) {
|
if (since_last_present >= FRAMESKIP_LIMIT) {
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||||
SDL_Texture *texture = textures[i];
|
SDL_Texture *texture = st->textures[i];
|
||||||
SDL_RenderTexture(renderer, texture, NULL, NULL);
|
SDL_RenderTexture(renderer, texture, NULL, NULL);
|
||||||
}
|
}
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,9 +680,10 @@ void SDL_AppQuit(void* appstate, SDL_AppResult result) {
|
||||||
struct AppState* st = (struct AppState*)appstate;
|
struct AppState* st = (struct AppState*)appstate;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||||
mCoreConfigDeinit(&cores[i]->config);
|
struct mCore* core = st->cores[i];
|
||||||
cores[i]->deinit(cores[i]);
|
mCoreConfigDeinit(&core->config);
|
||||||
SDL_DestroyTexture(textures[i]);
|
core->deinit(core);
|
||||||
|
SDL_DestroyTexture(st->textures[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_CloseCamera(st->camera);
|
SDL_CloseCamera(st->camera);
|
||||||
|
|
Loading…
Reference in New Issue