OpenEmu: Start the OpenEmu core

This commit is contained in:
Jeffrey Pfau 2016-01-01 21:57:46 -08:00
parent 29556f45a4
commit 342b02134d
5 changed files with 366 additions and 0 deletions

View File

@ -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_SDL ON CACHE BOOL "Build SDL frontend")
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_TEST OFF CACHE BOOL "Build testing harness")
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)
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)
add_definitions(-DBUILD_SDL)
add_subdirectory(${CMAKE_SOURCE_DIR}/src/platform/sdl ${CMAKE_BINARY_DIR}/sdl)

View File

@ -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>

View File

@ -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

View File

@ -0,0 +1,6 @@
#import <Cocoa/Cocoa.h>
#import <OpenEmuBase/OEGameCore.h>
OE_EXPORTED_CLASS
@interface mGBAGameCore : OEGameCore
@end

View File

@ -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