Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1b76eae51e | |||
| 4db4639569 | |||
| 1e9dc7ee26 | |||
| e62374c88d | |||
| c4ea492891 | |||
| 4b460d1cb8 | |||
| 14cfd5c93c | |||
| 14a65ab35d | |||
| 46d186d251 | |||
| b1a06da5ba | |||
| 7bd6e5ea8b | |||
| 9d79c1a4a5 | |||
| c1271716eb | |||
| cd166c0561 | |||
| dd9e1c3cee | |||
| 28ae039566 | |||
| 33026a6424 | |||
| 10e4d8fd38 | |||
| 2758d42404 | |||
| 0fa341d5c1 | |||
| 5bfdfc26d4 | |||
| 22d81842fa |
Binary file not shown.
+49
-1079
File diff suppressed because it is too large
Load Diff
+410
-76
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2015, OpenEmu Team
|
||||
Copyright (c) 2018, OpenEmu Team
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
@@ -41,18 +41,37 @@
|
||||
extern uint8 *XBuf;
|
||||
static uint32_t palette[256];
|
||||
|
||||
#define OVERSCAN_VERTICAL 8
|
||||
#define OVERSCAN_HORIZONTAL 8
|
||||
|
||||
#define OptionDefault(_NAME_, _PREFKEY_) @{ OEGameCoreDisplayModeNameKey : _NAME_, OEGameCoreDisplayModePrefKeyNameKey : _PREFKEY_, OEGameCoreDisplayModeStateKey : @YES, }
|
||||
#define Option(_NAME_, _PREFKEY_) @{ OEGameCoreDisplayModeNameKey : _NAME_, OEGameCoreDisplayModePrefKeyNameKey : _PREFKEY_, OEGameCoreDisplayModeStateKey : @NO, }
|
||||
#define OptionIndented(_NAME_, _PREFKEY_) @{ OEGameCoreDisplayModeNameKey : _NAME_, OEGameCoreDisplayModePrefKeyNameKey : _PREFKEY_, OEGameCoreDisplayModeStateKey : @NO, OEGameCoreDisplayModeIndentationLevelKey : @(1), }
|
||||
#define OptionToggleable(_NAME_, _PREFKEY_) @{ OEGameCoreDisplayModeNameKey : _NAME_, OEGameCoreDisplayModePrefKeyNameKey : _PREFKEY_, OEGameCoreDisplayModeStateKey : @NO, OEGameCoreDisplayModeAllowsToggleKey : @YES, }
|
||||
#define OptionToggleableNoSave(_NAME_, _PREFKEY_) @{ OEGameCoreDisplayModeNameKey : _NAME_, OEGameCoreDisplayModePrefKeyNameKey : _PREFKEY_, OEGameCoreDisplayModeStateKey : @NO, OEGameCoreDisplayModeAllowsToggleKey : @YES, OEGameCoreDisplayModeDisallowPrefSaveKey : @YES, }
|
||||
#define Label(_NAME_) @{ OEGameCoreDisplayModeLabelKey : _NAME_, }
|
||||
#define SeparatorItem() @{ OEGameCoreDisplayModeSeparatorItemKey : @"",}
|
||||
|
||||
@interface FCEUGameCore () <OENESSystemResponderClient>
|
||||
{
|
||||
uint32_t *videoBuffer;
|
||||
uint8_t *pXBuf;
|
||||
int32_t *soundBuffer;
|
||||
int32_t soundSize;
|
||||
uint32_t pad;
|
||||
uint32_t arkanoid[3];
|
||||
uint32_t zapper[3];
|
||||
uint32_t hypershot[4];
|
||||
uint32_t *_videoBuffer;
|
||||
int32_t *_soundBuffer;
|
||||
int32_t _soundSize;
|
||||
uint32_t _pad;
|
||||
uint32_t _arkanoid[3];
|
||||
uint32_t _zapper[3];
|
||||
uint32_t _hypershot[4];
|
||||
int _videoWidth, _videoHeight;
|
||||
int _videoOffsetX, _videoOffsetY;
|
||||
int _aspectWidth, _aspectHeight;
|
||||
BOOL _isHorzOverscanCropped;
|
||||
BOOL _isVertOverscanCropped;
|
||||
NSMutableDictionary<NSString *, NSNumber *> *_cheatList;
|
||||
NSMutableArray <NSMutableDictionary <NSString *, id> *> *_availableDisplayModes;
|
||||
}
|
||||
|
||||
- (void)loadDisplayModeOptions;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FCEUGameCore
|
||||
@@ -63,7 +82,7 @@ static __weak FCEUGameCore *_current;
|
||||
{
|
||||
if((self = [super init]))
|
||||
{
|
||||
videoBuffer = (uint32_t *)malloc(256 * 240 * 4);
|
||||
_cheatList = [NSMutableDictionary dictionary];
|
||||
}
|
||||
|
||||
_current = self;
|
||||
@@ -73,51 +92,51 @@ static __weak FCEUGameCore *_current;
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
free(videoBuffer);
|
||||
free(_videoBuffer);
|
||||
}
|
||||
|
||||
# pragma mark - Execution
|
||||
|
||||
- (BOOL)loadFileAtPath:(NSString *)path error:(NSError **)error
|
||||
{
|
||||
pad = 0;
|
||||
memset(arkanoid, 0, sizeof(arkanoid));
|
||||
memset(zapper, 0, sizeof(zapper));
|
||||
memset(hypershot, 0, sizeof(hypershot));
|
||||
_pad = 0;
|
||||
memset(_arkanoid, 0, sizeof(_arkanoid));
|
||||
memset(_zapper, 0, sizeof(_zapper));
|
||||
memset(_hypershot, 0, sizeof(_hypershot));
|
||||
|
||||
//newppu = 0 default off, set 1 to enable
|
||||
|
||||
FCEUI_Initialize();
|
||||
|
||||
NSURL *batterySavesDirectory = [NSURL fileURLWithPath:[self batterySavesDirectoryPath]];
|
||||
[[NSFileManager defaultManager] createDirectoryAtURL:batterySavesDirectory withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
//FCEUI_SetBaseDirectory([[self biosDirectoryPath] UTF8String]); unused for now
|
||||
FCEUI_SetDirOverride(FCEUIOD_NV, strdup([[batterySavesDirectory path] UTF8String]));
|
||||
NSURL *batterySavesDirectory = [NSURL fileURLWithPath:self.batterySavesDirectoryPath];
|
||||
[NSFileManager.defaultManager createDirectoryAtURL:batterySavesDirectory withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
//FCEUI_SetBaseDirectory([[self biosDirectoryPath] fileSystemRepresentation]); unused for now
|
||||
FCEUI_SetDirOverride(FCEUIOD_NV, strdup(batterySavesDirectory.fileSystemRepresentation));
|
||||
|
||||
FCEUI_SetSoundVolume(256);
|
||||
FCEUI_Sound(48000);
|
||||
|
||||
FCEUGI *FCEUGameInfo;
|
||||
FCEUGameInfo = FCEUI_LoadGame([path UTF8String], 1, false);
|
||||
FCEUGameInfo = FCEUI_LoadGame(path.fileSystemRepresentation, 1, false);
|
||||
|
||||
if(!FCEUGameInfo)
|
||||
return NO;
|
||||
|
||||
//NSLog(@"FPS: %d", FCEUI_GetDesiredFPS() >> 24); // Hz
|
||||
|
||||
FCEUI_SetInput(0, SI_GAMEPAD, &pad, 0); // Controllers 1 and 3
|
||||
FCEUI_SetInput(0, SI_GAMEPAD, &_pad, 0); // Controllers 1 and 3
|
||||
|
||||
if(FCEUGameInfo->input[1] == SI_ZAPPER)
|
||||
FCEUI_SetInput(1, SI_ZAPPER, &zapper, 0);
|
||||
FCEUI_SetInput(1, SI_ZAPPER, &_zapper, 0);
|
||||
else if(FCEUGameInfo->input[1] == SI_ARKANOID)
|
||||
FCEUI_SetInput(1, SI_ARKANOID, &arkanoid, 0);
|
||||
FCEUI_SetInput(1, SI_ARKANOID, &_arkanoid, 0);
|
||||
else
|
||||
FCEUI_SetInput(1, SI_GAMEPAD, &pad, 0); // Controllers 2 and 4
|
||||
FCEUI_SetInput(1, SI_GAMEPAD, &_pad, 0); // Controllers 2 and 4
|
||||
|
||||
if(FCEUGameInfo->inputfc == SIFC_SHADOW)
|
||||
FCEUI_SetInputFC(SIFC_SHADOW, &hypershot, 0);
|
||||
FCEUI_SetInputFC(SIFC_SHADOW, &_hypershot, 0);
|
||||
else if(FCEUGameInfo->inputfc == SIFC_ARKANOID)
|
||||
FCEUI_SetInputFC(SIFC_ARKANOID, &arkanoid, 0);
|
||||
FCEUI_SetInputFC(SIFC_ARKANOID, &_arkanoid, 0);
|
||||
|
||||
extern uint32_t iNESGameCRC32;
|
||||
NSString *cartCRC32 = [NSString stringWithFormat:@"%08x", iNESGameCRC32];
|
||||
@@ -192,29 +211,29 @@ static __weak FCEUGameCore *_current;
|
||||
FCEUI_SetInputFourscore(true);
|
||||
|
||||
if([famicom4Player containsObject:cartCRC32])
|
||||
FCEUI_SetInputFC(SIFC_4PLAYER, &pad, 0);
|
||||
FCEUI_SetInputFC(SIFC_4PLAYER, &_pad, 0);
|
||||
|
||||
FCEU_ResetPalette();
|
||||
|
||||
// Only temporary, so core doesn't crash on an older OpenEmu version
|
||||
if ([self respondsToSelector:@selector(displayModeInfo)]) {
|
||||
[self loadDisplayModeOptions];
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)executeFrame
|
||||
{
|
||||
pXBuf = 0;
|
||||
soundSize = 0;
|
||||
uint8_t *pXBuf;
|
||||
_soundSize = 0;
|
||||
|
||||
FCEUI_Emulate(&pXBuf, &soundBuffer, &soundSize, 0);
|
||||
FCEUI_Emulate(&pXBuf, &_soundBuffer, &_soundSize, 0);
|
||||
|
||||
pXBuf = XBuf;
|
||||
for (unsigned y = 0; y < 240; y++)
|
||||
for (unsigned x = 0; x < 256; x++, pXBuf++)
|
||||
videoBuffer[y * 256 + x] = palette[*pXBuf];
|
||||
for (int i = 0; i < _soundSize; i++)
|
||||
_soundBuffer[i] = (_soundBuffer[i] << 16) | (_soundBuffer[i] & 0xffff);
|
||||
|
||||
for (int i = 0; i < soundSize; i++)
|
||||
soundBuffer[i] = (soundBuffer[i] << 16) | (soundBuffer[i] & 0xffff);
|
||||
|
||||
[[self ringBufferAtIndex:0] write:soundBuffer maxLength:soundSize << 2];
|
||||
[[self ringBufferAtIndex:0] write:_soundBuffer maxLength:_soundSize << 2];
|
||||
}
|
||||
|
||||
- (void)resetEmulation
|
||||
@@ -237,19 +256,39 @@ static __weak FCEUGameCore *_current;
|
||||
|
||||
# pragma mark - Video
|
||||
|
||||
- (const void *)videoBuffer
|
||||
- (const void *)getVideoBufferWithHint:(void *)hint
|
||||
{
|
||||
return videoBuffer;
|
||||
if (!hint) {
|
||||
if (!_videoBuffer) _videoBuffer = (uint32_t *)malloc(256 * 240 * sizeof(uint32_t));
|
||||
hint = _videoBuffer;
|
||||
}
|
||||
|
||||
// TODO: support paletted video in OE
|
||||
uint8_t *pXBuf = XBuf;
|
||||
uint32_t *pOBuf = (uint32_t *)hint;
|
||||
for (unsigned y = 0; y < 240; y++)
|
||||
for (unsigned x = 0; x < 256; x++, pXBuf++)
|
||||
pOBuf[y * 256 + x] = palette[*pXBuf];
|
||||
|
||||
return hint;
|
||||
}
|
||||
|
||||
- (OEIntRect)screenRect
|
||||
{
|
||||
return OEIntRectMake(0, 0, 256, 240);
|
||||
_videoOffsetX = _isHorzOverscanCropped ? OVERSCAN_HORIZONTAL : 0;
|
||||
_videoOffsetY = _isVertOverscanCropped ? OVERSCAN_VERTICAL : 0;
|
||||
_videoWidth = _isHorzOverscanCropped ? 256 - (OVERSCAN_HORIZONTAL * 2) : 256;
|
||||
_videoHeight = _isVertOverscanCropped ? 240 - (OVERSCAN_VERTICAL * 2) : 240;
|
||||
|
||||
return OEIntRectMake(_videoOffsetX, _videoOffsetY, _videoWidth, _videoHeight);
|
||||
}
|
||||
|
||||
- (OEIntSize)aspectSize
|
||||
{
|
||||
return OEIntSizeMake(256 * (8.0/7.0), 240);
|
||||
_aspectWidth = _isHorzOverscanCropped ? (256 - (OVERSCAN_HORIZONTAL * 2)) * (8.0/7.0) : 256 * (8.0/7.0);
|
||||
_aspectHeight = _isVertOverscanCropped ? 240 - (OVERSCAN_VERTICAL * 2) : 240;
|
||||
|
||||
return OEIntSizeMake(_aspectWidth, _aspectHeight);
|
||||
}
|
||||
|
||||
- (OEIntSize)bufferSize
|
||||
@@ -267,11 +306,6 @@ static __weak FCEUGameCore *_current;
|
||||
return GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
|
||||
- (GLenum)internalPixelFormat
|
||||
{
|
||||
return GL_RGB8;
|
||||
}
|
||||
|
||||
# pragma mark - Audio
|
||||
|
||||
- (double)audioSampleRate
|
||||
@@ -316,8 +350,8 @@ static __weak FCEUGameCore *_current;
|
||||
|
||||
- (BOOL)deserializeState:(NSData *)state withError:(NSError **)outError
|
||||
{
|
||||
u8 *bytes = (u8 *)[state bytes];
|
||||
size_t length = [state length];
|
||||
u8 *bytes = (u8 *)state.bytes;
|
||||
size_t length = state.length;
|
||||
std::vector<u8> byteVector(bytes, bytes + length);
|
||||
EMUFILE *emuFile = new EMUFILE_MEMORY(&byteVector);
|
||||
|
||||
@@ -349,7 +383,7 @@ const int NESMap[] = {JOY_UP, JOY_DOWN, JOY_LEFT, JOY_RIGHT, JOY_A, JOY_B, JOY_S
|
||||
break;
|
||||
}
|
||||
|
||||
pad |= NESMap[button] << playerShift;
|
||||
_pad |= NESMap[button] << playerShift;
|
||||
}
|
||||
|
||||
- (oneway void)didReleaseNESButton:(OENESButton)button forPlayer:(NSUInteger)player;
|
||||
@@ -370,87 +404,384 @@ const int NESMap[] = {JOY_UP, JOY_DOWN, JOY_LEFT, JOY_RIGHT, JOY_A, JOY_B, JOY_S
|
||||
break;
|
||||
}
|
||||
|
||||
pad &= ~(NESMap[button] << playerShift);
|
||||
_pad &= ~(NESMap[button] << playerShift);
|
||||
}
|
||||
|
||||
- (oneway void)didTriggerGunAtPoint:(OEIntPoint)aPoint
|
||||
{
|
||||
[self mouseMovedAtPoint:aPoint];
|
||||
|
||||
arkanoid[2] = 1;
|
||||
int xcoord = _isHorzOverscanCropped ? (aPoint.x + OVERSCAN_HORIZONTAL) * 0.876712 : aPoint.x * 0.876712;
|
||||
int ycoord = _isVertOverscanCropped ? aPoint.y + OVERSCAN_VERTICAL : aPoint.y;
|
||||
|
||||
zapper[0] = aPoint.x * 0.876712;
|
||||
zapper[1] = aPoint.y;
|
||||
zapper[2] = 1;
|
||||
_arkanoid[2] = 1;
|
||||
|
||||
hypershot[0] = aPoint.x * 0.876712;
|
||||
hypershot[1] = aPoint.y;
|
||||
hypershot[2] = 1;
|
||||
_zapper[0] = xcoord;
|
||||
_zapper[1] = ycoord;
|
||||
_zapper[2] = 1;
|
||||
|
||||
_hypershot[0] = xcoord;
|
||||
_hypershot[1] = ycoord;
|
||||
_hypershot[2] = 1;
|
||||
}
|
||||
|
||||
- (oneway void)didReleaseTrigger
|
||||
{
|
||||
arkanoid[2] = 0;
|
||||
zapper[2] = 0;
|
||||
hypershot[2] = 0;
|
||||
_arkanoid[2] = 0;
|
||||
_zapper[2] = 0;
|
||||
_hypershot[2] = 0;
|
||||
}
|
||||
|
||||
- (oneway void)mouseMovedAtPoint:(OEIntPoint)aPoint
|
||||
{
|
||||
arkanoid[0] = aPoint.x * 0.876712;
|
||||
_arkanoid[0] = _isHorzOverscanCropped ? (aPoint.x + OVERSCAN_HORIZONTAL) * 0.876712 : aPoint.x * 0.876712;
|
||||
}
|
||||
|
||||
- (oneway void)rightMouseDownAtPoint:(OEIntPoint)point
|
||||
{
|
||||
hypershot[3] = 1; // "move" button
|
||||
_hypershot[3] = 1; // "move" button
|
||||
}
|
||||
|
||||
- (oneway void)rightMouseUp;
|
||||
{
|
||||
hypershot[3] = 0;
|
||||
_hypershot[3] = 0;
|
||||
}
|
||||
|
||||
#pragma mark - Cheats
|
||||
|
||||
NSMutableDictionary *cheatList = [[NSMutableDictionary alloc] init];
|
||||
|
||||
- (void)setCheat:(NSString *)code setType:(NSString *)type setEnabled:(BOOL)enabled
|
||||
{
|
||||
// Sanitize
|
||||
code = [code stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
code = [code stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet];
|
||||
|
||||
// Remove any spaces
|
||||
code = [code stringByReplacingOccurrencesOfString:@" " withString:@""];
|
||||
|
||||
if (enabled)
|
||||
[cheatList setValue:@YES forKey:code];
|
||||
_cheatList[code] = @YES;
|
||||
else
|
||||
[cheatList removeObjectForKey:code];
|
||||
[_cheatList removeObjectForKey:code];
|
||||
|
||||
FCEU_FlushGameCheats(0, 1);
|
||||
|
||||
NSArray *multipleCodes = [[NSArray alloc] init];
|
||||
NSArray<NSString *> *multipleCodes = [NSArray array];
|
||||
|
||||
// Apply enabled cheats found in dictionary
|
||||
for (id key in cheatList)
|
||||
for (NSString *key in _cheatList)
|
||||
{
|
||||
if ([[cheatList valueForKey:key] isEqual:@YES])
|
||||
if ([_cheatList[key] boolValue])
|
||||
{
|
||||
// Handle multi-line cheats
|
||||
multipleCodes = [key componentsSeparatedByString:@"+"];
|
||||
for (NSString *singleCode in multipleCodes) {
|
||||
const char *cCode = [singleCode UTF8String];
|
||||
const char *cCode = singleCode.UTF8String;
|
||||
|
||||
int address, value, compare;
|
||||
int type = 1;
|
||||
|
||||
if (FCEUI_DecodeGG(cCode, &address, &value, &compare))
|
||||
if (singleCode.length == 7 && [singleCode characterAtIndex:4] == ':')
|
||||
{
|
||||
address = (int)strtoul([singleCode substringToIndex:4].UTF8String, NULL, 16);
|
||||
value = (int)strtoul([singleCode substringFromIndex:5].UTF8String, NULL, 16);
|
||||
compare = -1;
|
||||
FCEUI_AddCheat(cCode, address, value, compare, type);
|
||||
}
|
||||
else if (singleCode.length == 10 && [singleCode characterAtIndex:4] == '?' && [singleCode characterAtIndex:7] == ':')
|
||||
{
|
||||
address = (int)strtoul([singleCode substringToIndex:4].UTF8String, NULL, 16);
|
||||
compare = (int)strtoul([singleCode substringWithRange:NSMakeRange(5, 2)].UTF8String, NULL, 16);
|
||||
value = (int)strtoul([singleCode substringFromIndex:8].UTF8String, NULL, 16);
|
||||
FCEUI_AddCheat(cCode, address, value, compare, type);
|
||||
}
|
||||
else if (FCEUI_DecodeGG(cCode, &address, &value, &compare))
|
||||
FCEUI_AddCheat(cCode, address, value, compare, type);
|
||||
// Does not work
|
||||
// else if (FCEUI_DecodePAR(cCode, &address, &value, &compare, &type))
|
||||
// FCEUI_AddCheat(cCode, address, value, compare, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# pragma mark - Display Mode
|
||||
|
||||
- (NSArray <NSDictionary <NSString *, id> *> *)displayModes
|
||||
{
|
||||
if (_availableDisplayModes.count == 0)
|
||||
{
|
||||
_availableDisplayModes = [NSMutableArray array];
|
||||
|
||||
NSArray <NSDictionary <NSString *, id> *> *availableModesWithDefault =
|
||||
@[
|
||||
OptionToggleableNoSave(@"No Sprite Limit", @"noSpriteLimit"),
|
||||
SeparatorItem(),
|
||||
Label(@"Overscan"),
|
||||
OptionToggleable(@"Crop Horizontal", @"cropHorizontalOverscan"),
|
||||
OptionToggleable(@"Crop Vertical", @"cropVerticalOverscan"),
|
||||
SeparatorItem(),
|
||||
Label(@"Palette"),
|
||||
OptionDefault(@"Default — FCEUX", @"palette"),
|
||||
Option(@"RGB (PlayChoice-10)", @"palette"),
|
||||
Option(@"NESCAP", @"palette"),
|
||||
Option(@"Sony CXA2025AS", @"palette"),
|
||||
Option(@"Smooth (FBX)", @"palette"),
|
||||
Option(@"Wavebeam", @"palette"),
|
||||
];
|
||||
|
||||
// Deep mutable copy
|
||||
_availableDisplayModes = (NSMutableArray *)CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFArrayRef)availableModesWithDefault, kCFPropertyListMutableContainers));
|
||||
}
|
||||
|
||||
return [_availableDisplayModes copy];
|
||||
}
|
||||
|
||||
- (void)changeDisplayWithMode:(NSString *)displayMode
|
||||
{
|
||||
if (_availableDisplayModes.count == 0)
|
||||
[self displayModes];
|
||||
|
||||
// First check if 'displayMode' is valid
|
||||
BOOL isDisplayModeToggleable = NO;
|
||||
BOOL isValidDisplayMode = NO;
|
||||
BOOL displayModeState = NO;
|
||||
NSString *displayModePrefKey;
|
||||
|
||||
for (NSDictionary *modeDict in _availableDisplayModes) {
|
||||
if ([modeDict[OEGameCoreDisplayModeNameKey] isEqualToString:displayMode]) {
|
||||
displayModeState = [modeDict[OEGameCoreDisplayModeStateKey] boolValue];
|
||||
displayModePrefKey = modeDict[OEGameCoreDisplayModePrefKeyNameKey];
|
||||
isDisplayModeToggleable = [modeDict[OEGameCoreDisplayModeAllowsToggleKey] boolValue];
|
||||
isValidDisplayMode = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Disallow a 'displayMode' not found in _availableDisplayModes
|
||||
if (!isValidDisplayMode)
|
||||
return;
|
||||
|
||||
// Handle option state changes
|
||||
for (NSMutableDictionary *optionDict in _availableDisplayModes) {
|
||||
NSString *modeName = optionDict[OEGameCoreDisplayModeNameKey];
|
||||
NSString *prefKey = optionDict[OEGameCoreDisplayModePrefKeyNameKey];
|
||||
|
||||
if (!modeName)
|
||||
continue;
|
||||
// Mutually exclusive option state change
|
||||
else if ([modeName isEqualToString:displayMode] && !isDisplayModeToggleable)
|
||||
optionDict[OEGameCoreDisplayModeStateKey] = @YES;
|
||||
// Reset mutually exclusive options that are the same prefs group as 'displayMode'
|
||||
else if (!isDisplayModeToggleable && [prefKey isEqualToString:displayModePrefKey])
|
||||
optionDict[OEGameCoreDisplayModeStateKey] = @NO;
|
||||
// Toggleable option state change
|
||||
else if ([modeName isEqualToString:displayMode] && isDisplayModeToggleable)
|
||||
optionDict[OEGameCoreDisplayModeStateKey] = @(!displayModeState);
|
||||
}
|
||||
|
||||
if ([displayMode isEqualToString:@"Crop Horizontal"])
|
||||
{
|
||||
_isHorzOverscanCropped = !_isHorzOverscanCropped;
|
||||
}
|
||||
else if ([displayMode isEqualToString:@"Crop Vertical"])
|
||||
{
|
||||
_isVertOverscanCropped = !_isVertOverscanCropped;
|
||||
}
|
||||
else if ([displayMode isEqualToString:@"No Sprite Limit"])
|
||||
{
|
||||
FCEUI_DisableSpriteLimitation(!displayModeState);
|
||||
}
|
||||
else if ([displayMode isEqualToString:@"Default — FCEUX"])
|
||||
{
|
||||
FCEU_ResetPalette();
|
||||
}
|
||||
else if ([displayMode isEqualToString:@"RGB (PlayChoice-10)"])
|
||||
{
|
||||
unsigned int pc10_palette[64] =
|
||||
{
|
||||
0x6D6D6D, 0x002492, 0x0000DB, 0x6D49DB,
|
||||
0x92006D, 0xB6006D, 0xB62400, 0x924900,
|
||||
0x6D4900, 0x244900, 0x006D24, 0x009200,
|
||||
0x004949, 0x000000, 0x000000, 0x000000,
|
||||
0xB6B6B6, 0x006DDB, 0x0049FF, 0x9200FF,
|
||||
0xB600FF, 0xFF0092, 0xFF0000, 0xDB6D00,
|
||||
0x926D00, 0x249200, 0x009200, 0x00B66D,
|
||||
0x009292, 0x242424, 0x000000, 0x000000,
|
||||
0xFFFFFF, 0x6DB6FF, 0x9292FF, 0xDB6DFF,
|
||||
0xFF00FF, 0xFF6DFF, 0xFF9200, 0xFFB600,
|
||||
0xDBDB00, 0x6DDB00, 0x00FF00, 0x49FFDB,
|
||||
0x00FFFF, 0x494949, 0x000000, 0x000000,
|
||||
0xFFFFFF, 0xB6DBFF, 0xDBB6FF, 0xFFB6FF,
|
||||
0xFF92FF, 0xFFB6B6, 0xFFDB92, 0xFFFF49,
|
||||
0xFFFF6D, 0xB6FF49, 0x92FF6D, 0x49FFDB,
|
||||
0x92DBFF, 0x929292, 0x000000, 0x000000
|
||||
};
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
int r = pc10_palette[i] >> 16;
|
||||
int g = (pc10_palette[i] & 0xff00) >> 8;
|
||||
int b = pc10_palette[i] & 0xff;
|
||||
FCEUD_SetPalette(i, r, g, b);
|
||||
FCEUD_SetPalette(i + 64, r, g, b);
|
||||
FCEUD_SetPalette(i + 128, r, g, b);
|
||||
FCEUD_SetPalette(i + 192, r, g, b);
|
||||
}
|
||||
}
|
||||
else if ([displayMode isEqualToString:@"NESCAP"])
|
||||
{
|
||||
unsigned int nescap_palette[64] =
|
||||
{
|
||||
0x646365, 0x001580, 0x1D0090, 0x380082,
|
||||
0x56005D, 0x5A001A, 0x4F0900, 0x381B00,
|
||||
0x1E3100, 0x003D00, 0x004100, 0x003A1B,
|
||||
0x002F55, 0x000000, 0x000000, 0x000000,
|
||||
0xAFADAF, 0x164BCA, 0x472AE7, 0x6B1BDB,
|
||||
0x9617B0, 0x9F185B, 0x963001, 0x7B4800,
|
||||
0x5A6600, 0x237800, 0x017F00, 0x00783D,
|
||||
0x006C8C, 0x000000, 0x000000, 0x000000,
|
||||
0xFFFFFF, 0x60A6FF, 0x8F84FF, 0xB473FF,
|
||||
0xE26CFF, 0xF268C3, 0xEF7E61, 0xD89527,
|
||||
0xBAB307, 0x81C807, 0x57D43D, 0x47CF7E,
|
||||
0x4BC5CD, 0x4C4B4D, 0x000000, 0x000000,
|
||||
0xFFFFFF, 0xC2E0FF, 0xD5D2FF, 0xE3CBFF,
|
||||
0xF7C8FF, 0xFEC6EE, 0xFECEC6, 0xF6D7AE,
|
||||
0xE9E49F, 0xD3ED9D, 0xC0F2B2, 0xB9F1CC,
|
||||
0xBAEDED, 0xBAB9BB, 0x000000, 0x000000
|
||||
};
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
int r = nescap_palette[i] >> 16;
|
||||
int g = (nescap_palette[i] & 0xff00) >> 8;
|
||||
int b = nescap_palette[i] & 0xff;
|
||||
FCEUD_SetPalette(i, r, g, b);
|
||||
FCEUD_SetPalette(i + 64, r, g, b);
|
||||
FCEUD_SetPalette(i + 128, r, g, b);
|
||||
FCEUD_SetPalette(i + 192, r, g, b);
|
||||
}
|
||||
}
|
||||
else if ([displayMode isEqualToString:@"Sony CXA2025AS"])
|
||||
{
|
||||
unsigned int cxa2025as_palette[64] =
|
||||
{
|
||||
0x585858, 0x00238C, 0x00139B, 0x2D0585,
|
||||
0x5D0052, 0x7A0017, 0x7A0800, 0x5F1800,
|
||||
0x352A00, 0x093900, 0x003F00, 0x003C22,
|
||||
0x00325D, 0x000000, 0x000000, 0x000000,
|
||||
0xA1A1A1, 0x0053EE, 0x153CFE, 0x6028E4,
|
||||
0xA91D98, 0xD41E41, 0xD22C00, 0xAA4400,
|
||||
0x6C5E00, 0x2D7300, 0x007D06, 0x007852,
|
||||
0x0069A9, 0x000000, 0x000000, 0x000000,
|
||||
0xFFFFFF, 0x1FA5FE, 0x5E89FE, 0xB572FE,
|
||||
0xFE65F6, 0xFE6790, 0xFE773C, 0xFE9308,
|
||||
0xC4B200, 0x79CA10, 0x3AD54A, 0x11D1A4,
|
||||
0x06BFFE, 0x424242, 0x000000, 0x000000,
|
||||
0xFFFFFF, 0xA0D9FE, 0xBDCCFE, 0xE1C2FE,
|
||||
0xFEBCFB, 0xFEBDD0, 0xFEC5A9, 0xFED18E,
|
||||
0xE9DE86, 0xC7E992, 0xA8EEB0, 0x95ECD9,
|
||||
0x91E4FE, 0xACACAC, 0x000000, 0x000000
|
||||
};
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
int r = cxa2025as_palette[i] >> 16;
|
||||
int g = (cxa2025as_palette[i] & 0xff00) >> 8;
|
||||
int b = cxa2025as_palette[i] & 0xff;
|
||||
FCEUD_SetPalette(i, r, g, b);
|
||||
FCEUD_SetPalette(i + 64, r, g, b);
|
||||
FCEUD_SetPalette(i + 128, r, g, b);
|
||||
FCEUD_SetPalette(i + 192, r, g, b);
|
||||
}
|
||||
}
|
||||
else if ([displayMode isEqualToString:@"Smooth (FBX)"])
|
||||
{
|
||||
unsigned int smoothfbx_palette[64] =
|
||||
{
|
||||
0x6A6D6A, 0x001380, 0x1E008A, 0x39007A,
|
||||
0x550056, 0x5A0018, 0x4F1000, 0x3D1C00,
|
||||
0x253200, 0x003D00, 0x004000, 0x003924,
|
||||
0x002E55, 0x000000, 0x000000, 0x000000,
|
||||
0xB9BCB9, 0x1850C7, 0x4B30E3, 0x7322D6,
|
||||
0x951FA9, 0x9D285C, 0x983700, 0x7F4C00,
|
||||
0x5E6400, 0x227700, 0x027E02, 0x007645,
|
||||
0x006E8A, 0x000000, 0x000000, 0x000000,
|
||||
0xFFFFFF, 0x68A6FF, 0x8C9CFF, 0xB586FF,
|
||||
0xD975FD, 0xE377B9, 0xE58D68, 0xD49D29,
|
||||
0xB3AF0C, 0x7BC211, 0x55CA47, 0x46CB81,
|
||||
0x47C1C5, 0x4A4D4A, 0x000000, 0x000000,
|
||||
0xFFFFFF, 0xCCEAFF, 0xDDDEFF, 0xECDAFF,
|
||||
0xF8D7FE, 0xFCD6F5, 0xFDDBCF, 0xF9E7B5,
|
||||
0xF1F0AA, 0xDAFAA9, 0xC9FFBC, 0xC3FBD7,
|
||||
0xC4F6F6, 0xBEC1BE, 0x000000, 0x000000
|
||||
};
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
int r = smoothfbx_palette[i] >> 16;
|
||||
int g = (smoothfbx_palette[i] & 0xff00) >> 8;
|
||||
int b = smoothfbx_palette[i] & 0xff;
|
||||
FCEUD_SetPalette(i, r, g, b);
|
||||
FCEUD_SetPalette(i + 64, r, g, b);
|
||||
FCEUD_SetPalette(i + 128, r, g, b);
|
||||
FCEUD_SetPalette(i + 192, r, g, b);
|
||||
}
|
||||
}
|
||||
else if ([displayMode isEqualToString:@"Wavebeam"])
|
||||
{
|
||||
unsigned int wavebeam_palette[64] =
|
||||
{
|
||||
0x6B6B6B, 0x001B88, 0x21009A, 0x40008C,
|
||||
0x600067, 0x64001E, 0x590800, 0x481600,
|
||||
0x283600, 0x004500, 0x004908, 0x00421D,
|
||||
0x003659, 0x000000, 0x000000, 0x000000,
|
||||
0xB4B4B4, 0x1555D3, 0x4337EF, 0x7425DF,
|
||||
0x9C19B9, 0xAC0F64, 0xAA2C00, 0x8A4B00,
|
||||
0x666B00, 0x218300, 0x008A00, 0x008144,
|
||||
0x007691, 0x000000, 0x000000, 0x000000,
|
||||
0xFFFFFF, 0x63B2FF, 0x7C9CFF, 0xC07DFE,
|
||||
0xE977FF, 0xF572CD, 0xF4886B, 0xDDA029,
|
||||
0xBDBD0A, 0x89D20E, 0x5CDE3E, 0x4BD886,
|
||||
0x4DCFD2, 0x525252, 0x000000, 0x000000,
|
||||
0xFFFFFF, 0xBCDFFF, 0xD2D2FF, 0xE1C8FF,
|
||||
0xEFC7FF, 0xFFC3E1, 0xFFCAC6, 0xF2DAAD,
|
||||
0xEBE3A0, 0xD2EDA2, 0xBCF4B4, 0xB5F1CE,
|
||||
0xB6ECF1, 0xBFBFBF, 0x000000, 0x000000
|
||||
};
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
int r = wavebeam_palette[i] >> 16;
|
||||
int g = (wavebeam_palette[i] & 0xff00) >> 8;
|
||||
int b = wavebeam_palette[i] & 0xff;
|
||||
FCEUD_SetPalette(i, r, g, b);
|
||||
FCEUD_SetPalette(i + 64, r, g, b);
|
||||
FCEUD_SetPalette(i + 128, r, g, b);
|
||||
FCEUD_SetPalette(i + 192, r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)loadDisplayModeOptions
|
||||
{
|
||||
// Restore palette
|
||||
NSString *lastPalette = self.displayModeInfo[@"palette"];
|
||||
if (lastPalette && ![lastPalette isEqualToString:@"Default — FCEUX"]) {
|
||||
[self changeDisplayWithMode:lastPalette];
|
||||
}
|
||||
|
||||
// Crop horizontal overscan
|
||||
BOOL isHorizontalOverscanCropped = [self.displayModeInfo[@"cropHorizontalOverscan"] boolValue];
|
||||
if (isHorizontalOverscanCropped) {
|
||||
[self changeDisplayWithMode:@"Crop Horizontal"];
|
||||
}
|
||||
|
||||
// Crop vertical overscan
|
||||
BOOL isVerticalOverscanCropped = [self.displayModeInfo[@"cropVerticalOverscan"] boolValue];
|
||||
if (isVerticalOverscanCropped) {
|
||||
[self changeDisplayWithMode:@"Crop Vertical"];
|
||||
}
|
||||
}
|
||||
|
||||
// FCEUX internal functions and stubs
|
||||
void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b)
|
||||
{
|
||||
@@ -465,6 +796,7 @@ bool turbo = false;
|
||||
bool swapDuty = 0; // some Famicom and NES clones had duty cycle bits swapped
|
||||
int dendy = 0;
|
||||
int closeFinishedMovie = 0;
|
||||
int KillFCEUXonFrame = 0;
|
||||
int FCEUD_ShowStatusIcon(void) {return 0;}
|
||||
int FCEUD_SendData(void *data, uint32 len) {return 1;}
|
||||
int FCEUD_RecvData(void *data, uint32 len) {return 1;}
|
||||
@@ -501,15 +833,17 @@ bool FCEUI_AviIsRecording(void) {return false;}
|
||||
bool FCEUI_AviDisableMovieMessages() {return true;}
|
||||
FCEUFILE *FCEUD_OpenArchiveIndex(ArchiveScanRecord &asr, std::string &fname, int innerIndex) {return 0;}
|
||||
FCEUFILE *FCEUD_OpenArchive(ArchiveScanRecord &asr, std::string &fname, std::string *innerFilename) {return 0;}
|
||||
FCEUFILE *FCEUD_OpenArchiveIndex(ArchiveScanRecord &asr, std::string &fname, int innerIndex, int *userCancel) {return 0;}
|
||||
FCEUFILE *FCEUD_OpenArchive(ArchiveScanRecord &asr, std::string &fname, std::string *innerFilename, int *userCancel) {return 0;}
|
||||
ArchiveScanRecord FCEUD_ScanArchive(std::string fname) { return ArchiveScanRecord(); }
|
||||
void GetMouseData(uint32 (&md)[3]) {}
|
||||
void FCEUD_PrintError(const char *s)
|
||||
{
|
||||
NSLog(@"FCEUX error: %s", s);
|
||||
NSLog(@"[FCEUX] error: %s", s);
|
||||
}
|
||||
void FCEUD_Message(const char *s)
|
||||
{
|
||||
NSLog(@"FCEUX message: %s", s);
|
||||
NSLog(@"[FCEUX] message: %s", s);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
+5
-3
@@ -3,7 +3,7 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.2.3</string>
|
||||
<string>2.6.3</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>OEGameCoreController</string>
|
||||
<key>OEGameCoreClass</key>
|
||||
@@ -32,6 +32,8 @@
|
||||
<integer>0</integer>
|
||||
<key>OEGameCoreSupportsCheatCode</key>
|
||||
<true/>
|
||||
<key>OEGameCoreSupportsDisplayModeChange</key>
|
||||
<true/>
|
||||
<key>OEGameCoreSupportsRewinding</key>
|
||||
<true/>
|
||||
</dict>
|
||||
@@ -39,7 +41,7 @@
|
||||
<key>OEGameCorePlayerCount</key>
|
||||
<string>4</string>
|
||||
<key>OEProjectURL</key>
|
||||
<string>http://sourceforge.net/projects/fceultra/</string>
|
||||
<string>https://github.com/TASEmulators/fceux</string>
|
||||
<key>OESystemIdentifiers</key>
|
||||
<array>
|
||||
<string>openemu.system.nes</string>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
@@ -0,0 +1,681 @@
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set( APP_NAME fceux)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
if ( ${QT6} )
|
||||
message( STATUS "GUI Frontend: Qt6")
|
||||
set( Qt Qt6 )
|
||||
else()
|
||||
message( STATUS "GUI Frontend: Qt5")
|
||||
set( Qt Qt5 )
|
||||
endif()
|
||||
|
||||
if ( ${QHELP} )
|
||||
set(QtHelpModule Help)
|
||||
add_definitions( -D_USE_QHELP )
|
||||
endif()
|
||||
|
||||
if ( ${QT6} )
|
||||
find_package( Qt6 REQUIRED COMPONENTS Widgets OpenGL OpenGLWidgets ${QtHelpModule})
|
||||
add_definitions( ${Qt6Widgets_DEFINITIONS} ${Qt6Help_DEFINITIONS} ${Qt6OpenGLWidgets_DEFINITIONS} )
|
||||
include_directories( ${Qt6Widgets_INCLUDE_DIRS} ${Qt6Help_INCLUDE_DIRS} ${Qt6OpenGLWidgets_INCLUDE_DIRS} )
|
||||
else()
|
||||
find_package( Qt5 REQUIRED COMPONENTS Widgets OpenGL ${QtHelpModule})
|
||||
add_definitions( ${Qt5Widgets_DEFINITIONS} ${Qt5Help_DEFINITIONS} )
|
||||
include_directories( ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Help_INCLUDE_DIRS} )
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
find_package(OpenGL REQUIRED)
|
||||
#find_package(Qt5 COMPONENTS Widgets OpenGL REQUIRED)
|
||||
#add_definitions( ${Qt5Widgets_DEFINITIONS} )
|
||||
#include_directories( ${Qt5Widgets_INCLUDE_DIRS} )
|
||||
add_definitions( -DMSVC -D_CRT_SECURE_NO_WARNINGS )
|
||||
add_definitions( -D__SDL__ -D__QT_DRIVER__ -DQT_DEPRECATED_WARNINGS )
|
||||
add_definitions( -DFCEUDEF_DEBUGGER )
|
||||
include_directories( ${SDL_INSTALL_PREFIX}/SDL2/include )
|
||||
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib )
|
||||
set( OPENGL_LDFLAGS OpenGL::GL )
|
||||
set( SDL2_LDFLAGS ${SDL_INSTALL_PREFIX}/SDL2/lib/x64/SDL2.lib )
|
||||
set( SYS_LIBS wsock32 ws2_32 vfw32 Htmlhelp )
|
||||
set(APP_ICON_RESOURCES_WINDOWS ${CMAKE_SOURCE_DIR}/icons/fceux.rc )
|
||||
|
||||
if ( ${USE_LIBAV} )
|
||||
add_definitions( -D_USE_LIBAV ${LIBAV_CFLAGS} )
|
||||
include_directories( ${FFMPEG_INSTALL_PREFIX}/ffmpeg/include )
|
||||
set( LIBAV_LDFLAGS ${FFMPEG_INSTALL_PREFIX}/ffmpeg/lib/avcodec.lib
|
||||
${FFMPEG_INSTALL_PREFIX}/ffmpeg/lib/avformat.lib
|
||||
${FFMPEG_INSTALL_PREFIX}/ffmpeg/lib/avutil.lib
|
||||
${FFMPEG_INSTALL_PREFIX}/ffmpeg/lib/swscale.lib
|
||||
${FFMPEG_INSTALL_PREFIX}/ffmpeg/lib/swresample.lib )
|
||||
endif()
|
||||
|
||||
else(WIN32)
|
||||
# Non Windows System
|
||||
# UNIX (Linux or Mac OSX)
|
||||
|
||||
if ( ${GLVND} )
|
||||
message( STATUS "OpenGL preference: GLVND")
|
||||
set (OpenGL_GL_PREFERENCE GLVND)
|
||||
else()
|
||||
message( STATUS "OpenGL preference: LEGACY")
|
||||
set (OpenGL_GL_PREFERENCE LEGACY)
|
||||
endif()
|
||||
|
||||
# Use the built-in cmake find_package functions to find dependencies
|
||||
# Use package PkgConfig to detect headers/library what find_package cannot find.
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
add_definitions( -Wall -Wno-write-strings -Wno-sign-compare -Wno-parentheses -Wno-unused-local-typedefs -fPIC )
|
||||
add_definitions( -DFCEUDEF_DEBUGGER )
|
||||
|
||||
#if ( ${QT6} )
|
||||
# find_package( Qt6 COMPONENTS Widgets OpenGL OpenGLWidgets REQUIRED)
|
||||
# add_definitions( ${Qt6Widgets_DEFINITIONS} ${Qt6OpenGLWidgets_DEFINITIONS} )
|
||||
# include_directories( ${Qt6Widgets_INCLUDE_DIRS} ${QtOpenGLWidgets_INCLUDE_DIRS} )
|
||||
#else()
|
||||
# find_package( Qt5 COMPONENTS Widgets OpenGL REQUIRED)
|
||||
# add_definitions( ${Qt5Widgets_DEFINITIONS} )
|
||||
# include_directories( ${Qt5Widgets_INCLUDE_DIRS} )
|
||||
#endif()
|
||||
add_definitions( -D__QT_DRIVER__ -DQT_DEPRECATED_WARNINGS )
|
||||
|
||||
# Check for libminizip
|
||||
pkg_check_modules( MINIZIP REQUIRED minizip)
|
||||
|
||||
if ( ${MINIZIP_FOUND} )
|
||||
message( STATUS "Using System minizip ${MINIZIP_VERSION}" )
|
||||
add_definitions( -D_SYSTEM_MINIZIP ${MINIZIP_CFLAGS} )
|
||||
endif()
|
||||
|
||||
pkg_check_modules( X264 x264)
|
||||
|
||||
if ( ${X264_FOUND} )
|
||||
message( STATUS "Using System X264 Encoder Library ${X264_VERSION}" )
|
||||
add_definitions( -D_USE_X264 ${X264_CFLAGS} )
|
||||
endif()
|
||||
|
||||
pkg_check_modules( X265 x265)
|
||||
|
||||
if ( ${X265_FOUND} )
|
||||
message( STATUS "Using System X265 Encoder Library ${X265_VERSION}" )
|
||||
add_definitions( -D_USE_X265 ${X265_CFLAGS} )
|
||||
endif()
|
||||
|
||||
pkg_check_modules( LIBAV libavcodec libavformat libavutil libswresample libswscale)
|
||||
|
||||
if ( ${LIBAV_FOUND} )
|
||||
message( STATUS "Using System Libav Library ${LIBAV_VERSION}" )
|
||||
add_definitions( -D_USE_LIBAV ${LIBAV_CFLAGS} )
|
||||
endif()
|
||||
|
||||
#find_package(X11)
|
||||
pkg_check_modules( X11 x11)
|
||||
|
||||
if ( ${X11_FOUND} )
|
||||
message( STATUS "Has X11 Library ${X11_VERSION}" )
|
||||
add_definitions( -D_HAS_X11 )
|
||||
include_directories( ${X11_INCLUDE_DIR} )
|
||||
endif()
|
||||
|
||||
pkg_check_modules( XKB xkbcommon)
|
||||
|
||||
if ( ${XKB_FOUND} )
|
||||
message( STATUS "Has XKB Library ${XKB_VERSION}" )
|
||||
add_definitions( -D_HAS_XKB ${XKB_CFLAGS} )
|
||||
endif()
|
||||
|
||||
#pkg_check_modules( GL gl) # Use built in find package instead for OpenGL
|
||||
|
||||
# Check for OpenGL
|
||||
if ( ${OPENGL_FOUND} )
|
||||
include_directories( ${OPENGL_INCLUDE_DIR} )
|
||||
endif()
|
||||
|
||||
# Check for SDL2
|
||||
pkg_check_modules( SDL2 REQUIRED sdl2)
|
||||
|
||||
if ( ${SDL2_FOUND} )
|
||||
add_definitions( ${SDL2_CFLAGS} -D__SDL__ )
|
||||
endif()
|
||||
|
||||
# Check for LUA
|
||||
pkg_search_module( LUA lua5.1 lua-5.1 )
|
||||
|
||||
add_definitions( -DHAVE_ASPRINTF ) # What system wouldn't have this?
|
||||
add_definitions( -DLUA_USE_LINUX ) # This needs to be set when link LUA internally for linux and macosx
|
||||
|
||||
if(APPLE)
|
||||
set( OPENGL_LDFLAGS "-framework OpenGL" )
|
||||
else()
|
||||
set( OPENGL_LDFLAGS ${OPENGL_LIBRARIES} )
|
||||
# OpenBSD refuses to implement the POSIX realtime interface and
|
||||
# refuses to provide a stub library for -ldl
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
||||
set( SYS_LIBS -lpthread)
|
||||
else()
|
||||
set( SYS_LIBS -lrt -lpthread -ldl)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endif(WIN32)
|
||||
|
||||
if ( ${LUA_FOUND} )
|
||||
# Use System LUA
|
||||
message( STATUS "Using System Lua ${LUA_VERSION}" )
|
||||
|
||||
add_definitions( -D_S9XLUA_H ${LUA_CFLAGS} )
|
||||
|
||||
set( LUA_ENGINE_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/lua-engine.cpp )
|
||||
|
||||
else ()
|
||||
|
||||
# Use Internal LUA
|
||||
message( STATUS "Using Internal Lua" )
|
||||
|
||||
add_definitions( -D_S9XLUA_H -I${CMAKE_CURRENT_SOURCE_DIR}/lua/src )
|
||||
|
||||
set( LUA_ENGINE_SOURCE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lapi.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lauxlib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lbaselib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lcode.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ldblib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ldebug.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ldo.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ldump.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lfunc.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lgc.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/linit.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/liolib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/llex.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lmathlib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lmem.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/loadlib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lobject.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lopcodes.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/loslib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lparser.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lstate.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lstring.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lstrlib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ltable.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ltablib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ltm.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lundump.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lvm.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lzio.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/print.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua-engine.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if ( ${ZLIB_FOUND} )
|
||||
|
||||
message( STATUS "Using System zlib ${ZLIB_VERSION_STRING}" )
|
||||
#add_definitions( ${ZLIB_CFLAGS} )
|
||||
include_directories( ${ZLIB_INCLUDE_DIRS} )
|
||||
else()
|
||||
|
||||
message( STATUS "Using Internal zlib" )
|
||||
|
||||
set( ZLIB_SOURCE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/adler32.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/compress.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/crc32.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/deflate.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/gzio.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/infblock.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/infcodes.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/inffast.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/inflate.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/inftrees.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/infutil.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/trees.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/uncompr.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/unzip.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/zutil.c
|
||||
)
|
||||
endif()
|
||||
|
||||
include_directories( ${CMAKE_SOURCE_DIR}/src )
|
||||
include_directories( ${CMAKE_SOURCE_DIR}/src/drivers )
|
||||
|
||||
if(APPLE)
|
||||
add_definitions( -DPSS_STYLE=1 )
|
||||
else(APPLE)
|
||||
if(UNIX)
|
||||
add_definitions( -DPSS_STYLE=1 )
|
||||
endif(UNIX)
|
||||
endif(APPLE)
|
||||
|
||||
set(SRC_CORE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/asm.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cart.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cheat.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/conddebug.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/config.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/debug.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drawing.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/fceu.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/fds.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/file.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/emufile.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/filter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ines.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/movie.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/netplay.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/nsf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/oldmovie.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/palette.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ppu.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sound.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/state.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/unif.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/video.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vsuni.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wave.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/x6502.cpp
|
||||
${LUA_ENGINE_SOURCE}
|
||||
${ZLIB_SOURCE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/01-222.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/09-034a.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/103.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/106.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/108.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/112.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/116.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/117.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/120.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/121.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/12in1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/151.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/156.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/158B.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/15.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/164.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/168.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/170.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/175.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/176.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/177.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/178.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/183.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/185.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/186.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/187.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/189.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/18.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/190.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/193.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/199.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/206.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/208.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/222.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/225.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/228.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/230.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/232.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/234.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/235.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/244.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/246.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/252.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/253.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/28.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/32.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/33.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/34.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/36.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/3d-block.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/40.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/411120-c.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/41.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/42.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/43.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/46.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/50.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/51.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/57.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/603-5052.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/62.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/65.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/67.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/68.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/69.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/71.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/72.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/77.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/79.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/80013-B.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/80.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/8157.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/8237.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/82.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/830118C.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/88.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/8in1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/90.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/91.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/96.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/99.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/a9746.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ac-08.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/addrlatch.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ax5705.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bandai.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bb.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bmc13in1jy110.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bmc42in1r.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bmc64in1nr.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bmc70in1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/BMW8544.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bonza.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bs-5.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bs4xxxr.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/cheapocabra.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/cityfighter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/coolboy.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/dance2000.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/datalatch.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/dream.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/__dummy_mapper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/edu2000.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/eh8813a.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/emu2413.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/et-100.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/et-4320.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/F-15.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/famicombox.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ffe.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/fk23c.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/fns.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ghostbusters63in1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/gs-2004.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/gs-2013.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/h2288.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/hp10xx_hp20xx.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/hp898f.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/inlnsf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/karaoke.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/kof97.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7010.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7012.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7013.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7016.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7017.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7030.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7031.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7032.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7037.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7057.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/le05.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/lh32.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/lh53.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/malee.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/mihunche.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/mmc1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/mmc2and4.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/mmc3.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/mmc5.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/n106.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/n625092.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/novel.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/onebus.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/pec-586.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/rt-01.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/sa-9602b.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/sachen.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/sb-2000.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/sc-127.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/sheroes.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/sl1632.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/subor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/super24.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/supervision.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/t-227-1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/t-262.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/tengen.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/tf-1201.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/transformer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/unrom512.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc2and4.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc3.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc5.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc6.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc7.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc7p.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/yoko.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/arkanoid.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/bworld.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/cursor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/fkb.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/fns.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/ftrainer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/hypershot.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/mahjong.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/mouse.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/oekakids.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/pec586kb.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/powerpad.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/quiz.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/shadow.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/snesmouse.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/suborkb.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/toprider.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/virtualboy.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/lcdcompzapper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/zapper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils/backward.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils/xstring.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils/crc32.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils/endian.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils/general.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils/guid.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils/md5.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils/memory.cpp
|
||||
)
|
||||
|
||||
|
||||
set(SRC_DRIVERS_COMMON
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/args.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/cheat.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/config.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/configSys.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/hq2x.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/hq3x.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/scale2x.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/scale3x.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/scalebit.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/vidblit.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/os_utils.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/nes_ntsc.c
|
||||
)
|
||||
|
||||
set(SRC_DRIVERS_SDL
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/main.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleWindow.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleViewerGL.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleViewerSDL.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/InputConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GamePadConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/FamilyKeyboard.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HotKeyConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TimingConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/FrameTimingStats.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/PaletteConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/PaletteEditor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ColorMenu.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GuiConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HelpPages.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MoviePlay.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MovieRecord.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MovieOptions.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/LuaControl.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/CheatsConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GameGenie.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HexEditor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MsgLogViewer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/CodeDataLogger.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/SymbolicDebug.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleDebugger.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleUtilities.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleVideoConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleSoundConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/iNesHeaderEditor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/SplashScreen.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TraceLogger.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/AboutWindow.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/fceuWrapper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ppuViewer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/NameTableViewer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/RamWatch.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/RamSearch.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/config.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/input.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/nes_shm.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/keyscan.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/sdl-sound.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/sdl-video.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/sdl-joystick.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/sdl-throttle.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/unix-netplay.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/AviRecord.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/AviRiffViewer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/avi/avi-utils.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/avi/fileio.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/avi/gwavi.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/TasEditorWindow.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/taseditor_project.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/taseditor_config.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/taseditor_lua.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/markers_manager.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/greenzone.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/selection.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/playback.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/recorder.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/history.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/splicer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/inputlog.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/laglog.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/branches.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/bookmarks.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/bookmark.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/snapshot.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/markers.cpp
|
||||
)
|
||||
|
||||
set(SOURCES ${SRC_CORE} ${SRC_DRIVERS_COMMON} ${SRC_DRIVERS_SDL})
|
||||
|
||||
# Put build timestamp into BUILD_TS environment variable and from there into
|
||||
# the FCEUX_BUILD_TIMESTAMP preprocessor definition.
|
||||
# Note: with CMake >= 3.8.0, this will respect SOURCE_DATE_EPOCH. For more info,
|
||||
# see <https://reproducible-builds.org/docs/source-date-epoch/>.
|
||||
string(TIMESTAMP BUILD_TS "%H:%M:%S %b %d %Y")
|
||||
add_definitions( -DFCEUX_BUILD_TIMESTAMP=\"${BUILD_TS}\" )
|
||||
|
||||
if (WIN32)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/scripts/genGitHdr.bat ${CMAKE_CURRENT_BINARY_DIR}
|
||||
VERBATIM )
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/scripts/genGitHdr.sh ${CMAKE_CURRENT_BINARY_DIR}
|
||||
VERBATIM )
|
||||
endif()
|
||||
|
||||
set_property(SOURCE ${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp PROPERTY SKIP_AUTOGEN ON)
|
||||
|
||||
if (APPLE)
|
||||
|
||||
set(MACOSX_BUNDLE_ICON_FILE fceux.icns)
|
||||
set(APP_ICON ${CMAKE_SOURCE_DIR}/fceux.icns )
|
||||
set_source_files_properties( ${APP_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources" )
|
||||
|
||||
add_executable( ${APP_NAME} MACOSX_BUNDLE ${APP_ICON} ${SOURCES} ../resources.qrc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp)
|
||||
elseif (WIN32)
|
||||
|
||||
add_executable( ${APP_NAME} ${SOURCES} ../resources.qrc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp
|
||||
${APP_ICON_RESOURCES_WINDOWS} )
|
||||
else()
|
||||
add_executable( ${APP_NAME} ${SOURCES} ../resources.qrc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp)
|
||||
endif()
|
||||
|
||||
target_link_libraries( ${APP_NAME}
|
||||
${${Qt}Widgets_LIBRARIES}
|
||||
${${Qt}Help_LIBRARIES}
|
||||
${${Qt}OpenGL_LIBRARIES}
|
||||
${${Qt}OpenGLWidgets_LIBRARIES}
|
||||
${OPENGL_LDFLAGS}
|
||||
${SDL2_LDFLAGS}
|
||||
${MINIZIP_LDFLAGS} ${ZLIB_LIBRARIES}
|
||||
${LUA_LDFLAGS} ${X264_LDFLAGS} ${X265_LDFLAGS} ${LIBAV_LDFLAGS}
|
||||
${SYS_LIBS}
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
# target_link_libraries( ${APP_NAME} wsock32 ws2_32 )
|
||||
|
||||
set_target_properties(${APP_NAME} PROPERTIES WIN32_EXECUTABLE TRUE)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
|
||||
install( TARGETS ${APP_NAME}
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION bin COMPONENT Runtime )
|
||||
|
||||
# Use \$ to defer expansion until install script is called; CPack will call it with its own CMAKE_INSTALL_PREFIX
|
||||
set(APP \${CMAKE_INSTALL_PREFIX}/${APP_NAME}.app)
|
||||
|
||||
install( DIRECTORY ${CMAKE_SOURCE_DIR}/output/.
|
||||
DESTINATION ${APP_NAME}.app/Contents/Resources COMPONENT Extra )
|
||||
|
||||
set(CPACK_PACKAGE_ICON ${CMAKE_SOURCE_DIR}/fceux.icns )
|
||||
set(CPACK_GENERATOR "DragNDrop")
|
||||
include(CPACK)
|
||||
|
||||
# macdeployqt tool that comes with Qt: https://doc.qt.io/qt-5/macos-deployment.html#macdeploy
|
||||
# Compared to fixup_bundle, correctly finds and installs Qt-specific resources as well as non-Qt dependencies
|
||||
find_program(MACDEPLOYQT macdeployqt)
|
||||
if(NOT MACDEPLOYQT)
|
||||
message(FATAL_ERROR "Could not find macdeployqt executable")
|
||||
endif()
|
||||
|
||||
find_package(Perl REQUIRED)
|
||||
|
||||
install( CODE "
|
||||
message(STATUS \"Deploying and fixing up dependencies in app: ${APP}\")
|
||||
execute_process(COMMAND \"${MACDEPLOYQT}\" \"${APP}\" -verbose=1)
|
||||
execute_process(COMMAND \"${PERL_EXECUTABLE}\"
|
||||
\"${CMAKE_SOURCE_DIR}/scripts/macOSX_BundleFix.pl\"
|
||||
\"${CMAKE_BINARY_DIR}/_CPack_Packages\")
|
||||
"
|
||||
COMPONENT Runtime
|
||||
)
|
||||
|
||||
else(APPLE)
|
||||
|
||||
install( TARGETS ${APP_NAME}
|
||||
RUNTIME DESTINATION bin )
|
||||
|
||||
install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/auxlib.lua DESTINATION share/fceux/luaScripts )
|
||||
install( DIRECTORY ${CMAKE_SOURCE_DIR}/output/. DESTINATION share/fceux )
|
||||
install( FILES ${CMAKE_SOURCE_DIR}/fceux1.png DESTINATION share/pixmaps )
|
||||
install( FILES ${CMAKE_SOURCE_DIR}/fceux.desktop DESTINATION share/applications )
|
||||
install( FILES ${CMAKE_SOURCE_DIR}/documentation/fceux.6 DESTINATION ${CMAKE_INSTALL_MANDIR}/man6 )
|
||||
install( FILES ${CMAKE_SOURCE_DIR}/documentation/fceux-net-server.6 DESTINATION ${CMAKE_INSTALL_MANDIR}/man6 )
|
||||
|
||||
endif(APPLE)
|
||||
@@ -1,42 +0,0 @@
|
||||
import glob
|
||||
file_list = glob.glob('*.cpp')
|
||||
file_list.remove('lua-engine.cpp') # use logic below for this
|
||||
|
||||
subdirs = Split("""
|
||||
boards
|
||||
drivers/common
|
||||
fir
|
||||
input
|
||||
utils
|
||||
""")
|
||||
#palettes
|
||||
|
||||
Import('env')
|
||||
Export('env')
|
||||
|
||||
if env['LUA']:
|
||||
file_list.append('lua-engine.cpp')
|
||||
if env['SYSTEM_LUA'] == 0:
|
||||
subdirs.append('lua')
|
||||
|
||||
if env['CREATE_AVI']:
|
||||
subdirs.append('drivers/videolog')
|
||||
|
||||
|
||||
|
||||
for dir in subdirs:
|
||||
subdir_files = SConscript('%s/SConscript' % dir)
|
||||
file_list.append(subdir_files)
|
||||
if env['PLATFORM'] == 'win32':
|
||||
platform_files = SConscript('drivers/win/SConscript')
|
||||
else:
|
||||
platform_files = SConscript('drivers/sdl/SConscript')
|
||||
file_list.append(platform_files)
|
||||
|
||||
print env['LINKFLAGS']
|
||||
|
||||
if env['PLATFORM'] == 'win32':
|
||||
fceux = env.Program('fceux.exe', file_list)
|
||||
else:
|
||||
fceux = env.Program('fceux', file_list)
|
||||
Return('fceux')
|
||||
+7
-7
@@ -16,7 +16,7 @@ int Assemble(unsigned char *output, int addr, char *str) {
|
||||
output[0] = output[1] = output[2] = 0;
|
||||
char astr[128],ins[4];
|
||||
int len = strlen(str);
|
||||
if ((!len) || (len > 0x127)) return 1;
|
||||
if ((!len) || (len > 127)) return 1;
|
||||
|
||||
strcpy(astr,str);
|
||||
str_ucase(astr);
|
||||
@@ -272,7 +272,7 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||
(a) = opcode[1] | opcode[2]<<8; \
|
||||
}
|
||||
#define zpIndex(a,i) { \
|
||||
(a) = opcode[1]+(i); \
|
||||
(a) = (opcode[1]+(i))&0xFF; \
|
||||
}
|
||||
#define indirectX(a) { \
|
||||
(a) = (opcode[1]+RX)&0xFF; \
|
||||
@@ -360,8 +360,8 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||
case 0xE6: strcpy(chr,"INC"); goto _zeropage;
|
||||
_zeropage:
|
||||
// ################################## Start of SP CODE ###########################
|
||||
// Change width to %04X
|
||||
sprintf(str,"%s $%04X = #$%02X", chr,opcode[1],GetMem(opcode[1]));
|
||||
// Change width to %04X // don't!
|
||||
sprintf(str,"%s $%02X = #$%02X", chr,opcode[1],GetMem(opcode[1]));
|
||||
// ################################## End of SP CODE ###########################
|
||||
break;
|
||||
|
||||
@@ -457,7 +457,7 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||
_zeropagex:
|
||||
zpIndex(tmp,RX);
|
||||
// ################################## Start of SP CODE ###########################
|
||||
// Change width to %04X
|
||||
// Change width to %04X // don't!
|
||||
sprintf(str,"%s $%02X,X @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
||||
// ################################## End of SP CODE ###########################
|
||||
break;
|
||||
@@ -515,8 +515,8 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||
_zeropagey:
|
||||
zpIndex(tmp,RY);
|
||||
// ################################## Start of SP CODE ###########################
|
||||
// Change width to %04X
|
||||
sprintf(str,"%s $%04X,Y @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
||||
// Change width to %04X // don't!
|
||||
sprintf(str,"%s $%02X,Y @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
||||
// ################################## End of SP CODE ###########################
|
||||
break;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*
|
||||
* TXC mappers, originally much complex banksitching
|
||||
*
|
||||
* P/N PRG MAP, UNIF Name
|
||||
* 01-22111-000 (05-00002-010) (132, 22211) - MGC-001 Qi Wang
|
||||
* 01-22110-000 (52S ) - MGC-002 2-in-1 Gun
|
||||
* 01-22111-100 (02-00002-010) (173 ) - MGC-008 Mahjong Block
|
||||
@@ -27,6 +28,7 @@
|
||||
* 01-22000-400 (05-00002-010) (036 ) - MGC-015 Policeman
|
||||
* 01-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior
|
||||
* 01-11160-000 (04-02310-000) ( , 11160) - MGC-023 6-in-1
|
||||
* 01-22026-000 (05-04010-090) ( ) - MGC-026 4-in-1
|
||||
* 01-22270-000 (05-00002-010) (132, 22211) - MGC-xxx Creatom
|
||||
* 01-22200-400 (------------) (079 ) - ET.03 F-15 City War
|
||||
* (172 ) - 1991 Du Ma Racing
|
||||
|
||||
+89
-89
@@ -1,90 +1,90 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* NTDEC, ASDER games
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 reg[8];
|
||||
static uint8 mirror, cmd, bank;
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &cmd, 1, "CMD" },
|
||||
{ &mirror, 1, "MIRR" },
|
||||
{ &bank, 1, "BANK" },
|
||||
{ reg, 8, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setmirror(mirror ^ 1);
|
||||
setprg8(0x8000, reg[0]);
|
||||
setprg8(0xA000, reg[1]);
|
||||
setchr2(0x0000, (reg[2] >> 1));
|
||||
setchr2(0x0800, (reg[3] >> 1));
|
||||
setchr1(0x1000, ((bank & 0x10) << 4) | reg[4]);
|
||||
setchr1(0x1400, ((bank & 0x20) << 3) | reg[5]);
|
||||
setchr1(0x1800, ((bank & 0x40) << 2) | reg[6]);
|
||||
setchr1(0x1C00, ((bank & 0x80) << 1) | reg[7]);
|
||||
}
|
||||
|
||||
static DECLFW(M112Write) {
|
||||
switch (A) {
|
||||
case 0xe000: mirror = V & 1; Sync();; break;
|
||||
case 0x8000: cmd = V & 7; break;
|
||||
case 0xa000: reg[cmd] = V; Sync(); break;
|
||||
case 0xc000: bank = V; Sync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void M112Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
static void M112Power(void) {
|
||||
bank = 0;
|
||||
setprg16(0xC000, ~0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M112Write);
|
||||
SetWriteHandler(0x4020, 0x5FFF, M112Write);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* NTDEC, ASDER games
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 reg[8];
|
||||
static uint8 mirror, cmd, bank;
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &cmd, 1, "CMD" },
|
||||
{ &mirror, 1, "MIRR" },
|
||||
{ &bank, 1, "BANK" },
|
||||
{ reg, 8, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setmirror(mirror ^ 1);
|
||||
setprg8(0x8000, reg[0]);
|
||||
setprg8(0xA000, reg[1]);
|
||||
setchr2(0x0000, (reg[2] >> 1));
|
||||
setchr2(0x0800, (reg[3] >> 1));
|
||||
setchr1(0x1000, ((bank & 0x10) << 4) | reg[4]);
|
||||
setchr1(0x1400, ((bank & 0x20) << 3) | reg[5]);
|
||||
setchr1(0x1800, ((bank & 0x40) << 2) | reg[6]);
|
||||
setchr1(0x1C00, ((bank & 0x80) << 1) | reg[7]);
|
||||
}
|
||||
|
||||
static DECLFW(M112Write) {
|
||||
switch (A) {
|
||||
case 0xe000: mirror = V & 1; Sync();; break;
|
||||
case 0x8000: cmd = V & 7; break;
|
||||
case 0xa000: reg[cmd] = V; Sync(); break;
|
||||
case 0xc000: bank = V; Sync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void M112Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
static void M112Power(void) {
|
||||
bank = 0;
|
||||
setprg16(0xC000, ~0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M112Write);
|
||||
SetWriteHandler(0x4020, 0x5FFF, M112Write);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper112_Init(CartInfo *info) {
|
||||
info->Power = M112Power;
|
||||
info->Close = M112Close;
|
||||
GameStateRestore = StateRestore;
|
||||
WRAM = (uint8*)FCEU_gmalloc(8192);
|
||||
SetupCartPRGMapping(0x10, WRAM, 8192, 1);
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper112_Init(CartInfo *info) {
|
||||
info->Power = M112Power;
|
||||
info->Close = M112Close;
|
||||
GameStateRestore = StateRestore;
|
||||
WRAM = (uint8*)FCEU_gmalloc(8192);
|
||||
SetupCartPRGMapping(0x10, WRAM, 8192, 1);
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
+18
-11
@@ -35,31 +35,39 @@ static SFORMAT StateRegs[] =
|
||||
static void Sync(void) {
|
||||
int i;
|
||||
setmirror(((latched >> 6) & 1) ^ 1);
|
||||
switch (latchea) {
|
||||
case 0x8000:
|
||||
switch (latchea & 3) {
|
||||
case 0:
|
||||
for (i = 0; i < 4; i++)
|
||||
setprg8(0x8000 + (i << 13), (((latched & 0x7F) << 1) + i) ^ (latched >> 7));
|
||||
setprg8(0x8000 + (i << 13), ((latched & 0x3F) << 1) + i);
|
||||
break;
|
||||
case 0x8002:
|
||||
case 2:
|
||||
for (i = 0; i < 4; i++)
|
||||
setprg8(0x8000 + (i << 13), ((latched & 0x7F) << 1) + (latched >> 7));
|
||||
setprg8(0x8000 + (i << 13), ((latched & 0x3F) << 1) + (latched >> 7));
|
||||
break;
|
||||
case 0x8001:
|
||||
case 0x8003:
|
||||
case 1:
|
||||
case 3:
|
||||
for (i = 0; i < 4; i++) {
|
||||
unsigned int b;
|
||||
b = latched & 0x7F;
|
||||
b = latched & 0x3F;
|
||||
if (i >= 2 && !(latchea & 0x2))
|
||||
b = 0x7F;
|
||||
setprg8(0x8000 + (i << 13), (i & 1) + ((b << 1) ^ (latched >> 7)));
|
||||
b = b | 0x07;
|
||||
setprg8(0x8000 + (i << 13), (i & 1) + (b << 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static DECLFW(M15Write) {
|
||||
latchea = A;
|
||||
latched = V;
|
||||
// cah4e3 02.10.19 once again, there may be either two similar mapper 15 exist. the one for 110in1 or 168in1 carts with complex multi game features.
|
||||
// and another implified version for subor/waixing chinese originals and hacks with no different modes, working only in mode 0 and which does not
|
||||
// expect there is any CHR write protection. protecting CHR writes only for mode 3 fixes the problem, all roms may be run on the same source again.
|
||||
if((latchea & 3) == 3)
|
||||
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0);
|
||||
else
|
||||
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1);
|
||||
Sync();
|
||||
}
|
||||
|
||||
@@ -70,7 +78,6 @@ static void StateRestore(int version) {
|
||||
static void M15Power(void) {
|
||||
latchea = 0x8000;
|
||||
latched = 0;
|
||||
setchr8(0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
|
||||
+229
-229
@@ -1,232 +1,232 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel 2006 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* It seems that 162/163/164 mappers are the same mapper with just different
|
||||
* mapper modes enabled or disabled in software or hardware, need more nanjing
|
||||
* carts
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 laststrobe, trigger;
|
||||
static uint8 reg[8];
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
|
||||
static writefunc pcmwrite;
|
||||
|
||||
static void (*WSync)(void);
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &laststrobe, 1, "STB" },
|
||||
{ &trigger, 1, "TRG" },
|
||||
{ reg, 8, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
setprg32(0x8000, (reg[0] << 4) | (reg[1] & 0xF));
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
WSync();
|
||||
}
|
||||
|
||||
static DECLFR(ReadLow) {
|
||||
switch (A & 0x7700) {
|
||||
case 0x5100: return reg[2] | reg[0] | reg[1] | reg[3] ^ 0xff; break;
|
||||
case 0x5500:
|
||||
if (trigger)
|
||||
return reg[2] | reg[1]; // Lei Dian Huang Bi Ka Qiu Chuan Shuo (NJ046) may broke other games
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
static void M163HB(void) {
|
||||
if (reg[1] & 0x80) {
|
||||
if (scanline == 239) {
|
||||
setchr4(0x0000, 0);
|
||||
setchr4(0x1000, 0);
|
||||
} else if (scanline == 127) {
|
||||
setchr4(0x0000, 1);
|
||||
setchr4(0x1000, 1);
|
||||
}
|
||||
/*
|
||||
if(scanline>=127) // Hu Lu Jin Gang (NJ039) (Ch) [!] don't like it
|
||||
{
|
||||
setchr4(0x0000,1);
|
||||
setchr4(0x1000,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
setchr4(0x0000,0);
|
||||
setchr4(0x1000,0);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Write) {
|
||||
switch (A & 0x7300) {
|
||||
case 0x5100: reg[0] = V; WSync(); break;
|
||||
case 0x5000: reg[1] = V; WSync(); break;
|
||||
case 0x5300: reg[2] = V; break;
|
||||
case 0x5200: reg[3] = V; WSync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Power(void) {
|
||||
memset(reg, 0, 8);
|
||||
reg[1] = 0xFF;
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel 2006 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* It seems that 162/163/164 mappers are the same mapper with just different
|
||||
* mapper modes enabled or disabled in software or hardware, need more nanjing
|
||||
* carts
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 laststrobe, trigger;
|
||||
static uint8 reg[8];
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
|
||||
static writefunc pcmwrite;
|
||||
|
||||
static void (*WSync)(void);
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &laststrobe, 1, "STB" },
|
||||
{ &trigger, 1, "TRG" },
|
||||
{ reg, 8, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
setprg32(0x8000, (reg[0] << 4) | (reg[1] & 0xF));
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
WSync();
|
||||
}
|
||||
|
||||
static DECLFR(ReadLow) {
|
||||
switch (A & 0x7700) {
|
||||
case 0x5100: return reg[2] | reg[0] | reg[1] | reg[3] ^ 0xff; break;
|
||||
case 0x5500:
|
||||
if (trigger)
|
||||
return reg[2] | reg[1]; // Lei Dian Huang Bi Ka Qiu Chuan Shuo (NJ046) may broke other games
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
static void M163HB(void) {
|
||||
if (reg[1] & 0x80) {
|
||||
if (scanline == 239) {
|
||||
setchr4(0x0000, 0);
|
||||
setchr4(0x1000, 0);
|
||||
} else if (scanline == 127) {
|
||||
setchr4(0x0000, 1);
|
||||
setchr4(0x1000, 1);
|
||||
}
|
||||
/*
|
||||
if(scanline>=127) // Hu Lu Jin Gang (NJ039) (Ch) [!] don't like it
|
||||
{
|
||||
setchr4(0x0000,1);
|
||||
setchr4(0x1000,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
setchr4(0x0000,0);
|
||||
setchr4(0x1000,0);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Write) {
|
||||
switch (A & 0x7300) {
|
||||
case 0x5100: reg[0] = V; WSync(); break;
|
||||
case 0x5000: reg[1] = V; WSync(); break;
|
||||
case 0x5300: reg[2] = V; break;
|
||||
case 0x5200: reg[3] = V; WSync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Power(void) {
|
||||
memset(reg, 0, 8);
|
||||
reg[1] = 0xFF;
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
void Mapper164_Init(CartInfo *info) {
|
||||
info->Power = Power;
|
||||
info->Close = Close;
|
||||
WSync = Sync;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
static DECLFW(Write2) {
|
||||
if (A == 0x5101) {
|
||||
if (laststrobe && !V) {
|
||||
trigger ^= 1;
|
||||
}
|
||||
laststrobe = V;
|
||||
} else if (A == 0x5100 && V == 6) //damn thoose protected games
|
||||
setprg32(0x8000, 3);
|
||||
else
|
||||
switch (A & 0x7300) {
|
||||
case 0x5200: reg[0] = V; WSync(); break;
|
||||
case 0x5000: reg[1] = V; WSync(); if (!(reg[1] & 0x80) && (scanline < 128)) setchr8(0); /* setchr8(0); */ break;
|
||||
case 0x5300: reg[2] = V; break;
|
||||
case 0x5100: reg[3] = V; WSync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Power2(void) {
|
||||
memset(reg, 0, 8);
|
||||
laststrobe = 1;
|
||||
pcmwrite = GetWriteHandler(0x4011);
|
||||
SetReadHandler(0x5000, 0x5FFF, ReadLow);
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write2);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
void Mapper164_Init(CartInfo *info) {
|
||||
info->Power = Power;
|
||||
info->Close = Close;
|
||||
WSync = Sync;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
static DECLFW(Write2) {
|
||||
if (A == 0x5101) {
|
||||
if (laststrobe && !V) {
|
||||
trigger ^= 1;
|
||||
}
|
||||
laststrobe = V;
|
||||
} else if (A == 0x5100 && V == 6) //damn thoose protected games
|
||||
setprg32(0x8000, 3);
|
||||
else
|
||||
switch (A & 0x7300) {
|
||||
case 0x5200: reg[0] = V; WSync(); break;
|
||||
case 0x5000: reg[1] = V; WSync(); if (!(reg[1] & 0x80) && (scanline < 128)) setchr8(0); /* setchr8(0); */ break;
|
||||
case 0x5300: reg[2] = V; break;
|
||||
case 0x5100: reg[3] = V; WSync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Power2(void) {
|
||||
memset(reg, 0, 8);
|
||||
laststrobe = 1;
|
||||
pcmwrite = GetWriteHandler(0x4011);
|
||||
SetReadHandler(0x5000, 0x5FFF, ReadLow);
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write2);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
WSync();
|
||||
}
|
||||
|
||||
void Mapper163_Init(CartInfo *info) {
|
||||
info->Power = Power2;
|
||||
info->Close = Close;
|
||||
WSync = Sync;
|
||||
GameHBIRQHook = M163HB;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
static void Sync3(void) {
|
||||
setchr8(0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
switch (reg[3] & 7) {
|
||||
case 0:
|
||||
case 2: setprg32(0x8000, (reg[0] & 0xc) | (reg[1] & 2) | ((reg[2] & 0xf) << 4)); break;
|
||||
case 1:
|
||||
case 3: setprg32(0x8000, (reg[0] & 0xc) | (reg[2] & 0xf) << 4); break;
|
||||
case 4:
|
||||
case 6: setprg32(0x8000, (reg[0] & 0xe) | ((reg[1] >> 1) & 1) | ((reg[2] & 0xf) << 4)); break;
|
||||
case 5:
|
||||
case 7: setprg32(0x8000, (reg[0] & 0xf) | ((reg[2] & 0xf) << 4)); break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Write3) {
|
||||
// FCEU_printf("bs %04x %02x\n",A,V);
|
||||
reg[(A >> 8) & 3] = V;
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void Power3(void) {
|
||||
reg[0] = 3;
|
||||
reg[1] = 0;
|
||||
reg[2] = 0;
|
||||
reg[3] = 7;
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write3);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
WSync();
|
||||
}
|
||||
|
||||
void Mapper163_Init(CartInfo *info) {
|
||||
info->Power = Power2;
|
||||
info->Close = Close;
|
||||
WSync = Sync;
|
||||
GameHBIRQHook = M163HB;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
static void Sync3(void) {
|
||||
setchr8(0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
switch (reg[3] & 7) {
|
||||
case 0:
|
||||
case 2: setprg32(0x8000, (reg[0] & 0xc) | (reg[1] & 2) | ((reg[2] & 0xf) << 4)); break;
|
||||
case 1:
|
||||
case 3: setprg32(0x8000, (reg[0] & 0xc) | (reg[2] & 0xf) << 4); break;
|
||||
case 4:
|
||||
case 6: setprg32(0x8000, (reg[0] & 0xe) | ((reg[1] >> 1) & 1) | ((reg[2] & 0xf) << 4)); break;
|
||||
case 5:
|
||||
case 7: setprg32(0x8000, (reg[0] & 0xf) | ((reg[2] & 0xf) << 4)); break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Write3) {
|
||||
// FCEU_printf("bs %04x %02x\n",A,V);
|
||||
reg[(A >> 8) & 3] = V;
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void Power3(void) {
|
||||
reg[0] = 3;
|
||||
reg[1] = 0;
|
||||
reg[2] = 0;
|
||||
reg[3] = 7;
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write3);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
WSync();
|
||||
}
|
||||
|
||||
void UNLFS304_Init(CartInfo *info) {
|
||||
info->Power = Power3;
|
||||
info->Close = Close;
|
||||
WSync = Sync3;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
WSync();
|
||||
}
|
||||
|
||||
void UNLFS304_Init(CartInfo *info) {
|
||||
info->Power = Power3;
|
||||
info->Close = Close;
|
||||
WSync = Sync3;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
+2
-2
@@ -37,8 +37,8 @@ static int32 SensorDelay;
|
||||
// highly experimental, not actually working, just curious if it hapen to work with some other decoder
|
||||
// SND Registers
|
||||
static uint8 pcm_enable = 0;
|
||||
static int16 pcm_latch = 0x3F6, pcm_clock = 0x3F6;
|
||||
static writefunc pcmwrite;
|
||||
//static int16 pcm_latch = 0x3F6, pcm_clock = 0x3F6;
|
||||
//static writefunc pcmwrite;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
|
||||
@@ -18,6 +18,33 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Family Study Box by Fukutake Shoten
|
||||
*
|
||||
* REG[0] R dddddddd / W ww---sss
|
||||
* ddd - TAPE DATA BYTE (ready when IRQ occurs)
|
||||
* sss - BRAM hi-bank
|
||||
* ww - PRAM bank
|
||||
* REG[1] R 0123---- / W ----PPPP
|
||||
* 0 - ?
|
||||
* 1 - ?
|
||||
* 2 - ?
|
||||
* 3 - ?
|
||||
* PPPP- PROM bank
|
||||
* REG[2] R -?--R--- / W A-BC-DEF
|
||||
* 4 - ?
|
||||
* R - sb4x power supply status (active low)
|
||||
* A - ?
|
||||
* B - ?
|
||||
* C - ?
|
||||
* D - ?
|
||||
* E - ?
|
||||
* F - ?
|
||||
*
|
||||
* BRAM0 4400-4FFF, 3K bank 0 (32K SWRAM) [hardwired]
|
||||
* BRAMB 5000-5FFF, 4K banks 1-7 (32K SWRAM) [REG[0] W -----sss]
|
||||
* PRAMB 6000-7FFF, 8K banks 1-3 (32K PRAM) [REG[0] W ww------]
|
||||
* PROMB 8000-BFFF, 16K banks 1-15 (256K PROM)[REG[1] W ----PPPP]
|
||||
* PROM0 C000-FFFF, 16K bank 0 (256K PROM) [hardwired]
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright (C) 2017 FCEUX Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Magic Kid GooGoo
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 prgr, chrr[4];
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
static void Mapper190_Sync(void) {
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
|
||||
setprg16(0x8000, prgr);
|
||||
setprg16(0xC000, 0);
|
||||
setchr2(0x0000, chrr[0]);
|
||||
setchr2(0x0800, chrr[1]);
|
||||
setchr2(0x1000, chrr[2]);
|
||||
setchr2(0x1800, chrr[3]);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper190_Write89) { prgr = V&7; Mapper190_Sync(); }
|
||||
static DECLFW(Mapper190_WriteCD) { prgr = 8|(V&7); Mapper190_Sync(); }
|
||||
|
||||
static DECLFW(Mapper190_WriteAB) {
|
||||
int bank = A&3;
|
||||
chrr[bank] = V&63;
|
||||
Mapper190_Sync();
|
||||
}
|
||||
|
||||
|
||||
static void Mapper190_Power(void) {
|
||||
FCEU_CheatAddRAM(0x2000 >> 10, 0x6000, WRAM);
|
||||
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetWriteHandler(0x8000, 0x9FFF, Mapper190_Write89);
|
||||
SetWriteHandler(0xA000, 0xBFFF, Mapper190_WriteAB);
|
||||
SetWriteHandler(0xC000, 0xDFFF, Mapper190_WriteCD);
|
||||
Mapper190_Sync();
|
||||
|
||||
setmirror(MI_V);
|
||||
}
|
||||
|
||||
static void Mapper190_Close(void) {
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
static void Mapper190_Restore(int) {
|
||||
Mapper190_Sync();
|
||||
}
|
||||
|
||||
|
||||
void Mapper190_Init(CartInfo *info) {
|
||||
info->Power = Mapper190_Power;
|
||||
info->Close = Mapper190_Close;
|
||||
GameStateRestore = Mapper190_Restore;
|
||||
|
||||
WRAM = (uint8*)FCEU_gmalloc(0x2000);
|
||||
SetupCartPRGMapping(0x10, WRAM, 0x2000, 1);
|
||||
|
||||
chrr[0] = chrr[1] = chrr[2] = chrr[3] = prgr = 0;
|
||||
|
||||
AddExState(&prgr, 1, 0, "PRGR");
|
||||
AddExState(chrr, 4, 0, "CHRR");
|
||||
AddExState(WRAM, 0x2000, 0, "WRAM");
|
||||
}
|
||||
+11
-1
@@ -52,15 +52,23 @@ static DECLFW(M225Write) {
|
||||
}
|
||||
|
||||
static DECLFW(M225LoWrite) {
|
||||
if (A & 0x800) {
|
||||
prot[A & 0x03] = V;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(M225LoRead) {
|
||||
return 0;
|
||||
if (A & 0x800) {
|
||||
return prot[A & 3] & 0x0F;
|
||||
}
|
||||
return X.DB;
|
||||
}
|
||||
|
||||
static void M225Power(void) {
|
||||
prg = 0;
|
||||
chr = 0;
|
||||
mode = 0;
|
||||
mirr = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x5000, 0x5FFF, M225LoRead);
|
||||
SetWriteHandler(0x5000, 0x5FFF, M225LoWrite);
|
||||
@@ -70,7 +78,9 @@ static void M225Power(void) {
|
||||
|
||||
static void M225Reset(void) {
|
||||
prg = 0;
|
||||
chr = 0;
|
||||
mode = 0;
|
||||
mirr = 0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
|
||||
+6
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2012 FCEUX team
|
||||
Copyright (C) 2012-2017 FCEUX team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -53,8 +53,8 @@ void Mirror(uint8 value)
|
||||
|
||||
static void Sync()
|
||||
{
|
||||
int prglo;
|
||||
int prghi;
|
||||
int prglo = 0;
|
||||
int prghi = 0;
|
||||
|
||||
int outb = outer << 1;
|
||||
//this can probably be rolled up, but i have no motivation to do so
|
||||
@@ -127,20 +127,21 @@ static void Sync()
|
||||
|
||||
static DECLFW(WriteEXP)
|
||||
{
|
||||
uint32 addr = A;
|
||||
//uint32 addr = A;
|
||||
uint8 value = V;
|
||||
reg = value & 0x81;
|
||||
}
|
||||
|
||||
static DECLFW(WritePRG)
|
||||
{
|
||||
uint32 addr = A;
|
||||
//uint32 addr = A;
|
||||
uint8 value = V;
|
||||
switch (reg)
|
||||
{
|
||||
case 0x00:
|
||||
chr = value & 3;
|
||||
Mirror(value);
|
||||
Sync();
|
||||
break;
|
||||
case 0x01:
|
||||
prg = value & 15;
|
||||
|
||||
+7
-1
@@ -22,11 +22,12 @@
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 latche;
|
||||
static uint8 latche, mirr;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &latche, 1, "LATC" },
|
||||
{ &mirr, 1, "MIRR" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -36,6 +37,11 @@ static void Sync(void) {
|
||||
}
|
||||
|
||||
static DECLFW(M36Write) {
|
||||
|
||||
switch((A>>12)&7) { // need to 4-in-1 MGC-26 BMC, doesnt break other games though
|
||||
case 0: mirr = MI_V; setmirror(mirr); break;
|
||||
case 4: mirr = MI_H; setmirror(mirr); break;
|
||||
}
|
||||
latche = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 preg, mirr;
|
||||
static int hardmirr;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
@@ -35,6 +36,8 @@ static void Sync(void) {
|
||||
setchr8(0);
|
||||
if(mirr)
|
||||
setmirror(mirr);
|
||||
else
|
||||
setmirror(hardmirr); // restore hardwired mirroring
|
||||
}
|
||||
|
||||
static DECLFW(M71Write) {
|
||||
@@ -46,6 +49,7 @@ static DECLFW(M71Write) {
|
||||
}
|
||||
|
||||
static void M71Power(void) {
|
||||
preg = 0;
|
||||
mirr = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
@@ -57,6 +61,7 @@ static void StateRestore(int version) {
|
||||
}
|
||||
|
||||
void Mapper71_Init(CartInfo *info) {
|
||||
hardmirr = info->mirror;
|
||||
info->Power = M71Power;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2017 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 bios_prg, rom_prg, rom_mode, mirror;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &bios_prg, 1, "BREG" },
|
||||
{ &rom_prg, 1, "RREG" },
|
||||
{ &rom_mode, 1, "RMODE" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setchr8(0);
|
||||
if(rom_mode&2) {
|
||||
setprg16r(0,0x8000,(bios_prg&0xF)|(rom_prg&0x70));
|
||||
} else {
|
||||
setprg16r(1,0x8000,bios_prg&3);
|
||||
}
|
||||
setprg16r(0,0xC000,rom_prg&0x7F);
|
||||
setmirror(((bios_prg>>4)&1)^1);
|
||||
}
|
||||
|
||||
static DECLFW(BMC80013BWrite) {
|
||||
uint8 reg = (A>>13)&3;
|
||||
if(reg == 0) {
|
||||
bios_prg = V;
|
||||
} else {
|
||||
rom_prg = V;
|
||||
rom_mode = reg;
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMC80013BPower(void) {
|
||||
bios_prg=rom_prg=rom_mode=mirror=0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, BMC80013BWrite);
|
||||
}
|
||||
|
||||
static void BMC80013BReset(void) {
|
||||
bios_prg=rom_prg=rom_mode=mirror=0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void BMC80013B_Init(CartInfo *info) {
|
||||
info->Reset = BMC80013BReset;
|
||||
info->Power = BMC80013BPower;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
+1
-2
@@ -19,7 +19,6 @@
|
||||
*
|
||||
* Super Game (Sugar Softec) protected mapper
|
||||
* Pocahontas 2 (Unl) [U][!], etc.
|
||||
* TODO: 9in1 LION KING HANGS!
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
@@ -139,7 +138,7 @@ static DECLFW(UNL8237Write) {
|
||||
}
|
||||
|
||||
static DECLFW(UNL8237ExWrite) {
|
||||
switch (A) {
|
||||
switch (A & 0xF007) {
|
||||
case 0x5000: EXPREGS[0] = V; FixMMC3PRG(MMC3_cmd); break;
|
||||
case 0x5001: EXPREGS[1] = V; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); break;
|
||||
case 0x5007: EXPREGS[2] = V; break;
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import glob
|
||||
source_list = glob.glob('*.cpp')+glob.glob('*.c')
|
||||
|
||||
for x in range(len(source_list)):
|
||||
source_list[x] = 'boards/' + source_list[x]
|
||||
Return('source_list')
|
||||
@@ -237,13 +237,8 @@ void Mapper200_Init(CartInfo *info) {
|
||||
//------------------ Map 201 ---------------------------
|
||||
|
||||
static void M201Sync(void) {
|
||||
if (latche & 8) {
|
||||
setprg32(0x8000, latche & 3);
|
||||
setchr8(latche & 3);
|
||||
} else {
|
||||
setprg32(0x8000, 0);
|
||||
setchr8(0);
|
||||
}
|
||||
setprg32(0x8000, latche & 3);
|
||||
setchr8(latche & 3);
|
||||
}
|
||||
|
||||
void Mapper201_Init(CartInfo *info) {
|
||||
@@ -309,8 +304,14 @@ void Mapper212_Init(CartInfo *info) {
|
||||
//------------------ Map 213 ---------------------------
|
||||
|
||||
static void M213Sync(void) {
|
||||
setprg32(0x8000, (latche >> 1) & 3);
|
||||
if(latche & 0x40) {
|
||||
setprg16(0x8000, (latche & 7));
|
||||
setprg16(0xC000, (latche & 7));
|
||||
} else {
|
||||
setprg32(0x8000, (latche >> 1) & 3);
|
||||
}
|
||||
setchr8((latche >> 3) & 7);
|
||||
setmirror(((latche & 1)^((latche >> 6) & 1)) ^ 1);
|
||||
}
|
||||
|
||||
void Mapper213_Init(CartInfo *info) {
|
||||
@@ -347,6 +348,17 @@ static void M227Sync(void) {
|
||||
uint32 p = ((latche >> 2) & 0x1F) + ((latche & 0x100) >> 3);
|
||||
uint32 L = (latche >> 9) & 1;
|
||||
|
||||
// ok, according to nesdev wiki (refrenced to the nesdev dumping thread) there is a CHR write protection bit7.
|
||||
// however, this bit clearly determined a specific PRG layout for some game but does not meant to have additional
|
||||
// functionality. as I see from the menu code, it disables the chr writing before run an actual game.
|
||||
// this fix here makes happy both waixing rpgs and multigame menus at once. can't veryfy it on a hardware
|
||||
// but if I find some i'll definitly do this.
|
||||
|
||||
if ((latche & 0xF000) == 0xF000)
|
||||
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0);
|
||||
else
|
||||
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1);
|
||||
|
||||
if ((latche >> 7) & 1) {
|
||||
if (S) {
|
||||
setprg32(0x8000, p >> 1);
|
||||
|
||||
+274
-128
@@ -48,120 +48,205 @@ static SFORMAT StateRegs[] =
|
||||
#define X24C0X_READ 3
|
||||
#define X24C0X_WRITE 4
|
||||
|
||||
static uint8 x24c0x_data[256], x24c0x_state;
|
||||
static uint8 x24c0x_addr, x24c0x_word, x24c0x_latch, x24c0x_bitcount;
|
||||
static uint8 x24c0x_sda, x24c0x_scl, x24c0x_out, x24c0x_oe;
|
||||
static uint8 x24c0x_data[512];
|
||||
|
||||
static SFORMAT x24c0xStateRegs[] =
|
||||
static uint8 x24c01_state;
|
||||
static uint8 x24c01_addr, x24c01_word, x24c01_latch, x24c01_bitcount;
|
||||
static uint8 x24c01_sda, x24c01_scl, x24c01_out;
|
||||
|
||||
static uint8 x24c02_state;
|
||||
static uint8 x24c02_addr, x24c02_word, x24c02_latch, x24c02_bitcount;
|
||||
static uint8 x24c02_sda, x24c02_scl, x24c02_out;
|
||||
|
||||
static SFORMAT x24c01StateRegs[] =
|
||||
{
|
||||
{ &x24c0x_addr, 1, "ADDR" },
|
||||
{ &x24c0x_word, 1, "WORD" },
|
||||
{ &x24c0x_latch, 1, "LATC" },
|
||||
{ &x24c0x_bitcount, 1, "BITC" },
|
||||
{ &x24c0x_sda, 1, "SDA" },
|
||||
{ &x24c0x_scl, 1, "SCL" },
|
||||
{ &x24c0x_out, 1, "OUT" },
|
||||
{ &x24c0x_oe, 1, "OE" },
|
||||
{ &x24c0x_state, 1, "STAT" },
|
||||
{ &x24c01_addr, 1, "ADDR" },
|
||||
{ &x24c01_word, 1, "WORD" },
|
||||
{ &x24c01_latch, 1, "LATC" },
|
||||
{ &x24c01_bitcount, 1, "BITC" },
|
||||
{ &x24c01_sda, 1, "SDA" },
|
||||
{ &x24c01_scl, 1, "SCL" },
|
||||
{ &x24c01_out, 1, "OUT" },
|
||||
{ &x24c01_state, 1, "STAT" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void x24c0x_init() {
|
||||
x24c0x_addr = x24c0x_word = x24c0x_latch = x24c0x_bitcount = x24c0x_sda = x24c0x_scl = x24c0x_oe = 0;
|
||||
x24c0x_state = X24C0X_STANDBY;
|
||||
static SFORMAT x24c02StateRegs[] =
|
||||
{
|
||||
{ &x24c02_addr, 1, "ADDR" },
|
||||
{ &x24c02_word, 1, "WORD" },
|
||||
{ &x24c02_latch, 1, "LATC" },
|
||||
{ &x24c02_bitcount, 1, "BITC" },
|
||||
{ &x24c02_sda, 1, "SDA" },
|
||||
{ &x24c02_scl, 1, "SCL" },
|
||||
{ &x24c02_out, 1, "OUT" },
|
||||
{ &x24c02_state, 1, "STAT" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void x24c01_init() {
|
||||
x24c01_addr = x24c01_word = x24c01_latch = x24c01_bitcount = x24c01_sda = x24c01_scl = 0;
|
||||
x24c01_state = X24C0X_STANDBY;
|
||||
}
|
||||
|
||||
static void x24c0x_write(uint8 data) {
|
||||
uint8 sda = (data >> 6) & 1;
|
||||
uint8 scl = (data >> 5) & 1;
|
||||
x24c0x_oe = (data >> 7);
|
||||
static void x24c02_init() {
|
||||
x24c02_addr = x24c02_word = x24c02_latch = x24c02_bitcount = x24c02_sda = x24c02_scl = 0;
|
||||
x24c02_state = X24C0X_STANDBY;
|
||||
}
|
||||
|
||||
if(x24c0x_scl && scl) {
|
||||
if(x24c0x_sda && !sda) { // START
|
||||
x24c0x_state = X24C0X_ADDRESS;
|
||||
x24c0x_bitcount = 0;
|
||||
x24c0x_addr = 0;
|
||||
} else if(!x24c0x_sda && sda) { //STOP
|
||||
x24c0x_state = X24C0X_STANDBY;
|
||||
static void x24c01_write(uint8 data) {
|
||||
uint8 scl = (data >> 5) & 1;
|
||||
uint8 sda = (data >> 6) & 1;
|
||||
|
||||
if(x24c01_scl && scl) {
|
||||
if(x24c01_sda && !sda) { // START
|
||||
x24c01_state = X24C0X_ADDRESS;
|
||||
x24c01_bitcount = 0;
|
||||
x24c01_addr = 0;
|
||||
} else if(!x24c01_sda && sda) { //STOP
|
||||
x24c01_state = X24C0X_STANDBY;
|
||||
}
|
||||
} else if(!x24c0x_scl && scl) { // RISING EDGE
|
||||
switch(x24c0x_state) {
|
||||
} else if(!x24c01_scl && scl) { // RISING EDGE
|
||||
switch(x24c01_state) {
|
||||
case X24C0X_ADDRESS:
|
||||
if(x24c0x_bitcount < 7) {
|
||||
x24c0x_addr <<= 1;
|
||||
x24c0x_addr |= sda;
|
||||
if(x24c01_bitcount < 7) {
|
||||
x24c01_addr <<= 1;
|
||||
x24c01_addr |= sda;
|
||||
} else {
|
||||
if(!x24c02) // X24C01 mode
|
||||
x24c0x_word = x24c0x_addr;
|
||||
if(sda) { // READ COMMAND
|
||||
x24c0x_state = X24C0X_READ;
|
||||
} else { // WRITE COMMAND
|
||||
if(x24c02) // X24C02 mode
|
||||
x24c0x_state = X24C0X_WORD;
|
||||
else
|
||||
x24c0x_state = X24C0X_WRITE;
|
||||
}
|
||||
x24c01_word = x24c01_addr;
|
||||
if(sda) // READ COMMAND
|
||||
x24c01_state = X24C0X_READ;
|
||||
else // WRITE COMMAND
|
||||
x24c01_state = X24C0X_WRITE;
|
||||
}
|
||||
x24c0x_bitcount++;
|
||||
break;
|
||||
case X24C0X_WORD:
|
||||
if(x24c0x_bitcount == 8) { // ACK
|
||||
x24c0x_word = 0;
|
||||
x24c0x_out = 0;
|
||||
} else { // WORD ADDRESS INPUT
|
||||
x24c0x_word <<= 1;
|
||||
x24c0x_word |= sda;
|
||||
if(x24c0x_bitcount == 16) { // END OF ADDRESS INPUT
|
||||
x24c0x_bitcount = 7;
|
||||
x24c0x_state = X24C0X_WRITE;
|
||||
}
|
||||
}
|
||||
x24c0x_bitcount++;
|
||||
x24c01_bitcount++;
|
||||
break;
|
||||
case X24C0X_READ:
|
||||
if (x24c0x_bitcount == 8) { // ACK
|
||||
x24c0x_out = 0;
|
||||
x24c0x_latch = x24c0x_data[x24c0x_word];
|
||||
x24c0x_bitcount = 0;
|
||||
} else { // REAL OUTPUT
|
||||
x24c0x_out = x24c0x_latch >> 7;
|
||||
x24c0x_latch <<= 1;
|
||||
x24c0x_bitcount++;
|
||||
if(x24c0x_bitcount == 8) {
|
||||
x24c0x_word++;
|
||||
x24c0x_word &= 0xff;
|
||||
if (x24c01_bitcount == 8) { // ACK
|
||||
x24c01_out = 0;
|
||||
x24c01_latch = x24c0x_data[x24c01_word];
|
||||
x24c01_bitcount = 0;
|
||||
} else { // REAL OUTPUT
|
||||
x24c01_out = x24c01_latch >> 7;
|
||||
x24c01_latch <<= 1;
|
||||
x24c01_bitcount++;
|
||||
if(x24c01_bitcount == 8) {
|
||||
x24c01_word++;
|
||||
x24c01_word &= 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case X24C0X_WRITE:
|
||||
if (x24c0x_bitcount == 8) { // ACK
|
||||
x24c0x_out = 0;
|
||||
x24c0x_latch = 0;
|
||||
x24c0x_bitcount = 0;
|
||||
} else { // REAL INPUT
|
||||
x24c0x_latch <<= 1;
|
||||
x24c0x_latch |= sda;
|
||||
x24c0x_bitcount++;
|
||||
if(x24c0x_bitcount == 8) {
|
||||
x24c0x_data[x24c0x_word] = x24c0x_latch;
|
||||
x24c0x_word++;
|
||||
x24c0x_word &= 0xff;
|
||||
if (x24c01_bitcount == 8) { // ACK
|
||||
x24c01_out = 0;
|
||||
x24c01_latch = 0;
|
||||
x24c01_bitcount = 0;
|
||||
} else { // REAL INPUT
|
||||
x24c01_latch <<= 1;
|
||||
x24c01_latch |= sda;
|
||||
x24c01_bitcount++;
|
||||
if(x24c01_bitcount == 8) {
|
||||
x24c0x_data[x24c01_word] = x24c01_latch;
|
||||
x24c01_word++;
|
||||
x24c01_word &= 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
x24c0x_sda = sda;
|
||||
x24c0x_scl = scl;
|
||||
x24c01_sda = sda;
|
||||
x24c01_scl = scl;
|
||||
}
|
||||
|
||||
static uint8 x24c0x_read() {
|
||||
return x24c0x_out << 4;
|
||||
static void x24c02_write(uint8 data) {
|
||||
uint8 scl = (data >> 5) & 1;
|
||||
uint8 sda = (data >> 6) & 1;
|
||||
|
||||
if (x24c02_scl && scl) {
|
||||
if (x24c02_sda && !sda) { // START
|
||||
x24c02_state = X24C0X_ADDRESS;
|
||||
x24c02_bitcount = 0;
|
||||
x24c02_addr = 0;
|
||||
} else if (!x24c02_sda && sda) { //STOP
|
||||
x24c02_state = X24C0X_STANDBY;
|
||||
}
|
||||
} else if (!x24c02_scl && scl) { // RISING EDGE
|
||||
switch (x24c02_state) {
|
||||
case X24C0X_ADDRESS:
|
||||
if (x24c02_bitcount < 7) {
|
||||
x24c02_addr <<= 1;
|
||||
x24c02_addr |= sda;
|
||||
} else {
|
||||
if (sda) // READ COMMAND
|
||||
x24c02_state = X24C0X_READ;
|
||||
else // WRITE COMMAND
|
||||
x24c02_state = X24C0X_WORD;
|
||||
}
|
||||
x24c02_bitcount++;
|
||||
break;
|
||||
case X24C0X_WORD:
|
||||
if (x24c02_bitcount == 8) { // ACK
|
||||
x24c02_word = 0;
|
||||
x24c02_out = 0;
|
||||
} else { // WORD ADDRESS INPUT
|
||||
x24c02_word <<= 1;
|
||||
x24c02_word |= sda;
|
||||
if (x24c02_bitcount == 16) {// END OF ADDRESS INPUT
|
||||
x24c02_bitcount = 7;
|
||||
x24c02_state = X24C0X_WRITE;
|
||||
}
|
||||
}
|
||||
x24c02_bitcount++;
|
||||
break;
|
||||
case X24C0X_READ:
|
||||
if (x24c02_bitcount == 8) { // ACK
|
||||
x24c02_out = 0;
|
||||
x24c02_latch = x24c0x_data[x24c02_word|0x100];
|
||||
x24c02_bitcount = 0;
|
||||
} else { // REAL OUTPUT
|
||||
x24c02_out = x24c02_latch >> 7;
|
||||
x24c02_latch <<= 1;
|
||||
x24c02_bitcount++;
|
||||
if (x24c02_bitcount == 8) {
|
||||
x24c02_word++;
|
||||
x24c02_word &= 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case X24C0X_WRITE:
|
||||
if (x24c02_bitcount == 8) { // ACK
|
||||
x24c02_out = 0;
|
||||
x24c02_latch = 0;
|
||||
x24c02_bitcount = 0;
|
||||
} else { // REAL INPUT
|
||||
x24c02_latch <<= 1;
|
||||
x24c02_latch |= sda;
|
||||
x24c02_bitcount++;
|
||||
if (x24c02_bitcount == 8) {
|
||||
x24c0x_data[x24c02_word|0x100] = x24c02_latch;
|
||||
x24c02_word++;
|
||||
x24c02_word &= 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
x24c02_sda = sda;
|
||||
x24c02_scl = scl;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
static void SyncMirror(void) {
|
||||
switch (reg[9] & 3) {
|
||||
case 0: setmirror(MI_V); break;
|
||||
case 1: setmirror(MI_H); break;
|
||||
case 2: setmirror(MI_0); break;
|
||||
case 3: setmirror(MI_1); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Sync(void) {
|
||||
if (is153) {
|
||||
int base = (reg[0] & 1) << 4;
|
||||
@@ -174,12 +259,7 @@ static void Sync(void) {
|
||||
setprg16(0x8000, reg[8]);
|
||||
setprg16(0xC000, ~0);
|
||||
}
|
||||
switch (reg[9] & 3) {
|
||||
case 0: setmirror(MI_V); break;
|
||||
case 1: setmirror(MI_H); break;
|
||||
case 2: setmirror(MI_0); break;
|
||||
case 3: setmirror(MI_1); break;
|
||||
}
|
||||
SyncMirror();
|
||||
}
|
||||
|
||||
static DECLFW(BandaiWrite) {
|
||||
@@ -192,12 +272,15 @@ static DECLFW(BandaiWrite) {
|
||||
case 0x0A: X6502_IRQEnd(FCEU_IQEXT); IRQa = V & 1; IRQCount = IRQLatch; break;
|
||||
case 0x0B: IRQLatch &= 0xFF00; IRQLatch |= V; break;
|
||||
case 0x0C: IRQLatch &= 0xFF; IRQLatch |= V << 8; break;
|
||||
case 0x0D: x24c0x_write(V); break;
|
||||
case 0x0D: if(x24c02) x24c02_write(V); else x24c01_write(V); break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(BandaiRead) {
|
||||
return (X.DB & 0xEF) | x24c0x_read();
|
||||
if(x24c02)
|
||||
return (X.DB & 0xEF) | (x24c02_out << 4);
|
||||
else
|
||||
return (X.DB & 0xEF) | (x24c01_out << 4);
|
||||
}
|
||||
|
||||
static void BandaiIRQHook(int a) {
|
||||
@@ -213,7 +296,10 @@ static void BandaiIRQHook(int a) {
|
||||
|
||||
static void BandaiPower(void) {
|
||||
IRQa = 0;
|
||||
x24c0x_init();
|
||||
if(x24c02)
|
||||
x24c02_init();
|
||||
else
|
||||
x24c01_init();
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0x7FFF, BandaiRead);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
@@ -231,12 +317,12 @@ void Mapper16_Init(CartInfo *info) {
|
||||
MapIRQHook = BandaiIRQHook;
|
||||
|
||||
info->battery = 1;
|
||||
info->SaveGame[0] = x24c0x_data;
|
||||
info->SaveGame[0] = x24c0x_data + 256;
|
||||
info->SaveGameLen[0] = 256;
|
||||
AddExState(x24c0x_data, 256, 0, "DATA");
|
||||
AddExState(&x24c02StateRegs, ~0, 0, 0);
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&x24c0xStateRegs, ~0, 0, 0);
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -250,9 +336,9 @@ void Mapper159_Init(CartInfo *info) {
|
||||
info->SaveGame[0] = x24c0x_data;
|
||||
info->SaveGameLen[0] = 128;
|
||||
AddExState(x24c0x_data, 128, 0, "DATA");
|
||||
AddExState(&x24c01StateRegs, ~0, 0, 0);
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&x24c0xStateRegs, ~0, 0, 0);
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -307,7 +393,9 @@ static int BarcodeReadPos;
|
||||
static int BarcodeCycleCount;
|
||||
static uint32 BarcodeOut;
|
||||
|
||||
int FCEUI_DatachSet(const uint8 *rcode) {
|
||||
// #define INTERL2OF5
|
||||
|
||||
int FCEUI_DatachSet(uint8 *rcode) {
|
||||
int prefix_parity_type[10][6] = {
|
||||
{ 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 1, 1 }, { 0, 0, 1, 1, 0, 1 }, { 0, 0, 1, 1, 1, 0 },
|
||||
{ 0, 1, 0, 0, 1, 1 }, { 0, 1, 1, 0, 0, 1 }, { 0, 1, 1, 1, 0, 0 }, { 0, 1, 0, 1, 0, 1 },
|
||||
@@ -330,6 +418,7 @@ int FCEUI_DatachSet(const uint8 *rcode) {
|
||||
};
|
||||
uint8 code[13 + 1];
|
||||
uint32 tmp_p = 0;
|
||||
uint32 csum = 0;
|
||||
int i, j;
|
||||
int len;
|
||||
|
||||
@@ -341,18 +430,46 @@ int FCEUI_DatachSet(const uint8 *rcode) {
|
||||
}
|
||||
if (len != 13 && len != 12 && len != 8 && len != 7) return(0);
|
||||
|
||||
#define BS(x) BarcodeData[tmp_p] = x; tmp_p++
|
||||
#define BS(x) BarcodeData[tmp_p] = x; tmp_p++
|
||||
|
||||
for (j = 0; j < 32; j++) {
|
||||
for (j = 0; j < 32; j++) { // delay before sending a code
|
||||
BS(0x00);
|
||||
}
|
||||
|
||||
/* Left guard bars */
|
||||
#ifdef INTERL2OF5
|
||||
|
||||
BS(1); BS(1); BS(0); BS(0); // 1
|
||||
BS(1); BS(1); BS(0); BS(0); // 1
|
||||
BS(1); BS(1); BS(0); BS(0); // 1
|
||||
BS(1); BS(1); BS(0); BS(0); // 1
|
||||
BS(1); BS(1); BS(0); BS(0); // 1
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0 cs
|
||||
BS(1); BS(1); BS(0); BS(0); // 1
|
||||
|
||||
#else
|
||||
// Left guard bars
|
||||
BS(1); BS(0); BS(1);
|
||||
|
||||
if (len == 13 || len == 12) {
|
||||
uint32 csum;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
if (prefix_parity_type[code[0]][i]) {
|
||||
for (j = 0; j < 7; j++) {
|
||||
@@ -362,53 +479,53 @@ int FCEUI_DatachSet(const uint8 *rcode) {
|
||||
for (j = 0; j < 7; j++) {
|
||||
BS(data_left_odd[code[i + 1]][j]);
|
||||
}
|
||||
|
||||
/* Center guard bars */
|
||||
// Center guard bars
|
||||
BS(0); BS(1); BS(0); BS(1); BS(0);
|
||||
|
||||
for (i = 7; i < 12; i++)
|
||||
for (j = 0; j < 7; j++) {
|
||||
BS(data_right[code[i]][j]);
|
||||
}
|
||||
csum = 0;
|
||||
for (i = 0; i < 12; i++) csum += code[i] * ((i & 1) ? 3 : 1);
|
||||
csum = (10 - (csum % 10)) % 10;
|
||||
// Calc and write down the control code if not assigned, instead, send code as is
|
||||
// Battle Rush uses modified type of codes with different control code calculation
|
||||
if (len == 12) {
|
||||
for (i = 0; i < 12; i++)
|
||||
csum += code[i] * ((i & 1) ? 3 : 1);
|
||||
csum = (10 - (csum % 10)) % 10;
|
||||
rcode[12] = csum + 0x30; // update check code to the input string as well
|
||||
rcode[13] = 0;
|
||||
code[12] = csum;
|
||||
}
|
||||
for (j = 0; j < 7; j++) {
|
||||
BS(data_right[csum][j]);
|
||||
BS(data_right[code[12]][j]);
|
||||
}
|
||||
} else if (len == 8 || len == 7) {
|
||||
uint32 csum = 0;
|
||||
|
||||
for (i = 0; i < 7; i++) csum += (i & 1) ? code[i] : (code[i] * 3);
|
||||
|
||||
csum = (10 - (csum % 10)) % 10;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 7; j++) {
|
||||
BS(data_left_odd[code[i]][j]);
|
||||
}
|
||||
|
||||
|
||||
/* Center guard bars */
|
||||
// Center guard bars
|
||||
BS(0); BS(1); BS(0); BS(1); BS(0);
|
||||
|
||||
for (i = 4; i < 7; i++)
|
||||
for (j = 0; j < 7; j++) {
|
||||
BS(data_right[code[i]][j]);
|
||||
}
|
||||
|
||||
csum = 0;
|
||||
for (i = 0; i < 7; i++)
|
||||
csum += (i & 1) ? code[i] : (code[i] * 3);
|
||||
csum = (10 - (csum % 10)) % 10;
|
||||
rcode[7] = csum + 0x30; // update check code to the input string as well
|
||||
rcode[8] = 0;
|
||||
for (j = 0; j < 7; j++) {
|
||||
BS(data_right[csum][j]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Right guard bars */
|
||||
// Right guard bars
|
||||
BS(1); BS(0); BS(1);
|
||||
#endif
|
||||
|
||||
for (j = 0; j < 32; j++) {
|
||||
BS(0x00);
|
||||
}
|
||||
|
||||
BS(0xFF);
|
||||
|
||||
#undef BS
|
||||
@@ -419,6 +536,26 @@ int FCEUI_DatachSet(const uint8 *rcode) {
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void BarcodeSync(void) {
|
||||
setchr8(0);
|
||||
setprg16(0x8000, (reg[8] & 0x0F));
|
||||
setprg16(0xC000, 0x0F);
|
||||
SyncMirror();
|
||||
}
|
||||
|
||||
static DECLFW(BarcodeWrite) {
|
||||
A &= 0x0F;
|
||||
switch (A) {
|
||||
case 0x00: reg[0] = (V & 8) << 2; x24c01_write(reg[0xD] | reg[0]); break; // extra EEPROM x24C01 used in Battle Rush mini-cart
|
||||
case 0x08:
|
||||
case 0x09: reg[A] = V; BarcodeSync(); break;
|
||||
case 0x0A: X6502_IRQEnd(FCEU_IQEXT); IRQa = V & 1; IRQCount = IRQLatch; break;
|
||||
case 0x0B: IRQLatch &= 0xFF00; IRQLatch |= V; break;
|
||||
case 0x0C: IRQLatch &= 0xFF; IRQLatch |= V << 8; break;
|
||||
case 0x0D: reg[0xD] = V & (~0x20); x24c01_write(reg[0xD] | reg[0]); x24c02_write(V); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void BarcodeIRQHook(int a) {
|
||||
BandaiIRQHook(a);
|
||||
|
||||
@@ -436,7 +573,7 @@ static void BarcodeIRQHook(int a) {
|
||||
}
|
||||
|
||||
static DECLFR(BarcodeRead) {
|
||||
return BarcodeOut;
|
||||
return (X.DB & 0xE7) | ((x24c02_out | x24c01_out) << 4) | BarcodeOut;
|
||||
}
|
||||
|
||||
static void M157Power(void) {
|
||||
@@ -446,20 +583,29 @@ static void M157Power(void) {
|
||||
BarcodeOut = 0;
|
||||
BarcodeCycleCount = 0;
|
||||
|
||||
Sync();
|
||||
x24c01_init();
|
||||
x24c02_init();
|
||||
BarcodeSync();
|
||||
|
||||
SetWriteHandler(0x6000, 0xFFFF, BandaiWrite);
|
||||
SetReadHandler(0x6000, 0x7FFF, BarcodeRead);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, BarcodeWrite);
|
||||
}
|
||||
|
||||
void Mapper157_Init(CartInfo *info) {
|
||||
is153 = 1;
|
||||
x24c02 = 1;
|
||||
info->Power = M157Power;
|
||||
MapIRQHook = BarcodeIRQHook;
|
||||
|
||||
GameInfo->cspecial = SIS_DATACH;
|
||||
info->battery = 1;
|
||||
info->SaveGame[0] = x24c0x_data;
|
||||
info->SaveGameLen[0] = 512;
|
||||
AddExState(x24c0x_data, 512, 0, "DATA");
|
||||
AddExState(&x24c01StateRegs, ~0, 0, 0);
|
||||
AddExState(&x24c02StateRegs, ~0, 0, 0);
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -84,12 +84,12 @@ byte_8C29: .BYTE 0,$76, 0, 0, 8
|
||||
byte_8CC6: .BYTE 0,$78, 0, 0,$12
|
||||
*/
|
||||
|
||||
static uint8 sim0reset[0x1F] = {
|
||||
0x3B, 0xE9, 0x00, 0xFF, 0xC1, 0x10, 0x31, 0xFE,
|
||||
0x55, 0xC8, 0x10, 0x20, 0x55, 0x47, 0x4F, 0x53,
|
||||
0x56, 0x53, 0x43, 0xAD, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
|
||||
};
|
||||
//static uint8 sim0reset[0x1F] = {
|
||||
// 0x3B, 0xE9, 0x00, 0xFF, 0xC1, 0x10, 0x31, 0xFE,
|
||||
// 0x55, 0xC8, 0x10, 0x20, 0x55, 0x47, 0x4F, 0x53,
|
||||
// 0x56, 0x53, 0x43, 0xAD, 0x10, 0x10, 0x10, 0x10,
|
||||
// 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
|
||||
//};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg32(0x8000, prg_reg);
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Double Dragon 310000-in-1 (4040R)
|
||||
* 700000-in-1 (BS-400R)(Unl)
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 pointer;
|
||||
static uint8 offset;
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
|
||||
static int getPRGBankBS4XXXR(int bank)
|
||||
{
|
||||
if (((~bank) & 1) && (pointer & 0x40))
|
||||
bank ^= 2;
|
||||
return (bank & 2) ? (0xFE | (bank & 1)) : EXPREGS[4 | (bank & 1)];
|
||||
}
|
||||
|
||||
static void BS4XXXRPW(uint32 A, uint8 V) {
|
||||
|
||||
if ((EXPREGS[3] >> 4) & 0x01)
|
||||
{
|
||||
int AND = ((EXPREGS[0] >> 1) & 1) ? 0x0F : 0x0F;
|
||||
int OR = (EXPREGS[0] & 7) << 4;
|
||||
int bank0 = getPRGBankBS4XXXR(0);
|
||||
int bank1 = getPRGBankBS4XXXR(1);
|
||||
if (!((EXPREGS[3] >> 1) & 1)) //16K Mode
|
||||
{
|
||||
setprg8(0x8000, ((bank0) & AND) | OR);
|
||||
setprg8(0xA000, ((bank1) & AND) | OR);
|
||||
setprg8(0xC000, ((bank0) & AND) | OR);
|
||||
setprg8(0xE000, ((bank1) & AND) | OR);
|
||||
}
|
||||
else // 32K Mode
|
||||
{
|
||||
setprg8(0x8000, ((bank0) & AND) | OR);
|
||||
setprg8(0xA000, ((bank1) & AND) | OR);
|
||||
setprg8(0xC000, ((bank0 | 2) & AND) | OR);
|
||||
setprg8(0xE000, ((bank1 | 2) & AND) | OR);
|
||||
}
|
||||
}
|
||||
else // MMC3 Mode
|
||||
{
|
||||
int prgAND = ((EXPREGS[0] >> offset) & 1) ? 0x0F : 0x1F;
|
||||
int prgOR = (EXPREGS[0] & 7) << 4;
|
||||
setprg8(A, (V & prgAND) | (prgOR));
|
||||
}
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
}
|
||||
|
||||
static void BS4XXXRCW(uint32 A, uint8 V) {
|
||||
if ((EXPREGS[3] >> 4) & 1)
|
||||
{
|
||||
int AND = ((EXPREGS[0] >> 1) & 1) ? 0x0F : 0x0F;
|
||||
int bank = EXPREGS[2] & AND;
|
||||
int chrOR = ((EXPREGS[0] >> 3) & 7) << 4;
|
||||
setchr8((bank) | (chrOR));
|
||||
}
|
||||
else
|
||||
{
|
||||
int chrAND = ((EXPREGS[0] >> 1) & 1) ? 0xFF : 0xFF;
|
||||
int chrOR = ((EXPREGS[0] >> 3) & 7) << 7;
|
||||
setchr1(A, (V & chrAND) | (chrOR));
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(BS4XXXRHiWrite) {
|
||||
// FCEU_printf("w: %04x-%02x\n",A,V)
|
||||
if (A==0x8000)
|
||||
{
|
||||
pointer = MMC3_cmd ^ V;
|
||||
}
|
||||
else if (A == 0x8001)
|
||||
{
|
||||
if((MMC3_cmd & 7) > 5)
|
||||
EXPREGS[4|(MMC3_cmd & 1)] = V;
|
||||
}
|
||||
MMC3_CMDWrite(A, V);
|
||||
}
|
||||
|
||||
static DECLFW(BS4XXXRLoWrite) {
|
||||
// FCEU_printf("w: %04x-%02x\n", A, V);
|
||||
if (A & 0x800)
|
||||
{
|
||||
if (!(EXPREGS[3] & 0x80)) {
|
||||
EXPREGS[A & 0x03] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
else if (EXPREGS[3] & 0x10)
|
||||
{
|
||||
EXPREGS[A & 0x03] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
else
|
||||
WRAM[A - 0x6000] = V;
|
||||
}
|
||||
else
|
||||
WRAM[A - 0x6000] = V;
|
||||
}
|
||||
|
||||
|
||||
static void BSXXXXRPower(void) {
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = EXPREGS[4] = EXPREGS[5] = 0;
|
||||
GenMMC3Power();
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, BS4XXXRLoWrite);
|
||||
SetWriteHandler(0x8000, 0x9FFF, BS4XXXRHiWrite);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void BS4XXXRClose(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
void BSXXXXR_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap = BS4XXXRCW;
|
||||
pwrap = BS4XXXRPW;
|
||||
|
||||
info->Power = BSXXXXRPower;
|
||||
info->Close = BS4XXXRClose;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
}
|
||||
|
||||
void BS400R_Init(CartInfo *info) {
|
||||
offset = 1;
|
||||
BSXXXXR_Init(info);
|
||||
}
|
||||
|
||||
void BS4040R_Init(CartInfo *info) {
|
||||
offset = 6;
|
||||
BSXXXXR_Init(info);
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
// mapper 111 - Cheapocabra board by Memblers
|
||||
// http://forums.nesdev.com/viewtopic.php?p=146039
|
||||
//
|
||||
// 512k PRG-ROM in 32k pages (flashable if battery backed is specified)
|
||||
// 32k CHR-RAM used as:
|
||||
// 2 x 8k pattern pages
|
||||
// 2 x 8k nametable pages
|
||||
//
|
||||
// Notes:
|
||||
// - CHR-RAM for nametables maps to $3000-3FFF as well, but FCEUX internally mirrors to 4k?
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "../ines.h"
|
||||
|
||||
static uint8 reg;
|
||||
static uint8 *CHRRAM = NULL;
|
||||
const uint32 CHRRAMSIZE = 1024 * 32;
|
||||
|
||||
static bool flash = false;
|
||||
static uint8 flash_mode;
|
||||
static uint8 flash_sequence;
|
||||
static uint8 flash_id;
|
||||
static uint8 *FLASHROM = NULL;
|
||||
const uint32 FLASHROMSIZE = 1024 * 512;
|
||||
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ ®, 1, "REG" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static SFORMAT FlashRegs[] =
|
||||
{
|
||||
{ &flash_mode, 1, "FMOD" },
|
||||
{ &flash_sequence, 1, "FSEQ" },
|
||||
{ &flash_id, 1, "FMID" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
// bit 7 controls green LED
|
||||
// bit 6 controls red LED
|
||||
int nt = (reg & 0x20) ? 8192 : 0; // bit 5 controls 8k nametable page
|
||||
int chr = (reg & 0x10) ? 1 : 0; // bit 4 selects 8k CHR page
|
||||
int prg = (reg & 0x0F); // bits 0-3 select 32k PRG page
|
||||
|
||||
nt += (16 * 1024);
|
||||
for (int n=0; n<4; ++n)
|
||||
{
|
||||
setntamem(CHRRAM + nt + (1024 * n),1,n);
|
||||
}
|
||||
setchr8r(0x10, chr);
|
||||
|
||||
uint32 prg_chip = flash ? 0x10 : 0;
|
||||
setprg32r(prg_chip,0x8000,prg);
|
||||
}
|
||||
|
||||
static DECLFW(M111Write) {
|
||||
if ((A >= 0x5000 && A <= 0x5FFF) || (A >= 0x7000 && A <= 0x7FFF))
|
||||
{
|
||||
reg = V;
|
||||
Sync();
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(M111FlashID)
|
||||
{
|
||||
// Software ID mode is undefined by the datasheet for all but the lowest 2 addressable bytes,
|
||||
// but some tests of the chip currently being used found it repeats in 512-byte patterns.
|
||||
// http://forums.nesdev.com/viewtopic.php?p=178728#p178728
|
||||
|
||||
uint32 aid = A & 0x1FF;
|
||||
switch (aid)
|
||||
{
|
||||
case 0: return 0xBF;
|
||||
case 1: return 0xB7;
|
||||
default: return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void M111FlashIDEnter()
|
||||
{
|
||||
if (flash_id) return;
|
||||
flash_id = 1;
|
||||
SetReadHandler(0x8000,0xFFFF,M111FlashID);
|
||||
}
|
||||
|
||||
void M111FlashIDExit()
|
||||
{
|
||||
if (!flash_id) return;
|
||||
flash_id = 0;
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
}
|
||||
|
||||
static DECLFW(M111Flash) {
|
||||
if (A < 0x8000 || A > 0xFFFF) return;
|
||||
|
||||
uint32 flash_addr = ((reg & 0x0F) << 15) | (A & 0x7FFF);
|
||||
uint32 command_addr = flash_addr & 0x7FFF;
|
||||
|
||||
enum
|
||||
{
|
||||
FLASH_MODE_READY = 0,
|
||||
FLASH_MODE_COMMAND,
|
||||
FLASH_MODE_BYTE_WRITE,
|
||||
FLASH_MODE_ERASE,
|
||||
};
|
||||
|
||||
switch (flash_mode)
|
||||
{
|
||||
default:
|
||||
case FLASH_MODE_READY:
|
||||
if (command_addr == 0x5555 && V == 0xAA)
|
||||
{
|
||||
flash_mode = FLASH_MODE_COMMAND;
|
||||
flash_sequence = 0;
|
||||
}
|
||||
else if (V == 0xF0)
|
||||
{
|
||||
M111FlashIDExit();
|
||||
}
|
||||
break;
|
||||
case FLASH_MODE_COMMAND:
|
||||
if (flash_sequence == 0)
|
||||
{
|
||||
if (command_addr == 0x2AAA && V == 0x55)
|
||||
flash_sequence = 1;
|
||||
else
|
||||
flash_mode = FLASH_MODE_READY;
|
||||
}
|
||||
else if (flash_sequence == 1)
|
||||
{
|
||||
if (command_addr == 0x5555)
|
||||
{
|
||||
flash_sequence = 0;
|
||||
switch (V)
|
||||
{
|
||||
default: flash_mode = FLASH_MODE_READY; break;
|
||||
case 0xA0: flash_mode = FLASH_MODE_BYTE_WRITE; break;
|
||||
case 0x80: flash_mode = FLASH_MODE_ERASE; break;
|
||||
case 0x90: M111FlashIDEnter(); flash_mode = FLASH_MODE_READY; break;
|
||||
case 0xF0: M111FlashIDExit(); flash_mode = FLASH_MODE_READY; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
flash_mode = FLASH_MODE_READY;
|
||||
}
|
||||
else
|
||||
flash_mode = FLASH_MODE_READY; // should be unreachable
|
||||
break;
|
||||
case FLASH_MODE_BYTE_WRITE:
|
||||
FLASHROM[flash_addr] &= V;
|
||||
flash_mode = FLASH_MODE_READY;
|
||||
break;
|
||||
case FLASH_MODE_ERASE:
|
||||
if (flash_sequence == 0)
|
||||
{
|
||||
if (command_addr == 0x5555 && V == 0xAA)
|
||||
flash_sequence = 1;
|
||||
else
|
||||
flash_mode = FLASH_MODE_READY;
|
||||
}
|
||||
else if (flash_sequence == 1)
|
||||
{
|
||||
if (command_addr == 0x2AAA && V == 0x55)
|
||||
flash_sequence = 2;
|
||||
else
|
||||
flash_mode = FLASH_MODE_READY;
|
||||
}
|
||||
else if (flash_sequence == 2)
|
||||
{
|
||||
if (command_addr == 0x5555 && V == 0x10) // erase chip
|
||||
{
|
||||
memset(FLASHROM, 0xFF, FLASHROMSIZE);
|
||||
}
|
||||
else if (V == 0x30) // erase 4k sector
|
||||
{
|
||||
uint32 sector = flash_addr & 0x7F000;
|
||||
memset(FLASHROM + sector, 0xFF, 1024 * 4);
|
||||
}
|
||||
flash_mode = FLASH_MODE_READY;
|
||||
}
|
||||
else
|
||||
flash_mode = FLASH_MODE_READY; // should be unreachable
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void M111Power(void) {
|
||||
reg = 0xFF;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x5000, 0x5fff, M111Write);
|
||||
SetWriteHandler(0x7000, 0x7fff, M111Write);
|
||||
|
||||
if (flash)
|
||||
{
|
||||
flash_mode = 0;
|
||||
flash_sequence = 0;
|
||||
flash_id = false;
|
||||
SetWriteHandler(0x8000, 0xFFFF, M111Flash);
|
||||
}
|
||||
}
|
||||
|
||||
static void M111Close(void) {
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
|
||||
if (FLASHROM)
|
||||
FCEU_gfree(FLASHROM);
|
||||
FLASHROM = NULL;
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper111_Init(CartInfo *info) {
|
||||
info->Power = M111Power;
|
||||
info->Close = M111Close;
|
||||
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM");
|
||||
|
||||
flash = (info->battery != 0);
|
||||
if (flash)
|
||||
{
|
||||
FLASHROM = (uint8*)FCEU_gmalloc(FLASHROMSIZE);
|
||||
info->SaveGame[0] = FLASHROM;
|
||||
info->SaveGameLen[0] = FLASHROMSIZE;
|
||||
AddExState(FLASHROM, FLASHROMSIZE, 0, "FROM");
|
||||
AddExState(&FlashRegs, ~0, 0, 0);
|
||||
|
||||
// copy PRG ROM into FLASHROM, use it instead of PRG ROM
|
||||
const uint32 PRGSIZE = ROM_size * 16 * 1024;
|
||||
for (uint32 w=0, r=0; w<FLASHROMSIZE; ++w)
|
||||
{
|
||||
FLASHROM[w] = ROM[r];
|
||||
++r;
|
||||
if (r >= PRGSIZE) r = 0;
|
||||
}
|
||||
SetupCartPRGMapping(0x10, FLASHROM, FLASHROMSIZE, 0);
|
||||
}
|
||||
}
|
||||
+91
-24
@@ -1,7 +1,7 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2015 CaH4e3, ClusteR
|
||||
* Copyright (C) 2018 CaH4e3, Cluster
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,15 +17,60 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* CoolBoy 400-in-1 FK23C-mimic mapper 16Mb/32Mb PROM + 128K/256K CHR RAM, optional SRAM, optional NTRAM
|
||||
* only MMC3 mode
|
||||
* SMD132 and SMD133 ASICs, MMC3 clones that can address up to 32 MiB of PRG-ROM, 256 KiB of CHR-RAM, and 8 KiB of WRAM.
|
||||
*
|
||||
* 6000 (xx76x210) | 0xC0
|
||||
* 6001 (xxx354x)
|
||||
* 6002 = 0
|
||||
* 6003 = 0
|
||||
* COOLBOY cartridges use registers at address $6xxx
|
||||
* MINDKIDS cartridges use a solder pad labelled "5/6K" to select between $5000 and $6000
|
||||
*
|
||||
* $xxx0
|
||||
* 7 bit 0
|
||||
* ---- ----
|
||||
* ABCC DEEE
|
||||
* |||| ||||
|
||||
* |||| |+++-- PRG offset (PRG A19, A18, A17)
|
||||
* |||| +----- Alternate CHR A17
|
||||
* ||++------- PRG offset (PRG A24, A23)
|
||||
* |+--------- PRG mask (PRG A17 from 0: MMC3; 1: offset)
|
||||
* +---------- CHR mask (CHR A17 from 0: MMC3; 1: alternate)
|
||||
*
|
||||
* $xxx1
|
||||
*
|
||||
* 7 bit 0
|
||||
* ---- ----
|
||||
* GHIJ KKLx
|
||||
* |||| |||
|
||||
* |||| ||+--- GNROM mode bank PRG size (1: 32 KiB bank, PRG A14=CPU A14; 0: 16 KiB bank, PRG A14=offset A14)
|
||||
* |||+-++---- PRG offset (in order: PRG A20, A22, A21)
|
||||
* ||+-------- PRG mask (PRG A20 from 0: offset; 1: MMC3)
|
||||
* |+--------- PRG mask (PRG A19 from 0: offset; 1: MMC3)
|
||||
* +---------- PRG mask (PRG A18 from 0: MMC3; 1: offset)
|
||||
*
|
||||
* $xxx2
|
||||
* 7 bit 0
|
||||
* ---- ----
|
||||
* xxxx MMMM
|
||||
* ||||
|
||||
* ++++-- CHR offset for GNROM mode (CHR A16, A15, A14, A13)
|
||||
*
|
||||
* $xxx3
|
||||
* 7 bit 0
|
||||
* ---- ----
|
||||
* NPxP QQRx
|
||||
* || | |||
|
||||
* || | +++--- PRG offset for GNROM mode (PRG A16, A15, A14)
|
||||
* || +------- 1: GNROM mode; 0: MMC3 mode
|
||||
* || | (1: PRG A16...13 from QQ, L, R, CPU A14, A13 + CHR A16...10 from MMMM, PPU A12...10;
|
||||
* || | 0: PRG A16...13 from MMC3 + CHR A16...A10 from MMC3 )
|
||||
* |+-+------- Banking mode
|
||||
* |+--------- "Weird MMC3 mode"
|
||||
* +---------- Lockout (prevent further writes to these four registers, only works in MMC3 mode)
|
||||
*
|
||||
* Also some new cartridges from MINDKIDS have /WE and /OE pins connected to mapper,
|
||||
* which allows you to rewrite flash memory without soldering.
|
||||
* This also allows console to write data to the cartridge.
|
||||
* This behavior is not emulated.
|
||||
* No cart has been discovered so far that makes use of this feature, but this can be used for homebrew.
|
||||
*
|
||||
* hardware tested logic, don't try to understand lol
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
@@ -71,12 +116,7 @@ static void COOLBOYPW(uint32 A, uint8 V) {
|
||||
// Last banks are first in this mode, ignored when MMC3_cmd&0x40
|
||||
if ((EXPREGS[3] & 0x40) && (V >= 0xFE) && !((MMC3_cmd & 0x40) != 0)) {
|
||||
switch (A & 0xE000) {
|
||||
case 0xA000:
|
||||
if ((MMC3_cmd & 0x40)) V = 0;
|
||||
break;
|
||||
case 0xC000:
|
||||
if (!(MMC3_cmd & 0x40)) V = 0;
|
||||
break;
|
||||
case 0xE000:
|
||||
V = 0;
|
||||
break;
|
||||
@@ -115,10 +155,6 @@ static DECLFW(COOLBOYWrite) {
|
||||
static void COOLBOYReset(void) {
|
||||
MMC3RegReset();
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||
// EXPREGS[0] = 0;
|
||||
// EXPREGS[1] = 0x60;
|
||||
// EXPREGS[2] = 0;
|
||||
// EXPREGS[3] = 0;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
@@ -126,21 +162,52 @@ static void COOLBOYReset(void) {
|
||||
static void COOLBOYPower(void) {
|
||||
GenMMC3Power();
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||
// EXPREGS[0] = 0;
|
||||
// EXPREGS[1] = 0x60;
|
||||
// EXPREGS[2] = 0;
|
||||
// EXPREGS[3] = 0;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
SetWriteHandler(0x5000, 0x5fff, CartBW); // some games access random unmapped areas and crashes because of KT-008 PCB hack in MMC3 source lol
|
||||
SetWriteHandler(0x6000, 0x7fff, COOLBOYWrite);
|
||||
SetWriteHandler(0x6000, 0x6fff, COOLBOYWrite);
|
||||
}
|
||||
|
||||
static void MINDKIDSPower(void) {
|
||||
GenMMC3Power();
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
SetWriteHandler(0x5000, 0x5fff, COOLBOYWrite);
|
||||
}
|
||||
|
||||
// Registers at $6xxx
|
||||
void COOLBOY_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
GenMMC3_Init(info, 2048, 256, 8, 1);
|
||||
pwrap = COOLBOYPW;
|
||||
cwrap = COOLBOYCW;
|
||||
info->Power = COOLBOYPower;
|
||||
info->Reset = COOLBOYReset;
|
||||
AddExState(EXPREGS, 4, 0, "EXPR");
|
||||
}
|
||||
}
|
||||
|
||||
// Registers at $5xxx
|
||||
void MINDKIDS_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 2048, 256, 8, 1);
|
||||
pwrap = COOLBOYPW;
|
||||
cwrap = COOLBOYCW;
|
||||
info->Power = MINDKIDSPower;
|
||||
info->Reset = COOLBOYReset;
|
||||
AddExState(EXPREGS, 4, 0, "EXPR");
|
||||
}
|
||||
|
||||
// For NES 2.0 loader
|
||||
void SMD132_SMD133_Init(CartInfo *info) {
|
||||
switch (info->submapper)
|
||||
{
|
||||
case 0:
|
||||
COOLBOY_Init(info);
|
||||
break;
|
||||
case 1:
|
||||
MINDKIDS_Init(info);
|
||||
break;
|
||||
default:
|
||||
FCEU_PrintError("Unknown submapper: #%d.", info->submapper);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+540
-498
File diff suppressed because it is too large
Load Diff
+18
-18
@@ -53,22 +53,22 @@
|
||||
#include "emu2413.h"
|
||||
|
||||
static const unsigned char default_inst[15][8] = {
|
||||
/* VRC7 instruments, January 17, 2004 update -Xodnizel */
|
||||
{ 0x03, 0x21, 0x04, 0x06, 0x8D, 0xF2, 0x42, 0x17 },
|
||||
{ 0x13, 0x41, 0x05, 0x0E, 0x99, 0x96, 0x63, 0x12 },
|
||||
{ 0x31, 0x11, 0x10, 0x0A, 0xF0, 0x9C, 0x32, 0x02 },
|
||||
{ 0x21, 0x61, 0x1D, 0x07, 0x9F, 0x64, 0x20, 0x27 },
|
||||
{ 0x22, 0x21, 0x1E, 0x06, 0xF0, 0x76, 0x08, 0x28 },
|
||||
{ 0x02, 0x01, 0x06, 0x00, 0xF0, 0xF2, 0x03, 0x95 },
|
||||
{ 0x21, 0x61, 0x1C, 0x07, 0x82, 0x81, 0x16, 0x07 },
|
||||
{ 0x23, 0x21, 0x1A, 0x17, 0xEF, 0x82, 0x25, 0x15 },
|
||||
{ 0x25, 0x11, 0x1F, 0x00, 0x86, 0x41, 0x20, 0x11 },
|
||||
{ 0x85, 0x01, 0x1F, 0x0F, 0xE4, 0xA2, 0x11, 0x12 },
|
||||
{ 0x07, 0xC1, 0x2B, 0x45, 0xB4, 0xF1, 0x24, 0xF4 },
|
||||
{ 0x61, 0x23, 0x11, 0x06, 0x96, 0x96, 0x13, 0x16 },
|
||||
{ 0x01, 0x02, 0xD3, 0x05, 0x82, 0xA2, 0x31, 0x51 },
|
||||
{ 0x61, 0x22, 0x0D, 0x02, 0xC3, 0x7F, 0x24, 0x05 },
|
||||
{ 0x21, 0x62, 0x0E, 0x00, 0xA1, 0xA0, 0x44, 0x17 },
|
||||
/* VRC7 instruments, March 15, 2019 dumped by Nuke.YKT */
|
||||
{ 0x03, 0x21, 0x05, 0x06, 0xE8, 0x81, 0x42, 0x27 },
|
||||
{ 0x13, 0x41, 0x14, 0x0D, 0xD8, 0xF6, 0x23, 0x12 },
|
||||
{ 0x11, 0x11, 0x08, 0x08, 0xFA, 0xB2, 0x20, 0x12 },
|
||||
{ 0x31, 0x61, 0x0C, 0x07, 0xA8, 0x64, 0x61, 0x27 },
|
||||
{ 0x32, 0x21, 0x1E, 0x06, 0xE1, 0x76, 0x01, 0x28 },
|
||||
{ 0x02, 0x01, 0x06, 0x00, 0xA3, 0xE2, 0xF4, 0xF4 },
|
||||
{ 0x21, 0x61, 0x1D, 0x07, 0x82, 0x81, 0x11, 0x07 },
|
||||
{ 0x23, 0x21, 0x22, 0x17, 0xA2, 0x72, 0x01, 0x17 },
|
||||
{ 0x35, 0x11, 0x25, 0x00, 0x40, 0x73, 0x72, 0x01 },
|
||||
{ 0xB5, 0x01, 0x0F, 0x0F, 0xA8, 0xA5, 0x51, 0x02 },
|
||||
{ 0x17, 0xC1, 0x24, 0x07, 0xF8, 0xF8, 0x22, 0x12 },
|
||||
{ 0x71, 0x23, 0x11, 0x06, 0x65, 0x74, 0x18, 0x16 },
|
||||
{ 0x01, 0x02, 0xD3, 0x05, 0xC9, 0x95, 0x03, 0x02 },
|
||||
{ 0x61, 0x63, 0x0C, 0x00, 0x94, 0xC0, 0x33, 0xF6 },
|
||||
{ 0x21, 0x72, 0x0D, 0x00, 0xC1, 0xD5, 0x56, 0x06 },
|
||||
};
|
||||
|
||||
/* Size of Sintable ( 8 -- 18 can be used. 9 recommended.)*/
|
||||
@@ -604,8 +604,8 @@ void OPLL_reset(OPLL * opll) {
|
||||
for (i = 0; i < 0x40; i++)
|
||||
OPLL_writeReg(opll, i, 0);
|
||||
|
||||
opll->realstep = (uint32)((1 << 31) / rate);
|
||||
opll->opllstep = (uint32)((1 << 31) / (clk / 72));
|
||||
opll->realstep = (uint32)((1u << 31) / rate);
|
||||
opll->opllstep = (uint32)((1u << 31) / (clk / 72));
|
||||
opll->oplltime = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ static void SSSNROMPower(void) {
|
||||
regs[0] = regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0;
|
||||
regs[7] = 0xff;
|
||||
Sync();
|
||||
memset(WRAM, 0x00, WRAMSIZE);
|
||||
FCEU_MemoryRand(WRAM, WRAMSIZE, true);
|
||||
// SetWriteHandler(0x0000,0x1FFF,SSSNROMRamWrite);
|
||||
SetReadHandler(0x0800, 0x1FFF, CartBR);
|
||||
SetWriteHandler(0x0800, 0x1FFF, CartBW);
|
||||
|
||||
+130
-131
@@ -30,26 +30,22 @@ static uint32 CHRRAMSize;
|
||||
|
||||
static void BMCFK23CCW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&0x40)
|
||||
setchr8(EXPREGS[2]|unromchr);
|
||||
else if(EXPREGS[0]&0x20) {
|
||||
setchr1r(0x10, A, V);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16 base=(EXPREGS[2]&0x7F)<<3;
|
||||
if(EXPREGS[3]&2)
|
||||
{
|
||||
int cbase=(MMC3_cmd&0x80)<<5;
|
||||
setchr1(A,V|base);
|
||||
setchr1(0x0000^cbase,DRegBuf[0]|base);
|
||||
setchr1(0x0400^cbase,EXPREGS[6]|base);
|
||||
setchr1(0x0800^cbase,DRegBuf[1]|base);
|
||||
setchr1(0x0c00^cbase,EXPREGS[7]|base);
|
||||
}
|
||||
else
|
||||
setchr1(A,V|base);
|
||||
}
|
||||
if(EXPREGS[0]&0x40)
|
||||
setchr8(EXPREGS[2]|unromchr);
|
||||
else if(EXPREGS[0]&0x20) {
|
||||
setchr1r(0x10, A, V);
|
||||
} else {
|
||||
uint16 base=(EXPREGS[2]&0x7F)<<3;
|
||||
if(EXPREGS[3]&2) {
|
||||
int cbase=(MMC3_cmd&0x80)<<5;
|
||||
setchr1(A,V|base);
|
||||
setchr1(0x0000^cbase,DRegBuf[0]|base);
|
||||
setchr1(0x0400^cbase,EXPREGS[6]|base);
|
||||
setchr1(0x0800^cbase,DRegBuf[1]|base);
|
||||
setchr1(0x0c00^cbase,EXPREGS[7]|base);
|
||||
} else
|
||||
setchr1(A,V|base);
|
||||
}
|
||||
}
|
||||
|
||||
//some games are wired differently, and this will need to be changed.
|
||||
@@ -86,110 +82,110 @@ static int prg_mask;
|
||||
//PRG wrapper
|
||||
static void BMCFK23CPW(uint32 A, uint8 V)
|
||||
{
|
||||
uint32 bank = (EXPREGS[1] & 0x1F);
|
||||
uint32 hiblock = ((EXPREGS[0] & 8) << 4)|((EXPREGS[0] & 0x80) << 1)|(UNIFchrrama?((EXPREGS[2] & 0x40)<<3):0);
|
||||
uint32 block = (EXPREGS[1] & 0x60) | hiblock;
|
||||
uint32 extra = (EXPREGS[3] & 2);
|
||||
//uint32 bank = (EXPREGS[1] & 0x1F);
|
||||
//uint32 hiblock = ((EXPREGS[0] & 8) << 4)|((EXPREGS[0] & 0x80) << 1)|(UNIFchrrama?((EXPREGS[2] & 0x40)<<3):0);
|
||||
//uint32 block = (EXPREGS[1] & 0x60) | hiblock;
|
||||
//uint32 extra = (EXPREGS[3] & 2);
|
||||
// FCEU_printf("0:%04X:%02X\n",A,V);
|
||||
|
||||
if((EXPREGS[0]&7)==4)
|
||||
setprg32(0x8000,EXPREGS[1]>>1);
|
||||
else if ((EXPREGS[0]&7)==3)
|
||||
{
|
||||
setprg16(0x8000,EXPREGS[1]);
|
||||
setprg16(0xC000,EXPREGS[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(EXPREGS[0]&3)
|
||||
{
|
||||
if((EXPREGS[0]&7)==4)
|
||||
setprg32(0x8000,EXPREGS[1]>>1);
|
||||
else if ((EXPREGS[0]&7)==3) {
|
||||
setprg16(0x8000,EXPREGS[1]);
|
||||
setprg16(0xC000,EXPREGS[1]);
|
||||
} else {
|
||||
if(EXPREGS[0]&3) {
|
||||
uint32 blocksize = (6)-(EXPREGS[0]&3);
|
||||
uint32 mask = (1<<blocksize)-1;
|
||||
V &= mask;
|
||||
//V &= 63; //? is this a good idea?
|
||||
V |= (EXPREGS[1]<<1);
|
||||
setprg8(A,V);
|
||||
// FCEU_printf("1:%04X:%02X\n",A,V);
|
||||
setprg8(A,V);
|
||||
} else {
|
||||
setprg8(A,V & prg_mask);
|
||||
// FCEU_printf("2:%04X:%02X\n",A,V);
|
||||
}
|
||||
else
|
||||
setprg8(A,V & prg_mask);
|
||||
|
||||
if(EXPREGS[3]&2)
|
||||
{
|
||||
setprg8(0xC000,EXPREGS[4]);
|
||||
setprg8(0xE000,EXPREGS[5]);
|
||||
}
|
||||
}
|
||||
if(EXPREGS[3]&2) {
|
||||
setprg8(0xC000,EXPREGS[4]);
|
||||
setprg8(0xE000,EXPREGS[5]);
|
||||
}
|
||||
}
|
||||
setprg8r(0x10,0x6000,A001B&3);
|
||||
}
|
||||
|
||||
//PRG handler ($8000-$FFFF)
|
||||
static DECLFW(BMCFK23CHiWrite)
|
||||
{
|
||||
if(EXPREGS[0]&0x40)
|
||||
{
|
||||
// FCEU_printf("K4:(exp0=%02x)\n",EXPREGS[0]);
|
||||
// FCEU_printf("W0:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||
if((EXPREGS[0]&0x60)==0x40) {
|
||||
// FCEU_printf("W2:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||
if(EXPREGS[0]&0x30)
|
||||
unromchr=0;
|
||||
else
|
||||
{
|
||||
else {
|
||||
unromchr=V&3;
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((A==0x8001)&&(EXPREGS[3]&2&&MMC3_cmd&8))
|
||||
{
|
||||
} else {
|
||||
if((A==0x8001)&&(EXPREGS[3]&2)&&(MMC3_cmd&8)) {
|
||||
// FCEU_printf("W3:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||
EXPREGS[4|(MMC3_cmd&3)]=V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
else
|
||||
if(A<0xC000) {
|
||||
if(UNIFchrrama) { // hacky... strange behaviour, must be bit scramble due to pcb layot restrictions
|
||||
// check if it not interfer with other dumps
|
||||
if((A==0x8000)&&(V==0x46))
|
||||
V=0x47;
|
||||
else if((A==0x8000)&&(V==0x47))
|
||||
V=0x46;
|
||||
}
|
||||
MMC3_CMDWrite(A,V);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
else
|
||||
MMC3_IRQWrite(A,V);
|
||||
}
|
||||
} else
|
||||
if(A<0xC000) {
|
||||
if(UNIFchrrama) { // hacky... strange behaviour, must be bit scramble due to pcb layot restrictions
|
||||
// check if it not interfer with other dumps
|
||||
if((A==0x8000)&&(V==0x46))
|
||||
V=0x47;
|
||||
else if((A==0x8000)&&(V==0x47))
|
||||
V=0x46;
|
||||
}
|
||||
// FCEU_printf("W1:%04X:%02X\n",A,V);
|
||||
MMC3_CMDWrite(A,V);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
} else {
|
||||
MMC3_IRQWrite(A,V);
|
||||
// FCEU_printf("W4:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//EXP handler ($5000-$5FFF)
|
||||
static DECLFW(BMCFK23CWrite)
|
||||
{
|
||||
if(A&(1<<(dipswitch+4)))
|
||||
{
|
||||
if(A&(1<<(dipswitch+4))) {
|
||||
//printf("+ ");
|
||||
EXPREGS[A&3]=V;
|
||||
EXPREGS[A&3]=V;
|
||||
|
||||
bool remap = false;
|
||||
// BUT WHY is there any rom that need it actually?
|
||||
// bool remap = false;
|
||||
// FCEU_printf("K3:(exp0=%02x)\n",EXPREGS[0]);
|
||||
// FCEU_printf("WH0:%04X:%02X\n",A,V);
|
||||
|
||||
//sometimes writing to reg0 causes remappings to occur. we think the 2 signifies this.
|
||||
//sometimes writing to reg0 causes remappings to occur. we think the 2 signifies this.
|
||||
//if not, 0x24 is a value that is known to work
|
||||
//however, the low 4 bits are known to control the mapping mode, so 0x20 is more likely to be the immediate remap flag
|
||||
remap |= ((EXPREGS[0]&0xF0)==0x20);
|
||||
// remap |= ((EXPREGS[0]&0xF0)==0x20);
|
||||
|
||||
//this is an actual mapping reg. i think reg0 controls what happens when reg1 is written. anyway, we have to immediately remap these
|
||||
remap |= (A&3)==1;
|
||||
// remap |= (A&3)==1;
|
||||
//this too.
|
||||
remap |= (A&3)==2;
|
||||
// remap |= (A&3)==2;
|
||||
|
||||
if(remap)
|
||||
{
|
||||
// if(remap) {
|
||||
// FCEU_printf("WH1:%04X:%02X\n",A,V);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
if(is_BMCFK23CA)
|
||||
{
|
||||
if(is_BMCFK23CA) {
|
||||
if(EXPREGS[3]&2)
|
||||
EXPREGS[0] &= ~7; // hacky hacky! if someone wants extra banking, then for sure doesn't want mode 4 for it! (allow to run A version boards on normal mapper)
|
||||
// FCEU_printf("EXTRA!\n",A);
|
||||
EXPREGS[0] &= ~7; // hacky hacky! if someone wants extra banking, then for sure doesn't want mode 4 for it! (allow to run A version boards on normal mapper)
|
||||
}
|
||||
|
||||
//printf("%04X = $%02X\n",A,V);
|
||||
@@ -199,62 +195,65 @@ static DECLFW(BMCFK23CWrite)
|
||||
static void BMCFK23CReset(void)
|
||||
{
|
||||
//NOT NECESSARY ANYMORE
|
||||
// BUT WHY?
|
||||
//this little hack makes sure that we try all the dip switch settings eventually, if we reset enough
|
||||
// dipswitch++;
|
||||
// dipswitch&=7;
|
||||
//printf("BMCFK23C dipswitch set to %d\n",dipswitch);
|
||||
dipswitch++;
|
||||
dipswitch&=7;
|
||||
printf("BMCFK23C dipswitch set to %u\n",dipswitch);
|
||||
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
MMC3RegReset();
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
// FCEU_printf("K0:(exp0=%02x)\n",EXPREGS[0]);
|
||||
MMC3RegReset();
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void BMCFK23CPower(void)
|
||||
{
|
||||
GenMMC3Power();
|
||||
dipswitch = 0;
|
||||
GenMMC3Power();
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
// FCEU_printf("K1:(exp0=%02x)\n",EXPREGS[0]);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||
}
|
||||
|
||||
static void BMCFK23CAPower(void)
|
||||
{
|
||||
GenMMC3Power();
|
||||
dipswitch = 0;
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
GenMMC3Power();
|
||||
dipswitch = 0;
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
// FCEU_printf("K2:(exp0=%02x)\n",EXPREGS[0]);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||
}
|
||||
|
||||
static void BMCFK23CAClose(void)
|
||||
{
|
||||
if(CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM=NULL;
|
||||
if(CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM=NULL;
|
||||
}
|
||||
|
||||
void BMCFK23C_Init(CartInfo *info)
|
||||
{
|
||||
is_BMCFK23CA = false;
|
||||
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap=BMCFK23CCW;
|
||||
pwrap=BMCFK23CPW;
|
||||
info->Power=BMCFK23CPower;
|
||||
info->Reset=BMCFK23CReset;
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap=BMCFK23CCW;
|
||||
pwrap=BMCFK23CPW;
|
||||
info->Power=BMCFK23CPower;
|
||||
info->Reset=BMCFK23CReset;
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
|
||||
prg_bonus = 1;
|
||||
if(MasterRomInfoParams.find("bonus") != MasterRomInfoParams.end())
|
||||
@@ -267,21 +266,21 @@ void BMCFK23CA_Init(CartInfo *info)
|
||||
{
|
||||
is_BMCFK23CA = true;
|
||||
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap=BMCFK23CCW;
|
||||
pwrap=BMCFK23CPW;
|
||||
info->Power=BMCFK23CAPower;
|
||||
info->Reset=BMCFK23CReset;
|
||||
info->Close=BMCFK23CAClose;
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap=BMCFK23CCW;
|
||||
pwrap=BMCFK23CPW;
|
||||
info->Power=BMCFK23CAPower;
|
||||
info->Reset=BMCFK23CReset;
|
||||
info->Close=BMCFK23CAClose;
|
||||
|
||||
CHRRAMSize=8192;
|
||||
CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
|
||||
AddExState(CHRRAM, CHRRAMSize, 0, "CRAM");
|
||||
CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
|
||||
AddExState(CHRRAM, CHRRAMSize, 0, "CRAM");
|
||||
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
|
||||
prg_bonus = 1;
|
||||
if(MasterRomInfoParams.find("bonus") != MasterRomInfoParams.end())
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 1998 BERO
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
* Copyright (C) 2020 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Famicom Network System Base Unit + MMC1 cartridge board
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 DRegs[4];
|
||||
static uint8 Buffer, BufferShift;
|
||||
|
||||
static uint32 WRAMSIZE;
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
static int kanji_pos, kanji_page, r40C0;
|
||||
static int IRQa, IRQCount;
|
||||
|
||||
static DECLFW(MBWRAM) {
|
||||
if (!(DRegs[3] & 0x10))
|
||||
Page[A >> 11][A] = V;
|
||||
}
|
||||
|
||||
static DECLFR(MAWRAM) {
|
||||
if (DRegs[3] & 0x10)
|
||||
return X.DB;
|
||||
return(Page[A >> 11][A]);
|
||||
}
|
||||
|
||||
static void MMC1CHR(void) {
|
||||
setchr8((r40C0 >> 3) & 1);
|
||||
}
|
||||
|
||||
static void MMC1PRG(void) {
|
||||
uint8 offs_16banks = DRegs[1] & 0x10;
|
||||
uint8 prg_reg = DRegs[3] & 0xF;
|
||||
|
||||
setprg8r(0x10, 0x6000, DRegs[1] & 3);
|
||||
|
||||
switch (DRegs[0] & 0xC) {
|
||||
case 0xC:
|
||||
setprg16(0x8000, (prg_reg + offs_16banks));
|
||||
setprg16(0xC000, 0xF + offs_16banks);
|
||||
break;
|
||||
case 0x8:
|
||||
setprg16(0xC000, (prg_reg + offs_16banks));
|
||||
setprg16(0x8000, offs_16banks);
|
||||
break;
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
setprg16(0x8000, ((prg_reg & ~1) + offs_16banks));
|
||||
setprg16(0xc000, ((prg_reg & ~1) + offs_16banks + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void MMC1MIRROR(void) {
|
||||
switch (DRegs[0] & 3) {
|
||||
case 2: setmirror(MI_V); break;
|
||||
case 3: setmirror(MI_H); break;
|
||||
case 0: setmirror(MI_0); break;
|
||||
case 1: setmirror(MI_1); break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64 lreset;
|
||||
static DECLFW(MMC1_write) {
|
||||
int n = (A >> 13) - 4;
|
||||
if ((timestampbase + timestamp) < (lreset + 2))
|
||||
return;
|
||||
|
||||
if (V & 0x80) {
|
||||
DRegs[0] |= 0xC;
|
||||
BufferShift = Buffer = 0;
|
||||
MMC1PRG();
|
||||
lreset = timestampbase + timestamp;
|
||||
return;
|
||||
}
|
||||
|
||||
Buffer |= (V & 1) << (BufferShift++);
|
||||
|
||||
if (BufferShift == 5) {
|
||||
FCEU_printf("MMC1 REG%d:%02x (PC %04x)\n", n, Buffer, X.PC);
|
||||
DRegs[n] = Buffer;
|
||||
BufferShift = Buffer = 0;
|
||||
switch (n) {
|
||||
case 0: MMC1MIRROR();
|
||||
case 1:
|
||||
case 2:
|
||||
case 3: MMC1PRG(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MMC1_Restore(int version) {
|
||||
MMC1MIRROR();
|
||||
MMC1CHR();
|
||||
MMC1PRG();
|
||||
lreset = 0;
|
||||
}
|
||||
|
||||
static void MMC1CMReset(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
DRegs[i] = 0;
|
||||
Buffer = BufferShift = 0;
|
||||
DRegs[0] = 0x1F;
|
||||
|
||||
DRegs[1] = 0;
|
||||
DRegs[2] = 0;
|
||||
DRegs[3] = 0;
|
||||
|
||||
MMC1MIRROR();
|
||||
MMC1CHR();
|
||||
MMC1PRG();
|
||||
}
|
||||
|
||||
static DECLFW(FNC_cmd_write) {
|
||||
switch (A) {
|
||||
case 0x40A6: {
|
||||
IRQCount = (IRQCount & 0xFF00) | V;
|
||||
break;
|
||||
}
|
||||
case 0x40A7: {
|
||||
IRQCount = (IRQCount & 0x00FF) | (V << 8);
|
||||
break;
|
||||
}
|
||||
case 0x40A8: {
|
||||
IRQa = V;
|
||||
break;
|
||||
}
|
||||
case 0x40B0: {
|
||||
kanji_page = V & 1;
|
||||
break;
|
||||
}
|
||||
case 0x40C0: {
|
||||
FCEU_printf("FNS W %04x:%02x (PC %04x)\n", A, V, X.PC);
|
||||
r40C0 = V;
|
||||
MMC1CHR();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FCEU_printf("FNS W %04x:%02x (PC %04x)\n", A, V, X.PC);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(FNC_stat_read) {
|
||||
switch (A) {
|
||||
case 0x40A2: {
|
||||
int ret = (IRQa >> 1);
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
IRQa = 0;
|
||||
return ret;
|
||||
}
|
||||
case 0x40AC: { // NMI/IRQ state reset (lookalike)
|
||||
return 0;
|
||||
}
|
||||
case 0x40B0: {
|
||||
kanji_pos = 0;
|
||||
return 0;
|
||||
}
|
||||
case 0x40C0: {
|
||||
FCEU_printf("FNS R %04x (PC %04x)\n", A, X.PC);
|
||||
int ret = r40C0;
|
||||
r40C0 &= 0;
|
||||
return ret;
|
||||
}
|
||||
default: {
|
||||
FCEU_printf("FNS R %04x (PC %04x)\n", A, X.PC);
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(FNC_cart_i2c_read) {
|
||||
FCEU_printf("I2C R %04x (PC %04x)\n", A, X.PC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static DECLFR(FNC_kanji_read) {
|
||||
int32 ofs = ((A & 0xFFF) << 5) + kanji_pos;
|
||||
kanji_pos++;
|
||||
kanji_pos &= 0x1F;
|
||||
// if (PRGptr[1] != NULL) // iNES debug
|
||||
return PRGptr[1][ofs];
|
||||
// else
|
||||
// return CHRptr[0][ofs];
|
||||
}
|
||||
|
||||
void NFC_IRQ(int a) {
|
||||
if (IRQa) {
|
||||
IRQCount -= a;
|
||||
if (IRQCount <= 0)
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
|
||||
static void FNS_Power(void) {
|
||||
lreset = 0;
|
||||
SetWriteHandler(0x8000, 0xFFFF, MMC1_write);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
|
||||
kanji_page = 0;
|
||||
kanji_pos = 0;
|
||||
r40C0 = 0xC0;
|
||||
|
||||
SetWriteHandler(0x4080, 0x40FF, FNC_cmd_write);
|
||||
SetReadHandler(0x4080, 0x40FF, FNC_stat_read);
|
||||
SetReadHandler(0x5000, 0x5FFF, FNC_kanji_read);
|
||||
|
||||
SetReadHandler(0x6000, 0x6000, FNC_cart_i2c_read);
|
||||
SetReadHandler(0x6001, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
|
||||
FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
||||
MMC1CMReset();
|
||||
}
|
||||
|
||||
static void FNS_Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
void FNS_Init(CartInfo *info) {
|
||||
info->Close = FNS_Close;
|
||||
info->Power = FNS_Power;
|
||||
|
||||
GameStateRestore = MMC1_Restore;
|
||||
MapIRQHook = NFC_IRQ;
|
||||
|
||||
WRAMSIZE = (8 + 32) * 1024;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
|
||||
AddExState(DRegs, 4, 0, "DREG");
|
||||
AddExState(&lreset, 8, 1, "LRST");
|
||||
AddExState(&Buffer, 1, 1, "BFFR");
|
||||
AddExState(&BufferShift, 1, 1, "BFRS");
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2017 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* HP10xx/HP20xx - a simplified version of FK23C mapper with pretty strict and better
|
||||
* organized banking behaviour. It seems that some 176 mapper assigned game may be
|
||||
* actually this kind of board instead but in common they aren't compatible at all,
|
||||
* the games on the regular FK23C boards couldn't run on this mapper and vice versa...
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
#include "../ines.h"
|
||||
|
||||
static uint8 unromchr, lock;
|
||||
static uint32 dipswitch;
|
||||
|
||||
static void BMCHPxxCW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&4) { // custom banking
|
||||
switch(EXPREGS[0]&3) {
|
||||
case 0:
|
||||
case 1:
|
||||
setchr8(EXPREGS[2]&0x3F);
|
||||
// FCEU_printf("\tCHR8 %02X\n",EXPREGS[2]&0x3F);
|
||||
break;
|
||||
case 2:
|
||||
setchr8((EXPREGS[2]&0x3E)|(unromchr&1));
|
||||
// FCEU_printf("\tCHR8 %02X\n",(EXPREGS[2]&0x3E)|(unromchr&1));
|
||||
break;
|
||||
case 3:
|
||||
setchr8((EXPREGS[2]&0x3C)|(unromchr&3));
|
||||
// FCEU_printf("\tCHR8 %02X\n",(EXPREGS[2]&0x3C)|(unromchr&3));
|
||||
break;
|
||||
}
|
||||
} else { // mmc3 banking
|
||||
int base, mask;
|
||||
if(EXPREGS[0]&1) { // 128K mode
|
||||
base=EXPREGS[2]&0x30;
|
||||
mask=0x7F;
|
||||
} else { // 256K mode
|
||||
base=EXPREGS[2]&0x20;
|
||||
mask=0xFF;
|
||||
}
|
||||
// FCEU_printf("\tCHR1 %04x:%02X\n",A,(V&mask)|(base<<3));
|
||||
setchr1(A,(V&mask)|(base<<3));
|
||||
}
|
||||
}
|
||||
|
||||
//PRG wrapper
|
||||
static void BMCHPxxPW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&4) { // custom banking
|
||||
if((EXPREGS[0]&0xF)==4) { // 16K mode
|
||||
// FCEU_printf("\tPRG16 %02X\n",EXPREGS[1]&0x1F);
|
||||
setprg16(0x8000,EXPREGS[1]&0x1F);
|
||||
setprg16(0xC000,EXPREGS[1]&0x1F);
|
||||
} else { // 32K modes
|
||||
// FCEU_printf("\tPRG32 %02X\n",(EXPREGS[1]&0x1F)>>1);
|
||||
setprg32(0x8000,(EXPREGS[1]&0x1F)>>1);
|
||||
}
|
||||
} else { // mmc3 banking
|
||||
int base, mask;
|
||||
if(EXPREGS[0]&2) { // 128K mode
|
||||
base=EXPREGS[1]&0x18;
|
||||
mask=0x0F;
|
||||
} else { // 256K mode
|
||||
base=EXPREGS[1]&0x10;
|
||||
mask=0x1F;
|
||||
}
|
||||
// FCEU_printf("\tPRG8 %02X\n",(V&mask)|(base<<1));
|
||||
setprg8(A,(V&mask)|(base<<1));
|
||||
setprg8r(0x10,0x6000,A001B&3);
|
||||
}
|
||||
}
|
||||
|
||||
//MIRROR wrapper
|
||||
static void BMCHPxxMW(uint8 V) {
|
||||
if(EXPREGS[0]&4) { // custom banking
|
||||
// FCEU_printf("CUSTOM MIRR: %d\n",(unromchr>>2)&1);
|
||||
setmirror(((unromchr>>2)&1)^1);
|
||||
} else { // mmc3 banking
|
||||
// FCEU_printf("MMC3 MIRR: %d\n",(V&1)^1);
|
||||
A000B = V;
|
||||
setmirror((A000B & 1) ^ 1);
|
||||
}
|
||||
}
|
||||
|
||||
//PRG handler ($8000-$FFFF)
|
||||
static DECLFW(BMCHPxxHiWrite)
|
||||
{
|
||||
// FCEU_printf("HI WRITE %04X:%02X\n",A,V);
|
||||
if(EXPREGS[0]&4) { // custom banking
|
||||
// FCEU_printf("CUSTOM\n");
|
||||
unromchr=V;
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
} else { // mmc3 banking
|
||||
// FCEU_printf("MMC3\n");
|
||||
if(A<0xC000) {
|
||||
MMC3_CMDWrite(A,V);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
} else {
|
||||
MMC3_IRQWrite(A,V);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//EXP handler ($5000-$5FFF)
|
||||
static DECLFW(BMCHPxxWrite)
|
||||
{
|
||||
if(!lock) {
|
||||
// FCEU_printf("LO WRITE %04X:%02X\n",A,V);
|
||||
EXPREGS[A&3]=V;
|
||||
lock=V&0x80;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(BMCHPxxRead) {
|
||||
return dipswitch;
|
||||
}
|
||||
|
||||
static void BMCHPxxReset(void)
|
||||
{
|
||||
dipswitch++;
|
||||
dipswitch&=0xF;
|
||||
lock=0;
|
||||
// FCEU_printf("BMCHPxx dipswitch set to %d\n",dipswitch);
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
MMC3RegReset();
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void BMCHPxxPower(void)
|
||||
{
|
||||
GenMMC3Power();
|
||||
dipswitch=lock=0;
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
SetReadHandler(0x5000,0x5fff,BMCHPxxRead);
|
||||
SetWriteHandler(0x5000,0x5fff,BMCHPxxWrite);
|
||||
SetWriteHandler(0x8000,0xffff,BMCHPxxHiWrite);
|
||||
}
|
||||
|
||||
void BMCHPxx_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC3_Init(info, 256, 256, 8, 0);
|
||||
cwrap=BMCHPxxCW;
|
||||
pwrap=BMCHPxxPW;
|
||||
mwrap=BMCHPxxMW;
|
||||
info->Power=BMCHPxxPower;
|
||||
info->Reset=BMCHPxxReset;
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
AddExState(&lock, 1, 0, "LOCK");
|
||||
}
|
||||
@@ -35,6 +35,7 @@ static void MALEEPower(void) {
|
||||
|
||||
void MALEE_Init(CartInfo *info) {
|
||||
info->Power = MALEEPower;
|
||||
FCEU_MemoryRand(WRAM,sizeof(WRAM),true);
|
||||
SetupCartPRGMapping(0x10, WRAM, 2048, 1);
|
||||
AddExState(WRAM, 2048, 0, "WRAM");
|
||||
}
|
||||
|
||||
+59
-48
@@ -22,12 +22,13 @@
|
||||
#include "mapinc.h"
|
||||
|
||||
static void GenMMC1Power(void);
|
||||
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery);
|
||||
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int bram);
|
||||
|
||||
static uint8 DRegs[4];
|
||||
static uint8 Buffer, BufferShift;
|
||||
|
||||
static int mmc1opts;
|
||||
static uint32 WRAMSIZE;
|
||||
static uint32 NONBRAMSIZE; // size of non-battery-backed portion of WRAM
|
||||
|
||||
static void (*MMC1CHRHook4)(uint32 A, uint8 V);
|
||||
static void (*MMC1PRGHook16)(uint32 A, uint8 V);
|
||||
@@ -48,9 +49,9 @@ static DECLFR(MAWRAM) {
|
||||
}
|
||||
|
||||
static void MMC1CHR(void) {
|
||||
if (mmc1opts & 4) {
|
||||
if (DRegs[0] & 0x10)
|
||||
setprg8r(0x10, 0x6000, (DRegs[1] >> 4) & 1);
|
||||
if (WRAMSIZE > 0x2000) {
|
||||
if (WRAMSIZE > 0x4000)
|
||||
setprg8r(0x10, 0x6000, (DRegs[1] >> 2) & 3);
|
||||
else
|
||||
setprg8r(0x10, 0x6000, (DRegs[1] >> 3) & 1);
|
||||
}
|
||||
@@ -179,20 +180,39 @@ static void MMC1CMReset(void) {
|
||||
MMC1PRG();
|
||||
}
|
||||
|
||||
static int DetectMMC1WRAMSize(uint32 crc32) {
|
||||
switch (crc32) {
|
||||
static int DetectMMC1WRAMSize(CartInfo *info, int *bs) {
|
||||
int ws = 8;
|
||||
switch (info->CRC32) {
|
||||
case 0xc6182024: // Romance of the 3 Kingdoms
|
||||
case 0xabbf7217: // "" "" (J) (PRG0)
|
||||
case 0xccf35c02: // "" "" (J) (PRG1)
|
||||
case 0x2225c20f: // Genghis Khan
|
||||
case 0xfb69743a: // "" "" (J)
|
||||
case 0x4642dda6: // Nobunaga's Ambition
|
||||
case 0x29449ba9: // "" "" (J)
|
||||
case 0x2b11e0b0: // "" "" (J)
|
||||
case 0xb8747abf: // Best Play Pro Yakyuu Special (J)
|
||||
case 0xc9556b36: // Final Fantasy I & II (J) [!]
|
||||
FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n");
|
||||
return(16);
|
||||
case 0x3f7ad415: // "" "" (J) (PRG0)
|
||||
case 0x2b11e0b0: // "" "" (J) (PRG1)
|
||||
*bs = 8;
|
||||
ws = 16;
|
||||
break;
|
||||
default: return(8);
|
||||
case 0xb8747abf: // Best Play Pro Yakyuu Special (J) (PRG0)
|
||||
case 0xc3de7c69: // "" "" (J) (PRG1)
|
||||
case 0xc9556b36: // Final Fantasy I & II (J) [!]
|
||||
*bs = 32;
|
||||
ws = 32;
|
||||
break;
|
||||
default:
|
||||
if(info->ines2) {
|
||||
ws = (info->wram_size + info->battery_wram_size) / 1024;
|
||||
*bs = info->battery_wram_size / 1024;
|
||||
// we only support sizes between 8K and 32K
|
||||
if (ws > 0 && ws < 8) ws = 8;
|
||||
if (ws > 32) ws = 32;
|
||||
if (*bs > ws) *bs = ws;
|
||||
}
|
||||
}
|
||||
if (ws > 8)
|
||||
FCEU_printf(" >8KB external WRAM present. Use NES 2.0 if you hack the ROM image.\n");
|
||||
return ws;
|
||||
}
|
||||
|
||||
static uint32 NWCIRQCount;
|
||||
@@ -244,17 +264,16 @@ void Mapper105_Init(CartInfo *info) {
|
||||
|
||||
static void GenMMC1Power(void) {
|
||||
lreset = 0;
|
||||
if (mmc1opts & 1) {
|
||||
FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
||||
if (mmc1opts & 4)
|
||||
FCEU_dwmemset(WRAM, 0, 8192)
|
||||
else if (!(mmc1opts & 2))
|
||||
FCEU_dwmemset(WRAM, 0, 8192); // wtf?
|
||||
}
|
||||
SetWriteHandler(0x8000, 0xFFFF, MMC1_write);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
|
||||
if (mmc1opts & 1) {
|
||||
if (WRAMSIZE) {
|
||||
FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
||||
|
||||
// clear non-battery-backed portion of WRAM
|
||||
if (NONBRAMSIZE)
|
||||
FCEU_MemoryRand(WRAM, NONBRAMSIZE, true);
|
||||
|
||||
SetReadHandler(0x6000, 0x7FFF, MAWRAM);
|
||||
SetWriteHandler(0x6000, 0x7FFF, MBWRAM);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
@@ -271,31 +290,24 @@ static void GenMMC1Close(void) {
|
||||
CHRRAM = WRAM = NULL;
|
||||
}
|
||||
|
||||
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery) {
|
||||
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int bram) {
|
||||
is155 = 0;
|
||||
|
||||
info->Close = GenMMC1Close;
|
||||
MMC1PRGHook16 = MMC1CHRHook4 = 0;
|
||||
mmc1opts = 0;
|
||||
WRAMSIZE = wram * 1024;
|
||||
NONBRAMSIZE = (wram - bram) * 1024;
|
||||
PRGmask16[0] &= (prg >> 14) - 1;
|
||||
CHRmask4[0] &= (chr >> 12) - 1;
|
||||
CHRmask8[0] &= (chr >> 13) - 1;
|
||||
|
||||
if (wram) {
|
||||
WRAM = (uint8*)FCEU_gmalloc(wram * 1024);
|
||||
//mbg 17-jun-08 - this shouldve been cleared to re-initialize save ram
|
||||
//ch4 10-dec-08 - nope, this souldn't
|
||||
//mbg 29-mar-09 - no time to debate this, we need to keep from breaking some old stuff.
|
||||
//we really need to make up a policy for how compatibility and accuracy can be resolved.
|
||||
memset(WRAM, 0, wram * 1024);
|
||||
mmc1opts |= 1;
|
||||
if (wram > 8) mmc1opts |= 4;
|
||||
SetupCartPRGMapping(0x10, WRAM, wram * 1024, 1);
|
||||
AddExState(WRAM, wram * 1024, 0, "WRAM");
|
||||
if (battery) {
|
||||
mmc1opts |= 2;
|
||||
info->SaveGame[0] = WRAM + ((mmc1opts & 4) ? 8192 : 0);
|
||||
info->SaveGameLen[0] = 8192;
|
||||
if (WRAMSIZE) {
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
if (bram) {
|
||||
info->SaveGame[0] = WRAM + NONBRAMSIZE;
|
||||
info->SaveGameLen[0] = bram * 1024;
|
||||
}
|
||||
}
|
||||
if (!chr) {
|
||||
@@ -313,13 +325,14 @@ static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery)
|
||||
}
|
||||
|
||||
void Mapper1_Init(CartInfo *info) {
|
||||
int ws = DetectMMC1WRAMSize(info->CRC32);
|
||||
GenMMC1Init(info, 512, 256, ws, info->battery);
|
||||
int bs = info->battery ? 8 : 0;
|
||||
int ws = DetectMMC1WRAMSize(info, &bs);
|
||||
GenMMC1Init(info, 512, 256, ws, bs);
|
||||
}
|
||||
|
||||
/* Same as mapper 1, without respect for WRAM enable bit. */
|
||||
void Mapper155_Init(CartInfo *info) {
|
||||
GenMMC1Init(info, 512, 256, 8, info->battery);
|
||||
GenMMC1Init(info, 512, 256, 8, info->battery ? 8 : 0);
|
||||
is155 = 1;
|
||||
}
|
||||
|
||||
@@ -331,7 +344,7 @@ void Mapper171_Init(CartInfo *info) {
|
||||
}
|
||||
|
||||
void SAROM_Init(CartInfo *info) {
|
||||
GenMMC1Init(info, 128, 64, 8, info->battery);
|
||||
GenMMC1Init(info, 128, 64, 8, info->battery ? 8 : 0);
|
||||
}
|
||||
|
||||
void SBROM_Init(CartInfo *info) {
|
||||
@@ -351,7 +364,7 @@ void SGROM_Init(CartInfo *info) {
|
||||
}
|
||||
|
||||
void SKROM_Init(CartInfo *info) {
|
||||
GenMMC1Init(info, 256, 64, 8, info->battery);
|
||||
GenMMC1Init(info, 256, 64, 8, info->battery ? 8 : 0);
|
||||
}
|
||||
|
||||
void SLROM_Init(CartInfo *info) {
|
||||
@@ -383,11 +396,9 @@ void SHROM_Init(CartInfo *info) {
|
||||
/* */
|
||||
|
||||
void SNROM_Init(CartInfo *info) {
|
||||
GenMMC1Init(info, 256, 0, 8, info->battery);
|
||||
GenMMC1Init(info, 256, 0, 8, info->battery ? 8 : 0);
|
||||
}
|
||||
|
||||
void SOROM_Init(CartInfo *info) {
|
||||
GenMMC1Init(info, 256, 0, 16, info->battery);
|
||||
GenMMC1Init(info, 256, 0, 16, info->battery ? 8 : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+40
-3
@@ -113,6 +113,9 @@ void MMC3RegReset(void) {
|
||||
DRegBuf[6] = 0;
|
||||
DRegBuf[7] = 1;
|
||||
|
||||
// KT-008 boards hack 2-in-1, TODO assign to new ines mapper, most dump of KT-boards on the net are mapper 4, so need database or goodnes fix support
|
||||
kt_extra = 0;
|
||||
|
||||
FixMMC3PRG(0);
|
||||
FixMMC3CHR(0);
|
||||
}
|
||||
@@ -187,7 +190,14 @@ DECLFW(MMC3_IRQWrite) {
|
||||
DECLFW(KT008HackWrite) {
|
||||
// FCEU_printf("%04x:%04x\n",A,V);
|
||||
switch (A & 3) {
|
||||
case 0: kt_extra = V; FixMMC3PRG(MMC3_cmd); break;
|
||||
case 0: {
|
||||
if (V == 0x27) // FF Xn hack! one more mapper in one
|
||||
kt_extra = 0;
|
||||
else
|
||||
kt_extra = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
break;
|
||||
}
|
||||
case 1: break; // unk
|
||||
case 2: break; // unk
|
||||
case 3: break; // unk
|
||||
@@ -279,11 +289,11 @@ void GenMMC3Power(void) {
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
}
|
||||
if (!(mmc3opts & 2))
|
||||
FCEU_dwmemset(WRAM, 0, WRAMSIZE);
|
||||
FCEU_MemoryRand(WRAM, WRAMSIZE, true);
|
||||
}
|
||||
MMC3RegReset();
|
||||
if (CHRRAM)
|
||||
FCEU_dwmemset(CHRRAM, 0, CHRRAMSIZE);
|
||||
FCEU_MemoryRand(CHRRAM, CHRRAMSIZE, true);
|
||||
}
|
||||
|
||||
static void GenMMC3Close(void) {
|
||||
@@ -1353,3 +1363,30 @@ void TQROM_Init(CartInfo *info) {
|
||||
void HKROM_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 512, 1, info->battery);
|
||||
}
|
||||
|
||||
// -------------------------------- iNES 2.0 ----------------------------
|
||||
|
||||
// ---------------------------- Mapper 406 ------------------------------
|
||||
|
||||
static DECLFW(M406CMDWrite) {
|
||||
MMC3_CMDWrite((A & 0xFFFE) | ((A & 2) >> 1), V);
|
||||
}
|
||||
|
||||
static DECLFW(M406IRQWrite) {
|
||||
MMC3_IRQWrite((A & 0xFFFE) | ((A & 2) >> 1), V);
|
||||
}
|
||||
|
||||
static DECLFW(M406Write) {
|
||||
}
|
||||
|
||||
static void M406_Power(void) {
|
||||
GenMMC3Power();
|
||||
// TODO : FLASH
|
||||
SetWriteHandler(0x8000, 0xBFFF, M406CMDWrite);
|
||||
SetWriteHandler(0xC000, 0xFFFF, M406IRQWrite);
|
||||
}
|
||||
|
||||
void Mapper406_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 256, 0, 0);
|
||||
info->Power = M406_Power;
|
||||
}
|
||||
|
||||
+245
-62
@@ -22,6 +22,15 @@
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
#define ABANKS MMC5SPRVPage
|
||||
#define BBANKS MMC5BGVPage
|
||||
#define SpriteON (PPU[1] & 0x10) //Show Sprite
|
||||
#define ScreenON (PPU[1] & 0x08) //Show screen
|
||||
#define PPUON (PPU[1] & 0x18) //PPU should operate
|
||||
#define Sprite16 (PPU[0] & 0x20) //Sprites 8x16/8x8
|
||||
|
||||
static void (*sfun)(int P);
|
||||
static void (*psfun)(void);
|
||||
|
||||
@@ -74,10 +83,11 @@ static INLINE void MMC5BGVROM_BANK8(uint32 V) {
|
||||
}
|
||||
}
|
||||
|
||||
static uint8 PRGBanks[4];
|
||||
static std::array<uint8,4> PRGBanks;
|
||||
static uint8 WRAMPage;
|
||||
static uint16 CHRBanksA[8], CHRBanksB[4];
|
||||
static uint8 WRAMMaskEnable[2];
|
||||
static std::array<uint16,8> CHRBanksA;
|
||||
static std::array<uint16,4> CHRBanksB;
|
||||
static std::array<uint8,2> WRAMMaskEnable;
|
||||
uint8 mmc5ABMode; /* A=0, B=1 */
|
||||
|
||||
static uint8 IRQScanline, IRQEnable;
|
||||
@@ -86,18 +96,20 @@ static uint8 CHRMode, NTAMirroring, NTFill, ATFill;
|
||||
static uint8 MMC5IRQR;
|
||||
static uint8 MMC5LineCounter;
|
||||
static uint8 mmc5psize, mmc5vsize;
|
||||
static uint8 mul[2];
|
||||
static std::array<uint8,2> mul;
|
||||
|
||||
static uint32 WRAMSIZE = 0;
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint8 *MMC5fill = NULL;
|
||||
static uint8 *ExRAM = NULL;
|
||||
static uint8 MMC5battery = 0;
|
||||
|
||||
static uint8 MMC5WRAMsize; //configuration, not state
|
||||
static uint8 MMC5WRAMIndex[8]; //configuration, not state
|
||||
const int MMC5WRAMMAX = 1<<7; // 7 bits in register interface (real MMC5 has only 4 pins, however)
|
||||
static uint8 MMC5WRAMsize=0; //configuration, not state
|
||||
static uint8 MMC5WRAMIndex[MMC5WRAMMAX]; //configuration, not state
|
||||
|
||||
static uint8 MMC5ROMWrProtect[4];
|
||||
static uint8 MMC5MemIn[5];
|
||||
static std::array<uint8,4> MMC5ROMWrProtect;
|
||||
static std::array<uint8,5> MMC5MemIn;
|
||||
|
||||
static void MMC5CHRA(void);
|
||||
static void MMC5CHRB(void);
|
||||
@@ -107,26 +119,50 @@ typedef struct __cartdata {
|
||||
uint8 size;
|
||||
} cartdata;
|
||||
|
||||
#define Sprite16 (PPU[0]& 0x20) //Sprites 8x16/8x8
|
||||
//#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V)>>10][(V)]
|
||||
static inline uint8 * MMC5BGVRAMADR(uint32 A) {
|
||||
#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)]
|
||||
|
||||
uint8* MMC5BGVRAMADR(uint32 A)
|
||||
{
|
||||
if(newppu)
|
||||
{
|
||||
if(Sprite16)
|
||||
{
|
||||
bool isPattern = PPUON != 0;
|
||||
if (ppuphase == PPUPHASE_OBJ && isPattern)
|
||||
return &ABANKS[(A) >> 10][(A)];
|
||||
if (ppuphase == PPUPHASE_BG && isPattern)
|
||||
return &BBANKS[(A) >> 10][(A)];
|
||||
else if(mmc5ABMode == 0)
|
||||
return &ABANKS[(A) >> 10][(A)];
|
||||
else
|
||||
return &BBANKS[(A) >> 10][(A)];
|
||||
}
|
||||
else return &ABANKS[(A) >> 10][(A)];;
|
||||
}
|
||||
|
||||
if (!Sprite16) {
|
||||
if (mmc5ABMode == 0)
|
||||
return &MMC5SPRVPage[(A) >> 10][(A)];
|
||||
return &ABANKS[(A) >> 10][(A)];
|
||||
else
|
||||
return &MMC5BGVPage[(A) >> 10][(A)];
|
||||
} else return &MMC5BGVPage[(A) >> 10][(A)];
|
||||
return &BBANKS[(A) >> 10][(A)];
|
||||
} else return &BBANKS[(A) >> 10][(A)];
|
||||
}
|
||||
|
||||
static void mmc5_PPUWrite(uint32 A, uint8 V) {
|
||||
uint32 tmp = A;
|
||||
extern uint8 PALRAM[0x20];
|
||||
extern uint8 UPALRAM[0x03];
|
||||
|
||||
if (tmp >= 0x3F00) {
|
||||
// hmmm....
|
||||
if (!(tmp & 0xf))
|
||||
PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = V & 0x3F;
|
||||
else if (tmp & 3) PALRAM[(tmp & 0x1f)] = V & 0x3f;
|
||||
if (!(tmp & 3)) {
|
||||
if (!(tmp & 0xC)) {
|
||||
PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = V & 0x3F;
|
||||
PALRAM[0x10] = PALRAM[0x14] = PALRAM[0x18] = PALRAM[0x1C] = V & 0x3F;
|
||||
}
|
||||
else
|
||||
UPALRAM[((tmp & 0xC) >> 2) - 1] = V & 0x3F;
|
||||
} else
|
||||
PALRAM[tmp & 0x1F] = V & 0x3F;
|
||||
} else if (tmp < 0x2000) {
|
||||
if (PPUCHRRAM & (1 << (tmp >> 10)))
|
||||
VPage[tmp >> 10][tmp] = V;
|
||||
@@ -136,16 +172,105 @@ static void mmc5_PPUWrite(uint32 A, uint8 V) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8 FASTCALL mmc5_PPURead(uint32 A) {
|
||||
if (A < 0x2000) {
|
||||
if (ppuphase == PPUPHASE_BG
|
||||
//zero 03-aug-2014 - added this to fix Uchuu Keibitai SDF. The game reads NT entries from CHR rom while PPU is disabled.
|
||||
//obviously we have enormous numbers of bugs springing from our terrible emulation of ppu-disabled states, but this does the job for fixing this one
|
||||
&& (PPU[1] & 0x10)
|
||||
)
|
||||
return *MMC5BGVRAMADR(A);
|
||||
else return MMC5SPRVPage[(A) >> 10][(A)];
|
||||
} else {
|
||||
extern uint32 NTRefreshAddr;
|
||||
uint8 FASTCALL mmc5_PPURead(uint32 A)
|
||||
{
|
||||
bool split = false;
|
||||
if(newppu)
|
||||
{
|
||||
if((MMC5HackSPMode&0x80) && !(MMC5HackCHRMode&2))
|
||||
{
|
||||
int target = MMC5HackSPMode&0x1f;
|
||||
int side = MMC5HackSPMode&0x40;
|
||||
int ht = NTRefreshAddr&31;
|
||||
|
||||
if(side==0)
|
||||
{
|
||||
if(ht<target) split = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ht>=target) split = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (A < 0x2000)
|
||||
{
|
||||
if(Sprite16)
|
||||
{
|
||||
bool isPattern = !!PPUON;
|
||||
if (ppuphase == PPUPHASE_OBJ && isPattern)
|
||||
return ABANKS[(A) >> 10][(A)];
|
||||
if (ppuphase == PPUPHASE_BG && isPattern)
|
||||
{
|
||||
if(split)
|
||||
return MMC5HackVROMPTR[MMC5HackSPPage*0x1000 + (A&0xFFF)];
|
||||
|
||||
//uhhh call through to this more sophisticated function, only if it's really needed?
|
||||
//we should probably reuse it completely, if we can
|
||||
if (MMC5HackCHRMode == 1)
|
||||
return *FCEUPPU_GetCHR(A,NTRefreshAddr);
|
||||
|
||||
return BBANKS[(A) >> 10][(A)];
|
||||
}
|
||||
else if(mmc5ABMode == 0)
|
||||
return ABANKS[(A) >> 10][(A)];
|
||||
else
|
||||
return BBANKS[(A) >> 10][(A)];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ppuphase == PPUPHASE_BG && ScreenON)
|
||||
{
|
||||
if(split)
|
||||
return MMC5HackVROMPTR[MMC5HackSPPage*0x1000 + (A&0xFFF)];
|
||||
|
||||
//uhhh call through to this more sophisticated function, only if it's really needed?
|
||||
//we should probably reuse it completely, if we can
|
||||
if (MMC5HackCHRMode == 1)
|
||||
return *FCEUPPU_GetCHR(A,NTRefreshAddr);
|
||||
}
|
||||
|
||||
return ABANKS[(A) >> 10][(A)];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(split)
|
||||
{
|
||||
static const int kHack = -1; //dunno if theres science to this or if it just fixes SDF (cant be bothered to think about it)
|
||||
int linetile = (newppu_get_scanline()+kHack)/8 + MMC5HackSPScroll;
|
||||
|
||||
//REF NT: return 0x2000 | (v << 0xB) | (h << 0xA) | (vt << 5) | ht;
|
||||
//REF AT: return 0x2000 | (v << 0xB) | (h << 0xA) | 0x3C0 | ((vt & 0x1C) << 1) | ((ht & 0x1C) >> 2);
|
||||
|
||||
if((A&0x3FF)>=0x3C0)
|
||||
{
|
||||
A &= ~(0x1C<<1); //mask off VT
|
||||
A |= (linetile&0x1C)<<1; //mask on adjusted VT
|
||||
return ExRAM[A & 0x3FF];
|
||||
}
|
||||
else
|
||||
{
|
||||
A &= ~((0x1F<<5) | (1<<0xB)); //mask off VT and V
|
||||
A |= (linetile&31)<<5; //mask on adjusted VT (V doesnt make any sense, I think)
|
||||
return ExRAM[A & 0x3FF];
|
||||
}
|
||||
}
|
||||
|
||||
if (MMC5HackCHRMode == 1)
|
||||
{
|
||||
if((A&0x3FF)>=0x3C0)
|
||||
{
|
||||
uint8 byte = ExRAM[NTRefreshAddr & 0x3ff];
|
||||
//get attribute part and paste it 4x across the byte
|
||||
byte >>= 6;
|
||||
byte *= 0x55;
|
||||
return byte;
|
||||
}
|
||||
}
|
||||
|
||||
return vnapage[(A >> 10) & 0x3][A & 0x3FF];
|
||||
}
|
||||
}
|
||||
@@ -194,6 +319,8 @@ int DetectMMC5WRAMSize(uint32 crc32) {
|
||||
}
|
||||
|
||||
static void BuildWRAMSizeTable(void) {
|
||||
bool other = false; // non-standard configuration
|
||||
// fill first 8 entries
|
||||
int x;
|
||||
for (x = 0; x < 8; x++) {
|
||||
switch (MMC5WRAMsize) {
|
||||
@@ -201,9 +328,22 @@ static void BuildWRAMSizeTable(void) {
|
||||
case 1: MMC5WRAMIndex[x] = (x > 3) ? 255 : 0; break; //0,0,0,0,X,X,X,X
|
||||
case 2: MMC5WRAMIndex[x] = (x & 4) >> 2; break; //0,0,0,0,1,1,1,1
|
||||
case 4: MMC5WRAMIndex[x] = (x > 3) ? 255 : (x & 3); break; //0,1,2,3,X,X,X,X
|
||||
case 8: MMC5WRAMIndex[x] = x; break; //0,1,2,3,4,5,6,7
|
||||
case 8: MMC5WRAMIndex[x] = x; break; //0,1,2,3,4,5,6,7
|
||||
default: MMC5WRAMIndex[x] = x; other = true; break; //0,1,2...
|
||||
}
|
||||
}
|
||||
// extend to fill complete table
|
||||
if (other)
|
||||
{
|
||||
for (x = 0; x < MMC5WRAMMAX && x < MMC5WRAMsize; ++x) MMC5WRAMIndex[x] = x; // linear mapping
|
||||
for (x = MMC5WRAMsize; x < MMC5WRAMMAX; ++x) MMC5WRAMIndex[x] = MMC5WRAMIndex[x-MMC5WRAMsize]; // repeat to fill table
|
||||
// theoretically the table fill should decompose into powers of two for possible mismatched SRAM combos,
|
||||
// but I don't want to complicate the code with unnecessary hypotheticals
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = 8; x < MMC5WRAMMAX; ++x) MMC5WRAMIndex[x] = MMC5WRAMIndex[x & 7]; // fill table, repeating groups of 8
|
||||
}
|
||||
}
|
||||
|
||||
static void MMC5CHRA(void) {
|
||||
@@ -271,7 +411,7 @@ static void MMC5CHRB(void) {
|
||||
}
|
||||
|
||||
static void MMC5WRAM(uint32 A, uint32 V) {
|
||||
V = MMC5WRAMIndex[V & 7];
|
||||
V = MMC5WRAMIndex[V & (MMC5WRAMMAX-1)];
|
||||
if (V != 255) {
|
||||
setprg8r(0x10, A, V);
|
||||
FCEU_CheatAddRAM(8, 0x6000, (WRAM + ((V * 8192) & (WRAMSIZE - 1))));
|
||||
@@ -296,8 +436,8 @@ static void MMC5PRG(void) {
|
||||
MMC5MemIn[1] = MMC5MemIn[2] = 1;
|
||||
} else {
|
||||
MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0;
|
||||
MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE);
|
||||
MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1);
|
||||
MMC5WRAM(0x8000, PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE);
|
||||
MMC5WRAM(0xA000, (PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE) + 1);
|
||||
}
|
||||
MMC5MemIn[3] = MMC5MemIn[4] = 1;
|
||||
MMC5ROMWrProtect[2] = MMC5ROMWrProtect[3] = 1;
|
||||
@@ -310,8 +450,8 @@ static void MMC5PRG(void) {
|
||||
setprg16(0x8000, (PRGBanks[1] & 0x7F) >> 1);
|
||||
} else {
|
||||
MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0;
|
||||
MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE);
|
||||
MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1);
|
||||
MMC5WRAM(0x8000, PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE);
|
||||
MMC5WRAM(0xA000, (PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE) + 1);
|
||||
}
|
||||
if (PRGBanks[2] & 0x80) {
|
||||
MMC5ROMWrProtect[2] = 1;
|
||||
@@ -319,7 +459,7 @@ static void MMC5PRG(void) {
|
||||
setprg8(0xC000, PRGBanks[2] & 0x7F);
|
||||
} else {
|
||||
MMC5ROMWrProtect[2] = 0;
|
||||
MMC5WRAM(0xC000, PRGBanks[2] & 7);
|
||||
MMC5WRAM(0xC000, PRGBanks[2] & (MMC5WRAMMAX-1));
|
||||
}
|
||||
MMC5MemIn[4] = 1;
|
||||
MMC5ROMWrProtect[3] = 1;
|
||||
@@ -333,7 +473,7 @@ static void MMC5PRG(void) {
|
||||
MMC5MemIn[1 + x] = 1;
|
||||
} else {
|
||||
MMC5ROMWrProtect[x] = 0;
|
||||
MMC5WRAM(0x8000 + (x << 13), PRGBanks[x] & 7);
|
||||
MMC5WRAM(0x8000 + (x << 13), PRGBanks[x] & (MMC5WRAMMAX-1));
|
||||
}
|
||||
MMC5MemIn[4] = 1;
|
||||
MMC5ROMWrProtect[3] = 1;
|
||||
@@ -396,7 +536,7 @@ static DECLFW(Mapper5_write) {
|
||||
break;
|
||||
case 0x5113:
|
||||
WRAMPage = V;
|
||||
MMC5WRAM(0x6000, V & 7);
|
||||
MMC5WRAM(0x6000, V & (MMC5WRAMMAX-1));
|
||||
break;
|
||||
case 0x5114:
|
||||
case 0x5115:
|
||||
@@ -492,7 +632,7 @@ void MMC5Synco(void) {
|
||||
case 3: PPUNTARAM &= ~(1 << x); vnapage[x] = MMC5fill; break;
|
||||
}
|
||||
}
|
||||
MMC5WRAM(0x6000, WRAMPage & 7);
|
||||
MMC5WRAM(0x6000, WRAMPage & (MMC5WRAMMAX-1));
|
||||
if (!mmc5ABMode) {
|
||||
MMC5CHRB();
|
||||
MMC5CHRA();
|
||||
@@ -755,22 +895,42 @@ void NSFMMC5_Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
MMC5WRAMsize = 0;
|
||||
FCEU_gfree(ExRAM);
|
||||
ExRAM = NULL;
|
||||
}
|
||||
|
||||
static void GenMMC5Reset(void) {
|
||||
int x;
|
||||
static void GenMMC5Power(void) {
|
||||
|
||||
for (x = 0; x < 4; x++) PRGBanks[x] = ~0;
|
||||
for (x = 0; x < 8; x++) CHRBanksA[x] = ~0;
|
||||
for (x = 0; x < 4; x++) CHRBanksB[x] = ~0;
|
||||
WRAMMaskEnable[0] = WRAMMaskEnable[1] = ~0;
|
||||
|
||||
mmc5psize = mmc5vsize = 3;
|
||||
PRGBanks.fill(0xFF);
|
||||
WRAMPage = 0;
|
||||
CHRBanksA.fill(0xFF);
|
||||
CHRBanksB.fill(0xFF);
|
||||
WRAMMaskEnable.fill(0xFF);
|
||||
mmc5ABMode = 0;
|
||||
IRQScanline = 0;
|
||||
IRQEnable = 0;
|
||||
CHRMode = 0;
|
||||
|
||||
NTAMirroring = NTFill = ATFill = 0xFF;
|
||||
MMC5IRQR = 0;
|
||||
MMC5LineCounter = 0;
|
||||
mmc5psize = mmc5vsize = 3;
|
||||
mul.fill(0);
|
||||
|
||||
MMC5ROMWrProtect.fill(0);
|
||||
MMC5MemIn.fill(0);
|
||||
|
||||
// MMC5fill is and 8-bit tile index, and a 2-bit attribute implented as a mirrored nametable
|
||||
u8 nval = MMC5fill[0x000];
|
||||
u8 aval = MMC5fill[0x3C0] & 3; aval = aval | (aval << 2) | (aval << 4) | (aval << 6);
|
||||
FCEU_dwmemset(MMC5fill + 0x000, nval | (nval<<8) | (nval<<16) | (nval<<24), 0x3C0);
|
||||
FCEU_dwmemset(MMC5fill + 0x3C0, aval | (aval<<8) | (aval<<16) | (aval<<24), 0x040);
|
||||
|
||||
if(MMC5battery == 0) {
|
||||
FCEU_MemoryRand(WRAM, MMC5WRAMsize * 8 * 1024);
|
||||
FCEU_MemoryRand(MMC5fill,1024);
|
||||
FCEU_MemoryRand(ExRAM,1024);
|
||||
}
|
||||
|
||||
MMC5Synco();
|
||||
|
||||
@@ -793,11 +953,11 @@ static void GenMMC5Reset(void) {
|
||||
}
|
||||
|
||||
static SFORMAT MMC5_StateRegs[] = {
|
||||
{ PRGBanks, 4, "PRGB" },
|
||||
{ CHRBanksA, 16, "CHRA" },
|
||||
{ CHRBanksB, 8, "CHRB" },
|
||||
{ &PRGBanks, 4, "PRGB" },
|
||||
{ &CHRBanksA, 16, "CHRA" },
|
||||
{ &CHRBanksB, 8, "CHRB" },
|
||||
{ &WRAMPage, 1, "WRMP" },
|
||||
{ WRAMMaskEnable, 2, "WRME" },
|
||||
{ &WRAMMaskEnable, 2, "WRME" },
|
||||
{ &mmc5ABMode, 1, "ABMD" },
|
||||
{ &IRQScanline, 1, "IRQS" },
|
||||
{ &IRQEnable, 1, "IRQE" },
|
||||
@@ -811,9 +971,9 @@ static SFORMAT MMC5_StateRegs[] = {
|
||||
{ &MMC5LineCounter, 1, "LCTR" },
|
||||
{ &mmc5psize, 1, "PSIZ" },
|
||||
{ &mmc5vsize, 1, "VSIZ" },
|
||||
{ mul, 2, "MUL2" },
|
||||
{ MMC5ROMWrProtect, 4, "WRPR" },
|
||||
{ MMC5MemIn, 5, "MEMI" },
|
||||
{ &mul, 2, "MUL2" },
|
||||
{ &MMC5ROMWrProtect, 4, "WRPR" },
|
||||
{ &MMC5MemIn, 5, "MEMI" },
|
||||
|
||||
{ &MMC5Sound.wl[0], 2 | FCEUSTATE_RLSB, "SDW0" },
|
||||
{ &MMC5Sound.wl[1], 2 | FCEUSTATE_RLSB, "SDW1" },
|
||||
@@ -836,13 +996,17 @@ static SFORMAT MMC5_StateRegs[] = {
|
||||
|
||||
static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
|
||||
if (wsize) {
|
||||
WRAM = (uint8*)FCEU_gmalloc(wsize * 1024);
|
||||
WRAM = (uint8*)FCEU_malloc(wsize * 1024);
|
||||
FCEU_MemoryRand(WRAM, wsize * 1024);
|
||||
SetupCartPRGMapping(0x10, WRAM, wsize * 1024, 1);
|
||||
AddExState(WRAM, wsize * 1024, 0, "WRAM");
|
||||
}
|
||||
|
||||
MMC5fill = (uint8*)FCEU_gmalloc(1024);
|
||||
ExRAM = (uint8*)FCEU_gmalloc(1024);
|
||||
MMC5fill = (uint8*)FCEU_malloc(1024);
|
||||
ExRAM = (uint8*)FCEU_malloc(1024);
|
||||
|
||||
FCEU_MemoryRand(MMC5fill,1024);
|
||||
FCEU_MemoryRand(ExRAM,1024);
|
||||
|
||||
AddExState(ExRAM, 1024, 0, "ERAM");
|
||||
AddExState(&MMC5HackSPMode, 1, 0, "SPLM");
|
||||
@@ -854,14 +1018,26 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
|
||||
MMC5WRAMsize = wsize / 8;
|
||||
BuildWRAMSizeTable();
|
||||
GameStateRestore = MMC5_StateRestore;
|
||||
info->Power = GenMMC5Reset;
|
||||
info->Power = GenMMC5Power;
|
||||
|
||||
MMC5battery = battery;
|
||||
if (battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
if (wsize <= 16)
|
||||
info->SaveGameLen[0] = 8192;
|
||||
if (info->ines2)
|
||||
{
|
||||
info->SaveGameLen[0] = info->battery_wram_size;
|
||||
}
|
||||
else
|
||||
info->SaveGameLen[0] = 32768;
|
||||
{
|
||||
//this is more complex than it looks because it MUST BE, I guess. is there an assumption that only 8KB of 16KB is battery backed? That's NES mappers for you
|
||||
//I added 64KB for the new 64KB homebrews
|
||||
if (wsize <= 16)
|
||||
info->SaveGameLen[0] = 8192;
|
||||
else if(wsize == 64)
|
||||
info->SaveGameLen[0] = 64*1024;
|
||||
else
|
||||
info->SaveGameLen[0] = 32768;
|
||||
}
|
||||
}
|
||||
|
||||
MMC5HackVROMMask = CHRmask4[0];
|
||||
@@ -877,7 +1053,14 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
|
||||
}
|
||||
|
||||
void Mapper5_Init(CartInfo *info) {
|
||||
WRAMSIZE = DetectMMC5WRAMSize(info->CRC32);
|
||||
if (info->ines2)
|
||||
{
|
||||
WRAMSIZE = (info->wram_size + info->battery_wram_size) / 1024;
|
||||
}
|
||||
else
|
||||
{
|
||||
WRAMSIZE = DetectMMC5WRAMSize(info->CRC32);
|
||||
}
|
||||
GenMMC5_Init(info, WRAMSIZE, info->battery);
|
||||
}
|
||||
|
||||
|
||||
+28
-4
@@ -57,9 +57,23 @@ static SFORMAT N106_StateRegs[] = {
|
||||
{ PRG, 3, "PRG" },
|
||||
{ CHR, 8, "CHR" },
|
||||
{ NTAPage, 4, "NTA" },
|
||||
{ &gorfus, 1, "GORF" },
|
||||
{ &dopol, 1, "DOPO" },
|
||||
{ &gorko, 1, "GORK" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void SyncMirror()
|
||||
{
|
||||
switch(gorko) {
|
||||
case 0: setmirror(MI_0); break;
|
||||
case 1: setmirror(MI_V); break;
|
||||
case 2: setmirror(MI_H); break;
|
||||
case 3: setmirror(MI_0); break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void SyncPRG(void) {
|
||||
setprg8(0x8000, PRG[0]);
|
||||
setprg8(0xa000, PRG[1]);
|
||||
@@ -143,7 +157,10 @@ static void FixCache(int a, int V) {
|
||||
case 0x02: FreqCache[w] &= ~0x0000FF00; FreqCache[w] |= V << 8; break;
|
||||
case 0x04:
|
||||
FreqCache[w] &= ~0x00030000; FreqCache[w] |= (V & 3) << 16;
|
||||
LengthCache[w] = (8 - ((V >> 2) & 7)) << 2;
|
||||
// something wrong here http://www.romhacking.net/forum/index.php?topic=21907.msg306903#msg306903
|
||||
// LengthCache[w] = (8 - ((V >> 2) & 7)) << 2;
|
||||
// fix be like in https://github.com/SourMesen/Mesen/blob/cda0a0bdcb5525480784f4b8c71de6fc7273b570/Core/Namco163Audio.h#L61
|
||||
LengthCache[w] = 256 - (V & 0xFC);
|
||||
break;
|
||||
case 0x07: EnvCache[w] = (double)(V & 0xF) * 576716; break;
|
||||
}
|
||||
@@ -179,8 +196,11 @@ static DECLFW(Mapper19_write) {
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 0xE000:
|
||||
gorko = V & 0xC0;
|
||||
PRG[0] = V & 0x3F;
|
||||
if(is210) {
|
||||
gorko = V>>6;
|
||||
SyncMirror();
|
||||
}
|
||||
SyncPRG();
|
||||
break;
|
||||
case 0xE800:
|
||||
@@ -331,6 +351,7 @@ static void DoNamcoSound(int32 *Wave, int Count) {
|
||||
|
||||
static void Mapper19_StateRestore(int version) {
|
||||
SyncPRG();
|
||||
SyncMirror();
|
||||
FixNTAR();
|
||||
FixCRR();
|
||||
int x;
|
||||
@@ -382,8 +403,8 @@ static void N106_Power(void) {
|
||||
FixCRR();
|
||||
|
||||
if (!battery) {
|
||||
FCEU_dwmemset(WRAM, 0, 8192);
|
||||
FCEU_dwmemset(IRAM, 0, 128);
|
||||
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
|
||||
FCEU_MemoryRand(IRAM, sizeof(IRAM), true);
|
||||
}
|
||||
for (x = 0x40; x < 0x80; x++)
|
||||
FixCache(x, IRAM[x]);
|
||||
@@ -401,6 +422,8 @@ void Mapper19_Init(CartInfo *info) {
|
||||
if (FSettings.SndRate)
|
||||
Mapper19_ESI();
|
||||
|
||||
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
|
||||
FCEU_MemoryRand(IRAM, sizeof(IRAM), true);
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(IRAM, 128, 0, "IRAM");
|
||||
AddExState(N106_StateRegs, ~0, 0, 0);
|
||||
@@ -422,6 +445,7 @@ void Mapper210_Init(CartInfo *info) {
|
||||
is210 = 1;
|
||||
GameStateRestore = Mapper210_StateRestore;
|
||||
info->Power = N106_Power;
|
||||
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(N106_StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ static int16 pcm_addr, pcm_size, pcm_latch, pcm_clock = 0xE1;
|
||||
static writefunc defapuwrite[64];
|
||||
static readfunc defapuread[64];
|
||||
|
||||
static uint32 WRAMSIZE;
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ cpu410x, 16, "REGC" },
|
||||
@@ -265,6 +268,13 @@ static void UNLOneBusPower(void) {
|
||||
SetWriteHandler(0x4100, 0x410f, UNLOneBusWriteCPU410X);
|
||||
SetWriteHandler(0x8000, 0xffff, UNLOneBusWriteMMC3);
|
||||
|
||||
if (WRAMSIZE) {
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
SetWriteHandler(0x6000, 0x6000 + ((WRAMSIZE - 1) & 0x1fff), CartBW);
|
||||
SetReadHandler(0x6000, 0x6000 + ((WRAMSIZE - 1) & 0x1fff), CartBR);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
}
|
||||
|
||||
Sync();
|
||||
}
|
||||
|
||||
@@ -282,9 +292,16 @@ static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void UNLOneBusClose(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
void UNLOneBus_Init(CartInfo *info) {
|
||||
info->Power = UNLOneBusPower;
|
||||
info->Reset = UNLOneBusReset;
|
||||
info->Close = UNLOneBusClose;
|
||||
|
||||
if (((*(uint32*)&(info->MD5)) == 0x305fcdc3) || // PowerJoy Supermax Carts
|
||||
((*(uint32*)&(info->MD5)) == 0x6abfce8e))
|
||||
@@ -294,4 +311,17 @@ void UNLOneBus_Init(CartInfo *info) {
|
||||
MapIRQHook = UNLOneBusCpuHook;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
|
||||
WRAMSIZE = 8 * 1024;
|
||||
if (info->ines2)
|
||||
WRAMSIZE = info->wram_size + info->battery_wram_size;
|
||||
if (WRAMSIZE) {
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* PEC-586 FC based computer series by DUNDA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
extern u64 xoroshiro128plus_next(); // deterministic random
|
||||
|
||||
static DECLFR(UNLRT01Read) {
|
||||
// u16 i, prot_areas[2][2] = {
|
||||
// { 0x8E80, 0x8EFF },
|
||||
@@ -33,7 +35,7 @@ static DECLFR(UNLRT01Read) {
|
||||
// };
|
||||
if(((A >= 0xCE80) && (A < 0xCF00)) ||
|
||||
((A >= 0xFE80) && (A < 0xFF00))) {
|
||||
return 0xF2 | (rand() & 0x0D);
|
||||
return 0xF2 | (xoroshiro128plus_next() & 0x0D);
|
||||
} else
|
||||
return CartBR(A);
|
||||
}
|
||||
|
||||
+44
-28
@@ -40,38 +40,38 @@ static uint16 latcha;
|
||||
static uint8 *flashdata;
|
||||
static uint32 *flash_write_count;
|
||||
static uint8 *FlashPage[32];
|
||||
static uint32 *FlashWriteCountPage[32];
|
||||
static uint8 flashloaded = false;
|
||||
//static uint32 *FlashWriteCountPage[32];
|
||||
//static uint8 flashloaded = false;
|
||||
|
||||
static uint8 flash_save=0, flash_state=0, flash_mode=0, flash_bank;
|
||||
static void (*WLSync)(void);
|
||||
static void (*WHSync)(void);
|
||||
|
||||
static INLINE void setfpageptr(int s, uint32 A, uint8 *p) {
|
||||
uint32 AB = A >> 11;
|
||||
int x;
|
||||
|
||||
if (p)
|
||||
for (x = (s >> 1) - 1; x >= 0; x--) {
|
||||
FlashPage[AB + x] = p - A;
|
||||
}
|
||||
else
|
||||
for (x = (s >> 1) - 1; x >= 0; x--) {
|
||||
FlashPage[AB + x] = 0;
|
||||
}
|
||||
static INLINE void setfpageptr(int s, uint32 A, uint8 *p) {
|
||||
uint32 AB = A >> 11;
|
||||
int x;
|
||||
|
||||
if (p)
|
||||
for (x = (s >> 1) - 1; x >= 0; x--) {
|
||||
FlashPage[AB + x] = p - A;
|
||||
}
|
||||
else
|
||||
for (x = (s >> 1) - 1; x >= 0; x--) {
|
||||
FlashPage[AB + x] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void setfprg16(uint32 A, uint32 V) {
|
||||
if (PRGsize[0] >= 16384) {
|
||||
V &= PRGmask16[0];
|
||||
setfpageptr(16, A, flashdata ? (&flashdata[V << 14]) : 0);
|
||||
} else {
|
||||
uint32 VA = V << 3;
|
||||
int x;
|
||||
|
||||
for (x = 0; x < 8; x++)
|
||||
setfpageptr(2, A + (x << 11), flashdata ? (&flashdata[((VA + x) & PRGmask2[0]) << 11]) : 0);
|
||||
}
|
||||
void setfprg16(uint32 A, uint32 V) {
|
||||
if (PRGsize[0] >= 16384) {
|
||||
V &= PRGmask16[0];
|
||||
setfpageptr(16, A, flashdata ? (&flashdata[V << 14]) : 0);
|
||||
} else {
|
||||
uint32 VA = V << 3;
|
||||
int x;
|
||||
|
||||
for (x = 0; x < 8; x++)
|
||||
setfpageptr(2, A + (x << 11), flashdata ? (&flashdata[((VA + x) & PRGmask2[0]) << 11]) : 0);
|
||||
}
|
||||
}
|
||||
|
||||
void inc_flash_write_count(uint8 bank, uint32 A)
|
||||
@@ -240,8 +240,24 @@ void UNROM512_Init(CartInfo *info) {
|
||||
chrram_mask = 0x20;
|
||||
else
|
||||
chrram_mask = 0x60;
|
||||
|
||||
SetupCartMirroring(info->mirror,(info->mirror>=MI_0)?0:1,0);
|
||||
|
||||
int mirror = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2);
|
||||
switch (mirror)
|
||||
{
|
||||
case 0: // hard horizontal, internal
|
||||
SetupCartMirroring(MI_H, 1, NULL);
|
||||
break;
|
||||
case 1: // hard vertical, internal
|
||||
SetupCartMirroring(MI_V, 1, NULL);
|
||||
break;
|
||||
case 2: // switchable 1-screen, internal (flags: 4-screen + horizontal)
|
||||
SetupCartMirroring(MI_0, 0, NULL);
|
||||
break;
|
||||
case 3: // hard four screen, last 8k of 32k RAM (flags: 4-screen + vertical)
|
||||
SetupCartMirroring( 4, 1, VROM + (info->vram_size - 8192));
|
||||
break;
|
||||
}
|
||||
|
||||
bus_conflict = !info->battery;
|
||||
latcheinit = 0;
|
||||
WLSync = UNROM512LSync;
|
||||
@@ -266,4 +282,4 @@ void UNROM512_Init(CartInfo *info) {
|
||||
}
|
||||
AddExState(&latche, 1, 0, "LATC");
|
||||
AddExState(&bus_conflict, 1, 0, "BUSC");
|
||||
}
|
||||
}
|
||||
|
||||
+49
-92
@@ -20,14 +20,14 @@
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 isPirate, is22;
|
||||
static bool isPirate;
|
||||
static uint8 is22, reg1mask, reg2mask;
|
||||
static uint16 IRQCount;
|
||||
static uint8 IRQLatch, IRQa;
|
||||
static uint8 prgreg[2], chrreg[8];
|
||||
static uint16 chrhi[8];
|
||||
static uint8 regcmd, irqcmd, mirr, big_bank;
|
||||
static uint16 acount = 0;
|
||||
static uint16 weirdo = 0;
|
||||
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
@@ -37,6 +37,7 @@ static SFORMAT StateRegs[] =
|
||||
{ prgreg, 2, "PREG" },
|
||||
{ chrreg, 8, "CREG" },
|
||||
{ chrhi, 16, "CRGH" },
|
||||
{ &acount, 2, "ACNT" },
|
||||
{ ®cmd, 1, "CMDR" },
|
||||
{ &irqcmd, 1, "CMDI" },
|
||||
{ &mirr, 1, "MIRR" },
|
||||
@@ -61,15 +62,8 @@ static void Sync(void) {
|
||||
setchr8(0);
|
||||
else{
|
||||
uint8 i;
|
||||
if(!weirdo)
|
||||
for (i = 0; i < 8; i++)
|
||||
setchr1(i << 10, (chrhi[i] | chrreg[i]) >> is22);
|
||||
else {
|
||||
setchr1(0x0000, 0xFC);
|
||||
setchr1(0x0400, 0xFD);
|
||||
setchr1(0x0800, 0xFF);
|
||||
weirdo--;
|
||||
}
|
||||
for (i = 0; i < 8; i++)
|
||||
setchr1(i << 10, (chrhi[i] | chrreg[i]) >> is22);
|
||||
}
|
||||
switch (mirr & 0x3) {
|
||||
case 0: setmirror(MI_V); break;
|
||||
@@ -80,7 +74,7 @@ static void Sync(void) {
|
||||
}
|
||||
|
||||
static DECLFW(VRC24Write) {
|
||||
A &= 0xF003;
|
||||
A = A & 0xF000 | !!(A & reg2mask) << 1 | !!(A & reg1mask);
|
||||
if ((A >= 0xB000) && (A <= 0xE003)) {
|
||||
if (UNIFchrrama)
|
||||
big_bank = (V & 8) << 2; // my personally many-in-one feature ;) just for support pirate cart 2-in-1
|
||||
@@ -126,61 +120,17 @@ static DECLFW(VRC24Write) {
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(M21Write) {
|
||||
A = (A & 0xF000) | ((A >> 1) & 0x3); // Ganbare Goemon Gaiden 2 - Tenka no Zaihou (J) [!] isn't mapper 21 actually,
|
||||
// it's mapper 23 by wirings
|
||||
VRC24Write(A, V);
|
||||
}
|
||||
|
||||
static DECLFW(M22Write) {
|
||||
if (A == 0xC007) { // Ganbare Goemon Gaiden does strange things!!! at the end credits
|
||||
weirdo = 8; // quick dirty hack, seems there is no other games with such PCB, so
|
||||
// we never know if it will not work for something else lol
|
||||
static void VRC24Power(void) {
|
||||
big_bank = 0x20;
|
||||
Sync();
|
||||
if (WRAM) {
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
A |= ((A >> 2) & 0x3); // It's just swapped lines from 21 mapper
|
||||
//
|
||||
VRC24Write((A & 0xF000) | ((A >> 1) & 1) | ((A << 1) & 2), V);
|
||||
}
|
||||
|
||||
static DECLFW(M23Write) {
|
||||
A |= ((A >> 2) & 0x3) | ((A >> 4) & 0x3) | ((A >> 6) & 0x3);// actually there is many-in-one mapper source, some pirate or
|
||||
// licensed games use various address bits for registers
|
||||
VRC24Write(A, V);
|
||||
}
|
||||
|
||||
static void M21Power(void) {
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M21Write);
|
||||
}
|
||||
|
||||
static void M22Power(void) {
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M22Write);
|
||||
}
|
||||
|
||||
static void M23Power(void) {
|
||||
big_bank = 0x20;
|
||||
Sync();
|
||||
setprg8r(0x10, 0x6000, 0); // Only two Goemon games are have battery backed RAM, three more shooters
|
||||
// (Parodius Da!, Gradius 2 and Crisis Force uses 2k or SRAM at 6000-67FF only
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M23Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M25Power(void) {
|
||||
big_bank = 0x20;
|
||||
Sync();
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M22Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
SetWriteHandler(0x8000, 0xFFFF, VRC24Write);
|
||||
}
|
||||
|
||||
void VRC24IRQHook(int a) {
|
||||
@@ -210,26 +160,8 @@ static void VRC24Close(void) {
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
void Mapper21_Init(CartInfo *info) {
|
||||
isPirate = 0;
|
||||
is22 = 0;
|
||||
info->Power = M21Power;
|
||||
MapIRQHook = VRC24IRQHook;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Mapper22_Init(CartInfo *info) {
|
||||
isPirate = 0;
|
||||
is22 = 1;
|
||||
info->Power = M22Power;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void VRC24_Init(CartInfo *info) {
|
||||
static void VRC24_Init(CartInfo *info) {
|
||||
info->Power = VRC24Power;
|
||||
info->Close = VRC24Close;
|
||||
MapIRQHook = VRC24IRQHook;
|
||||
GameStateRestore = StateRestore;
|
||||
@@ -247,23 +179,48 @@ void VRC24_Init(CartInfo *info) {
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Mapper23_Init(CartInfo *info) {
|
||||
isPirate = 0;
|
||||
void Mapper21_Init(CartInfo *info) {
|
||||
isPirate = false;
|
||||
is22 = 0;
|
||||
info->Power = M23Power;
|
||||
reg1mask = 0x42;
|
||||
reg2mask = 0x84;
|
||||
VRC24_Init(info);
|
||||
}
|
||||
|
||||
void Mapper22_Init(CartInfo *info) {
|
||||
isPirate = false;
|
||||
is22 = 1;
|
||||
reg1mask = 2;
|
||||
reg2mask = 1;
|
||||
|
||||
// no IRQ (all mapper 22 games are VRC2)
|
||||
// no WRAM
|
||||
info->Power = VRC24Power;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Mapper23_Init(CartInfo *info) {
|
||||
isPirate = false;
|
||||
is22 = 0;
|
||||
reg1mask = 0x15;
|
||||
reg2mask = 0x2a;
|
||||
VRC24_Init(info);
|
||||
}
|
||||
|
||||
void Mapper25_Init(CartInfo *info) {
|
||||
isPirate = 0;
|
||||
isPirate = false;
|
||||
is22 = 0;
|
||||
info->Power = M25Power;
|
||||
reg1mask = 0xa;
|
||||
reg2mask = 0x5;
|
||||
VRC24_Init(info);
|
||||
}
|
||||
|
||||
void UNLT230_Init(CartInfo *info) {
|
||||
isPirate = 1;
|
||||
isPirate = true;
|
||||
is22 = 0;
|
||||
info->Power = M23Power;
|
||||
reg1mask = 0x15;
|
||||
reg2mask = 0x2a;
|
||||
VRC24_Init(info);
|
||||
}
|
||||
|
||||
+159
-120
@@ -1,7 +1,7 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
* Copyright (C) 2005-2019 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,25 +17,118 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* VRC-5 (CAI Shogakko no Sansu)
|
||||
* VRC-V (CAI Shogakko no Sansu)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 QTAINTRAM[2048];
|
||||
static writefunc old2007wrap;
|
||||
//#define CAI_DEBUG
|
||||
|
||||
// main tiles RAM is 8K in size, but unless other non-CHR ROM type carts,
|
||||
// this one accesses the $0000 and $1000 pages based on extra NT RAM on board
|
||||
// which is similar to MMC5 but much simpler because there are no additional
|
||||
// bankings here.
|
||||
// extra NT RAM handling is in PPU code now.
|
||||
|
||||
static uint16 CHRSIZE = 8192;
|
||||
static uint16 WRAMSIZE = 8192 + 4096;
|
||||
// there are two separate WRAMs 8K each, on main system cartridge (not battery
|
||||
// backed), and one on the daughter cart (with battery). both are accessed
|
||||
// via the same registers with additional selector flags.
|
||||
static uint16 WRAMSIZE = 8192 + 8192;
|
||||
static uint8 *CHRRAM = NULL;
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
static uint8 IRQa, K4IRQ;
|
||||
static uint32 IRQLatch, IRQCount;
|
||||
|
||||
// some kind of 16-bit text encoding (actually 14-bit) used in game resources
|
||||
// may be converted by the hardware into the tile indexes for internal CHR ROM
|
||||
// not sure whey they made it hardware, because most of calculations are just
|
||||
// bit shifting. the main purpose of this table is to calculate actual CHR ROM
|
||||
// bank for every character. there is a some kind of regularity, so this table
|
||||
// may be calculated in software easily.
|
||||
|
||||
// table read out from hardware registers as is
|
||||
|
||||
///*
|
||||
static uint8 conv_tbl[4][8] = {
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x40, 0x10, 0x28, 0x00, 0x18, 0x30 },
|
||||
{ 0x00, 0x00, 0x48, 0x18, 0x30, 0x08, 0x20, 0x38 },
|
||||
{ 0x00, 0x00, 0x80, 0x20, 0x38, 0x10, 0x28, 0xB0 }
|
||||
};
|
||||
//*/
|
||||
/*
|
||||
static uint8 conv_tbl[64][4] = {
|
||||
{ 0x40, 0x40, 0x40, 0x40 }, // 00 | A - 40 41 42 43 44 45 46 47
|
||||
{ 0x41, 0x41, 0x41, 0x41 }, // 02 | B - 48 49 4A 4B 4C 4D 4E 4F
|
||||
{ 0x42, 0x42, 0x42, 0x42 }, // 04 | C - 50 51 52 53 54 55 56 57
|
||||
{ 0x43, 0x43, 0x43, 0x43 }, // 06 | D - 58 59 5A 5B 5C 5D 5E 5F
|
||||
{ 0x44, 0x44, 0x44, 0x44 }, // 08 | E - 60 61 62 63 64 65 66 67
|
||||
{ 0x45, 0x45, 0x45, 0x45 }, // 0A | F - 68 69 6A 6B 6C 6D 6E 6F
|
||||
{ 0x46, 0x46, 0x46, 0x46 }, // 0C | G - 70 71 72 73 74 75 76 77
|
||||
{ 0x47, 0x47, 0x47, 0x47 }, // 0E | H - 78 79 7A 7B 7C 7D 7E 7F
|
||||
{ 0x40, 0x40, 0x40, 0x40 }, // 10 |
|
||||
{ 0x41, 0x41, 0x41, 0x41 }, // 12 +----------------------------
|
||||
{ 0x42, 0x42, 0x42, 0x42 }, // 14 | A A A A
|
||||
{ 0x43, 0x43, 0x43, 0x43 }, // 16 | A A A A
|
||||
{ 0x44, 0x44, 0x44, 0x44 }, // 18 | A A' B' A"
|
||||
{ 0x45, 0x45, 0x45, 0x45 }, // 1A | A C D E
|
||||
{ 0x46, 0x46, 0x46, 0x46 }, // 1C | A F G H
|
||||
{ 0x47, 0x47, 0x47, 0x47 }, // 1E | A A B C
|
||||
{ 0x40, 0x40, 0x48, 0x44 }, // 20 | A D E F
|
||||
{ 0x41, 0x41, 0x49, 0x45 }, // 22 | A G H G"
|
||||
{ 0x42, 0x42, 0x4A, 0x46 }, // 24 +----------------------------
|
||||
{ 0x43, 0x43, 0x4B, 0x47 }, // 26 | A' - 40 41 42 43 40 41 42 43
|
||||
{ 0x44, 0x40, 0x48, 0x44 }, // 28 | A" - 44 45 46 47 44 45 46 47
|
||||
{ 0x45, 0x41, 0x49, 0x45 }, // 2A | B' - 48 49 4A 4B 48 49 4A 4B
|
||||
{ 0x46, 0x42, 0x4A, 0x46 }, // 2C | G" - 74 75 76 77 74 75 76 77
|
||||
{ 0x47, 0x43, 0x4B, 0x47 }, // 2E
|
||||
{ 0x40, 0x50, 0x58, 0x60 }, // 30
|
||||
{ 0x41, 0x51, 0x59, 0x61 }, // 32
|
||||
{ 0x42, 0x52, 0x5A, 0x62 }, // 34
|
||||
{ 0x43, 0x53, 0x5B, 0x63 }, // 36
|
||||
{ 0x44, 0x54, 0x5C, 0x64 }, // 38
|
||||
{ 0x45, 0x55, 0x5D, 0x65 }, // 3A
|
||||
{ 0x46, 0x56, 0x5E, 0x66 }, // 3C
|
||||
{ 0x47, 0x57, 0x5F, 0x67 }, // 3E
|
||||
{ 0x40, 0x68, 0x70, 0x78 }, // 40
|
||||
{ 0x41, 0x69, 0x71, 0x79 }, // 42
|
||||
{ 0x42, 0x6A, 0x72, 0x7A }, // 44
|
||||
{ 0x43, 0x6B, 0x73, 0x7B }, // 46
|
||||
{ 0x44, 0x6C, 0x74, 0x7C }, // 48
|
||||
{ 0x45, 0x6D, 0x75, 0x7D }, // 4A
|
||||
{ 0x46, 0x6E, 0x76, 0x7E }, // 4C
|
||||
{ 0x47, 0x6F, 0x77, 0x7F }, // 4E
|
||||
{ 0x40, 0x40, 0x48, 0x50 }, // 50
|
||||
{ 0x41, 0x41, 0x49, 0x51 }, // 52
|
||||
{ 0x42, 0x42, 0x4A, 0x52 }, // 54
|
||||
{ 0x43, 0x43, 0x4B, 0x53 }, // 56
|
||||
{ 0x44, 0x44, 0x4C, 0x54 }, // 58
|
||||
{ 0x45, 0x45, 0x4D, 0x55 }, // 5A
|
||||
{ 0x46, 0x46, 0x4E, 0x56 }, // 5C
|
||||
{ 0x47, 0x47, 0x4F, 0x57 }, // 5E
|
||||
{ 0x40, 0x58, 0x60, 0x68 }, // 60
|
||||
{ 0x41, 0x59, 0x61, 0x69 }, // 62
|
||||
{ 0x42, 0x5A, 0x62, 0x6A }, // 64
|
||||
{ 0x43, 0x5B, 0x63, 0x6B }, // 66
|
||||
{ 0x44, 0x5C, 0x64, 0x6C }, // 68
|
||||
{ 0x45, 0x5D, 0x65, 0x6D }, // 6A
|
||||
{ 0x46, 0x5E, 0x66, 0x6E }, // 6C
|
||||
{ 0x47, 0x5F, 0x67, 0x6F }, // 6E
|
||||
{ 0x40, 0x70, 0x78, 0x74 }, // 70
|
||||
{ 0x41, 0x71, 0x79, 0x75 }, // 72
|
||||
{ 0x42, 0x72, 0x7A, 0x76 }, // 74
|
||||
{ 0x43, 0x73, 0x7B, 0x77 }, // 76
|
||||
{ 0x44, 0x74, 0x7C, 0x74 }, // 78
|
||||
{ 0x45, 0x75, 0x7D, 0x75 }, // 7A
|
||||
{ 0x46, 0x76, 0x7E, 0x76 }, // 7C
|
||||
{ 0x47, 0x77, 0x7F, 0x77 }, // 7E
|
||||
};
|
||||
*/
|
||||
|
||||
static uint8 regs[16];
|
||||
//static uint8 test[8];
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &IRQCount, 1, "IRQC" },
|
||||
@@ -48,93 +141,68 @@ static SFORMAT StateRegs[] =
|
||||
|
||||
static void chrSync(void) {
|
||||
setchr4r(0x10, 0x0000, regs[5] & 1);
|
||||
setchr4r(0x10, 0x1000, 0);
|
||||
// 30.06.19 CaH4e3 there is much more complicated behaviour with second banking register, you may actually
|
||||
// view the content of the internal character CHR rom via this window, but it is useless because hardware
|
||||
// does not use this area to access the internal ROM. not sure why they did this, but I see no need to
|
||||
// emulate this behaviour carefully, unless I find something that I missed...
|
||||
setchr4r(0x10, 0x1000, 1);
|
||||
}
|
||||
|
||||
static void Sync(void) {
|
||||
chrSync();
|
||||
// if(regs[0xA]&0x10)
|
||||
// {
|
||||
/* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0);
|
||||
setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1);
|
||||
setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2);
|
||||
setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3);
|
||||
setchr1r(0x10,0x1000,0);
|
||||
setchr1r(0x10,0x1400,1);
|
||||
setchr1r(0x10,0x1800,2);
|
||||
setchr1r(0x10,0x1c00,3);*/
|
||||
/* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0);
|
||||
setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1);
|
||||
setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2);
|
||||
setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3);
|
||||
setchr1r(0x10,0x1000,(((regs[5]&1)^1)<<2)+4);
|
||||
setchr1r(0x10,0x1400,(((regs[5]&1)^1)<<2)+5);
|
||||
setchr1r(0x10,0x1800,(((regs[5]&1)^1)<<2)+6);
|
||||
setchr1r(0x10,0x1c00,(((regs[5]&1)^1)<<2)+7);
|
||||
*/
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
/*
|
||||
setchr1r(0x10,0x0000,(((regs[5]&1)^1)<<2)+0);
|
||||
setchr1r(0x10,0x0400,(((regs[5]&1)^1)<<2)+1);
|
||||
setchr1r(0x10,0x0800,(((regs[5]&1)^1)<<2)+2);
|
||||
setchr1r(0x10,0x0c00,(((regs[5]&1)^1)<<2)+3);
|
||||
setchr1r(0x10,0x1000,(((regs[5]&1))<<2)+4);
|
||||
setchr1r(0x10,0x1400,(((regs[5]&1))<<2)+5);
|
||||
setchr1r(0x10,0x1800,(((regs[5]&1))<<2)+6);
|
||||
setchr1r(0x10,0x1c00,(((regs[5]&1))<<2)+7);
|
||||
// }
|
||||
//*/
|
||||
/* setchr1r(1,0x0000,test[0]);
|
||||
setchr1r(1,0x0400,test[1]);
|
||||
setchr1r(1,0x0800,test[2]);
|
||||
setchr1r(1,0x0c00,test[3]);
|
||||
setchr1r(1,0x1000,test[4]);
|
||||
setchr1r(1,0x1400,test[5]);
|
||||
setchr1r(1,0x1800,test[6]);
|
||||
setchr1r(1,0x1c00,test[7]);
|
||||
*/
|
||||
setprg4r(0x10, 0x6000, regs[0] & 1);
|
||||
if (regs[2] >= 0x40)
|
||||
setprg8r(1, 0x8000, (regs[2] - 0x40));
|
||||
else
|
||||
setprg8r(0, 0x8000, (regs[2] & 0x3F));
|
||||
if (regs[3] >= 0x40)
|
||||
setprg8r(1, 0xA000, (regs[3] - 0x40));
|
||||
else
|
||||
setprg8r(0, 0xA000, (regs[3] & 0x3F));
|
||||
if (regs[4] >= 0x40)
|
||||
setprg8r(1, 0xC000, (regs[4] - 0x40));
|
||||
else
|
||||
setprg8r(0, 0xC000, (regs[4] & 0x3F));
|
||||
|
||||
setprg8r(1, 0xE000, ~0);
|
||||
setmirror(MI_V);
|
||||
setprg4r(0x10, 0x6000, (regs[0] & 1) | (regs[0] >> 2)); // two 4K banks are identical, either internal or excernal
|
||||
setprg4r(0x10, 0x7000, (regs[1] & 1) | (regs[1] >> 2)); // SRAMs may be mapped in any bank independently
|
||||
if (PRGptr[1] == NULL) { // for iNES 2.0 version it even more hacky lol
|
||||
setprg8(0x8000, (regs[2] & 0x3F) + ((regs[2] & 0x40) >> 2));
|
||||
setprg8(0xA000, (regs[3] & 0x3F) + ((regs[3] & 0x40) >> 2));
|
||||
setprg8(0xC000, (regs[4] & 0x3F) + ((regs[4] & 0x40) >> 2));
|
||||
setprg8(0xE000, 0x10 + 0x3F);
|
||||
} else {
|
||||
setprg8r((regs[2] >> 6) & 1, 0x8000, (regs[2] & 0x3F));
|
||||
setprg8r((regs[3] >> 6) & 1, 0xA000, (regs[3] & 0x3F));
|
||||
setprg8r((regs[4] >> 6) & 1, 0xC000, (regs[4] & 0x3F));
|
||||
setprg8r(1, 0xE000, ~0); // always sees the last bank of the external cart, so can't be booted without it.
|
||||
}
|
||||
setmirror(((regs[0xA]&2)>>1)^1);
|
||||
}
|
||||
|
||||
/*static DECLFW(TestWrite)
|
||||
{
|
||||
test[A&7] = V;
|
||||
Sync();
|
||||
}*/
|
||||
|
||||
static DECLFW(M190Write) {
|
||||
// FCEU_printf("write %04x:%04x %d, %d\n",A,V,scanline,timestamp);
|
||||
regs[(A & 0x0F00) >> 8] = V;
|
||||
static DECLFW(QTAiWrite) {
|
||||
regs[(A & 0x0F00) >> 8] = V; // IRQ pretty the same as in other VRC mappers by Konami
|
||||
switch (A) {
|
||||
case 0xd600: IRQLatch &= 0xFF00; IRQLatch |= V; break;
|
||||
case 0xd700: IRQLatch &= 0x00FF; IRQLatch |= V << 8; break;
|
||||
case 0xd900: IRQCount = IRQLatch; IRQa = V & 2; K4IRQ = V & 1; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 0xd800: IRQa = K4IRQ; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 0xda00: qtaintramreg = regs[0xA] & 3; break; // register shadow to share it with ppu
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFR(M190Read) {
|
||||
// FCEU_printf("read %04x:%04x %d, %d\n",A,regs[(A&0x0F00)>>8],scanline,timestamp);
|
||||
return regs[(A & 0x0F00) >> 8] + regs[0x0B];
|
||||
static DECLFR(QTAiRead) {
|
||||
|
||||
// uint8 res1 = conv_tbl[(regs[0xD] & 0x7F) >> 1][(regs[0xC] >> 5) & 3];
|
||||
// uint8 res2 = ((regs[0xD] & 1) << 7) | ((regs[0xC] & 0x1F) << 2) | (regs[0xB] & 3);
|
||||
|
||||
uint8 tabl = conv_tbl[(regs[0xC] >> 5) & 3][(regs[0xD] & 0x7F) >> 4];
|
||||
uint8 res1 = 0x40 | (tabl & 0x3F) | ((regs[0xD] >> 1) & 7) | ((regs[0xB] & 4) << 5);
|
||||
uint8 res2 = ((regs[0xD] & 1) << 7) | ((regs[0xC] & 0x1F) << 2) | (regs[0xB] & 3);
|
||||
|
||||
if (tabl & 0x40)
|
||||
res1 &= 0xFB;
|
||||
else if (tabl & 0x80)
|
||||
res1 |= 0x04;
|
||||
|
||||
if (A == 0xDD00) {
|
||||
return res1;
|
||||
} else if (A == 0xDC00) {
|
||||
#ifdef CAI_DEBUG
|
||||
FCEU_printf("%02x:%02x+%d -> %02x:%02x\n", regs[0xD], regs[0xC], regs[0xB], res1, res2);
|
||||
#endif
|
||||
return res2;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void VRC5IRQ(int a) {
|
||||
if (IRQa) {
|
||||
IRQCount += a;
|
||||
@@ -145,50 +213,17 @@ static void VRC5IRQ(int a) {
|
||||
}
|
||||
}
|
||||
|
||||
//static void Mapper190_PPU(uint32 A)
|
||||
//{
|
||||
// if(A<0x2000)
|
||||
// setchr4r(0x10,0x1000,QTAINTRAM[A&0x1FFF]&1);
|
||||
// else
|
||||
// chrSync();
|
||||
//}
|
||||
|
||||
static DECLFW(M1902007Wrap) {
|
||||
if (A >= 0x2000) {
|
||||
if (regs[0xA] & 1)
|
||||
QTAINTRAM[A & 0x1FFF] = V;
|
||||
else
|
||||
old2007wrap(A, V);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void M190Power(void) {
|
||||
/* test[0]=0;
|
||||
test[1]=1;
|
||||
test[2]=2;
|
||||
test[3]=3;
|
||||
test[4]=4;
|
||||
test[5]=5;
|
||||
test[6]=6;
|
||||
test[7]=7;
|
||||
*/
|
||||
setprg4r(0x10, 0x7000, 2);
|
||||
|
||||
old2007wrap = GetWriteHandler(0x2007);
|
||||
SetWriteHandler(0x2007, 0x2007, M1902007Wrap);
|
||||
|
||||
static void QTAiPower(void) {
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
// SetWriteHandler(0x5000,0x5007,TestWrite);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M190Write);
|
||||
SetReadHandler(0xDC00, 0xDC00, M190Read);
|
||||
SetReadHandler(0xDD00, 0xDD00, M190Read);
|
||||
SetWriteHandler(0x8000, 0xFFFF, QTAiWrite);
|
||||
SetReadHandler(0xDC00, 0xDC00, QTAiRead);
|
||||
SetReadHandler(0xDD00, 0xDD00, QTAiRead);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M190Close(void) {
|
||||
static void QTAiClose(void) {
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
@@ -201,13 +236,14 @@ static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper190_Init(CartInfo *info) {
|
||||
info->Power = M190Power;
|
||||
info->Close = M190Close;
|
||||
void QTAi_Init(CartInfo *info) {
|
||||
QTAIHack = 1;
|
||||
|
||||
info->Power = QTAiPower;
|
||||
info->Close = QTAiClose;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
MapIRQHook = VRC5IRQ;
|
||||
// PPU_hook=Mapper190_PPU;
|
||||
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRSIZE, 1);
|
||||
@@ -219,7 +255,10 @@ void Mapper190_Init(CartInfo *info) {
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE - 4096;
|
||||
// note, only extrnal cart's SRAM is battery backed, the the part on the main cartridge is just
|
||||
// an additional work ram. so we may save only half here, but I forgot what part is saved lol, will
|
||||
// find out later.
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ static void VRC7SKill(void) {
|
||||
static void VRC7_ESI(void) {
|
||||
GameExpSound.RChange = VRC7SC;
|
||||
GameExpSound.Kill = VRC7SKill;
|
||||
VRC7Sound = OPLL_new(3579545, FSettings.SndRate ? FSettings.SndRate : 44100);
|
||||
VRC7Sound = OPLL_new(3579545, FSettings.SndRate ? FSettings.SndRate : 48000);
|
||||
OPLL_reset(VRC7Sound);
|
||||
OPLL_reset(VRC7Sound);
|
||||
}
|
||||
|
||||
@@ -76,6 +76,8 @@ uint8 geniech[3];
|
||||
|
||||
uint32 genieaddr[3];
|
||||
|
||||
CartInfo *currCartInfo;
|
||||
|
||||
static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram) {
|
||||
uint32 AB = A >> 11;
|
||||
int x;
|
||||
@@ -130,6 +132,11 @@ void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram) {
|
||||
CHRmask4[chip] = (size >> 12) - 1;
|
||||
CHRmask8[chip] = (size >> 13) - 1;
|
||||
|
||||
if (CHRmask1[chip] >= (unsigned int)(-1)) CHRmask1[chip] = 0;
|
||||
if (CHRmask2[chip] >= (unsigned int)(-1)) CHRmask2[chip] = 0;
|
||||
if (CHRmask4[chip] >= (unsigned int)(-1)) CHRmask4[chip] = 0;
|
||||
if (CHRmask8[chip] >= (unsigned int)(-1)) CHRmask8[chip] = 0;
|
||||
|
||||
CHRram[chip] = ram;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#ifndef CART_H
|
||||
#define CART_H
|
||||
|
||||
typedef struct {
|
||||
// Set by mapper/board code:
|
||||
void (*Power)(void);
|
||||
@@ -25,6 +28,8 @@ typedef struct {
|
||||
// other code in the future.
|
||||
} CartInfo;
|
||||
|
||||
extern CartInfo *currCartInfo;
|
||||
|
||||
void FCEU_SaveGameSave(CartInfo *LocalHWInfo);
|
||||
void FCEU_LoadGameSave(CartInfo *LocalHWInfo);
|
||||
void FCEU_ClearGameSave(CartInfo *LocalHWInfo);
|
||||
@@ -98,3 +103,5 @@ void FCEU_GeniePower(void);
|
||||
bool FCEU_OpenGenie(void);
|
||||
void FCEU_CloseGenie(void);
|
||||
void FCEU_KillGenie(void);
|
||||
|
||||
#endif
|
||||
|
||||
+289
-296
@@ -39,8 +39,7 @@ using namespace std;
|
||||
static uint8 *CheatRPtrs[64];
|
||||
|
||||
vector<uint16> FrozenAddresses; //List of addresses that are currently frozen
|
||||
void UpdateFrozenList(void); //Function that populates the list of frozen addresses
|
||||
unsigned int FrozenAddressCount=0; //Keeps up with the Frozen address count, necessary for using in other dialogs (such as hex editor)
|
||||
unsigned int FrozenAddressCount = 0; //Keeps up with the Frozen address count, necessary for using in other dialogs (such as hex editor)
|
||||
|
||||
void FCEU_CheatResetRAM(void)
|
||||
{
|
||||
@@ -60,27 +59,13 @@ void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p)
|
||||
}
|
||||
|
||||
|
||||
struct CHEATF {
|
||||
struct CHEATF *next;
|
||||
char *name;
|
||||
uint16 addr;
|
||||
uint8 val;
|
||||
int compare; /* -1 for no compare. */
|
||||
int type; /* 0 for replace, 1 for substitute(GG). */
|
||||
int status;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint16 addr;
|
||||
uint8 val;
|
||||
int compare;
|
||||
readfunc PrevRead;
|
||||
} CHEATF_SUBFAST;
|
||||
|
||||
|
||||
static CHEATF_SUBFAST SubCheats[256];
|
||||
static int numsubcheats=0;
|
||||
struct CHEATF *cheats=0,*cheatsl=0;
|
||||
CHEATF_SUBFAST SubCheats[256] = { 0 };
|
||||
uint32 numsubcheats = 0;
|
||||
int globalCheatDisabled = 0;
|
||||
int disableAutoLSCheats = 0;
|
||||
bool disableShowGG = 0;
|
||||
static _8BYTECHEATMAP* cheatMap = NULL;
|
||||
struct CHEATF *cheats = 0, *cheatsl = 0;
|
||||
|
||||
|
||||
#define CHEATC_NONE 0x8000
|
||||
@@ -92,7 +77,7 @@ int savecheats = 0;
|
||||
|
||||
static DECLFR(SubCheatsRead)
|
||||
{
|
||||
CHEATF_SUBFAST *s=SubCheats;
|
||||
CHEATF_SUBFAST *s = SubCheats;
|
||||
int x=numsubcheats;
|
||||
|
||||
do
|
||||
@@ -116,79 +101,98 @@ static DECLFR(SubCheatsRead)
|
||||
|
||||
void RebuildSubCheats(void)
|
||||
{
|
||||
int x;
|
||||
struct CHEATF *c=cheats;
|
||||
for(x=0;x<numsubcheats;x++)
|
||||
SetReadHandler(SubCheats[x].addr,SubCheats[x].addr,SubCheats[x].PrevRead);
|
||||
|
||||
numsubcheats=0;
|
||||
while(c)
|
||||
uint32 x;
|
||||
struct CHEATF *c = cheats;
|
||||
for (x = 0; x < numsubcheats; x++)
|
||||
{
|
||||
if(c->type==1 && c->status)
|
||||
SetReadHandler(SubCheats[x].addr, SubCheats[x].addr, SubCheats[x].PrevRead);
|
||||
if (cheatMap)
|
||||
FCEUI_SetCheatMapByte(SubCheats[x].addr, false);
|
||||
}
|
||||
|
||||
numsubcheats = 0;
|
||||
|
||||
if (!globalCheatDisabled)
|
||||
{
|
||||
while(c)
|
||||
{
|
||||
if(GetReadHandler(c->addr)==SubCheatsRead)
|
||||
if(c->type == 1 && c->status && GetReadHandler(c->addr) != SubCheatsRead)
|
||||
{
|
||||
/* Prevent a catastrophe by this check. */
|
||||
//FCEU_DispMessage("oops",0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SubCheats[numsubcheats].PrevRead=GetReadHandler(c->addr);
|
||||
SubCheats[numsubcheats].addr=c->addr;
|
||||
SubCheats[numsubcheats].val=c->val;
|
||||
SubCheats[numsubcheats].compare=c->compare;
|
||||
SetReadHandler(c->addr,c->addr,SubCheatsRead);
|
||||
SubCheats[numsubcheats].PrevRead = GetReadHandler(c->addr);
|
||||
SubCheats[numsubcheats].addr = c->addr;
|
||||
SubCheats[numsubcheats].val = c->val;
|
||||
SubCheats[numsubcheats].compare = c->compare;
|
||||
SetReadHandler(c->addr, c->addr, SubCheatsRead);
|
||||
if (cheatMap)
|
||||
FCEUI_SetCheatMapByte(SubCheats[numsubcheats].addr, true);
|
||||
numsubcheats++;
|
||||
}
|
||||
c = c->next;
|
||||
}
|
||||
c=c->next;
|
||||
}
|
||||
FrozenAddressCount = numsubcheats; //Update the frozen address list
|
||||
UpdateFrozenList();
|
||||
//FCEUI_DispMessage("Active Cheats: %d",0, FrozenAddresses.size()/*FrozenAddressCount*/); //Debug
|
||||
|
||||
}
|
||||
|
||||
void FCEU_PowerCheats()
|
||||
{
|
||||
numsubcheats=0; /* Quick hack to prevent setting of ancient read addresses. */
|
||||
numsubcheats = 0; /* Quick hack to prevent setting of ancient read addresses. */
|
||||
if (cheatMap)
|
||||
FCEUI_RefreshCheatMap();
|
||||
RebuildSubCheats();
|
||||
}
|
||||
|
||||
static int AddCheatEntry(char *name, uint32 addr, uint8 val, int compare, int status, int type);
|
||||
int FCEU_CalcCheatAffectedBytes(uint32 address, uint32 size) {
|
||||
|
||||
uint32 count = 0;
|
||||
if (cheatMap)
|
||||
for (uint32 i = 0; i < size; ++i)
|
||||
if (FCEUI_FindCheatMapByte(address + i))
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
static int AddCheatEntry(const char *name, uint32 addr, uint8 val, int compare, int status, int type);
|
||||
static void CheatMemErr(void)
|
||||
{
|
||||
FCEUD_PrintError("Error allocating memory for cheat data.");
|
||||
}
|
||||
|
||||
/* This function doesn't allocate any memory for "name" */
|
||||
static int AddCheatEntry(char *name, uint32 addr, uint8 val, int compare, int status, int type)
|
||||
static int AddCheatEntry(const char *name, uint32 addr, uint8 val, int compare, int status, int type)
|
||||
{
|
||||
struct CHEATF *temp;
|
||||
if(!(temp=(struct CHEATF *)FCEU_dmalloc(sizeof(struct CHEATF))))
|
||||
if(!(temp = (struct CHEATF *)FCEU_dmalloc(sizeof(struct CHEATF))))
|
||||
{
|
||||
CheatMemErr();
|
||||
return(0);
|
||||
}
|
||||
temp->name=name;
|
||||
temp->addr=addr;
|
||||
temp->val=val;
|
||||
temp->status=status;
|
||||
temp->compare=compare;
|
||||
temp->type=type;
|
||||
temp->next=0;
|
||||
|
||||
temp->name = strcpy((char*) FCEU_dmalloc(strlen(name) + 1), name);
|
||||
temp->addr = addr;
|
||||
temp->val = val;
|
||||
temp->status = status;
|
||||
temp->compare = compare;
|
||||
temp->type = type;
|
||||
temp->next = 0;
|
||||
|
||||
if(cheats)
|
||||
{
|
||||
cheatsl->next=temp;
|
||||
cheatsl=temp;
|
||||
cheatsl->next = temp;
|
||||
cheatsl = temp;
|
||||
}
|
||||
else
|
||||
cheats=cheatsl=temp;
|
||||
cheats = cheatsl = temp;
|
||||
|
||||
return(1);
|
||||
return (1);
|
||||
}
|
||||
|
||||
void FCEU_LoadGameCheats(FILE *override)
|
||||
/* The "override_existing" parameter is used only in cheat dialog import.
|
||||
Since the default behaviour will reset numsubcheats to 0 everytime,
|
||||
In game loading, this is absolutely right, but when importing in cheat window,
|
||||
resetting numsubcheats to 0 will override existed cheat items to make them
|
||||
invalid.
|
||||
*/
|
||||
void FCEU_LoadGameCheats(FILE *override, int override_existing)
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned int addr;
|
||||
@@ -198,89 +202,121 @@ void FCEU_LoadGameCheats(FILE *override)
|
||||
unsigned int compare;
|
||||
int x;
|
||||
|
||||
char linebuf[2048];
|
||||
char *namebuf;
|
||||
int tc=0;
|
||||
char linebuf[2048] = { 0 };
|
||||
char namebuf[128] = { 0 };
|
||||
int tc = 0;
|
||||
char *fn;
|
||||
|
||||
numsubcheats=savecheats=0;
|
||||
if (override_existing)
|
||||
{
|
||||
numsubcheats = 0;
|
||||
if (cheatMap)
|
||||
FCEUI_RefreshCheatMap();
|
||||
}
|
||||
|
||||
if(override)
|
||||
fp = override;
|
||||
else
|
||||
{
|
||||
fn=strdup(FCEU_MakeFName(FCEUMKF_CHEAT,0,0).c_str());
|
||||
fp=FCEUD_UTF8fopen(fn,"rb");
|
||||
fn = strdup(FCEU_MakeFName(FCEUMKF_CHEAT, 0, 0).c_str());
|
||||
fp = FCEUD_UTF8fopen(fn, "rb");
|
||||
free(fn);
|
||||
if(!fp) return;
|
||||
if (!fp) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
FCEU_DispMessage("Cheats file loaded.",0); //Tells user a cheats file was loaded.
|
||||
while(fgets(linebuf,2048,fp)>0)
|
||||
while(fgets(linebuf, 2048, fp) != nullptr)
|
||||
{
|
||||
char *tbuf=linebuf;
|
||||
int doc=0;
|
||||
char *tbuf = linebuf;
|
||||
int doc = 0;
|
||||
|
||||
addr=val=compare=status=type=0;
|
||||
addr = val = compare = status = type = 0;
|
||||
|
||||
if(tbuf[0]=='S')
|
||||
if(tbuf[0] == 'S')
|
||||
{
|
||||
tbuf++;
|
||||
type=1;
|
||||
type = 1;
|
||||
}
|
||||
else type=0;
|
||||
else
|
||||
type = 0;
|
||||
|
||||
if(tbuf[0]=='C')
|
||||
if(tbuf[0] == 'C')
|
||||
{
|
||||
tbuf++;
|
||||
doc=1;
|
||||
doc = 1;
|
||||
}
|
||||
|
||||
if(tbuf[0]==':')
|
||||
if(tbuf[0] == ':')
|
||||
{
|
||||
tbuf++;
|
||||
status=0;
|
||||
status = 0;
|
||||
}
|
||||
else status=1;
|
||||
else status = 1;
|
||||
|
||||
if(doc)
|
||||
{
|
||||
char *neo=&tbuf[4+2+2+1+1+1];
|
||||
if(sscanf(tbuf,"%04x%*[:]%02x%*[:]%02x",&addr,&val,&compare)!=3)
|
||||
char *neo = &tbuf[4+2+2+1+1+1];
|
||||
if(sscanf(tbuf, "%04x%*[:]%02x%*[:]%02x", &addr, &val, &compare) != 3)
|
||||
continue;
|
||||
if (!(namebuf=(char *)FCEU_dmalloc(strlen(neo)+1)))
|
||||
return;
|
||||
strcpy(namebuf,neo);
|
||||
strcpy(namebuf, neo);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *neo=&tbuf[4+2+1+1];
|
||||
if(sscanf(tbuf,"%04x%*[:]%02x",&addr,&val)!=2)
|
||||
char *neo = &tbuf[4+2+1+1];
|
||||
if(sscanf(tbuf, "%04x%*[:]%02x", &addr, &val) != 2)
|
||||
continue;
|
||||
if (!(namebuf=(char *)FCEU_dmalloc(strlen(neo)+1)))
|
||||
return;
|
||||
strcpy(namebuf,neo);
|
||||
strcpy(namebuf, neo);
|
||||
}
|
||||
|
||||
for(x=0;x<(int)strlen(namebuf);x++)
|
||||
for(x = 0; x < (int)strlen(namebuf); x++)
|
||||
{
|
||||
if(namebuf[x]==10 || namebuf[x]==13)
|
||||
if(namebuf[x] == 10 || namebuf[x] == 13)
|
||||
{
|
||||
namebuf[x]=0;
|
||||
namebuf[x] = 0;
|
||||
break;
|
||||
}
|
||||
else if(namebuf[x] > 0x00 && namebuf[x] < 0x20)
|
||||
namebuf[x]=0x20;
|
||||
namebuf[x] = 0x20;
|
||||
}
|
||||
|
||||
AddCheatEntry(namebuf,addr,val,doc?compare:-1,status,type);
|
||||
AddCheatEntry(namebuf, addr, val, doc ? compare : -1, status, type);
|
||||
tc++;
|
||||
}
|
||||
|
||||
RebuildSubCheats();
|
||||
|
||||
FCEU_DispMessage("Cheats file loaded.", 0); //Tells user a cheats file was loaded.
|
||||
|
||||
if(!override)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void FCEU_SaveGameCheats(FILE* fp, int release)
|
||||
{
|
||||
struct CHEATF *next = cheats;
|
||||
while (next)
|
||||
{
|
||||
if (next->type)
|
||||
fputc('S', fp);
|
||||
if (next->compare >= 0)
|
||||
fputc('C', fp);
|
||||
|
||||
if (!next->status)
|
||||
fputc(':', fp);
|
||||
|
||||
if (next->compare >= 0)
|
||||
fprintf(fp, "%04x:%02x:%02x:%s\n", next->addr, next->val, next->compare, next->name);
|
||||
else
|
||||
fprintf(fp, "%04x:%02x:%s\n", next->addr, next->val, next->name);
|
||||
|
||||
if (release) free(next->name);
|
||||
struct CHEATF *t = next;
|
||||
next = next->next;
|
||||
if (release) free(t);
|
||||
}
|
||||
}
|
||||
|
||||
void FCEU_FlushGameCheats(FILE *override, int nosave)
|
||||
{
|
||||
if(CheatComp)
|
||||
@@ -313,7 +349,6 @@ void FCEU_FlushGameCheats(FILE *override, int nosave)
|
||||
|
||||
if(cheats)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
FILE *fp;
|
||||
|
||||
if(override)
|
||||
@@ -323,28 +358,7 @@ void FCEU_FlushGameCheats(FILE *override, int nosave)
|
||||
|
||||
if(fp)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
struct CHEATF *t;
|
||||
if(next->type)
|
||||
fputc('S',fp);
|
||||
if(next->compare>=0)
|
||||
fputc('C',fp);
|
||||
|
||||
if(!next->status)
|
||||
fputc(':',fp);
|
||||
|
||||
if(next->compare>=0)
|
||||
fprintf(fp,"%04x:%02x:%02x:%s\n",next->addr,next->val,next->compare,next->name);
|
||||
else
|
||||
fprintf(fp,"%04x:%02x:%s\n",next->addr,next->val,next->name);
|
||||
|
||||
free(next->name);
|
||||
t=next;
|
||||
next=next->next;
|
||||
free(t);
|
||||
if(!next) break;
|
||||
}
|
||||
FCEU_SaveGameCheats(fp, 1);
|
||||
if(!override)
|
||||
fclose(fp);
|
||||
}
|
||||
@@ -365,23 +379,13 @@ void FCEU_FlushGameCheats(FILE *override, int nosave)
|
||||
|
||||
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type)
|
||||
{
|
||||
char *t;
|
||||
|
||||
if(!(t=(char *)FCEU_dmalloc(strlen(name)+1)))
|
||||
{
|
||||
CheatMemErr();
|
||||
return(0);
|
||||
}
|
||||
strcpy(t,name);
|
||||
if(!AddCheatEntry(t,addr,val,compare,1,type))
|
||||
{
|
||||
free(t);
|
||||
return(0);
|
||||
}
|
||||
savecheats=1;
|
||||
if(!AddCheatEntry(name, addr, val, compare, 1, type))
|
||||
return 0;
|
||||
savecheats = 1;
|
||||
RebuildSubCheats();
|
||||
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FCEUI_DelCheat(uint32 which)
|
||||
@@ -566,7 +570,7 @@ int FCEUI_DecodeGG(const char *str, int *a, int *v, int *c)
|
||||
|
||||
int FCEUI_DecodePAR(const char *str, int *a, int *v, int *c, int *type)
|
||||
{
|
||||
int boo[4];
|
||||
unsigned int boo[4];
|
||||
if(strlen(str)!=8) return(0);
|
||||
|
||||
sscanf(str,"%02x%02x%02x%02x",boo,boo+1,boo+2,boo+3);
|
||||
@@ -598,43 +602,40 @@ int FCEUI_DecodePAR(const char *str, int *a, int *v, int *c, int *type)
|
||||
|
||||
int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int c, int s, int type)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
uint32 x=0;
|
||||
struct CHEATF *next = cheats;
|
||||
uint32 x = 0;
|
||||
|
||||
while(next)
|
||||
{
|
||||
if(x==which)
|
||||
if(x == which)
|
||||
{
|
||||
if(name)
|
||||
{
|
||||
char *t;
|
||||
if((t=(char *)realloc(next->name, strlen(name)+1)))
|
||||
{
|
||||
next->name=t;
|
||||
strcpy(next->name,name);
|
||||
}
|
||||
if((t = (char *)realloc(next->name, strlen(name) + 1)))
|
||||
strcpy(next->name = t, name);
|
||||
else
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
if(a>=0)
|
||||
next->addr=a;
|
||||
if(v>=0)
|
||||
next->val=v;
|
||||
if(s>=0)
|
||||
next->status=s;
|
||||
if(c>=-1)
|
||||
next->compare=c;
|
||||
next->type=type;
|
||||
if(a >= 0)
|
||||
next->addr = a;
|
||||
if(v >= 0)
|
||||
next->val = v;
|
||||
if(s >= 0)
|
||||
next->status = s;
|
||||
if(c >= -1)
|
||||
next->compare = c;
|
||||
next->type = type;
|
||||
|
||||
savecheats=1;
|
||||
savecheats = 1;
|
||||
RebuildSubCheats();
|
||||
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
next=next->next;
|
||||
next = next->next;
|
||||
x++;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convenience function. */
|
||||
@@ -659,6 +660,14 @@ int FCEUI_ToggleCheat(uint32 which)
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int FCEUI_GlobalToggleCheat(int global_enabled)
|
||||
{
|
||||
int _numsubcheats = numsubcheats;
|
||||
globalCheatDisabled = !global_enabled;
|
||||
RebuildSubCheats();
|
||||
return _numsubcheats != numsubcheats;
|
||||
}
|
||||
|
||||
static int InitCheatComp(void)
|
||||
{
|
||||
uint32 x;
|
||||
@@ -741,7 +750,7 @@ void FCEUI_CheatSearchGet(int (*callb)(uint32 a, uint8 last, uint8 current, void
|
||||
void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current))
|
||||
{
|
||||
uint32 x;
|
||||
uint32 in=0;
|
||||
uint32 in = 0;
|
||||
|
||||
if(!CheatComp)
|
||||
{
|
||||
@@ -750,14 +759,15 @@ void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a,
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
|
||||
for(x = 0; x < 0x10000; x++)
|
||||
if(!(CheatComp[x] & CHEATC_NOSHOW) && CheatRPtrs[x >> 10])
|
||||
{
|
||||
if(in>=first)
|
||||
if(!callb(x,CheatComp[x],CheatRPtrs[x>>10][x]))
|
||||
if(in >= first)
|
||||
if(!callb(x, CheatComp[x], CheatRPtrs[x >> 10][x]))
|
||||
break;
|
||||
in++;
|
||||
if(in>last) return;
|
||||
if(in > last)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -803,130 +813,56 @@ void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!type) // Change to a specific value.
|
||||
switch (type)
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]==v1 && CheatRPtrs[x>>10][x]==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
default:
|
||||
case FCEU_SEARCH_SPECIFIC_CHANGE: // Change to a specific value
|
||||
for (x = 0; x < 0x10000; ++x)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && (CheatComp[x] != v1 || CheatRPtrs[x >> 10][x] != v2))
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_RELATIVE_CHANGE: // Search for relative change (between values).
|
||||
for (x = 0; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && (CheatComp[x] != v1 || CAbs(CheatComp[x] - CheatRPtrs[x >> 10][x]) != v2))
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_PUERLY_RELATIVE_CHANGE: // Purely relative change.
|
||||
for (x = 0x000; x<0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && CAbs(CheatComp[x] - CheatRPtrs[x >> 10][x]) != v2)
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_ANY_CHANGE: // Any change.
|
||||
for (x = 0x000; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && CheatComp[x] == CheatRPtrs[x >> 10][x])
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_NEWVAL_KNOWN: // new value = known
|
||||
for (x = 0x000; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && CheatRPtrs[x >> 10][x] != v1)
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_NEWVAL_GT: // new value greater than
|
||||
for (x = 0x000; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && CheatComp[x] >= CheatRPtrs[x >> 10][x])
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_NEWVAL_LT: // new value less than
|
||||
for (x = 0x000; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && CheatComp[x] <= CheatRPtrs[x >> 10][x])
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_NEWVAL_GT_KNOWN: // new value greater than by known value
|
||||
for (x = 0x000; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && CheatRPtrs[x >> 10][x] - CheatComp[x] != v2)
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_NEWVAL_LT_KNOWN: // new value less than by known value
|
||||
for (x = 0x000; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && (CheatComp[x] - CheatRPtrs[x >> 10][x]) != v2)
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
}
|
||||
else if(type==1) // Search for relative change(between values).
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]==v1 && CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==2) // Purely relative change.
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==3) // Any change.
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]!=CheatRPtrs[x>>10][x])
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
}
|
||||
else if(type==4) // new value = known
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatRPtrs[x>>10][x]==v1)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
}
|
||||
else if(type==5) // new value greater than
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]<CheatRPtrs[x>>10][x])
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
}
|
||||
else if(type==6) // new value less than
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]>CheatRPtrs[x>>10][x])
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
}
|
||||
else if(type==7) // new value greater than by known value
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if((CheatRPtrs[x>>10][x]-CheatComp[x])==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
}
|
||||
else if(type==8) // new value less than by known value
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if((CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int FCEU_CheatGetByte(uint32 A)
|
||||
@@ -949,18 +885,75 @@ void FCEU_CheatSetByte(uint32 A, uint8 V)
|
||||
BWrite[A](A, V);
|
||||
}
|
||||
|
||||
void UpdateFrozenList(void)
|
||||
// disable all cheats
|
||||
int FCEU_DisableAllCheats(void)
|
||||
{
|
||||
//The purpose of this function is to keep an up to date list of addresses that are currently frozen
|
||||
//and make these accessible to other dialogs that deal with memory addresses such as
|
||||
//memwatch, hex editor, ramfilter, etc.
|
||||
|
||||
int x;
|
||||
FrozenAddresses.clear(); //Clear vector and repopulate
|
||||
for(x=0;x<numsubcheats;x++)
|
||||
int count = 0;
|
||||
struct CHEATF *next = cheats;
|
||||
while(next)
|
||||
{
|
||||
FrozenAddresses.push_back(SubCheats[x].addr);
|
||||
//FCEU_printf("Address %d: %d \n",x,FrozenAddresses[x]); //Debug
|
||||
if(next->status){
|
||||
count++;
|
||||
}
|
||||
next->status = 0;
|
||||
next = next->next;
|
||||
}
|
||||
savecheats = 1;
|
||||
RebuildSubCheats();
|
||||
return count;
|
||||
}
|
||||
|
||||
// delete all cheats
|
||||
int FCEU_DeleteAllCheats(void)
|
||||
{
|
||||
struct CHEATF *cur = cheats;
|
||||
struct CHEATF *next = NULL;
|
||||
while (cur)
|
||||
{
|
||||
next = cur->next;
|
||||
if ( cur->name )
|
||||
{
|
||||
free(cur->name);
|
||||
}
|
||||
free(cur);
|
||||
cur = next;
|
||||
}
|
||||
cheats = cheatsl = 0;
|
||||
savecheats = 1;
|
||||
RebuildSubCheats();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FCEUI_FindCheatMapByte(uint16 address)
|
||||
{
|
||||
return cheatMap[address / 8] >> (address % 8) & 1;
|
||||
}
|
||||
|
||||
void FCEUI_SetCheatMapByte(uint16 address, bool cheat)
|
||||
{
|
||||
cheat ? cheatMap[address / 8] |= (1 << address % 8) : cheatMap[address / 8] ^= (1 << address % 8);
|
||||
}
|
||||
|
||||
void FCEUI_CreateCheatMap(void)
|
||||
{
|
||||
if (!cheatMap)
|
||||
cheatMap = (unsigned char*)malloc(CHEATMAP_SIZE);
|
||||
FCEUI_RefreshCheatMap();
|
||||
}
|
||||
|
||||
void FCEUI_RefreshCheatMap(void)
|
||||
{
|
||||
memset(cheatMap, 0, CHEATMAP_SIZE);
|
||||
for (uint32 i = 0; i < numsubcheats; ++i)
|
||||
FCEUI_SetCheatMapByte(SubCheats[i].addr, true);
|
||||
}
|
||||
|
||||
void FCEUI_ReleaseCheatMap(void)
|
||||
{
|
||||
if (cheatMap)
|
||||
{
|
||||
free(cheatMap);
|
||||
cheatMap = NULL;
|
||||
}
|
||||
//FCEUI_DispMessage("FrozenCount: %d",0,FrozenAddressCount);//Debug
|
||||
}
|
||||
|
||||
+60
-2
@@ -1,12 +1,70 @@
|
||||
#ifndef CHEAT_H
|
||||
#define CHEAT_H
|
||||
void FCEU_CheatResetRAM(void);
|
||||
void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p);
|
||||
|
||||
void FCEU_LoadGameCheats(FILE *override);
|
||||
void FCEU_LoadGameCheats(FILE *override, int override_existing = 1);
|
||||
void FCEU_FlushGameCheats(FILE *override, int nosave);
|
||||
void FCEU_SaveGameCheats(FILE *fp, int release = 0);
|
||||
int FCEUI_GlobalToggleCheat(int global_enabled);
|
||||
void FCEU_ApplyPeriodicCheats(void);
|
||||
void FCEU_PowerCheats(void);
|
||||
int FCEU_CalcCheatAffectedBytes(uint32 address, uint32 size);
|
||||
|
||||
// Trying to find a more efficient way for determining if an address has a cheat
|
||||
// each bit of 1 byte represents to 8 bytes in NES
|
||||
typedef unsigned char _8BYTECHEATMAP;
|
||||
#define CHEATMAP_SIZE 0x10000 / 8
|
||||
|
||||
extern int FCEUI_FindCheatMapByte(uint16 address);
|
||||
extern void FCEUI_SetCheatMapByte(uint16 address, bool cheat);
|
||||
extern void FCEUI_CreateCheatMap(void);
|
||||
extern void FCEUI_RefreshCheatMap(void);
|
||||
extern void FCEUI_ReleaseCheatMap(void);
|
||||
extern unsigned int FrozenAddressCount;
|
||||
|
||||
int FCEU_CheatGetByte(uint32 A);
|
||||
void FCEU_CheatSetByte(uint32 A, uint8 V);
|
||||
|
||||
extern int savecheats;
|
||||
extern int savecheats;
|
||||
extern int globalCheatDisabled;
|
||||
extern int disableAutoLSCheats;
|
||||
|
||||
int FCEU_DisableAllCheats(void);
|
||||
int FCEU_DeleteAllCheats(void);
|
||||
|
||||
typedef struct {
|
||||
uint16 addr;
|
||||
uint8 val;
|
||||
int compare;
|
||||
readfunc PrevRead;
|
||||
} CHEATF_SUBFAST;
|
||||
|
||||
struct CHEATF {
|
||||
struct CHEATF *next;
|
||||
char *name;
|
||||
uint16 addr;
|
||||
uint8 val;
|
||||
int compare; /* -1 for no compare. */
|
||||
int type; /* 0 for replace, 1 for substitute(GG). */
|
||||
int status;
|
||||
};
|
||||
|
||||
struct SEARCHPOSSIBLE {
|
||||
uint16 addr;
|
||||
uint8 previous;
|
||||
uint8 current;
|
||||
bool update;
|
||||
};
|
||||
|
||||
#define FCEU_SEARCH_SPECIFIC_CHANGE 0
|
||||
#define FCEU_SEARCH_RELATIVE_CHANGE 1
|
||||
#define FCEU_SEARCH_PUERLY_RELATIVE_CHANGE 2
|
||||
#define FCEU_SEARCH_ANY_CHANGE 3
|
||||
#define FCEU_SEARCH_NEWVAL_KNOWN 4
|
||||
#define FCEU_SEARCH_NEWVAL_GT 5
|
||||
#define FCEU_SEARCH_NEWVAL_LT 6
|
||||
#define FCEU_SEARCH_NEWVAL_GT_KNOWN 7
|
||||
#define FCEU_SEARCH_NEWVAL_LT_KNOWN 8
|
||||
|
||||
#endif
|
||||
|
||||
+62
-11
@@ -34,10 +34,11 @@
|
||||
* Primitive -> Number | Address | Register | Flag | PC Bank | '(' Connect ')'
|
||||
* Number -> '#' [1-9A-F]*
|
||||
* Address -> '$' [1-9A-F]* | '$' '[' Connect ']'
|
||||
* Register -> 'A' | 'X' | 'Y' | 'P'
|
||||
* Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V'
|
||||
* Register -> 'A' | 'X' | 'Y' | 'P' | 'S'
|
||||
* Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V' | 'U' | 'D'
|
||||
* PC Bank -> 'K'
|
||||
* Data Bank -> 'T'
|
||||
* Data Bank -> 'T'
|
||||
* Value -> 'R' | 'W'
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
@@ -50,8 +51,9 @@
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
|
||||
// hack: this address is used by 'T' condition
|
||||
uint16 addressOfTheLastAccessedData = 0;
|
||||
uint16 debugLastAddress = 0; // used by 'T' and 'R' conditions
|
||||
uint8 debugLastOpcode; // used to evaluate 'W' condition
|
||||
|
||||
// Next non-whitespace character in string
|
||||
char next;
|
||||
|
||||
@@ -137,7 +139,7 @@ int isFlag(char c)
|
||||
// Determines if a character is a register
|
||||
int isRegister(char c)
|
||||
{
|
||||
return c == 'A' || c == 'X' || c == 'Y' || c == 'P';
|
||||
return c == 'A' || c == 'X' || c == 'Y' || c == 'P' || c == 'S';
|
||||
}
|
||||
|
||||
// Determines if a character is for PC bank
|
||||
@@ -152,6 +154,18 @@ int isDataBank(char c)
|
||||
return c == 'T';
|
||||
}
|
||||
|
||||
// Determines if a character is for value read
|
||||
int isValueRead(char c)
|
||||
{
|
||||
return c == 'R';
|
||||
}
|
||||
|
||||
// Determines if a character is for value write
|
||||
int isValueWrite(char c)
|
||||
{
|
||||
return c == 'W';
|
||||
}
|
||||
|
||||
// Reads a hexadecimal number from str
|
||||
int getNumber(unsigned int* number, const char** str)
|
||||
{
|
||||
@@ -180,10 +194,10 @@ Condition* Parentheses(const char** str, Condition* c, char openPar, char closeP
|
||||
{
|
||||
scan(str);
|
||||
|
||||
c->lhs = Connect(str);
|
||||
|
||||
if (!c) return 0;
|
||||
|
||||
c->lhs = Connect(str);
|
||||
|
||||
if (next == closePar)
|
||||
{
|
||||
scan(str);
|
||||
@@ -272,6 +286,40 @@ Condition* Primitive(const char** str, Condition* c)
|
||||
|
||||
return c;
|
||||
}
|
||||
else if (isValueRead(next))
|
||||
{
|
||||
if (c->type1 == TYPE_NO)
|
||||
{
|
||||
c->type1 = TYPE_VALUE_READ;
|
||||
c->value1 = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->type2 = TYPE_VALUE_READ;
|
||||
c->value2 = next;
|
||||
}
|
||||
|
||||
scan(str);
|
||||
|
||||
return c;
|
||||
}
|
||||
else if (isValueWrite(next))
|
||||
{
|
||||
if (c->type1 == TYPE_NO)
|
||||
{
|
||||
c->type1 = TYPE_VALUE_WRITE;
|
||||
c->value1 = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->type2 = TYPE_VALUE_WRITE;
|
||||
c->value2 = next;
|
||||
}
|
||||
|
||||
scan(str);
|
||||
|
||||
return c;
|
||||
}
|
||||
else if (next == '#') /* Numbers */
|
||||
{
|
||||
unsigned int number = 0;
|
||||
@@ -352,9 +400,12 @@ Condition* Term(const char** str)
|
||||
Condition* t1;
|
||||
Condition* mid;
|
||||
|
||||
t = (Condition*)FCEU_dmalloc(sizeof(Condition));
|
||||
if (!t)
|
||||
return NULL;
|
||||
t = (Condition*)FCEU_dmalloc(sizeof(Condition));
|
||||
|
||||
if (!t)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(t, 0, sizeof(Condition));
|
||||
|
||||
|
||||
+5
-1
@@ -28,6 +28,8 @@
|
||||
#define TYPE_ADDR 4
|
||||
#define TYPE_PC_BANK 5
|
||||
#define TYPE_DATA_BANK 6
|
||||
#define TYPE_VALUE_READ 7
|
||||
#define TYPE_VALUE_WRITE 8
|
||||
|
||||
#define OP_NO 0
|
||||
#define OP_EQ 1
|
||||
@@ -43,7 +45,9 @@
|
||||
#define OP_OR 11
|
||||
#define OP_AND 12
|
||||
|
||||
extern uint16 addressOfTheLastAccessedData;
|
||||
extern uint16 debugLastAddress;
|
||||
extern uint8 debugLastOpcode;
|
||||
|
||||
//mbg merge 7/18/06 turned into sane c++
|
||||
struct Condition
|
||||
{
|
||||
|
||||
+15
-6
@@ -13,15 +13,20 @@
|
||||
|
||||
static char *aboutString = 0;
|
||||
|
||||
#ifndef FCEUX_BUILD_TIMESTAMP
|
||||
#define FCEUX_BUILD_TIMESTAMP __TIME__ " " __DATE__
|
||||
#endif
|
||||
|
||||
// returns a string suitable for use in an aboutbox
|
||||
char *FCEUI_GetAboutString() {
|
||||
const char *FCEUI_GetAboutString(void)
|
||||
{
|
||||
const char *aboutTemplate =
|
||||
FCEU_NAME_AND_VERSION "\n\n"
|
||||
"Administrators:\n"
|
||||
"zeromus, punkrockguy318 (Lukas Sabota), feos\n"
|
||||
"zeromus, mjbudd77, feos\n"
|
||||
"\n"
|
||||
"Current Contributors:\n"
|
||||
"CaH4e3, rainwarrior\n"
|
||||
"CaH4e3, rainwarrior, owomomo, punkrockguy318\n"
|
||||
"\n"
|
||||
"Past Contributors:\n"
|
||||
"xhainingx, gocha, AnS\n"
|
||||
@@ -40,13 +45,17 @@ char *FCEUI_GetAboutString() {
|
||||
"FCEU TAS - blip & nitsuja\n"
|
||||
"FCEU TAS+ - Luke Gustafson\n"
|
||||
"\n"
|
||||
"Logo/icon:\n"
|
||||
"Terwilf\n"
|
||||
"\n"
|
||||
"FCEUX is dedicated to the fallen heroes\n"
|
||||
"of NES emulation. In Memoriam --\n"
|
||||
"ugetab\n"
|
||||
"\n"
|
||||
__TIME__ " " __DATE__ "\n";
|
||||
"\n"
|
||||
FCEUX_BUILD_TIMESTAMP "\n";
|
||||
|
||||
if(aboutString) return aboutString;
|
||||
if (aboutString) return aboutString;
|
||||
|
||||
const char *compilerString = FCEUD_GetCompilerString();
|
||||
|
||||
@@ -54,6 +63,6 @@ char *FCEUI_GetAboutString() {
|
||||
if (!(aboutString = (char*)FCEU_dmalloc(strlen(aboutTemplate) + strlen(compilerString) + 1)))
|
||||
return NULL;
|
||||
|
||||
sprintf(aboutString,"%s%s",aboutTemplate,compilerString);
|
||||
sprintf(aboutString,"%s%s",aboutTemplate,compilerString);
|
||||
return aboutString;
|
||||
}
|
||||
|
||||
+229
-95
@@ -22,7 +22,7 @@ int offsetStringToInt(unsigned int type, const char* offsetBuffer)
|
||||
{
|
||||
int offset = -1;
|
||||
|
||||
if (sscanf(offsetBuffer,"%4X",&offset) == EOF)
|
||||
if (sscanf(offsetBuffer,"%7X",(unsigned int *)&offset) == EOF)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -35,14 +35,24 @@ int offsetStringToInt(unsigned int type, const char* offsetBuffer)
|
||||
{
|
||||
return offset & 0x00FF;
|
||||
}
|
||||
else if (type & BT_R)
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
else // BT_C
|
||||
{
|
||||
if (GameInfo->type == GIT_NSF) { //NSF Breakpoint keywords
|
||||
int type = GIT_CART;
|
||||
|
||||
if (GameInfo)
|
||||
{
|
||||
type = GameInfo->type;
|
||||
}
|
||||
if (type == GIT_NSF) { //NSF Breakpoint keywords
|
||||
if (strcmp(offsetBuffer,"LOAD") == 0) return (NSFHeader.LoadAddressLow | (NSFHeader.LoadAddressHigh<<8));
|
||||
if (strcmp(offsetBuffer,"INIT") == 0) return (NSFHeader.InitAddressLow | (NSFHeader.InitAddressHigh<<8));
|
||||
if (strcmp(offsetBuffer,"PLAY") == 0) return (NSFHeader.PlayAddressLow | (NSFHeader.PlayAddressHigh<<8));
|
||||
}
|
||||
else if (GameInfo->type == GIT_FDS) { //FDS Breakpoint keywords
|
||||
else if (type == GIT_FDS) { //FDS Breakpoint keywords
|
||||
if (strcmp(offsetBuffer,"NMI1") == 0) return (GetMem(0xDFF6) | (GetMem(0xDFF7)<<8));
|
||||
if (strcmp(offsetBuffer,"NMI2") == 0) return (GetMem(0xDFF8) | (GetMem(0xDFF9)<<8));
|
||||
if (strcmp(offsetBuffer,"NMI3") == 0) return (GetMem(0xDFFA) | (GetMem(0xDFFB)<<8));
|
||||
@@ -56,7 +66,7 @@ int offsetStringToInt(unsigned int type, const char* offsetBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
return offset & 0xFFFF;
|
||||
}
|
||||
|
||||
// Returns the value of a given type or register
|
||||
@@ -77,6 +87,7 @@ int getValue(int type)
|
||||
case 'Z': return _P & Z_FLAG ? 1 : 0;
|
||||
case 'C': return _P & C_FLAG ? 1 : 0;
|
||||
case 'P': return _PC;
|
||||
case 'S': return _S;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -193,6 +204,9 @@ unsigned int NewBreak(const char* name, int start, int end, unsigned int type, c
|
||||
watchpoint[num].flags|=BT_S;
|
||||
watchpoint[num].flags&=~WP_X; //disable execute flag!
|
||||
}
|
||||
if (type & BT_R) {
|
||||
watchpoint[num].flags|=BT_R;
|
||||
}
|
||||
|
||||
if (watchpoint[num].desc)
|
||||
free(watchpoint[num].desc);
|
||||
@@ -207,11 +221,27 @@ int GetPRGAddress(int A){
|
||||
int result;
|
||||
if(A > 0xFFFF)
|
||||
return -1;
|
||||
result = &Page[A>>11][A]-PRGptr[0];
|
||||
if((result > (int)PRGsize[0]) || (result < 0))
|
||||
return -1;
|
||||
else
|
||||
return result;
|
||||
if (GameInfo->type == GIT_FDS) {
|
||||
if (A < 0xE000) {
|
||||
result = &Page[A >> 11][A] - PRGptr[1];
|
||||
if ((result > (int)PRGsize[1]) || (result < 0))
|
||||
return -1;
|
||||
else
|
||||
return result;
|
||||
} else {
|
||||
result = &Page[A >> 11][A] - PRGptr[0];
|
||||
if ((result > (int)PRGsize[0]) || (result < 0))
|
||||
return -1;
|
||||
else
|
||||
return result + PRGsize[1];
|
||||
}
|
||||
} else {
|
||||
result = &Page[A >> 11][A] - PRGptr[0];
|
||||
if ((result > (int)PRGsize[0]) || (result < 0))
|
||||
return -1;
|
||||
else
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,6 +339,32 @@ uint8 GetPPUMem(uint8 A) {
|
||||
|
||||
//---------------------
|
||||
|
||||
uint8 evaluateWrite(uint8 opcode, uint16 address)
|
||||
{
|
||||
// predicts value written by this opcode
|
||||
switch (opwrite[opcode])
|
||||
{
|
||||
default:
|
||||
case 0: return 0; // no write
|
||||
case 1: return _A; // STA, PHA
|
||||
case 2: return _X; // STX
|
||||
case 3: return _Y; // STY
|
||||
case 4: return _P; // PHP
|
||||
case 5: return GetMem(address) << 1; // ASL (SLO)
|
||||
case 6: return GetMem(address) >> 1; // LSR (SRE)
|
||||
case 7: return (GetMem(address) << 1) | (_P & 1); // ROL (RLA)
|
||||
case 8: return (GetMem(address) >> 1) | ((_P & 1) << 7); // ROL (RRA)
|
||||
case 9: return GetMem(address) + 1; // INC (ISC)
|
||||
case 10: return GetMem(address) - 1; // DEC (DCP)
|
||||
case 11: return _A & _X; // (SAX)
|
||||
case 12: return _A&_X&(((address-_Y)>>8)+1); // (AHX)
|
||||
case 13: return _Y&(((address-_X)>>8)+1); // (SHY)
|
||||
case 14: return _X&(((address-_Y)>>8)+1); // (SHX)
|
||||
case 15: return _S& (((address-_Y)>>8)+1); // (TAS)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Evaluates a condition
|
||||
int evaluate(Condition* c)
|
||||
{
|
||||
@@ -334,7 +390,9 @@ int evaluate(Condition* c)
|
||||
{
|
||||
case TYPE_ADDR: value1 = GetMem(value1); break;
|
||||
case TYPE_PC_BANK: value1 = getBank(_PC); break;
|
||||
case TYPE_DATA_BANK: value1 = getBank(addressOfTheLastAccessedData); break;
|
||||
case TYPE_DATA_BANK: value1 = getBank(debugLastAddress); break;
|
||||
case TYPE_VALUE_READ: value1 = GetMem(debugLastAddress); break;
|
||||
case TYPE_VALUE_WRITE: value1 = evaluateWrite(debugLastOpcode, debugLastAddress); break;
|
||||
}
|
||||
|
||||
f = value1;
|
||||
@@ -359,7 +417,9 @@ int evaluate(Condition* c)
|
||||
{
|
||||
case TYPE_ADDR: value2 = GetMem(value2); break;
|
||||
case TYPE_PC_BANK: value2 = getBank(_PC); break;
|
||||
case TYPE_DATA_BANK: value2 = getBank(addressOfTheLastAccessedData); break;
|
||||
case TYPE_DATA_BANK: value2 = getBank(debugLastAddress); break;
|
||||
case TYPE_VALUE_READ: value2 = GetMem(debugLastAddress); break;
|
||||
case TYPE_VALUE_WRITE: value2 = evaluateWrite(debugLastOpcode, debugLastAddress); break;
|
||||
}
|
||||
|
||||
switch (c->op)
|
||||
@@ -371,7 +431,7 @@ int evaluate(Condition* c)
|
||||
case OP_G: f = value1 > value2; break;
|
||||
case OP_L: f = value1 < value2; break;
|
||||
case OP_MULT: f = value1 * value2; break;
|
||||
case OP_DIV: f = value1 / value2; break;
|
||||
case OP_DIV: f = (value2==0) ? 0 : (value1 / value2); break;
|
||||
case OP_PLUS: f = value1 + value2; break;
|
||||
case OP_MINUS: f = value1 - value2; break;
|
||||
case OP_OR: f = value1 || value2; break;
|
||||
@@ -390,12 +450,12 @@ int condition(watchpointinfo* wp)
|
||||
|
||||
//---------------------
|
||||
|
||||
volatile int codecount, datacount, undefinedcount;
|
||||
unsigned char *cdloggerdata;
|
||||
volatile int codecount = 0, datacount = 0, undefinedcount = 0;
|
||||
unsigned char *cdloggerdata = NULL;
|
||||
unsigned int cdloggerdataSize = 0;
|
||||
static int indirectnext;
|
||||
static int indirectnext = 0;
|
||||
|
||||
int debug_loggingCD;
|
||||
int debug_loggingCD = 0;
|
||||
|
||||
//called by the cpu to perform logging if CDLogging is enabled
|
||||
void LogCDVectors(int which){
|
||||
@@ -417,20 +477,29 @@ void LogCDVectors(int which){
|
||||
}
|
||||
}
|
||||
|
||||
void LogCDData(uint8 *opcode, uint16 A, int size) {
|
||||
bool break_on_unlogged_code = false;
|
||||
bool break_on_unlogged_data = false;
|
||||
|
||||
void LogCDData(uint8 *opcode, uint16 A, int size)
|
||||
{
|
||||
int i, j;
|
||||
uint8 memop = 0;
|
||||
bool newCodeHit = false, newDataHit = false;
|
||||
|
||||
if((j = GetPRGAddress(_PC)) != -1)
|
||||
for (i = 0; i < size; i++) {
|
||||
if(cdloggerdata[j+i] & 1)continue; //this has been logged so skip
|
||||
if ((j = GetPRGAddress(_PC)) != -1)
|
||||
{
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (cdloggerdata[j+i] & 1) continue; //this has been logged so skip
|
||||
cdloggerdata[j+i] |= 1;
|
||||
cdloggerdata[j+i] |= ((_PC + i) >> 11) & 0x0c;
|
||||
cdloggerdata[j+i] |= ((_PC & 0x8000) >> 8) ^ 0x80; // 19/07/14 used last reserved bit, if bit 7 is 1, then code is running from lowe area (6000)
|
||||
if(indirectnext)cdloggerdata[j+i] |= 0x10;
|
||||
if (indirectnext)cdloggerdata[j+i] |= 0x10;
|
||||
codecount++;
|
||||
if(!(cdloggerdata[j+i] & 2))undefinedcount--;
|
||||
if (!(cdloggerdata[j+i] & 2))undefinedcount--;
|
||||
newCodeHit = true;
|
||||
}
|
||||
}
|
||||
|
||||
//log instruction jumped to in an indirect jump
|
||||
if(opcode[0] == 0x6c)
|
||||
@@ -443,14 +512,43 @@ void LogCDData(uint8 *opcode, uint16 A, int size) {
|
||||
case 4: memop = 0x20; break;
|
||||
}
|
||||
|
||||
if((j = GetPRGAddress(A)) != -1) {
|
||||
if(!(cdloggerdata[j] & 2)) {
|
||||
cdloggerdata[j] |= 2;
|
||||
cdloggerdata[j] |=(A>>11)&0x0c;
|
||||
cdloggerdata[j] |= memop;
|
||||
datacount++;
|
||||
if(!(cdloggerdata[j] & 1))undefinedcount--;
|
||||
if ((j = GetPRGAddress(A)) != -1)
|
||||
{
|
||||
if (opwrite[opcode[0]] == 0)
|
||||
{
|
||||
if (!(cdloggerdata[j] & 2))
|
||||
{
|
||||
cdloggerdata[j] |= 2;
|
||||
cdloggerdata[j] |= (A >> 11) & 0x0c;
|
||||
cdloggerdata[j] |= memop;
|
||||
cdloggerdata[j] |= ((A & 0x8000) >> 8) ^ 0x80;
|
||||
datacount++;
|
||||
if (!(cdloggerdata[j] & 1))undefinedcount--;
|
||||
newDataHit = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cdloggerdata[j] & 1)
|
||||
{
|
||||
codecount--;
|
||||
}
|
||||
if (cdloggerdata[j] & 2)
|
||||
{
|
||||
datacount--;
|
||||
}
|
||||
if ((cdloggerdata[j] & 3) != 0) undefinedcount++;
|
||||
cdloggerdata[j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( break_on_unlogged_code && newCodeHit )
|
||||
{
|
||||
BreakHit( BREAK_TYPE_UNLOGGED_CODE );
|
||||
}
|
||||
else if ( break_on_unlogged_data && newDataHit )
|
||||
{
|
||||
BreakHit( BREAK_TYPE_UNLOGGED_DATA );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,61 +600,70 @@ void IncrementInstructionsCounters()
|
||||
delta_instructions++;
|
||||
}
|
||||
|
||||
void BreakHit(int bp_num, bool force)
|
||||
{
|
||||
if(!force)
|
||||
bool CondForbidTest(int bp_num) {
|
||||
if (bp_num >= 0 && !condition(&watchpoint[bp_num]))
|
||||
{
|
||||
//check to see whether we fall in any forbid zone
|
||||
for (int i = 0; i < numWPs; i++)
|
||||
{
|
||||
watchpointinfo& wp = watchpoint[i];
|
||||
if(!(wp.flags & WP_F) || !(wp.flags & WP_E))
|
||||
continue;
|
||||
return false; // condition rejected
|
||||
}
|
||||
|
||||
if (condition(&wp))
|
||||
{
|
||||
if (wp.endaddress) {
|
||||
if( (wp.address <= _PC) && (wp.endaddress >= _PC) )
|
||||
return; //forbid
|
||||
} else {
|
||||
if(wp.address == _PC)
|
||||
return; //forbid
|
||||
}
|
||||
//check to see whether we fall in any forbid zone
|
||||
for (int i = 0; i < numWPs; i++)
|
||||
{
|
||||
watchpointinfo& wp = watchpoint[i];
|
||||
if (!(wp.flags & WP_F) || !(wp.flags & WP_E))
|
||||
continue;
|
||||
|
||||
if (condition(&wp))
|
||||
{
|
||||
if (wp.endaddress) {
|
||||
if ((wp.address <= _PC) && (wp.endaddress >= _PC))
|
||||
return false; // forbid
|
||||
}
|
||||
else {
|
||||
if (wp.address == _PC)
|
||||
return false; // forbid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FCEUI_SetEmulationPaused(EMULATIONPAUSED_PAUSED); //mbg merge 7/19/06 changed to use EmulationPaused()
|
||||
|
||||
#ifdef WIN32
|
||||
FCEUD_DebugBreakpoint(bp_num);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8 StackAddrBackup = X.S;
|
||||
void BreakHit(int bp_num)
|
||||
{
|
||||
FCEUI_SetEmulationPaused(EMULATIONPAUSED_PAUSED); //mbg merge 7/19/06 changed to use EmulationPaused()
|
||||
|
||||
//#ifdef WIN32
|
||||
FCEUD_DebugBreakpoint(bp_num);
|
||||
//#endif
|
||||
}
|
||||
|
||||
int StackAddrBackup;
|
||||
uint16 StackNextIgnorePC = 0xFFFF;
|
||||
|
||||
///fires a breakpoint
|
||||
static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
int i, j;
|
||||
int i, j, romAddrPC;
|
||||
uint8 brk_type;
|
||||
uint8 stackop=0;
|
||||
uint8 stackopstartaddr,stackopendaddr;
|
||||
uint8 stackopstartaddr=0,stackopendaddr=0;
|
||||
|
||||
debugLastAddress = A;
|
||||
debugLastOpcode = opcode[0];
|
||||
|
||||
if (break_asap)
|
||||
{
|
||||
break_asap = false;
|
||||
BreakHit(BREAK_TYPE_LUA, true);
|
||||
BreakHit(BREAK_TYPE_LUA);
|
||||
}
|
||||
|
||||
if (break_on_cycles && ((timestampbase + (uint64)timestamp - total_cycles_base) > break_cycles_limit))
|
||||
BreakHit(BREAK_TYPE_CYCLES_EXCEED, true);
|
||||
BreakHit(BREAK_TYPE_CYCLES_EXCEED);
|
||||
if (break_on_instructions && (total_instructions > break_instructions_limit))
|
||||
BreakHit(BREAK_TYPE_INSTRUCTIONS_EXCEED, true);
|
||||
BreakHit(BREAK_TYPE_INSTRUCTIONS_EXCEED);
|
||||
|
||||
//if the current instruction is bad, and we are breaking on bad opcodes, then hit the breakpoint
|
||||
if(dbgstate.badopbreak && (size == 0))
|
||||
BreakHit(BREAK_TYPE_BADOP, true);
|
||||
BreakHit(BREAK_TYPE_BADOP);
|
||||
|
||||
//if we're stepping out, track the nest level
|
||||
if (dbgstate.stepout) {
|
||||
@@ -575,7 +682,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
//if we're stepping, then we'll always want to break
|
||||
if (dbgstate.step) {
|
||||
dbgstate.step = false;
|
||||
BreakHit(BREAK_TYPE_STEP, true);
|
||||
BreakHit(BREAK_TYPE_STEP);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -587,7 +694,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if (diff<=0)
|
||||
{
|
||||
dbgstate.runline=false;
|
||||
BreakHit(BREAK_TYPE_STEP, true);
|
||||
BreakHit(BREAK_TYPE_STEP);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -596,33 +703,36 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if ((watchpoint[64].address == _PC) && (watchpoint[64].flags)) {
|
||||
watchpoint[64].address = 0;
|
||||
watchpoint[64].flags = 0;
|
||||
BreakHit(BREAK_TYPE_STEP, true);
|
||||
BreakHit(BREAK_TYPE_STEP);
|
||||
return;
|
||||
}
|
||||
|
||||
romAddrPC = GetNesFileAddress(_PC);
|
||||
|
||||
brk_type = opbrktype[opcode[0]] | WP_X;
|
||||
|
||||
switch (opcode[0]) {
|
||||
//Push Ops
|
||||
case 0x08: //Fall to next
|
||||
case 0x48: stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||
case 0x48: debugLastAddress=stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||
//Pull Ops
|
||||
case 0x28: //Fall to next
|
||||
case 0x68: stackopstartaddr=stackopendaddr=X.S+1; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||
case 0x68: debugLastAddress=stackopstartaddr=stackopendaddr=X.S+1; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||
//JSR (Includes return address - 1)
|
||||
case 0x20: stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=(opcode[1]|opcode[2]<<8); break;
|
||||
//RTI (Includes processor status, and exact return address)
|
||||
case 0x40: stackopstartaddr=X.S+1; stackopendaddr=X.S+3; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=(GetMem(X.S+2|0x0100)|GetMem(X.S+3|0x0100)<<8); break;
|
||||
//RTS (Includes return address - 1)
|
||||
case 0x60: stackopstartaddr=X.S+1; stackopendaddr=X.S+2; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=(GetMem(stackopstartaddr|0x0100)|GetMem(stackopendaddr|0x0100)<<8)+1; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
#define BREAKHIT(x) { if (CondForbidTest(x)) { breakHit = (x); goto STOPCHECKING; } }
|
||||
int breakHit = -1;
|
||||
for (i = 0; i < numWPs; i++)
|
||||
{
|
||||
// ################################## Start of SP CODE ###########################
|
||||
if ((watchpoint[i].flags & WP_E) && condition(&watchpoint[i]))
|
||||
if ((watchpoint[i].flags & WP_E))
|
||||
{
|
||||
// ################################## End of SP CODE ###########################
|
||||
if (watchpoint[i].flags & BT_P)
|
||||
{
|
||||
// PPU Mem breaks
|
||||
@@ -632,11 +742,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if (watchpoint[i].endaddress)
|
||||
{
|
||||
if ((watchpoint[i].address <= PPUAddr) && (watchpoint[i].endaddress >= PPUAddr))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == PPUAddr)
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
}
|
||||
} else if (watchpoint[i].flags & BT_S)
|
||||
@@ -647,16 +757,16 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if (watchpoint[i].endaddress)
|
||||
{
|
||||
if ((watchpoint[i].address <= PPU[3]) && (watchpoint[i].endaddress >= PPU[3]))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == PPU[3])
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
} else if ((watchpoint[i].flags & WP_W) && (A == 0x4014))
|
||||
{
|
||||
// Sprite DMA! :P
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
} else
|
||||
{
|
||||
@@ -667,12 +777,32 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
{
|
||||
if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address <= A) && (watchpoint[i].endaddress >= A)) ||
|
||||
((watchpoint[i].flags & WP_X) && (watchpoint[i].address <= _PC) && (watchpoint[i].endaddress >= _PC)))
|
||||
BreakHit(i);
|
||||
} else
|
||||
BREAKHIT(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address == A)) ||
|
||||
((watchpoint[i].flags & WP_X) && (watchpoint[i].address == _PC)))
|
||||
BreakHit(i);
|
||||
if (watchpoint[i].flags & BT_R)
|
||||
{
|
||||
if ( (watchpoint[i].flags & WP_X) && (watchpoint[i].address == romAddrPC) )
|
||||
{
|
||||
BREAKHIT(i);
|
||||
}
|
||||
//else if ( (watchpoint[i].flags & WP_R) && (watchpoint[i].address == A) )
|
||||
//{
|
||||
// BREAKHIT(i);
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address == A))
|
||||
{
|
||||
BREAKHIT(i);
|
||||
}
|
||||
else if ( (watchpoint[i].flags & WP_X) && (watchpoint[i].address == _PC) )
|
||||
{
|
||||
BREAKHIT(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
@@ -689,11 +819,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if (watchpoint[i].endaddress)
|
||||
{
|
||||
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == j)
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -704,7 +834,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
StackNextIgnorePC = 0xFFFF;
|
||||
} else
|
||||
{
|
||||
if ((X.S < StackAddrBackup) && (stackop==0))
|
||||
if (StackAddrBackup != -1 && (X.S < StackAddrBackup) && (stackop==0))
|
||||
{
|
||||
// Unannounced stack mem breaks
|
||||
// Pushes to stack
|
||||
@@ -715,15 +845,15 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if (watchpoint[i].endaddress)
|
||||
{
|
||||
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == j)
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ((StackAddrBackup < X.S) && (stackop==0))
|
||||
} else if (StackAddrBackup != -1 && (StackAddrBackup < X.S) && (stackop==0))
|
||||
{
|
||||
// Pulls from stack
|
||||
if (watchpoint[i].flags & WP_R)
|
||||
@@ -733,11 +863,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if (watchpoint[i].endaddress)
|
||||
{
|
||||
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == j)
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -746,13 +876,20 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
|
||||
}
|
||||
}
|
||||
// ################################## Start of SP CODE ###########################
|
||||
}
|
||||
// ################################## End of SP CODE ###########################
|
||||
}
|
||||
} //loop across all breakpoints
|
||||
|
||||
STOPCHECKING:
|
||||
|
||||
//Update the stack address with the current one, now that changes have registered.
|
||||
//ZEROMUS THINKS IT MAKES MORE SENSE HERE
|
||||
StackAddrBackup = X.S;
|
||||
|
||||
if(breakHit != -1)
|
||||
BreakHit(i);
|
||||
|
||||
////Update the stack address with the current one, now that changes have registered.
|
||||
//StackAddrBackup = X.S;
|
||||
}
|
||||
//bbit edited: this is the end of the inserted code
|
||||
|
||||
@@ -781,9 +918,12 @@ void DebugCycle()
|
||||
size = opsize[opcode[0]];
|
||||
switch (size)
|
||||
{
|
||||
default:
|
||||
case 1: break;
|
||||
case 2:
|
||||
opcode[1] = GetMem(_PC + 1);
|
||||
break;
|
||||
case 0: // illegal instructions may have operands
|
||||
case 3:
|
||||
opcode[1] = GetMem(_PC + 1);
|
||||
opcode[2] = GetMem(_PC + 2);
|
||||
@@ -807,7 +947,6 @@ void DebugCycle()
|
||||
case 7: A = (opcode[1] | (opcode[2] << 8)) + _X; break;
|
||||
case 8: A = opcode[1] + _Y; break;
|
||||
}
|
||||
addressOfTheLastAccessedData = A;
|
||||
|
||||
if (numWPs || dbgstate.step || dbgstate.runline || dbgstate.stepout || watchpoint[64].flags || dbgstate.badopbreak || break_on_cycles || break_on_instructions || break_asap)
|
||||
breakpoint(opcode, A, size);
|
||||
@@ -815,10 +954,5 @@ void DebugCycle()
|
||||
if(debug_loggingCD)
|
||||
LogCDData(opcode, A, size);
|
||||
|
||||
#ifdef WIN32
|
||||
//This needs to be windows only or else the linux build system will fail since logging is declared in a
|
||||
//windows source file
|
||||
FCEUD_TraceInstruction(opcode, size);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
+13
-7
@@ -15,12 +15,15 @@
|
||||
#define BT_C 0x00 //break type, cpu mem
|
||||
#define BT_P 0x20 //break type, ppu mem
|
||||
#define BT_S 0x40 //break type, sprite mem
|
||||
#define BT_R 0x80 //break type, rom mem
|
||||
|
||||
#define BREAK_TYPE_STEP -1
|
||||
#define BREAK_TYPE_BADOP -2
|
||||
#define BREAK_TYPE_CYCLES_EXCEED -3
|
||||
#define BREAK_TYPE_INSTRUCTIONS_EXCEED -4
|
||||
#define BREAK_TYPE_LUA -5
|
||||
#define BREAK_TYPE_UNLOGGED_CODE -6
|
||||
#define BREAK_TYPE_UNLOGGED_DATA -7
|
||||
|
||||
//opbrktype is used to grab the breakpoint type that each instruction will cause.
|
||||
//WP_X is not used because ALL opcodes will have the execute bit set.
|
||||
@@ -46,21 +49,20 @@ static const uint8 opbrktype[256] = {
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16 address;
|
||||
uint16 endaddress;
|
||||
uint8 flags;
|
||||
// ################################## Start of SP CODE ###########################
|
||||
uint32 address;
|
||||
uint32 endaddress;
|
||||
uint16 flags;
|
||||
|
||||
Condition* cond;
|
||||
char* condText;
|
||||
char* desc;
|
||||
|
||||
// ################################## End of SP CODE ###########################
|
||||
} watchpointinfo;
|
||||
|
||||
//mbg merge 7/18/06 had to make this extern
|
||||
extern watchpointinfo watchpoint[65]; //64 watchpoints, + 1 reserved for step over
|
||||
|
||||
extern unsigned int debuggerPageSize;
|
||||
int getBank(int offs);
|
||||
int GetNesFileAddress(int A);
|
||||
int GetPRGAddress(int A);
|
||||
@@ -95,9 +97,12 @@ static INLINE int FCEUI_GetLoggingCD() { return debug_loggingCD; }
|
||||
extern int iaPC;
|
||||
extern uint32 iapoffset; //mbg merge 7/18/06 changed from int
|
||||
void DebugCycle();
|
||||
void BreakHit(int bp_num, bool force = false);
|
||||
bool CondForbidTest(int bp_num);
|
||||
void BreakHit(int bp_num);
|
||||
|
||||
extern bool break_asap;
|
||||
extern bool break_on_unlogged_code;
|
||||
extern bool break_on_unlogged_data;
|
||||
extern uint64 total_cycles_base;
|
||||
extern uint64 delta_cycles_base;
|
||||
extern bool break_on_cycles;
|
||||
@@ -115,8 +120,9 @@ extern void IncrementInstructionsCounters();
|
||||
|
||||
//internal variables that debuggers will want access to
|
||||
extern uint8 *vnapage[4],*VPage[8];
|
||||
extern uint8 PPU[4],PALRAM[0x20],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset;
|
||||
extern uint8 PPU[4],PALRAM[0x20],UPALRAM[3],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset;
|
||||
extern uint32 FCEUPPU_PeekAddress();
|
||||
extern uint8 READPAL_MOTHEROFALL(uint32 A);
|
||||
extern int numWPs;
|
||||
|
||||
///encapsulates the operational state of the debugger core
|
||||
|
||||
+4
-4
@@ -395,10 +395,10 @@ static int FixJoedChar(uint8 ch)
|
||||
int c = ch - 32;
|
||||
return (c < 0 || c > 98) ? 0 : c;
|
||||
}
|
||||
static int JoedCharWidth(uint8 ch)
|
||||
{
|
||||
return Font6x7[FixJoedChar(ch)*8];
|
||||
}
|
||||
//static int JoedCharWidth(uint8 ch)
|
||||
//{
|
||||
// return Font6x7[FixJoedChar(ch)*8];
|
||||
//}
|
||||
|
||||
char target[64][256];
|
||||
|
||||
|
||||
+18
-5
@@ -14,14 +14,16 @@ inline FILE *FCEUD_UTF8fopen(const std::string &n, const char *mode) { return FC
|
||||
EMUFILE_FILE* FCEUD_UTF8_fstream(const char *n, const char *m);
|
||||
inline EMUFILE_FILE* FCEUD_UTF8_fstream(const std::string &n, const char *m) { return FCEUD_UTF8_fstream(n.c_str(),m); }
|
||||
FCEUFILE* FCEUD_OpenArchiveIndex(ArchiveScanRecord& asr, std::string& fname, int innerIndex);
|
||||
FCEUFILE* FCEUD_OpenArchiveIndex(ArchiveScanRecord& asr, std::string& fname, int innerIndex, int* userCancel);
|
||||
FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename);
|
||||
FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename, int* userCancel);
|
||||
ArchiveScanRecord FCEUD_ScanArchive(std::string fname);
|
||||
|
||||
//mbg 7/23/06
|
||||
const char *FCEUD_GetCompilerString();
|
||||
|
||||
//This makes me feel dirty for some reason.
|
||||
void FCEU_printf(char *format, ...);
|
||||
void FCEU_printf(const char *format, ...);
|
||||
#define FCEUI_printf FCEU_printf
|
||||
|
||||
//Video interface
|
||||
@@ -122,7 +124,8 @@ void FCEUI_SetVidSystem(int a);
|
||||
|
||||
//Set variables for NTSC(0) / PAL(1) / Dendy(2)
|
||||
//Dendy has PAL framerate and resolution, but ~NTSC timings, and has 50 dummy scanlines to force 50 fps
|
||||
void FCEUI_SetRegion(int region);
|
||||
void FCEUI_SetRegion(int region, int notify = 1);
|
||||
int FCEUI_GetRegion(void);
|
||||
|
||||
//Convenience function; returns currently emulated video system(0=NTSC, 1=PAL).
|
||||
int FCEUI_GetCurrentVidSystem(int *slstart, int *slend);
|
||||
@@ -140,7 +143,9 @@ void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall);
|
||||
|
||||
//Sets the base directory(save states, snapshots, etc. are saved in directories below this directory.
|
||||
void FCEUI_SetBaseDirectory(std::string const & dir);
|
||||
const char *FCEUI_GetBaseDirectory(void);
|
||||
|
||||
bool FCEUI_GetUserPaletteAvail(void);
|
||||
void FCEUI_SetUserPalette(uint8 *pal, int nEntries);
|
||||
|
||||
//Sets up sound code to render sound at the specified rate, in samples
|
||||
@@ -178,10 +183,16 @@ void FCEUD_MovieRecordTo(void);
|
||||
void FCEUD_MovieReplayFrom(void);
|
||||
void FCEUD_LuaRunFrom(void);
|
||||
|
||||
#ifdef _S9XLUA_H
|
||||
// lua engine
|
||||
void TaseditorAutoFunction(void);
|
||||
void TaseditorManualFunction(void);
|
||||
#endif
|
||||
|
||||
int32 FCEUI_GetDesiredFPS(void);
|
||||
void FCEUI_SaveSnapshot(void);
|
||||
void FCEUI_SaveSnapshotAs(void);
|
||||
void FCEU_DispMessage(char *format, int disppos, ...);
|
||||
void FCEU_DispMessage(const char *format, int disppos, ...);
|
||||
#define FCEUI_DispMessage FCEU_DispMessage
|
||||
|
||||
int FCEUI_DecodePAR(const char *code, int *a, int *v, int *c, int *type);
|
||||
@@ -189,6 +200,7 @@ int FCEUI_DecodeGG(const char *str, int *a, int *v, int *c);
|
||||
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type);
|
||||
int FCEUI_DelCheat(uint32 which);
|
||||
int FCEUI_ToggleCheat(uint32 which);
|
||||
int FCEUI_GlobalToggleCheat(int global_enable);
|
||||
|
||||
int32 FCEUI_CheatSearchGetCount(void);
|
||||
void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current));
|
||||
@@ -247,7 +259,7 @@ void FCEUI_FDSInsert(void); //mbg merge 7/17/06 changed to void fn(void) to make
|
||||
//int FCEUI_FDSEject(void);
|
||||
void FCEUI_FDSSelect(void);
|
||||
|
||||
int FCEUI_DatachSet(const uint8 *rcode);
|
||||
int FCEUI_DatachSet(uint8 *rcode);
|
||||
|
||||
///returns a flag indicating whether emulation is paused
|
||||
int FCEUI_EmulationPaused();
|
||||
@@ -337,7 +349,8 @@ enum EFCEUI
|
||||
FCEUI_STOPMOVIE, FCEUI_RECORDMOVIE, FCEUI_PLAYMOVIE,
|
||||
FCEUI_OPENGAME, FCEUI_CLOSEGAME,
|
||||
FCEUI_TASEDITOR,
|
||||
FCEUI_RESET, FCEUI_POWER, FCEUI_PLAYFROMBEGINNING, FCEUI_EJECT_DISK, FCEUI_SWITCH_DISK, FCEUI_INSERT_COIN
|
||||
FCEUI_RESET, FCEUI_POWER, FCEUI_PLAYFROMBEGINNING, FCEUI_EJECT_DISK, FCEUI_SWITCH_DISK, FCEUI_INSERT_COIN, FCEUI_INPUT_BARCODE,
|
||||
FCEUI_TOGGLERECORDINGMOVIE, FCEUI_TRUNCATEMOVIE, FCEUI_INSERT1FRAME, FCEUI_DELETE1FRAME
|
||||
};
|
||||
|
||||
//checks whether an EFCEUI is valid right now
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import glob
|
||||
source_list = glob.glob('*.cpp') + glob.glob('*.c')
|
||||
|
||||
for x in range(len(source_list)):
|
||||
source_list[x] = 'drivers/common/' + source_list[x]
|
||||
Return('source_list')
|
||||
@@ -19,11 +19,11 @@
|
||||
*/
|
||||
|
||||
/****************************************************************/
|
||||
/* FCE Ultra */
|
||||
/* */
|
||||
/* This file contains code for parsing command-line */
|
||||
/* options. */
|
||||
/* */
|
||||
/* FCE Ultra */
|
||||
/* */
|
||||
/* This file contains code for parsing command-line */
|
||||
/* options. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -176,7 +176,7 @@ int AddToList(char *text, uint32 id)
|
||||
**/
|
||||
|
||||
typedef struct MENU {
|
||||
char *text;
|
||||
const char *text;
|
||||
void *action;
|
||||
int type; // 0 for menu, 1 for function.
|
||||
} MENU;
|
||||
@@ -226,7 +226,7 @@ static void ModifyCheat(int num)
|
||||
printf("Address [$%04x]: ",(unsigned int)A);
|
||||
A=GetH16(A);
|
||||
|
||||
printf("Value [%03d]: ",(unsigned int)V);
|
||||
printf("Value [%03u]: ",(unsigned int)V);
|
||||
V=Get8(V);
|
||||
|
||||
printf("Compare [%3d]: ",compare);
|
||||
@@ -302,9 +302,9 @@ static void AddCheatParam(uint32 A, uint8 V)
|
||||
GetString(name,256);
|
||||
printf("Address [$%04x]: ",(unsigned int)A);
|
||||
A=GetH16(A);
|
||||
printf("Value [%03d]: ",(unsigned int)V);
|
||||
printf("Value [%03u]: ",(unsigned int)V);
|
||||
V=Get8(V);
|
||||
printf("Add cheat \"%s\" for address $%04x with value %03d?",name,(unsigned int)A,(unsigned int)V);
|
||||
printf("Add cheat \"%s\" for address $%04x with value %03u?",name,(unsigned int)A,(unsigned int)V);
|
||||
if(GetYN(0))
|
||||
{
|
||||
if(FCEUI_AddCheat(name,A,V,-1,0))
|
||||
@@ -326,9 +326,9 @@ static int clistcallb(char *name, uint32 a, uint8 v, int compare, int s, int typ
|
||||
int ret;
|
||||
|
||||
if(compare>=0)
|
||||
sprintf(tmp,"%s $%04x:%03d:%03d - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,compare,name);
|
||||
sprintf(tmp,"%s $%04x:%03u:%03d - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,compare,name);
|
||||
else
|
||||
sprintf(tmp,"%s $%04x:%03d - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,name);
|
||||
sprintf(tmp,"%s $%04x:%03u - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,name);
|
||||
if(type==1)
|
||||
tmp[2]='S';
|
||||
ret=AddToList(tmp,lid);
|
||||
@@ -373,7 +373,7 @@ static void ResetSearch(void)
|
||||
static int srescallb(uint32 a, uint8 last, uint8 current, void *data)
|
||||
{
|
||||
char tmp[14];
|
||||
sprintf(tmp, "$%04x:%03d:%03d",(unsigned int)a,(unsigned int)last,(unsigned int)current);
|
||||
sprintf(tmp, "$%04x:%03u:%03u",(unsigned int)a,(unsigned int)last,(unsigned int)current);
|
||||
return(AddToList(tmp,a));
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ static void ShowRes(void)
|
||||
}
|
||||
}
|
||||
|
||||
static int ShowShortList(char *moe[], int n, int def)
|
||||
static int ShowShortList(const char *moe[], int n, int def)
|
||||
{
|
||||
int x,c;
|
||||
int baa; //mbg merge 7/17/06 made to normal int
|
||||
@@ -430,7 +430,7 @@ static void DoSearch(void)
|
||||
{
|
||||
static int v1=0,v2=0;
|
||||
static int method=0;
|
||||
char *m[9]={"O==V1 && C==V2",
|
||||
const char *m[9]={"O==V1 && C==V2",
|
||||
"O==V1 && |O-C|==V2",
|
||||
"|O-C|==V2",
|
||||
"O!=C",
|
||||
|
||||
@@ -17,5 +17,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef COMMON_CHEAT_H
|
||||
#define COMMON_CHEAT_H
|
||||
void DoConsoleCheatConfig(void);
|
||||
#endif
|
||||
@@ -125,7 +125,7 @@ static void cfg_Save(FILE *fp)
|
||||
{
|
||||
if(it->first.size()>30 || it->second.size()>30)
|
||||
{
|
||||
int zzz=9;
|
||||
//int zzz=9;
|
||||
}
|
||||
fprintf(fp,"%s %s\n",it->first.c_str(),it->second.c_str());
|
||||
}
|
||||
|
||||
@@ -23,16 +23,21 @@ void LoadFCEUConfig(const char *filename, CFGSTRUCT *cfgst);
|
||||
// isn't really hurting much.
|
||||
|
||||
// Single piece of data(integer).
|
||||
#define AC(x) { #x,&x,sizeof(x)}
|
||||
#define NAC(w,x) { #w,&x,sizeof(x)}
|
||||
#define AC(x) {#x,&x,sizeof(x)}
|
||||
#define NAC(w,x) {#w,&x,sizeof(x)}
|
||||
// VAC intruduced for backward compatibility with
|
||||
// configuration files of previous versions
|
||||
#define VAC(x,version) {#x "_V" #version,&x,sizeof(x)}
|
||||
|
||||
// Array.
|
||||
#define ACA(x) {#x,x,sizeof(x)}
|
||||
#define NACA(w,x) {#w,x,sizeof(x)}
|
||||
#define VACA(x,version) {#x "_V" #version,x,sizeof(x)}
|
||||
|
||||
// String(pointer) with automatic memory allocation.
|
||||
#define ACS(x) {#x,&x,0}
|
||||
#define NACS(w,x) {#w,&x,0}
|
||||
#define VACS(x,version) {#x "_V" #version,&x,0}
|
||||
|
||||
#define _DRIVERS_CONFIGH
|
||||
#endif
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#include "../../types.h"
|
||||
#include "configSys.h"
|
||||
@@ -444,6 +447,23 @@ Config::getOption(const std::string &name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Config::getOption(const std::string &name,
|
||||
bool *value) const
|
||||
{
|
||||
std::map<std::string, int>::const_iterator opt_i;
|
||||
|
||||
// confirm that the option exists
|
||||
opt_i = _intOptMap.find(name);
|
||||
if(opt_i == _intOptMap.end()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get the option
|
||||
(*value) = opt_i->second ? true : false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Config::getOption(const std::string &name,
|
||||
double *value) const
|
||||
@@ -559,6 +579,7 @@ Config::parse(int argc,
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
// try to read cfg.d/*
|
||||
std::string cfgd_dir_name = _dir + "/" + "cfg.d/";
|
||||
DIR *d;
|
||||
@@ -576,7 +597,7 @@ Config::parse(int argc,
|
||||
|
||||
// TODO 0 = good -1 = bad
|
||||
std::string fname = cfgd_dir_name + dir->d_name;
|
||||
printf("Loading auxilary configuration file at %s...\n", fname.c_str());
|
||||
printf("Loading auxiliary configuration file at %s...\n", fname.c_str());
|
||||
if (_loadFile(fname.c_str()) != 0)
|
||||
{
|
||||
printf("Failed to parse configuration at %s\n", fname.c_str());
|
||||
@@ -585,7 +606,9 @@ Config::parse(int argc,
|
||||
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
#else
|
||||
// FIXME TODO WIN32
|
||||
#endif
|
||||
// parse the arguments
|
||||
return _parseArgs(argc, argv);
|
||||
}
|
||||
@@ -681,7 +704,7 @@ Config::_loadFile(const char* fname)
|
||||
|
||||
// close the file
|
||||
config.close();
|
||||
} catch(std::fstream::failure e) {
|
||||
} catch(std::fstream::failure &e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -737,7 +760,7 @@ Config::save()
|
||||
|
||||
// close the file
|
||||
config.close();
|
||||
} catch(std::fstream::failure e)
|
||||
} catch(std::fstream::failure &e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
return -1;
|
||||
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
int getOption(const std::string &, std::string *) const;
|
||||
int getOption(const std::string &, const char **) const;
|
||||
int getOption(const std::string &, int *) const;
|
||||
int getOption(const std::string &, bool *) const;
|
||||
int getOption(const std::string &, double *) const;
|
||||
|
||||
/**
|
||||
|
||||
@@ -242,15 +242,16 @@ void nes_ntsc_init( nes_ntsc_t* ntsc, nes_ntsc_setup_t const* setup, int bpp )
|
||||
|
||||
#ifndef NES_NTSC_NO_BLITTERS
|
||||
|
||||
void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, long in_row_width,
|
||||
int burst_phase, int emphasis, int in_width, int in_height, void* rgb_out, long out_pitch )
|
||||
void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, NES_NTSC_IN_T const* inputD, long in_row_width,
|
||||
int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch )
|
||||
{
|
||||
int chunk_count = (in_width - 1) / nes_ntsc_in_chunk;
|
||||
|
||||
for ( ; in_height; --in_height )
|
||||
{
|
||||
NES_NTSC_IN_T const* line_in = input;
|
||||
NES_NTSC_BEGIN_ROW( ntsc, burst_phase, nes_ntsc_black, nes_ntsc_black, NES_NTSC_ADJ_IN( *line_in ) );
|
||||
NES_NTSC_IN_T const* line_inD = inputD;
|
||||
NES_NTSC_BEGIN_ROW( ntsc, burst_phase, nes_ntsc_black, nes_ntsc_black, NES_NTSC_ADJ_IN( *line_in, *line_inD ) );
|
||||
nes_ntsc_out_t* restrict line_out = (nes_ntsc_out_t*) rgb_out;
|
||||
int n;
|
||||
++line_in;
|
||||
@@ -259,20 +260,21 @@ void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, long in_
|
||||
{
|
||||
|
||||
/* order of input and output pixels must not be altered */
|
||||
NES_NTSC_COLOR_IN( 0, NES_NTSC_ADJ_IN( line_in [0] ) );
|
||||
NES_NTSC_COLOR_IN( 0, NES_NTSC_ADJ_IN( line_in [0], line_inD [0] ) );
|
||||
NES_NTSC_RGB_OUT( 0, line_out [0], OutputDepth );
|
||||
NES_NTSC_RGB_OUT( 1, line_out [1], OutputDepth );
|
||||
|
||||
NES_NTSC_COLOR_IN( 1, NES_NTSC_ADJ_IN( line_in [1] ) );
|
||||
NES_NTSC_COLOR_IN( 1, NES_NTSC_ADJ_IN( line_in [1], line_inD [1] ) );
|
||||
NES_NTSC_RGB_OUT( 2, line_out [2], OutputDepth );
|
||||
NES_NTSC_RGB_OUT( 3, line_out [3], OutputDepth );
|
||||
|
||||
NES_NTSC_COLOR_IN( 2, NES_NTSC_ADJ_IN( line_in [2] ) );
|
||||
NES_NTSC_COLOR_IN( 2, NES_NTSC_ADJ_IN( line_in [2], line_inD [2] ) );
|
||||
NES_NTSC_RGB_OUT( 4, line_out [4], OutputDepth );
|
||||
NES_NTSC_RGB_OUT( 5, line_out [5], OutputDepth );
|
||||
NES_NTSC_RGB_OUT( 6, line_out [6], OutputDepth );
|
||||
|
||||
line_in += 3;
|
||||
line_inD += 3;
|
||||
line_out += rescale_out;
|
||||
}
|
||||
|
||||
@@ -293,6 +295,7 @@ void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, long in_
|
||||
|
||||
burst_phase = (burst_phase + 1) % nes_ntsc_burst_count;
|
||||
input += in_row_width;
|
||||
inputD += in_row_width;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,8 +61,8 @@ In_row_width is the number of pixels to get to the next input row. Emphasis is
|
||||
the emphasis bits to bitwise-OR with all pixels in the input data. Out_pitch
|
||||
is the number of *bytes* to get to the next output row. Output pixel format
|
||||
is set by NES_NTSC_OUT_DEPTH (defaults to 16-bit RGB). */
|
||||
void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* nes_in,
|
||||
long in_row_width, int burst_phase, int emphasis, int in_width,
|
||||
void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* nes_in, NES_NTSC_IN_T const* nes_inD,
|
||||
long in_row_width, int burst_phase, int in_width,
|
||||
int in_height, void* rgb_out, long out_pitch );
|
||||
|
||||
/* Number of output pixels written by blitter for given input width. Width might
|
||||
|
||||
@@ -21,7 +21,7 @@ if you enable emphasis above. */
|
||||
// CUSTOM: (XBuf uses bit 0x80, and has palettes above 0x3f for LUA)
|
||||
/* Each raw pixel input value is passed through this. You might want to mask
|
||||
the pixel index if you use the high bits as flags, etc. */
|
||||
#define NES_NTSC_ADJ_IN( in ) ((in & 0x3f) | emphasis)
|
||||
#define NES_NTSC_ADJ_IN( in, inD ) ((in & 0x3F) | (inD << 6))
|
||||
|
||||
/* For each pixel, this is the basic operation:
|
||||
output_color = color_palette [NES_NTSC_ADJ_IN( NES_NTSC_IN_T )] */
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
// os_util.cpp
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include "common/os_utils.h"
|
||||
//************************************************************
|
||||
int fceu_mkdir( const char *path )
|
||||
{
|
||||
int retval;
|
||||
#if defined(WIN32)
|
||||
retval = _mkdir(path);
|
||||
_chmod(path, 755);
|
||||
#else
|
||||
retval = mkdir(path, S_IRWXU);
|
||||
|
||||
if ( retval != 0 )
|
||||
{
|
||||
if ( errno == EEXIST )
|
||||
{
|
||||
//printf("Path Exists: '%s'\n", path);
|
||||
retval = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
//************************************************************
|
||||
int fceu_mkpath( const char *path )
|
||||
{
|
||||
int i, retval = 0;
|
||||
char p[512];
|
||||
|
||||
i=0;
|
||||
while ( path[i] != 0 )
|
||||
{
|
||||
if ( path[i] == '/' )
|
||||
{
|
||||
if ( i > 0 )
|
||||
{
|
||||
p[i] = 0;
|
||||
|
||||
retval = fceu_mkdir( p );
|
||||
|
||||
if ( retval )
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
p[i] = path[i]; i++;
|
||||
}
|
||||
p[i] = 0;
|
||||
|
||||
retval = fceu_mkdir( p );
|
||||
|
||||
return retval;
|
||||
}
|
||||
//************************************************************
|
||||
bool fceu_file_exists( const char *filepath )
|
||||
{
|
||||
#ifdef WIN32
|
||||
FILE *fp;
|
||||
fp = ::fopen( filepath, "r" );
|
||||
|
||||
if ( fp != NULL )
|
||||
{
|
||||
::fclose(fp);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
struct stat sb;
|
||||
|
||||
if ( stat( filepath, &sb ) == 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
//************************************************************
|
||||
int msleep( int ms )
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef WIN32
|
||||
Sleep(ms);
|
||||
#else
|
||||
ret = usleep(ms*1000);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
//************************************************************
|
||||
@@ -0,0 +1,10 @@
|
||||
// os_utils.h
|
||||
//
|
||||
|
||||
int fceu_mkdir( const char *path );
|
||||
|
||||
int fceu_mkpath( const char *path );
|
||||
|
||||
bool fceu_file_exists( const char *filepath );
|
||||
|
||||
int msleep( int ms );
|
||||
@@ -65,9 +65,9 @@ static float *moire = NULL; // modulated signal
|
||||
const float phasex = (float) 5/18*2;
|
||||
const float phasey = (float) 1/ 6*2;
|
||||
const float pi = 3.14f;
|
||||
int palnotch = 90;
|
||||
int palnotch = 100;
|
||||
int palsaturation = 100;
|
||||
int palsharpness = 50;
|
||||
int palsharpness = 0;
|
||||
int palcontrast = 100;
|
||||
int palbrightness = 50;
|
||||
bool palupdate = 1;
|
||||
@@ -88,13 +88,13 @@ static int PAL_LUT(uint32 *buffer, int index, int x, int y)
|
||||
|
||||
static void CalculateShift(uint32 *CBM, int *cshiftr, int *cshiftl)
|
||||
{
|
||||
int a,x,z,y;
|
||||
int a,x,z;
|
||||
cshiftl[0]=cshiftl[1]=cshiftl[2]=-1;
|
||||
for(a=0;a<3;a++)
|
||||
{
|
||||
for(x=0,y=-1,z=0;x<32;x++)
|
||||
for(x=0,z=0;x<32;x++)
|
||||
{
|
||||
if(CBM[a]&(1<<x))
|
||||
if(CBM[a]&(1u<<x))
|
||||
{
|
||||
if(cshiftl[a]==-1) cshiftl[a]=x;
|
||||
z++;
|
||||
@@ -107,8 +107,6 @@ static void CalculateShift(uint32 *CBM, int *cshiftr, int *cshiftl)
|
||||
|
||||
int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int specfilt, int specfilteropt)
|
||||
{
|
||||
//paldeemphswap = 0; // determine this in FCEUPPU_SetVideoSystem() instead
|
||||
|
||||
// -Video Modes Tag-
|
||||
if(specfilt == 3) // NTSC 2x
|
||||
{
|
||||
@@ -208,6 +206,7 @@ int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int
|
||||
palrgb = (uint32 *)FCEU_dmalloc((256+512)*PAL_PHASES*sizeof(uint32));
|
||||
palrgb2 = (uint32 *)FCEU_dmalloc((256+512)*PAL_PHASES*sizeof(uint32));
|
||||
moire = (float *)FCEU_dmalloc( PAL_PHASES*sizeof(float));
|
||||
palupdate = 1;
|
||||
}
|
||||
|
||||
silt = specfilt;
|
||||
@@ -218,6 +217,11 @@ int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int
|
||||
return(0);
|
||||
|
||||
//allocate adequate room for 32bpp palette
|
||||
if ( palettetranslate )
|
||||
{
|
||||
free(palettetranslate);
|
||||
palettetranslate=NULL;
|
||||
}
|
||||
palettetranslate=(uint32*)FCEU_dmalloc(256*4 + 512*4);
|
||||
|
||||
if(!palettetranslate)
|
||||
@@ -255,6 +259,7 @@ void KillBlitToHigh(void)
|
||||
hq3x_Kill();
|
||||
else
|
||||
hq2x_Kill();
|
||||
free(specbuf);
|
||||
specbuf=NULL;
|
||||
}
|
||||
if (nes_ntsc) {
|
||||
@@ -461,7 +466,7 @@ void Blit8To8(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, in
|
||||
/* Todo: Make sure 24bpp code works right with big-endian cpus */
|
||||
|
||||
//takes a pointer to XBuf and applies fully modern deemph palettizing
|
||||
u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int xscale, int yscale)
|
||||
template<int SCALE> static u32 _ModernDeemphColorMap(u8* src, u8* srcbuf)
|
||||
{
|
||||
u8 pixel = *src;
|
||||
|
||||
@@ -471,8 +476,8 @@ u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int xscale, int yscale)
|
||||
int ofs = src-srcbuf;
|
||||
int xofs = ofs&255;
|
||||
int yofs = ofs>>8;
|
||||
if(xscale!=1) xofs /= xscale; //untested optimization
|
||||
if(yscale!=1) yofs /= yscale; //untested optimization
|
||||
xofs /= SCALE;
|
||||
yofs /= SCALE;
|
||||
ofs = xofs+yofs*256;
|
||||
|
||||
//find out which deemph bitplane value we're on
|
||||
@@ -480,11 +485,47 @@ u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int xscale, int yscale)
|
||||
|
||||
//if it was a deemph'd value, grab it from the deemph palette
|
||||
if(deemph != 0)
|
||||
color = palettetranslate[256+(pixel&0x3F)+deemph*64];
|
||||
{
|
||||
color = palettetranslate[256+(pixel&0x3F)+(deemph*64)];
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int scale)
|
||||
{
|
||||
if(scale == 1) return _ModernDeemphColorMap<1>(src,srcbuf);
|
||||
else if(scale == 2) return _ModernDeemphColorMap<2>(src,srcbuf);
|
||||
else if(scale == 3) return _ModernDeemphColorMap<3>(src,srcbuf);
|
||||
else if(scale == 4) return _ModernDeemphColorMap<4>(src,srcbuf);
|
||||
else if(scale == 5) return _ModernDeemphColorMap<5>(src,srcbuf);
|
||||
else if(scale == 6) return _ModernDeemphColorMap<6>(src,srcbuf);
|
||||
else if(scale == 7) return _ModernDeemphColorMap<7>(src,srcbuf);
|
||||
else if(scale == 8) return _ModernDeemphColorMap<8>(src,srcbuf);
|
||||
else if(scale == 9) return _ModernDeemphColorMap<9>(src,srcbuf);
|
||||
else { abort(); return 0; }
|
||||
}
|
||||
|
||||
typedef u32 (*ModernDeemphColorMapFuncPtr)( u8*, u8* );
|
||||
|
||||
static ModernDeemphColorMapFuncPtr getModernDeemphColorMapFunc(int scale)
|
||||
{
|
||||
ModernDeemphColorMapFuncPtr ptr = NULL;
|
||||
|
||||
if(scale == 1) ptr = &_ModernDeemphColorMap<1>;
|
||||
else if(scale == 2) ptr = &_ModernDeemphColorMap<2>;
|
||||
else if(scale == 3) ptr = &_ModernDeemphColorMap<3>;
|
||||
else if(scale == 4) ptr = &_ModernDeemphColorMap<4>;
|
||||
else if(scale == 5) ptr = &_ModernDeemphColorMap<5>;
|
||||
else if(scale == 6) ptr = &_ModernDeemphColorMap<6>;
|
||||
else if(scale == 7) ptr = &_ModernDeemphColorMap<7>;
|
||||
else if(scale == 8) ptr = &_ModernDeemphColorMap<8>;
|
||||
else if(scale == 9) ptr = &_ModernDeemphColorMap<9>;
|
||||
else { abort(); ptr = NULL; }
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale)
|
||||
{
|
||||
int x,y;
|
||||
@@ -500,6 +541,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
int mult;
|
||||
int base;
|
||||
ModernDeemphColorMapFuncPtr ModernDeemphColorMapFunc = NULL;
|
||||
|
||||
// -Video Modes Tag-
|
||||
if(silt == 2) mult = 2;
|
||||
@@ -508,7 +550,12 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
Blit8To8(src, specbuf8bpp, xr, yr, 256*mult, xscale, yscale, 0, silt);
|
||||
int mdcmxs = xscale*mult;
|
||||
int mdcmys = yscale*mult;
|
||||
|
||||
if(mdcmxs != mdcmys)
|
||||
abort();
|
||||
|
||||
ModernDeemphColorMapFunc = getModernDeemphColorMapFunc( mdcmxs );
|
||||
|
||||
xr *= mult;
|
||||
yr *= mult;
|
||||
xscale=yscale=1;
|
||||
@@ -523,7 +570,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
*(uint32 *)dest=ModernDeemphColorMap(src,specbuf8bpp,mdcmxs, mdcmys);
|
||||
*(uint32 *)dest=ModernDeemphColorMapFunc(src,specbuf8bpp);
|
||||
dest+=4;
|
||||
src++;
|
||||
}
|
||||
@@ -536,7 +583,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp=ModernDeemphColorMap(src,specbuf8bpp,mdcmxs, mdcmys);
|
||||
uint32 tmp=ModernDeemphColorMapFunc(src,specbuf8bpp);
|
||||
*(uint8 *)dest=tmp;
|
||||
*((uint8 *)dest+1)=tmp>>8;
|
||||
*((uint8 *)dest+2)=tmp>>16;
|
||||
@@ -576,7 +623,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
for(x=xr; x; x--)
|
||||
{
|
||||
*(uint32 *)dest = ModernDeemphColorMap(src,XBuf,1,1);
|
||||
*(uint32 *)dest = _ModernDeemphColorMap<1>(src,XBuf);
|
||||
dest += 4;
|
||||
src++;
|
||||
}
|
||||
@@ -587,9 +634,11 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
uint32 *s = prescalebuf;
|
||||
uint32 *d = (uint32 *)destbackup; // use 32-bit pointers ftw
|
||||
int subpixel;
|
||||
int subpixel,yend;
|
||||
|
||||
for (y=0; y<yr*yscale; y++)
|
||||
yend = yr*yscale;
|
||||
|
||||
for (y=0; y<yend; y++)
|
||||
{
|
||||
int back = xr*(y%yscale>0); // bool as multiplier
|
||||
for (x=0; x<xr; x++)
|
||||
@@ -715,7 +764,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
newindex = (*src&63) | (deemph*64);
|
||||
newindex += 256;
|
||||
|
||||
if(GameInfo->type==GIT_NSF)
|
||||
if(GameInfo && GameInfo->type==GIT_NSF)
|
||||
{
|
||||
*d++ = palettetranslate[temp];
|
||||
*d++ = palettetranslate[temp];
|
||||
@@ -785,6 +834,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
lastindex = index;
|
||||
}
|
||||
}
|
||||
src += (256-xr);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -807,11 +857,13 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
switch(Bpp)
|
||||
{
|
||||
case 4:
|
||||
if ( nes_ntsc && GameInfo->type!=GIT_NSF) {
|
||||
if ( nes_ntsc && GameInfo && GameInfo->type!=GIT_NSF) {
|
||||
int outxr = 301;
|
||||
//if(xr == 282) outxr = 282; //hack for windows
|
||||
burst_phase ^= 1;
|
||||
nes_ntsc_blit( nes_ntsc, (unsigned char*)src, xr, burst_phase, (PPU[1] >> 5) << 6, xr, yr, ntscblit, (2*outxr) * Bpp );
|
||||
|
||||
u8* srcD = XDBuf + (src-XBuf); // get deemphasis buffer
|
||||
nes_ntsc_blit( nes_ntsc, (unsigned char*)src, (unsigned char*)srcD, xr, burst_phase, xr, yr, ntscblit, (2*outxr) * Bpp );
|
||||
|
||||
const uint8 *in = ntscblit + (Bpp * xscale);
|
||||
uint8 *out = dest;
|
||||
@@ -912,7 +964,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
//THE MAIN BLITTING CODEPATH (there may be others that are important)
|
||||
*(uint32 *)dest = ModernDeemphColorMap(src,XBuf,1,1);
|
||||
*(uint32 *)dest = _ModernDeemphColorMap<1>(src,XBuf);
|
||||
dest+=4;
|
||||
src++;
|
||||
}
|
||||
@@ -925,7 +977,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp = ModernDeemphColorMap(src,XBuf,1,1);
|
||||
uint32 tmp = _ModernDeemphColorMap<1>(src,XBuf);
|
||||
*(uint8 *)dest=tmp;
|
||||
*((uint8 *)dest+1)=tmp>>8;
|
||||
*((uint8 *)dest+2)=tmp>>16;
|
||||
@@ -941,7 +993,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
*(uint16 *)dest = ModernDeemphColorMap(src,XBuf,1,1);
|
||||
*(uint16 *)dest = _ModernDeemphColorMap<1>(src,XBuf);
|
||||
dest+=2;
|
||||
src++;
|
||||
}
|
||||
|
||||
@@ -29,4 +29,4 @@ void Blit32to16(uint32 *src, uint16 *dest, int xr, int yr, int dpitch,
|
||||
int shiftr[3], int shiftl[3]);
|
||||
|
||||
|
||||
u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int xscale, int yscale);
|
||||
u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int scale);
|
||||
@@ -1,28 +0,0 @@
|
||||
# Fix compliation error about 'XKeysymToString' by linking X11 explicitly
|
||||
# Thanks Antonio Ospite!
|
||||
Import('env')
|
||||
config_string = 'pkg-config --cflags --libs x11'
|
||||
env.ParseConfig(config_string)
|
||||
Export('env')
|
||||
|
||||
source_list = Split(
|
||||
"""
|
||||
input.cpp
|
||||
config.cpp
|
||||
sdl.cpp
|
||||
sdl-joystick.cpp
|
||||
sdl-sound.cpp
|
||||
sdl-throttle.cpp
|
||||
sdl-video.cpp
|
||||
unix-netplay.cpp
|
||||
""")
|
||||
|
||||
Import('env')
|
||||
if 'GL' in env['LIBS']:
|
||||
source_list.append('sdl-opengl.cpp')
|
||||
|
||||
if env['GTK'] or env['GTK3']:
|
||||
source_list.append('gui.cpp')
|
||||
|
||||
source_list = ['drivers/sdl/' + source for source in source_list]
|
||||
Return('source_list')
|
||||
@@ -1,443 +0,0 @@
|
||||
#include "main.h"
|
||||
#include "throttle.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "../common/cheat.h"
|
||||
|
||||
#include "input.h"
|
||||
#include "dface.h"
|
||||
|
||||
#include "sdl.h"
|
||||
#include "sdl-video.h"
|
||||
#include "unix-netplay.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <csignal>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/**
|
||||
* Read a custom pallete from a file and load it into the core.
|
||||
*/
|
||||
int
|
||||
LoadCPalette(const std::string &file)
|
||||
{
|
||||
uint8 tmpp[192];
|
||||
FILE *fp;
|
||||
|
||||
if(!(fp = FCEUD_UTF8fopen(file.c_str(), "rb"))) {
|
||||
char errorMsg[256];
|
||||
strcpy(errorMsg, "Error loading custom palette from file: ");
|
||||
strcat(errorMsg, file.c_str());
|
||||
FCEUD_PrintError(errorMsg);
|
||||
return 0;
|
||||
}
|
||||
size_t result = fread(tmpp, 1, 192, fp);
|
||||
if(result != 192) {
|
||||
char errorMsg[256];
|
||||
strcpy(errorMsg, "Error loading custom palette from file: ");
|
||||
strcat(errorMsg, file.c_str());
|
||||
FCEUD_PrintError(errorMsg);
|
||||
return 0;
|
||||
}
|
||||
FCEUI_SetUserPalette(tmpp, result/3);
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the subdirectories used for saving snapshots, movies, game
|
||||
* saves, etc. Hopefully obsolete with new configuration system.
|
||||
*/
|
||||
static void
|
||||
CreateDirs(const std::string &dir)
|
||||
{
|
||||
char *subs[8]={"fcs","snaps","gameinfo","sav","cheats","movies","cfg.d"};
|
||||
std::string subdir;
|
||||
int x;
|
||||
|
||||
#if defined(WIN32) || defined(NEED_MINGW_HACKS)
|
||||
mkdir(dir.c_str());
|
||||
chmod(dir.c_str(), 755);
|
||||
for(x = 0; x < 6; x++) {
|
||||
subdir = dir + PSS + subs[x];
|
||||
mkdir(subdir.c_str());
|
||||
}
|
||||
#else
|
||||
mkdir(dir.c_str(), S_IRWXU);
|
||||
for(x = 0; x < 6; x++) {
|
||||
subdir = dir + PSS + subs[x];
|
||||
mkdir(subdir.c_str(), S_IRWXU);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to locate FCEU's application directory. This will
|
||||
* hopefully become obsolete once the new configuration system is in
|
||||
* place.
|
||||
*/
|
||||
static void
|
||||
GetBaseDirectory(std::string &dir)
|
||||
{
|
||||
char *home = getenv("HOME");
|
||||
if(home) {
|
||||
dir = std::string(home) + "/.fceux";
|
||||
} else {
|
||||
#ifdef WIN32
|
||||
home = new char[MAX_PATH + 1];
|
||||
GetModuleFileName(NULL, home, MAX_PATH + 1);
|
||||
|
||||
char *lastBS = strrchr(home,'\\');
|
||||
if(lastBS) {
|
||||
*lastBS = 0;
|
||||
}
|
||||
|
||||
dir = std::string(home);
|
||||
delete[] home;
|
||||
#else
|
||||
dir = "";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// returns a config structure with default options
|
||||
// also creates config base directory (ie: /home/user/.fceux as well as subdirs
|
||||
Config *
|
||||
InitConfig()
|
||||
{
|
||||
std::string dir, prefix;
|
||||
Config *config;
|
||||
|
||||
GetBaseDirectory(dir);
|
||||
|
||||
FCEUI_SetBaseDirectory(dir.c_str());
|
||||
CreateDirs(dir);
|
||||
|
||||
config = new Config(dir);
|
||||
|
||||
// sound options
|
||||
config->addOption('s', "sound", "SDL.Sound", 1);
|
||||
config->addOption("volume", "SDL.Sound.Volume", 150);
|
||||
config->addOption("trianglevol", "SDL.Sound.TriangleVolume", 256);
|
||||
config->addOption("square1vol", "SDL.Sound.Square1Volume", 256);
|
||||
config->addOption("square2vol", "SDL.Sound.Square2Volume", 256);
|
||||
config->addOption("noisevol", "SDL.Sound.NoiseVolume", 256);
|
||||
config->addOption("pcmvol", "SDL.Sound.PCMVolume", 256);
|
||||
config->addOption("soundrate", "SDL.Sound.Rate", 44100);
|
||||
config->addOption("soundq", "SDL.Sound.Quality", 1);
|
||||
config->addOption("soundrecord", "SDL.Sound.RecordFile", "");
|
||||
config->addOption("soundbufsize", "SDL.Sound.BufSize", 128);
|
||||
config->addOption("lowpass", "SDL.Sound.LowPass", 0);
|
||||
|
||||
config->addOption('g', "gamegenie", "SDL.GameGenie", 0);
|
||||
config->addOption("pal", "SDL.PAL", 0);
|
||||
config->addOption("frameskip", "SDL.Frameskip", 0);
|
||||
config->addOption("clipsides", "SDL.ClipSides", 0);
|
||||
config->addOption("nospritelim", "SDL.DisableSpriteLimit", 1);
|
||||
config->addOption("swapduty", "SDL.SwapDuty", 0);
|
||||
|
||||
// color control
|
||||
config->addOption('p', "palette", "SDL.Palette", "");
|
||||
config->addOption("tint", "SDL.Tint", 56);
|
||||
config->addOption("hue", "SDL.Hue", 72);
|
||||
config->addOption("ntsccolor", "SDL.NTSCpalette", 0);
|
||||
|
||||
// scanline settings
|
||||
config->addOption("slstart", "SDL.ScanLineStart", 0);
|
||||
config->addOption("slend", "SDL.ScanLineEnd", 239);
|
||||
|
||||
// video controls
|
||||
config->addOption('f', "fullscreen", "SDL.Fullscreen", 0);
|
||||
|
||||
// set x/y res to 0 for automatic fullscreen resolution detection (no change)
|
||||
config->addOption('x', "xres", "SDL.XResolution", 0);
|
||||
config->addOption('y', "yres", "SDL.YResolution", 0);
|
||||
config->addOption("SDL.LastXRes", 0);
|
||||
config->addOption("SDL.LastYRes", 0);
|
||||
config->addOption('b', "bpp", "SDL.BitsPerPixel", 32);
|
||||
config->addOption("doublebuf", "SDL.DoubleBuffering", 0);
|
||||
config->addOption("autoscale", "SDL.AutoScale", 1);
|
||||
config->addOption("keepratio", "SDL.KeepRatio", 1);
|
||||
config->addOption("xscale", "SDL.XScale", 1.0);
|
||||
config->addOption("yscale", "SDL.YScale", 1.0);
|
||||
config->addOption("xstretch", "SDL.XStretch", 0);
|
||||
config->addOption("ystretch", "SDL.YStretch", 0);
|
||||
config->addOption("noframe", "SDL.NoFrame", 0);
|
||||
config->addOption("special", "SDL.SpecialFilter", 0);
|
||||
config->addOption("showfps", "SDL.ShowFPS", 0);
|
||||
config->addOption("togglemenu", "SDL.ToggleMenu", 0);
|
||||
|
||||
// OpenGL options
|
||||
config->addOption("opengl", "SDL.OpenGL", 0);
|
||||
config->addOption("openglip", "SDL.OpenGLip", 0);
|
||||
config->addOption("SDL.SpecialFilter", 0);
|
||||
config->addOption("SDL.SpecialFX", 0);
|
||||
config->addOption("SDL.Vsync", 1);
|
||||
|
||||
// network play options - netplay is broken
|
||||
config->addOption("server", "SDL.NetworkIsServer", 0);
|
||||
config->addOption('n', "net", "SDL.NetworkIP", "");
|
||||
config->addOption('u', "user", "SDL.NetworkUsername", "");
|
||||
config->addOption('w', "pass", "SDL.NetworkPassword", "");
|
||||
config->addOption('k', "netkey", "SDL.NetworkGameKey", "");
|
||||
config->addOption("port", "SDL.NetworkPort", 4046);
|
||||
config->addOption("players", "SDL.NetworkPlayers", 1);
|
||||
|
||||
// input configuration options
|
||||
config->addOption("input1", "SDL.Input.0", "GamePad.0");
|
||||
config->addOption("input2", "SDL.Input.1", "GamePad.1");
|
||||
config->addOption("input3", "SDL.Input.2", "Gamepad.2");
|
||||
config->addOption("input4", "SDL.Input.3", "Gamepad.3");
|
||||
|
||||
// allow for input configuration
|
||||
config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg);
|
||||
|
||||
// display input
|
||||
config->addOption("inputdisplay", "SDL.InputDisplay", 0);
|
||||
|
||||
// enable / disable opposite directionals (left + right or up + down simultaneously)
|
||||
config->addOption("opposite-directionals", "SDL.Input.EnableOppositeDirectionals", 1);
|
||||
|
||||
// pause movie playback at frame x
|
||||
config->addOption("pauseframe", "SDL.PauseFrame", 0);
|
||||
config->addOption("recordhud", "SDL.RecordHUD", 1);
|
||||
config->addOption("moviemsg", "SDL.MovieMsg", 1);
|
||||
|
||||
// overwrite the config file?
|
||||
config->addOption("no-config", "SDL.NoConfig", 0);
|
||||
|
||||
config->addOption("autoresume", "SDL.AutoResume", 0);
|
||||
|
||||
// video playback
|
||||
config->addOption("playmov", "SDL.Movie", "");
|
||||
config->addOption("subtitles", "SDL.SubtitleDisplay", 1);
|
||||
|
||||
config->addOption("fourscore", "SDL.FourScore", 0);
|
||||
|
||||
config->addOption("nofscursor", "SDL.NoFullscreenCursor", 1);
|
||||
|
||||
#ifdef _S9XLUA_H
|
||||
// load lua script
|
||||
config->addOption("loadlua", "SDL.LuaScript", "");
|
||||
#endif
|
||||
|
||||
#ifdef CREATE_AVI
|
||||
config->addOption("videolog", "SDL.VideoLog", "");
|
||||
config->addOption("mute", "SDL.MuteCapture", 0);
|
||||
#endif
|
||||
|
||||
// auto load/save on gameload/close
|
||||
config->addOption("loadstate", "SDL.AutoLoadState", INVALID_STATE);
|
||||
config->addOption("savestate", "SDL.AutoSaveState", INVALID_STATE);
|
||||
|
||||
//TODO implement this
|
||||
config->addOption("periodicsaves", "SDL.PeriodicSaves", 0);
|
||||
|
||||
|
||||
#ifdef _GTK
|
||||
char* home_dir = getenv("HOME");
|
||||
// prefixed with _ because they are internal (not cli options)
|
||||
config->addOption("_lastopenfile", "SDL.LastOpenFile", home_dir);
|
||||
config->addOption("_laststatefrom", "SDL.LastLoadStateFrom", home_dir);
|
||||
config->addOption("_lastopennsf", "SDL.LastOpenNSF", home_dir);
|
||||
config->addOption("_lastsavestateas", "SDL.LastSaveStateAs", home_dir);
|
||||
config->addOption("_lastloadlua", "SDL.LastLoadLua", "");
|
||||
#endif
|
||||
|
||||
// fcm -> fm2 conversion
|
||||
config->addOption("fcmconvert", "SDL.FCMConvert", "");
|
||||
|
||||
// fm2 -> srt conversion
|
||||
config->addOption("ripsubs", "SDL.RipSubs", "");
|
||||
|
||||
// enable new PPU core
|
||||
config->addOption("newppu", "SDL.NewPPU", 0);
|
||||
|
||||
// quit when a+b+select+start is pressed
|
||||
config->addOption("4buttonexit", "SDL.ABStartSelectExit", 0);
|
||||
|
||||
// GamePad 0 - 3
|
||||
for(unsigned int i = 0; i < GAMEPAD_NUM_DEVICES; i++) {
|
||||
char buf[64];
|
||||
snprintf(buf, 20, "SDL.Input.GamePad.%d.", i);
|
||||
prefix = buf;
|
||||
|
||||
config->addOption(prefix + "DeviceType", DefaultGamePadDevice[i]);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < GAMEPAD_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + GamePadNames[j], DefaultGamePad[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
// PowerPad 0 - 1
|
||||
for(unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) {
|
||||
char buf[64];
|
||||
snprintf(buf, 20, "SDL.Input.PowerPad.%d.", i);
|
||||
prefix = buf;
|
||||
|
||||
config->addOption(prefix + "DeviceType", DefaultPowerPadDevice[i]);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < POWERPAD_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix +PowerPadNames[j], DefaultPowerPad[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
// QuizKing
|
||||
prefix = "SDL.Input.QuizKing.";
|
||||
config->addOption(prefix + "DeviceType", DefaultQuizKingDevice);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < QUIZKING_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + QuizKingNames[j], DefaultQuizKing[j]);
|
||||
}
|
||||
|
||||
// HyperShot
|
||||
prefix = "SDL.Input.HyperShot.";
|
||||
config->addOption(prefix + "DeviceType", DefaultHyperShotDevice);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < HYPERSHOT_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + HyperShotNames[j], DefaultHyperShot[j]);
|
||||
}
|
||||
|
||||
// Mahjong
|
||||
prefix = "SDL.Input.Mahjong.";
|
||||
config->addOption(prefix + "DeviceType", DefaultMahjongDevice);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < MAHJONG_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + MahjongNames[j], DefaultMahjong[j]);
|
||||
}
|
||||
|
||||
// TopRider
|
||||
prefix = "SDL.Input.TopRider.";
|
||||
config->addOption(prefix + "DeviceType", DefaultTopRiderDevice);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < TOPRIDER_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + TopRiderNames[j], DefaultTopRider[j]);
|
||||
}
|
||||
|
||||
// FTrainer
|
||||
prefix = "SDL.Input.FTrainer.";
|
||||
config->addOption(prefix + "DeviceType", DefaultFTrainerDevice);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < FTRAINER_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + FTrainerNames[j], DefaultFTrainer[j]);
|
||||
}
|
||||
|
||||
// FamilyKeyBoard
|
||||
prefix = "SDL.Input.FamilyKeyBoard.";
|
||||
config->addOption(prefix + "DeviceType", DefaultFamilyKeyBoardDevice);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < FAMILYKEYBOARD_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + FamilyKeyBoardNames[j],
|
||||
DefaultFamilyKeyBoard[j]);
|
||||
}
|
||||
|
||||
// for FAMICOM microphone in pad 2 pad 1 didn't have it
|
||||
// Takeshi no Chousenjou uses it for example.
|
||||
prefix = "SDL.Input.FamicomPad2.";
|
||||
config->addOption("rp2mic", prefix + "EnableMic", 0);
|
||||
|
||||
// TODO: use a better data structure to store the hotkeys or something
|
||||
// improve this code overall in the future to make it
|
||||
// easier to maintain
|
||||
const int Hotkeys[HK_MAX] = {
|
||||
SDLK_F1, // cheat menu
|
||||
SDLK_F2, // bind state
|
||||
SDLK_F3, // load lua
|
||||
SDLK_F4, // toggleBG
|
||||
SDLK_F5, // save state
|
||||
SDLK_F6, // fds select
|
||||
SDLK_F7, // load state
|
||||
SDLK_F8, // fds eject
|
||||
SDLK_F6, // VS insert coin
|
||||
SDLK_F8, // VS toggle dipswitch
|
||||
SDLK_PERIOD, // toggle frame display
|
||||
SDLK_F10, // toggle subtitle
|
||||
SDLK_F11, // reset
|
||||
SDLK_F12, // screenshot
|
||||
SDLK_PAUSE, // pause
|
||||
SDLK_MINUS, // speed++
|
||||
SDLK_EQUALS, // speed--
|
||||
SDLK_BACKSLASH, //frame advnace
|
||||
SDLK_TAB, // turbo
|
||||
SDLK_COMMA, // toggle input display
|
||||
SDLK_q, // toggle movie RW
|
||||
SDLK_QUOTE, // toggle mute capture
|
||||
0, // quit // edit 10/11/11 - don't map to escape, it causes ugly things to happen to sdl. can be manually appended to config
|
||||
SDLK_DELETE, // frame advance lag skip
|
||||
SDLK_SLASH, // lag counter display
|
||||
SDLK_0, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5,
|
||||
SDLK_6, SDLK_7, SDLK_8, SDLK_9,
|
||||
SDLK_PAGEUP, // select state next
|
||||
SDLK_PAGEDOWN}; // select state prev
|
||||
|
||||
prefix = "SDL.Hotkeys.";
|
||||
for(int i=0; i < HK_MAX; i++)
|
||||
config->addOption(prefix + HotkeyStrings[i], Hotkeys[i]);
|
||||
// All mouse devices
|
||||
config->addOption("SDL.OekaKids.0.DeviceType", "Mouse");
|
||||
config->addOption("SDL.OekaKids.0.DeviceNum", 0);
|
||||
|
||||
config->addOption("SDL.Arkanoid.0.DeviceType", "Mouse");
|
||||
config->addOption("SDL.Arkanoid.0.DeviceNum", 0);
|
||||
|
||||
config->addOption("SDL.Shadow.0.DeviceType", "Mouse");
|
||||
config->addOption("SDL.Shadow.0.DeviceNum", 0);
|
||||
|
||||
config->addOption("SDL.Zapper.0.DeviceType", "Mouse");
|
||||
config->addOption("SDL.Zapper.0.DeviceNum", 0);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
void
|
||||
UpdateEMUCore(Config *config)
|
||||
{
|
||||
int ntsccol, ntsctint, ntschue, flag, region, start, end;
|
||||
std::string cpalette;
|
||||
|
||||
config->getOption("SDL.NTSCpalette", &ntsccol);
|
||||
config->getOption("SDL.Tint", &ntsctint);
|
||||
config->getOption("SDL.Hue", &ntschue);
|
||||
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
|
||||
|
||||
config->getOption("SDL.Palette", &cpalette);
|
||||
if(cpalette.size()) {
|
||||
LoadCPalette(cpalette);
|
||||
}
|
||||
|
||||
config->getOption("SDL.PAL", ®ion);
|
||||
FCEUI_SetRegion(region);
|
||||
|
||||
config->getOption("SDL.GameGenie", &flag);
|
||||
FCEUI_SetGameGenie(flag ? 1 : 0);
|
||||
|
||||
config->getOption("SDL.Sound.LowPass", &flag);
|
||||
FCEUI_SetLowPass(flag ? 1 : 0);
|
||||
|
||||
config->getOption("SDL.DisableSpriteLimit", &flag);
|
||||
FCEUI_DisableSpriteLimitation(flag ? 1 : 0);
|
||||
|
||||
config->getOption("SDL.ScanLineStart", &start);
|
||||
config->getOption("SDL.ScanLineEnd", &end);
|
||||
|
||||
#if DOING_SCANLINE_CHECKS
|
||||
for(int i = 0; i < 2; x++) {
|
||||
if(srendlinev[x]<0 || srendlinev[x]>239) srendlinev[x]=0;
|
||||
if(erendlinev[x]<srendlinev[x] || erendlinev[x]>239) erendlinev[x]=239;
|
||||
}
|
||||
#endif
|
||||
|
||||
FCEUI_SetRenderedLines(start + 8, end - 8, start, end);
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#ifndef CONFIG_H_HF128
|
||||
#define CONFIG_H_HF128
|
||||
|
||||
#include "../common/configSys.h"
|
||||
|
||||
Config *InitConfig(void);
|
||||
void UpdateEMUCore(Config *);
|
||||
int LoadCPalette(const std::string &file);
|
||||
|
||||
// hotkey definitions
|
||||
// TODO: encapsulate this in an improved data structure
|
||||
enum HOTKEY { HK_CHEAT_MENU=0, HK_BIND_STATE, HK_LOAD_LUA, HK_TOGGLE_BG,
|
||||
HK_SAVE_STATE, HK_FDS_SELECT, HK_LOAD_STATE, HK_FDS_EJECT ,
|
||||
HK_VS_INSERT_COIN, HK_VS_TOGGLE_DIPSWITCH,
|
||||
HK_TOGGLE_FRAME_DISPLAY, HK_TOGGLE_SUBTITLE, HK_RESET, HK_SCREENSHOT,
|
||||
HK_PAUSE, HK_DECREASE_SPEED, HK_INCREASE_SPEED, HK_FRAME_ADVANCE, HK_TURBO,
|
||||
HK_TOGGLE_INPUT_DISPLAY, HK_MOVIE_TOGGLE_RW, HK_MUTE_CAPTURE, HK_QUIT,
|
||||
HK_FA_LAG_SKIP, HK_LAG_COUNTER_DISPLAY,
|
||||
HK_SELECT_STATE_0, HK_SELECT_STATE_1, HK_SELECT_STATE_2, HK_SELECT_STATE_3,
|
||||
HK_SELECT_STATE_4, HK_SELECT_STATE_5, HK_SELECT_STATE_6, HK_SELECT_STATE_7,
|
||||
HK_SELECT_STATE_8, HK_SELECT_STATE_9,
|
||||
HK_SELECT_STATE_NEXT, HK_SELECT_STATE_PREV, HK_VOLUME_DOWN, HK_VOLUME_UP,
|
||||
HK_MAX};
|
||||
|
||||
|
||||
static const char* HotkeyStrings[HK_MAX] = {
|
||||
"CheatMenu",
|
||||
"BindState",
|
||||
"LoadLua",
|
||||
"ToggleBG",
|
||||
"SaveState",
|
||||
"FDSSelect",
|
||||
"LoadState",
|
||||
"FDSEject",
|
||||
"VSInsertCoin",
|
||||
"VSToggleDip",
|
||||
"MovieToggleFrameDisplay",
|
||||
"SubtitleDisplay",
|
||||
"Reset",
|
||||
"Screenshot",
|
||||
"Pause",
|
||||
"DecreaseSpeed",
|
||||
"IncreaseSpeed",
|
||||
"FrameAdvance",
|
||||
"Turbo",
|
||||
"ToggleInputDisplay",
|
||||
"ToggleMovieRW",
|
||||
"MuteCapture",
|
||||
"Quit",
|
||||
"FrameAdvanceLagSkip",
|
||||
"LagCounterDisplay",
|
||||
"SelectState0", "SelectState1", "SelectState2", "SelectState3",
|
||||
"SelectState4", "SelectState5", "SelectState6", "SelectState7",
|
||||
"SelectState8", "SelectState9", "SelectStateNext", "SelectStatePrev",
|
||||
"VolumeDown", "VolumeUp" };
|
||||
#endif
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#include "../common/args.h"
|
||||
#include "../common/config.h"
|
||||
|
||||
#include "input.h"
|
||||
|
||||
extern CFGSTRUCT DriverConfig[];
|
||||
extern ARGPSTRUCT DriverArgs[];
|
||||
|
||||
void DoDriverArgs(void);
|
||||
|
||||
int InitSound();
|
||||
void WriteSound(int32 *Buffer, int Count);
|
||||
int KillSound(void);
|
||||
uint32 GetMaxSound(void);
|
||||
uint32 GetWriteSound(void);
|
||||
|
||||
void SilenceSound(int s); /* DOS and SDL */
|
||||
|
||||
int InitJoysticks(void);
|
||||
int KillJoysticks(void);
|
||||
uint32 *GetJSOr(void);
|
||||
|
||||
int InitVideo(FCEUGI *gi);
|
||||
int KillVideo(void);
|
||||
void BlitScreen(uint8 *XBuf);
|
||||
void LockConsole(void);
|
||||
void UnlockConsole(void);
|
||||
void ToggleFS(); /* SDL */
|
||||
|
||||
int LoadGame(const char *path);
|
||||
//int CloseGame(void);
|
||||
|
||||
void Giggles(int);
|
||||
void DoFun(void);
|
||||
|
||||
int FCEUD_NetworkConnect(void);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,88 +0,0 @@
|
||||
// gui.h
|
||||
//
|
||||
// Copyright 2009 Lukas <lukas@LTx3-64>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
|
||||
#ifndef FCEUX_GUI_H
|
||||
#define FCEUX_GUI_H
|
||||
|
||||
#define GTK
|
||||
|
||||
#ifdef _GTK
|
||||
#include <gtk/gtk.h>
|
||||
#endif
|
||||
extern GtkWidget* MainWindow;
|
||||
extern GtkWidget* evbox;
|
||||
extern GtkRadioAction* stateSlot;
|
||||
extern int GtkMouseData[3];
|
||||
extern bool gtkIsStarted;
|
||||
|
||||
int InitGTKSubsystem(int argc, char** argv);
|
||||
void pushOutputToGTK(const char* str);
|
||||
void showGui(bool b);
|
||||
|
||||
bool checkGTKVersion(int major_required, int minor_required);
|
||||
|
||||
int configHotkey(char* hotkeyString);
|
||||
|
||||
void resetVideo();
|
||||
void openPaletteConfig();
|
||||
|
||||
void openNetworkConfig();
|
||||
void flushGtkEvents();
|
||||
|
||||
void openHotkeyConfig();
|
||||
void openGamepadConfig();
|
||||
|
||||
void resizeGtkWindow();
|
||||
|
||||
#ifdef OPENGL
|
||||
void setGl(GtkWidget* w, gpointer p);
|
||||
void setDoubleBuffering(GtkWidget* w, gpointer p);
|
||||
#endif
|
||||
|
||||
void openVideoConfig();
|
||||
void openSoundConfig();
|
||||
void quit ();
|
||||
void openAbout ();
|
||||
|
||||
void emuReset ();
|
||||
void hardReset ();
|
||||
void enableFullscreen ();
|
||||
|
||||
void recordMovie();
|
||||
void recordMovieAs ();
|
||||
void loadMovie ();
|
||||
#ifdef _S9XLUA_H
|
||||
void loadLua ();
|
||||
#endif
|
||||
void loadFdsBios ();
|
||||
|
||||
void enableGameGenie(int enabled);
|
||||
void loadGameGenie ();
|
||||
|
||||
void loadNSF ();
|
||||
void closeGame();
|
||||
void loadGame ();
|
||||
void saveStateAs();
|
||||
void loadStateFrom();
|
||||
void quickLoad();
|
||||
void quickSave();
|
||||
unsigned short GDKToSDLKeyval(int gdk_key);
|
||||
int InitGTKSubsystem(int argc, char** argv);
|
||||
|
||||
#endif // ifndef FCEUX_GUI_H
|
||||
@@ -1,55 +0,0 @@
|
||||
/* XPM */
|
||||
static const char * icon_xpm[] = {
|
||||
"32 32 20 1",
|
||||
" c None",
|
||||
". c #040204",
|
||||
"+ c #84A284",
|
||||
"@ c #C42204",
|
||||
"# c #8482C4",
|
||||
"$ c #FCFEFC",
|
||||
"% c #848284",
|
||||
"& c #648284",
|
||||
"* c #646284",
|
||||
"= c #444244",
|
||||
"- c #A4A284",
|
||||
"; c #C4A284",
|
||||
"> c #C48284",
|
||||
", c #A4CAF4",
|
||||
"' c #244244",
|
||||
") c #444204",
|
||||
"! c #442204",
|
||||
"~ c #446244",
|
||||
"{ c #646244",
|
||||
"] c #644244",
|
||||
" ",
|
||||
" ........ ",
|
||||
" ............... ",
|
||||
" ........................ ",
|
||||
" ...........................+ ",
|
||||
" ............@@..@@........... ",
|
||||
" .#............@@............$$ ",
|
||||
" .##..........@@.@.....$$%%%%$$ ",
|
||||
" &...........@....@$$$$$$%%&%$$ ",
|
||||
" *&...............$$$$$$$%%&%$$ ",
|
||||
" =&*.......-;;>;...$$,$$$%**&.. ",
|
||||
" '&&..............$$,,,%=)!~.. ",
|
||||
" ~&&............-%%##%*.~'=%& ",
|
||||
" *&&.....+%%****&&%%&*.&!!' ",
|
||||
" **&%&***********&&&*~{'= ",
|
||||
" ********=**~**~**~ ",
|
||||
" *****~******] ",
|
||||
" **~***]' ",
|
||||
" ~]== ",
|
||||
" ",
|
||||
" ..... .... .... .. ..@@ @@",
|
||||
" ..... .... .... .. ..@@@ @@@",
|
||||
" .. .. .. .. .. @@@ @@@ ",
|
||||
" .... .. .. .. .. @@@@@@ ",
|
||||
" .... .. ... .. .. @@@@ ",
|
||||
" .. .. ... .. .. @@@@ ",
|
||||
" .. .. .. .. .. @@@@@@ ",
|
||||
" .. .. .. .. .. @@@ @@@ ",
|
||||
" .. .... .... .....@@@ @@@",
|
||||
" .. .... .... ... @@ @@",
|
||||
" ",
|
||||
" "};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,60 +0,0 @@
|
||||
#ifndef _aosdfjk02fmasf
|
||||
#define _aosdfjk02fmasf
|
||||
|
||||
#include "../common/configSys.h"
|
||||
|
||||
#define MAXBUTTCONFIG 4
|
||||
typedef struct {
|
||||
uint8 ButtType[MAXBUTTCONFIG];
|
||||
uint8 DeviceNum[MAXBUTTCONFIG];
|
||||
uint16 ButtonNum[MAXBUTTCONFIG];
|
||||
uint32 NumC;
|
||||
//uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */
|
||||
} ButtConfig;
|
||||
|
||||
|
||||
extern int NoWaiting;
|
||||
extern CFGSTRUCT InputConfig[];
|
||||
extern ARGPSTRUCT InputArgs[];
|
||||
extern int Hotkeys[];
|
||||
void ParseGIInput(FCEUGI *GI);
|
||||
void setHotKeys();
|
||||
int ButtonConfigBegin();
|
||||
void ButtonConfigEnd();
|
||||
void ConfigButton(char *text, ButtConfig *bc);
|
||||
int DWaitButton(const uint8 *text, ButtConfig *bc, int wb);
|
||||
|
||||
#define BUTTC_KEYBOARD 0x00
|
||||
#define BUTTC_JOYSTICK 0x01
|
||||
#define BUTTC_MOUSE 0x02
|
||||
|
||||
#define FCFGD_GAMEPAD 1
|
||||
#define FCFGD_POWERPAD 2
|
||||
#define FCFGD_HYPERSHOT 3
|
||||
#define FCFGD_QUIZKING 4
|
||||
|
||||
#define SDL_FCEU_HOTKEY_EVENT SDL_USEREVENT
|
||||
|
||||
void InitInputInterface(void);
|
||||
void InputUserActiveFix(void);
|
||||
|
||||
extern bool replaceP2StartWithMicrophone;
|
||||
extern ButtConfig GamePadConfig[4][10];
|
||||
//extern ButtConfig powerpadsc[2][12];
|
||||
//extern ButtConfig QuizKingButtons[6];
|
||||
//extern ButtConfig FTrainerButtons[12];
|
||||
|
||||
void IncreaseEmulationSpeed(void);
|
||||
void DecreaseEmulationSpeed(void);
|
||||
|
||||
int DTestButtonJoy(ButtConfig *bc);
|
||||
|
||||
void FCEUD_UpdateInput(void);
|
||||
|
||||
void UpdateInput(Config *config);
|
||||
void InputCfg(const std::string &);
|
||||
|
||||
std::string GetUserText(const char* title);
|
||||
const char* ButtonName(const ButtConfig* bc, int which);
|
||||
#endif
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#define SDLK_A SDLK_a
|
||||
#define SDLK_B SDLK_b
|
||||
#define SDLK_C SDLK_c
|
||||
#define SDLK_D SDLK_d
|
||||
#define SDLK_E SDLK_e
|
||||
#define SDLK_F SDLK_f
|
||||
#define SDLK_G SDLK_g
|
||||
#define SDLK_H SDLK_h
|
||||
#define SDLK_I SDLK_i
|
||||
#define SDLK_J SDLK_j
|
||||
#define SDLK_K SDLK_k
|
||||
#define SDLK_L SDLK_l
|
||||
#define SDLK_M SDLK_m
|
||||
#define SDLK_N SDLK_n
|
||||
#define SDLK_O SDLK_o
|
||||
#define SDLK_P SDLK_p
|
||||
#define SDLK_Q SDLK_q
|
||||
#define SDLK_R SDLK_r
|
||||
#define SDLK_S SDLK_s
|
||||
#define SDLK_T SDLK_t
|
||||
#define SDLK_U SDLK_u
|
||||
#define SDLK_V SDLK_v
|
||||
#define SDLK_W SDLK_w
|
||||
#define SDLK_X SDLK_x
|
||||
#define SDLK_Y SDLK_y
|
||||
#define SDLK_Z SDLK_z
|
||||
#define SDLK_LEFTCONTROL SDLK_LCTRL
|
||||
#define SDLK_RIGHTCONTROL SDLK_RCTRL
|
||||
#define SDLK_LEFTALT SDLK_LALT
|
||||
#define SDLK_RIGHTALT SDLK_RALT
|
||||
#define SDLK_LEFTSHIFT SDLK_LSHIFT
|
||||
#define SDLK_RIGHTSHIFT SDLK_RSHIFT
|
||||
#define SDLK_CURSORDOWN SDLK_DOWN
|
||||
#define SDLK_CURSORUP SDLK_UP
|
||||
#define SDLK_CURSORLEFT SDLK_LEFT
|
||||
#define SDLK_CURSORRIGHT SDLK_RIGHT
|
||||
#define SDLK_ENTER SDLK_RETURN
|
||||
#define SDLK_EQUAL SDLK_EQUALS
|
||||
#define SDLK_APOSTROPHE SDLK_QUOTE
|
||||
#define SDLK_BRACKET_LEFT SDLK_LEFTBRACKET
|
||||
#define SDLK_BRACKET_RIGHT SDLK_RIGHTBRACKET
|
||||
#define SDLK_SCROLLLOCK SDLK_SCROLLOCK /* I guess the SDL people don't like lots of Ls... */
|
||||
#define SDLK_GRAVE SDLK_BACKQUOTE
|
||||
#define MKK(k) SDLK_##k
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#define SDLK_LAST SDL_NUM_SCANCODES
|
||||
#endif
|
||||
#define MKK_COUNT (SDLK_LAST+1)
|
||||
@@ -1,134 +0,0 @@
|
||||
static const struct {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */
|
||||
uint8 pixel_data[32 * 32 * 3 + 1];
|
||||
} fceu_playicon = {
|
||||
32, 32, 3,
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\0\0\0\0\0\0\0\0\0\\\223\373\\\223\373\267\317\373"
|
||||
"\246\304\373\260\312\373\222\267\373\246\304\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\267\317\373\246\304\373\260\312\373\210\261\373\246\304\373\\\223\373\\"
|
||||
"\223\373\210\261\373\222\267\373\267\317\373\241\301\373\\\223\373\\\223"
|
||||
"\373\0\0\0\0\0\0\\\223\373\\\223\373\227\272\373\227\272\373\227\272\373"
|
||||
"\227\272\373\227\272\373\227\272\373\\\223\373\\\223\373z`sr\242\373\227"
|
||||
"\272\373\227\272\373\\\223\373\\\223\373\\\223\373\\\223\373\213\261\373"
|
||||
"z\247\373\213\261\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\313i=\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40"
|
||||
"\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40"
|
||||
"\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\257T*\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40"
|
||||
"\355\235\203\355\235\203\341\232\205\341\232\205\365\255\233\355\235\203"
|
||||
"\355\235\203\350\250\232\365\255\233\355\235\203\307L\14\307L\14\307L\14"
|
||||
"\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256B\12\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\315Z\40\273zc\233l_\325\225\205\325\225\205\325\225\205\273\212"
|
||||
"\201\325\225\205\237qd\325\225\205\317\231\216\307L\14\307L\14\307L\14\307"
|
||||
"L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256B\12\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\315Z\40\344\232\203\301\215\201\344\232\203\273\212\201\325\225"
|
||||
"\205\2114\10\344\232\203\350\250\232\325\225\205\333\230\205\307L\14\307"
|
||||
"L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256"
|
||||
"B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\315Z\40\2259\11}0\10\2259\11}0\10}0\10\307L\14\225"
|
||||
"9\11d&\6}0\10}0\10\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14"
|
||||
"\307L\14\307L\14\307L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40\355\235\203"
|
||||
"\355\233\201\355\235\203\355\235\203\355\235\203\365\255\233\355\235\203"
|
||||
"\341\232\205\355\235\203\355\235\203\307L\14\365\255\233\355\235\203\365"
|
||||
"\255\233\355\235\203\355\235\203\355\235\203\355\235\203\355\235\203\307"
|
||||
"L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\315Z\40\325\225\205\311\221\204\311\221\204"
|
||||
"\325\225\205\311\221\204\325\225\205\311\221\204\325\225\205\325\225\205"
|
||||
"\311\221\204\307L\14\325\225\205\311\221\204\325\225\205\311\221\204\325"
|
||||
"\225\205\311\221\204\325\225\205\311\221\204\307L\14\256B\12\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\315Z\40\325\225\205\325\225\205\325\225\205\325\225\205\325\225"
|
||||
"\205\325\225\205\317\231\216\325\225\205\325\225\205\325\225\205\307L\14"
|
||||
"\325\225\205\317\231\216\325\225\205\317\231\216\325\225\205\325\225\205"
|
||||
"\273zc\241n_\307L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0"
|
||||
"\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40\325\225\205\325"
|
||||
"\225\205\325\225\205\365\255\233\333\243\231\325\225\205\333\230\205\325"
|
||||
"\225\205\325\225\205\325\225\205\307L\14\325\225\205\317\223\204\325\225"
|
||||
"\205\333\230\205\325\225\205\325\225\205\333\230\205\317\223\204\307L\14"
|
||||
"\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\315Z\40\325\225\205\325\225\205\325\225\205"
|
||||
"\325\225\205\311\221\204\325\225\205\325\225\205\325\225\205\344\232\203"
|
||||
"\273\212\201\307L\14\325\225\205\273\212\201\325\225\205\325\225\205\344"
|
||||
"\232\203\273\212\201\344\232\203\273\212\201\341\232\205\256B\12\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\257T*d&\6d&\6d&\6d&\6d&\6d&\6d&\6d&\6}0\10d&\6\256B\12d&\6p+\7"
|
||||
"d&\6d&\6}0\10d&\6}0\10d&\6d&\6\223@\26\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\234\243"
|
||||
"\335\213\237\344\237\244\333\251\247\326\237\244\333\\\223\373\267\252\317"
|
||||
"\222\241\341\267\252\317\210\237\346\241\245\332\267\252\317\246\246\327"
|
||||
"\246\246\327\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0"
|
||||
"\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\257hT\\\223\373\213\261\373\\\223"
|
||||
"\373\241\301\373\210\261\373\246\304\373\222\267\373\241\301\373\260\312"
|
||||
"\373\\\223\373\237\277\373\246\304\373\267\317\373\241\301\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\246\304\373\\\223\373\241"
|
||||
"\301\373\210\261\373\246\304\373\222\267\373\241\301\373\260\312\373\\\223"
|
||||
"\373\237\277\373\246\304\373\267\317\373\241\301\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
|
||||
"\\\223\373\\\223\373D\203\270D\203\270\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0"
|
||||
"\0\0\0\0\\\223\373\\\223\373(\211n\0\247\0\0n\0(\211n\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\0\0\0\0\0\0\\\223\373(\211n\0\247\0\0\247\0\0\247\0\0\247\0(\211n\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\210\261\373\246\304\373\241\301\373z\247"
|
||||
"\373\\\223\373\227\272\373\227\272\373\227\272\373\227\272\373\227\272\373"
|
||||
"\227\272\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\0\0\0\0\0\0(\211n\0\247\0\0n\0\0\247\0\\\215\12fs\16"
|
||||
"\0\247\0(\211n\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373Z\231Z[\230SZ\231Z[\230SZ\231Z[\230S\\\223\373\0\0\0\0"
|
||||
"\0\0\0\247\0\0\247\0\0\247\0\0\247\0vy\7p|\7\0\247\0\0\247\0(\211n\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373b\237L\200\317\20\200\317"
|
||||
"\20\200\317\20\200\317\20\200\317\20\200\317\20[\223H\0\0\0\0\0\0\230P.\323"
|
||||
"d0\230P.\323d0\221M&\313`%\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323"
|
||||
"d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323"
|
||||
"d0\230P.\323d0\230P.\323d0\0\0\0\0\0\0\0\0\0\237N(\225E\35\237N(\225E\35"
|
||||
"\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237"
|
||||
"N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N("
|
||||
"\225E\35\237N(\225E\35\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
|
||||
};
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
* Copyright (C) 2002 Paul Kuliniewicz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/// \file
|
||||
/// \brief Handles joystick input using the SDL.
|
||||
|
||||
#include "sdl.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <cerrno>
|
||||
|
||||
#define MAX_JOYSTICKS 32
|
||||
static SDL_Joystick *s_Joysticks[MAX_JOYSTICKS] = {NULL};
|
||||
|
||||
static int s_jinited = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Tests if the given button is active on the joystick.
|
||||
*/
|
||||
int
|
||||
DTestButtonJoy(ButtConfig *bc)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x = 0; x < bc->NumC; x++)
|
||||
{
|
||||
if(bc->ButtonNum[x] & 0x2000)
|
||||
{
|
||||
/* Hat "button" */
|
||||
if(SDL_JoystickGetHat(s_Joysticks[bc->DeviceNum[x]],
|
||||
((bc->ButtonNum[x] >> 8) & 0x1F)) &
|
||||
(bc->ButtonNum[x]&0xFF))
|
||||
return 1;
|
||||
}
|
||||
else if(bc->ButtonNum[x] & 0x8000)
|
||||
{
|
||||
/* Axis "button" */
|
||||
int pos;
|
||||
pos = SDL_JoystickGetAxis(s_Joysticks[bc->DeviceNum[x]],
|
||||
bc->ButtonNum[x] & 16383);
|
||||
if ((bc->ButtonNum[x] & 0x4000) && pos <= -16383) {
|
||||
return 1;
|
||||
} else if (!(bc->ButtonNum[x] & 0x4000) && pos >= 16363) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if(SDL_JoystickGetButton(s_Joysticks[bc->DeviceNum[x]],
|
||||
bc->ButtonNum[x]))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the SDL joystick subsystem.
|
||||
*/
|
||||
int
|
||||
KillJoysticks()
|
||||
{
|
||||
int n; /* joystick index */
|
||||
|
||||
if(!s_jinited) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(n = 0; n < MAX_JOYSTICKS; n++) {
|
||||
if (s_Joysticks[n] != 0) {
|
||||
SDL_JoystickClose(s_Joysticks[n]);
|
||||
}
|
||||
s_Joysticks[n]=0;
|
||||
}
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the SDL joystick subsystem.
|
||||
*/
|
||||
int
|
||||
InitJoysticks()
|
||||
{
|
||||
int n; /* joystick index */
|
||||
int total;
|
||||
|
||||
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
|
||||
|
||||
total = SDL_NumJoysticks();
|
||||
if(total>MAX_JOYSTICKS) {
|
||||
total = MAX_JOYSTICKS;
|
||||
}
|
||||
|
||||
for(n = 0; n < total; n++) {
|
||||
/* Open the joystick under SDL. */
|
||||
s_Joysticks[n] = SDL_JoystickOpen(n);
|
||||
//printf("Could not open joystick %d: %s.\n",
|
||||
//joy[n] - 1, SDL_GetError());
|
||||
continue;
|
||||
}
|
||||
|
||||
s_jinited = 1;
|
||||
return 1;
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
#include "sdl.h"
|
||||
#include "input.h"
|
||||
#include <SDL_net.h>
|
||||
#include "sdl-netplay.h"
|
||||
|
||||
char *ServerHost;
|
||||
int magic;
|
||||
|
||||
static int LocalPortTCP=0xFCE;
|
||||
static int LocalPortUDP=0xFCE;
|
||||
static int RemotePortTCP=0xFCE;
|
||||
|
||||
static int RemotePortUDP; /* Not configurable, figured out during handshake. */
|
||||
|
||||
static TCPsocket Socket;
|
||||
static UDPsocket UDPSocket;
|
||||
static SDLNet_SocketSet set;
|
||||
|
||||
|
||||
static void en32(uint8 *buf, uint32 morp)
|
||||
{
|
||||
buf[0]=morp;
|
||||
buf[1]=morp>>8;
|
||||
buf[2]=morp>>16;
|
||||
buf[3]=morp>>24;
|
||||
}
|
||||
|
||||
static uint32 de32(uint8 *morp)
|
||||
{
|
||||
return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
|
||||
}
|
||||
|
||||
|
||||
|
||||
int FCEUD_NetworkConnect(void)
|
||||
{
|
||||
IPaddress rip;
|
||||
|
||||
SDLNet_Init();
|
||||
int netplay =1;
|
||||
if(netplay==1) /* Be a server. */
|
||||
{
|
||||
TCPsocket tmp;
|
||||
Uint16 p=LocalPortUDP;
|
||||
|
||||
SDLNet_ResolveHost(&rip,NULL,LocalPortTCP);
|
||||
|
||||
UDPSocket=SDLNet_UDP_Open(p);
|
||||
|
||||
tmp=SDLNet_TCP_Open(&rip);
|
||||
Socket=SDLNet_TCP_Accept(tmp);
|
||||
|
||||
memcpy(&rip,SDLNet_TCP_GetPeerAddress(Socket),sizeof(IPaddress));
|
||||
{
|
||||
Uint32 buf[12];
|
||||
uint32 player=1;
|
||||
|
||||
magic=SDL_GetTicks();
|
||||
|
||||
SDLNet_Write32(buf,uport);
|
||||
SDLNet_Write32(buf+4,1);
|
||||
SDLNet_Write32(buf+8,magic);
|
||||
|
||||
SDLNet_TCP_Send(Socket, buf, 12);
|
||||
|
||||
/* Get the UDP port the client is waiting for data on. */
|
||||
SDLNet_TCP_Recv(Socket, buf, 2);
|
||||
RemotePortUDP=de32(buf);
|
||||
}
|
||||
}
|
||||
else /* Be a client */
|
||||
{
|
||||
SDLNet_ResolveHost(&rip,ServerHost,RemotePortTCP);
|
||||
Socket=SDLNet_TCP_Open(&rip);
|
||||
|
||||
{
|
||||
Uint16 p=LocalPortUDP;
|
||||
uint8 buf[12];
|
||||
|
||||
UDPSocket=SDLNet_UDP_Open(p);
|
||||
|
||||
/* Now, tell the server what local UDP port it should send to. */
|
||||
en32(buf,p);
|
||||
SDLNet_TCP_Send(Socket, buf, 4);
|
||||
|
||||
/* Get the UDP port from the server we should send data to. */
|
||||
SDLNet_TCP_Recv(Socket, buf, 12);
|
||||
RemotePortUDP=de32(buf);
|
||||
magic=de32(buf+8);
|
||||
}
|
||||
set=SDLNet_AllocSocketSet(1);
|
||||
SDLNet_TCP_AddSocket(set,Socket);
|
||||
SDLNet_UDP_AddSocket(set,UDPSocket);
|
||||
} // End client connect code.
|
||||
|
||||
rip.port=RemotePortUDP;
|
||||
SDLNet_UDP_Bind(UDPSocket, 0, &rip);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int CheckUDP(uint8 *packet, int32 len, int32 alt)
|
||||
{
|
||||
uint32 crc;
|
||||
uint32 repcrc;
|
||||
|
||||
crc=FCEUI_CRC32(0,packet+4,len+8);
|
||||
repcrc=de32(packet);
|
||||
|
||||
if(crc!=repcrc) return(0); /* CRC32 mismatch, bad packet. */
|
||||
packet+=4;
|
||||
|
||||
if(de32(packet)!=magic) /* Magic number mismatch, bad or spoofed packet. */
|
||||
return(0);
|
||||
|
||||
packet+=4;
|
||||
if(alt)
|
||||
{
|
||||
if(de32(packet)<incounter) /* Time warped packet. */
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
if(de32(packet)!=incounter) /* Time warped packet. */
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* Be careful where these MakeXXX() functions are used. */
|
||||
static uint8 *MakeUDP(uint8 *data, int32 len)
|
||||
{
|
||||
/* UDP packet data header is 12 bytes in length. */
|
||||
static uint8 buf[12+32]; // arbitrary 32.
|
||||
|
||||
en32(buf+4,magic);
|
||||
en32(buf+8,outcounter);
|
||||
memcpy(buf+12,data,len);
|
||||
en32(buf,FCEUI_CRC32(0,buf+4,8+len));
|
||||
return(buf);
|
||||
}
|
||||
|
||||
static uint8 *MakeTCP(uint8 *data, int32 len)
|
||||
{
|
||||
/* TCP packet data header is 4 bytes in length. */
|
||||
static uint8 buf[4+32]; // arbitrary 32.
|
||||
|
||||
en32(buf,outcounter);
|
||||
memcpy(buf+4,data,len);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
#define UDPHEADSIZE 12
|
||||
#define TCPHEADSIZE 4
|
||||
|
||||
void FCEUD_NetworkClose(void)
|
||||
{
|
||||
SDLNet_Quit();
|
||||
}
|
||||
|
||||
/* 1 byte to server */
|
||||
int FCEUD_SendDataToServer(uint8 v,uint8 cmd)
|
||||
{
|
||||
UDPpacket upack;
|
||||
|
||||
upack.channel=0;
|
||||
upack.data=MakeUDP(data,1);
|
||||
upack.len=upack.maxlen=UDPHEADSIZE+1;
|
||||
upack.status=0;
|
||||
|
||||
SDLNet_UDP_Send(UDPSocket,0,&upack);
|
||||
|
||||
outcounter++;
|
||||
return(1);
|
||||
}
|
||||
|
||||
void FCEUD_SendDataToClients(uint8 *data)
|
||||
{
|
||||
UDPpacket upack;
|
||||
|
||||
SDLNet_TCP_Send(Socket,MakeTCP(data,5),TCPHEADSIZE+5);
|
||||
|
||||
upack.channel=0;
|
||||
upack.data=MakeUDP(data,5);
|
||||
upack.len=upack.maxlen=UDPHEADSIZE+5;
|
||||
upack.status=0;
|
||||
|
||||
SDLNet_UDP_Send(UDPSocket,0,&upack);
|
||||
|
||||
outcounter++;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int FCEUD_GetDataFromServer(uint8 *data)
|
||||
{
|
||||
uint8 buf[128];
|
||||
NoWaiting&=~2;
|
||||
|
||||
while(SDLNet_CheckSockets(set,1)==0)
|
||||
{
|
||||
// do something here.
|
||||
}
|
||||
if(SDLNet_SocketReady(Socket))
|
||||
{
|
||||
if(de32(buf)==incounter) /* New packet, keep. */
|
||||
{
|
||||
unsigned long beefie;
|
||||
memcpy(data,buf+TCPHEADSIZE,5);
|
||||
incounter++;
|
||||
|
||||
if(!ioctl(Socket,FIONREAD,&beefie))
|
||||
if(beefie)
|
||||
NoWaiting|=2;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
}
|
||||
if(SDLNet_SocketReady(UDPSocket)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,251 +0,0 @@
|
||||
#define GL_GLEXT_LEGACY
|
||||
|
||||
#include "sdl.h"
|
||||
#include "sdl-opengl.h"
|
||||
#include "../common/vidblit.h"
|
||||
#include "../../utils/memory.h"
|
||||
|
||||
#ifdef APPLEOPENGL
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glu.h>
|
||||
#include <OpenGL/glext.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <GL/glext.h>
|
||||
#endif
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
#ifndef APIENTRY
|
||||
#define APIENTRY
|
||||
#endif
|
||||
|
||||
static GLuint textures[2]={0,0}; // Normal image, scanline overlay.
|
||||
|
||||
static int left,right,top,bottom; // right and bottom are not inclusive.
|
||||
static int scanlines;
|
||||
static void *HiBuffer;
|
||||
|
||||
typedef void APIENTRY (*glColorTableEXT_Func)(GLenum target,
|
||||
GLenum internalformat, GLsizei width, GLenum format, GLenum type,
|
||||
const GLvoid *table);
|
||||
glColorTableEXT_Func p_glColorTableEXT;
|
||||
|
||||
void
|
||||
SetOpenGLPalette(uint8 *data)
|
||||
{
|
||||
if(!HiBuffer) {
|
||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
p_glColorTableEXT(GL_TEXTURE_2D, GL_RGB, 256,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
} else {
|
||||
SetPaletteBlitToHigh((uint8*)data);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BlitOpenGL(uint8 *buf)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
|
||||
if(HiBuffer) {
|
||||
Blit8ToHigh(buf, (uint8*)HiBuffer, 256, 240, 256*4, 1, 1);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, HiBuffer);
|
||||
}
|
||||
else {
|
||||
//glPixelStorei(GL_UNPACK_ROW_LENGTH, 256);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, 256, 256, 0,
|
||||
GL_COLOR_INDEX,GL_UNSIGNED_BYTE,buf);
|
||||
}
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of picture.
|
||||
glVertex2f(-1.0f, -1.0f); // Bottom left of target.
|
||||
|
||||
glTexCoord2f(1.0f*right/256, 1.0f*bottom/256);// Bottom right of picture.
|
||||
glVertex2f( 1.0f, -1.0f); // Bottom right of target.
|
||||
|
||||
glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture.
|
||||
glVertex2f( 1.0f, 1.0f); // Top right of target.
|
||||
|
||||
glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture.
|
||||
glVertex2f(-1.0f, 1.0f); // Top left of target.
|
||||
glEnd();
|
||||
|
||||
//glDisable(GL_BLEND);
|
||||
if(scanlines) {
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textures[1]);
|
||||
glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
glTexCoord2f(1.0f*left/256,
|
||||
1.0f*bottom/256); // Bottom left of our picture.
|
||||
glVertex2f(-1.0f, -1.0f); // Bottom left of target.
|
||||
|
||||
glTexCoord2f(1.0f*right/256,
|
||||
1.0f*bottom/256); // Bottom right of our picture.
|
||||
glVertex2f( 1.0f, -1.0f); // Bottom right of target.
|
||||
|
||||
glTexCoord2f(1.0f*right/256,
|
||||
1.0f*top/256); // Top right of our picture.
|
||||
glVertex2f( 1.0f, 1.0f); // Top right of target.
|
||||
|
||||
glTexCoord2f(1.0f*left/256,
|
||||
1.0f*top/256); // Top left of our picture.
|
||||
glVertex2f(-1.0f, 1.0f); // Top left of target.
|
||||
|
||||
glEnd();
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
SDL_GL_SwapBuffers();
|
||||
}
|
||||
|
||||
void
|
||||
KillOpenGL(void)
|
||||
{
|
||||
if(textures[0]) {
|
||||
glDeleteTextures(2, &textures[0]);
|
||||
}
|
||||
textures[0]=0;
|
||||
if(HiBuffer) {
|
||||
free(HiBuffer);
|
||||
HiBuffer=0;
|
||||
}
|
||||
}
|
||||
/* Rectangle, left, right(not inclusive), top, bottom(not inclusive). */
|
||||
|
||||
int
|
||||
InitOpenGL(int l,
|
||||
int r,
|
||||
int t,
|
||||
int b,
|
||||
double xscale,
|
||||
double yscale,
|
||||
int efx,
|
||||
int ipolate,
|
||||
int stretchx,
|
||||
int stretchy,
|
||||
SDL_Surface *screen)
|
||||
{
|
||||
const char *extensions;
|
||||
|
||||
#define LFG(x) if(!(##x = (x##_Func) SDL_GL_GetProcAddress(#x))) return(0);
|
||||
|
||||
#define LFGN(x) p_##x = (x##_Func) SDL_GL_GetProcAddress(#x)
|
||||
|
||||
// LFG(glBindTexture);
|
||||
LFGN(glColorTableEXT);
|
||||
// LFG(glTexImage2D);
|
||||
// LFG(glBegin);
|
||||
// LFG(glVertex2f);
|
||||
// LFG(glTexCoord2f);
|
||||
// LFG(glEnd);
|
||||
// LFG(glEnable);
|
||||
// LFG(glBlendFunc);
|
||||
// LFG(glGetString);
|
||||
// LFG(glViewport);
|
||||
// LFG(glGenTextures);
|
||||
// LFG(glDeleteTextures);
|
||||
// LFG(glTexParameteri);
|
||||
// LFG(glClearColor);
|
||||
// LFG(glLoadIdentity);
|
||||
// LFG(glClear);
|
||||
// LFG(glMatrixMode);
|
||||
// LFG(glDisable);
|
||||
|
||||
left=l;
|
||||
right=r;
|
||||
top=t;
|
||||
bottom=b;
|
||||
|
||||
HiBuffer=0;
|
||||
|
||||
extensions=(const char*)glGetString(GL_EXTENSIONS);
|
||||
|
||||
if((efx&2) || !extensions || !p_glColorTableEXT || !strstr(extensions,"GL_EXT_paletted_texture"))
|
||||
{
|
||||
if(!(efx&2)) // Don't want to print out a warning message in this case...
|
||||
FCEU_printf("Paletted texture extension not found. Using slower texture format...\n");
|
||||
HiBuffer=FCEU_malloc(4*256*256);
|
||||
memset(HiBuffer,0x00,4*256*256);
|
||||
#ifndef LSB_FIRST
|
||||
InitBlitToHigh(4,0xFF000000,0xFF0000,0xFF00,efx&2,0,0);
|
||||
#else
|
||||
InitBlitToHigh(4,0xFF,0xFF00,0xFF0000,efx&2,0,0);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(screen->flags & SDL_FULLSCREEN)
|
||||
{
|
||||
xscale=(double)screen->w / (double)(r-l);
|
||||
yscale=(double)screen->h / (double)(b-t);
|
||||
if(xscale<yscale) yscale = xscale;
|
||||
if(yscale<xscale) xscale = yscale;
|
||||
}
|
||||
|
||||
{
|
||||
int rw=(int)((r-l)*xscale);
|
||||
int rh=(int)((b-t)*yscale);
|
||||
int sx=(screen->w-rw)/2; // Start x
|
||||
int sy=(screen->h-rh)/2; // Start y
|
||||
|
||||
if(stretchx) { sx=0; rw=screen->w; }
|
||||
if(stretchy) { sy=0; rh=screen->h; }
|
||||
glViewport(sx, sy, rw, rh);
|
||||
}
|
||||
glGenTextures(2, &textures[0]);
|
||||
scanlines=0;
|
||||
|
||||
if(efx&1)
|
||||
{
|
||||
uint8 *buf;
|
||||
int x,y;
|
||||
|
||||
scanlines=1;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textures[1]);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
|
||||
|
||||
buf=(uint8*)FCEU_dmalloc(256*(256*2)*4);
|
||||
|
||||
for(y=0;y<(256*2);y++)
|
||||
for(x=0;x<256;x++)
|
||||
{
|
||||
buf[y*256*4+x*4]=0;
|
||||
buf[y*256*4+x*4+1]=0;
|
||||
buf[y*256*4+x*4+2]=0;
|
||||
buf[y*256*4+x*4+3]=(y&1)?0x00:0xFF; //?0xa0:0xFF; // <-- Pretty
|
||||
//buf[y*256+x]=(y&1)?0x00:0xFF;
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, (scanlines==2)?256*4:512, 0,
|
||||
GL_RGBA,GL_UNSIGNED_BYTE,buf);
|
||||
FCEU_dfree(buf);
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background color to black.
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
// In a double buffered setup with page flipping, be sure to clear both buffers.
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
SDL_GL_SwapBuffers();
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
SDL_GL_SwapBuffers();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
void SetOpenGLPalette(uint8 *data);
|
||||
void BlitOpenGL(uint8 *buf);
|
||||
void KillOpenGL(void);
|
||||
int InitOpenGL(int l, int r, int t, int b, double xscale,double yscale, int efx, int ipolate,
|
||||
int stretchx, int stretchy, SDL_Surface *screen);
|
||||
|
||||
@@ -1,272 +0,0 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/// \file
|
||||
/// \brief Handles sound emulation using the SDL.
|
||||
|
||||
#include "sdl.h"
|
||||
|
||||
#include "../common/configSys.h"
|
||||
#include "../../utils/memory.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
extern Config *g_config;
|
||||
|
||||
static volatile int *s_Buffer = 0;
|
||||
static unsigned int s_BufferSize;
|
||||
static unsigned int s_BufferRead;
|
||||
static unsigned int s_BufferWrite;
|
||||
static volatile unsigned int s_BufferIn;
|
||||
|
||||
static int s_mute = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Callback from the SDL to get and play audio data.
|
||||
*/
|
||||
static void
|
||||
fillaudio(void *udata,
|
||||
uint8 *stream,
|
||||
int len)
|
||||
{
|
||||
int16 *tmps = (int16*)stream;
|
||||
len >>= 1;
|
||||
while(len) {
|
||||
int16 sample = 0;
|
||||
if(s_BufferIn) {
|
||||
sample = s_Buffer[s_BufferRead];
|
||||
s_BufferRead = (s_BufferRead + 1) % s_BufferSize;
|
||||
s_BufferIn--;
|
||||
} else {
|
||||
sample = 0;
|
||||
}
|
||||
|
||||
*tmps = sample;
|
||||
tmps++;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the audio subsystem.
|
||||
*/
|
||||
int
|
||||
InitSound()
|
||||
{
|
||||
int sound, soundrate, soundbufsize, soundvolume, soundtrianglevolume, soundsquare1volume, soundsquare2volume, soundnoisevolume, soundpcmvolume, soundq;
|
||||
SDL_AudioSpec spec;
|
||||
|
||||
g_config->getOption("SDL.Sound", &sound);
|
||||
if(!sound) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&spec, 0, sizeof(spec));
|
||||
if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
|
||||
puts(SDL_GetError());
|
||||
KillSound();
|
||||
return 0;
|
||||
}
|
||||
char driverName[8];
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
// TODO - SDL 2
|
||||
#else
|
||||
SDL_AudioDriverName(driverName, 8);
|
||||
fprintf(stderr, "Loading SDL sound with %s driver...\n", driverName);
|
||||
#endif
|
||||
|
||||
// load configuration variables
|
||||
g_config->getOption("SDL.Sound.Rate", &soundrate);
|
||||
g_config->getOption("SDL.Sound.BufSize", &soundbufsize);
|
||||
g_config->getOption("SDL.Sound.Volume", &soundvolume);
|
||||
g_config->getOption("SDL.Sound.Quality", &soundq);
|
||||
g_config->getOption("SDL.Sound.TriangleVolume", &soundtrianglevolume);
|
||||
g_config->getOption("SDL.Sound.Square1Volume", &soundsquare1volume);
|
||||
g_config->getOption("SDL.Sound.Square2Volume", &soundsquare2volume);
|
||||
g_config->getOption("SDL.Sound.NoiseVolume", &soundnoisevolume);
|
||||
g_config->getOption("SDL.Sound.PCMVolume", &soundpcmvolume);
|
||||
|
||||
spec.freq = soundrate;
|
||||
spec.format = AUDIO_S16SYS;
|
||||
spec.channels = 1;
|
||||
spec.samples = 512;
|
||||
spec.callback = fillaudio;
|
||||
spec.userdata = 0;
|
||||
|
||||
s_BufferSize = soundbufsize * soundrate / 1000;
|
||||
|
||||
// For safety, set a bare minimum:
|
||||
if (s_BufferSize < spec.samples * 2)
|
||||
s_BufferSize = spec.samples * 2;
|
||||
|
||||
s_Buffer = (int *)FCEU_dmalloc(sizeof(int) * s_BufferSize);
|
||||
if (!s_Buffer)
|
||||
return 0;
|
||||
s_BufferRead = s_BufferWrite = s_BufferIn = 0;
|
||||
|
||||
if(SDL_OpenAudio(&spec, 0) < 0)
|
||||
{
|
||||
puts(SDL_GetError());
|
||||
KillSound();
|
||||
return 0;
|
||||
}
|
||||
SDL_PauseAudio(0);
|
||||
|
||||
FCEUI_SetSoundVolume(soundvolume);
|
||||
FCEUI_SetSoundQuality(soundq);
|
||||
FCEUI_Sound(soundrate);
|
||||
FCEUI_SetTriangleVolume(soundtrianglevolume);
|
||||
FCEUI_SetSquare1Volume(soundsquare1volume);
|
||||
FCEUI_SetSquare2Volume(soundsquare2volume);
|
||||
FCEUI_SetNoiseVolume(soundnoisevolume);
|
||||
FCEUI_SetPCMVolume(soundpcmvolume);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the size of the audio buffer.
|
||||
*/
|
||||
uint32
|
||||
GetMaxSound(void)
|
||||
{
|
||||
return(s_BufferSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of free space in the audio buffer.
|
||||
*/
|
||||
uint32
|
||||
GetWriteSound(void)
|
||||
{
|
||||
return(s_BufferSize - s_BufferIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a sound clip to the audio subsystem.
|
||||
*/
|
||||
void
|
||||
WriteSound(int32 *buf,
|
||||
int Count)
|
||||
{
|
||||
extern int EmulationPaused;
|
||||
if (EmulationPaused == 0)
|
||||
while(Count)
|
||||
{
|
||||
while(s_BufferIn == s_BufferSize)
|
||||
{
|
||||
SDL_Delay(1);
|
||||
}
|
||||
|
||||
s_Buffer[s_BufferWrite] = *buf;
|
||||
Count--;
|
||||
s_BufferWrite = (s_BufferWrite + 1) % s_BufferSize;
|
||||
|
||||
SDL_LockAudio();
|
||||
s_BufferIn++;
|
||||
SDL_UnlockAudio();
|
||||
|
||||
buf++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause (1) or unpause (0) the audio output.
|
||||
*/
|
||||
void
|
||||
SilenceSound(int n)
|
||||
{
|
||||
SDL_PauseAudio(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shut down the audio subsystem.
|
||||
*/
|
||||
int
|
||||
KillSound(void)
|
||||
{
|
||||
FCEUI_Sound(0);
|
||||
SDL_CloseAudio();
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
if(s_Buffer) {
|
||||
free((void *)s_Buffer);
|
||||
s_Buffer = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adjust the volume either down (-1), up (1), or to the default (0).
|
||||
* Unmutes if mute was active before.
|
||||
*/
|
||||
void
|
||||
FCEUD_SoundVolumeAdjust(int n)
|
||||
{
|
||||
int soundvolume;
|
||||
g_config->getOption("SDL.Sound.Volume", &soundvolume);
|
||||
|
||||
switch(n) {
|
||||
case -1:
|
||||
soundvolume -= 10;
|
||||
if(soundvolume < 0) {
|
||||
soundvolume = 0;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
soundvolume = 100;
|
||||
break;
|
||||
case 1:
|
||||
soundvolume += 10;
|
||||
if(soundvolume > 150) {
|
||||
soundvolume = 150;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
s_mute = 0;
|
||||
FCEUI_SetSoundVolume(soundvolume);
|
||||
g_config->setOption("SDL.Sound.Volume", soundvolume);
|
||||
|
||||
FCEU_DispMessage("Sound volume %d.",0, soundvolume);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the sound on or off.
|
||||
*/
|
||||
void
|
||||
FCEUD_SoundToggle(void)
|
||||
{
|
||||
if(s_mute) {
|
||||
int soundvolume;
|
||||
g_config->getOption("SDL.SoundVolume", &soundvolume);
|
||||
|
||||
s_mute = 0;
|
||||
FCEUI_SetSoundVolume(soundvolume);
|
||||
FCEU_DispMessage("Sound mute off.",0);
|
||||
} else {
|
||||
s_mute = 1;
|
||||
FCEUI_SetSoundVolume(0);
|
||||
FCEU_DispMessage("Sound mute on.",0);
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
/// \file
|
||||
/// \brief Handles emulation speed throttling using the SDL timing functions.
|
||||
|
||||
#include "sdl.h"
|
||||
#include "throttle.h"
|
||||
|
||||
static const double Slowest = 0.015625; // 1/64x speed (around 1 fps on NTSC)
|
||||
static const double Fastest = 32; // 32x speed (around 1920 fps on NTSC)
|
||||
static const double Normal = 1.0; // 1x speed (around 60 fps on NTSC)
|
||||
|
||||
static uint64 Lasttime, Nexttime;
|
||||
static long double desired_frametime;
|
||||
static int InFrame;
|
||||
double g_fpsScale = Normal; // used by sdl.cpp
|
||||
bool MaxSpeed = false;
|
||||
|
||||
/* LOGMUL = exp(log(2) / 3)
|
||||
*
|
||||
* This gives us a value such that if we do x*=LOGMUL three times,
|
||||
* then after that, x is twice the value it was before.
|
||||
*
|
||||
* This gives us three speed steps per order of magnitude.
|
||||
*
|
||||
*/
|
||||
#define LOGMUL 1.259921049894873
|
||||
|
||||
/**
|
||||
* Refreshes the FPS throttling variables.
|
||||
*/
|
||||
void
|
||||
RefreshThrottleFPS()
|
||||
{
|
||||
uint64 fps = FCEUI_GetDesiredFPS(); // Do >> 24 to get in Hz
|
||||
desired_frametime = 16777216.0l / (fps * g_fpsScale);
|
||||
|
||||
Lasttime=0;
|
||||
Nexttime=0;
|
||||
InFrame=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform FPS speed throttling by delaying until the next time slot.
|
||||
*/
|
||||
int
|
||||
SpeedThrottle()
|
||||
{
|
||||
if(g_fpsScale >= 32)
|
||||
{
|
||||
return 0; /* Done waiting */
|
||||
}
|
||||
uint64 time_left;
|
||||
uint64 cur_time;
|
||||
|
||||
if(!Lasttime)
|
||||
Lasttime = SDL_GetTicks();
|
||||
|
||||
if(!InFrame)
|
||||
{
|
||||
InFrame = 1;
|
||||
Nexttime = Lasttime + desired_frametime * 1000;
|
||||
}
|
||||
|
||||
cur_time = SDL_GetTicks();
|
||||
if(cur_time >= Nexttime)
|
||||
time_left = 0;
|
||||
else
|
||||
time_left = Nexttime - cur_time;
|
||||
|
||||
if(time_left > 50)
|
||||
{
|
||||
time_left = 50;
|
||||
/* In order to keep input responsive, don't wait too long at once */
|
||||
/* 50 ms wait gives us a 20 Hz responsetime which is nice. */
|
||||
}
|
||||
else
|
||||
InFrame = 0;
|
||||
|
||||
/*fprintf(stderr, "attempting to sleep %Ld ms, frame complete=%s\n",
|
||||
time_left, InFrame?"no":"yes");*/
|
||||
SDL_Delay(time_left);
|
||||
|
||||
if(!InFrame)
|
||||
{
|
||||
Lasttime = SDL_GetTicks();
|
||||
return 0; /* Done waiting */
|
||||
}
|
||||
return 1; /* Must still wait some more */
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the emulation speed throttling to the next entry in the speed table.
|
||||
*/
|
||||
void IncreaseEmulationSpeed(void)
|
||||
{
|
||||
g_fpsScale *= LOGMUL;
|
||||
|
||||
if(g_fpsScale > Fastest) g_fpsScale = Fastest;
|
||||
|
||||
RefreshThrottleFPS();
|
||||
|
||||
FCEU_DispMessage("Emulation speed %.1f%%",0, g_fpsScale*100.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the emulation speed throttling to the previous entry in the speed table.
|
||||
*/
|
||||
void DecreaseEmulationSpeed(void)
|
||||
{
|
||||
g_fpsScale /= LOGMUL;
|
||||
if(g_fpsScale < Slowest)
|
||||
g_fpsScale = Slowest;
|
||||
|
||||
RefreshThrottleFPS();
|
||||
|
||||
FCEU_DispMessage("Emulation speed %.1f%%",0, g_fpsScale*100.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the emulation speed throttling to a specific value.
|
||||
*/
|
||||
void
|
||||
FCEUD_SetEmulationSpeed(int cmd)
|
||||
{
|
||||
MaxSpeed = false;
|
||||
|
||||
switch(cmd) {
|
||||
case EMUSPEED_SLOWEST:
|
||||
g_fpsScale = Slowest;
|
||||
break;
|
||||
case EMUSPEED_SLOWER:
|
||||
DecreaseEmulationSpeed();
|
||||
break;
|
||||
case EMUSPEED_NORMAL:
|
||||
g_fpsScale = Normal;
|
||||
break;
|
||||
case EMUSPEED_FASTER:
|
||||
IncreaseEmulationSpeed();
|
||||
break;
|
||||
case EMUSPEED_FASTEST:
|
||||
g_fpsScale = Fastest;
|
||||
MaxSpeed = true;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshThrottleFPS();
|
||||
|
||||
FCEU_DispMessage("Emulation speed %.1f%%",0, g_fpsScale*100.0);
|
||||
}
|
||||
@@ -1,861 +0,0 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/// \file
|
||||
/// \brief Handles the graphical game display for the SDL implementation.
|
||||
|
||||
#include "sdl.h"
|
||||
#include "sdl-opengl.h"
|
||||
#include "../common/vidblit.h"
|
||||
#include "../../fceu.h"
|
||||
#include "../../version.h"
|
||||
#include "../../video.h"
|
||||
|
||||
#include "../../utils/memory.h"
|
||||
|
||||
#include "sdl-icon.h"
|
||||
#include "dface.h"
|
||||
|
||||
#include "../common/configSys.h"
|
||||
#include "sdl-video.h"
|
||||
|
||||
#ifdef CREATE_AVI
|
||||
#include "../videolog/nesvideos-piece.h"
|
||||
#endif
|
||||
|
||||
#ifdef _GTK
|
||||
#include "gui.h"
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
#include <gdk/gdkx.h>
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
// GLOBALS
|
||||
extern Config *g_config;
|
||||
|
||||
// STATIC GLOBALS
|
||||
extern SDL_Surface *s_screen;
|
||||
|
||||
static SDL_Surface *s_BlitBuf; // Buffer when using hardware-accelerated blits.
|
||||
static SDL_Surface *s_IconSurface = NULL;
|
||||
|
||||
static int s_curbpp;
|
||||
static int s_srendline, s_erendline;
|
||||
static int s_tlines;
|
||||
static int s_inited;
|
||||
|
||||
#ifdef OPENGL
|
||||
static int s_useOpenGL;
|
||||
#endif
|
||||
static double s_exs, s_eys;
|
||||
static int s_eefx;
|
||||
static int s_clipSides;
|
||||
static int s_fullscreen;
|
||||
static int noframe;
|
||||
static int s_nativeWidth = -1;
|
||||
static int s_nativeHeight = -1;
|
||||
|
||||
#define NWIDTH (256 - (s_clipSides ? 16 : 0))
|
||||
#define NOFFSET (s_clipSides ? 8 : 0)
|
||||
|
||||
static int s_paletterefresh;
|
||||
|
||||
extern bool MaxSpeed;
|
||||
|
||||
/**
|
||||
* Attempts to destroy the graphical video display. Returns 0 on
|
||||
* success, -1 on failure.
|
||||
*/
|
||||
|
||||
//draw input aids if we are fullscreen
|
||||
bool FCEUD_ShouldDrawInputAids()
|
||||
{
|
||||
return s_fullscreen!=0;
|
||||
}
|
||||
|
||||
int
|
||||
KillVideo()
|
||||
{
|
||||
// if the IconSurface has been initialized, destroy it
|
||||
if(s_IconSurface) {
|
||||
SDL_FreeSurface(s_IconSurface);
|
||||
s_IconSurface=0;
|
||||
}
|
||||
|
||||
// return failure if the video system was not initialized
|
||||
if(s_inited == 0)
|
||||
return -1;
|
||||
|
||||
// if the rest of the system has been initialized, shut it down
|
||||
#ifdef OPENGL
|
||||
// check for OpenGL and shut it down
|
||||
if(s_useOpenGL)
|
||||
KillOpenGL();
|
||||
else
|
||||
#endif
|
||||
// shut down the system that converts from 8 to 16/32 bpp
|
||||
if(s_curbpp > 8)
|
||||
KillBlitToHigh();
|
||||
|
||||
// shut down the SDL video sub-system
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
|
||||
s_inited = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// this variable contains information about the special scaling filters
|
||||
static int s_sponge;
|
||||
|
||||
/**
|
||||
* These functions determine an appropriate scale factor for fullscreen/
|
||||
*/
|
||||
inline double GetXScale(int xres)
|
||||
{
|
||||
return ((double)xres) / NWIDTH;
|
||||
}
|
||||
inline double GetYScale(int yres)
|
||||
{
|
||||
return ((double)yres) / s_tlines;
|
||||
}
|
||||
void FCEUD_VideoChanged()
|
||||
{
|
||||
int buf;
|
||||
g_config->getOption("SDL.PAL", &buf);
|
||||
if(buf == 1)
|
||||
PAL = 1;
|
||||
else
|
||||
PAL = 0; // NTSC and Dendy
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
int InitVideo(FCEUGI *gi)
|
||||
{
|
||||
// This is a big TODO. Stubbing this off into its own function,
|
||||
// as the SDL surface routines have changed drastically in SDL2
|
||||
// TODO - SDL2
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* Attempts to initialize the graphical video display. Returns 0 on
|
||||
* success, -1 on failure.
|
||||
*/
|
||||
int
|
||||
InitVideo(FCEUGI *gi)
|
||||
{
|
||||
// XXX soules - const? is this necessary?
|
||||
const SDL_VideoInfo *vinf;
|
||||
int error, flags = 0;
|
||||
int doublebuf, xstretch, ystretch, xres, yres, show_fps;
|
||||
|
||||
FCEUI_printf("Initializing video...");
|
||||
|
||||
// load the relevant configuration variables
|
||||
g_config->getOption("SDL.Fullscreen", &s_fullscreen);
|
||||
g_config->getOption("SDL.DoubleBuffering", &doublebuf);
|
||||
#ifdef OPENGL
|
||||
g_config->getOption("SDL.OpenGL", &s_useOpenGL);
|
||||
#endif
|
||||
g_config->getOption("SDL.SpecialFilter", &s_sponge);
|
||||
g_config->getOption("SDL.XStretch", &xstretch);
|
||||
g_config->getOption("SDL.YStretch", &ystretch);
|
||||
g_config->getOption("SDL.LastXRes", &xres);
|
||||
g_config->getOption("SDL.LastYRes", &yres);
|
||||
g_config->getOption("SDL.ClipSides", &s_clipSides);
|
||||
g_config->getOption("SDL.NoFrame", &noframe);
|
||||
g_config->getOption("SDL.ShowFPS", &show_fps);
|
||||
|
||||
// check the starting, ending, and total scan lines
|
||||
FCEUI_GetCurrentVidSystem(&s_srendline, &s_erendline);
|
||||
s_tlines = s_erendline - s_srendline + 1;
|
||||
|
||||
// check if we should auto-set x/y resolution
|
||||
|
||||
// check for OpenGL and set the global flags
|
||||
#if OPENGL
|
||||
if(s_useOpenGL && !s_sponge) {
|
||||
flags = SDL_OPENGL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// initialize the SDL video subsystem if it is not already active
|
||||
if(!SDL_WasInit(SDL_INIT_VIDEO)) {
|
||||
error = SDL_InitSubSystem(SDL_INIT_VIDEO);
|
||||
if(error) {
|
||||
FCEUD_PrintError(SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
s_inited = 1;
|
||||
|
||||
// shows the cursor within the display window
|
||||
SDL_ShowCursor(1);
|
||||
|
||||
// determine if we can allocate the display on the video card
|
||||
vinf = SDL_GetVideoInfo();
|
||||
if(vinf->hw_available) {
|
||||
flags |= SDL_HWSURFACE;
|
||||
}
|
||||
|
||||
// get the monitor's current resolution if we do not already have it
|
||||
if(s_nativeWidth < 0) {
|
||||
s_nativeWidth = vinf->current_w;
|
||||
}
|
||||
if(s_nativeHeight < 0) {
|
||||
s_nativeHeight = vinf->current_h;
|
||||
}
|
||||
|
||||
// check to see if we are showing FPS
|
||||
FCEUI_SetShowFPS(show_fps);
|
||||
|
||||
// check if we are rendering fullscreen
|
||||
if(s_fullscreen) {
|
||||
int no_cursor;
|
||||
g_config->getOption("SDL.NoFullscreenCursor", &no_cursor);
|
||||
flags |= SDL_FULLSCREEN;
|
||||
SDL_ShowCursor(!no_cursor);
|
||||
}
|
||||
else {
|
||||
SDL_ShowCursor(1);
|
||||
}
|
||||
|
||||
if(noframe) {
|
||||
flags |= SDL_NOFRAME;
|
||||
}
|
||||
|
||||
// gives the SDL exclusive palette control... ensures the requested colors
|
||||
flags |= SDL_HWPALETTE;
|
||||
|
||||
// enable double buffering if requested and we have hardware support
|
||||
#ifdef OPENGL
|
||||
if(s_useOpenGL) {
|
||||
FCEU_printf("Initializing with OpenGL (Disable with '--opengl 0').\n");
|
||||
if(doublebuf) {
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if(doublebuf && (flags & SDL_HWSURFACE)) {
|
||||
flags |= SDL_DOUBLEBUF;
|
||||
}
|
||||
|
||||
if(s_fullscreen) {
|
||||
int desbpp, autoscale;
|
||||
g_config->getOption("SDL.BitsPerPixel", &desbpp);
|
||||
g_config->getOption("SDL.AutoScale", &autoscale);
|
||||
if (autoscale)
|
||||
{
|
||||
double auto_xscale = GetXScale(xres);
|
||||
double auto_yscale = GetYScale(yres);
|
||||
double native_ratio = ((double)NWIDTH) / s_tlines;
|
||||
double screen_ratio = ((double)xres) / yres;
|
||||
int keep_ratio;
|
||||
|
||||
g_config->getOption("SDL.KeepRatio", &keep_ratio);
|
||||
|
||||
// Try to choose resolution
|
||||
if (screen_ratio < native_ratio)
|
||||
{
|
||||
// The screen is narrower than the original. Maximizing width will not clip
|
||||
auto_xscale = auto_yscale = GetXScale(xres);
|
||||
if (keep_ratio)
|
||||
auto_yscale = GetYScale(yres);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto_yscale = auto_xscale = GetYScale(yres);
|
||||
if (keep_ratio)
|
||||
auto_xscale = GetXScale(xres);
|
||||
}
|
||||
s_exs = auto_xscale;
|
||||
s_eys = auto_yscale;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_config->getOption("SDL.XScale", &s_exs);
|
||||
g_config->getOption("SDL.YScale", &s_eys);
|
||||
}
|
||||
g_config->getOption("SDL.SpecialFX", &s_eefx);
|
||||
|
||||
#ifdef OPENGL
|
||||
if(!s_useOpenGL) {
|
||||
s_exs = (int)s_exs;
|
||||
s_eys = (int)s_eys;
|
||||
} else {
|
||||
desbpp = 0;
|
||||
}
|
||||
|
||||
|
||||
if((s_useOpenGL && !xstretch) || !s_useOpenGL)
|
||||
#endif
|
||||
if(xres < (NWIDTH * s_exs) || s_exs <= 0.01) {
|
||||
FCEUD_PrintError("xscale out of bounds.");
|
||||
KillVideo();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef OPENGL
|
||||
if((s_useOpenGL && !ystretch) || !s_useOpenGL)
|
||||
#endif
|
||||
if(yres < s_tlines * s_eys || s_eys <= 0.01) {
|
||||
FCEUD_PrintError("yscale out of bounds.");
|
||||
KillVideo();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef OPENGL
|
||||
s_screen = SDL_SetVideoMode(s_useOpenGL ? s_nativeWidth : xres,
|
||||
s_useOpenGL ? s_nativeHeight : yres,
|
||||
desbpp, flags);
|
||||
#else
|
||||
s_screen = SDL_SetVideoMode(xres, yres, desbpp, flags);
|
||||
#endif
|
||||
|
||||
if(!s_screen) {
|
||||
FCEUD_PrintError(SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
int desbpp;
|
||||
g_config->getOption("SDL.BitsPerPixel", &desbpp);
|
||||
|
||||
g_config->getOption("SDL.XScale", &s_exs);
|
||||
g_config->getOption("SDL.YScale", &s_eys);
|
||||
g_config->getOption("SDL.SpecialFX", &s_eefx);
|
||||
|
||||
// -Video Modes Tag-
|
||||
if(s_sponge) {
|
||||
if(s_sponge <= 3 && s_sponge >= 1)
|
||||
{
|
||||
s_exs = s_eys = 2;
|
||||
} else if (s_sponge >=4 && s_sponge <= 5)
|
||||
{
|
||||
s_exs = s_eys = 3;
|
||||
} else if (s_sponge >= 6 && s_sponge <= 8)
|
||||
{
|
||||
s_exs = s_eys = s_sponge - 4;
|
||||
}
|
||||
else if(s_sponge == 9)
|
||||
{
|
||||
s_exs = s_eys = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_exs = s_eys = 1;
|
||||
}
|
||||
if(s_sponge == 3) {
|
||||
xres = 301 * s_exs;
|
||||
}
|
||||
s_eefx = 0;
|
||||
if(s_sponge == 1 || s_sponge == 4) {
|
||||
desbpp = 32;
|
||||
}
|
||||
}
|
||||
|
||||
int scrw = NWIDTH * s_exs;
|
||||
if(s_sponge == 3) {
|
||||
scrw = 301 * s_exs;
|
||||
}
|
||||
|
||||
#ifdef OPENGL
|
||||
if(!s_useOpenGL) {
|
||||
s_exs = (int)s_exs;
|
||||
s_eys = (int)s_eys;
|
||||
}
|
||||
if(s_exs <= 0.01) {
|
||||
FCEUD_PrintError("xscale out of bounds.");
|
||||
KillVideo();
|
||||
return -1;
|
||||
}
|
||||
if(s_eys <= 0.01) {
|
||||
FCEUD_PrintError("yscale out of bounds.");
|
||||
KillVideo();
|
||||
return -1;
|
||||
}
|
||||
if(s_sponge && s_useOpenGL) {
|
||||
FCEUD_PrintError("scalers not compatible with openGL mode.");
|
||||
KillVideo();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_GTK) && defined(SDL_VIDEO_DRIVER_X11) && defined(GDK_WINDOWING_X11)
|
||||
if(noGui == 0)
|
||||
{
|
||||
while (gtk_events_pending())
|
||||
gtk_main_iteration_do(FALSE);
|
||||
|
||||
char SDL_windowhack[128];
|
||||
sprintf(SDL_windowhack, "SDL_WINDOWID=%u", (unsigned int)GDK_WINDOW_XID(gtk_widget_get_window(evbox)));
|
||||
SDL_putenv(SDL_windowhack);
|
||||
|
||||
// init SDL video
|
||||
if (SDL_WasInit(SDL_INIT_VIDEO))
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
if ( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0 )
|
||||
{
|
||||
fprintf(stderr, "Couldn't init SDL video: %s\n", SDL_GetError());
|
||||
gtk_main_quit();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
s_screen = SDL_SetVideoMode(scrw, (int)(s_tlines * s_eys),
|
||||
desbpp, flags);
|
||||
if(!s_screen) {
|
||||
FCEUD_PrintError(SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _GTK
|
||||
if(noGui == 0)
|
||||
{
|
||||
GtkRequisition req;
|
||||
gtk_widget_size_request(GTK_WIDGET(MainWindow), &req);
|
||||
gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
s_curbpp = s_screen->format->BitsPerPixel;
|
||||
if(!s_screen) {
|
||||
FCEUD_PrintError(SDL_GetError());
|
||||
KillVideo();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// XXX soules - this would be creating a surface on the video
|
||||
// card, but was commented out for some reason...
|
||||
s_BlitBuf = SDL_CreateRGBSurface(SDL_HWSURFACE, 256, 240,
|
||||
s_screen->format->BitsPerPixel,
|
||||
s_screen->format->Rmask,
|
||||
s_screen->format->Gmask,
|
||||
s_screen->format->Bmask, 0);
|
||||
#endif
|
||||
|
||||
FCEU_printf(" Video Mode: %d x %d x %d bpp %s\n",
|
||||
s_screen->w, s_screen->h, s_screen->format->BitsPerPixel,
|
||||
s_fullscreen ? "full screen" : "");
|
||||
|
||||
if(s_curbpp != 8 && s_curbpp != 16 && s_curbpp != 24 && s_curbpp != 32) {
|
||||
FCEU_printf(" Sorry, %dbpp modes are not supported by FCE Ultra. Supported bit depths are 8bpp, 16bpp, and 32bpp.\n", s_curbpp);
|
||||
KillVideo();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// if the game being run has a name, set it as the window name
|
||||
if(gi)
|
||||
{
|
||||
if(gi->name) {
|
||||
SDL_WM_SetCaption((const char *)gi->name, (const char *)gi->name);
|
||||
} else {
|
||||
SDL_WM_SetCaption(FCEU_NAME_AND_VERSION,"FCE Ultra");
|
||||
}
|
||||
}
|
||||
|
||||
// create the surface for displaying graphical messages
|
||||
#ifdef LSB_FIRST
|
||||
s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
|
||||
32, 32, 24, 32 * 3,
|
||||
0xFF, 0xFF00, 0xFF0000, 0x00);
|
||||
#else
|
||||
s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
|
||||
32, 32, 24, 32 * 3,
|
||||
0xFF0000, 0xFF00, 0xFF, 0x00);
|
||||
#endif
|
||||
SDL_WM_SetIcon(s_IconSurface,0);
|
||||
s_paletterefresh = 1;
|
||||
|
||||
// XXX soules - can't SDL do this for us?
|
||||
// if using more than 8bpp, initialize the conversion routines
|
||||
if(s_curbpp > 8) {
|
||||
InitBlitToHigh(s_curbpp >> 3,
|
||||
s_screen->format->Rmask,
|
||||
s_screen->format->Gmask,
|
||||
s_screen->format->Bmask,
|
||||
s_eefx, s_sponge, 0);
|
||||
#ifdef OPENGL
|
||||
if(s_useOpenGL)
|
||||
{
|
||||
int openGLip;
|
||||
g_config->getOption("SDL.OpenGLip", &openGLip);
|
||||
|
||||
if(!InitOpenGL(NOFFSET, 256 - (s_clipSides ? 8 : 0),
|
||||
s_srendline, s_erendline + 1,
|
||||
s_exs, s_eys, s_eefx,
|
||||
openGLip, xstretch, ystretch, s_screen))
|
||||
{
|
||||
FCEUD_PrintError("Error initializing OpenGL.");
|
||||
KillVideo();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Toggles the full-screen display.
|
||||
*/
|
||||
void ToggleFS()
|
||||
{
|
||||
// pause while we we are making the switch
|
||||
bool paused = FCEUI_EmulationPaused();
|
||||
if(!paused)
|
||||
FCEUI_ToggleEmulationPause();
|
||||
|
||||
int error, fullscreen = s_fullscreen;
|
||||
|
||||
// shut down the current video system
|
||||
KillVideo();
|
||||
|
||||
// flip the fullscreen flag
|
||||
g_config->setOption("SDL.Fullscreen", !fullscreen);
|
||||
#ifdef _GTK
|
||||
if(noGui == 0)
|
||||
{
|
||||
if(!fullscreen)
|
||||
showGui(0);
|
||||
else
|
||||
showGui(1);
|
||||
}
|
||||
#endif
|
||||
// try to initialize the video
|
||||
error = InitVideo(GameInfo);
|
||||
if(error) {
|
||||
// if we fail, just continue with what worked before
|
||||
g_config->setOption("SDL.Fullscreen", fullscreen);
|
||||
InitVideo(GameInfo);
|
||||
}
|
||||
// if we paused to make the switch; unpause
|
||||
if(!paused)
|
||||
FCEUI_ToggleEmulationPause();
|
||||
}
|
||||
|
||||
static SDL_Color s_psdl[256];
|
||||
|
||||
/**
|
||||
* Sets the color for a particular index in the palette.
|
||||
*/
|
||||
void
|
||||
FCEUD_SetPalette(uint8 index,
|
||||
uint8 r,
|
||||
uint8 g,
|
||||
uint8 b)
|
||||
{
|
||||
s_psdl[index].r = r;
|
||||
s_psdl[index].g = g;
|
||||
s_psdl[index].b = b;
|
||||
|
||||
s_paletterefresh = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the color for a particular index in the palette.
|
||||
*/
|
||||
void
|
||||
FCEUD_GetPalette(uint8 index,
|
||||
uint8 *r,
|
||||
uint8 *g,
|
||||
uint8 *b)
|
||||
{
|
||||
*r = s_psdl[index].r;
|
||||
*g = s_psdl[index].g;
|
||||
*b = s_psdl[index].b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes the palette structure into the underlying video subsystem.
|
||||
*/
|
||||
static void RedoPalette()
|
||||
{
|
||||
#ifdef OPENGL
|
||||
if(s_useOpenGL)
|
||||
SetOpenGLPalette((uint8*)s_psdl);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if(s_curbpp > 8) {
|
||||
SetPaletteBlitToHigh((uint8*)s_psdl);
|
||||
} else
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
//TODO - SDL2
|
||||
#else
|
||||
SDL_SetPalette(s_screen, SDL_PHYSPAL, s_psdl, 0, 256);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
// XXX soules - console lock/unlock unimplemented?
|
||||
|
||||
///Currently unimplemented.
|
||||
void LockConsole(){}
|
||||
|
||||
///Currently unimplemented.
|
||||
void UnlockConsole(){}
|
||||
|
||||
/**
|
||||
* Pushes the given buffer of bits to the screen.
|
||||
*/
|
||||
void
|
||||
BlitScreen(uint8 *XBuf)
|
||||
{
|
||||
SDL_Surface *TmpScreen;
|
||||
uint8 *dest;
|
||||
int xo = 0, yo = 0;
|
||||
|
||||
if(!s_screen) {
|
||||
return;
|
||||
}
|
||||
|
||||
// refresh the palette if required
|
||||
if(s_paletterefresh) {
|
||||
RedoPalette();
|
||||
s_paletterefresh = 0;
|
||||
}
|
||||
|
||||
#ifdef OPENGL
|
||||
// OpenGL is handled separately
|
||||
if(s_useOpenGL) {
|
||||
BlitOpenGL(XBuf);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// XXX soules - not entirely sure why this is being done yet
|
||||
XBuf += s_srendline * 256;
|
||||
|
||||
if(s_BlitBuf) {
|
||||
TmpScreen = s_BlitBuf;
|
||||
} else {
|
||||
TmpScreen = s_screen;
|
||||
}
|
||||
|
||||
// lock the display, if necessary
|
||||
if(SDL_MUSTLOCK(TmpScreen)) {
|
||||
if(SDL_LockSurface(TmpScreen) < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dest = (uint8*)TmpScreen->pixels;
|
||||
|
||||
if(s_fullscreen) {
|
||||
xo = (int)(((TmpScreen->w - NWIDTH * s_exs)) / 2);
|
||||
dest += xo * (s_curbpp >> 3);
|
||||
if(TmpScreen->h > (s_tlines * s_eys)) {
|
||||
yo = (int)((TmpScreen->h - s_tlines * s_eys) / 2);
|
||||
dest += yo * TmpScreen->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX soules - again, I'm surprised SDL can't handle this
|
||||
// perform the blit, converting bpp if necessary
|
||||
if(s_curbpp > 8) {
|
||||
if(s_BlitBuf) {
|
||||
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
|
||||
TmpScreen->pitch, 1, 1);
|
||||
} else {
|
||||
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
|
||||
TmpScreen->pitch, (int)s_exs, (int)s_eys);
|
||||
}
|
||||
} else {
|
||||
if(s_BlitBuf) {
|
||||
Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
|
||||
TmpScreen->pitch, 1, 1, 0, s_sponge);
|
||||
} else {
|
||||
Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
|
||||
TmpScreen->pitch, (int)s_exs, (int)s_eys,
|
||||
s_eefx, s_sponge);
|
||||
}
|
||||
}
|
||||
|
||||
// unlock the display, if necessary
|
||||
if(SDL_MUSTLOCK(TmpScreen)) {
|
||||
SDL_UnlockSurface(TmpScreen);
|
||||
}
|
||||
|
||||
int scrw;
|
||||
if(s_sponge == 3) { // NTSC 2x
|
||||
scrw = 301;
|
||||
} else {
|
||||
scrw = NWIDTH;
|
||||
}
|
||||
|
||||
// if we have a hardware video buffer, do a fast video->video copy
|
||||
if(s_BlitBuf) {
|
||||
SDL_Rect srect;
|
||||
SDL_Rect drect;
|
||||
|
||||
srect.x = 0;
|
||||
srect.y = 0;
|
||||
srect.w = scrw;
|
||||
srect.h = s_tlines;
|
||||
|
||||
drect.x = 0;
|
||||
drect.y = 0;
|
||||
drect.w = (Uint16)(s_exs * scrw);
|
||||
drect.h = (Uint16)(s_eys * s_tlines);
|
||||
|
||||
SDL_BlitSurface(s_BlitBuf, &srect, s_screen, &drect);
|
||||
}
|
||||
|
||||
// ensure that the display is updated
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
//TODO - SDL2
|
||||
#else
|
||||
SDL_UpdateRect(s_screen, xo, yo,
|
||||
(Uint32)(scrw * s_exs), (Uint32)(s_tlines * s_eys));
|
||||
#endif
|
||||
|
||||
#ifdef CREATE_AVI
|
||||
#if 0 /* PAL INTO NTSC HACK */
|
||||
{ int fps = FCEUI_GetDesiredFPS();
|
||||
if(FCEUI_GetDesiredFPS() == 838977920) fps = 1008307711;
|
||||
NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp);
|
||||
if(FCEUI_GetDesiredFPS() == 838977920)
|
||||
{
|
||||
static unsigned dup=0;
|
||||
if(++dup==5) { dup=0;
|
||||
NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); }
|
||||
} }
|
||||
#else
|
||||
{ int fps = FCEUI_GetDesiredFPS();
|
||||
static unsigned char* result = NULL;
|
||||
static unsigned resultsize = 0;
|
||||
int width = NWIDTH, height = s_tlines;
|
||||
if(!result || resultsize != width*height*3*2)
|
||||
{
|
||||
if(result) free(result);
|
||||
result = (unsigned char*) FCEU_dmalloc(resultsize = width*height*3*2);
|
||||
}
|
||||
switch(s_curbpp)
|
||||
{
|
||||
#if 0
|
||||
case 24: case 32: case 15: case 16:
|
||||
/* Convert to I420 if possible, because our I420 conversion is optimized
|
||||
* and it'll produce less network traffic, hence faster throughput than
|
||||
* anything else. And H.264 eats only I420, so it'd be converted sooner
|
||||
* or later anyway if we didn't do it. Win-win situation.
|
||||
*/
|
||||
switch(s_curbpp)
|
||||
{
|
||||
case 32: Convert32To_I420Frame(s_screen->pixels, &result[0], width*height, width); break;
|
||||
case 24: Convert24To_I420Frame(s_screen->pixels, &result[0], width*height, width); break;
|
||||
case 15: Convert15To_I420Frame(s_screen->pixels, &result[0], width*height, width); break;
|
||||
case 16: Convert16To_I420Frame(s_screen->pixels, &result[0], width*height, width); break;
|
||||
}
|
||||
NESVideoLoggingVideo(&result[0], width,height, fps, 12);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if REALTIME_LOGGING
|
||||
{
|
||||
static struct timeval last_time;
|
||||
static int first_time=1;
|
||||
extern long soundrate;
|
||||
|
||||
struct timeval cur_time;
|
||||
gettimeofday(&cur_time, NULL);
|
||||
|
||||
double timediff =
|
||||
(cur_time.tv_sec *1e6 + cur_time.tv_usec
|
||||
- (last_time.tv_sec *1e6 + last_time.tv_usec)) / 1e6;
|
||||
|
||||
int nframes = timediff * 60 - 1;
|
||||
if(first_time)
|
||||
first_time = 0;
|
||||
else while(nframes > 0)
|
||||
{
|
||||
static const unsigned char Buf[800*4] = {0};
|
||||
NESVideoLoggingVideo(screen->pixels, 256,tlines, FCEUI_GetDesiredFPS(), s_curbpp);
|
||||
NESVideoLoggingAudio(Buf, soundrate,16,1, soundrate/60.0);
|
||||
--nframes;
|
||||
}
|
||||
memcpy(&last_time, &cur_time, sizeof(last_time));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
// TODO
|
||||
#else
|
||||
// have to flip the displayed buffer in the case of double buffering
|
||||
if(s_screen->flags & SDL_DOUBLEBUF) {
|
||||
SDL_Flip(s_screen);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an x-y coordinate in the window manager into an x-y
|
||||
* coordinate on FCEU's screen.
|
||||
*/
|
||||
uint32
|
||||
PtoV(uint16 x,
|
||||
uint16 y)
|
||||
{
|
||||
y = (uint16)((double)y / s_eys);
|
||||
x = (uint16)((double)x / s_exs);
|
||||
if(s_clipSides) {
|
||||
x += 8;
|
||||
}
|
||||
y += s_srendline;
|
||||
return (x | (y << 16));
|
||||
}
|
||||
|
||||
bool enableHUDrecording = false;
|
||||
bool FCEUI_AviEnableHUDrecording()
|
||||
{
|
||||
if (enableHUDrecording)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
void FCEUI_SetAviEnableHUDrecording(bool enable)
|
||||
{
|
||||
enableHUDrecording = enable;
|
||||
}
|
||||
|
||||
bool disableMovieMessages = false;
|
||||
bool FCEUI_AviDisableMovieMessages()
|
||||
{
|
||||
if (disableMovieMessages)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
void FCEUI_SetAviDisableMovieMessages(bool disable)
|
||||
{
|
||||
disableMovieMessages = disable;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#ifndef __FCEU_SDL_VIDEO_H
|
||||
#define __FCEU_SDL_VIDEO_H
|
||||
#ifdef _SDL2
|
||||
#include <SDL2/SDL.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
uint32 PtoV(uint16 x, uint16 y);
|
||||
bool FCEUD_ShouldDrawInputAids();
|
||||
bool FCEUI_AviDisableMovieMessages();
|
||||
static SDL_Surface *s_screen;
|
||||
bool FCEUI_AviEnableHUDrecording();
|
||||
void FCEUI_SetAviEnableHUDrecording(bool enable);
|
||||
bool FCEUI_AviDisableMovieMessages();
|
||||
void FCEUI_SetAviDisableMovieMessages(bool disable);
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,15 +1,15 @@
|
||||
#ifndef __FCEU_SDL_H
|
||||
#define __FCEU_SDL_H
|
||||
|
||||
#if _SDL2
|
||||
#include <SDL2/SDL.h>
|
||||
#else
|
||||
//#if _SDL2
|
||||
//#include <SDL2/SDL.h>
|
||||
//#else
|
||||
//#include <SDL.h>
|
||||
#endif
|
||||
//#endif
|
||||
|
||||
#include "main.h"
|
||||
#include "dface.h"
|
||||
#include "input.h"
|
||||
//#include "dface.h"
|
||||
//#include "input.h"
|
||||
|
||||
// I'm using this as a #define so the compiler can optimize the
|
||||
// modulo operation
|
||||
@@ -24,7 +24,7 @@ extern int dendy;
|
||||
extern int pal_emulation;
|
||||
extern bool swapDuty;
|
||||
|
||||
int LoadGame(const char *path);
|
||||
int LoadGame(const char *path, bool silent = false);
|
||||
int CloseGame(void);
|
||||
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count);
|
||||
uint64 FCEUD_GetTime();
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
void RefreshThrottleFPS();
|
||||
int SpeedThrottle(void);
|
||||
@@ -1,360 +0,0 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
//todo - ensure that #ifdef WIN32 makes sense
|
||||
//consider changing this to use sdl net stuff?
|
||||
|
||||
#include "main.h"
|
||||
#include "input.h"
|
||||
#include "dface.h"
|
||||
#include "unix-netplay.h"
|
||||
|
||||
#include "../../fceu.h"
|
||||
#include "../../utils/md5.h"
|
||||
#include "../../utils/memory.h"
|
||||
|
||||
#include <string>
|
||||
#include "../common/configSys.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
extern Config *g_config;
|
||||
|
||||
#ifndef socklen_t
|
||||
#define socklen_t int
|
||||
#endif
|
||||
|
||||
#ifndef SOL_TCP
|
||||
#define SOL_TCP IPPROTO_TCP
|
||||
#endif
|
||||
|
||||
int FCEUDnetplay=0;
|
||||
|
||||
static int s_Socket = -1;
|
||||
|
||||
static void
|
||||
en32(uint8 *buf,
|
||||
uint32 morp)
|
||||
{
|
||||
buf[0] = morp;
|
||||
buf[1] = morp >> 8;
|
||||
buf[2] = morp >> 16;
|
||||
buf[3] = morp >> 24;
|
||||
}
|
||||
|
||||
/*
|
||||
static uint32 de32(uint8 *morp)
|
||||
{
|
||||
return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
FCEUD_NetworkConnect(void)
|
||||
{
|
||||
struct sockaddr_in sockin;
|
||||
struct hostent *phostentb;
|
||||
unsigned long hadr;
|
||||
int TSocket, tcpopt, error;
|
||||
int netdivisor;
|
||||
|
||||
// get any required configuration variables
|
||||
int port, localPlayers;
|
||||
std::string server, username, password, key;
|
||||
g_config->getOption("SDL.NetworkIP", &server);
|
||||
g_config->getOption("SDL.NetworkUsername", &username);
|
||||
g_config->getOption("SDL.NetworkPassword", &password);
|
||||
g_config->getOption("SDL.NetworkGameKey", &key);
|
||||
g_config->getOption("SDL.NetworkPort", &port);
|
||||
g_config->getOption("SDL.NetworkPlayers", &localPlayers);
|
||||
|
||||
|
||||
g_config->setOption("SDL.NetworkIP", "");
|
||||
g_config->setOption("SDL.NetworkPassword", "");
|
||||
g_config->setOption("SDL.NetworkGameKey", "");
|
||||
|
||||
|
||||
|
||||
// only initialize if remote server is specified
|
||||
if(!server.size()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(TSocket < 0) {
|
||||
char* s = "Error creating stream socket.";
|
||||
puts(s);
|
||||
FCEU_DispMessage(s,0);
|
||||
FCEUD_NetworkClose();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// try to setup TCP_NODELAY to avoid network jitters
|
||||
tcpopt = 1;
|
||||
#ifdef BEOS
|
||||
error = setsockopt(TSocket, SOL_SOCKET, TCP_NODELAY, &tcpopt, sizeof(int));
|
||||
#elif WIN32
|
||||
error = setsockopt(TSocket, SOL_TCP, TCP_NODELAY,
|
||||
(char*)&tcpopt, sizeof(int));
|
||||
#else
|
||||
error = setsockopt(TSocket, SOL_TCP, TCP_NODELAY, &tcpopt, sizeof(int));
|
||||
#endif
|
||||
if(error) {
|
||||
puts("Nodelay fail");
|
||||
}
|
||||
|
||||
memset(&sockin, 0, sizeof(sockin));
|
||||
sockin.sin_family = AF_INET;
|
||||
hadr = inet_addr(server.c_str());
|
||||
if(hadr != INADDR_NONE) {
|
||||
sockin.sin_addr.s_addr = hadr;
|
||||
} else {
|
||||
puts("*** Looking up host name...");
|
||||
phostentb = gethostbyname(server.c_str());
|
||||
if(!phostentb) {
|
||||
puts("Error getting host network information.");
|
||||
FCEU_DispMessage("Error getting host info",0);
|
||||
close(TSocket);
|
||||
FCEUD_NetworkClose();
|
||||
return(0);
|
||||
}
|
||||
memcpy(&sockin.sin_addr, phostentb->h_addr, phostentb->h_length);
|
||||
}
|
||||
|
||||
sockin.sin_port = htons(port);
|
||||
puts("*** Connecting to remote host...");
|
||||
error = connect(TSocket, (struct sockaddr *)&sockin, sizeof(sockin));
|
||||
if(error < 0) {
|
||||
puts("Error connecting to remote host.");
|
||||
FCEU_DispMessage("Error connecting to server",0);
|
||||
close(TSocket);
|
||||
FCEUD_NetworkClose();
|
||||
return 0;
|
||||
}
|
||||
|
||||
s_Socket = TSocket;
|
||||
|
||||
puts("*** Sending initialization data to server...");
|
||||
uint8 *sendbuf;
|
||||
uint8 buf[5];
|
||||
uint32 sblen;
|
||||
|
||||
sblen = 4 + 16 + 16 + 64 + 1 + username.size();
|
||||
sendbuf = (uint8 *)FCEU_dmalloc(sblen);
|
||||
memset(sendbuf, 0, sblen);
|
||||
|
||||
// XXX soules - should use htons instead of en32() from above!
|
||||
//uint32 data = htons(sblen - 4);
|
||||
//memcpy(sendbuf, &data, sizeof(data));
|
||||
en32(sendbuf, sblen - 4);
|
||||
|
||||
if(key.size())
|
||||
{
|
||||
struct md5_context md5;
|
||||
uint8 md5out[16];
|
||||
|
||||
md5_starts(&md5);
|
||||
md5_update(&md5, (uint8*)&GameInfo->MD5.data, 16);
|
||||
md5_update(&md5, (uint8 *)key.c_str(), key.size());
|
||||
md5_finish(&md5, md5out);
|
||||
memcpy(sendbuf + 4, md5out, 16);
|
||||
} else
|
||||
{
|
||||
memcpy(sendbuf + 4, (uint8*)&GameInfo->MD5.data, 16);
|
||||
}
|
||||
|
||||
if(password.size()) {
|
||||
struct md5_context md5;
|
||||
uint8 md5out[16];
|
||||
|
||||
md5_starts(&md5);
|
||||
md5_update(&md5, (uint8 *)password.c_str(), password.size());
|
||||
md5_finish(&md5, md5out);
|
||||
memcpy(sendbuf + 4 + 16, md5out, 16);
|
||||
}
|
||||
|
||||
memset(sendbuf + 4 + 16 + 16, 0, 64);
|
||||
|
||||
sendbuf[4 + 16 + 16 + 64] = (uint8)localPlayers;
|
||||
|
||||
if(username.size()) {
|
||||
memcpy(sendbuf + 4 + 16 + 16 + 64 + 1,
|
||||
username.c_str(), username.size());
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
send(s_Socket, (char*)sendbuf, sblen, 0);
|
||||
#else
|
||||
send(s_Socket, sendbuf, sblen, 0);
|
||||
#endif
|
||||
FCEU_dfree(sendbuf);
|
||||
|
||||
#ifdef WIN32
|
||||
recv(s_Socket, (char*)buf, 1, 0);
|
||||
#else
|
||||
recv(s_Socket, buf, 1, MSG_WAITALL);
|
||||
#endif
|
||||
netdivisor = buf[0];
|
||||
|
||||
puts("*** Connection established.");
|
||||
FCEU_DispMessage("Connection established.",0);
|
||||
|
||||
FCEUDnetplay = 1;
|
||||
FCEUI_NetplayStart(localPlayers, netdivisor);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
FCEUD_SendData(void *data,
|
||||
uint32 len)
|
||||
{
|
||||
int check = 0, error = 0;
|
||||
#ifndef WIN32
|
||||
error = ioctl(fileno(stdin), FIONREAD, &check);
|
||||
#endif
|
||||
if(!error && check) {
|
||||
char buf[1024];
|
||||
char *f;
|
||||
fgets(buf, 1024, stdin);
|
||||
if((f=strrchr(buf,'\n'))) {
|
||||
*f = 0;
|
||||
}
|
||||
FCEUI_NetplayText((uint8 *)buf);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
send(s_Socket, (char*)data, len ,0);
|
||||
#else
|
||||
send(s_Socket, data, len ,0);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
FCEUD_RecvData(void *data,
|
||||
uint32 len)
|
||||
{
|
||||
int size;
|
||||
NoWaiting &= ~2;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
fd_set funfun;
|
||||
struct timeval popeye;
|
||||
|
||||
popeye.tv_sec=0;
|
||||
popeye.tv_usec=100000;
|
||||
|
||||
FD_ZERO(&funfun);
|
||||
FD_SET(s_Socket, &funfun);
|
||||
|
||||
switch(select(s_Socket + 1,&funfun,0,0,&popeye)) {
|
||||
case 0: continue;
|
||||
case -1:return 0;
|
||||
}
|
||||
|
||||
if(FD_ISSET(s_Socket,&funfun)) {
|
||||
#ifdef WIN32
|
||||
size = recv(s_Socket, (char*)data, len, 0);
|
||||
#else
|
||||
size = recv(s_Socket, data, len, MSG_WAITALL);
|
||||
#endif
|
||||
|
||||
if(size == len) {
|
||||
//unsigned long beefie;
|
||||
|
||||
FD_ZERO(&funfun);
|
||||
FD_SET(s_Socket, &funfun);
|
||||
|
||||
popeye.tv_sec = popeye.tv_usec = 0;
|
||||
if(select(s_Socket + 1, &funfun, 0, 0, &popeye) == 1)
|
||||
//if(!ioctl(s_Socket,FIONREAD,&beefie))
|
||||
// if(beefie)
|
||||
{
|
||||
NoWaiting|=2;
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
FCEUD_NetworkClose(void)
|
||||
{
|
||||
if(s_Socket > 0) {
|
||||
#ifdef BEOS
|
||||
closesocket(s_Socket);
|
||||
#else
|
||||
close(s_Socket);
|
||||
#endif
|
||||
}
|
||||
s_Socket = -1;
|
||||
|
||||
if(FCEUDnetplay) {
|
||||
FCEUI_NetplayStop();
|
||||
}
|
||||
FCEUDnetplay = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FCEUD_NetplayText(uint8 *text)
|
||||
{
|
||||
char *tot = (char *)FCEU_dmalloc(strlen((const char *)text) + 1);
|
||||
char *tmp;
|
||||
if (!tot)
|
||||
return;
|
||||
strcpy(tot, (const char *)text);
|
||||
tmp = tot;
|
||||
|
||||
while(*tmp) {
|
||||
if(*tmp < 0x20) {
|
||||
*tmp = ' ';
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
puts(tot);
|
||||
FCEU_dfree(tot);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
extern char *netplaynick;
|
||||
extern char *netplayhost;
|
||||
extern char *netpassword;
|
||||
extern char *netgamekey;
|
||||
extern int tport;
|
||||
extern int netlocalplayers;
|
||||
@@ -1,14 +0,0 @@
|
||||
my_list = Split("""
|
||||
nesvideos-piece.cpp
|
||||
rgbtorgb.cpp
|
||||
""")
|
||||
|
||||
Import('env')
|
||||
|
||||
if env['LOGO']:
|
||||
env.Append(CCFLAGS = "-DHAVE_GD")
|
||||
|
||||
for x in range(len(my_list)):
|
||||
my_list[x] = 'drivers/videolog/' + my_list[x]
|
||||
Return('my_list')
|
||||
|
||||
@@ -828,7 +828,7 @@ extern "C"
|
||||
|| new_height != LogoInfo::height)
|
||||
{
|
||||
if(new_height < LogoInfo::height || new_height > LogoInfo::height+20)
|
||||
fprintf(stderr, "'%s': ERROR, expected %dx%d, got %dx%d\n", fn,
|
||||
fprintf(stderr, "'%s': ERROR, expected %ux%u, got %ux%u\n", fn,
|
||||
LogoInfo::width, LogoInfo::height,
|
||||
new_width, new_height);
|
||||
}
|
||||
@@ -857,7 +857,7 @@ extern "C"
|
||||
std::string avdir = "/home/you/yourlogo/";
|
||||
|
||||
char AvName[512];
|
||||
sprintf(AvName, "logo_%d_%d_f%03u.png",
|
||||
sprintf(AvName, "logo_%u_%u_f%03u.png",
|
||||
LogoInfo::width,
|
||||
LogoInfo::height,
|
||||
frameno);
|
||||
|
||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user