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