Compare commits
25 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 | |||
| cf62e4485d | |||
| 386ca2848a | |||
| a8a134743c |
Binary file not shown.
+119
-1079
File diff suppressed because it is too large
Load Diff
+413
-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)
|
||||
{
|
||||
@@ -462,7 +793,10 @@ uint64 FCEUD_GetTime(void) {return 0;}
|
||||
uint64 FCEUD_GetTimeFreq(void) {return 0;}
|
||||
const char *GetKeyboard(void) {return "";}
|
||||
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;}
|
||||
@@ -499,14 +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
|
||||
|
||||
+6
-4
@@ -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.2</string>
|
||||
<string>2.6.3</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>OEGameCoreController</string>
|
||||
<key>OEGameCoreClass</key>
|
||||
@@ -27,11 +27,13 @@
|
||||
<key>openemu.system.nes</key>
|
||||
<dict>
|
||||
<key>OEGameCoreRewindBufferSeconds</key>
|
||||
<integer>3600</integer>
|
||||
<integer>60</integer>
|
||||
<key>OEGameCoreRewindInterval</key>
|
||||
<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')
|
||||
+17
-10
@@ -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,20 +272,27 @@ 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; \
|
||||
(a) = GetMem((a)) | (GetMem((a)+1))<<8; \
|
||||
(a) = GetMem((a)) | (GetMem(((a)+1)&0xff))<<8; \
|
||||
}
|
||||
#define indirectY(a) { \
|
||||
(a) = GetMem(opcode[1]) | (GetMem(opcode[1]+1))<<8; \
|
||||
(a) = GetMem(opcode[1]) | (GetMem((opcode[1]+1)&0xff))<<8; \
|
||||
(a) += RY; \
|
||||
}
|
||||
|
||||
|
||||
#ifdef BRK_3BYTE_HACK
|
||||
case 0x00:
|
||||
sprintf(str,"BRK %02X %02X", opcode[1], opcode[2]);
|
||||
break;
|
||||
#else
|
||||
case 0x00: strcpy(str,"BRK"); break;
|
||||
#endif
|
||||
|
||||
//odd, 1-byte opcodes
|
||||
case 0x00: strcpy(str,"BRK"); break;
|
||||
case 0x08: strcpy(str,"PHP"); break;
|
||||
case 0x0A: strcpy(str,"ASL"); break;
|
||||
case 0x18: strcpy(str,"CLC"); break;
|
||||
@@ -353,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;
|
||||
|
||||
@@ -450,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;
|
||||
@@ -508,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
|
||||
|
||||
+90
-89
@@ -1,89 +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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
|
||||
+21
-18
@@ -17,43 +17,45 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* 7-in-1 Darkwing Duck, Snake, MagicBlock (PCB marked as "12 in 1")
|
||||
* 7-in-1 Darkwing Duck, Snake, MagicBlock (PCB marked as "12 in 1")
|
||||
* 12-in-1 1991 New Star Co. Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 reg[4];
|
||||
static uint8 prgchr[2], ctrl;
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ reg, 4, "REGS" },
|
||||
{ prgchr, 2, "REGS" },
|
||||
{ &ctrl, 1, "CTRL" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
uint8 bank = (reg[3] & 3) << 3;
|
||||
setchr4(0x0000, (reg[1] >> 3) | (bank << 2));
|
||||
setchr4(0x1000, (reg[2] >> 3) | (bank << 2));
|
||||
if (reg[3] & 8) {
|
||||
setprg32(0x8000, ((reg[2] & 7) >> 1) | bank);
|
||||
uint8 bank = (ctrl & 3) << 3;
|
||||
setchr4(0x0000, (prgchr[0] >> 3) | (bank << 2));
|
||||
setchr4(0x1000, (prgchr[1] >> 3) | (bank << 2));
|
||||
if (ctrl & 8) {
|
||||
setprg16(0x8000, bank | (prgchr[0] & 6) | 0); // actually, both 0 and 1 registers used, but they will switch each PA12 transition
|
||||
setprg16(0xc000, bank | (prgchr[0] & 6) | 1); // if bits are different for both registers, so they must be programmed strongly the same!
|
||||
} else {
|
||||
setprg16(0x8000, (reg[1] & 7) | bank);
|
||||
setprg16(0xc000, 7 | bank);
|
||||
setprg16(0x8000, bank | (prgchr[0] & 7));
|
||||
setprg16(0xc000, bank | 7 );
|
||||
}
|
||||
setmirror(((reg[3] & 4) >> 2) ^ 1);
|
||||
setmirror(((ctrl & 4) >> 2) ^ 1);
|
||||
}
|
||||
|
||||
static DECLFW(BMC12IN1Write) {
|
||||
switch (A) {
|
||||
case 0xafff: reg[0] = V; break;
|
||||
case 0xbfff: reg[1] = V; break;
|
||||
case 0xdfff: reg[2] = V; break;
|
||||
case 0xefff: reg[3] = V; break;
|
||||
switch (A & 0xE000) {
|
||||
case 0xA000: prgchr[0] = V; Sync(); break;
|
||||
case 0xC000: prgchr[1] = V; Sync(); break;
|
||||
case 0xE000: ctrl = V & 0x0F; Sync(); break;
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMC12IN1Power(void) {
|
||||
reg[0] = reg[1] = reg[2] = reg[3] = 0;
|
||||
prgchr[0] = prgchr[1] = ctrl = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, BMC12IN1Write);
|
||||
@@ -68,3 +70,4 @@ void BMC12IN1_Init(CartInfo *info) {
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
+19
-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,12 +78,12 @@ 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);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M15Write);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
Sync();
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ static void M156Power(void) {
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetWriteHandler(0xC000, 0xCFFF, M156Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M156Close(void) {
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2015 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
|
||||
*
|
||||
* "Blood Of Jurassic" protected MMC3 based board (GD-98 Cart ID, 158B PCB ID)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 lut[8] = { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0F, 0x00 };
|
||||
|
||||
static void UNL158BPW(uint32 A, uint8 V) {
|
||||
if (EXPREGS[0] & 0x80) {
|
||||
uint32 bank = EXPREGS[0] & 7;
|
||||
if(EXPREGS[0] & 0x20) { // 32Kb mode
|
||||
setprg32(0x8000, bank >> 1);
|
||||
} else { // 16Kb mode
|
||||
setprg16(0x8000, bank);
|
||||
setprg16(0xC000, bank);
|
||||
}
|
||||
} else {
|
||||
setprg8(A, V & 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(UNL158BProtWrite) {
|
||||
EXPREGS[A & 7] = V;
|
||||
switch(A & 7) {
|
||||
case 0:
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
break;
|
||||
case 7:
|
||||
FCEU_printf("UNK PROT WRITE\n");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static DECLFR(UNL158BProtRead) {
|
||||
return X.DB | lut[A & 7];
|
||||
}
|
||||
|
||||
static void UNL158BPower(void) {
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x5000, 0x5FFF, UNL158BProtWrite);
|
||||
SetReadHandler(0x5000, 0x5FFF, UNL158BProtRead);
|
||||
}
|
||||
|
||||
void UNL158B_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 128, 128, 0, 0);
|
||||
pwrap = UNL158BPW;
|
||||
info->Power = UNL158BPower;
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
}
|
||||
+232
-229
@@ -1,229 +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);
|
||||
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();
|
||||
}
|
||||
|
||||
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 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);
|
||||
}
|
||||
/* 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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
+2
-2
@@ -55,7 +55,7 @@ static void M168Power(void) {
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
}
|
||||
|
||||
static void MNNNClose(void) {
|
||||
static void M168Close(void) {
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
@@ -67,7 +67,7 @@ static void StateRestore(int version) {
|
||||
|
||||
void Mapper168_Init(CartInfo *info) {
|
||||
info->Power = M168Power;
|
||||
info->Close = MNNNClose;
|
||||
info->Close = M168Close;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
|
||||
|
||||
+6
-5
@@ -111,15 +111,16 @@ static DECLFW(M176Write_WriteSRAM)
|
||||
|
||||
static void M176Power(void)
|
||||
{
|
||||
SetReadHandler(0x6000,0x7fff,CartBR);
|
||||
SetWriteHandler(0x6000,0x7fff,M176Write_WriteSRAM);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetReadHandler(0x6000,0x7fff,CartBR);
|
||||
SetWriteHandler(0x6000,0x7fff,M176Write_WriteSRAM);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0xA001,0xA001,M176Write_A001);
|
||||
SetWriteHandler(0x5001,0x5001,M176Write_5001);
|
||||
SetWriteHandler(0x5010,0x5010,M176Write_5010);
|
||||
SetWriteHandler(0x5011,0x5011,M176Write_5011);
|
||||
SetWriteHandler(0x5ff1,0x5ff1,M176Write_5FF1);
|
||||
SetWriteHandler(0x5ff2,0x5ff2,M176Write_5FF2);
|
||||
SetWriteHandler(0x5ff1,0x5ff1,M176Write_5FF1);
|
||||
SetWriteHandler(0x5ff2,0x5ff2,M176Write_5FF2);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
|
||||
we_sram = 0;
|
||||
sbw = 0;
|
||||
|
||||
@@ -50,6 +50,7 @@ static void M177Power(void) {
|
||||
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M177Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M177Close(void) {
|
||||
|
||||
+70
-45
@@ -29,10 +29,16 @@ static uint8 reg[4];
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
|
||||
// Tennis with VR sensor, very simple behaviour
|
||||
extern void GetMouseData(uint32 (&md)[3]);
|
||||
static uint32 MouseData[3], click, lastclick;
|
||||
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[] =
|
||||
{
|
||||
@@ -40,41 +46,41 @@ static SFORMAT StateRegs[] =
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static int16 step_size[49] = {
|
||||
16, 17, 19, 21, 23, 25, 28, 31, 34, 37,
|
||||
41, 45, 50, 55, 60, 66, 73, 80, 88, 97,
|
||||
107, 118, 130, 143, 157, 173, 190, 209, 230, 253,
|
||||
279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
|
||||
724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
|
||||
}; //49 items
|
||||
static int32 step_adj[16] = { -1, -1, -1, -1, 2, 5, 7, 9, -1, -1, -1, -1, 2, 5, 7, 9 };
|
||||
//static int16 step_size[49] = {
|
||||
// 16, 17, 19, 21, 23, 25, 28, 31, 34, 37,
|
||||
// 41, 45, 50, 55, 60, 66, 73, 80, 88, 97,
|
||||
// 107, 118, 130, 143, 157, 173, 190, 209, 230, 253,
|
||||
// 279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
|
||||
// 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
|
||||
//}; //49 items
|
||||
//static int32 step_adj[16] = { -1, -1, -1, -1, 2, 5, 7, 9, -1, -1, -1, -1, 2, 5, 7, 9 };
|
||||
|
||||
//decode stuff
|
||||
static int32 jedi_table[16 * 49];
|
||||
static int32 acc = 0; //ADPCM accumulator, initial condition must be 0
|
||||
static int32 decstep = 0; //ADPCM decoding step, initial condition must be 0
|
||||
//static int32 jedi_table[16 * 49];
|
||||
//static int32 acc = 0; //ADPCM accumulator, initial condition must be 0
|
||||
//static int32 decstep = 0; //ADPCM decoding step, initial condition must be 0
|
||||
|
||||
static void jedi_table_init() {
|
||||
int step, nib;
|
||||
//static void jedi_table_init() {
|
||||
// int step, nib;
|
||||
//
|
||||
// for (step = 0; step < 49; step++) {
|
||||
// for (nib = 0; nib < 16; nib++) {
|
||||
// int value = (2 * (nib & 0x07) + 1) * step_size[step] / 8;
|
||||
// jedi_table[step * 16 + nib] = ((nib & 0x08) != 0) ? -value : value;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
for (step = 0; step < 49; step++) {
|
||||
for (nib = 0; nib < 16; nib++) {
|
||||
int value = (2 * (nib & 0x07) + 1) * step_size[step] / 8;
|
||||
jedi_table[step * 16 + nib] = ((nib & 0x08) != 0) ? -value : value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8 decode(uint8 code) {
|
||||
acc += jedi_table[decstep + code];
|
||||
if ((acc & ~0x7ff) != 0) // acc is > 2047
|
||||
acc |= ~0xfff;
|
||||
else acc &= 0xfff;
|
||||
decstep += step_adj[code & 7] * 16;
|
||||
if (decstep < 0) decstep = 0;
|
||||
if (decstep > 48 * 16) decstep = 48 * 16;
|
||||
return (acc >> 8) & 0xff;
|
||||
}
|
||||
//static uint8 decode(uint8 code) {
|
||||
// acc += jedi_table[decstep + code];
|
||||
// if ((acc & ~0x7ff) != 0) // acc is > 2047
|
||||
// acc |= ~0xfff;
|
||||
// else acc &= 0xfff;
|
||||
// decstep += step_adj[code & 7] * 16;
|
||||
// if (decstep < 0) decstep = 0;
|
||||
// if (decstep > 48 * 16) decstep = 48 * 16;
|
||||
// return (acc >> 8) & 0xff;
|
||||
//}
|
||||
|
||||
static void Sync(void) {
|
||||
uint32 sbank = reg[1] & 0x7;
|
||||
@@ -109,11 +115,11 @@ static DECLFW(M178WriteSnd) {
|
||||
if (V & 0xF0) {
|
||||
pcm_enable = 1;
|
||||
// pcmwrite(0x4011, (V & 0xF) << 3);
|
||||
pcmwrite(0x4011, decode(V & 0xf));
|
||||
// pcmwrite(0x4011, decode(V & 0xf));
|
||||
} else
|
||||
pcm_enable = 0;
|
||||
} else
|
||||
FCEU_printf("misc %04x:%02x\n", A, V);
|
||||
}// else
|
||||
// FCEU_printf("misc %04x:%02x\n", A, V);
|
||||
}
|
||||
|
||||
static DECLFR(M178ReadSnd) {
|
||||
@@ -123,26 +129,45 @@ static DECLFR(M178ReadSnd) {
|
||||
return X.DB;
|
||||
}
|
||||
|
||||
static DECLFR(M178ReadSensor) {
|
||||
X6502_IRQEnd(FCEU_IQEXT); // hacky-hacky, actual reg is 6000 and it clear IRQ while reading, but then I need another mapper lol
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
static void M178Power(void) {
|
||||
reg[0] = reg[1] = reg[2] = reg[3] = 0;
|
||||
reg[0] = reg[1] = reg[2] = reg[3] = SensorDelay = 0;
|
||||
Sync();
|
||||
pcmwrite = GetWriteHandler(0x4011);
|
||||
// pcmwrite = GetWriteHandler(0x4011);
|
||||
SetWriteHandler(0x4800, 0x4fff, M178Write);
|
||||
SetWriteHandler(0x5800, 0x5fff, M178WriteSnd);
|
||||
SetReadHandler(0x5800, 0x5fff, M178ReadSnd);
|
||||
SetReadHandler(0x5000, 0x5000, M178ReadSensor);
|
||||
SetReadHandler(0x6000, 0x7fff, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M178SndClk(int a) {
|
||||
if (pcm_enable) {
|
||||
pcm_latch -= a;
|
||||
if (pcm_latch <= 0) {
|
||||
pcm_latch += pcm_clock;
|
||||
pcm_enable = 0;
|
||||
}
|
||||
SensorDelay += a;
|
||||
if(SensorDelay > 0x32768) {
|
||||
SensorDelay -= 32768;
|
||||
GetMouseData (MouseData);
|
||||
lastclick = click;
|
||||
click = MouseData[2] & 1; // to prevent from continuos IRQ trigger if button is held.
|
||||
// actual circuit is just a D-C-R edge detector for IR-sensor
|
||||
// triggered by the active IR bat.
|
||||
if(lastclick && !click)
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
|
||||
// if (pcm_enable) {
|
||||
// pcm_latch -= a;
|
||||
// if (pcm_latch <= 0) {
|
||||
// pcm_latch += pcm_clock;
|
||||
// pcm_enable = 0;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
static void M178Close(void) {
|
||||
@@ -161,7 +186,7 @@ void Mapper178_Init(CartInfo *info) {
|
||||
GameStateRestore = StateRestore;
|
||||
MapIRQHook = M178SndClk;
|
||||
|
||||
jedi_table_init();
|
||||
// jedi_table_init();
|
||||
|
||||
WRAMSIZE = 32768;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
|
||||
@@ -89,6 +89,7 @@ static void M18Power(void) {
|
||||
SetWriteHandler(0x8000, 0x9FFF, M18WritePrg);
|
||||
SetWriteHandler(0xA000, 0xDFFF, M18WriteChr);
|
||||
SetWriteHandler(0xE000, 0xFFFF, M18WriteIRQ);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M18IRQHook(int a) {
|
||||
|
||||
@@ -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"
|
||||
@@ -69,6 +96,7 @@ static void M186Power(void) {
|
||||
SetWriteHandler(0x4200, 0x43FF, M186Write);
|
||||
SetReadHandler(0x4400, 0x4FFF, ASWRAM);
|
||||
SetWriteHandler(0x4400, 0x4FFF, BSWRAM);
|
||||
FCEU_CheatAddRAM(32, 0x6000, WRAM);
|
||||
regs[0] = regs[1] = regs[2] = regs[3];
|
||||
Sync();
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
+12
-2
@@ -39,7 +39,7 @@ static void Sync(void) {
|
||||
} else
|
||||
setprg32(0x8000, prg >> 1);
|
||||
setchr8(chr);
|
||||
setmirror(mirr);
|
||||
setmirror(mirr ^ 1);
|
||||
}
|
||||
|
||||
static DECLFW(M225Write) {
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ static void M246Power(void) {
|
||||
SetReadHandler(0x6800, 0x6FFF, CartBR);
|
||||
SetWriteHandler(0x6800, 0x6FFF, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M246Close(void)
|
||||
|
||||
@@ -80,6 +80,7 @@ static void M252Power(void) {
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M252Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M252IRQ(int a) {
|
||||
|
||||
@@ -96,6 +96,7 @@ static void M253Power(void) {
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M253Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M253Close(void) {
|
||||
|
||||
+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;
|
||||
|
||||
@@ -75,6 +75,7 @@ static void M32Power(void) {
|
||||
SetWriteHandler(0x9000, 0x9FFF, M32Write1);
|
||||
SetWriteHandler(0xA000, 0xAFFF, M32Write2);
|
||||
SetWriteHandler(0xB000, 0xBFFF, M32Write3);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M32Close(void)
|
||||
|
||||
@@ -66,6 +66,7 @@ static void M34Power(void) {
|
||||
SetWriteHandler(0x6000, 0x7ffc, CartBW);
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x7ffd, 0xffff, M34Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M34Close(void) {
|
||||
|
||||
+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();
|
||||
}
|
||||
|
||||
@@ -134,6 +134,7 @@ static void M68Power(void) {
|
||||
SetWriteHandler(0xF000, 0xFFFF, M68WriteROM);
|
||||
SetWriteHandler(0x6000, 0x6000, M68WriteLo);
|
||||
SetWriteHandler(0x6001, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M68Close(void) {
|
||||
|
||||
+8
-4
@@ -41,7 +41,7 @@ static SFORMAT StateRegs[] =
|
||||
static void Sync(void) {
|
||||
uint8 i;
|
||||
if ((preg[3] & 0xC0) == 0xC0)
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
setprg8r(0x10, 0x6000, preg[3] & 0x3F);
|
||||
else
|
||||
setprg8(0x6000, preg[3] & 0x3F);
|
||||
setprg8(0x8000, preg[0]);
|
||||
@@ -90,8 +90,8 @@ static DECLFW(M69Write1) {
|
||||
case 0xB: preg[2] = V; Sync(); break;
|
||||
case 0xC: mirr = V & 3; Sync();break;
|
||||
case 0xD: IRQa = V; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 0xE: IRQCount &= 0xFF00; IRQCount |= V; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 0xF: IRQCount &= 0x00FF; IRQCount |= V << 8; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 0xE: IRQCount &= 0xFF00; IRQCount |= V; break;
|
||||
case 0xF: IRQCount &= 0x00FF; IRQCount |= V << 8; break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,6 +232,7 @@ static void M69Power(void) {
|
||||
SetWriteHandler(0xA000, 0xBFFF, M69Write1);
|
||||
SetWriteHandler(0xC000, 0xDFFF, M69SWrite0);
|
||||
SetWriteHandler(0xE000, 0xFFFF, M69SWrite1);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M69Close(void) {
|
||||
@@ -257,7 +258,10 @@ void Mapper69_Init(CartInfo *info) {
|
||||
info->Power = M69Power;
|
||||
info->Close = M69Close;
|
||||
MapIRQHook = M69IRQHook;
|
||||
WRAMSIZE = 8192;
|
||||
if(info->ines2)
|
||||
WRAMSIZE = info->wram_size + info->battery_wram_size;
|
||||
else
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -68,6 +68,7 @@ static void M82Power(void) {
|
||||
SetReadHandler(0x6000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
||||
SetWriteHandler(0x7ef0, 0x7efc, M82Write); // external WRAM might end at $73FF
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M82Close(void) {
|
||||
|
||||
+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;
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2016 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
|
||||
*
|
||||
* 8-in-1 Rockin' Kats, Snake, (PCB marked as "8 in 1"), similar to 12IN1,
|
||||
* but with MMC3 on board, all games are hacked the same, Snake is buggy too!
|
||||
*
|
||||
* no reset-citcuit, so selected game can be reset, but to change it you must use power
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void BMC8IN1CW(uint32 A, uint8 V) {
|
||||
setchr1(A, ((EXPREGS[0] & 0xC) << 5) | (V & 0x7F));
|
||||
}
|
||||
|
||||
static void BMC8IN1PW(uint32 A, uint8 V) {
|
||||
if(EXPREGS[0] & 0x10) { // MMC3 mode
|
||||
setprg8(A, ((EXPREGS[0] & 0xC) << 2) | (V & 0xF));
|
||||
} else {
|
||||
setprg32(0x8000, EXPREGS[0] & 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(BMC8IN1Write) {
|
||||
if(A & 0x1000) {
|
||||
EXPREGS[0] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
} else {
|
||||
if(A < 0xC000)
|
||||
MMC3_CMDWrite(A, V);
|
||||
else
|
||||
MMC3_IRQWrite(A, V);
|
||||
}
|
||||
}
|
||||
|
||||
static void BMC8IN1Power(void) {
|
||||
EXPREGS[0] = 0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x8000, 0xFFFF, BMC8IN1Write);
|
||||
}
|
||||
|
||||
void BMC8IN1_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 128, 128, 0, 0);
|
||||
cwrap = BMC8IN1CW;
|
||||
pwrap = BMC8IN1PW;
|
||||
info->Power = BMC8IN1Power;
|
||||
AddExState(EXPREGS, 1, 0, "EXPR");
|
||||
}
|
||||
@@ -51,6 +51,7 @@ static void M99Power(void) {
|
||||
SetWriteHandler(0x4016, 0x4016, M99Write);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M99Close(void)
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2015 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
|
||||
*
|
||||
* "Dragon Fighter" protected MMC3 based custom mapper board
|
||||
* mostly hacky implementation, I can't verify if this mapper can read a RAM of the
|
||||
* console or watches the bus writes somehow.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void UNLBMW8544PW(uint32 A, uint8 V) {
|
||||
if(A == 0x8000)
|
||||
setprg8(A,EXPREGS[0] & 0x1F); // the real hardware has this bank overrided with it's own register,
|
||||
else // but MMC3 prg swap still works and you can actually change bank C000 at the same time if use 0x46 cmd
|
||||
setprg8(A,V);
|
||||
}
|
||||
|
||||
static void UNLBMW8544CW(uint32 A, uint8 V) {
|
||||
if(A == 0x0000)
|
||||
setchr2(0x0000,(V >> 1) ^ EXPREGS[1]);
|
||||
else if (A == 0x0800)
|
||||
setchr2(0x0800,(V >> 1) | ((EXPREGS[2] & 0x40) << 1));
|
||||
else if (A == 0x1000)
|
||||
setchr4(0x1000, EXPREGS[2] & 0x3F);
|
||||
|
||||
}
|
||||
|
||||
static DECLFW(UNLBMW8544ProtWrite) {
|
||||
if(!(A & 1)) {
|
||||
EXPREGS[0] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(UNLBMW8544ProtRead) {
|
||||
if(!fceuindbg) {
|
||||
if(!(A & 1)) {
|
||||
if((EXPREGS[0] & 0xE0) == 0xC0) {
|
||||
EXPREGS[1] = ARead[0x6a](0x6a); // program can latch some data from the BUS, but I can't say how exactly,
|
||||
} else { // without more euipment and skills ;) probably here we can try to get any write
|
||||
EXPREGS[2] = ARead[0xff](0xff); // before the read operation
|
||||
}
|
||||
FixMMC3CHR(MMC3_cmd & 0x7F); // there are more different behaviour of the board isn't used by game itself, so unimplemented here and
|
||||
} // actually will break the current logic ;)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void UNLBMW8544Power(void) {
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x6FFF, UNLBMW8544ProtWrite);
|
||||
SetReadHandler(0x6000, 0x6FFF, UNLBMW8544ProtRead);
|
||||
}
|
||||
|
||||
void UNLBMW8544_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 128, 256, 0, 0);
|
||||
pwrap = UNLBMW8544PW;
|
||||
cwrap = UNLBMW8544CW;
|
||||
info->Power = UNLBMW8544Power;
|
||||
AddExState(EXPREGS, 3, 0, "EXPR");
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2015 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
|
||||
*
|
||||
* BMC F-15 PCB (256+266 MMC3 based, with 16/32Kb banking discrete logic)
|
||||
* 150-in-1 Unchaied Melody FIGHT version with system test (START+SELECT)
|
||||
*
|
||||
* CHR - MMC3 stock regs
|
||||
* PRG - MMC3 regs disabled, area 6000-7FFF used instead
|
||||
* 011xxxxxxxxxxxxx addr mask,
|
||||
* ----APPp reg bits mask
|
||||
* A - higher 128K PRG bank select/32K bank mode override
|
||||
* PP - bank number in 32K mode
|
||||
* PPp - bank number in 16K mode
|
||||
* initial state of extra regs is undefined, A001 enables/disables the 6000 area
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void BMCF15PW(uint32 A, uint8 V) {
|
||||
uint32 bank = EXPREGS[0] & 0xF;
|
||||
uint32 mode = (EXPREGS[0] & 8) >> 3;
|
||||
uint32 mask = ~(mode);
|
||||
setprg16(0x8000, (bank & mask));
|
||||
setprg16(0xC000, (bank & mask) | mode);
|
||||
}
|
||||
|
||||
static DECLFW(BMCF15Write) {
|
||||
if (A001B & 0x80) {
|
||||
EXPREGS[0] = V & 0xF;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void BMCF15Power(void) {
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, BMCF15Write);
|
||||
SetWriteHandler(0x6000, 0x7FFF, BMCF15Write);
|
||||
}
|
||||
|
||||
void BMCF15_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 256, 256, 0, 0);
|
||||
pwrap = BMCF15PW;
|
||||
info->Power = BMCF15Power;
|
||||
AddExState(EXPREGS, 1, 0, "EXPR");
|
||||
}
|
||||
@@ -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')
|
||||
@@ -44,6 +44,7 @@ static void LatchPower(void) {
|
||||
if (WRAM) {
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
} else
|
||||
SetReadHandler(0x6000, 0xFFFF, defread);
|
||||
SetWriteHandler(addrreg0, addrreg1, LatchWrite);
|
||||
@@ -236,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) {
|
||||
@@ -302,14 +298,20 @@ static void M212Sync(void) {
|
||||
}
|
||||
|
||||
void Mapper212_Init(CartInfo *info) {
|
||||
Latch_Init(info, M212Sync, M212Read, 0xFFFF, 0x8000, 0xFFFF, 0);
|
||||
Latch_Init(info, M212Sync, M212Read, 0x0000, 0x8000, 0xFFFF, 0);
|
||||
}
|
||||
|
||||
//------------------ 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) {
|
||||
@@ -346,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);
|
||||
|
||||
+275
-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);
|
||||
}
|
||||
|
||||
@@ -270,6 +356,7 @@ static void M153Power(void) {
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, BandaiWrite);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
|
||||
@@ -306,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 },
|
||||
@@ -329,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;
|
||||
|
||||
@@ -340,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++) {
|
||||
@@ -361,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
|
||||
@@ -418,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);
|
||||
|
||||
@@ -435,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) {
|
||||
@@ -445,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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void COOLBOYCW(uint32 A, uint8 V) {
|
||||
uint32 mask = 0xFF ^ (EXPREGS[0] & 0x80);
|
||||
if (EXPREGS[3] & 0x10) {
|
||||
if (EXPREGS[3] & 0x40) { // Weird mode
|
||||
int cbase = (MMC3_cmd & 0x80) << 5;
|
||||
switch (cbase ^ A) { // Don't even try do understand
|
||||
case 0x0400:
|
||||
case 0x0C00: V &= 0x7F; break;
|
||||
}
|
||||
}
|
||||
// Highest bit goes from MMC3 registers when EXPREGS[3]&0x80==0 or from EXPREGS[0]&0x08 otherwise
|
||||
setchr1(A,
|
||||
(V & 0x80 & mask) | ((((EXPREGS[0] & 0x08) << 4) & ~mask)) // 7th bit
|
||||
| ((EXPREGS[2] & 0x0F) << 3) // 6-3 bits
|
||||
| ((A >> 10) & 7) // 2-0 bits
|
||||
);
|
||||
} else {
|
||||
if (EXPREGS[3] & 0x40) { // Weird mode, again
|
||||
int cbase = (MMC3_cmd & 0x80) << 5;
|
||||
switch (cbase ^ A) { // Don't even try do understand
|
||||
case 0x0000: V = DRegBuf[0]; break;
|
||||
case 0x0800: V = DRegBuf[1]; break;
|
||||
case 0x0400:
|
||||
case 0x0C00: V = 0; break;
|
||||
}
|
||||
}
|
||||
// Simple MMC3 mode
|
||||
// Highest bit goes from MMC3 registers when EXPREGS[3]&0x80==0 or from EXPREGS[0]&0x08 otherwise
|
||||
setchr1(A, (V & mask) | (((EXPREGS[0] & 0x08) << 4) & ~mask));
|
||||
}
|
||||
}
|
||||
|
||||
static void COOLBOYPW(uint32 A, uint8 V) {
|
||||
uint32 mask = ((0x3F | (EXPREGS[1] & 0x40) | ((EXPREGS[1] & 0x20) << 2)) ^ ((EXPREGS[0] & 0x40) >> 2)) ^ ((EXPREGS[1] & 0x80) >> 2);
|
||||
uint32 base = ((EXPREGS[0] & 0x07) >> 0) | ((EXPREGS[1] & 0x10) >> 1) | ((EXPREGS[1] & 0x0C) << 2) | ((EXPREGS[0] & 0x30) << 2);
|
||||
|
||||
// Very weird mode
|
||||
// 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 0xC000:
|
||||
case 0xE000:
|
||||
V = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Regular MMC3 mode, internal ROM size can be up to 2048kb!
|
||||
if (!(EXPREGS[3] & 0x10))
|
||||
setprg8(A, (((base << 4) & ~mask)) | (V & mask));
|
||||
else { // NROM mode
|
||||
mask &= 0xF0;
|
||||
uint8 emask;
|
||||
if ((((EXPREGS[1] & 2) != 0))) // 32kb mode
|
||||
emask = (EXPREGS[3] & 0x0C) | ((A & 0x4000) >> 13);
|
||||
else // 16kb mode
|
||||
emask = EXPREGS[3] & 0x0E;
|
||||
setprg8(A, ((base << 4) & ~mask) // 7-4 bits are from base (see below)
|
||||
| (V & mask) // ... or from MM3 internal regs, depends on mask
|
||||
| emask // 3-1 (or 3-2 when (EXPREGS[3]&0x0C is set) from EXPREGS[3]
|
||||
| ((A & 0x2000) >> 13)); // 0th just as is
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(COOLBOYWrite) {
|
||||
if(A001B & 0x80)
|
||||
CartBW(A,V);
|
||||
|
||||
// Deny any further writes when 7th bit is 1 AND 4th is 0
|
||||
if ((EXPREGS[3] & 0x90) != 0x80) {
|
||||
EXPREGS[A & 3] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void COOLBOYReset(void) {
|
||||
MMC3RegReset();
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void COOLBOYPower(void) {
|
||||
GenMMC3Power();
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = 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, 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, 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;
|
||||
}
|
||||
}
|
||||
@@ -67,6 +67,7 @@ static void UNLD2000Power(void) {
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, UNLD2000Read);
|
||||
SetWriteHandler(0x5000, 0x5FFF, UNLD2000Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void UNL2000Hook(uint32 A) {
|
||||
|
||||
+543
-484
File diff suppressed because it is too large
Load Diff
@@ -48,6 +48,7 @@ static void UNLEDU2000Power(void) {
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0xFFFF, CartBW);
|
||||
SetWriteHandler(0x8000, 0xFFFF, UNLEDU2000HiWrite);
|
||||
FCEU_CheatAddRAM(32, 0x6000, WRAM);
|
||||
reg = 0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2015 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 uint16 addrlatch;
|
||||
static uint8 datalatch, hw_mode;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &addrlatch, 2, "ADRL" },
|
||||
{ &datalatch, 1, "DATL" },
|
||||
{ &hw_mode, 1, "HWMO" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
uint8 prg = (addrlatch & 7);
|
||||
setchr8(datalatch);
|
||||
if(addrlatch & 0x80) {
|
||||
setprg16(0x8000,prg);
|
||||
setprg16(0xC000,prg);
|
||||
} else {
|
||||
setprg32(0x8000,prg >> 1);
|
||||
}
|
||||
setmirror(MI_V);
|
||||
}
|
||||
|
||||
static DECLFW(EH8813AWrite) {
|
||||
if((addrlatch & 0x100) == 0) {
|
||||
addrlatch = A & 0x1FF;
|
||||
datalatch = V & 0xF;
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFR(EH8813ARead) {
|
||||
if (addrlatch & 0x40)
|
||||
A= (A & 0xFFF0) + hw_mode;
|
||||
return CartBR(A);
|
||||
}
|
||||
|
||||
static void EH8813APower(void) {
|
||||
addrlatch = datalatch = hw_mode = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, EH8813ARead);
|
||||
SetWriteHandler(0x8000, 0xFFFF, EH8813AWrite);
|
||||
}
|
||||
|
||||
static void EH8813AReset(void) {
|
||||
addrlatch = datalatch = 0;
|
||||
hw_mode = (hw_mode + 1) & 0xF;
|
||||
FCEU_printf("Hardware Switch is %01X\n", hw_mode);
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void UNLEH8813A_Init(CartInfo *info) {
|
||||
info->Reset = EH8813AReset;
|
||||
info->Power = EH8813APower;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
+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;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2015 Cluster
|
||||
* http://clusterrr.com
|
||||
* clusterrr@clusterrr.com
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
MMC3-based multicart mapper with CHR RAM, CHR ROM and PRG RAM
|
||||
|
||||
$6000-7FFF: A~[011xxxxx xxMRSBBB] Multicart reg
|
||||
This register can only be written to if PRG-RAM is enabled and writable (see $A001)
|
||||
and BBB = 000 (power on state)
|
||||
|
||||
BBB = CHR+PRG block select bits (A19, A18, A17 for both PRG and CHR)
|
||||
S = PRG block size (0=256k 1=128k)
|
||||
R = CHR mode (0=CHR ROM 1=CHR RAM)
|
||||
M = CHR block size (0=256k 1=128k)
|
||||
ignored when S is 0 for some reason
|
||||
|
||||
Example Game:
|
||||
--------------------------
|
||||
6 in 1 multicart (SMB3, TMNT2, Contra, Ninja Cat, Ninja Crusaders, Rainbow Islands 2)
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 *CHRRAM;
|
||||
static uint32 CHRRAMSize;
|
||||
|
||||
static void BMC1024CA1PW(uint32 A, uint8 V) {
|
||||
if ((EXPREGS[0]>>3)&1)
|
||||
setprg8(A, (V&0x1F) | ((EXPREGS[0] & 7) << 4));
|
||||
else
|
||||
setprg8(A, (V&0x0F) | ((EXPREGS[0] & 7) << 4));
|
||||
}
|
||||
|
||||
static void BMC1024CA1CW(uint32 A, uint8 V) {
|
||||
if ((EXPREGS[0]>>4)&1)
|
||||
setchr1r(0x10, A, V);
|
||||
else if (((EXPREGS[0]>>5)&1) && ((EXPREGS[0]>>3)&1))
|
||||
setchr1(A, V | ((EXPREGS[0] & 7) << 7));
|
||||
else
|
||||
setchr1(A, (V&0x7F) | ((EXPREGS[0] & 7) << 7));
|
||||
}
|
||||
|
||||
static DECLFW(BMC1024CA1Write) {
|
||||
if (((A001B & 0xC0) == 0x80) && !(EXPREGS[0] & 7))
|
||||
{
|
||||
EXPREGS[0] = A & 0x3F;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
} else {
|
||||
CartBW(A, V);
|
||||
}
|
||||
}
|
||||
|
||||
static void BMC1024CA1Reset(void) {
|
||||
EXPREGS[0] = 0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void BMC1024CA1Power(void) {
|
||||
EXPREGS[0] = 0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, BMC1024CA1Write);
|
||||
}
|
||||
|
||||
static void BMC1024CA1Close(void) {
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
}
|
||||
|
||||
void BMC1024CA1_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 256, 256, 8, 0);
|
||||
CHRRAMSize = 8192;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
|
||||
AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
|
||||
pwrap = BMC1024CA1PW;
|
||||
cwrap = BMC1024CA1CW;
|
||||
info->Power = BMC1024CA1Power;
|
||||
info->Reset = BMC1024CA1Reset;
|
||||
info->Close = BMC1024CA1Close;
|
||||
AddExState(EXPREGS, 1, 0, "EXPR");
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2016 Cluster
|
||||
* http://clusterrr.com
|
||||
* clusterrr@clusterrr.com
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
MMC3-based multicart mapper with CHR RAM, CHR ROM and PRG RAM
|
||||
|
||||
$6000-7FFF: A~[011xxxxx xxMRSBBB] Multicart reg
|
||||
This register can only be written to if PRG-RAM is enabled and writable (see $A001)
|
||||
and BBB = 000 (power on state)
|
||||
|
||||
BBB = CHR+PRG block select bits (A19, A18, A17 for both PRG and CHR)
|
||||
S = PRG block size & mirroring mode (0=128k with normal MMC3, 1=256k with TxSROM-like single-screen mirroring)
|
||||
R = CHR mode (0=CHR ROM 1=CHR RAM)
|
||||
M = CHR block size (0=256k 1=128k)
|
||||
ignored when S is 0 for some reason
|
||||
|
||||
Example Game:
|
||||
--------------------------
|
||||
7 in 1 multicart (Amarello, TMNT2, Contra, Ninja Cat, Ninja Crusaders, Rainbow Islands 2)
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 *CHRRAM;
|
||||
static uint32 CHRRAMSize;
|
||||
static uint8 PPUCHRBus;
|
||||
static uint8 TKSMIR[8];
|
||||
|
||||
static void BMC810131C_PW(uint32 A, uint8 V) {
|
||||
if ((EXPREGS[0] >> 3) & 1)
|
||||
setprg8(A, (V & 0x1F) | ((EXPREGS[0] & 7) << 4));
|
||||
else
|
||||
setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 7) << 4));
|
||||
}
|
||||
|
||||
static void BMC810131C_CW(uint32 A, uint8 V) {
|
||||
if ((EXPREGS[0] >> 4) & 1)
|
||||
setchr1r(0x10, A, V);
|
||||
else if (((EXPREGS[0] >> 5) & 1) && ((EXPREGS[0] >> 3) & 1))
|
||||
setchr1(A, V | ((EXPREGS[0] & 7) << 7));
|
||||
else
|
||||
setchr1(A, (V & 0x7F) | ((EXPREGS[0] & 7) << 7));
|
||||
|
||||
TKSMIR[A >> 10] = V >> 7;
|
||||
if (((EXPREGS[0] >> 3) & 1) && (PPUCHRBus == (A >> 10)))
|
||||
setmirror(MI_0 + (V >> 7));
|
||||
}
|
||||
|
||||
static DECLFW(BMC810131C_Write) {
|
||||
if (((A001B & 0xC0) == 0x80) && !(EXPREGS[0] & 7))
|
||||
{
|
||||
EXPREGS[0] = A & 0x3F;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
else {
|
||||
CartBW(A, V);
|
||||
}
|
||||
}
|
||||
|
||||
static void BMC810131C_Reset(void) {
|
||||
EXPREGS[0] = 0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void BMC810131C_Power(void) {
|
||||
EXPREGS[0] = 0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x6000, 0x7FFF, BMC810131C_Write);
|
||||
}
|
||||
|
||||
static void BMC810131C_Close(void) {
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
}
|
||||
|
||||
static void TKSPPU(uint32 A) {
|
||||
A &= 0x1FFF;
|
||||
A >>= 10;
|
||||
PPUCHRBus = A;
|
||||
if ((EXPREGS[0] >> 3) & 1)
|
||||
setmirror(MI_0 + TKSMIR[A]);
|
||||
}
|
||||
|
||||
void BMC810131C_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 256, 256, 8, 0);
|
||||
CHRRAMSize = 8192;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
|
||||
AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
|
||||
pwrap = BMC810131C_PW;
|
||||
cwrap = BMC810131C_CW;
|
||||
PPU_hook = TKSPPU;
|
||||
info->Power = BMC810131C_Power;
|
||||
info->Reset = BMC810131C_Reset;
|
||||
info->Close = BMC810131C_Close;
|
||||
AddExState(EXPREGS, 1, 0, "EXPR");
|
||||
}
|
||||
@@ -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);
|
||||
@@ -79,6 +79,7 @@ static void SSSNROMPower(void) {
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void SSSNROMReset(void) {
|
||||
@@ -109,7 +110,6 @@ void SSSNROM_Init(CartInfo *info) {
|
||||
WRAMSIZE = 16384;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -102,6 +102,7 @@ static void FFEPower(void) {
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, FFEWriteLatch);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void FFEIRQHook(int a) {
|
||||
|
||||
+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");
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2015 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 regs[2];
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ regs, 2, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
uint8 chr = (regs[0] >> 4) & 7;
|
||||
uint8 prg = (regs[1] >> 3) & 7;
|
||||
uint8 dec = (regs[1] >> 4) & 4;
|
||||
setchr8(chr & (~(((regs[0] & 1) << 2) | (regs[0] & 2))));
|
||||
setprg16(0x8000,prg & (~dec));
|
||||
setprg16(0xC000,prg | dec);
|
||||
setmirror(regs[1] >> 7);
|
||||
}
|
||||
|
||||
static DECLFW(HP898FWrite) {
|
||||
if((A & 0x6000) == 0x6000) {
|
||||
regs[(A & 4) >> 2] = V;
|
||||
Sync();
|
||||
}
|
||||
}
|
||||
|
||||
static void HP898FPower(void) {
|
||||
regs[0] = regs[1] = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0xFFFF, HP898FWrite);
|
||||
}
|
||||
|
||||
static void HP898FReset(void) {
|
||||
regs[0] = regs[1] = 0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void BMCHP898F_Init(CartInfo *info) {
|
||||
info->Reset = HP898FReset;
|
||||
info->Power = HP898FPower;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 regs[8];
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ regs, 8, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
for (int i=0; i < 8; ++i)
|
||||
{
|
||||
setprg4(0x8000 + (0x1000 * i), regs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(M31Write) {
|
||||
if (A >= 0x5000 && A <= 0x5FFF)
|
||||
{
|
||||
regs[A&7] = V;
|
||||
Sync();
|
||||
}
|
||||
}
|
||||
|
||||
static void M31Power(void) {
|
||||
setchr8(0);
|
||||
regs[7] = 0xFF;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x5000, 0x5fff, M31Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper31_Init(CartInfo *info) {
|
||||
info->Power = M31Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2007 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 preg[4], creg, mirr;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ preg, 4, "PREG" },
|
||||
{ &creg, 1, "CREG" },
|
||||
{ &mirr, 1, "MIRR" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg8(0x6000, preg[0]);
|
||||
setprg8(0x8000, 0xa);
|
||||
setprg8(0xa000, 0xb);
|
||||
setprg8(0xc000, 0x6);
|
||||
setprg8(0xe000, 0x7);
|
||||
setchr8(0x0c);
|
||||
setmirror(mirr);
|
||||
}
|
||||
|
||||
static DECLFW(UNLKS7010Write) {
|
||||
switch (A) {
|
||||
case 0x4025: mirr = (((V >> 3) & 1) ^ 1); Sync(); break;
|
||||
default:
|
||||
FCEU_printf("bs %04x %02x\n",A,V);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void UNLKS7010Reset(void) {
|
||||
preg[0]++;
|
||||
if(preg[0] == 0x10) {
|
||||
preg[0] = 0;
|
||||
preg[1]++;
|
||||
if(preg[1] == 0x10) {
|
||||
preg[1] = 0;
|
||||
preg[2]++;
|
||||
}
|
||||
}
|
||||
FCEU_printf("preg %02x %02x %02x\n",preg[0], preg[1], preg[2]);
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void UNLKS7010Power(void) {
|
||||
preg[0] = preg[1] = preg[2] = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0x7fff, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x4020, 0xffff, UNLKS7010Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void UNLKS7010_Init(CartInfo *info) {
|
||||
info->Power = UNLKS7010Power;
|
||||
info->Reset = UNLKS7010Reset;
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
@@ -51,6 +51,7 @@ static void UNLKS7012Power(void) {
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, UNLKS7012Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void UNLKS7012Reset(void) {
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2016 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
|
||||
*
|
||||
* FDS Conversion (Exciting Basket), weird banking addressing, seems because
|
||||
* of used addressing scheme, made to disable the lower system banks from 6000
|
||||
* but the kaiser mapper chip and PCB are the same as usual
|
||||
* probably need a hard eprom dump to verify actual banks layout
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 preg;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &preg, 1, "PREG" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg8(0x6000, preg);
|
||||
setprg8(0x8000, 0xC);
|
||||
setprg8(0xA000, 0xD);
|
||||
setprg8(0xC000, 0xE);
|
||||
setprg8(0xE000, 0xF);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static DECLFW(UNLKS7016Write) {
|
||||
u16 mask = (A & 0x30);
|
||||
switch(A & 0xD943) {
|
||||
case 0xD943: {
|
||||
if(mask == 0x30) {
|
||||
preg = 8 | 3; // or A, or no bus (all FF)
|
||||
} else {
|
||||
preg = (A >> 2) & 0xF; // can be anything but C-F
|
||||
}
|
||||
Sync();
|
||||
break;
|
||||
}
|
||||
case 0xD903: { // this case isn't usedby the game, but addressing does this as a side effect
|
||||
if(mask == 0x30) {
|
||||
preg = 8 | ((A >> 2) & 3); // also masked C-F from output
|
||||
} else {
|
||||
preg = 8 | 3;
|
||||
}
|
||||
Sync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void UNLKS7016Power(void) {
|
||||
preg = 8;
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x8000, 0xffff, UNLKS7016Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void UNLKS7016_Init(CartInfo *info) {
|
||||
info->Power = UNLKS7016Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
@@ -87,6 +87,7 @@ static void UNLKS7017Power(void) {
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetReadHandler(0x4030, 0x4030, FDSRead4030);
|
||||
SetWriteHandler(0x4020, 0x5FFF, UNLKS7017Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void UNLKS7017Close(void) {
|
||||
|
||||
@@ -82,6 +82,7 @@ static void LH10Power(void) {
|
||||
SetWriteHandler(0x8000, 0xBFFF, UNLKS7037Write);
|
||||
SetWriteHandler(0xC000, 0xDFFF, CartBW);
|
||||
SetWriteHandler(0xE000, 0xFFFF, UNLKS7037Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void Close(void) {
|
||||
|
||||
@@ -52,6 +52,7 @@ static void LH32Power(void) {
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0xC000, 0xDFFF, CartBW);
|
||||
SetWriteHandler(0x6000, 0x6000, LH32Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void LH32Close(void) {
|
||||
|
||||
@@ -80,6 +80,7 @@ static void LH53Power(void) {
|
||||
SetWriteHandler(0xB800, 0xD7FF, LH53RamWrite);
|
||||
SetWriteHandler(0xE000, 0xEFFF, LH53IRQaWrite);
|
||||
SetWriteHandler(0xF000, 0xFFFF, LH53Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void LH53Close(void) {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
+73
-61
@@ -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);
|
||||
}
|
||||
@@ -73,37 +74,38 @@ static void MMC1CHR(void) {
|
||||
}
|
||||
|
||||
static void MMC1PRG(void) {
|
||||
uint8 offs = DRegs[1] & 0x10;
|
||||
uint8 offs_16banks = DRegs[1] & 0x10;
|
||||
uint8 prg_reg = DRegs[3] & 0xF; //homebrewers arent allowed to use more banks on MMC1. use another mapper.
|
||||
if (MMC1PRGHook16) {
|
||||
switch (DRegs[0] & 0xC) {
|
||||
case 0xC:
|
||||
MMC1PRGHook16(0x8000, (DRegs[3] + offs));
|
||||
MMC1PRGHook16(0xC000, 0xF + offs);
|
||||
MMC1PRGHook16(0x8000, (prg_reg + offs_16banks));
|
||||
MMC1PRGHook16(0xC000, 0xF + offs_16banks);
|
||||
break;
|
||||
case 0x8:
|
||||
MMC1PRGHook16(0xC000, (DRegs[3] + offs));
|
||||
MMC1PRGHook16(0x8000, offs);
|
||||
MMC1PRGHook16(0xC000, (prg_reg + offs_16banks));
|
||||
MMC1PRGHook16(0x8000, offs_16banks);
|
||||
break;
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
MMC1PRGHook16(0x8000, ((DRegs[3] & ~1) + offs));
|
||||
MMC1PRGHook16(0xc000, ((DRegs[3] & ~1) + offs + 1));
|
||||
MMC1PRGHook16(0x8000, ((prg_reg & ~1) + offs_16banks));
|
||||
MMC1PRGHook16(0xc000, ((prg_reg & ~1) + offs_16banks + 1));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (DRegs[0] & 0xC) {
|
||||
case 0xC:
|
||||
setprg16(0x8000, (DRegs[3] + offs));
|
||||
setprg16(0xC000, 0xF + offs);
|
||||
setprg16(0x8000, (prg_reg + offs_16banks));
|
||||
setprg16(0xC000, 0xF + offs_16banks);
|
||||
break;
|
||||
case 0x8:
|
||||
setprg16(0xC000, (DRegs[3] + offs));
|
||||
setprg16(0x8000, offs);
|
||||
setprg16(0xC000, (prg_reg + offs_16banks));
|
||||
setprg16(0x8000, offs_16banks);
|
||||
break;
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
setprg16(0x8000, ((DRegs[3] & ~1) + offs));
|
||||
setprg16(0xc000, ((DRegs[3] & ~1) + offs + 1));
|
||||
setprg16(0x8000, ((prg_reg & ~1) + offs_16banks));
|
||||
setprg16(0xc000, ((prg_reg & ~1) + offs_16banks + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -178,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;
|
||||
@@ -243,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);
|
||||
}
|
||||
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);
|
||||
@@ -270,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) {
|
||||
@@ -312,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;
|
||||
}
|
||||
|
||||
@@ -330,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) {
|
||||
@@ -350,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) {
|
||||
@@ -382,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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ static void MMC2and4Power(void) {
|
||||
if (is10) {
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0xA000, 0xFFFF, MMC2and4Write);
|
||||
|
||||
+75
-11
@@ -28,6 +28,7 @@
|
||||
#include "mmc3.h"
|
||||
|
||||
uint8 MMC3_cmd;
|
||||
uint8 kt_extra;
|
||||
uint8 *WRAM;
|
||||
uint32 WRAMSIZE;
|
||||
uint8 *CHRRAM;
|
||||
@@ -112,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);
|
||||
}
|
||||
@@ -182,6 +186,24 @@ DECLFW(MMC3_IRQWrite) {
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
DECLFW(KT008HackWrite) {
|
||||
// FCEU_printf("%04x:%04x\n",A,V);
|
||||
switch (A & 3) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
static void ClockMMC3Counter(void) {
|
||||
int count = IRQCount;
|
||||
if (!count || IRQReload) {
|
||||
@@ -220,7 +242,10 @@ static void GENCWRAP(uint32 A, uint8 V) {
|
||||
}
|
||||
|
||||
static void GENPWRAP(uint32 A, uint8 V) {
|
||||
setprg8(A, V & 0x7F); // [NJ102] Mo Dao Jie (C) has 1024Mb MMC3 BOARD, maybe something other will be broken
|
||||
// [NJ102] Mo Dao Jie (C) has 1024Mb MMC3 BOARD, maybe something other will be broken
|
||||
// also HengGe BBC-2x boards enables this mode as default board mode at boot up
|
||||
setprg8(A, (V & 0x7F) | ((kt_extra & 4) << 4));
|
||||
// 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
|
||||
}
|
||||
|
||||
static void GENMWRAP(uint8 V) {
|
||||
@@ -246,6 +271,10 @@ void GenMMC3Power(void) {
|
||||
SetWriteHandler(0x8000, 0xBFFF, MMC3_CMDWrite);
|
||||
SetWriteHandler(0xC000, 0xFFFF, MMC3_IRQWrite);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
|
||||
// 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
|
||||
SetWriteHandler(0x5000,0x5FFF, KT008HackWrite);
|
||||
|
||||
A001B = A000B = 0;
|
||||
setmirror(1);
|
||||
if (mmc3opts & 1) {
|
||||
@@ -254,17 +283,17 @@ void GenMMC3Power(void) {
|
||||
SetReadHandler(0x7000, 0x7FFF, MAWRAMMMC6);
|
||||
SetWriteHandler(0x7000, 0x7FFF, MBWRAMMMC6);
|
||||
} else {
|
||||
FCEU_CheatAddRAM((WRAMSIZE & 0x1fff) >> 10, 0x6000, WRAM);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
SetWriteHandler(0x6000, 0x6000 + ((WRAMSIZE - 1) & 0x1fff), CartBW);
|
||||
SetReadHandler(0x6000, 0x6000 + ((WRAMSIZE - 1) & 0x1fff), CartBR);
|
||||
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) {
|
||||
@@ -299,6 +328,8 @@ void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery) {
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
|
||||
// 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
|
||||
AddExState(&kt_extra, 1, 0, "KTEX");
|
||||
AddExState(MMC3_StateRegs, ~0, 0, 0);
|
||||
|
||||
info->Power = GenMMC3Power;
|
||||
@@ -477,13 +508,18 @@ static void M45CW(uint32 A, uint8 V) {
|
||||
NV &= 0; // hack ;( don't know exactly how it should be
|
||||
NV |= EXPREGS[0] | ((EXPREGS[2] & 0xF0) << 4);
|
||||
setchr1(A, NV);
|
||||
}
|
||||
} else
|
||||
// setchr8(0); // i don't know what cart need this, but a new one need other lol
|
||||
setchr1(A, V);
|
||||
}
|
||||
|
||||
static void M45PW(uint32 A, uint8 V) {
|
||||
V &= (EXPREGS[3] & 0x3F) ^ 0x3F;
|
||||
V |= EXPREGS[1];
|
||||
setprg8(A, V);
|
||||
uint32 MV = V & ((EXPREGS[3] & 0x3F) ^ 0x3F);
|
||||
MV |= EXPREGS[1];
|
||||
if(UNIFchrrama)
|
||||
MV |= ((EXPREGS[2] & 0x40) << 2);
|
||||
setprg8(A, MV);
|
||||
// FCEU_printf("1:%02x 2:%02x 3:%02x A=%04x V=%03x\n",EXPREGS[1],EXPREGS[2],EXPREGS[3],A,MV);
|
||||
}
|
||||
|
||||
static DECLFW(M45Write) {
|
||||
@@ -513,7 +549,6 @@ static void M45Reset(void) {
|
||||
}
|
||||
|
||||
static void M45Power(void) {
|
||||
setchr8(0);
|
||||
GenMMC3Power();
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = EXPREGS[4] = EXPREGS[5] = 0;
|
||||
SetWriteHandler(0x5000, 0x7FFF, M45Write);
|
||||
@@ -820,6 +855,7 @@ void Mapper119_Init(CartInfo *info) {
|
||||
CHRRAMSIZE = 8192;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR");
|
||||
}
|
||||
|
||||
// ---------------------------- Mapper 134 ------------------------------
|
||||
@@ -1017,8 +1053,8 @@ static DECLFW(Mapper196Write) {
|
||||
}
|
||||
|
||||
static DECLFW(Mapper196WriteLo) {
|
||||
EXPREGS[0] = 1;
|
||||
EXPREGS[1] = (V & 0xf) | (V >> 4);
|
||||
EXPREGS[0] = 1; // hacky
|
||||
EXPREGS[1] = (V & 0xf) | (V >> 4); // this is the same as 189 mapper, but with addr permutations
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
|
||||
@@ -1321,8 +1357,36 @@ void TQROM_Init(CartInfo *info) {
|
||||
CHRRAMSIZE = 8192;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
+279
-67
@@ -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,17 +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);
|
||||
@@ -106,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;
|
||||
@@ -135,12 +172,105 @@ static void mmc5_PPUWrite(uint32 A, uint8 V) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8 FASTCALL mmc5_PPURead(uint32 A) {
|
||||
if (A < 0x2000) {
|
||||
if (ppuphase == PPUPHASE_BG)
|
||||
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];
|
||||
}
|
||||
}
|
||||
@@ -189,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) {
|
||||
@@ -196,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) {
|
||||
@@ -266,9 +411,10 @@ 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))));
|
||||
MMC5MemIn[(A - 0x6000) >> 13] = 1;
|
||||
} else
|
||||
MMC5MemIn[(A - 0x6000) >> 13] = 0;
|
||||
@@ -290,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;
|
||||
@@ -304,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;
|
||||
@@ -313,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;
|
||||
@@ -327,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;
|
||||
@@ -390,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:
|
||||
@@ -486,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();
|
||||
@@ -510,21 +656,40 @@ void MMC5Synco(void) {
|
||||
}
|
||||
|
||||
void MMC5_hb(int scanline) {
|
||||
if (scanline == 240) {
|
||||
//zero 24-jul-2014 - revised for newer understanding, to fix metal slader glory credits. see r7371 in bizhawk
|
||||
|
||||
int sl = scanline + 1;
|
||||
int ppuon = (PPU[1] & 0x18);
|
||||
|
||||
if (!ppuon || sl >= 241)
|
||||
{
|
||||
// whenever rendering is off for any reason (vblank or forced disable
|
||||
// the irq counter resets, as well as the inframe flag (easily verifiable from software)
|
||||
MMC5IRQR &= ~0x40;
|
||||
MMC5IRQR &= ~0x80;
|
||||
MMC5LineCounter = 0;
|
||||
MMC5IRQR = 0x40;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
return;
|
||||
}
|
||||
if (MMC5LineCounter < 240) {
|
||||
if (MMC5LineCounter == IRQScanline) {
|
||||
|
||||
if (!(MMC5IRQR&0x40))
|
||||
{
|
||||
MMC5IRQR |= 0x40;
|
||||
MMC5IRQR &= ~0x80;
|
||||
MMC5LineCounter = 0;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
MMC5LineCounter++;
|
||||
if (MMC5LineCounter == IRQScanline)
|
||||
{
|
||||
MMC5IRQR |= 0x80;
|
||||
if (IRQEnable & 0x80)
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
MMC5LineCounter++;
|
||||
}
|
||||
if (MMC5LineCounter == 240)
|
||||
MMC5IRQR = 0;
|
||||
|
||||
}
|
||||
|
||||
void MMC5_StateRestore(int version) {
|
||||
@@ -727,22 +892,45 @@ void NSFMMC5_Init(void) {
|
||||
}
|
||||
|
||||
void NSFMMC5_Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
MMC5WRAMsize = 0;
|
||||
FCEU_gfree(ExRAM);
|
||||
ExRAM = 0;
|
||||
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();
|
||||
|
||||
@@ -760,16 +948,16 @@ static void GenMMC5Reset(void) {
|
||||
SetReadHandler(0x5205, 0x5206, MMC5_read);
|
||||
|
||||
// GameHBIRQHook=MMC5_hb;
|
||||
FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
||||
// FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
||||
FCEU_CheatAddRAM(1, 0x5c00, ExRAM);
|
||||
}
|
||||
|
||||
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" },
|
||||
@@ -783,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" },
|
||||
@@ -808,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");
|
||||
@@ -826,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];
|
||||
@@ -849,7 +1053,15 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
|
||||
}
|
||||
|
||||
void Mapper5_Init(CartInfo *info) {
|
||||
GenMMC5_Init(info, DetectMMC5WRAMSize(info->CRC32), info->battery);
|
||||
if (info->ines2)
|
||||
{
|
||||
WRAMSIZE = (info->wram_size + info->battery_wram_size) / 1024;
|
||||
}
|
||||
else
|
||||
{
|
||||
WRAMSIZE = DetectMMC5WRAMSize(info->CRC32);
|
||||
}
|
||||
GenMMC5_Init(info, WRAMSIZE, info->battery);
|
||||
}
|
||||
|
||||
// ELROM seems to have 0KB of WRAM
|
||||
|
||||
+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);
|
||||
}
|
||||
|
||||
+46
-11
@@ -32,21 +32,24 @@ static uint8 cpu410x[16], ppu201x[16], apu40xx[64];
|
||||
|
||||
// IRQ Registers
|
||||
static uint8 IRQCount, IRQa, IRQReload;
|
||||
#define IRQLatch cpu410x[0x1]
|
||||
#define IRQLatch cpu410x[0x1] // accc cccc, a = 0, AD12 switching, a = 1, HSYNC switching
|
||||
|
||||
// MMC3 Registers
|
||||
static uint8 inv_hack = 0; // some OneBus Systems have swapped PRG reg commans in MMC3 inplementation,
|
||||
// trying to autodetect unusual behavior, due not to add a new mapper.
|
||||
#define mmc3cmd cpu410x[0x5]
|
||||
#define mirror cpu410x[0x6]
|
||||
static uint8 inv_hack = 0; // some OneBus Systems have swapped PRG reg commans in MMC3 inplementation,
|
||||
// trying to autodetect unusual behavior, due not to add a new mapper.
|
||||
#define mmc3cmd cpu410x[0x5] // pcv- ----, p - program swap, c - video swap, v - internal VRAM enable
|
||||
#define mirror cpu410x[0x6] // ---- ---m, m = 0 - H, m = 1 - V
|
||||
|
||||
// APU Registers
|
||||
static uint8 pcm_enable = 0, pcm_irq = 0;
|
||||
static int16 pcm_addr, pcm_size, pcm_latch, pcm_clock = 0xF6;
|
||||
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" },
|
||||
@@ -113,7 +116,7 @@ static void CSync(void) {
|
||||
setchr1(0x1800 ^ cswap, block | (bank6 & mask));
|
||||
setchr1(0x1c00 ^ cswap, block | (bank7 & mask));
|
||||
|
||||
setmirror((mirror & 1) ^ 1);
|
||||
setmirror((mirror ^ 1) & 1);
|
||||
}
|
||||
|
||||
static void Sync(void) {
|
||||
@@ -124,7 +127,7 @@ static void Sync(void) {
|
||||
static DECLFW(UNLOneBusWriteCPU410X) {
|
||||
// FCEU_printf("CPU %04x:%04x\n",A,V);
|
||||
switch (A & 0xf) {
|
||||
case 0x1: IRQLatch = V & 0xfe; break;
|
||||
case 0x1: IRQLatch = V & 0xfe; break; // íå ïî äàòàøèòó
|
||||
case 0x2: IRQReload = 1; break;
|
||||
case 0x3: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break;
|
||||
case 0x4: IRQa = 1; break;
|
||||
@@ -180,17 +183,19 @@ static void UNLOneBusIRQHook(void) {
|
||||
}
|
||||
|
||||
static DECLFW(UNLOneBusWriteAPU40XX) {
|
||||
// FCEU_printf("APU %04x:%04x\n",A,V);
|
||||
// if(((A & 0x3f)!=0x16) && ((apu40xx[0x30] & 0x10) || ((A & 0x3f)>0x17)))FCEU_printf("APU %04x:%04x\n",A,V);
|
||||
apu40xx[A & 0x3f] = V;
|
||||
switch (A & 0x3f) {
|
||||
case 0x12:
|
||||
if (apu40xx[0x30] & 0x10) {
|
||||
pcm_addr = V << 6;
|
||||
}
|
||||
break;
|
||||
case 0x13:
|
||||
if (apu40xx[0x30] & 0x10) {
|
||||
pcm_size = (V << 4) + 1;
|
||||
}
|
||||
break;
|
||||
case 0x15:
|
||||
if (apu40xx[0x30] & 0x10) {
|
||||
pcm_enable = V & 0x10;
|
||||
@@ -202,6 +207,7 @@ static DECLFW(UNLOneBusWriteAPU40XX) {
|
||||
pcm_latch = pcm_clock;
|
||||
V &= 0xef;
|
||||
}
|
||||
break;
|
||||
}
|
||||
defapuwrite[A & 0x3f](A, V);
|
||||
}
|
||||
@@ -214,6 +220,7 @@ static DECLFR(UNLOneBusReadAPU40XX) {
|
||||
if (apu40xx[0x30] & 0x10) {
|
||||
result = (result & 0x7f) | pcm_irq;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -229,7 +236,8 @@ static void UNLOneBusCpuHook(int a) {
|
||||
pcm_enable = 0;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
} else {
|
||||
uint8 raw_pcm = ARead[pcm_addr](pcm_addr) >> 1;
|
||||
uint16 addr = pcm_addr | ((apu40xx[0x30]^3) << 14);
|
||||
uint8 raw_pcm = ARead[addr](addr) >> 1;
|
||||
defapuwrite[0x11](0x4011, raw_pcm);
|
||||
pcm_addr++;
|
||||
pcm_addr &= 0x7FFF;
|
||||
@@ -260,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();
|
||||
}
|
||||
|
||||
@@ -277,11 +292,18 @@ 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
|
||||
if (((*(uint32*)&(info->MD5)) == 0x305fcdc3) || // PowerJoy Supermax Carts
|
||||
((*(uint32*)&(info->MD5)) == 0x6abfce8e))
|
||||
inv_hack = 0xf;
|
||||
|
||||
@@ -289,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"
|
||||
@@ -101,6 +104,7 @@ static void UNLPEC586Power(void) {
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x5000, 0x5fff, UNLPEC586Write);
|
||||
SetReadHandler(0x5000, 0x5fff, UNLPEC586Read);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void UNLPEC586Close(void) {
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2016 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
|
||||
*
|
||||
* Test Ver. 1.01 Dlya Proverki TV Pristavok (RT-01, by SS aka Snake)
|
||||
* A simple board with 16K PRG ROM + 2K CHR ROM with no mapper, hardwired mirroring
|
||||
* PRG EPROM has copy protected areas with "weak bits", which is tested at some
|
||||
* points of the program. Trying to simalate "weak bits" behaviour
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
extern u64 xoroshiro128plus_next(); // deterministic random
|
||||
|
||||
static DECLFR(UNLRT01Read) {
|
||||
// u16 i, prot_areas[2][2] = {
|
||||
// { 0x8E80, 0x8EFF },
|
||||
// { 0xFE80, 0xFEFF },
|
||||
// };
|
||||
if(((A >= 0xCE80) && (A < 0xCF00)) ||
|
||||
((A >= 0xFE80) && (A < 0xFF00))) {
|
||||
return 0xF2 | (xoroshiro128plus_next() & 0x0D);
|
||||
} else
|
||||
return CartBR(A);
|
||||
}
|
||||
|
||||
static void UNLRT01Power(void) {
|
||||
setprg16(0x8000, 0);
|
||||
setprg16(0xC000, 0);
|
||||
setchr2(0x0000,0);
|
||||
setchr2(0x0800,0);
|
||||
setchr2(0x1000,0);
|
||||
setchr2(0x1800,0);
|
||||
SetReadHandler(0x8000, 0xFFFF, UNLRT01Read);
|
||||
}
|
||||
|
||||
void UNLRT01_Init(CartInfo *info) {
|
||||
info->Power = UNLRT01Power;
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2014 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 preg[8];
|
||||
static uint8 IRQa;
|
||||
static int16 IRQCount, IRQLatch;
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
/*
|
||||
static uint8 *CHRRAM = NULL;
|
||||
static uint32 CHRRAMSIZE;
|
||||
*/
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ preg, 8, "PREG" },
|
||||
{ &IRQa, 1, "IRQA" },
|
||||
{ &IRQCount, 2, "IRQC" },
|
||||
{ &IRQLatch, 2, "IRQL" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setchr8(0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
if(preg[0] & 0x80)
|
||||
setprg4r(0x10,0x8000,preg[0] & 0x7f);
|
||||
else
|
||||
setprg4(0x8000,preg[0] & 0x7f);
|
||||
if(preg[1] & 0x80)
|
||||
setprg4r(0x10,0x9000,preg[1] & 0x7f);
|
||||
else
|
||||
setprg4(0x9000,preg[1] & 0x7f);
|
||||
if(preg[2] & 0x80)
|
||||
setprg4r(0x10,0xa000,preg[2] & 0x7f);
|
||||
else
|
||||
setprg4(0xa000,preg[2] & 0x7f);
|
||||
if(preg[3] & 0x80)
|
||||
setprg4r(0x10,0xb000,preg[3] & 0x7f);
|
||||
else
|
||||
setprg4(0xb000,preg[3] & 0x7f);
|
||||
/*
|
||||
if(preg[4] & 0x80)
|
||||
setprg4r(0x10,0xc000,preg[4] & 0x7f);
|
||||
else
|
||||
setprg4(0xc000,preg[4] & 0x7f);
|
||||
if(preg[5] & 0x80)
|
||||
setprg4r(0x10,0xd000,preg[5] & 0x7f);
|
||||
else
|
||||
setprg4(0xd000,preg[5] & 0x7f);
|
||||
if(preg[6] & 0x80)
|
||||
setprg4r(0x10,0xe000,preg[6] & 0x7f);
|
||||
else
|
||||
setprg4(0xe000,preg[6] & 0x7f);
|
||||
if(preg[7] & 0x80)
|
||||
setprg4r(0x10,0xf000,preg[7] & 0x7f);
|
||||
else
|
||||
setprg4(0xf000,preg[7] & 0x7f);
|
||||
*/
|
||||
setprg16(0xC000,1);
|
||||
}
|
||||
|
||||
static DECLFR(UNLSB2000Read) {
|
||||
switch(A) {
|
||||
case 0x4033: // IRQ flags
|
||||
X6502_IRQEnd(FCEU_IQFCOUNT);
|
||||
return 0xff;
|
||||
// case 0x4204: // unk
|
||||
// return 0xff;
|
||||
// case 0x4205: // unk
|
||||
// return 0xff;
|
||||
default:
|
||||
FCEU_printf("unk read: %04x\n",A);
|
||||
// break;
|
||||
return 0xff; // needed to prevent C4715 warning?
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(UNLSB2000Write) {
|
||||
switch(A) {
|
||||
case 0x4027: // PCM output
|
||||
BWrite[0x4015](0x4015, 0x10);
|
||||
BWrite[0x4011](0x4011, V >> 1);
|
||||
break;
|
||||
case 0x4032: // IRQ mask
|
||||
IRQa &= ~V;
|
||||
// X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 0x4040:
|
||||
case 0x4041:
|
||||
case 0x4042:
|
||||
case 0x4043:
|
||||
case 0x4044:
|
||||
case 0x4045:
|
||||
case 0x4046:
|
||||
case 0x4047:
|
||||
// FCEU_printf("bank write: %04x:%02x\n",A,V);
|
||||
preg[A&7] = V;
|
||||
Sync();
|
||||
break;
|
||||
default:
|
||||
// FCEU_printf("unk write: %04x:%02x\n",A,V);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void UNLSB2000Reset(void) {
|
||||
preg[0] = 0;
|
||||
preg[1] = 1;
|
||||
preg[2] = 2;
|
||||
preg[3] = 3;
|
||||
preg[4] = 4;
|
||||
preg[5] = 5;
|
||||
preg[6] = 6;
|
||||
preg[7] = 7;
|
||||
IRQa = 0;
|
||||
// BWrite[0x4017](0x4017,0xC0);
|
||||
// BWrite[0x4015](0x4015,0x1F);
|
||||
}
|
||||
|
||||
static void UNLSB2000Power(void) {
|
||||
UNLSB2000Reset();
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0x7fff, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x8000, 0xbfff, CartBW);
|
||||
SetWriteHandler(0x4020, 0x5fff, UNLSB2000Write);
|
||||
SetReadHandler(0x4020, 0x5fff, UNLSB2000Read);
|
||||
}
|
||||
|
||||
static void UNLSB2000Close(void)
|
||||
{
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
/*
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
*/
|
||||
WRAM = /*CHRRAM = */NULL;
|
||||
}
|
||||
/*
|
||||
static void UNLSB2000IRQHook() {
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
*/
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void UNLSB2000_Init(CartInfo *info) {
|
||||
info->Reset = UNLSB2000Reset;
|
||||
info->Power = UNLSB2000Power;
|
||||
info->Close = UNLSB2000Close;
|
||||
// GameHBIRQHook = UNLSB2000IRQHook;
|
||||
GameStateRestore = StateRestore;
|
||||
/*
|
||||
CHRRAMSIZE = 8192;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM");
|
||||
*/
|
||||
|
||||
// SetupCartCHRMapping(0, PRGptr[0], PRGsize[0], 0);
|
||||
|
||||
WRAMSIZE = 512 * 1024;
|
||||
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;
|
||||
}
|
||||
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
+15
-6
@@ -31,16 +31,18 @@ static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ reg, 8, "REGS" },
|
||||
{ chr, 8, "CHRS" },
|
||||
{ &IRQCount, 16, "IRQc" },
|
||||
{ &IRQa, 16, "IRQa" },
|
||||
{ &IRQCount, 2, "IRQc" },
|
||||
{ &IRQa, 2, "IRQa" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
int i;
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
setprg8(0x8000, reg[0]);
|
||||
setprg8(0xA000, reg[1]);
|
||||
setprg8(0xC000, reg[2]);
|
||||
setprg8(0xE000, ~0);
|
||||
for (i = 0; i < 8; i++)
|
||||
setchr1(i << 10, chr[i]);
|
||||
setmirror(reg[3] ^ 1);
|
||||
@@ -67,20 +69,26 @@ static DECLFW(UNLSC127Write) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFR(UNLSC127ProtRead) {
|
||||
return 0x20;
|
||||
}
|
||||
|
||||
static void UNLSC127Power(void) {
|
||||
IRQCount = IRQa = 0;
|
||||
Sync();
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
setprg8(0xE000, ~0);
|
||||
SetReadHandler(0x5800, 0x5800, UNLSC127ProtRead);
|
||||
SetReadHandler(0x6000, 0x7fff, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, UNLSC127Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void UNLSC127IRQ(void) {
|
||||
if (IRQa) {
|
||||
IRQCount--;
|
||||
if (IRQCount == 0) {
|
||||
if(IRQCount > 0)
|
||||
IRQCount--;
|
||||
if (!IRQCount) {
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
IRQa = 0;
|
||||
}
|
||||
@@ -88,6 +96,7 @@ static void UNLSC127IRQ(void) {
|
||||
}
|
||||
|
||||
static void UNLSC127Reset(void) {
|
||||
IRQCount = IRQa = 0;
|
||||
}
|
||||
|
||||
static void UNLSC127Close(void) {
|
||||
|
||||
@@ -71,6 +71,7 @@ static void TransformerPower(void) {
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
|
||||
MapIRQHook = TransformerIRQHook;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2014 CaitSith2
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Roms still using NES 1.0 format should be loaded as 32K CHR RAM.
|
||||
* Roms defined under NES 2.0 should use the VRAM size field, defining 7, 8 or 9, based on how much VRAM should be present.
|
||||
* UNIF doesn't have this problem, because unique board names can define this information.
|
||||
* The UNIF names are UNROM-512-8K, UNROM-512-16K and UNROM-512-32K
|
||||
*
|
||||
* The battery flag in the NES header enables flash, Mirrror mode 2 Enables MI_0 and MI_1 mode.
|
||||
* Known games to use this board are:
|
||||
* Battle Kid 2: Mountain of Torment (512K PRG, 8K CHR RAM, Horizontal Mirroring, Flash disabled)
|
||||
* Study Hall (128K PRG (in 512K flash chip), 8K CHR RAM, Horizontal Mirroring, Flash enabled)
|
||||
* Although Xmas 2013 uses a different board, where LEDs can be controlled (with writes to the $8000-BFFF space),
|
||||
* it otherwise functions identically.
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "../ines.h"
|
||||
|
||||
static uint8 latche, latcheinit, bus_conflict, chrram_mask, software_id=false;
|
||||
static uint16 latcha;
|
||||
static uint8 *flashdata;
|
||||
static uint32 *flash_write_count;
|
||||
static uint8 *FlashPage[32];
|
||||
//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;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
flash_write_count[(bank*4) + ((A&0x3000)>>12)]++;
|
||||
if(!flash_write_count[(bank*4) + ((A&0x3000)>>12)])
|
||||
flash_write_count[(bank*4) + ((A&0x3000)>>12)]++;
|
||||
}
|
||||
|
||||
uint32 GetFlashWriteCount(uint8 bank, uint32 A)
|
||||
{
|
||||
return flash_write_count[(bank*4) + ((A&0x3000)>>12)];
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
WHSync();
|
||||
}
|
||||
|
||||
static DECLFW(UNROM512LLatchWrite)
|
||||
{
|
||||
latche = V;
|
||||
latcha = A;
|
||||
WLSync();
|
||||
}
|
||||
|
||||
static DECLFW(UNROM512HLatchWrite)
|
||||
{
|
||||
if (bus_conflict)
|
||||
latche = (V == CartBR(A)) ? V : 0;
|
||||
else
|
||||
latche = V;
|
||||
latcha = A;
|
||||
WHSync();
|
||||
}
|
||||
|
||||
static DECLFR(UNROM512LatchRead)
|
||||
{
|
||||
uint8 flash_id[3]={0xB5,0xB6,0xB7};
|
||||
if(software_id)
|
||||
{
|
||||
if(A&1)
|
||||
return flash_id[ROM_size>>4];
|
||||
else
|
||||
return 0xBF;
|
||||
}
|
||||
if(flash_save)
|
||||
{
|
||||
if(A < 0xC000)
|
||||
{
|
||||
if(GetFlashWriteCount(flash_bank,A))
|
||||
return FlashPage[A >> 11][A];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(GetFlashWriteCount(ROM_size-1,A))
|
||||
return FlashPage[A >> 11][A];
|
||||
}
|
||||
}
|
||||
return Page[A >> 11][A];
|
||||
}
|
||||
|
||||
static void UNROM512LatchPower(void) {
|
||||
latche = latcheinit;
|
||||
WHSync();
|
||||
SetReadHandler(0x8000, 0xFFFF, UNROM512LatchRead);
|
||||
if(!flash_save)
|
||||
SetWriteHandler(0x8000, 0xFFFF, UNROM512HLatchWrite);
|
||||
else
|
||||
{
|
||||
SetWriteHandler(0x8000,0xBFFF,UNROM512LLatchWrite);
|
||||
SetWriteHandler(0xC000,0xFFFF,UNROM512HLatchWrite);
|
||||
}
|
||||
}
|
||||
|
||||
static void UNROM512LatchClose(void) {
|
||||
if(flash_write_count)
|
||||
FCEU_gfree(flash_write_count);
|
||||
if(flashdata)
|
||||
FCEU_gfree(flashdata);
|
||||
flash_write_count = NULL;
|
||||
flashdata = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void UNROM512LSync() {
|
||||
int erase_a[5]={0x9555,0xAAAA,0x9555,0x9555,0xAAAA};
|
||||
int erase_d[5]={0xAA,0x55,0x80,0xAA,0x55};
|
||||
int erase_b[5]={1,0,1,1,0};
|
||||
|
||||
if(flash_mode==0)
|
||||
{
|
||||
if((latcha == erase_a[flash_state]) && (latche == erase_d[flash_state]) && (flash_bank == erase_b[flash_state]))
|
||||
{
|
||||
flash_state++;
|
||||
if(flash_state == 5)
|
||||
{
|
||||
flash_mode=1;
|
||||
}
|
||||
}
|
||||
else if ((flash_state==2)&&(latcha==0x9555)&&(latche==0xA0)&&(flash_bank==1))
|
||||
{
|
||||
flash_state++;
|
||||
flash_mode=2;
|
||||
}
|
||||
else if ((flash_state==2)&&(latcha==0x9555)&&(latche==0x90)&&(flash_bank==1))
|
||||
{
|
||||
flash_state=0;
|
||||
software_id=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(latche==0xF0)
|
||||
software_id=false;
|
||||
flash_state=0;
|
||||
}
|
||||
}
|
||||
else if(flash_mode==1) //Chip Erase or Sector Erase
|
||||
{
|
||||
if(latche==0x30)
|
||||
{
|
||||
inc_flash_write_count(flash_bank,latcha);
|
||||
memset(&FlashPage[(latcha & 0xF000) >> 11][latcha & 0xF000],0xFF,0x1000);
|
||||
}
|
||||
else if (latche==0x10)
|
||||
{
|
||||
for(uint32 i=0;i<(ROM_size*4);i++)
|
||||
inc_flash_write_count(i>>2,i<<12);
|
||||
memset(flashdata,0xFF,ROM_size*0x4000); //Erasing the rom chip as instructed. Crash rate calulated to be 99.9% :)
|
||||
}
|
||||
flash_state=0;
|
||||
flash_mode=0;
|
||||
}
|
||||
else if(flash_mode==2) //Byte Program
|
||||
{
|
||||
if(!GetFlashWriteCount(flash_bank,latcha))
|
||||
{
|
||||
inc_flash_write_count(flash_bank,latcha);
|
||||
memcpy(&FlashPage[(latcha & 0xF000) >> 11][latcha & 0xF000],&Page[(latcha & 0xF000)>>11][latcha & 0xF000],0x1000);
|
||||
}
|
||||
FlashPage[latcha>>11][latcha]&=latche;
|
||||
flash_state=0;
|
||||
flash_mode=0;
|
||||
}
|
||||
}
|
||||
|
||||
static void UNROM512HSync()
|
||||
{
|
||||
flash_bank=latche&(ROM_size-1);
|
||||
|
||||
setprg16(0x8000, flash_bank);
|
||||
setprg16(0xc000, ~0);
|
||||
setfprg16(0x8000, flash_bank);
|
||||
setfprg16(0xC000, ~0);
|
||||
setchr8r(0, (latche & chrram_mask) >> 5);
|
||||
setmirror(MI_0+(latche>>7));
|
||||
}
|
||||
|
||||
void UNROM512_Init(CartInfo *info) {
|
||||
flash_state=0;
|
||||
flash_bank=0;
|
||||
flash_save=info->battery;
|
||||
|
||||
if(info->vram_size == 8192)
|
||||
chrram_mask = 0;
|
||||
else if (info->vram_size == 16384)
|
||||
chrram_mask = 0x20;
|
||||
else
|
||||
chrram_mask = 0x60;
|
||||
|
||||
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;
|
||||
WHSync = UNROM512HSync;
|
||||
info->Power = UNROM512LatchPower;
|
||||
info->Close = UNROM512LatchClose;
|
||||
GameStateRestore = StateRestore;
|
||||
if(flash_save)
|
||||
{
|
||||
flashdata = (uint8*)FCEU_gmalloc(ROM_size*0x4000);
|
||||
flash_write_count = (uint32*)FCEU_gmalloc(ROM_size*4*sizeof(uint32));
|
||||
info->SaveGame[0] = (uint8*)flash_write_count;
|
||||
info->SaveGame[1] = flashdata;
|
||||
info->SaveGameLen[0] = ROM_size*4*sizeof(uint32);
|
||||
info->SaveGameLen[1] = ROM_size*0x4000;
|
||||
AddExState(flash_write_count,ROM_size*4*sizeof(uint32),0,"FLASH_WRITE_COUNT");
|
||||
AddExState(flashdata,ROM_size*0x4000,0,"FLASH_DATA");
|
||||
AddExState(&flash_state,1,0,"FLASH_STATE");
|
||||
AddExState(&flash_mode,1,0,"FLASH_MODE");
|
||||
AddExState(&flash_bank,1,0,"FLASH_BANK");
|
||||
AddExState(&latcha,2,0,"LATA");
|
||||
}
|
||||
AddExState(&latche, 1, 0, "LATC");
|
||||
AddExState(&bus_conflict, 1, 0, "BUSC");
|
||||
}
|
||||
+49
-90
@@ -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,59 +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);
|
||||
}
|
||||
|
||||
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);
|
||||
SetWriteHandler(0x8000, 0xFFFF, VRC24Write);
|
||||
}
|
||||
|
||||
void VRC24IRQHook(int a) {
|
||||
@@ -208,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;
|
||||
@@ -245,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);
|
||||
}
|
||||
|
||||
@@ -106,6 +106,7 @@ static void M73Power(void) {
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M73Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M73Close(void)
|
||||
|
||||
+160
-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,49 +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;
|
||||
@@ -200,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);
|
||||
@@ -218,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);
|
||||
|
||||
@@ -127,6 +127,7 @@ static void VRC6Power(void) {
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetWriteHandler(0x8000, 0xFFFF, VRC6Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void VRC6IRQHook(int a) {
|
||||
|
||||
+10
-7
@@ -26,6 +26,12 @@ static int32 IRQCount, CycleCount;
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
|
||||
#include "emu2413.h"
|
||||
|
||||
static int32 dwave = 0;
|
||||
static OPLL *VRC7Sound = NULL;
|
||||
static OPLL **VRC7Sound_saveptr = &VRC7Sound;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &vrc7idx, 1, "VRCI" },
|
||||
@@ -37,16 +43,12 @@ static SFORMAT StateRegs[] =
|
||||
{ &IRQLatch, 1, "IRQL" },
|
||||
{ &IRQCount, 4, "IRQC" },
|
||||
{ &CycleCount, 4, "CYCC" },
|
||||
{ 0 }
|
||||
{ (void**)VRC7Sound_saveptr, sizeof(*VRC7Sound) | FCEUSTATE_INDIRECT, "VRC7" },
|
||||
{0}
|
||||
};
|
||||
|
||||
// VRC7 Sound
|
||||
|
||||
#include "emu2413.h"
|
||||
|
||||
static int32 dwave = 0;
|
||||
static OPLL *VRC7Sound = NULL;
|
||||
|
||||
void DoVRC7Sound(void) {
|
||||
int32 z, a;
|
||||
if (FSettings.soundq >= 1)
|
||||
@@ -84,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);
|
||||
}
|
||||
@@ -151,6 +153,7 @@ static void VRC7Power(void) {
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, VRC7Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void VRC7Close(void)
|
||||
|
||||
@@ -174,6 +174,7 @@ static void M83Power(void) {
|
||||
SetWriteHandler(0x6000, 0x7fff, CartBW); // Pirate Dragon Ball Z Party [p1] used if for saves instead of seraial EEPROM
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x8000, 0xffff, M83Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void UNLYOKOReset(void) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+13
@@ -1,3 +1,6 @@
|
||||
#ifndef CART_H
|
||||
#define CART_H
|
||||
|
||||
typedef struct {
|
||||
// Set by mapper/board code:
|
||||
void (*Power)(void);
|
||||
@@ -13,12 +16,20 @@ typedef struct {
|
||||
// that are not really MMC3 but are
|
||||
// set to mapper 4.
|
||||
int battery; // Presence of an actual battery.
|
||||
int ines2;
|
||||
int submapper; // Submappers as defined by NES 2.0
|
||||
int wram_size;
|
||||
int battery_wram_size;
|
||||
int vram_size;
|
||||
int battery_vram_size;
|
||||
uint8 MD5[16];
|
||||
uint32 CRC32; // Should be set by the iNES/UNIF loading
|
||||
// code, used by mapper/board code, maybe
|
||||
// other code in the future.
|
||||
} CartInfo;
|
||||
|
||||
extern CartInfo *currCartInfo;
|
||||
|
||||
void FCEU_SaveGameSave(CartInfo *LocalHWInfo);
|
||||
void FCEU_LoadGameSave(CartInfo *LocalHWInfo);
|
||||
void FCEU_ClearGameSave(CartInfo *LocalHWInfo);
|
||||
@@ -92,3 +103,5 @@ void FCEU_GeniePower(void);
|
||||
bool FCEU_OpenGenie(void);
|
||||
void FCEU_CloseGenie(void);
|
||||
void FCEU_KillGenie(void);
|
||||
|
||||
#endif
|
||||
|
||||
+297
-302
@@ -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,140 +813,68 @@ 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)
|
||||
{
|
||||
// if(CheatRPtrs[A>>10])
|
||||
// return CheatRPtrs[A>>10][A]; //adelikat-commenting this stuff out so that lua can see frozen addresses, I hope this doesn't bork stuff.
|
||||
/*else*/ if(A < 0x10000)
|
||||
return ARead[A](A);
|
||||
else
|
||||
return 0;
|
||||
if(A < 0x10000) {
|
||||
uint32 ret;
|
||||
fceuindbg=1;
|
||||
ret = ARead[A](A);
|
||||
fceuindbg=0;
|
||||
return ret;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FCEU_CheatSetByte(uint32 A, uint8 V)
|
||||
@@ -947,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
|
||||
{
|
||||
|
||||
+19
-7
@@ -13,15 +13,23 @@
|
||||
|
||||
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, adelikat, AnS\n\n"
|
||||
"zeromus, mjbudd77, feos\n"
|
||||
"\n"
|
||||
"Current Contributors:\n"
|
||||
"punkrockguy318 (Lukas Sabota)\n"
|
||||
"CaH4e3, gocha, xhainingx, feos\n"
|
||||
"CaH4e3, rainwarrior, owomomo, punkrockguy318\n"
|
||||
"\n"
|
||||
"Past Contributors:\n"
|
||||
"xhainingx, gocha, AnS\n"
|
||||
"\n"
|
||||
"FCEUX 2.0:\n"
|
||||
"mz, nitsujrehtona, SP, Ugly Joe,\n"
|
||||
@@ -37,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();
|
||||
|
||||
@@ -51,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;
|
||||
}
|
||||
|
||||
+269
-111
@@ -14,7 +14,7 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
unsigned int debuggerPageSize = 14;
|
||||
int vblankScanLines = 0; //Used to calculate scanlines 240-261 (vblank)
|
||||
int vblankPixel = 0; //Used to calculate the pixels in vblank
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,12 +262,12 @@ int getBank(int offs)
|
||||
|
||||
if (GameInfo && GameInfo->type==GIT_NSF)
|
||||
return addr != -1 ? addr / 0x1000 : -1;
|
||||
return addr != -1 ? addr / 0x4000 : -1;
|
||||
return addr != -1 ? addr / (1<<debuggerPageSize) : -1; //formerly, dividing by 0x4000
|
||||
}
|
||||
|
||||
int GetNesFileAddress(int A){
|
||||
int result;
|
||||
if((A < 0x8000) || (A > 0xFFFF))return -1;
|
||||
if((A < 0x6000) || (A > 0xFFFF))return -1;
|
||||
result = &Page[A>>11][A]-PRGptr[0];
|
||||
if((result > (int)(PRGsize[0])) || (result < 0))return -1;
|
||||
else return result+16; //16 bytes for the header remember
|
||||
@@ -263,7 +293,7 @@ uint8 *GetNesCHRPointer(int A){
|
||||
}
|
||||
|
||||
uint8 GetMem(uint16 A) {
|
||||
if ((A >= 0x2000) && (A < 0x4000)) {
|
||||
if ((A >= 0x2000) && (A < 0x4000)) // PPU regs and their mirrors
|
||||
switch (A&7) {
|
||||
case 0: return PPU[0];
|
||||
case 1: return PPU[1];
|
||||
@@ -271,16 +301,36 @@ uint8 GetMem(uint16 A) {
|
||||
case 3: return PPU[3];
|
||||
case 4: return SPRAM[PPU[3]];
|
||||
case 5: return XOffset;
|
||||
case 6: return RefreshAddr&0xFF;
|
||||
case 6: return FCEUPPU_PeekAddress() & 0xFF;
|
||||
case 7: return VRAMBuffer;
|
||||
}
|
||||
} else if ((A >= 0x4000) && (A < 0x5000)) return 0xFF; // AnS: changed the range, so MMC5 ExRAM can be watched in the Hexeditor
|
||||
if (GameInfo) return ARead[A](A); //adelikat: 11/17/09: Prevent crash if this is called with no game loaded.
|
||||
else return 0;
|
||||
// feos: added more registers
|
||||
else if ((A >= 0x4000) && (A < 0x4010))
|
||||
return PSG[A&15];
|
||||
else if ((A >= 0x4010) && (A < 0x4018))
|
||||
switch(A&7) {
|
||||
case 0: return DMCFormat;
|
||||
case 1: return RawDALatch;
|
||||
case 2: return DMCAddressLatch;
|
||||
case 3: return DMCSizeLatch;
|
||||
case 4: return SpriteDMA;
|
||||
case 5: return EnabledChannels;
|
||||
case 6: return RawReg4016;
|
||||
case 7: return IRQFrameMode;
|
||||
}
|
||||
else if ((A >= 0x4018) && (A < 0x5000)) // AnS: changed the range, so MMC5 ExRAM can be watched in the Hexeditor
|
||||
return 0xFF;
|
||||
if (GameInfo) { //adelikat: 11/17/09: Prevent crash if this is called with no game loaded.
|
||||
uint32 ret;
|
||||
fceuindbg=1;
|
||||
ret = ARead[A](A);
|
||||
fceuindbg=0;
|
||||
return ret;
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
uint8 GetPPUMem(uint8 A) {
|
||||
uint16 tmp=RefreshAddr&0x3FFF;
|
||||
uint16 tmp = FCEUPPU_PeekAddress() & 0x3FFF;
|
||||
|
||||
if (tmp<0x2000) return VPage[tmp>>10][tmp];
|
||||
if (tmp>=0x3F00) return PALRAM[tmp&0x1F];
|
||||
@@ -289,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)
|
||||
{
|
||||
@@ -314,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;
|
||||
@@ -339,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)
|
||||
@@ -351,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;
|
||||
@@ -370,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){
|
||||
@@ -397,19 +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;
|
||||
if(indirectnext)cdloggerdata[j+i] |= 0x10;
|
||||
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;
|
||||
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)
|
||||
@@ -422,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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,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) {
|
||||
@@ -554,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;
|
||||
}
|
||||
|
||||
@@ -566,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;
|
||||
}
|
||||
}
|
||||
@@ -575,46 +703,50 @@ 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
|
||||
if ((watchpoint[i].flags & brk_type) && ((A >= 0x2000) && (A < 0x4000)) && ((A&7) == 7))
|
||||
{
|
||||
const uint32 PPUAddr = FCEUPPU_PeekAddress();
|
||||
if (watchpoint[i].endaddress)
|
||||
{
|
||||
if ((watchpoint[i].address <= RefreshAddr) && (watchpoint[i].endaddress >= RefreshAddr))
|
||||
BreakHit(i);
|
||||
if ((watchpoint[i].address <= PPUAddr) && (watchpoint[i].endaddress >= PPUAddr))
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == RefreshAddr)
|
||||
BreakHit(i);
|
||||
if (watchpoint[i].address == PPUAddr)
|
||||
BREAKHIT(i);
|
||||
}
|
||||
}
|
||||
} else if (watchpoint[i].flags & BT_S)
|
||||
@@ -625,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
|
||||
{
|
||||
@@ -645,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
|
||||
{
|
||||
@@ -667,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -682,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
|
||||
@@ -693,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)
|
||||
@@ -711,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -724,20 +876,27 @@ 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
|
||||
|
||||
void DebugCycle()
|
||||
{
|
||||
uint8 opcode[3] = {0};
|
||||
uint16 A = 0;
|
||||
uint16 A = 0, tmp;
|
||||
int size;
|
||||
|
||||
if (scanline == 240)
|
||||
@@ -759,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);
|
||||
@@ -772,18 +934,19 @@ void DebugCycle()
|
||||
{
|
||||
case 0: break;
|
||||
case 1:
|
||||
A = (opcode[1] + _X) & 0xFF;
|
||||
A = GetMem(A) | (GetMem(A + 1) << 8);
|
||||
tmp = (opcode[1] + _X) & 0xFF;
|
||||
A = GetMem(tmp);
|
||||
tmp = (opcode[1] + _X + 1) & 0xFF;
|
||||
A |= (GetMem(tmp) << 8);
|
||||
break;
|
||||
case 2: A = opcode[1]; break;
|
||||
case 3: A = opcode[1] | (opcode[2] << 8); break;
|
||||
case 4: A = (GetMem(opcode[1]) | (GetMem(opcode[1]+1) << 8)) + _Y; break;
|
||||
case 4: A = (GetMem(opcode[1]) | (GetMem((opcode[1] + 1) & 0xFF) << 8)) + _Y; break;
|
||||
case 5: A = opcode[1] + _X; break;
|
||||
case 6: A = (opcode[1] | (opcode[2] << 8)) + _Y; break;
|
||||
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);
|
||||
@@ -791,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
|
||||
|
||||
}
|
||||
|
||||
+24
-10
@@ -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,10 +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 uint32 RefreshAddr;
|
||||
|
||||
extern int debug_loggingCD;
|
||||
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
|
||||
@@ -148,6 +152,16 @@ public:
|
||||
|
||||
extern NSF_HEADER NSFHeader;
|
||||
|
||||
extern uint8 PSG[0x10];
|
||||
extern uint8 DMCFormat;
|
||||
extern uint8 RawDALatch;
|
||||
extern uint8 DMCAddressLatch;
|
||||
extern uint8 DMCSizeLatch;
|
||||
extern uint8 EnabledChannels;
|
||||
extern uint8 SpriteDMA;
|
||||
extern uint8 RawReg4016;
|
||||
extern uint8 IRQFrameMode;
|
||||
|
||||
///retrieves the core's DebuggerState
|
||||
DebuggerState &FCEUI_Debugger();
|
||||
|
||||
|
||||
+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];
|
||||
|
||||
|
||||
+23
-8
@@ -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
|
||||
@@ -68,7 +70,7 @@ void FCEUI_NTSCSELTINT(void);
|
||||
void FCEUI_NTSCDEC(void);
|
||||
void FCEUI_NTSCINC(void);
|
||||
void FCEUI_GetNTSCTH(int *tint, int *hue);
|
||||
void FCEUI_SetNTSCTH(int n, int tint, int hue);
|
||||
void FCEUI_SetNTSCTH(bool en, int tint, int hue);
|
||||
|
||||
void FCEUI_SetInput(int port, ESI type, void *ptr, int attrib);
|
||||
void FCEUI_SetInputFC(ESIFC type, void *ptr, int attrib);
|
||||
@@ -120,6 +122,11 @@ void FCEUI_SetGameGenie(bool a);
|
||||
//Set video system a=0 NTSC, a=1 PAL
|
||||
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, 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);
|
||||
|
||||
@@ -136,10 +143,10 @@ 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);
|
||||
|
||||
//Tells FCE Ultra to copy the palette data pointed to by pal and use it.
|
||||
//Data pointed to by pal needs to be 64*3 bytes in length.
|
||||
void FCEUI_SetPaletteArray(uint8 *pal);
|
||||
bool FCEUI_GetUserPaletteAvail(void);
|
||||
void FCEUI_SetUserPalette(uint8 *pal, int nEntries);
|
||||
|
||||
//Sets up sound code to render sound at the specified rate, in samples
|
||||
//per second. Only sample rates of 44100, 48000, and 96000 are currently supported.
|
||||
@@ -176,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);
|
||||
@@ -187,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));
|
||||
@@ -245,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();
|
||||
@@ -335,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')
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user