Files
2023-04-01 10:20:33 +11:00

866 lines
27 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 "ATR800GameCore.h"
#import <OpenEmuBase/OERingBuffer.h>
#import "OEA8SystemResponderClient.h"
#import "OE5200SystemResponderClient.h"
#import <OpenGL/gl.h>
#include "afile.h"
#include "akey.h"
#include "antic.h"
#include "atari.h"
#include "cartridge.h"
#include "cassette.h"
#include "cfg.h"
#include "colours.h"
#include "colours_ntsc.h"
#include "config.h"
#include "devices.h"
#include "gtia.h"
#include "ide.h"
#include "input.h"
#include "memory.h"
#include "pbi.h"
#include "pia.h"
#include "platform.h"
#include "pokey.h"
#include "pokeysnd.h"
#include "rtime.h"
#include "sio.h"
#include "sound.h"
#include "statesav.h"
#include "sysrom.h"
#include "ui.h"
int UI_is_active = FALSE;
int UI_alt_function = -1;
int UI_n_atari_files_dir = 0;
int UI_n_saved_files_dir = 0;
char UI_atari_files_dir[UI_MAX_DIRECTORIES][FILENAME_MAX];
char UI_saved_files_dir[UI_MAX_DIRECTORIES][FILENAME_MAX];
typedef struct {
int up;
int down;
int left;
int right;
int fire;
int fire2;
int start;
int pause;
int reset;
} ATR5200ControllerState;
@interface ATR800GameCore () <OEA8SystemResponderClient, OE5200SystemResponderClient>
{
uint8_t *_videoBuffer;
uint8_t *_soundBuffer;
ATR5200ControllerState controllerStates[4];
}
- (ATR5200ControllerState)controllerStateForPlayer:(NSUInteger)playerNum;
//int16_t convertSample(uint8_t);
@end
static ATR800GameCore *_currentCore;
//void ATR800WriteSoundBuffer(uint8_t *buffer, unsigned int len);
@implementation ATR800GameCore
- (id)init
{
if((self = [super init]))
{
_soundBuffer = malloc(2048); // 4096 if stereo?
}
_currentCore = self;
return self;
}
- (void)dealloc
{
Atari800_Exit(false);
free(_videoBuffer);
free(_soundBuffer);
}
#pragma mark - Execution
- (BOOL)loadFileAtPath:(NSString *)path error:(NSError **)error
{
// Set the default palette (NTSC)
NSString *palettePath = [[[NSBundle bundleForClass:[self class]] resourcePath] stringByAppendingPathComponent:@"Default.act"];
strcpy(COLOURS_NTSC_external.filename, palettePath.fileSystemRepresentation);
COLOURS_NTSC_external.loaded = TRUE;
Atari800_tv_mode = Atari800_TV_NTSC;
/* It is necessary because of the CARTRIDGE_ColdStart (there must not be the
registry-read value available at startup) */
CARTRIDGE_main.type = CARTRIDGE_NONE;
Colours_PreInitialise();
if([[self systemIdentifier] isEqualToString:@"openemu.system.5200"])
{
// Set 5200.rom BIOS path
char biosFileName[2048];
NSString *biosPath = [self biosDirectoryPath];
strcpy(biosFileName, [[biosPath stringByAppendingPathComponent:@"5200.rom"] fileSystemRepresentation]);
SYSROM_SetPath(biosFileName, 1, SYSROM_5200);
// Setup machine type
Atari800_SetMachineType(Atari800_MACHINE_5200);
MEMORY_ram_size = 16;
}
else if([[self systemIdentifier] isEqualToString:@"openemu.system.atari8bit"])
{
char basicFileName[2048], osbFileName[2048], xlFileName[2048];
NSString *biosPath = [self biosDirectoryPath];
strcpy(basicFileName, [[biosPath stringByAppendingPathComponent:@"ataribas.rom"] fileSystemRepresentation]);
strcpy(osbFileName, [[biosPath stringByAppendingPathComponent:@"atariosb.rom"] fileSystemRepresentation]);
strcpy(xlFileName, [[biosPath stringByAppendingPathComponent:@"atarixl.rom"] fileSystemRepresentation]);
SYSROM_SetPath(basicFileName, 1, SYSROM_BASIC_C);
SYSROM_SetPath(osbFileName, 2, SYSROM_B_NTSC, SYSROM_800_CUSTOM);
SYSROM_SetPath(xlFileName, 1, SYSROM_BB01R2);
// Setup machine type as Atari 130XE
Atari800_SetMachineType(Atari800_MACHINE_XLXE);
MEMORY_ram_size = 128;
Atari800_builtin_basic = TRUE;
Atari800_keyboard_leds = FALSE;
Atari800_f_keys = FALSE;
Atari800_jumper = FALSE;
Atari800_builtin_game = FALSE;
Atari800_keyboard_detached = FALSE;
// Disable on-screen disk activity indicator
Screen_show_disk_led = FALSE;
}
int arg = 0;
int *argc = &arg;
char *argv[] = {};
if (
#if !defined(BASIC) && !defined(CURSES_BASIC)
!Colours_Initialise(argc, argv) ||
#endif
!Devices_Initialise(argc, argv)
|| !RTIME_Initialise(argc, argv)
#ifdef IDE
|| !IDE_Initialise(argc, argv)
#endif
|| !SIO_Initialise (argc, argv)
|| !CASSETTE_Initialise(argc, argv)
|| !PBI_Initialise(argc,argv)
#ifdef VOICEBOX
|| !VOICEBOX_Initialise(argc, argv)
#endif
#ifndef BASIC
|| !INPUT_Initialise(argc, argv)
#endif
#ifdef XEP80_EMULATION
|| !XEP80_Initialise(argc, argv)
#endif
#ifdef AF80
|| !AF80_Initialise(argc, argv)
#endif
#if SUPPORTS_CHANGE_VIDEOMODE
|| !VIDEOMODE_Initialise(argc, argv)
#endif
#ifndef DONT_DISPLAY
/* Platform Specific Initialisation */
|| !PLATFORM_Initialise(argc, argv)
#endif
|| !Screen_Initialise(argc, argv)
/* Initialise Custom Chips */
|| !ANTIC_Initialise(argc, argv)
|| !GTIA_Initialise(argc, argv)
|| !PIA_Initialise(argc, argv)
|| !POKEY_Initialise(argc, argv)
) {
NSLog(@"Failed to initialize part of atari800");
return NO;
}
if(!Atari800_InitialiseMachine()) {
NSLog(@"** Failed to initialize machine");
return NO;
}
// Open and try to automatically detect file type, not 100% accurate
if(!AFILE_OpenFile(path.fileSystemRepresentation, 1, 1, FALSE))
{
NSLog(@"Failed to open file");
return NO;
}
// TODO - still need this?
/* Install requested ROM cartridge */
if (CARTRIDGE_main.type == CARTRIDGE_UNKNOWN)
{
CARTRIDGE_SetType(&CARTRIDGE_main, UI_SelectCartType(CARTRIDGE_main.size));
}
//POKEYSND_Init(POKEYSND_FREQ_17_EXACT, 44100, 1, POKEYSND_BIT16);
return YES;
}
- (void)executeFrame
{
Atari800_Frame();
unsigned int size = 44100 / (Atari800_tv_mode == Atari800_TV_NTSC ? 59.9 : 50) * 2;
Sound_Callback(_soundBuffer, size);
//NSLog(@"Sound_desired.channels %d frag_frames %d freq %d sample_size %d", Sound_desired.channels, Sound_desired.frag_frames, Sound_desired.freq, Sound_desired.sample_size);
//NSLog(@"Sound_out.channels %d frag_frames %d freq %d sample_size %d", Sound_out.channels, Sound_out.frag_frames, Sound_out.freq, Sound_out.sample_size);
[[self ringBufferAtIndex:0] write:_soundBuffer maxLength:size];
}
- (void)resetEmulation
{
Atari800_Warmstart();
}
- (void)stopEmulation
{
[super stopEmulation];
}
- (NSTimeInterval)frameInterval
{
return Atari800_tv_mode == Atari800_TV_NTSC ? Atari800_FPS_NTSC : Atari800_FPS_PAL;
}
#pragma mark - Video
- (const void *)getVideoBufferWithHint:(void *)hint
{
if (!hint) {
if (!_videoBuffer) _videoBuffer = (uint8_t *)malloc(Screen_WIDTH * Screen_HEIGHT * 4);
hint = _videoBuffer;
}
// TODO: support paletted video in OE
int i, j;
UBYTE *source = (UBYTE *)(Screen_atari);
UBYTE *destination = (uint8_t*)hint;
for (i = 0; i < Screen_HEIGHT; i++)
{
for (j = 0; j < Screen_WIDTH; j++)
{
UBYTE r,g,b;
r = Colours_GetR(*source);
g = Colours_GetG(*source);
b = Colours_GetB(*source);
*destination++ = b;
*destination++ = g;
*destination++ = r;
*destination++ = 0xff;
source++;
}
// source += Screen_WIDTH - ATARI_VISIBLE_WIDTH;
}
return hint;
}
- (OEIntSize)bufferSize
{
return OEIntSizeMake(Screen_WIDTH, Screen_HEIGHT);
}
- (OEIntRect)screenRect
{
return OEIntRectMake(24, 0, 336, 240);
}
- (OEIntSize)aspectSize
{
// TODO: fix PAR
//return OEIntSizeMake(336 * (6.0 / 7.0), 240);
return OEIntSizeMake(336, 240);
}
- (GLenum)pixelFormat
{
return GL_BGRA;
}
- (GLenum)pixelType
{
return GL_UNSIGNED_INT_8_8_8_8_REV;
}
#pragma mark - Audio
- (double)audioSampleRate
{
return 44100;
}
- (NSUInteger)channelCount
{
return 1;
}
#pragma mark - Save States
- (void)saveStateToFileAtPath:(NSString *)fileName completionHandler:(void (^)(BOOL, NSError *))block
{
BOOL success = StateSav_SaveAtariState(fileName.fileSystemRepresentation, "wb", TRUE);
if(block) block(success==YES, nil);
}
- (void)loadStateFromFileAtPath:(NSString *)fileName completionHandler:(void (^)(BOOL, NSError *))block
{
BOOL success = StateSav_ReadAtariState(fileName.fileSystemRepresentation, "rb");
if(block) block(success==YES, nil);
}
#pragma mark - Input
- (oneway void)mouseMovedAtPoint:(OEIntPoint)point
{
}
- (oneway void)leftMouseDownAtPoint:(OEIntPoint)point
{
}
- (oneway void)leftMouseUp
{
}
- (oneway void)rightMouseDownAtPoint:(OEIntPoint)point
{
}
- (oneway void)rightMouseUp
{
}
- (oneway void)keyDown:(NSUInteger)keyHIDCode
{
}
- (oneway void)keyUp:(NSUInteger)keyHIDCode
{
}
- (oneway void)didPushA8Button:(OEA8Button)button forPlayer:(NSUInteger)player
{
player--;
switch (button)
{
case OEA8ButtonFire:
controllerStates[player].fire = 1;
break;
case OEA8JoystickUp:
controllerStates[player].up = 1;
//INPUT_key_code = AKEY_UP ^ AKEY_CTRL;
//INPUT_key_code = INPUT_STICK_FORWARD;
break;
case OEA8JoystickDown:
controllerStates[player].down = 1;
break;
case OEA8JoystickLeft:
controllerStates[player].left = 1;
break;
case OEA8JoystickRight:
controllerStates[player].right = 1;
break;
default:
break;
}
}
- (oneway void)didReleaseA8Button:(OEA8Button)button forPlayer:(NSUInteger)player
{
player--;
switch (button)
{
case OEA8ButtonFire:
controllerStates[player].fire = 0;
break;
case OEA8JoystickUp:
controllerStates[player].up = 0;
//INPUT_key_code = AKEY_UP ^ AKEY_CTRL;
//INPUT_key_code = INPUT_STICK_FORWARD;
break;
case OEA8JoystickDown:
controllerStates[player].down = 0;
break;
case OEA8JoystickLeft:
controllerStates[player].left = 0;
break;
case OEA8JoystickRight:
controllerStates[player].right = 0;
break;
default:
break;
}
}
- (oneway void)didPush5200Button:(OE5200Button)button forPlayer:(NSUInteger)player
{
player--;
switch (button)
{
case OE5200ButtonFire1:
controllerStates[player].fire = 1;
break;
case OE5200ButtonFire2:
//controllerStates[player].fire2 = 1;
INPUT_key_shift = 1; //AKEY_SHFTCTRL
break;
case OE5200ButtonUp:
controllerStates[player].up = 1;
//INPUT_key_code = AKEY_UP ^ AKEY_CTRL;
//INPUT_key_code = INPUT_STICK_FORWARD;
break;
case OE5200ButtonDown:
controllerStates[player].down = 1;
break;
case OE5200ButtonLeft:
controllerStates[player].left = 1;
break;
case OE5200ButtonRight:
controllerStates[player].right = 1;
break;
case OE5200ButtonStart:
// controllerStates[player].start = 1;
INPUT_key_code = AKEY_5200_START;
break;
case OE5200ButtonPause:
INPUT_key_code = AKEY_5200_PAUSE;
break;
case OE5200ButtonReset:
INPUT_key_code = AKEY_5200_RESET;
break;
case OE5200Button1:
INPUT_key_code = AKEY_5200_1;
break;
case OE5200Button2:
INPUT_key_code = AKEY_5200_2;
break;
case OE5200Button3:
INPUT_key_code = AKEY_5200_3;
break;
case OE5200Button4:
INPUT_key_code = AKEY_5200_4;
break;
case OE5200Button5:
INPUT_key_code = AKEY_5200_5;
break;
case OE5200Button6:
INPUT_key_code = AKEY_5200_6;
break;
case OE5200Button7:
INPUT_key_code = AKEY_5200_7;
break;
case OE5200Button8:
INPUT_key_code = AKEY_5200_8;
break;
case OE5200Button9:
INPUT_key_code = AKEY_5200_9;
break;
case OE5200Button0:
INPUT_key_code = AKEY_5200_0;
break;
case OE5200ButtonAsterisk:
INPUT_key_code = AKEY_5200_ASTERISK;
break;
case OE5200ButtonPound:
INPUT_key_code = AKEY_5200_HASH;
break;
default:
break;
}
}
- (oneway void)didRelease5200Button:(OE5200Button)button forPlayer:(NSUInteger)player
{
player--;
switch (button)
{
case OE5200ButtonFire1:
controllerStates[player].fire = 0;
break;
case OE5200ButtonFire2:
//controllerStates[player].fire2 = 0;
INPUT_key_shift = 0;
break;
case OE5200ButtonUp:
controllerStates[player].up = 0;
//INPUT_key_code = 0xff;
break;
case OE5200ButtonDown:
controllerStates[player].down = 0;
break;
case OE5200ButtonLeft:
controllerStates[player].left = 0;
break;
case OE5200ButtonRight:
controllerStates[player].right = 0;
break;
case OE5200ButtonStart:
// controllerStates[player].start = 1;
INPUT_key_code = AKEY_NONE;
break;
case OE5200ButtonPause:
INPUT_key_code = AKEY_NONE;
break;
case OE5200ButtonReset:
INPUT_key_code = AKEY_NONE;
break;
case OE5200Button1:
INPUT_key_code = AKEY_NONE;
break;
case OE5200Button2:
INPUT_key_code = AKEY_NONE;
break;
case OE5200Button3:
INPUT_key_code = AKEY_NONE;
break;
case OE5200Button4:
INPUT_key_code = AKEY_NONE;
break;
case OE5200Button5:
INPUT_key_code = AKEY_NONE;
break;
case OE5200Button6:
INPUT_key_code = AKEY_NONE;
break;
case OE5200Button7:
INPUT_key_code = AKEY_NONE;
break;
case OE5200Button8:
INPUT_key_code = AKEY_NONE;
break;
case OE5200Button9:
INPUT_key_code = AKEY_NONE;
break;
case OE5200Button0:
INPUT_key_code = AKEY_NONE;
break;
case OE5200ButtonAsterisk:
INPUT_key_code = AKEY_NONE;
break;
case OE5200ButtonPound:
INPUT_key_code = AKEY_NONE;
break;
default:
break;
}
}
#pragma mark - Misc Helper Methods
- (ATR5200ControllerState)controllerStateForPlayer:(NSUInteger)playerNum
{
ATR5200ControllerState state = {0,0,0,0,0,0,0,0};
if(playerNum < 4) {
state = controllerStates[playerNum];
}
return state;
}
// Atari800 platform calls
int UI_SelectCartType(int k)
{
NSLog(@"Cart size: %d", k);
if([[_currentCore systemIdentifier] isEqualToString:@"openemu.system.atari8bit"])
{
// TODO: improve detection using MD5 lookup
switch (k)
{
case 2: return CARTRIDGE_STD_2;
case 4: return CARTRIDGE_STD_4;
case 8: return CARTRIDGE_STD_8;
case 16: return CARTRIDGE_STD_16;
case 32: return CARTRIDGE_XEGS_32;
case 40: return CARTRIDGE_BBSB_40;
case 64: return CARTRIDGE_XEGS_07_64;
case 128: return CARTRIDGE_XEGS_128;
case 256: return CARTRIDGE_XEGS_256;
case 512: return CARTRIDGE_XEGS_512;
case 1024: return CARTRIDGE_ATMAX_1024;
default:
return CARTRIDGE_NONE;
}
}
if([[_currentCore systemIdentifier] isEqualToString:@"openemu.system.5200"])
{
NSArray *One_Chip_16KB = @[@"a47fcb4eedab9418ea098bb431a407aa", // A.E. (Proto)
@"45f8841269313736489180c8ec3e9588", // Activision Decathlon, The
@"1913310b1e44ad7f3b90aeb16790a850", // Beamrider
@"f8973db8dc272c2e5eb7b8dbb5c0cc3b", // BerZerk
@"e0b47a17fa6cd9d6addc1961fca43414", // Blaster
@"8123393ae9635f6bc15ddc3380b04328", // Blue Print
@"3ff7707e25359c9bcb2326a5d8539852", // Choplifter!
@"7c27d225a13e178610babf331a0759c0", // David Crane's Pitfall II - Lost Caverns
@"2bb63d65efc8682bc4dfac0fd0a823be", // Final Legacy (Proto)
@"f8f0e0a6dc2ffee41b2a2dd736cba4cd", // H.E.R.O.
@"46264c86edf30666e28553bd08369b83", // Last Starfighter, The (Proto)
@"1cd67468d123219201702eadaffd0275", // Meteorites
@"84d88bcdeffee1ab880a5575c6aca45e", // Millipede (Proto)
@"d859bff796625e980db1840f15dec4b5", // Miner 2049er Starring Bounty Bob
@"296e5a3a9efd4f89531e9cf0259c903d", // Moon Patrol
@"099706cedd068aced7313ffa371d7ec3", // Quest for Quintana Roo
@"5dba5b478b7da9fd2c617e41fb5ccd31", // Robotron 2084
@"802a11dfcba6229cc2f93f0f3aaeb3aa", // Space Shuttle - A Journey Into Space
@"7dab86351fe78c2f529010a1ac83a4cf", // Super Pac-Man (Proto)
@"496b6a002bc7d749c02014f7ec6c303c", // Tempest (Proto)
@"33053f432f9c4ad38b5d02d1b485b5bd", // Track and Field (Proto)
@"560b68b7f83077444a57ebe9f932905a", // Wizard of Wor
@"dc45af8b0996cb6a94188b0be3be2e17" // Zone Ranger
];
NSArray *Two_Chip_16KB = @[@"bae7c1e5eb04e19ef8d0d0b5ce134332", // Astro Chase
@"78ccbcbb6b4d17b749ebb012e4878008", // Atari PAM Diagnostics (v2.0)
@"32a6d0de4f1728dee163eb2d4b3f49f1", // Atari PAM Diagnostics (v2.3)
@"8576867c2cfc965cf152be0468f684a7", // Battlezone (Proto)
@"a074a1ff0a16d1e034ee314b85fa41e9", // Buck Rogers - Planet of Zoom
@"261702e8d9acbf45d44bb61fd8fa3e17", // Centipede
@"5720423ebd7575941a1586466ba9beaf", // Congo Bongo
@"1a64edff521608f9f4fa9d7bdb355087", // Countermeasure
@"27d5f32b0d46d3d80773a2b505f95046", // Defender
@"3abd0c057474bad46e45f3d4e96eecee", // Dig Dug
@"14bd9a0423eafc3090333af916cfbce6", // Frisky Tom (Proto)
@"d8636222c993ca71ca0904c8d89c4411", // Frogger II - Threeedeep!
@"dacc0a82e8ee0c086971f9d9bac14127", // Gyruss
@"936db7c08e6b4b902c585a529cb15fc5", // James Bond 007
@"25cfdef5bf9b126166d5394ae74a32e7", // Joust
@"bc748804f35728e98847da6cdaf241a7", // Jr. Pac-Man (Proto)
@"834067fdce5d09b86741e41e7e491d6c", // Jungle Hunt
@"796d2c22f8205fb0ce8f1ee67c8eb2ca", // Kangaroo
@"d0a1654625dbdf3c6b8480c1ed17137f", // Looney Tunes Hotel (Proto)
@"24348dd9287f54574ccc40ee40d24a86", // Microgammon SB (Proto)
@"69d472a79f404e49ad2278df3c8a266e", // Miniature Golf (Proto)
@"694897cc0d98fcf2f59eef788881f67d", // Montezuma's Revenge featuring Panama Joe
@"ef9a920ffdf592546499738ee911fc1e", // Ms. Pac-Man
@"f1a4d62d9ba965335fa13354a6264623", // Pac-Man
@"fd0cbea6ad18194be0538844e3d7fdc9", // Pole Position
@"dd4ae6add63452aafe7d4fa752cd78ca", // Popeye
@"9b7d9d874a93332582f34d1420e0f574", // Qix
@"a71bfb11676a4e4694af66e311721a1b", // RealSports Basketball (82-11-05) (Proto)
@"022c47b525b058796841134bb5c75a18", // RealSports Football
@"3074fad290298d56c67f82e8588c5a8b", // RealSports Soccer
@"7e683e571cbe7c77f76a1648f906b932", // RealSports Tennis
@"ddf7834a420f1eaae20a7a6255f80a99", // Road Runner (Proto)
@"6e24e3519458c5cb95a7fd7711131f8d", // Space Dungeon
@"993e3be7199ece5c3e03092e3b3c0d1d", // Sport Goofy (Proto)
@"e2d3a3e52bb4e3f7e489acd9974d68e2", // Star Raiders
@"c959b65be720a03b5479650a3af5a511", // Star Trek - Strategic Operations Simulator
@"00beaa8405c7fb90d86be5bb1b01ea66", // Star Wars - The Arcade Game
@"595703dc459cd51fed6e2a191c462969", // Stargate (Proto)
@"4f6c58c28c41f31e3a1515fe1e5d15af" // Xari Arena (Proto)
];
// Set 5200 cart type to load based on size
switch (k)
{
case 4: return CARTRIDGE_5200_4;
case 8: return CARTRIDGE_5200_8;
case 16:
// Determine if 16KB cart is one-chip (NS_16) or two-chip (EE_16)
if([One_Chip_16KB containsObject:[[_currentCore ROMMD5] lowercaseString]])
return CARTRIDGE_5200_NS_16;
else
return CARTRIDGE_5200_EE_16;
case 32: return CARTRIDGE_5200_32;
case 40: return CARTRIDGE_5200_40; // Bounty Bob Strikes Back
default:
return CARTRIDGE_NONE;
}
}
return CARTRIDGE_NONE;
}
void UI_Run(void)
{
}
int PLATFORM_Initialise(int *argc, char *argv[])
{
Sound_Initialise(argc, argv);
if (Sound_enabled) {
/* Up to this point the Sound_enabled flag indicated that we _want_ to
enable sound. From now on, the flag will indicate whether audio
output is enabled and working. So, since the sound output was not
yet initiated, we set the flag accordingly. */
Sound_enabled = FALSE;
/* Don't worry, Sound_Setup() will set Sound_enabled back to TRUE if
it opens audio output successfully. But Sound_Setup() relies on the
flag being set if and only if audio output is active. */
if (Sound_Setup())
/* Start sound if opening audio output was successful. */
Sound_Continue();
}
//POKEYSND_stereo_enabled = TRUE;
return TRUE;
}
int PLATFORM_Exit(int run_monitor)
{
Sound_Exit();
return FALSE;
}
int PLATFORM_PORT(int num)
{
if(num < 4 && num >= 0) {
ATR5200ControllerState state = [_currentCore controllerStateForPlayer:num];
if(state.up == 1 && state.left == 1) {
return INPUT_STICK_UL;
}
else if(state.up == 1 && state.right == 1) {
return INPUT_STICK_UR;
}
else if(state.up == 1) {
return INPUT_STICK_FORWARD;
}
else if(state.down == 1 && state.left == 1) {
return INPUT_STICK_LL;
}
else if(state.down == 1 && state.right == 1) {
return INPUT_STICK_LR;
}
else if(state.down == 1) {
return INPUT_STICK_BACK;
}
else if(state.left == 1) {
return INPUT_STICK_LEFT;
}
else if(state.right == 1) {
return INPUT_STICK_RIGHT;
}
return INPUT_STICK_CENTRE;
}
return 0xff;
}
int PLATFORM_TRIG(int num)
{
ATR5200ControllerState state = [_currentCore controllerStateForPlayer:num];
return state.fire == 1 ? 0 : 1;
}
int PLATFORM_Keyboard(void)
{
return 0;
}
void PLATFORM_DisplayScreen(void)
{
}
int PLATFORM_SoundSetup(Sound_setup_t *setup)
{
int buffer_samples;
if (setup->frag_frames == 0) {
/* Set frag_frames automatically. */
unsigned int val = setup->frag_frames = setup->freq / 50;
unsigned int pow_val = 1;
while (val >>= 1)
pow_val <<= 1;
if (pow_val < setup->frag_frames)
pow_val <<= 1;
setup->frag_frames = pow_val;
}
setup->sample_size = 2;
buffer_samples = setup->frag_frames * setup->channels;
setup->frag_frames = buffer_samples / setup->channels;
return TRUE;
}
void PLATFORM_SoundExit(void){}
void PLATFORM_SoundPause(void){}
void PLATFORM_SoundContinue(void){}
void PLATFORM_SoundLock(void){}
void PLATFORM_SoundUnlock(void){}
//int16_t convertSample(uint8_t sample)
//{
// float floatSample = (float)sample / 255;
// return (int16_t)(floatSample * 65535 - 32768);
//}
//
//void ATR800WriteSoundBuffer(uint8_t *buffer, unsigned int len) {
// int samples = len / sizeof(uint8_t);
// NSUInteger newLength = len * sizeof(int16_t);
// int16_t *newBuffer = malloc(len * sizeof(int16_t));
// int16_t *dest = newBuffer;
// uint8_t *source = buffer;
// for(int i = 0; i < samples; i++) {
// *dest = convertSample(*source);
// dest++;
// source++;
// }
// [[_currentCore ringBufferAtIndex:0] write:newBuffer maxLength:newLength];
// free(newBuffer);
//}
@end