mirror of https://github.com/mgba-emu/mgba.git
OpenEmu: Start the OpenEmu core
This commit is contained in:
parent
29556f45a4
commit
342b02134d
|
@ -18,6 +18,7 @@ set(USE_LZMA ON CACHE BOOL "Whether or not to enable 7-Zip support")
|
||||||
set(BUILD_QT ON CACHE BOOL "Build Qt frontend")
|
set(BUILD_QT ON CACHE BOOL "Build Qt frontend")
|
||||||
set(BUILD_SDL ON CACHE BOOL "Build SDL frontend")
|
set(BUILD_SDL ON CACHE BOOL "Build SDL frontend")
|
||||||
set(BUILD_LIBRETRO OFF CACHE BOOL "Build libretro core")
|
set(BUILD_LIBRETRO OFF CACHE BOOL "Build libretro core")
|
||||||
|
set(BUILD_OPENEMU OFF CACHE BOOL "Build OpenEmu core")
|
||||||
set(BUILD_PERF OFF CACHE BOOL "Build performance profiling tool")
|
set(BUILD_PERF OFF CACHE BOOL "Build performance profiling tool")
|
||||||
set(BUILD_TEST OFF CACHE BOOL "Build testing harness")
|
set(BUILD_TEST OFF CACHE BOOL "Build testing harness")
|
||||||
set(BUILD_STATIC OFF CACHE BOOL "Build a static library")
|
set(BUILD_STATIC OFF CACHE BOOL "Build a static library")
|
||||||
|
@ -558,6 +559,21 @@ if(BUILD_LIBRETRO)
|
||||||
install(TARGETS ${BINARY_NAME}_libretro LIBRARY DESTINATION ${LIBDIR} COMPONENT ${BINARY_NAME}_libretro NAMELINK_SKIP)
|
install(TARGETS ${BINARY_NAME}_libretro LIBRARY DESTINATION ${LIBDIR} COMPONENT ${BINARY_NAME}_libretro NAMELINK_SKIP)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_OPENEMU)
|
||||||
|
find_library(FOUNDATION Foundation)
|
||||||
|
find_library(OPENEMUBASE OpenEmuBase)
|
||||||
|
file(GLOB OE_SRC ${CMAKE_SOURCE_DIR}/src/platform/openemu/*.m)
|
||||||
|
add_library(${BINARY_NAME}-openemu MODULE ${CORE_SRC} ${OE_SRC})
|
||||||
|
set_target_properties(${BINARY_NAME}-openemu PROPERTIES
|
||||||
|
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/src/platform/openemu/Info.plist.in
|
||||||
|
BUNDLE TRUE
|
||||||
|
BUNDLE_EXTENSION oecoreplugin
|
||||||
|
OUTPUT_NAME ${PROJECT_NAME}EmuCore
|
||||||
|
COMPILE_DEFINITIONS "DISABLE_THREADING;${OS_DEFINES};${FUNCTION_DEFINES};MINIMAL_CORE=2")
|
||||||
|
target_link_libraries(${BINARY_NAME}-openemu ${OS_LIB} ${FOUNDATION} ${OPENEMUBASE})
|
||||||
|
install(TARGETS ${BINARY_NAME}-openemu LIBRARY DESTINATION ${LIBDIR} COMPONENT ${BINARY_NAME}.oecoreplugin NAMELINK_SKIP)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(BUILD_SDL)
|
if(BUILD_SDL)
|
||||||
add_definitions(-DBUILD_SDL)
|
add_definitions(-DBUILD_SDL)
|
||||||
add_subdirectory(${CMAKE_SOURCE_DIR}/src/platform/sdl ${CMAKE_BINARY_DIR}/sdl)
|
add_subdirectory(${CMAKE_SOURCE_DIR}/src/platform/sdl ${CMAKE_BINARY_DIR}/sdl)
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//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>${EXECUTABLE_NAME}</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>mGBA</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.endrift.mgba</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>BNDL</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.8.0.1232</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string>OEGameCoreController</string>
|
||||||
|
<key>OEGameCoreClass</key>
|
||||||
|
<string>mGBAGameCore</string>
|
||||||
|
<key>OEGameCoreOptions</key>
|
||||||
|
<dict>
|
||||||
|
<key>openemu.system.gba</key>
|
||||||
|
</dict>
|
||||||
|
<key>OEGameCorePlayerCount</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>OEProjectURL</key>
|
||||||
|
<string>https://mgba.io/</string>
|
||||||
|
<key>OESystemIdentifiers</key>
|
||||||
|
<array>
|
||||||
|
<string>openemu.system.gba</string>
|
||||||
|
</array>
|
||||||
|
<key>SUEnableAutomaticChecks</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>SUFeedURL</key>
|
||||||
|
<string>https://raw.github.com/OpenEmu/OpenEmu-Update/master/mgba_appcast.xml</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2011, OpenEmu Team
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the OpenEmu Team nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY OpenEmu Team ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL OpenEmu Team BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@protocol OESystemResponderClient;
|
||||||
|
|
||||||
|
typedef enum _OEGBAButton
|
||||||
|
{
|
||||||
|
OEGBAButtonUp,
|
||||||
|
OEGBAButtonDown,
|
||||||
|
OEGBAButtonLeft,
|
||||||
|
OEGBAButtonRight,
|
||||||
|
OEGBAButtonA,
|
||||||
|
OEGBAButtonB,
|
||||||
|
OEGBAButtonL,
|
||||||
|
OEGBAButtonR,
|
||||||
|
OEGBAButtonStart,
|
||||||
|
OEGBAButtonSelect,
|
||||||
|
OEGBAButtonCount
|
||||||
|
} OEGBAButton;
|
||||||
|
|
||||||
|
@protocol OEGBASystemResponderClient <OESystemResponderClient, NSObject>
|
||||||
|
|
||||||
|
- (oneway void)didPushGBAButton:(OEGBAButton)button forPlayer:(NSUInteger)player;
|
||||||
|
- (oneway void)didReleaseGBAButton:(OEGBAButton)button forPlayer:(NSUInteger)player;
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,6 @@
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import <OpenEmuBase/OEGameCore.h>
|
||||||
|
|
||||||
|
OE_EXPORTED_CLASS
|
||||||
|
@interface mGBAGameCore : OEGameCore
|
||||||
|
@end
|
|
@ -0,0 +1,251 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2016, Jeffrey Pfau
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS''
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "mGBAGameCore.h"
|
||||||
|
|
||||||
|
#include "util/common.h"
|
||||||
|
|
||||||
|
#include "gba/cheats.h"
|
||||||
|
#include "gba/renderers/video-software.h"
|
||||||
|
#include "gba/serialize.h"
|
||||||
|
#include "gba/context/context.h"
|
||||||
|
#include "util/circle-buffer.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "util/vfs.h"
|
||||||
|
|
||||||
|
#import <OpenEmuBase/OERingBuffer.h>
|
||||||
|
#import "OEGBASystemResponderClient.h"
|
||||||
|
#import <OpenGL/gl.h>
|
||||||
|
|
||||||
|
#define SAMPLES 1024
|
||||||
|
|
||||||
|
@interface mGBAGameCore () <OEGBASystemResponderClient>
|
||||||
|
{
|
||||||
|
struct GBAContext context;
|
||||||
|
struct GBAVideoSoftwareRenderer renderer;
|
||||||
|
struct GBACheatDevice cheats;
|
||||||
|
struct GBACheatSet cheatSet;
|
||||||
|
uint16_t keys;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation mGBAGameCore
|
||||||
|
|
||||||
|
- (id)init
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
// TODO: Add a log handler
|
||||||
|
GBAContextInit(&context, 0);
|
||||||
|
struct GBAOptions opts = {
|
||||||
|
.useBios = true,
|
||||||
|
.idleOptimization = IDLE_LOOP_REMOVE
|
||||||
|
};
|
||||||
|
GBAConfigLoadDefaults(&context.config, &opts);
|
||||||
|
GBAVideoSoftwareRendererCreate(&renderer);
|
||||||
|
renderer.outputBuffer = malloc(256 * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
|
||||||
|
renderer.outputBufferStride = 256;
|
||||||
|
context.renderer = &renderer.d;
|
||||||
|
GBAAudioResizeBuffer(&context.gba->audio, SAMPLES);
|
||||||
|
GBACheatDeviceCreate(&cheats);
|
||||||
|
GBACheatAttachDevice(context.gba, &cheats);
|
||||||
|
GBACheatSetInit(&cheatSet, "openemu");
|
||||||
|
GBACheatAddSet(&cheats, &cheatSet);
|
||||||
|
keys = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
GBAContextDeinit(&context);
|
||||||
|
GBACheatRemoveSet(&cheats, &cheatSet);
|
||||||
|
GBACheatDeviceDestroy(&cheats);
|
||||||
|
GBACheatSetDeinit(&cheatSet);
|
||||||
|
free(renderer.outputBuffer);
|
||||||
|
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Execution
|
||||||
|
|
||||||
|
- (BOOL)loadFileAtPath:(NSString *)path error:(NSError **)error
|
||||||
|
{
|
||||||
|
UNUSED(error);
|
||||||
|
if (!GBAContextLoadROM(&context, [path UTF8String], true)) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
GBAContextStart(&context);
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)executeFrame
|
||||||
|
{
|
||||||
|
GBAContextFrame(&context, keys);
|
||||||
|
|
||||||
|
int16_t samples[SAMPLES * 2];
|
||||||
|
size_t available = 0;
|
||||||
|
#if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF
|
||||||
|
available = blip_samples_avail(context.gba->audio.left);
|
||||||
|
blip_read_samples(context.gba->audio.left, samples, available, true);
|
||||||
|
blip_read_samples(context.gba->audio.right, samples + 1, available, true);
|
||||||
|
#else
|
||||||
|
#error BLIP_BUF is required for now
|
||||||
|
#endif
|
||||||
|
[[self ringBufferAtIndex:0] write:samples maxLength:available * 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)resetEmulation
|
||||||
|
{
|
||||||
|
ARMReset(context.cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)stopEmulation
|
||||||
|
{
|
||||||
|
NSLog(@"Stopping");
|
||||||
|
GBAContextStop(&context);
|
||||||
|
[super stopEmulation];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setupEmulation
|
||||||
|
{
|
||||||
|
#if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF
|
||||||
|
blip_set_rates(context.gba->audio.left, GBA_ARM7TDMI_FREQUENCY, 32768);
|
||||||
|
blip_set_rates(context.gba->audio.right, GBA_ARM7TDMI_FREQUENCY, 32768);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Video
|
||||||
|
|
||||||
|
- (OEIntSize)aspectSize
|
||||||
|
{
|
||||||
|
return OEIntSizeMake(3, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OEIntRect)screenRect
|
||||||
|
{
|
||||||
|
return OEIntRectMake(0, 0, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OEIntSize)bufferSize
|
||||||
|
{
|
||||||
|
return OEIntSizeMake(256, VIDEO_VERTICAL_PIXELS);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (const void *)videoBuffer
|
||||||
|
{
|
||||||
|
return renderer.outputBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (GLenum)pixelFormat
|
||||||
|
{
|
||||||
|
return GL_RGBA;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (GLenum)pixelType
|
||||||
|
{
|
||||||
|
return GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (GLenum)internalPixelFormat
|
||||||
|
{
|
||||||
|
return GL_RGB8;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSTimeInterval)frameInterval
|
||||||
|
{
|
||||||
|
return GBA_ARM7TDMI_FREQUENCY / (double) VIDEO_TOTAL_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Audio
|
||||||
|
|
||||||
|
- (NSUInteger)channelCount
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (double)audioSampleRate
|
||||||
|
{
|
||||||
|
return 32768;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Save State
|
||||||
|
|
||||||
|
- (NSData *)serializeStateWithError:(NSError **)outError
|
||||||
|
{
|
||||||
|
UNUSED(outError);
|
||||||
|
// TODO memory VFile that self-manages memory
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)deserializeState:(NSData *)state withError:(NSError **)outError
|
||||||
|
{
|
||||||
|
UNUSED(outError);
|
||||||
|
// TODO VFileFromConstMemory
|
||||||
|
struct VFile* vf = VFileFromMemory((void*) state.bytes, state.length);
|
||||||
|
return GBALoadStateNamed(context.gba, vf, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)saveStateToFileAtPath:(NSString *)fileName completionHandler:(void (^)(BOOL, NSError *))block
|
||||||
|
{
|
||||||
|
struct VFile* vf = VFileOpen([fileName UTF8String], O_CREAT | O_TRUNC | O_RDWR);
|
||||||
|
block(GBASaveStateNamed(context.gba, vf, 0), nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)loadStateFromFileAtPath:(NSString *)fileName completionHandler:(void (^)(BOOL, NSError *))block
|
||||||
|
{
|
||||||
|
struct VFile* vf = VFileOpen([fileName UTF8String], O_RDONLY);
|
||||||
|
block(GBALoadStateNamed(context.gba, vf, 0), nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Input
|
||||||
|
|
||||||
|
const int GBAMap[] = {
|
||||||
|
GBA_KEY_UP,
|
||||||
|
GBA_KEY_DOWN,
|
||||||
|
GBA_KEY_LEFT,
|
||||||
|
GBA_KEY_RIGHT,
|
||||||
|
GBA_KEY_A,
|
||||||
|
GBA_KEY_B,
|
||||||
|
GBA_KEY_L,
|
||||||
|
GBA_KEY_R,
|
||||||
|
GBA_KEY_START,
|
||||||
|
GBA_KEY_SELECT
|
||||||
|
};
|
||||||
|
|
||||||
|
- (oneway void)didPushGBAButton:(OEGBAButton)button forPlayer:(NSUInteger)player
|
||||||
|
{
|
||||||
|
UNUSED(player);
|
||||||
|
keys |= 1 << GBAMap[button];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (oneway void)didReleaseGBAButton:(OEGBAButton)button forPlayer:(NSUInteger)player
|
||||||
|
{
|
||||||
|
UNUSED(player);
|
||||||
|
keys &= ~(1 << GBAMap[button]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
Loading…
Reference in New Issue