Files
blueMSX-Core/blueMSXGameCore.m
2017-07-20 01:59:52 -07:00

836 lines
24 KiB
Objective-C

/*
Copyright (c) 2015, 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 "blueMSXGameCore.h"
#import <OpenEmuBase/OERingBuffer.h>
#import <OpenGL/gl.h>
#import "OEMSXSystemResponderClient.h"
#import "OEColecoVisionSystemResponderClient.h"
#include "ArchInput.h"
#include "ArchNotifications.h"
#include "Actions.h"
#include "JoystickPort.h"
#include "Machine.h"
#include "MidiIO.h"
#include "UartIO.h"
#include "Casette.h"
#include "Emulator.h"
#include "Board.h"
#include "Language.h"
#include "LaunchFile.h"
#include "PrinterIO.h"
#include "InputEvent.h"
#import "Emulator.h"
#include "ArchEvent.h"
#include "Properties.h"
#include "VideoRender.h"
#include "AudioMixer.h"
#include "CMCocoaBuffer.h"
#define SOUND_SAMPLE_RATE 44100
#define SOUND_FRAME_SIZE 8192
#define SOUND_BYTES_PER_FRAME 2
#define FB_MAX_WIDTH (272 * 2)
#define FB_MAX_HEIGHT 240
#define virtualCodeSet(eventCode) self->virtualCodeMap[eventCode] = 1
#define virtualCodeUnset(eventCode) self->virtualCodeMap[eventCode] = 0
#define virtualCodeClear() memset(self->virtualCodeMap, 0, sizeof(self->virtualCodeMap));
@interface blueMSXGameCore () <OEMSXSystemResponderClient, OEColecoVisionSystemResponderClient>
{
uint32_t *_videoBuffer;
int _videoWidth, _videoHeight;
int virtualCodeMap[256];
BOOL _isDoubleWidth;
NSString *fileToLoad;
RomType romTypeToLoad;
Properties *properties;
Video *video;
Mixer *mixer;
}
- (void)initializeEmulator;
@end
static blueMSXGameCore *_core;
static Int32 mixAudio(void *param, Int16 *buffer, UInt32 count);
static int framebufferScanline = 0;
@implementation blueMSXGameCore
- (id)init
{
if ((self = [super init]))
{
_videoWidth = 272;
_videoHeight = 240;
_isDoubleWidth = NO;
_core = self;
}
return self;
}
- (void)dealloc
{
free(_videoBuffer);
propDestroy(properties);
mixerSetWriteCallback(mixer, NULL, NULL, 0);
mixerDestroy(mixer);
}
- (void)initializeEmulator
{
NSString *resourcePath = [[[self owner] bundle] resourcePath];
__block NSString *machinesPath = [resourcePath stringByAppendingPathComponent:@"Machines"];
__block NSString *machineName;
if([[self systemIdentifier] isEqualToString:@"openemu.system.colecovision"])
machineName = @"COL - ColecoVision";
else
machineName = @"MSX2+ - C-BIOS - JP";
NSFileManager *fm = [NSFileManager defaultManager];
NSURL *supportPath = [NSURL fileURLWithPath:[self supportDirectoryPath]];
NSURL *customMachinesPath = [supportPath URLByAppendingPathComponent:@"Machines"];
if ([customMachinesPath checkResourceIsReachableAndReturnError:NULL] == YES && ![[self systemIdentifier] isEqualToString:@"openemu.system.colecovision"])
{
NSArray *customMachines = [fm contentsOfDirectoryAtURL:customMachinesPath
includingPropertiesForKeys:nil
options:NSDirectoryEnumerationSkipsHiddenFiles
error:NULL];
[customMachines enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
NSString *customMachine = [[obj lastPathComponent] stringByDeletingPathExtension];
machinesPath = [customMachinesPath path];
machineName = customMachine;
NSLog(@"blueMSX: Will use custom machine \"%@\"", customMachine);
*stop = YES;
}];
}
else
{
[fm createDirectoryAtURL:customMachinesPath
withIntermediateDirectories:YES
attributes:nil
error:NULL];
}
properties = propCreate(0, EMU_LANG_ENGLISH, P_KBD_EUROPEAN, P_EMU_SYNCNONE, "");
// Set machine name
machineSetDirectory([machinesPath UTF8String]);
strncpy(properties->emulation.machineName,
[machineName UTF8String], PROP_MAXPATH - 1);
// Set up properties
properties->emulation.speed = 50;
properties->emulation.syncMethod = P_EMU_SYNCTOVBLANKASYNC;
properties->emulation.enableFdcTiming = YES;
properties->emulation.vdpSyncMode = P_VDP_SYNCAUTO;
properties->video.brightness = 100;
properties->video.contrast = 100;
properties->video.saturation = 100;
properties->video.gamma = 100;
properties->video.colorSaturationWidth = 0;
properties->video.colorSaturationEnable = NO;
properties->video.deInterlace = YES;
properties->video.monitorType = P_VIDEO_PALNONE;
properties->video.monitorColor = P_VIDEO_COLOR;
properties->video.scanlinesPct = 100;
properties->video.scanlinesEnable = (properties->video.scanlinesPct < 100);
properties->sound.mixerChannel[MIXER_CHANNEL_PSG].volume = 100;
properties->sound.mixerChannel[MIXER_CHANNEL_PSG].pan = 50;
properties->sound.mixerChannel[MIXER_CHANNEL_PSG].enable = YES;
properties->sound.mixerChannel[MIXER_CHANNEL_SCC].volume = 100;
properties->sound.mixerChannel[MIXER_CHANNEL_SCC].pan = 50;
properties->sound.mixerChannel[MIXER_CHANNEL_SCC].enable = YES;
properties->sound.mixerChannel[MIXER_CHANNEL_MSXMUSIC].volume = 100;
properties->sound.mixerChannel[MIXER_CHANNEL_MSXMUSIC].pan = 50;
properties->sound.mixerChannel[MIXER_CHANNEL_MSXMUSIC].enable = YES;
properties->sound.mixerChannel[MIXER_CHANNEL_MSXAUDIO].volume = 100;
properties->sound.mixerChannel[MIXER_CHANNEL_MSXAUDIO].pan = 50;
properties->sound.mixerChannel[MIXER_CHANNEL_MSXAUDIO].enable = YES;
properties->sound.mixerChannel[MIXER_CHANNEL_KEYBOARD].volume = 100;
properties->sound.mixerChannel[MIXER_CHANNEL_KEYBOARD].pan = 50;
properties->sound.mixerChannel[MIXER_CHANNEL_KEYBOARD].enable = YES;
properties->sound.mixerChannel[MIXER_CHANNEL_MOONSOUND].volume = 100;
properties->sound.mixerChannel[MIXER_CHANNEL_MOONSOUND].pan = 50;
properties->sound.mixerChannel[MIXER_CHANNEL_MOONSOUND].enable = YES;
if([[self systemIdentifier] isEqualToString:@"openemu.system.colecovision"])
{
properties->joy1.typeId = JOYSTICK_PORT_COLECOJOYSTICK;
properties->joy2.typeId = JOYSTICK_PORT_COLECOJOYSTICK;
}
else
{
properties->joy1.typeId = JOYSTICK_PORT_JOYSTICK;
properties->joy2.typeId = JOYSTICK_PORT_JOYSTICK;
}
// Init translations (unused for the most part)
langSetLanguage(properties->language);
langInit();
// Init input
joystickPortSetType(0, properties->joy1.typeId);
joystickPortSetType(1, properties->joy2.typeId);
// Init misc. devices
printerIoSetType(properties->ports.Lpt.type, properties->ports.Lpt.fileName);
printerIoSetType(properties->ports.Lpt.type, properties->ports.Lpt.fileName);
uartIoSetType(properties->ports.Com.type, properties->ports.Com.fileName);
midiIoSetMidiOutType(properties->sound.MidiOut.type, properties->sound.MidiOut.fileName);
midiIoSetMidiInType(properties->sound.MidiIn.type, properties->sound.MidiIn.fileName);
ykIoSetMidiInType(properties->sound.YkIn.type, properties->sound.YkIn.fileName);
// Init mixer
mixer = mixerCreate();
for (int i = 0; i < MIXER_CHANNEL_TYPE_COUNT; i++)
{
mixerSetChannelTypeVolume(mixer, i, properties->sound.mixerChannel[i].volume);
mixerSetChannelTypePan(mixer, i, properties->sound.mixerChannel[i].pan);
mixerEnableChannelType(mixer, i, properties->sound.mixerChannel[i].enable);
}
mixerSetMasterVolume(mixer, properties->sound.masterVolume);
mixerEnableMaster(mixer, properties->sound.masterEnable);
mixerSetStereo(mixer, YES);
mixerSetWriteCallback(mixer, mixAudio, (__bridge void *)[self ringBufferAtIndex:0], SOUND_FRAME_SIZE);
// Init media DB
mediaDbLoad([[resourcePath stringByAppendingPathComponent:@"Databases"] UTF8String]);
mediaDbSetDefaultRomType(properties->cartridge.defaultType);
// Init board
boardSetFdcTimingEnable(properties->emulation.enableFdcTiming);
boardSetY8950Enable(properties->sound.chip.enableY8950);
boardSetYm2413Enable(properties->sound.chip.enableYM2413);
boardSetMoonsoundEnable(properties->sound.chip.enableMoonsound);
boardSetVideoAutodetect(properties->video.detectActiveMonitor);
boardEnableSnapshots(0);
// Init storage
for (int i = 0; i < PROP_MAX_CARTS; i++)
{
if (properties->media.carts[i].fileName[0])
insertCartridge(properties, i, properties->media.carts[i].fileName,
properties->media.carts[i].fileNameInZip,
properties->media.carts[i].type, -1);
}
for (int i = 0; i < PROP_MAX_DISKS; i++)
{
if (properties->media.disks[i].fileName[0])
insertDiskette(properties, i, properties->media.disks[i].fileName,
properties->media.disks[i].fileNameInZip, -1);
}
for (int i = 0; i < PROP_MAX_TAPES; i++)
{
if (properties->media.tapes[i].fileName[0])
insertCassette(properties, i, properties->media.tapes[i].fileName,
properties->media.tapes[i].fileNameInZip, 0);
}
tapeSetReadOnly(properties->cassette.readOnly);
// Misc. initialization
emulatorInit(properties, mixer);
actionInit(video, properties, mixer);
emulatorRestartSound();
}
- (void)startEmulation
{
// propertiesSetDirectory("", "");
// tapeSetDirectory("/Cassettes", "");
NSURL *batterySavesPath = [NSURL fileURLWithPath:[self batterySavesDirectoryPath]];
[[NSFileManager defaultManager] createDirectoryAtURL:batterySavesPath
withIntermediateDirectories:YES
attributes:nil
error:NULL];
boardSetDirectory([[self batterySavesDirectoryPath] UTF8String]);
tryLaunchUnknownFile(properties, [fileToLoad UTF8String], YES);
[super startEmulation];
}
- (void)stopEmulation
{
emulatorSuspend();
emulatorStop();
[super stopEmulation];
}
- (void)setPauseEmulation:(BOOL)pauseEmulation
{
if (pauseEmulation)
emulatorSetState(EMU_PAUSED);
else
emulatorSetState(EMU_RUNNING);
[super setPauseEmulation:pauseEmulation];
}
- (void)resetEmulation
{
actionEmuResetSoft();
}
- (void)fastForward:(BOOL)flag
{
[super fastForward:flag];
properties->emulation.speed = flag ? 100 : 50;
emulatorSetFrequency(properties->emulation.speed, NULL);
}
- (oneway void)didPushColecoVisionButton:(OEColecoVisionButton)button forPlayer:(NSUInteger)player;
{
int code = -1;
switch (button)
{
case OEColecoVisionButtonUp:
code = (player == 1) ? EC_JOY1_UP : EC_JOY2_UP;
break;
case OEColecoVisionButtonDown:
code = (player == 1) ? EC_JOY1_DOWN : EC_JOY2_DOWN;
break;
case OEColecoVisionButtonLeft:
code = (player == 1) ? EC_JOY1_LEFT : EC_JOY2_LEFT;
break;
case OEColecoVisionButtonRight:
code = (player == 1) ? EC_JOY1_RIGHT : EC_JOY2_RIGHT;
break;
case OEColecoVisionButtonLeftAction:
code = (player == 1) ? EC_JOY1_BUTTON1 : EC_JOY2_BUTTON1;
break;
case OEColecoVisionButtonRightAction:
code = (player == 1) ? EC_JOY1_BUTTON2 : EC_JOY2_BUTTON2;
break;
case OEColecoVisionButton1:
code = (player == 1) ? EC_COLECO1_1 : EC_COLECO2_1;
break;
case OEColecoVisionButton2:
code = (player == 1) ? EC_COLECO1_2 : EC_COLECO2_2;
break;
case OEColecoVisionButton3:
code = (player == 1) ? EC_COLECO1_3 : EC_COLECO2_3;
break;
case OEColecoVisionButton4:
code = (player == 1) ? EC_COLECO1_4 : EC_COLECO2_4;
break;
case OEColecoVisionButton5:
code = (player == 1) ? EC_COLECO1_5 : EC_COLECO2_5;
break;
case OEColecoVisionButton6:
code = (player == 1) ? EC_COLECO1_6 : EC_COLECO2_6;
break;
case OEColecoVisionButton7:
code = (player == 1) ? EC_COLECO1_7 : EC_COLECO2_7;
break;
case OEColecoVisionButton8:
code = (player == 1) ? EC_COLECO1_8 : EC_COLECO2_8;
break;
case OEColecoVisionButton9:
code = (player == 1) ? EC_COLECO1_9 : EC_COLECO2_9;
break;
case OEColecoVisionButton0:
code = (player == 1) ? EC_COLECO1_0 : EC_COLECO2_0;
break;
case OEColecoVisionButtonAsterisk:
code = (player == 1) ? EC_COLECO1_STAR : EC_COLECO2_STAR;
break;
case OEColecoVisionButtonPound:
code = (player == 1) ? EC_COLECO1_HASH : EC_COLECO2_HASH;
break;
default:
break;
}
if (code != -1)
virtualCodeSet(code);
}
- (oneway void)didReleaseColecoVisionButton:(OEColecoVisionButton)button forPlayer:(NSUInteger)player;
{
int code = -1;
switch (button)
{
case OEColecoVisionButtonUp:
code = (player == 1) ? EC_JOY1_UP : EC_JOY2_UP;
break;
case OEColecoVisionButtonDown:
code = (player == 1) ? EC_JOY1_DOWN : EC_JOY2_DOWN;
break;
case OEColecoVisionButtonLeft:
code = (player == 1) ? EC_JOY1_LEFT : EC_JOY2_LEFT;
break;
case OEColecoVisionButtonRight:
code = (player == 1) ? EC_JOY1_RIGHT : EC_JOY2_RIGHT;
break;
case OEColecoVisionButtonLeftAction:
code = (player == 1) ? EC_JOY1_BUTTON1 : EC_JOY2_BUTTON1;
break;
case OEColecoVisionButtonRightAction:
code = (player == 1) ? EC_JOY1_BUTTON2 : EC_JOY2_BUTTON2;
break;
case OEColecoVisionButton1:
code = (player == 1) ? EC_COLECO1_1 : EC_COLECO2_1;
break;
case OEColecoVisionButton2:
code = (player == 1) ? EC_COLECO1_2 : EC_COLECO2_2;
break;
case OEColecoVisionButton3:
code = (player == 1) ? EC_COLECO1_3 : EC_COLECO2_3;
break;
case OEColecoVisionButton4:
code = (player == 1) ? EC_COLECO1_4 : EC_COLECO2_4;
break;
case OEColecoVisionButton5:
code = (player == 1) ? EC_COLECO1_5 : EC_COLECO2_5;
break;
case OEColecoVisionButton6:
code = (player == 1) ? EC_COLECO1_6 : EC_COLECO2_6;
break;
case OEColecoVisionButton7:
code = (player == 1) ? EC_COLECO1_7 : EC_COLECO2_7;
break;
case OEColecoVisionButton8:
code = (player == 1) ? EC_COLECO1_8 : EC_COLECO2_8;
break;
case OEColecoVisionButton9:
code = (player == 1) ? EC_COLECO1_9 : EC_COLECO2_9;
break;
case OEColecoVisionButton0:
code = (player == 1) ? EC_COLECO1_0 : EC_COLECO2_0;
break;
case OEColecoVisionButtonAsterisk:
code = (player == 1) ? EC_COLECO1_STAR : EC_COLECO2_STAR;
break;
case OEColecoVisionButtonPound:
code = (player == 1) ? EC_COLECO1_HASH : EC_COLECO2_HASH;
break;
default:
break;
}
if (code != -1)
virtualCodeUnset(code);
}
- (oneway void)didPushMSXJoystickButton:(OEMSXJoystickButton)button
controller:(NSInteger)index
{
int code = -1;
switch (button)
{
case OEMSXJoystickUp:
code = (index == 1) ? EC_JOY1_UP : EC_JOY2_UP;
break;
case OEMSXJoystickDown:
code = (index == 1) ? EC_JOY1_DOWN : EC_JOY2_DOWN;
break;
case OEMSXJoystickLeft:
code = (index == 1) ? EC_JOY1_LEFT : EC_JOY2_LEFT;
break;
case OEMSXJoystickRight:
code = (index == 1) ? EC_JOY1_RIGHT : EC_JOY2_RIGHT;
break;
case OEMSXButtonA:
code = (index == 1) ? EC_JOY1_BUTTON1 : EC_JOY2_BUTTON1;
break;
case OEMSXButtonB:
code = (index == 1) ? EC_JOY1_BUTTON2 : EC_JOY2_BUTTON2;
break;
default:
break;
}
if (code != -1)
virtualCodeSet(code);
}
- (oneway void)didReleaseMSXJoystickButton:(OEMSXJoystickButton)button
controller:(NSInteger)index
{
int code = -1;
switch (button)
{
case OEMSXJoystickUp:
code = (index == 1) ? EC_JOY1_UP : EC_JOY2_UP;
break;
case OEMSXJoystickDown:
code = (index == 1) ? EC_JOY1_DOWN : EC_JOY2_DOWN;
break;
case OEMSXJoystickLeft:
code = (index == 1) ? EC_JOY1_LEFT : EC_JOY2_LEFT;
break;
case OEMSXJoystickRight:
code = (index == 1) ? EC_JOY1_RIGHT : EC_JOY2_RIGHT;
break;
case OEMSXButtonA:
code = (index == 1) ? EC_JOY1_BUTTON1 : EC_JOY2_BUTTON1;
break;
case OEMSXButtonB:
code = (index == 1) ? EC_JOY1_BUTTON2 : EC_JOY2_BUTTON2;
break;
default:
break;
}
if (code != -1)
virtualCodeUnset(code);
}
- (oneway void)didPressKey:(OEMSXKey)key
{
virtualCodeSet(key);
}
- (oneway void)didReleaseKey:(OEMSXKey)key
{
virtualCodeUnset(key);
}
- (void)executeFrame
{
// Update controls
memcpy(eventMap, _core->virtualCodeMap, sizeof(_core->virtualCodeMap));
}
- (NSTimeInterval)frameInterval
{
return boardGetRefreshRate() ? boardGetRefreshRate() : 60;
}
#pragma mark - OE I/O
- (BOOL)loadFileAtPath:(NSString *)path error:(NSError **)error
{
[self initializeEmulator];
fileToLoad = nil;
romTypeToLoad = ROM_UNKNOWN;
const char *cpath = [path UTF8String];
MediaType *mediaType = mediaDbLookupRomByPath(cpath);
if (!mediaType)
mediaType = mediaDbGuessRomByPath(cpath);
if (mediaType)
romTypeToLoad = mediaDbGetRomType(mediaType);
fileToLoad = path;
return YES;
}
- (void)saveStateToFileAtPath:(NSString *)fileName completionHandler:(void (^)(BOOL, NSError *))block
{
emulatorSuspend();
boardSaveState([fileName fileSystemRepresentation], 1);
emulatorResume();
block(YES, nil);
}
- (void)loadStateFromFileAtPath:(NSString *)fileName completionHandler:(void (^)(BOOL, NSError *))block
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 200 * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
emulatorSuspend();
emulatorStop();
emulatorStart([fileName fileSystemRepresentation]);
block(YES, nil);
});
}
#pragma mark - OE Video
- (OEIntSize)bufferSize
{
return OEIntSizeMake(FB_MAX_WIDTH, FB_MAX_HEIGHT);
}
- (OEIntRect)screenRect
{
return OEIntRectMake(0, 0, _videoWidth, _videoHeight);
}
- (OEIntSize)aspectSize
{
return OEIntSizeMake(256 * (8.0/7.0), 240);
}
- (const void *)getVideoBufferWithHint:(void *)hint
{
if (!hint) {
if (!_videoBuffer) _videoBuffer = (uint32_t *)malloc(FB_MAX_WIDTH * FB_MAX_HEIGHT * sizeof(uint32_t));
hint = _videoBuffer;
}
return _videoBuffer = (uint32_t *)hint;
}
- (GLenum)pixelFormat
{
return GL_BGRA;
}
- (GLenum)pixelType
{
return GL_UNSIGNED_INT_8_8_8_8_REV;
}
#pragma mark - OE Audio
- (double)audioSampleRate
{
return SOUND_SAMPLE_RATE;
}
- (NSUInteger)channelCount
{
return 2;
}
#pragma mark - Audio
static Int32 mixAudio(void *param, Int16 *buffer, UInt32 count)
{
[[_core ringBufferAtIndex:0] write:buffer maxLength:count * SOUND_BYTES_PER_FRAME];
return 0;
}
#pragma mark - blueMSX callbacks
#pragma mark - Emulation callbacks
void archEmulationStartNotification()
{
}
void archEmulationStopNotification()
{
}
void archEmulationStartFailure()
{
}
#pragma mark - Debugging callbacks
void archTrap(UInt8 value)
{
}
#pragma mark - Input Callbacks
void archPollInput()
{
}
UInt8 archJoystickGetState(int joystickNo)
{
return 0; // Coleco-specific; unused
}
void archKeyboardSetSelectedKey(int keyCode)
{
}
#pragma mark - Mouse Callbacks
void archMouseGetState(int *dx, int *dy)
{
// FIXME
// @autoreleasepool
// {
// NSPoint coordinates = theEmulator.mouse.pointerCoordinates;
// *dx = (int)coordinates.x;
// *dy = (int)coordinates.y;
// }
}
int archMouseGetButtonState(int checkAlways)
{
// FIXME
// @autoreleasepool
// {
// return theEmulator.mouse.buttonState;
// }
return 0;
}
void archMouseEmuEnable(AmEnableMode mode)
{
// FIXME
// @autoreleasepool
// {
// theEmulator.mouse.mouseMode = mode;
// }
}
void archMouseSetForceLock(int lock)
{
}
#pragma mark - Sound callbacks
void archSoundCreate(Mixer* mixer, UInt32 sampleRate, UInt32 bufferSize, Int16 channels)
{
}
void archSoundDestroy()
{
}
void archSoundResume()
{
}
void archSoundSuspend()
{
}
#pragma mark - Video callbacks
int archUpdateEmuDisplay(int syncMode)
{
return 1;
}
void archUpdateWindow()
{
}
void *archScreenCapture(ScreenCaptureType type, int *bitmapSize, int onlyBmp)
{
return NULL;
}
// Framebuffer
Pixel *frameBufferGetLine(FrameBuffer *frameBuffer, int y)
{
return (_core->_videoBuffer + y * FB_MAX_WIDTH);
}
FrameBufferData *frameBufferDataCreate(int maxWidth, int maxHeight, int defaultHorizZoom)
{
return (void *)_core->_videoBuffer;
}
FrameBufferData *frameBufferGetActive()
{
return (void *)_core->_videoBuffer;
}
FrameBuffer *frameBufferGetDrawFrame()
{
return (void *)_core->_videoBuffer;
}
FrameBuffer *frameBufferFlipDrawFrame()
{
return (void *)_core->_videoBuffer;
}
void frameBufferSetLineCount(FrameBuffer *frameBuffer, int val)
{
_core->_videoHeight = val;
}
int frameBufferGetLineCount(FrameBuffer *frameBuffer) {
return _core->_videoHeight;
}
int frameBufferGetDoubleWidth(FrameBuffer *frameBuffer, int y)
{
return _core->_isDoubleWidth;
}
void frameBufferSetDoubleWidth(FrameBuffer *frameBuffer, int y, int val)
{
if(_core->_isDoubleWidth != val)
{
_core->_isDoubleWidth = val;
_core->_videoWidth = _core->_isDoubleWidth ? FB_MAX_WIDTH : 272;
}
}
// MSX Ascii Laser and Gunstick
void frameBufferSetScanline(int scanline)
{
framebufferScanline = scanline;
}
int frameBufferGetScanline()
{
return framebufferScanline;
}
int frameBufferGetMaxWidth(FrameBuffer *frameBuffer)
{
return _core->_videoWidth;
}
void frameBufferDataDestroy(FrameBufferData *frameData) {}
void frameBufferSetActive(FrameBufferData *frameData) {}
void frameBufferSetMixMode(FrameBufferMixMode mode, FrameBufferMixMode mask) {}
void frameBufferClearDeinterlace() {}
void frameBufferSetInterlace(FrameBuffer *frameBuffer, int val) {}
@end