5 Commits

Author SHA1 Message Date
clobber 7e9cde361e Build fix
Now requires a minimum of C++11: Use of undeclared identifier 'nullptr'
2023-06-20 20:07:39 -06:00
clobber ee3ffeeacc Merge pull request #12 from ShutOstrich/master
Update to FCEUX 2.6.5
2023-04-29 20:40:56 -06:00
ShutOstrich 8a1427db5c Update to FCEUX 2.6.5 2023-04-30 00:37:54 +02:00
ShutOstrich 10724c5437 Disable "Reset" message 2023-04-30 00:32:10 +02:00
clobber 88b1044105 Fix -ringBufferAtIndex: deprecation warning. 2022-12-24 17:10:23 -07:00
80 changed files with 6181 additions and 1289 deletions
+26
View File
@@ -67,6 +67,11 @@
87709EE3294D2B0D0084AEE0 /* lcdcompzapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 87709EE2294D2B0D0084AEE0 /* lcdcompzapper.cpp */; };
8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
8F28FD5029FD3E7D008FC4A9 /* 354.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F28FD4D29FD3E7D008FC4A9 /* 354.cpp */; };
8F28FD5129FD3E7D008FC4A9 /* coolgirl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F28FD4E29FD3E7D008FC4A9 /* coolgirl.cpp */; };
8F28FD5229FD3E7D008FC4A9 /* inx007t.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F28FD4F29FD3E7D008FC4A9 /* inx007t.cpp */; };
8F28FD5529FD3EA4008FC4A9 /* debugsymboltable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F28FD5329FD3EA4008FC4A9 /* debugsymboltable.cpp */; };
8F28FD5829FD3EB8008FC4A9 /* mutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F28FD5629FD3EB8008FC4A9 /* mutex.cpp */; };
945942D014E4F2DC0015D2AA /* FCEUX.icns in Resources */ = {isa = PBXBuildFile; fileRef = 945942CF14E4F2DC0015D2AA /* FCEUX.icns */; };
949BBA741A9EF079007B49CC /* 01-222.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949BB7521A9EED55007B49CC /* 01-222.cpp */; };
949BBA751A9EF079007B49CC /* 09-034a.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949BB7531A9EED55007B49CC /* 09-034a.cpp */; };
@@ -334,6 +339,13 @@
87709EE2294D2B0D0084AEE0 /* lcdcompzapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lcdcompzapper.cpp; sourceTree = "<group>"; };
8D5B49B6048680CD000E48DA /* FCEU.oecoreplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FCEU.oecoreplugin; sourceTree = BUILT_PRODUCTS_DIR; };
8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8F28FD4D29FD3E7D008FC4A9 /* 354.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 354.cpp; sourceTree = "<group>"; };
8F28FD4E29FD3E7D008FC4A9 /* coolgirl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coolgirl.cpp; sourceTree = "<group>"; };
8F28FD4F29FD3E7D008FC4A9 /* inx007t.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inx007t.cpp; sourceTree = "<group>"; };
8F28FD5329FD3EA4008FC4A9 /* debugsymboltable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debugsymboltable.cpp; sourceTree = "<group>"; };
8F28FD5429FD3EA4008FC4A9 /* debugsymboltable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debugsymboltable.h; sourceTree = "<group>"; };
8F28FD5629FD3EB8008FC4A9 /* mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mutex.cpp; sourceTree = "<group>"; };
8F28FD5729FD3EB8008FC4A9 /* mutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mutex.h; sourceTree = "<group>"; };
945942CE14E4EF180015D2AA /* OENESSystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OENESSystemResponderClient.h; path = ../OpenEmu/SystemPlugins/NES/OENESSystemResponderClient.h; sourceTree = "<group>"; };
945942CF14E4F2DC0015D2AA /* FCEUX.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = FCEUX.icns; sourceTree = "<group>"; };
949BB74E1A9EED55007B49CC /* asm.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = asm.cpp; sourceTree = "<group>"; };
@@ -776,6 +788,8 @@
949BB7F01A9EED56007B49CC /* config.cpp */,
949BB7F21A9EED56007B49CC /* debug.cpp */,
949BB7F31A9EED56007B49CC /* debug.h */,
8F28FD5329FD3EA4008FC4A9 /* debugsymboltable.cpp */,
8F28FD5429FD3EA4008FC4A9 /* debugsymboltable.h */,
949BB7F41A9EED56007B49CC /* drawing.cpp */,
949BB7F51A9EED56007B49CC /* drawing.h */,
949BB7F61A9EED56007B49CC /* driver.h */,
@@ -893,6 +907,7 @@
949BB77D1A9EED56007B49CC /* 32.cpp */,
949BB77E1A9EED56007B49CC /* 33.cpp */,
949BB77F1A9EED56007B49CC /* 34.cpp */,
8F28FD4D29FD3E7D008FC4A9 /* 354.cpp */,
949BB7801A9EED56007B49CC /* 36.cpp */,
949BB7811A9EED56007B49CC /* 3d-block.cpp */,
949BB7821A9EED56007B49CC /* 40.cpp */,
@@ -944,6 +959,7 @@
87709ED8294D24F10084AEE0 /* cheapocabra.cpp */,
949BB7AC1A9EED56007B49CC /* cityfighter.cpp */,
870D6EA71D4C1F93001E8FC6 /* coolboy.cpp */,
8F28FD4E29FD3E7D008FC4A9 /* coolgirl.cpp */,
949BB7AD1A9EED56007B49CC /* dance2000.cpp */,
949BB7AE1A9EED56007B49CC /* datalatch.cpp */,
949BB7AF1A9EED56007B49CC /* dream.cpp */,
@@ -965,6 +981,7 @@
87709EDC294D252B0084AEE0 /* hp10xx_hp20xx.cpp */,
870D6EB11D4C20B3001E8FC6 /* hp898f.cpp */,
870D6EB21D4C20B3001E8FC6 /* inlnsf.cpp */,
8F28FD4F29FD3E7D008FC4A9 /* inx007t.cpp */,
949BB7BA1A9EED56007B49CC /* karaoke.cpp */,
949BB7BB1A9EED56007B49CC /* kof97.cpp */,
870D6EB51D4C20F8001E8FC6 /* ks7010.cpp */,
@@ -1166,6 +1183,8 @@
949BBA271A9EED5B007B49CC /* md5.h */,
949BBA281A9EED5B007B49CC /* memory.cpp */,
949BBA291A9EED5B007B49CC /* memory.h */,
8F28FD5629FD3EB8008FC4A9 /* mutex.cpp */,
8F28FD5729FD3EB8008FC4A9 /* mutex.h */,
949BBA2B1A9EED5B007B49CC /* unzip.cpp */,
949BBA2C1A9EED5B007B49CC /* unzip.h */,
949BBA2D1A9EED5B007B49CC /* valuearray.h */,
@@ -1270,6 +1289,7 @@
files = (
82EC40A30FD9EC5A0017FC19 /* FCEUGameCore.mm in Sources */,
949BBB381A9EFF4A007B49CC /* asm.cpp in Sources */,
8F28FD5129FD3E7D008FC4A9 /* coolgirl.cpp in Sources */,
949BBB391A9EFF4A007B49CC /* cart.cpp in Sources */,
870D6EA81D4C1F93001E8FC6 /* coolboy.cpp in Sources */,
949BBB3A1A9EFF4A007B49CC /* cheat.cpp in Sources */,
@@ -1296,6 +1316,7 @@
949BBB501A9EFF4B007B49CC /* video.cpp in Sources */,
949BBB511A9EFF4B007B49CC /* vsuni.cpp in Sources */,
949BBB521A9EFF4B007B49CC /* wave.cpp in Sources */,
8F28FD5829FD3EB8008FC4A9 /* mutex.cpp in Sources */,
949BBB531A9EFF4B007B49CC /* x6502.cpp in Sources */,
949BBA741A9EF079007B49CC /* 01-222.cpp in Sources */,
949BBA751A9EF079007B49CC /* 09-034a.cpp in Sources */,
@@ -1336,6 +1357,7 @@
949BBA961A9EF079007B49CC /* 230.cpp in Sources */,
949BBA971A9EF079007B49CC /* 232.cpp in Sources */,
949BBA981A9EF079007B49CC /* 234.cpp in Sources */,
8F28FD5029FD3E7D008FC4A9 /* 354.cpp in Sources */,
949BBA991A9EF079007B49CC /* 235.cpp in Sources */,
949BBA9A1A9EF079007B49CC /* 244.cpp in Sources */,
949BBA9B1A9EF079007B49CC /* 246.cpp in Sources */,
@@ -1401,6 +1423,7 @@
949BBAD01A9EF07A007B49CC /* datalatch.cpp in Sources */,
949BBAD11A9EF07A007B49CC /* dream.cpp in Sources */,
949BBAD21A9EF07A007B49CC /* edu2000.cpp in Sources */,
8F28FD5529FD3EA4008FC4A9 /* debugsymboltable.cpp in Sources */,
949BBAD31A9EF07A007B49CC /* emu2413.c in Sources */,
949BBAD51A9EF07A007B49CC /* famicombox.cpp in Sources */,
949BBAD61A9EF07A007B49CC /* ffe.cpp in Sources */,
@@ -1448,6 +1471,7 @@
870D6EC21D4C2BF4001E8FC6 /* snesmouse.cpp in Sources */,
949BBAFB1A9EF07A007B49CC /* sl1632.cpp in Sources */,
949BBAFC1A9EF07A007B49CC /* subor.cpp in Sources */,
8F28FD5229FD3E7D008FC4A9 /* inx007t.cpp in Sources */,
949BBAFD1A9EF07A007B49CC /* super24.cpp in Sources */,
870D6EAF1D4C1FE7001E8FC6 /* et-4320.cpp in Sources */,
949BBAFE1A9EF07A007B49CC /* supervision.cpp in Sources */,
@@ -1576,6 +1600,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
@@ -1611,6 +1636,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+3 -1
View File
@@ -233,7 +233,7 @@ static __weak FCEUGameCore *_current;
for (int i = 0; i < _soundSize; i++)
_soundBuffer[i] = (_soundBuffer[i] << 16) | (_soundBuffer[i] & 0xffff);
[[self ringBufferAtIndex:0] write:_soundBuffer maxLength:_soundSize << 2];
[[self audioBufferAtIndex:0] write:_soundBuffer maxLength:_soundSize << 2];
}
- (void)resetEmulation
@@ -795,6 +795,7 @@ 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 eoptions = 0;
int closeFinishedMovie = 0;
int KillFCEUXonFrame = 0;
int FCEUD_ShowStatusIcon(void) {return 0;}
@@ -824,6 +825,7 @@ EMUFILE_FILE *FCEUD_UTF8_fstream(const char *fn, const char *m)
}
void FCEUD_NetplayText(uint8 *text) {};
void FCEUD_NetworkClose(void) {}
void FCEUD_FlushTrace(void) {}
void FCEUD_VideoChanged (void) {}
bool FCEUD_ShouldDrawInputAids() {return false;}
bool FCEUD_PauseAfterPlayback() {return false;}
+1 -1
View File
@@ -17,7 +17,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>2.6.3</string>
<string>2.6.5</string>
<key>NSPrincipalClass</key>
<string>OEGameCoreController</string>
<key>OEGameCoreClass</key>
+25 -4
View File
@@ -5,6 +5,10 @@ set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
if (${PUBLIC_RELEASE})
add_definitions( -DPUBLIC_RELEASE=1 )
endif()
if ( ${QT6} )
message( STATUS "GUI Frontend: Qt6")
set( Qt Qt6 )
@@ -28,6 +32,7 @@ else()
include_directories( ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Help_INCLUDE_DIRS} )
endif()
if(WIN32)
find_package(OpenGL REQUIRED)
#find_package(Qt5 COMPONENTS Widgets OpenGL REQUIRED)
@@ -36,6 +41,8 @@ if(WIN32)
add_definitions( -DMSVC -D_CRT_SECURE_NO_WARNINGS )
add_definitions( -D__SDL__ -D__QT_DRIVER__ -DQT_DEPRECATED_WARNINGS )
add_definitions( -DFCEUDEF_DEBUGGER )
add_definitions( /wd4267 /wd4244 )
#add_definitions( /wd4018 ) # Integer comparison sign mismatch warnings
include_directories( ${SDL_INSTALL_PREFIX}/SDL2/include )
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib )
set( OPENGL_LDFLAGS OpenGL::GL )
@@ -71,7 +78,8 @@ else(WIN32)
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( -Wall -Wno-write-strings -Wno-parentheses -Wno-unused-local-typedefs -fPIC )
#add_definitions( -Wno-sign-compare ) # Integer comparison sign mismatch warnings
add_definitions( -DFCEUDEF_DEBUGGER )
#if ( ${QT6} )
@@ -85,6 +93,15 @@ else(WIN32)
#endif()
add_definitions( -D__QT_DRIVER__ -DQT_DEPRECATED_WARNINGS )
if ( ${ASAN_ENABLE} )
add_definitions( -fsanitize=address -fsanitize=bounds-strict )
add_definitions( -fsanitize=undefined -fno-sanitize=vptr )
set( ASAN_LDFLAGS -lasan -lubsan)
message( STATUS "Address Sanitizer Enabled" )
else()
message( STATUS "Address Sanitizer Disabled" )
endif()
# Check for libminizip
pkg_check_modules( MINIZIP REQUIRED minizip)
@@ -261,6 +278,7 @@ set(SRC_CORE
${CMAKE_CURRENT_SOURCE_DIR}/conddebug.cpp
${CMAKE_CURRENT_SOURCE_DIR}/config.cpp
${CMAKE_CURRENT_SOURCE_DIR}/debug.cpp
${CMAKE_CURRENT_SOURCE_DIR}/debugsymboltable.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drawing.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fceu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fds.cpp
@@ -332,6 +350,7 @@ set(SRC_CORE
${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/354.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/36.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/3d-block.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/40.cpp
@@ -382,6 +401,7 @@ set(SRC_CORE
${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/coolgirl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/dance2000.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/datalatch.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/dream.cpp
@@ -453,6 +473,7 @@ set(SRC_CORE
${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}/boards/inx007t.cpp
${CMAKE_CURRENT_SOURCE_DIR}/input/arkanoid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/input/bworld.cpp
${CMAKE_CURRENT_SOURCE_DIR}/input/cursor.cpp
@@ -481,13 +502,13 @@ set(SRC_CORE
${CMAKE_CURRENT_SOURCE_DIR}/utils/guid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utils/md5.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utils/memory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utils/mutex.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
@@ -578,7 +599,7 @@ set(SOURCES ${SRC_CORE} ${SRC_DRIVERS_COMMON} ${SRC_DRIVERS_SDL})
# 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")
string(TIMESTAMP BUILD_TS "%H:%M:%S %b %d %Y" UTC)
add_definitions( -DFCEUX_BUILD_TIMESTAMP=\"${BUILD_TS}\" )
if (WIN32)
@@ -613,7 +634,7 @@ add_executable( ${APP_NAME} ${SOURCES} ../resources.qrc
${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp)
endif()
target_link_libraries( ${APP_NAME}
target_link_libraries( ${APP_NAME} ${ASAN_LDFLAGS}
${${Qt}Widgets_LIBRARIES}
${${Qt}Help_LIBRARIES}
${${Qt}OpenGL_LIBRARIES}
+1 -1
View File
@@ -48,7 +48,7 @@ static void M121CW(uint32 A, uint8 V) {
if (PRGsize[0] == CHRsize[0]) { // A9713 multigame extension hack!
setchr1(A, V | ((EXPREGS[3] & 0x80) << 1));
} else {
if ((A & 0x1000) == ((MMC3_cmd & 0x80) << 5))
if ((A & 0x1000) == static_cast<uint32>((MMC3_cmd & 0x80) << 5))
setchr1(A, V | 0x100);
else
setchr1(A, V);
+1 -1
View File
@@ -22,7 +22,7 @@
#include "mmc3.h"
static void M187CW(uint32 A, uint8 V) {
if ((A & 0x1000) == ((MMC3_cmd & 0x80) << 5))
if ((A & 0x1000) == static_cast<uint32>((MMC3_cmd & 0x80) << 5))
setchr1(A, V | 0x100);
else
setchr1(A, V);
+42 -34
View File
@@ -1,30 +1,40 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2011 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
*/
*
* Copyright notice for this file:
* Copyright (C) 2011 CaH4e3
* Copyright (C) 2019 Libretro Team
* Copyright (C) 2020
*
* 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
*
* PCB-018 board, discrete multigame cart 110-in-1
*
* Mapper 225
* Mapper 255
*
*/
/* 2020-2-20 - merge mapper 255, re-implement extra RAM */
#include "mapinc.h"
static uint8 prot[4], prg, mode, chr, mirr;
static uint8 extraRAM[4], prg, mode, chr, mirr;
static SFORMAT StateRegs[] =
{
{ prot, 4, "PROT" },
{ extraRAM, 4, "PROT" },
{ &prg, 1, "PRG" },
{ &chr, 1, "CHR" },
{ &mode, 1, "MODE" },
@@ -36,14 +46,15 @@ static void Sync(void) {
if (mode) {
setprg16(0x8000, prg);
setprg16(0xC000, prg);
} else
}
else
setprg32(0x8000, prg >> 1);
setchr8(chr);
setmirror(mirr ^ 1);
}
static DECLFW(M225Write) {
uint32 bank = (A >> 14) & 1;
uint8 bank = (A >> 14) & 1;
mirr = (A >> 13) & 1;
mode = (A >> 12) & 1;
chr = (A & 0x3f) | (bank << 6);
@@ -52,35 +63,28 @@ static DECLFW(M225Write) {
}
static DECLFW(M225LoWrite) {
if (A & 0x800) {
prot[A & 0x03] = V;
}
/* e.g. 115-in-1 [p1][!] CRC32 0xb39d30b4 */
if (A & 0x800) extraRAM[A & 3] = V & 0x0F;
}
static DECLFR(M225LoRead) {
if (A & 0x800) {
return prot[A & 3] & 0x0F;
}
if (A & 0x800) return extraRAM[A & 3];
return X.DB;
}
static void M225Power(void) {
prg = 0;
chr = 0;
mode = 0;
mirr = 0;
Sync();
SetReadHandler(0x5000, 0x5FFF, M225LoRead);
SetWriteHandler(0x5000, 0x5FFF, M225LoWrite);
SetReadHandler(0x5000, 0x5fff, M225LoRead);
SetWriteHandler(0x5000, 0x5fff, M225LoWrite);
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xFFFF, M225Write);
}
static void M225Reset(void) {
prg = 0;
chr = 0;
mode = 0;
mirr = 0;
Sync();
}
@@ -94,3 +98,7 @@ void Mapper225_Init(CartInfo *info) {
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}
void Mapper255_Init(CartInfo *info) {
Mapper225_Init(info);
}
+58 -11
View File
@@ -19,36 +19,79 @@
*/
#include "mapinc.h"
#include "ines.h"
static uint16 cmdreg = 0;
static uint8 openbus = 0;
// For carts with extra 128K prg rom (Contra)
static uint8 unrom = 0;
static uint8 unromData = 0;
static uint32 PRGROMSize = 0;
static uint16 cmdreg;
static SFORMAT StateRegs[] =
{
{ &cmdreg, 2, "CREG" },
{ &openbus, 1, "OB" },
{ &unrom, 1, "UROM" },
{ &unromData, 1, "UDTA" },
{ 0 }
};
static void Sync(void) {
if (cmdreg & 0x400)
setmirror(MI_0);
else
setmirror(((cmdreg >> 13) & 1) ^ 1);
if (cmdreg & 0x800) {
setprg16(0x8000, ((cmdreg & 0x300) >> 3) | ((cmdreg & 0x1F) << 1) | ((cmdreg >> 12) & 1));
setprg16(0xC000, ((cmdreg & 0x300) >> 3) | ((cmdreg & 0x1F) << 1) | ((cmdreg >> 12) & 1));
} else
setprg32(0x8000, ((cmdreg & 0x300) >> 4) | (cmdreg & 0x1F));
if (unrom) {
int PRGPageCount = PRGROMSize / (16 * 1024);
setprg16(0x8000, PRGPageCount & 0xC0 | (unromData & 7));
setprg16(0xC000, PRGPageCount & 0xC0 | 7);
setmirror(MI_V);
} else {
uint8 bank = ((cmdreg & 0x300) >> 3) | (cmdreg & 0x1F);
if (bank >= (PRGROMSize / (32 * 1024))) {
openbus = 1;
} else {
if (cmdreg & 0x400)
setmirror(MI_0);
else
setmirror(((cmdreg >> 13) & 1) ^ 1);
if (cmdreg & 0x800) {
setprg16(0x8000, (bank << 1) | ((cmdreg >> 12) & 1));
setprg16(0xC000, (bank << 1) | ((cmdreg >> 12) & 1));
} else
setprg32(0x8000, bank);
}
}
}
static DECLFR(M235Read) {
if (openbus) {
openbus = 0;
return X.DB;
}
return CartBR(A);
}
static DECLFW(M235Write) {
cmdreg = A;
unromData = V;
Sync();
}
static void M235Reset(void) {
cmdreg = 0;
unromData = 0;
if (PRGROMSize & 0x20000)
unrom = (unrom + 1) & 1;
Sync();
}
static void M235Power(void) {
setchr8(0);
SetWriteHandler(0x8000, 0xFFFF, M235Write);
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetReadHandler(0x8000, 0xFFFF, M235Read);
cmdreg = 0;
unromData = 0;
unrom = 0;
Sync();
}
@@ -57,7 +100,11 @@ static void M235Restore(int version) {
}
void Mapper235_Init(CartInfo *info) {
info->Reset = M235Reset;
info->Power = M235Power;
GameStateRestore = M235Restore;
AddExState(&StateRegs, ~0, 0, 0);
// needs raw, non-pow2 PRGROM size for comparison
PRGROMSize = head.ROM_size * 16384;
}
+97
View File
@@ -0,0 +1,97 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2022
*
* 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 latchAddr;
static uint8 latchData;
static uint8 submapper;
static SFORMAT StateRegs[] =
{
{ &latchAddr, 2, "ADDR" },
{ &latchData, 1, "DATA" },
{ 0 }
};
static void Mapper354_Sync(void)
{
int prg = latchData & 0x3F | latchAddr << 2 & 0x40 | latchAddr >> 5 & 0x80;
switch (latchAddr & 7)
{
case 0: case 4:
setprg32(0x8000, prg >> 1);
break;
case 1:
setprg16(0x8000, prg);
setprg16(0xC000, prg | 7);
break;
case 2: case 6:
setprg8(0x8000, prg << 1 | latchData >> 7);
setprg8(0xA000, prg << 1 | latchData >> 7);
setprg8(0xC000, prg << 1 | latchData >> 7);
setprg8(0xE000, prg << 1 | latchData >> 7);
break;
case 3: case 7:
setprg16(0x8000, prg);
setprg16(0xC000, prg);
break;
case 5:
setprg8(0x6000, prg << 1 | latchData >> 7);
setprg32(0x8000, prg >> 1 | 3);
break;
}
setchr8(0);
setmirror(latchData & 0x40 ? MI_H : MI_V);
}
static DECLFW(Mapper354_WriteLatch)
{
latchData = V;
latchAddr = A & 0xFFFF;
Mapper354_Sync();
}
static void Mapper354_Reset(void)
{
latchAddr = latchData = 0;
Mapper354_Sync();
}
static void Mapper354_Power(void)
{
latchAddr = latchData = 0;
SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(submapper == 1 ? 0xE000 : 0xF000, 0xFFFF, Mapper354_WriteLatch);
Mapper354_Sync();
}
static void StateRestore(int version) {
Mapper354_Sync();
}
void Mapper354_Init(CartInfo *info)
{
submapper = info->submapper;
info->Power = Mapper354_Power;
info->Reset = Mapper354_Reset;
GameStateRestore = StateRestore;
AddExState(StateRegs, ~0, 0, 0);
}
+1 -1
View File
@@ -122,7 +122,7 @@ static void UNL43272Sync(void) {
if ((latche & 0x81) == 0x81) {
setprg32(0x8000, (latche & 0x38) >> 3);
} else
FCEU_printf("unrecognized command %04!\n", latche);
FCEU_printf("unrecognized command %04x!\n", latche);
setchr8(0);
setmirror(0);
}
+347 -75
View File
@@ -21,7 +21,7 @@
*
* 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
* ---- ----
@@ -29,12 +29,11 @@
* |||| ||||
* |||| |+++-- PRG offset (PRG A19, A18, A17)
* |||| +----- Alternate CHR A17
* ||++------- PRG offset (PRG A24, A23)
* ||++------- PRG offset (PRG A24, A23), CHR offset (CHR A19, A18)
* |+--------- PRG mask (PRG A17 from 0: MMC3; 1: offset)
* +---------- CHR mask (CHR A17 from 0: MMC3; 1: alternate)
*
* $xxx1
*
* 7 bit 0
* ---- ----
* GHIJ KKLx
@@ -55,15 +54,16 @@
* $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 )
* NPZP 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 )
* ||+-------- 1: Also enable PRG RAM in $5000-$5FFF
* |+-+------- Banking mode
* |+--------- "Weird MMC3 mode"
* +---------- Lockout (prevent further writes to these four registers, only works in MMC3 mode)
* +---------- Lockout (prevent further writes to all registers but the one at $xxx2, 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.
@@ -75,25 +75,90 @@
#include "mapinc.h"
#include "mmc3.h"
#include "../ines.h"
static void COOLBOYCW(uint32 A, uint8 V) {
uint32 mask = 0xFF ^ (EXPREGS[0] & 0x80);
if (EXPREGS[3] & 0x10) {
if (EXPREGS[3] & 0x40) { // Weird mode
const int ROM_CHIP = 0x00;
const int CFI_CHIP = 0x11;
const int FLASH_CHIP = 0x12;
const uint32 FLASH_SECTOR_SIZE = 128 * 1024;
extern uint8* WRAM;
static uint8* CFI = NULL;
static uint8* Flash = NULL;
static uint8 flash_save = 0;
static uint8 flash_state = 0;
static uint16 flash_buffer_a[10];
static uint8 flash_buffer_v[10];
static uint8 cfi_mode = 0;
static uint16 regs_base = 0;
static uint8 flag23 = 0;
static uint8 flag45 = 0;
static uint8 flag67 = 0;
static uint8 flag89 = 0;
// Macronix 256-mbit memory CFI data
const uint8 cfi_data[] =
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x51, 0x52, 0x59, 0x02, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x27, 0x36, 0x00, 0x00, 0x03,
0x06, 0x09, 0x13, 0x03, 0x05, 0x03, 0x02, 0x19,
0x02, 0x00, 0x06, 0x00, 0x01, 0xFF, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0x50, 0x52, 0x49, 0x31, 0x33, 0x14, 0x02, 0x01,
0x00, 0x08, 0x00, 0x00, 0x02, 0x95, 0xA5, 0x05,
0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
static void AA6023CW(uint32 A, uint8 V) {
if (flag89) {
/*
$xxx0
7 bit 0
---- ----
AB.C DEEE
|| | ||||
|| | |+++-- PRG offset (PRG A19, A18, A17)
|| | +----- Alternate CHR A17
|| +------- 1=Write-protect CHR-RAM
|+--------- PRG mask (PRG A17 from 0: MMC3; 1: offset)
+---------- CHR mask (CHR A17 from 0: MMC3; 1: alternate)
*/
if (EXPREGS[0] & 0b00010000)
SetupCartCHRMapping(0, VROM, CHRsize[0], 0); // write-protect CHR-RAM
else
SetupCartCHRMapping(0, VROM, CHRsize[0], 1); // allow CHR writes
}
uint32 mask = 0xFF ^ (EXPREGS[0] & 0b10000000);
if (EXPREGS[3] & 0b00010000) {
if (EXPREGS[3] & 0b01000000) { // 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
// Highest bit goes from MMC3 registers when EXPREGS[0]&0x80==0 or from EXPREGS[0]&0x08 otherwise
setchr1(A,
(V & 0x80 & mask) | ((((EXPREGS[0] & 0x08) << 4) & ~mask)) // 7th bit
(V & 0x80 & mask) | ((((EXPREGS[0] & 0b00001000) << 4) & ~mask)) // 7th bit
| ((EXPREGS[2] & 0x0F) << 3) // 6-3 bits
| ((A >> 10) & 7) // 2-0 bits
| ((EXPREGS[0] & 0b00110000) << 4) // There are some ROMs with 1 MiB CHR-ROM
);
} else {
if (EXPREGS[3] & 0x40) { // Weird mode, again
}
else {
if (EXPREGS[3] & 0b01000000) { // Weird mode, again
int cbase = (MMC3_cmd & 0x80) << 5;
switch (cbase ^ A) { // Don't even try do understand
case 0x0000: V = DRegBuf[0]; break;
@@ -103,18 +168,81 @@ static void COOLBOYCW(uint32 A, uint8 V) {
}
}
// 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));
// Highest bit goes from MMC3 registers when EXPREGS[0]&0x80==0 or from EXPREGS[0]&0x08 otherwise
setchr1(A,
(V & mask)
| (((EXPREGS[0] & 0x08) << 4) & ~mask)
| ((EXPREGS[0] & 0b00110000) << 4)); // There are some ROMs with 1 MiB CHR-ROM
}
}
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);
static void AA6023PW(uint32 A, uint8 V) {
uint8 CREGS[] = {EXPREGS[0], EXPREGS[1], EXPREGS[2], EXPREGS[3]};
// Submappers has scrambled bits
if (flag23) {
/*
$xxx1
7 bit 0
---- ----
GHIL JKKx
|||| |||
|||| +++--- PRG offset (in order: PRG A20, A21, A22)
|||+------- GNROM mode bank PRG size (0: 32 KiB bank, PRG A14=CPU A14; 1: 16 KiB bank, PRG A14=offset A14)
||+-------- 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)
*/
CREGS[1] = (CREGS[1] & 0b11100101)
| ((CREGS[1] & 0b00001000) << 1) // PRG A20
| ((CREGS[1] & 0b00000010) << 2) // PRG A22
| ((((CREGS[1] ^ 0b00010000) & 0b00010000) >> 3)); // GNROM mode bank PRG size
}
if (flag45) {
/*
$xxx0
7 bit 0
---- ----
ABCC DEEE
|||| ||||
|||| |+++-- PRG offset (PRG A19, A18, A17)
|||| +----- Alternate CHR A17
||++------- PRG offset (PRG A21, A20)
|+--------- PRG mask (PRG A17 from 0: MMC3; 1: offset)
+---------- CHR mask (CHR A17 from 0: MMC3; 1: alternate)
$xxx1
7 bit 0
---- ----
GHIx xxLx
||| |
||| +--- GNROM mode bank PRG size (1: 32 KiB bank, PRG A14=CPU A14; 0: 16 KiB bank, PRG A14=offset A14)
||+-------- 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)
*/
CREGS[1] = (CREGS[1] & 0b11100011)
| ((CREGS[0] & 0b00100000) >> 3) // PRG A21
| (CREGS[0] & 0b00010000); // PRG A20
CREGS[0] &= 0b11001111;
}
uint32 mask = ((0b00111111 | (CREGS[1] & 0b01000000) | ((CREGS[1] & 0b00100000) << 2)) ^ ((CREGS[0] & 0b01000000) >> 2)) ^ ((CREGS[1] & 0b10000000) >> 2);
uint32 base = ((CREGS[0] & 0b00000111) >> 0) | ((CREGS[1] & 0b00010000) >> 1) | ((CREGS[1] & 0b00001100) << 2) | ((CREGS[0] & 0b00110000) << 2);
if (flash_save && cfi_mode) {
setprg32r(CFI_CHIP, 0x8000, 0);
return;
}
int chip = !flash_save ? ROM_CHIP : FLASH_CHIP;
// There are ROMs with multiple PRG ROM chips
int chip_offset = 0;
if (flag67 && EXPREGS[0] & 0b00001000) {
chip_offset += ROM_size;
}
// 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)) {
if ((CREGS[3] & 0b01000000) && (V >= 0xFE) && !((MMC3_cmd & 0x40) != 0)) {
switch (A & 0xE000) {
case 0xC000:
case 0xE000:
@@ -123,91 +251,235 @@ static void COOLBOYPW(uint32 A, uint8 V) {
}
}
// 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
if (!(CREGS[3] & 0x10)) {
// Regular MMC3 mode but can be extended to 2MiB
setprg8r(chip, A, ((((base << 4) & ~mask)) | (V & mask)) + chip_offset);
}
else {
// NROM mode
mask &= 0xF0;
uint8 emask;
if ((((EXPREGS[1] & 2) != 0))) // 32kb mode
emask = (EXPREGS[3] & 0x0C) | ((A & 0x4000) >> 13);
if (CREGS[1] & 0b00000010) // 32kb mode
emask = (CREGS[3] & 0b00001100) | ((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
emask = CREGS[3] & 0b00001110;
setprg8r(chip, A, (
((base << 4) & ~mask) // 7-4 bits are from base
| (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
) + chip_offset); // For multi-chip ROMs
}
}
static DECLFW(COOLBOYWrite) {
if(A001B & 0x80)
CartBW(A,V);
static DECLFW(AA6023WramWrite) {
if (A001B & 0x80)
CartBW(A, V);
}
static DECLFW(AA6023Write) {
if (A >= 0x6000) {
AA6023WramWrite(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);
}
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
static void COOLBOYReset(void) {
static DECLFW(AA6023FlashWrite) {
if (A < 0xC000)
MMC3_CMDWrite(A, V);
else
MMC3_IRQWrite(A, V);
if (!flash_save) return;
if (flash_state < sizeof(flash_buffer_a) / sizeof(flash_buffer_a[0])) {
flash_buffer_a[flash_state] = A & 0xFFF;
flash_buffer_v[flash_state] = V;
flash_state++;
// enter CFI mode
if ((flash_state == 1) &&
(flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0x98)) {
cfi_mode = 1;
flash_state = 0;
}
// erase sector
if ((flash_state == 6) &&
(flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0x80) &&
(flash_buffer_a[3] == 0x0AAA) && (flash_buffer_v[3] == 0xAA) &&
(flash_buffer_a[4] == 0x0555) && (flash_buffer_v[4] == 0x55) &&
(flash_buffer_v[5] == 0x30)) {
int offset = &Page[A >> 11][A] - Flash;
int sector = offset / FLASH_SECTOR_SIZE;
for (uint32 i = sector * FLASH_SECTOR_SIZE; i < (sector + 1) * FLASH_SECTOR_SIZE; i++)
Flash[i % PRGsize[ROM_CHIP]] = 0xFF;
FCEU_printf("Flash sector #%d is erased (0x%08x - 0x%08x).\n", sector, offset, offset + FLASH_SECTOR_SIZE);
flash_state = 0;
}
// erase chip, lol
if ((flash_state == 6) &&
(flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0x80) &&
(flash_buffer_a[3] == 0x0AAA) && (flash_buffer_v[3] == 0xAA) &&
(flash_buffer_a[4] == 0x0555) && (flash_buffer_v[4] == 0x55) &&
(flash_buffer_v[5] == 0x10)) {
memset(Flash, 0xFF, PRGsize[ROM_CHIP]);
FCEU_printf("Flash chip erased.\n");
flash_state = 0;
}
// write byte
if ((flash_state == 4) &&
(flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0xA0)) {
int offset = &Page[A >> 11][A] - Flash;
if (CartBR(A) != 0xFF) {
FCEU_PrintError("Error: can't write to 0x%08x, flash sector is not erased.\n", offset);
}
else {
CartBW(A, V);
}
flash_state = 0;
}
}
// not a command
if (((A & 0xFFF) != 0x0AAA) && ((A & 0xFFF) != 0x0555)) {
flash_state = 0;
}
// reset
if (V == 0xF0) {
flash_state = 0;
cfi_mode = 0;
}
FixMMC3PRG(MMC3_cmd);
}
static void AA6023Reset(void) {
MMC3RegReset();
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
flash_state = 0;
cfi_mode = 0;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
static void COOLBOYPower(void) {
static void AA6023Power(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);
if (regs_base != 0x5000)
SetWriteHandler(0x5000, 0x5fff, CartBW); // some games access random unmapped areas and crashes because of KT-008 PCB hack in MMC3 source lol
SetWriteHandler(0x6000, 0x7fff, AA6023WramWrite);
SetWriteHandler(regs_base, regs_base + 0x0fff, AA6023Write);
SetWriteHandler(0x8000, 0xFFFF, AA6023FlashWrite);
SetReadHandler(0x8000, 0xFFFF, CartBR);
}
static void MINDKIDSPower(void) {
GenMMC3Power();
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
static void AA6023Restore(int version) {
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
SetWriteHandler(0x5000, 0x5fff, COOLBOYWrite);
}
static void AA6023Close(void) {
if (WRAM)
FCEU_gfree(WRAM);
if (Flash)
FCEU_gfree(Flash);
if (CFI)
FCEU_gfree(CFI);
WRAM = Flash = CFI = NULL;
}
void CommonInit(CartInfo* info, int submapper)
{
GenMMC3_Init(info, 2048, info->vram_size / 1024, !info->ines2 ? 8 : (info->wram_size + info->battery_wram_size) / 1024, info->battery);
pwrap = AA6023PW;
cwrap = AA6023CW;
switch (submapper)
{
case 2:
regs_base = 0x7000;
break;
case 0:
case 4:
case 6:
case 8:
regs_base = 0x6000;
break;
case 1:
case 3:
case 5:
case 7:
case 9:
regs_base = 0x5000;
break;
default:
FCEU_PrintError("Submapper #%d is not supported", submapper);
}
flag23 = (submapper == 2) || (submapper == 3);
flag45 = (submapper == 4) || (submapper == 5);
flag67 = (submapper == 6) || (submapper == 7);
flag89 = (submapper == 8) || (submapper == 9);
info->Power = AA6023Power;
info->Reset = AA6023Reset;
info->Close = AA6023Close;
GameStateRestore = AA6023Restore;
flash_save = info->battery;
if (flash_save) {
CFI = (uint8*)FCEU_gmalloc(sizeof(cfi_data) * 2);
for (size_t i = 0; i < sizeof(cfi_data); i++) {
CFI[i * 2] = CFI[i * 2 + 1] = cfi_data[i];
}
SetupCartPRGMapping(CFI_CHIP, CFI, sizeof(cfi_data) * 2, 0);
Flash = (uint8*)FCEU_gmalloc(PRGsize[ROM_CHIP]);
for (unsigned int i = 0; i < PRGsize[ROM_CHIP]; i++) {
Flash[i] = PRGptr[ROM_CHIP][i % PRGsize[ROM_CHIP]];
}
SetupCartPRGMapping(FLASH_CHIP, Flash, PRGsize[ROM_CHIP], 1);
info->SaveGame[1] = Flash;
info->SaveGameLen[1] = PRGsize[ROM_CHIP];
}
AddExState(EXPREGS, 4, 0, "EXPR");
if (flash_save)
{
AddExState(&flash_state, sizeof(flash_state), 0, "FLST");
AddExState(flash_buffer_a, sizeof(flash_buffer_a), 0, "FLBA");
AddExState(flash_buffer_v, sizeof(flash_buffer_v), 0, "FLBV");
AddExState(&cfi_mode, sizeof(cfi_mode), 0, "CFIM");
AddExState(Flash, PRGsize[ROM_CHIP], 0, "FLAS");
}
}
// 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");
void COOLBOY_Init(CartInfo* info) {
CommonInit(info, 0);
}
// 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");
void MINDKIDS_Init(CartInfo* info) {
CommonInit(info, 1);
}
// 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;
}
void AA6023_Init(CartInfo* info) {
CommonInit(info, info->submapper);
}
File diff suppressed because it is too large Load Diff
+33
View File
@@ -474,6 +474,39 @@ void Mapper203_Init(CartInfo *info) {
Latch_Init(info, M203Sync, 0, 0x8000, 0xFFFF, 0, 0);
}
//------------------ Map 218 ---------------------------
static void Mapper218_Power()
{
//doesn't really matter
SetReadHandler(0x6000, 0xFFFF, &CartBROB);
}
void Mapper218_Init(CartInfo *info)
{
info->Power = &Mapper218_Power;
//fixed PRG mapping
setprg32(0x8000, 0);
//this mapper is supposed to interpret the iNES header bits specially
static const uint8 mirrorings[] = {MI_V,MI_H,MI_0,MI_1};
SetupCartMirroring(mirrorings[info->mirrorAs2Bits],1,nullptr);
//cryptic logic to effect the CHR RAM mappings by mapping 1k blocks to NTARAM according to how the pins are wired
//this could be done by bit logic, but this is self-documenting
static const uint8 mapping[] = {
0,1,0,1,0,1,0,1, //mirrorAs2Bits==0
0,0,1,1,0,0,1,1, //mirrorAs2Bits==1
0,0,0,0,1,1,1,1, //mirrorAs2Bits==2
0,0,0,0,0,0,0,0 //mirrorAs2Bits==3
};
for(int i=0;i<8;i++)
VPageR[i] = &NTARAM[mapping[info->mirrorAs2Bits*8+i]];
PPUCHRRAM = 0xFF;
}
//------------------ Map 240 ---------------------------
static void M240Sync(void) {
+2
View File
@@ -34,11 +34,13 @@ static uint8 *WRAM = NULL;
static int kanji_pos, kanji_page, r40C0;
static int IRQa, IRQCount;
FCEU_MAYBE_UNUSED
static DECLFW(MBWRAM) {
if (!(DRegs[3] & 0x10))
Page[A >> 11][A] = V;
}
FCEU_MAYBE_UNUSED
static DECLFR(MAWRAM) {
if (DRegs[3] & 0x10)
return X.DB;
+88
View File
@@ -0,0 +1,88 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2022 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
*
* NES 2.0 Mapper 470 denotes the INX_007T_V01 multicart circuit board,
* used for the Retro-Bit re-release of Battletoads and Double Dragon.
* It is basically AOROM with an additional outer bank register at $5000-$5FFF
* whose data selects the 256 KiB outer bank.
*
* $5000-$5FFF
* 7 bit 0
* ---- ----
* xxxx xxOO
* ||
* ++- Select outer 256 KB PRG ROM bank for CPU $8000-$FFFF
*
* $8000-$FFFF
* 7 bit 0
* ---- ----
* xxxM xPPP
* | |||
* | +++- Select inner 32 KB PRG ROM bank for CPU $8000-$FFFF
* +------ Select 1 KB VRAM page for all 4 nametables
*
*/
#include "mapinc.h"
static uint8 latch_out, latch_in;
static void INX_007T_Sync() {
setprg32(0x8000, (latch_in & 0b111) | (latch_out << 3));
setmirror(MI_0 + ((latch_in >> 4) & 1));
setchr8(0);
}
static void StateRestore(int version) {
INX_007T_Sync();
}
static DECLFW(INX_007T_WriteLow)
{
latch_out = V;
INX_007T_Sync();
}
static DECLFW(INX_007T_WriteHi)
{
latch_in = V;
INX_007T_Sync();
}
static void INX_007T_Power(void) {
latch_in = latch_out = 0;
INX_007T_Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x5000,0x5FFF, INX_007T_WriteLow);
SetWriteHandler(0x8000, 0xFFFF, INX_007T_WriteHi);
}
static void INX_007T_Reset(void) {
latch_in = latch_out = 0;
INX_007T_Sync();
}
void INX_007T_Init(CartInfo *info) {
info->Power = INX_007T_Power;
info->Reset = INX_007T_Reset;
GameStateRestore = StateRestore;
SetupCartMirroring(MI_0, 0, NULL);
AddExState(&latch_out, 1, 0, "LATO");
AddExState(&latch_in, 1, 0, "LATI");
}
+1
View File
@@ -1376,6 +1376,7 @@ static DECLFW(M406IRQWrite) {
MMC3_IRQWrite((A & 0xFFFE) | ((A & 2) >> 1), V);
}
FCEU_MAYBE_UNUSED
static DECLFW(M406Write) {
}
+1 -2
View File
@@ -307,8 +307,7 @@ cartdata MMC5CartList[] =
#define MMC5_NOCARTS (sizeof(MMC5CartList) / sizeof(MMC5CartList[0]))
int DetectMMC5WRAMSize(uint32 crc32) {
int x;
for (x = 0; x < MMC5_NOCARTS; x++) {
for (size_t x = 0; x < MMC5_NOCARTS; x++) {
if (crc32 == MMC5CartList[x].crc32) {
if(MMC5CartList[x].size > 1)
FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n");
+131 -193
View File
@@ -1,7 +1,7 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2014 CaitSith2
* Copyright (C) 2014 CaitSith2, 2022 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
@@ -19,7 +19,7 @@
*/
/*
* Roms still using NES 1.0 format should be loaded as 32K CHR RAM.
* Roms still using NES 1.0 format should be loaded as 8K 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
@@ -28,6 +28,7 @@
* 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)
* Nix: The Paradox Relic (512 PRG, 8K CHR RAM, Vertical 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.
*/
@@ -35,211 +36,147 @@
#include "mapinc.h"
#include "../ines.h"
static uint8 latche, latcheinit, bus_conflict, chrram_mask, software_id=false;
const int ROM_CHIP = 0x00;
const int CFI_CHIP = 0x10;
const int FLASH_CHIP = 0x11;
const int FLASH_SECTOR_SIZE = 4 * 1024;
static uint8 flash_save, flash_state, flash_id_mode, latche, bus_conflict;
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_data;
static uint16 flash_buffer_a[10];
static uint8 flash_buffer_v[10];
static uint8 flash_id[2];
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;
}
static void UNROM512_Sync() {
int chip;
if (flash_save)
chip = !flash_id_mode ? FLASH_CHIP : CFI_CHIP;
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)];
chip = ROM_CHIP;
setprg16r(chip, 0x8000, latche & 0b11111);
setprg16r(chip, 0xc000, ~0);
setchr8((latche >> 5) & 0b11);
setmirror(MI_0 + ((latche >> 7) & 1));
}
static void StateRestore(int version) {
WHSync();
UNROM512_Sync();
}
static DECLFW(UNROM512LLatchWrite)
static DECLFW(UNROM512FlashWrite)
{
latche = V;
latcha = A;
WLSync();
if (flash_state < sizeof(flash_buffer_a) / sizeof(flash_buffer_a[0])) {
flash_buffer_a[flash_state] = (A & 0x3FFF) | ((latche & 1) << 14);
flash_buffer_v[flash_state] = V;
flash_state++;
// enter flash ID mode
if ((flash_state == 2) &&
(flash_buffer_a[0] == 0x5555) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x2AAA) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[1] == 0x5555) && (flash_buffer_v[1] == 0x90)) {
flash_id_mode = 0;
flash_state = 0;
}
// erase sector
if ((flash_state == 6) &&
(flash_buffer_a[0] == 0x5555) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x2AAA) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[2] == 0x5555) && (flash_buffer_v[2] == 0x80) &&
(flash_buffer_a[3] == 0x5555) && (flash_buffer_v[3] == 0xAA) &&
(flash_buffer_a[4] == 0x2AAA) && (flash_buffer_v[4] == 0x55) &&
(flash_buffer_v[5] == 0x30)) {
int offset = &Page[A >> 11][A] - flash_data;
int sector = offset / FLASH_SECTOR_SIZE;
for (int i = sector * FLASH_SECTOR_SIZE; i < (sector + 1) * FLASH_SECTOR_SIZE; i++)
flash_data[i % PRGsize[ROM_CHIP]] = 0xFF;
FCEU_printf("Flash sector #%d is erased (0x%08x - 0x%08x).\n", sector, offset, offset + FLASH_SECTOR_SIZE);
}
// erase chip
if ((flash_state == 6) &&
(flash_buffer_a[0] == 0x5555) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x2AAA) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[2] == 0x5555) && (flash_buffer_v[2] == 0x80) &&
(flash_buffer_a[3] == 0x5555) && (flash_buffer_v[3] == 0xAA) &&
(flash_buffer_a[4] == 0x2AAA) && (flash_buffer_v[4] == 0x55) &&
(flash_buffer_a[4] == 0x5555) && (flash_buffer_v[4] == 0x10)) {
memset(flash_data, 0xFF, PRGsize[ROM_CHIP]);
FCEU_printf("Flash chip erased.\n");
flash_state = 0;
}
// write byte
if ((flash_state == 4) &&
(flash_buffer_a[0] == 0x5555) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x2AAA) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[2] == 0x5555) && (flash_buffer_v[2] == 0xA0)) {
int offset = &Page[A >> 11][A] - flash_data;
if (CartBR(A) != 0xFF) {
FCEU_PrintError("Error: can't write to 0x%08x, flash sector is not erased.\n", offset);
}
else {
CartBW(A, V);
}
flash_state = 0;
}
}
// not a command
if (((A & 0xFFF) != 0x0AAA) && ((A & 0xFFF) != 0x0555)) {
flash_state = 0;
}
// reset
if (V == 0xF0) {
flash_state = 0;
flash_id_mode = 0;
}
UNROM512_Sync();
}
static DECLFW(UNROM512HLatchWrite)
{
if (bus_conflict)
latche = (V == CartBR(A)) ? V : 0;
latche = V & CartBR(A);
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];
UNROM512_Sync();
}
static void UNROM512LatchPower(void) {
latche = latcheinit;
WHSync();
SetReadHandler(0x8000, 0xFFFF, UNROM512LatchRead);
latche = 0;
UNROM512_Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
if(!flash_save)
SetWriteHandler(0x8000, 0xFFFF, UNROM512HLatchWrite);
else
{
SetWriteHandler(0x8000,0xBFFF,UNROM512LLatchWrite);
SetWriteHandler(0x8000,0xBFFF,UNROM512FlashWrite);
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));
if(flash_data)
FCEU_gfree(flash_data);
flash_data = NULL;
}
void UNROM512_Init(CartInfo *info) {
flash_state=0;
flash_bank=0;
flash_save=info->battery;
info->Power = UNROM512LatchPower;
info->Close = UNROM512LatchClose;
GameStateRestore = StateRestore;
if(info->vram_size == 8192)
chrram_mask = 0;
else if (info->vram_size == 16384)
chrram_mask = 0x20;
else
chrram_mask = 0x60;
flash_state = 0;
flash_id_mode = 0;
flash_save = info->battery;
bus_conflict = !info->battery; // Is it required by any game?
int mirror = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2);
switch (mirror)
@@ -258,28 +195,29 @@ void UNROM512_Init(CartInfo *info) {
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");
// Allocate memory for flash
flash_data = (uint8*)FCEU_gmalloc(PRGsize[ROM_CHIP]);
// Copy ROM to flash data
for (unsigned int i = 0; i < PRGsize[ROM_CHIP]; i++) {
flash_data[i] = PRGptr[ROM_CHIP][i % PRGsize[ROM_CHIP]];
}
SetupCartPRGMapping(FLASH_CHIP, flash_data, PRGsize[ROM_CHIP], 1);
info->SaveGame[0] = flash_data;
info->SaveGameLen[0] = PRGsize[ROM_CHIP];
flash_id[0] = 0xBF;
flash_id[1] = 0xB5 + (ROM_size >> 4);
SetupCartPRGMapping(CFI_CHIP, flash_id, sizeof(flash_id), 0);
AddExState(flash_data, PRGsize[ROM_CHIP], 0, "FLSH");
AddExState(&flash_state, 1, 0, "FLST");
AddExState(&flash_id_mode, 1, 0, "FLMD");
AddExState(flash_buffer_a, sizeof(flash_buffer_a), 0, "FLBA");
AddExState(flash_buffer_v, sizeof(flash_buffer_v), 0, "FLBV");
}
AddExState(&latcha, 2, 0, "LATA");
AddExState(&latche, 1, 0, "LATC");
AddExState(&bus_conflict, 1, 0, "BUSC");
}
+19 -6
View File
@@ -23,7 +23,7 @@
static bool isPirate;
static uint8 is22, reg1mask, reg2mask;
static uint16 IRQCount;
static uint8 IRQLatch, IRQa;
static uint8 IRQLatch, IRQa, IRQMode;
static uint8 prgreg[2], chrreg[8];
static uint16 chrhi[8];
static uint8 regcmd, irqcmd, mirr, big_bank;
@@ -45,6 +45,7 @@ static SFORMAT StateRegs[] =
{ &IRQCount, 2, "IRQC" },
{ &IRQLatch, 1, "IRQL" },
{ &IRQa, 1, "IRQA" },
{ &IRQMode, 1, "IRQM" },
{ 0 }
};
@@ -115,7 +116,7 @@ static DECLFW(VRC24Write) {
case 0x9003: regcmd = V; Sync(); break;
case 0xF000: X6502_IRQEnd(FCEU_IQEXT); IRQLatch &= 0xF0; IRQLatch |= V & 0xF; break;
case 0xF001: X6502_IRQEnd(FCEU_IQEXT); IRQLatch &= 0x0F; IRQLatch |= V << 4; break;
case 0xF002: X6502_IRQEnd(FCEU_IQEXT); acount = 0; IRQCount = IRQLatch; IRQa = V & 2; irqcmd = V & 1; break;
case 0xF002: X6502_IRQEnd(FCEU_IQEXT); acount = 0; IRQCount = IRQLatch; IRQMode = V & 4; IRQa = V & 2; irqcmd = V & 1; break;
case 0xF003: X6502_IRQEnd(FCEU_IQEXT); IRQa = irqcmd; break;
}
}
@@ -136,16 +137,28 @@ static void VRC24Power(void) {
void VRC24IRQHook(int a) {
#define LCYCS 341
if (IRQa) {
acount += a * 3;
if (acount >= LCYCS) {
while (acount >= LCYCS) {
acount -= LCYCS;
if (IRQMode) {
acount += a;
while (acount > 0) {
acount--;
IRQCount++;
if (IRQCount & 0x100) {
X6502_IRQBegin(FCEU_IQEXT);
IRQCount = IRQLatch;
}
}
} else {
acount += a * 3;
if (acount >= LCYCS) {
while (acount >= LCYCS) {
acount -= LCYCS;
IRQCount++;
if (IRQCount & 0x100) {
X6502_IRQBegin(FCEU_IQEXT);
IRQCount = IRQLatch;
}
}
}
}
}
}
+22 -8
View File
@@ -25,7 +25,7 @@
static uint8 is26;
static uint8 prg[2], chr[8], mirr;
static uint8 IRQLatch, IRQa, IRQd;
static uint8 IRQLatch, IRQa, IRQd, IRQMode;
static int32 IRQCount, CycleCount;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
@@ -40,6 +40,7 @@ static SFORMAT StateRegs[] =
{ &IRQLatch, 1, "IRQL" },
{ &IRQCount, 4, "IRQC" },
{ &CycleCount, 4, "CYCC" },
{ &IRQMode, 1, "IRQM" },
{ 0 }
};
@@ -109,6 +110,7 @@ static DECLFW(VRC6Write) {
case 0xE003: chr[7] = V; Sync(); break;
case 0xF000: IRQLatch = V; X6502_IRQEnd(FCEU_IQEXT); break;
case 0xF001:
IRQMode = V & 4;
IRQa = V & 2;
IRQd = V & 1;
if (V & 2)
@@ -132,13 +134,25 @@ static void VRC6Power(void) {
static void VRC6IRQHook(int a) {
if (IRQa) {
CycleCount += a * 3;
while(CycleCount >= 341) {
CycleCount -= 341;
IRQCount++;
if (IRQCount == 0x100) {
IRQCount = IRQLatch;
X6502_IRQBegin(FCEU_IQEXT);
if (IRQMode) {
CycleCount += a;
while (CycleCount > 0) {
CycleCount--;
IRQCount++;
if (IRQCount & 0x100) {
X6502_IRQBegin(FCEU_IQEXT);
IRQCount = IRQLatch;
}
}
} else {
CycleCount += a * 3;
while(CycleCount >= 341) {
CycleCount -= 341;
IRQCount++;
if (IRQCount == 0x100) {
IRQCount = IRQLatch;
X6502_IRQBegin(FCEU_IQEXT);
}
}
}
}
+22 -8
View File
@@ -21,7 +21,7 @@
#include "mapinc.h"
static uint8 vrc7idx, preg[3], creg[8], mirr;
static uint8 IRQLatch, IRQa, IRQd;
static uint8 IRQLatch, IRQa, IRQd, IRQMode;
static int32 IRQCount, CycleCount;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
@@ -44,6 +44,7 @@ static SFORMAT StateRegs[] =
{ &IRQCount, 4, "IRQC" },
{ &CycleCount, 4, "CYCC" },
{ (void**)VRC7Sound_saveptr, sizeof(*VRC7Sound) | FCEUSTATE_INDIRECT, "VRC7" },
{ &IRQMode, 1, "IRQM" },
{0}
};
@@ -134,6 +135,7 @@ static DECLFW(VRC7Write) {
case 0xE000: mirr = V & 3; Sync(); break;
case 0xE010: IRQLatch = V; X6502_IRQEnd(FCEU_IQEXT); break;
case 0xF000:
IRQMode = V & 4;
IRQa = V & 2;
IRQd = V & 1;
if (V & 2)
@@ -165,13 +167,25 @@ static void VRC7Close(void)
static void VRC7IRQHook(int a) {
if (IRQa) {
CycleCount += a * 3;
while(CycleCount >= 341) {
CycleCount -= 341;
IRQCount++;
if (IRQCount == 0x100) {
IRQCount = IRQLatch;
X6502_IRQBegin(FCEU_IQEXT);
if (IRQMode) {
CycleCount += a;
while (CycleCount > 0) {
CycleCount--;
IRQCount++;
if (IRQCount & 0x100) {
X6502_IRQBegin(FCEU_IQEXT);
IRQCount = IRQLatch;
}
}
} else {
CycleCount += a * 3;
while(CycleCount >= 341) {
CycleCount -= 341;
IRQCount++;
if (IRQCount == 0x100) {
IRQCount = IRQLatch;
X6502_IRQBegin(FCEU_IQEXT);
}
}
}
}
+10 -2
View File
@@ -562,10 +562,18 @@ void FCEU_LoadGameSave(CartInfo *LocalHWInfo) {
std::string soot = FCEU_MakeFName(FCEUMKF_SAV, 0, "sav");
sp = FCEUD_UTF8fopen(soot, "rb");
if (sp != NULL) {
if (sp != NULL)
{
for (int x = 0; x < 4; x++)
{
if (LocalHWInfo->SaveGame[x])
fread(LocalHWInfo->SaveGame[x], 1, LocalHWInfo->SaveGameLen[x], sp);
{
if ( fread(LocalHWInfo->SaveGame[x], 1, LocalHWInfo->SaveGameLen[x], sp) != static_cast<size_t>(LocalHWInfo->SaveGameLen[x]) )
{
FCEU_printf("Warning save game data read came up short!\n");
}
}
}
}
}
}
+1
View File
@@ -15,6 +15,7 @@ typedef struct {
// to help support games like "Karnov"
// that are not really MMC3 but are
// set to mapper 4.
int mirrorAs2Bits;
int battery; // Presence of an actual battery.
int ines2;
int submapper; // Submappers as defined by NES 2.0
+19 -41
View File
@@ -59,7 +59,7 @@ void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p)
}
CHEATF_SUBFAST SubCheats[256] = { 0 };
CHEATF_SUBFAST SubCheats[256];
uint32 numsubcheats = 0;
int globalCheatDisabled = 0;
int disableAutoLSCheats = 0;
@@ -152,28 +152,23 @@ int FCEU_CalcCheatAffectedBytes(uint32 address, uint32 size) {
return count;
}
static int AddCheatEntry(const char *name, uint32 addr, uint8 val, int compare, int status, int type);
static void 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.");
}
static int AddCheatEntry(const char *name, uint32 addr, uint8 val, int compare, int status, int type)
static void 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))))
{
CheatMemErr();
return(0);
}
CHEATF *temp = new CHEATF();
temp->name = strcpy((char*) FCEU_dmalloc(strlen(name) + 1), name);
temp->name = name;
temp->addr = addr;
temp->val = val;
temp->status = status;
temp->compare = compare;
temp->type = type;
temp->next = 0;
temp->next = nullptr;
if(cheats)
{
@@ -182,8 +177,6 @@ static int AddCheatEntry(const char *name, uint32 addr, uint8 val, int compare,
}
else
cheats = cheatsl = temp;
return (1);
}
/* The "override_existing" parameter is used only in cheat dialog import.
@@ -306,14 +299,13 @@ void FCEU_SaveGameCheats(FILE* fp, int release)
fputc(':', fp);
if (next->compare >= 0)
fprintf(fp, "%04x:%02x:%02x:%s\n", next->addr, next->val, next->compare, next->name);
fprintf(fp, "%04x:%02x:%02x:%s\n", next->addr, next->val, next->compare, next->name.c_str());
else
fprintf(fp, "%04x:%02x:%s\n", next->addr, next->val, next->name);
fprintf(fp, "%04x:%02x:%s\n", next->addr, next->val, next->name.c_str());
if (release) free(next->name);
struct CHEATF *t = next;
next = next->next;
if (release) free(t);
if (release) delete t;
}
}
@@ -333,8 +325,7 @@ void FCEU_FlushGameCheats(FILE *override, int nosave)
{
struct CHEATF *last=next;
next=next->next;
free(last->name);
free(last);
delete last;
if(!next) break;
}
cheats=cheatsl=0;
@@ -379,9 +370,7 @@ void FCEU_FlushGameCheats(FILE *override, int nosave)
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type)
{
if(!AddCheatEntry(name, addr, val, compare, 1, type))
return 0;
AddCheatEntry(name, addr, val, compare, 1, type);
savecheats = 1;
RebuildSubCheats();
@@ -415,8 +404,7 @@ int FCEUI_DelCheat(uint32 which)
else
cheats=cheatsl=0; // No (more) cheats.
}
free(cur->name); // Now that all references to this cheat are removed,
free(cur); // free the memory.
delete cur; // free the memory.
break;
} // *END REMOVE THIS CHEAT*
@@ -451,18 +439,18 @@ void FCEU_ApplyPeriodicCheats(void)
}
void FCEUI_ListCheats(int (*callb)(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data)
void FCEUI_ListCheats(int (*callb)(const char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data)
{
struct CHEATF *next=cheats;
while(next)
{
if(!callb(next->name,next->addr,next->val,next->compare,next->status,next->type,data)) break;
if(!callb(next->name.c_str(),next->addr,next->val,next->compare,next->status,next->type,data)) break;
next=next->next;
}
}
int FCEUI_GetCheat(uint32 which, char **name, uint32 *a, uint8 *v, int *compare, int *s, int *type)
int FCEUI_GetCheat(uint32 which, std::string *name, uint32 *a, uint8 *v, int *compare, int *s, int *type)
{
struct CHEATF *next=cheats;
uint32 x=0;
@@ -600,7 +588,7 @@ int FCEUI_DecodePAR(const char *str, int *a, int *v, int *c, int *type)
/* name can be NULL if the name isn't going to be changed. */
/* same goes for a, v, and s(except the values of each one must be <0) */
int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int c, int s, int type)
int FCEUI_SetCheat(uint32 which, const std::string *name, int32 a, int32 v, int c, int s, int type)
{
struct CHEATF *next = cheats;
uint32 x = 0;
@@ -610,13 +598,7 @@ int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int c, int
if(x == which)
{
if(name)
{
char *t;
if((t = (char *)realloc(next->name, strlen(name) + 1)))
strcpy(next->name = t, name);
else
return 0;
}
next->name = *name;
if(a >= 0)
next->addr = a;
if(v >= 0)
@@ -662,7 +644,7 @@ int FCEUI_ToggleCheat(uint32 which)
int FCEUI_GlobalToggleCheat(int global_enabled)
{
int _numsubcheats = numsubcheats;
unsigned int _numsubcheats = numsubcheats;
globalCheatDisabled = !global_enabled;
RebuildSubCheats();
return _numsubcheats != numsubcheats;
@@ -911,11 +893,7 @@ int FCEU_DeleteAllCheats(void)
while (cur)
{
next = cur->next;
if ( cur->name )
{
free(cur->name);
}
free(cur);
delete cur;
cur = next;
}
cheats = cheatsl = 0;
+9 -3
View File
@@ -33,16 +33,22 @@ extern int disableAutoLSCheats;
int FCEU_DisableAllCheats(void);
int FCEU_DeleteAllCheats(void);
typedef struct {
struct CHEATF_SUBFAST
{
uint16 addr;
uint8 val;
int compare;
readfunc PrevRead;
} CHEATF_SUBFAST;
CHEATF_SUBFAST(void)
{
addr = 0; val = 0; compare = 0; PrevRead = nullptr;
}
};
struct CHEATF {
struct CHEATF *next;
char *name;
std::string name;
uint16 addr;
uint8 val;
int compare; /* -1 for no compare. */
+15 -10
View File
@@ -11,25 +11,27 @@
#include <cstdio>
#include <cstdlib>
static char *aboutString = 0;
static std::string aboutString;
#ifndef FCEUX_BUILD_TIMESTAMP
#define FCEUX_BUILD_TIMESTAMP __TIME__ " " __DATE__
#endif
//#pragma message( "Compiling using C++ Std: " __FCEU_STRINGIZE(__cplusplus) )
// returns a string suitable for use in an aboutbox
const char *FCEUI_GetAboutString(void)
{
const char *aboutTemplate =
FCEU_NAME_AND_VERSION "\n\n"
"Administrators:\n"
"zeromus, mjbudd77, feos\n"
"zeromus, feos\n"
"\n"
"Current Contributors:\n"
"CaH4e3, rainwarrior, owomomo, punkrockguy318\n"
"CaH4e3, rainwarrior, owomomo, punkrockguy318, Cluster\n"
"\n"
"Past Contributors:\n"
"xhainingx, gocha, AnS\n"
"xhainingx, gocha, AnS, mjbudd77\n"
"\n"
"FCEUX 2.0:\n"
"mz, nitsujrehtona, SP, Ugly Joe,\n"
@@ -55,14 +57,17 @@ const char *FCEUI_GetAboutString(void)
"\n"
FCEUX_BUILD_TIMESTAMP "\n";
if (aboutString) return aboutString;
if (aboutString.size() > 0) return aboutString.c_str();
const char *compilerString = FCEUD_GetCompilerString();
//allocate the string and concatenate the template with the compiler string
if (!(aboutString = (char*)FCEU_dmalloc(strlen(aboutTemplate) + strlen(compilerString) + 1)))
return NULL;
char cppVersion[128];
sprintf(aboutString,"%s%s",aboutTemplate,compilerString);
return aboutString;
snprintf( cppVersion, sizeof(cppVersion), "\nCompiled using C++ Language Standard: %li\n", __cplusplus);
aboutString.assign( aboutTemplate );
aboutString.append( compilerString );
aboutString.append( cppVersion );
return aboutString.c_str();
}
+14 -5
View File
@@ -6,6 +6,7 @@
#include "cart.h"
#include "ines.h"
#include "debug.h"
#include "debugsymboltable.h"
#include "driver.h"
#include "ppu.h"
@@ -41,6 +42,13 @@ int offsetStringToInt(unsigned int type, const char* offsetBuffer)
}
else // BT_C
{
auto sym = debugSymbolTable.getSymbolAtAnyBank(offsetBuffer);
if (sym)
{
return sym->offset() & 0xFFFF;
}
int type = GIT_CART;
if (GameInfo)
@@ -642,7 +650,8 @@ uint16 StackNextIgnorePC = 0xFFFF;
///fires a breakpoint
static void breakpoint(uint8 *opcode, uint16 A, int size) {
int i, j, romAddrPC;
int i, romAddrPC;
unsigned int j;
uint8 brk_type;
uint8 stackop=0;
uint8 stackopstartaddr=0,stackopendaddr=0;
@@ -783,7 +792,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
{
if (watchpoint[i].flags & BT_R)
{
if ( (watchpoint[i].flags & WP_X) && (watchpoint[i].address == romAddrPC) )
if ( (watchpoint[i].flags & WP_X) && (watchpoint[i].address == static_cast<unsigned int>(romAddrPC)) )
{
BREAKHIT(i);
}
@@ -814,7 +823,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
// TXS and TSX only deal with the pointer.
if (watchpoint[i].flags & stackop)
{
for (j = (stackopstartaddr|0x0100); j <= (stackopendaddr|0x0100); j++)
for (j = (stackopstartaddr|0x0100); j <= (static_cast<unsigned int>(stackopendaddr)|0x0100); j++)
{
if (watchpoint[i].endaddress)
{
@@ -840,7 +849,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
// Pushes to stack
if (watchpoint[i].flags & WP_W)
{
for (j = (X.S|0x0100); j < (StackAddrBackup|0x0100); j++)
for (j = (X.S|0x0100); j < (static_cast<unsigned int>(StackAddrBackup)|0x0100); j++)
{
if (watchpoint[i].endaddress)
{
@@ -858,7 +867,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
// Pulls from stack
if (watchpoint[i].flags & WP_R)
{
for (j = (StackAddrBackup|0x0100); j < (X.S|0x0100); j++)
for (j = (StackAddrBackup|0x0100); j < (static_cast<unsigned int>(X.S)|0x0100); j++)
{
if (watchpoint[i].endaddress)
{
+911
View File
@@ -0,0 +1,911 @@
/// \file
/// \brief Implements debug symbol table (from .nl files)
#include "debugsymboltable.h"
#include "types.h"
#include "debug.h"
#include "fceu.h"
#include "cart.h"
#ifdef __QT_DRIVER__
#include "Qt/ConsoleUtilities.h"
#else
extern char LoadedRomFName[4096];
static inline const char* getRomFile() { return LoadedRomFName; }
#endif
extern FCEUGI *GameInfo;
debugSymbolTable_t debugSymbolTable;
static char dbgSymTblErrMsg[256] = {0};
static bool dbgSymAllowDuplicateNames = true;
//--------------------------------------------------------------
// debugSymbol_t
//--------------------------------------------------------------
int debugSymbol_t::updateName( const char *name, int arrayIndex )
{
std::string newName;
newName.assign( name );
while ( newName.size() > 0 )
{
if ( isspace( newName.back() ) )
{
newName.pop_back();
}
else
{
break;
}
}
if (arrayIndex >= 0)
{
char stmp[32];
sprintf( stmp, "[%i]", arrayIndex );
newName.append(stmp);
}
if (page)
{
debugSymbol_t *dupSym = debugSymbolTable.getSymbol( page->pageNum(), newName );
if (!dbgSymAllowDuplicateNames && dupSym != nullptr && dupSym != this)
{
snprintf( dbgSymTblErrMsg, sizeof(dbgSymTblErrMsg), "Error: debug symbol '%s' already exists in %s page.\n", newName.c_str(), page->pageName() );
return -1;
}
}
_name = newName;
debugSymbolTable.updateSymbol(this);
return 0;
}
//--------------------------------------------------------------
void debugSymbol_t::trimTrailingSpaces(void)
{
while ( _name.size() > 0 )
{
if ( isspace( _name.back() ) )
{
_name.pop_back();
}
else
{
break;
}
}
while ( _comment.size() > 0 )
{
if ( isspace( _comment.back() ) )
{
_comment.pop_back();
}
else
{
break;
}
}
}
//--------------------------------------------------------------
// debugSymbolPage_t
//--------------------------------------------------------------
debugSymbolPage_t::debugSymbolPage_t(int page)
{
_pageNum = page;
_pageName[0] = 0;
if (page == -2)
{
strcpy( _pageName, "REG");
}
else if (page == -1)
{
strcpy( _pageName, "RAM");
}
else
{
snprintf( _pageName, sizeof(_pageName), "%X", page);
_pageName[sizeof(_pageName)-1] = 0;
}
}
//--------------------------------------------------------------
debugSymbolPage_t::~debugSymbolPage_t(void)
{
for (auto it=symMap.begin(); it!=symMap.end(); it++)
{
delete it->second;
}
}
//--------------------------------------------------------------
int debugSymbolPage_t::addSymbol( debugSymbol_t*sym )
{
// Check if symbol already is loaded by that name or offset
if ( symMap.count( sym->offset() ) )
{
snprintf( dbgSymTblErrMsg, sizeof(dbgSymTblErrMsg), "Error: symbol offset 0x%04X already has an entry on %s page\n", sym->offset(), _pageName );
return -1;
}
if ( !dbgSymAllowDuplicateNames && (sym->name().size() > 0) && symNameMap.count( sym->name() ) )
{
snprintf( dbgSymTblErrMsg, sizeof(dbgSymTblErrMsg), "Error: symbol name '%s' already exists on %s page\n", sym->name().c_str(), _pageName );
return -1;
}
symMap[ sym->offset() ] = sym;
sym->page = this;
// Comment only lines don't need to have a name.
if (sym->name().size() > 0)
{
symNameMap[ sym->name() ] = sym;
}
return 0;
}
//--------------------------------------------------------------
debugSymbol_t *debugSymbolPage_t::getSymbolAtOffset( int ofs )
{
auto it = symMap.find( ofs );
return it != symMap.end() ? it->second : nullptr;
}
//--------------------------------------------------------------
debugSymbol_t *debugSymbolPage_t::getSymbol( const std::string &name )
{
auto it = symNameMap.find( name );
return it != symNameMap.end() ? it->second : nullptr;
}
//--------------------------------------------------------------
int debugSymbolPage_t::deleteSymbolAtOffset( int ofs )
{
auto it = symMap.find( ofs );
if ( it != symMap.end() )
{
auto sym = it->second;
if ( sym->name().size() > 0 )
{
auto itName = symNameMap.find( sym->name() );
if ( (itName != symNameMap.end()) && (itName->second == sym) )
{
symNameMap.erase(itName);
}
}
symMap.erase(it);
delete sym;
return 0;
}
return -1;
}
//--------------------------------------------------------------
int debugSymbolPage_t::updateSymbol(debugSymbol_t *sym)
{
auto itName = symNameMap.begin();
while (itName != symNameMap.end())
{
if (itName->second == sym)
{
if (sym->name().size() == 0 || sym->name().compare( itName->first ) )
{
//printf("Changing Name: %s %s\n", itName->first.c_str(), sym->name().c_str() );
itName = symNameMap.erase(itName);
}
break;
}
else
{
itName++;
}
}
if (sym->name().size() > 0)
{
symNameMap[ sym->name() ] = sym;
}
// Sanity Check
auto it = symMap.find( sym->offset() );
if ( it == symMap.end() )
{ // This shouldn't happen
return -1;
}
return 0;
}
//--------------------------------------------------------------
int debugSymbolPage_t::save(void)
{
FILE *fp;
debugSymbol_t *sym;
std::map <int, debugSymbol_t*>::iterator it;
const char *romFile;
std::string filename;
char stmp[512];
int i,j;
if ( symMap.size() == 0 )
{
//printf("Skipping Empty Debug Page Save\n");
return 0;
}
if ( _pageNum == -2 )
{
//printf("Skipping Register Debug Page Save\n");
return 0;
}
romFile = getRomFile();
if ( romFile == nullptr )
{
return -1;
}
i=0;
while ( romFile[i] != 0 )
{
if ( romFile[i] == '|' )
{
filename.push_back('.');
}
else
{
filename.push_back(romFile[i]);
}
i++;
}
if ( _pageNum < 0 )
{
filename.append(".ram.nl" );
}
else
{
char suffix[32];
sprintf( suffix, ".%X.nl", _pageNum );
filename.append( suffix );
}
fp = ::fopen( filename.c_str(), "w" );
if ( fp == nullptr )
{
FCEU_printf("Error: Could not open file '%s' for writing\n", filename.c_str() );
return -1;
}
for (it=symMap.begin(); it!=symMap.end(); it++)
{
const char *c;
sym = it->second;
i=0; j=0; c = sym->_comment.c_str();
while ( c[i] != 0 )
{
if ( c[i] == '\n' )
{
i++; break;
}
else
{
stmp[j] = c[i]; j++; i++;
}
}
stmp[j] = 0;
fprintf( fp, "$%04X#%s#%s\n", sym->offset(), sym->name().c_str(), stmp );
j=0;
while ( c[i] != 0 )
{
if ( c[i] == '\n' )
{
i++; stmp[j] = 0;
if ( j > 0 )
{
fprintf( fp, "\\%s\n", stmp );
}
j=0;
}
else
{
stmp[j] = c[i]; j++; i++;
}
}
}
fclose(fp);
return 0;
}
//--------------------------------------------------------------
void debugSymbolPage_t::print(void)
{
FILE *fp;
debugSymbol_t *sym;
std::map <int, debugSymbol_t*>::iterator it;
fp = stdout;
fprintf( fp, "Page: %X \n", _pageNum );
for (it=symMap.begin(); it!=symMap.end(); it++)
{
sym = it->second;
fprintf( fp, " Sym: $%04X '%s' \n", sym->ofs, sym->name().c_str() );
}
}
//--------------------------------------------------------------
// debugSymbolTable_t
//--------------------------------------------------------------
debugSymbolTable_t::debugSymbolTable_t(void)
{
cs = new FCEU::mutex();
dbgSymTblErrMsg[0] = 0;
}
//--------------------------------------------------------------
debugSymbolTable_t::~debugSymbolTable_t(void)
{
this->clear();
if (cs)
{
delete cs;
}
}
//--------------------------------------------------------------
void debugSymbolTable_t::clear(void)
{
FCEU::autoScopedLock alock(cs);
std::map <int, debugSymbolPage_t*>::iterator it;
for (it=pageMap.begin(); it!=pageMap.end(); it++)
{
delete it->second;
}
pageMap.clear();
}
//--------------------------------------------------------------
static int generateNLFilenameForBank(int bank, std::string &NLfilename)
{
int i;
const char *romFile;
romFile = getRomFile();
if ( romFile == nullptr )
{
return -1;
}
i=0;
while ( romFile[i] != 0 )
{
if ( romFile[i] == '|' )
{
NLfilename.push_back('.');
}
else
{
NLfilename.push_back(romFile[i]);
}
i++;
}
if (bank < 0)
{
// The NL file for the RAM addresses has the name nesrom.nes.ram.nl
NLfilename.append(".ram.nl");
}
else
{
char stmp[64];
#ifdef DW3_NL_0F_1F_HACK
if(bank == 0x0F)
bank = 0x1F;
#endif
sprintf( stmp, ".%X.nl", bank);
NLfilename.append( stmp );
}
return 0;
}
//--------------------------------------------------------------
int generateNLFilenameForAddress(int address, std::string &NLfilename)
{
int bank;
if (address < 0x8000)
{
bank = -1;
}
else
{
bank = getBank(address);
#ifdef DW3_NL_0F_1F_HACK
if(bank == 0x0F)
bank = 0x1F;
#endif
}
return generateNLFilenameForBank( bank, NLfilename );
}
//--------------------------------------------------------------
int debugSymbolTable_t::loadFileNL( int bank )
{
FILE *fp;
int i, j, ofs, lineNum = 0, literal = 0, array = 0;
std::string fileName;
char stmp[512], line[512];
debugSymbolPage_t *page = nullptr;
debugSymbol_t *sym = nullptr;
FCEU::autoScopedLock alock(cs);
//printf("Looking to Load Debug Bank: $%X \n", bank );
if ( generateNLFilenameForBank( bank, fileName ) )
{
return -1;
}
//printf("Loading NL File: %s\n", fileName.c_str() );
fp = ::fopen( fileName.c_str(), "r" );
if ( fp == nullptr )
{
return -1;
}
page = new debugSymbolPage_t(bank);
pageMap[ page->pageNum() ] = page;
while ( fgets( line, sizeof(line), fp ) != 0 )
{
i=0; lineNum++;
//printf("%4i:%s", lineNum, line );
if ( line[i] == '\\' )
{
// Line is a comment continuation line.
i++;
j=0;
stmp[j] = '\n'; j++;
while ( line[i] != 0 )
{
stmp[j] = line[i]; j++; i++;
}
stmp[j] = 0;
j--;
while ( j >= 0 )
{
if ( isspace( stmp[j] ) )
{
stmp[j] = 0;
}
else
{
break;
}
j--;
}
if ( sym != nullptr )
{
sym->_comment.append( stmp );
}
}
else if ( line[i] == '$' )
{
// Line is a new debug offset
array = 0;
j=0; i++;
if ( !isxdigit( line[i] ) )
{
FCEU_printf("Error: Invalid Offset on Line %i of File %s\n", lineNum, fileName.c_str() );
}
while ( isxdigit( line[i] ) )
{
stmp[j] = line[i]; i++; j++;
}
stmp[j] = 0;
ofs = strtol( stmp, nullptr, 16 );
if ( line[i] == '/' )
{
j=0; i++;
while ( isxdigit( line[i] ) )
{
stmp[j] = line[i]; i++; j++;
}
stmp[j] = 0;
array = strtol( stmp, nullptr, 16 );
}
if ( line[i] != '#' )
{
FCEU_printf("Error: Missing field delimiter following offset $%X on Line %i of File %s\n", ofs, lineNum, fileName.c_str() );
continue;
}
i++;
while ( isspace(line[i]) ) i++;
j = 0;
while ( line[i] != 0 )
{
if ( line[i] == '\\' )
{
if ( literal )
{
switch ( line[i] )
{
case 'r':
stmp[j] = '\r';
break;
case 'n':
stmp[j] = '\n';
break;
case 't':
stmp[j] = '\t';
break;
default:
stmp[j] = line[i];
break;
}
j++; i++;
literal = 0;
}
else
{
i++;
literal = !literal;
}
}
else if ( line[i] == '#' )
{
break;
}
else
{
stmp[j] = line[i]; j++; i++;
}
}
stmp[j] = 0;
j--;
while ( j >= 0 )
{
if ( isspace( stmp[j] ) )
{
stmp[j] = 0;
}
else
{
break;
}
j--;
}
if ( line[i] != '#' )
{
FCEU_printf("Error: Missing field delimiter following name '%s' on Line %i of File %s\n", stmp, lineNum, fileName.c_str() );
continue;
}
i++;
sym = new debugSymbol_t( ofs, stmp );
if ( sym == nullptr )
{
FCEU_printf("Error: Failed to allocate memory for offset $%04X Name '%s' on Line %i of File %s\n", ofs, stmp, lineNum, fileName.c_str() );
continue;
}
sym->ofs = ofs;
sym->_name.assign( stmp );
while ( isspace( line[i] ) ) i++;
j=0;
while ( line[i] != 0 )
{
stmp[j] = line[i]; j++; i++;
}
stmp[j] = 0;
j--;
while ( j >= 0 )
{
if ( isspace( stmp[j] ) )
{
stmp[j] = 0;
}
else
{
break;
}
j--;
}
sym->_comment.assign( stmp );
if ( array > 0 )
{
debugSymbol_t *arraySym = nullptr;
for (j=0; j<array; j++)
{
arraySym = new debugSymbol_t();
if ( arraySym )
{
arraySym->ofs = sym->ofs + j;
sprintf( stmp, "[%i]", j );
arraySym->_name.assign( sym->name() );
arraySym->_name.append( stmp );
arraySym->_comment.assign( sym->comment() );
if ( page->addSymbol( arraySym ) )
{
FCEU_printf("Error: Failed to add symbol for offset $%04X Name '%s' on Line %i of File %s\n", ofs, arraySym->name().c_str(), lineNum, fileName.c_str() );
FCEU_printf("%s\n", errorMessage() );
delete arraySym; arraySym = nullptr; // Failed to add symbol
}
}
}
delete sym; sym = nullptr; // Delete temporary symbol
}
else
{
if ( page->addSymbol( sym ) )
{
FCEU_printf("Error: Failed to add symbol for offset $%04X Name '%s' on Line %i of File %s\n", ofs, sym->name().c_str(), lineNum, fileName.c_str() );
FCEU_printf("%s\n", errorMessage() );
delete sym; sym = nullptr; // Failed to add symbol
}
}
}
}
::fclose(fp);
return 0;
}
//--------------------------------------------------------------
int debugSymbolTable_t::loadRegisterMap(void)
{
FCEU::autoScopedLock alock(cs);
debugSymbolPage_t *page;
page = new debugSymbolPage_t(-2);
page->addSymbol( new debugSymbol_t( 0x2000, "PPU_CTRL" ) );
page->addSymbol( new debugSymbol_t( 0x2001, "PPU_MASK" ) );
page->addSymbol( new debugSymbol_t( 0x2002, "PPU_STATUS" ) );
page->addSymbol( new debugSymbol_t( 0x2003, "PPU_OAM_ADDR" ) );
page->addSymbol( new debugSymbol_t( 0x2004, "PPU_OAM_DATA" ) );
page->addSymbol( new debugSymbol_t( 0x2005, "PPU_SCROLL" ) );
page->addSymbol( new debugSymbol_t( 0x2006, "PPU_ADDRESS" ) );
page->addSymbol( new debugSymbol_t( 0x2007, "PPU_DATA" ) );
page->addSymbol( new debugSymbol_t( 0x4000, "SQ1_VOL" ) );
page->addSymbol( new debugSymbol_t( 0x4001, "SQ1_SWEEP" ) );
page->addSymbol( new debugSymbol_t( 0x4002, "SQ1_LO" ) );
page->addSymbol( new debugSymbol_t( 0x4003, "SQ1_HI" ) );
page->addSymbol( new debugSymbol_t( 0x4004, "SQ2_VOL" ) );
page->addSymbol( new debugSymbol_t( 0x4005, "SQ2_SWEEP" ) );
page->addSymbol( new debugSymbol_t( 0x4006, "SQ2_LO" ) );
page->addSymbol( new debugSymbol_t( 0x4007, "SQ2_HI" ) );
page->addSymbol( new debugSymbol_t( 0x4008, "TRI_LINEAR" ) );
// page->addSymbol( new debugSymbol_t( 0x4009, "UNUSED" ) );
page->addSymbol( new debugSymbol_t( 0x400A, "TRI_LO" ) );
page->addSymbol( new debugSymbol_t( 0x400B, "TRI_HI" ) );
page->addSymbol( new debugSymbol_t( 0x400C, "NOISE_VOL" ) );
// page->addSymbol( new debugSymbol_t( 0x400D, "UNUSED" ) );
page->addSymbol( new debugSymbol_t( 0x400E, "NOISE_LO" ) );
page->addSymbol( new debugSymbol_t( 0x400F, "NOISE_HI" ) );
page->addSymbol( new debugSymbol_t( 0x4010, "DMC_FREQ" ) );
page->addSymbol( new debugSymbol_t( 0x4011, "DMC_RAW" ) );
page->addSymbol( new debugSymbol_t( 0x4012, "DMC_START" ) );
page->addSymbol( new debugSymbol_t( 0x4013, "DMC_LEN" ) );
page->addSymbol( new debugSymbol_t( 0x4014, "OAM_DMA" ) );
page->addSymbol( new debugSymbol_t( 0x4015, "APU_STATUS" ) );
page->addSymbol( new debugSymbol_t( 0x4016, "JOY1" ) );
page->addSymbol( new debugSymbol_t( 0x4017, "JOY2_FRAME" ) );
pageMap[ page->pageNum() ] = page;
return 0;
}
//--------------------------------------------------------------
int debugSymbolTable_t::loadGameSymbols(void)
{
int nPages, pageSize, romSize = 0x10000;
this->save();
this->clear();
if ( GameInfo != nullptr )
{
romSize = 16 + CHRsize[0] + PRGsize[0];
}
loadFileNL( -1 );
loadRegisterMap();
pageSize = (1<<debuggerPageSize);
//nPages = 1<<(15-debuggerPageSize);
nPages = romSize / pageSize;
//printf("RomSize: %i NumPages: %i \n", romSize, nPages );
for(int i=0;i<nPages;i++)
{
//printf("Loading Page Offset: $%06X\n", pageSize*i );
loadFileNL( i );
}
//print();
return 0;
}
int debugSymbolTable_t::addSymbolAtBankOffset(int bank, int ofs, const char *name, const char *comment)
{
int result = -1;
debugSymbol_t *sym = new debugSymbol_t(ofs, name, comment);
result = addSymbolAtBankOffset(bank, ofs, sym);
if (result)
{ // Symbol add failed
delete sym;
}
return result;
}
//--------------------------------------------------------------
int debugSymbolTable_t::addSymbolAtBankOffset( int bank, int ofs, debugSymbol_t *sym )
{
int result = -1;
debugSymbolPage_t *page;
std::map <int, debugSymbolPage_t*>::iterator it;
FCEU::autoScopedLock alock(cs);
it = pageMap.find( bank );
if ( it == pageMap.end() )
{
page = new debugSymbolPage_t(bank);
pageMap[ bank ] = page;
}
else
{
page = it->second;
}
result = page->addSymbol( sym );
return result;
}
//--------------------------------------------------------------
int debugSymbolTable_t::deleteSymbolAtBankOffset( int bank, int ofs )
{
debugSymbolPage_t *page;
std::map <int, debugSymbolPage_t*>::iterator it;
FCEU::autoScopedLock alock(cs);
it = pageMap.find( bank );
if ( it == pageMap.end() )
{
return -1;
}
else
{
page = it->second;
}
return page->deleteSymbolAtOffset( ofs );
}
//--------------------------------------------------------------
int debugSymbolTable_t::updateSymbol(debugSymbol_t *sym)
{
FCEU::autoScopedLock alock(cs);
if (sym->page == nullptr)
{
return -1;
}
return sym->page->updateSymbol(sym);
}
//--------------------------------------------------------------
debugSymbol_t *debugSymbolTable_t::getSymbolAtBankOffset( int bank, int ofs )
{
FCEU::autoScopedLock alock(cs);
auto it = pageMap.find( bank );
return it != pageMap.end() ? it->second->getSymbolAtOffset( ofs ) : nullptr;
}
//--------------------------------------------------------------
debugSymbol_t *debugSymbolTable_t::getSymbol( int bank, const std::string &name )
{
FCEU::autoScopedLock alock(cs);
auto it = pageMap.find( bank );
return it != pageMap.end() ? it->second->getSymbol( name ) : nullptr;
}
//--------------------------------------------------------------
debugSymbol_t *debugSymbolTable_t::getSymbolAtAnyBank( const std::string &name )
{
FCEU::autoScopedLock alock(cs);
for (auto &page : pageMap)
{
auto sym = getSymbol( page.first, name );
if ( sym )
{
return sym;
}
}
return nullptr;
}
//--------------------------------------------------------------
void debugSymbolTable_t::save(void)
{
debugSymbolPage_t *page;
std::map <int, debugSymbolPage_t*>::iterator it;
FCEU::autoScopedLock alock(cs);
for (it=pageMap.begin(); it!=pageMap.end(); it++)
{
page = it->second;
page->save();
}
}
//--------------------------------------------------------------
void debugSymbolTable_t::print(void)
{
debugSymbolPage_t *page;
std::map <int, debugSymbolPage_t*>::iterator it;
FCEU::autoScopedLock alock(cs);
for (it=pageMap.begin(); it!=pageMap.end(); it++)
{
page = it->second;
page->print();
}
}
//--------------------------------------------------------------
const char *debugSymbolTable_t::errorMessage(void)
{
return dbgSymTblErrMsg;
}
//--------------------------------------------------------------
+166
View File
@@ -0,0 +1,166 @@
#ifndef _DEBUGSYMBOLTABLE_H_
#define _DEBUGSYMBOLTABLE_H_
#include <string>
#include <map>
#include "utils/mutex.h"
class debugSymbolPage_t;
class debugSymbolTable_t;
class debugSymbol_t
{
public:
debugSymbol_t(void)
{
ofs = 0;
page = nullptr;
};
debugSymbol_t( int ofs, const char *name = nullptr, const char *comment = nullptr )
{
this->ofs = ofs;
if (name)
{
this->_name.assign(name);
}
if ( comment )
{
this->_comment.assign( comment );
}
page = nullptr;
}
const std::string &name(void)
{
return _name;
}
const std::string &comment(void)
{
return _comment;
}
void commentAssign( std::string str )
{
_comment.assign(str);
return;
}
void commentAssign( const char *str )
{
_comment.assign(str);
return;
}
int offset(void)
{
return ofs;
}
void setOffset( int o )
{
if (o != ofs)
{
ofs = o;
}
}
int updateName( const char *name, int arrayIndex = -1 );
void trimTrailingSpaces(void);
private:
int ofs;
std::string _name;
std::string _comment;
debugSymbolPage_t *page;
friend class debugSymbolPage_t;
friend class debugSymbolTable_t;
};
class debugSymbolPage_t
{
public:
debugSymbolPage_t(int page);
~debugSymbolPage_t(void);
int save(void);
void print(void);
int size(void){ return symMap.size(); }
int addSymbol( debugSymbol_t *sym );
int deleteSymbolAtOffset( int ofs );
int updateSymbol( debugSymbol_t *sym );
debugSymbol_t *getSymbolAtOffset( int ofs );
debugSymbol_t *getSymbol( const std::string &name );
int pageNum(void)
{
return _pageNum;
}
const char *pageName(void)
{
return _pageName;
}
private:
int _pageNum;
char _pageName[8];
std::map <int, debugSymbol_t*> symMap;
std::map <std::string, debugSymbol_t*> symNameMap;
friend class debugSymbolTable_t;
};
class debugSymbolTable_t
{
public:
debugSymbolTable_t(void);
~debugSymbolTable_t(void);
int loadFileNL( int addr );
int loadGameSymbols(void);
int numPages(void){ return pageMap.size(); }
void save(void);
void clear(void);
void print(void);
debugSymbol_t *getSymbolAtBankOffset( int bank, int ofs );
debugSymbol_t *getSymbol( int bank, const std::string& name);
debugSymbol_t *getSymbolAtAnyBank( const std::string& name);
int addSymbolAtBankOffset( int bank, int ofs, debugSymbol_t *sym );
int addSymbolAtBankOffset(int bank, int ofs, const char* name, const char* comment = nullptr);
int deleteSymbolAtBankOffset( int bank, int ofs );
int updateSymbol( debugSymbol_t *sym );
const char *errorMessage(void);
private:
std::map <int, debugSymbolPage_t*> pageMap;
FCEU::mutex *cs;
int loadRegisterMap(void);
};
extern debugSymbolTable_t debugSymbolTable;
#endif
+10 -5
View File
@@ -23,7 +23,7 @@ ArchiveScanRecord FCEUD_ScanArchive(std::string fname);
const char *FCEUD_GetCompilerString();
//This makes me feel dirty for some reason.
void FCEU_printf(const char *format, ...);
void FCEU_printf( __FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 2 );
#define FCEUI_printf FCEU_printf
//Video interface
@@ -192,7 +192,7 @@ void TaseditorManualFunction(void);
int32 FCEUI_GetDesiredFPS(void);
void FCEUI_SaveSnapshot(void);
void FCEUI_SaveSnapshotAs(void);
void FCEU_DispMessage(const char *format, int disppos, ...);
void FCEU_DispMessage( __FCEU_PRINTF_FORMAT const char *format, int disppos, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 3 );
#define FCEUI_DispMessage FCEU_DispMessage
int FCEUI_DecodePAR(const char *code, int *a, int *v, int *c, int *type);
@@ -207,10 +207,10 @@ void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a,
void FCEUI_CheatSearchGet(int (*callb)(uint32 a, uint8 last, uint8 current, void *data), void *data);
void FCEUI_CheatSearchBegin(void);
void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2);
void FCEUI_ListCheats(int (*callb)(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data);
void FCEUI_ListCheats(int (*callb)(const char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data);
int FCEUI_GetCheat(uint32 which, char **name, uint32 *a, uint8 *v, int *compare, int *s, int *type);
int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int compare,int s, int type);
int FCEUI_GetCheat(uint32 which, std::string *name, uint32 *a, uint8 *v, int *compare, int *s, int *type);
int FCEUI_SetCheat(uint32 which, const std::string *name, int32 a, int32 v, int compare,int s, int type);
void FCEUI_CheatSearchShowExcluded(void);
void FCEUI_CheatSearchSetCurrentAsOriginal(void);
@@ -254,6 +254,8 @@ void FCEUI_VSUniToggleDIP(int w);
uint8 FCEUI_VSUniGetDIPs(void);
void FCEUI_VSUniSetDIP(int w, int state);
void FCEUI_VSUniCoin(void);
void FCEUI_VSUniCoin2(void);
void FCEUI_VSUniService(void);
void FCEUI_FDSInsert(void); //mbg merge 7/17/06 changed to void fn(void) to make it an EMUCMDFN
//int FCEUI_FDSEject(void);
@@ -330,6 +332,9 @@ void FCEUD_DebugBreakpoint(int bp_num);
///the driver should log the current instruction, if it wants (we should move the code in the win driver that does this to the shared area)
void FCEUD_TraceInstruction(uint8 *opcode, int size);
///the driver should flush its trace log
void FCEUD_FlushTrace();
///the driver might should update its NTView (only used if debugging support is compiled in)
void FCEUD_UpdateNTView(int scanline, bool drawall);
+48 -16
View File
@@ -26,7 +26,11 @@
static void GetString(char *s, int max)
{
int x;
fgets(s,max,stdin);
if ( fgets(s,max,stdin) == nullptr )
{
s[0] = 0;
return;
}
for(x=0;x<max;x++)
if(s[x]=='\n')
@@ -41,7 +45,10 @@ static uint32 GetH16(unsigned int def)
{
char buf[32];
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return def;
}
if(buf[0]=='\n')
return(def);
if(buf[0]=='$')
@@ -56,7 +63,10 @@ static uint8 Get8(unsigned int def)
{
char buf[32];
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return def;
}
if(buf[0]=='\n')
return(def);
sscanf(buf,"%u",&def);
@@ -67,7 +77,10 @@ static int GetI(int def)
{
char buf[32];
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return def;
}
if(buf[0]=='\n')
return(def);
sscanf(buf,"%d",&def);
@@ -78,7 +91,10 @@ static int GetYN(int def)
{
char buf[32];
printf("(Y/N)[%s]: ",def?"Y":"N");
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return def;
}
if(buf[0]=='y' || buf[0]=='Y')
return(1);
if(buf[0]=='n' || buf[0]=='N')
@@ -114,7 +130,10 @@ int ListChoice(int hmm)
tryagain:
printf(" <'Enter' to continue, (S)top, or enter a number.> ");
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return -1;
}
if(buf[0]=='s' || buf[0]=='S') return(-1);
if(buf[0]=='\n') return(0);
if(!sscanf(buf,"%d",&num))
@@ -128,7 +147,10 @@ int ListChoice(int hmm)
tryagain2:
printf(" <'Enter' to make no selection or enter a number.> ");
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return -1;
}
if(buf[0]=='\n') return(0);
if(!sscanf(buf,"%d",&num))
return(0);
@@ -199,7 +221,8 @@ static void ToggleCheat(int num)
static void ModifyCheat(int num)
{
char *name;
std::string name;
std::string *pName;
char buf[256];
uint32 A;
uint8 V;
@@ -211,7 +234,7 @@ static void ModifyCheat(int num)
FCEUI_GetCheat(num, &name, &A, &V, &compare, &s, &type);
printf("Name [%s]: ",name);
printf("Name [%s]: ",name.c_str());
GetString(buf,256);
/* This obviously doesn't allow for cheats with no names. Bah. Who wants
@@ -219,9 +242,9 @@ static void ModifyCheat(int num)
*/
if(buf[0])
name=buf; // Change name when FCEUI_SetCheat() is called.
pName=&name; // Change name when FCEUI_SetCheat() is called.
else
name=0; // Don't change name when FCEUI_SetCheat() is called.
pName=nullptr; // Don't change name when FCEUI_SetCheat() is called.
printf("Address [$%04x]: ",(unsigned int)A);
A=GetH16(A);
@@ -240,7 +263,7 @@ static void ModifyCheat(int num)
if(t=='Y' || t=='y') s=1;
else if(t=='N' || t=='n') s=0;
FCEUI_SetCheat(num,name,A,V,compare,s,type);
FCEUI_SetCheat(num,pName,A,V,compare,s,type);
}
@@ -320,7 +343,7 @@ static void AddCheat(void)
}
static int lid;
static int clistcallb(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data)
static int clistcallb(const char *name, uint32 a, uint8 v, int compare, int s, int type, void *data)
{
char tmp[512];
int ret;
@@ -348,7 +371,10 @@ static void ListCheats(void)
{
char tmp[32];
printf(" <(T)oggle status, (M)odify, or (D)elete this cheat.> ");
fgets(tmp,ARRAY_SIZE(tmp),stdin);
if ( fgets(tmp,ARRAY_SIZE(tmp),stdin) == nullptr )
{
tmp[0] = 0;
}
switch(tolower(tmp[0]))
{
case 't':ToggleCheat(which);
@@ -405,7 +431,10 @@ static int ShowShortList(const char *moe[], int n, int def)
clo:
printf("\nSelection [%d]> ",def+1);
fgets(tmp,ARRAY_SIZE(tmp),stdin);
if ( fgets(tmp,ARRAY_SIZE(tmp),stdin) == nullptr )
{
return def;
}
if(tmp[0]=='\n')
return def;
c=tolower(tmp[0]);
@@ -504,7 +533,10 @@ static void DoMenu(MENU *men)
recommand:
printf("Command> ");
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return;
}
c=tolower(buf[0]);
if(c=='\n')
goto recommand;
+6 -1
View File
@@ -145,6 +145,11 @@ static void GetValueR(FILE *fp, char *str, void *v, int c)
{
if(!c) // String, allocate some memory.
{
// Windows enforces a 32767 character limit for text boxes by default
// If a string exceeds this length, it's probably a corrupt file
if (s > 32768)
goto gogl;
if(!(*(char **)v=(char*)malloc(s)))
goto gogl;
@@ -208,7 +213,7 @@ void SaveParse(const CFGSTRUCT *cfgst, FILE *fp)
if(*(char **)cfgst[x].ptr)
{
// Only save it if there IS a string.
unsigned int len = strlen(*(char **)cfgst[x].ptr);
size_t len = strlen(*(char **)cfgst[x].ptr);
SetValueR(fp,cfgst[x].name,*(char **)cfgst[x].ptr, len + 1);
}
}
+7 -7
View File
@@ -641,7 +641,7 @@ Config::_load()
int
Config::_loadFile(const char* fname)
{
signed int pos, eqPos;
size_t pos=0, eqPos=0;
std::fstream config;
std::map<std::string, int>::iterator int_i;
std::map<std::string, double>::iterator dbl_i;
@@ -656,7 +656,7 @@ Config::_loadFile(const char* fname)
configFile = fname;
}
std::string line, name, value;
char buf[1024];
char buf[4096];
// set the exception handling to catch i/o errors
config.exceptions(std::fstream::badbit);
@@ -671,7 +671,7 @@ Config::_loadFile(const char* fname)
while(!config.eof()) {
// read a line
config.getline(buf, 1024);
config.getline(buf, sizeof(buf));
line = buf;
// check line validity
@@ -723,7 +723,7 @@ Config::save()
std::map<std::string, double>::iterator dbl_i;
std::map<std::string, std::string>::iterator str_i;
std::string configFile = _dir + "/" + cfgFile;
char buf[1024];
char buf[4096];
// set the exception handling to catch i/o errors
config.exceptions(std::ios::failbit | std::ios::badbit);
@@ -741,19 +741,19 @@ Config::save()
// write each configuration setting
for(int_i = _intOptMap.begin(); int_i != _intOptMap.end(); int_i++)
{
snprintf(buf, 1024, "%s = %d\n",
snprintf(buf, sizeof(buf), "%s = %d\n",
int_i->first.c_str(), int_i->second);
config.write(buf, strlen(buf));
}
for(dbl_i = _dblOptMap.begin(); dbl_i != _dblOptMap.end(); dbl_i++)
{
snprintf(buf, 1024, "%s = %f\n",
snprintf(buf, sizeof(buf), "%s = %f\n",
dbl_i->first.c_str(), dbl_i->second);
config.write(buf, strlen(buf));
}
for(str_i = _strOptMap.begin(); str_i != _strOptMap.end(); str_i++)
{
snprintf(buf, 1024, "%s = %s\n",
snprintf(buf, sizeof(buf), "%s = %s\n",
str_i->first.c_str(), str_i->second.c_str());
config.write(buf, strlen(buf));
}
+11 -11
View File
@@ -238,18 +238,18 @@ void KillBlitToHigh(void)
{
if(palettetranslate)
{
free(palettetranslate);
FCEU_free(palettetranslate);
palettetranslate=NULL;
}
if(specbuf8bpp)
{
free(specbuf8bpp);
FCEU_free(specbuf8bpp);
specbuf8bpp = NULL;
}
if(specbuf32bpp)
{
free(specbuf32bpp);
FCEU_free(specbuf32bpp);
specbuf32bpp = NULL;
}
if(specbuf)
@@ -259,11 +259,11 @@ void KillBlitToHigh(void)
hq3x_Kill();
else
hq2x_Kill();
free(specbuf);
FCEU_free(specbuf);
specbuf=NULL;
}
if (nes_ntsc) {
free(nes_ntsc);
FCEU_free(nes_ntsc);
nes_ntsc = NULL;
}
if (ntscblit) {
@@ -466,7 +466,7 @@ void Blit8To8(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, in
/* Todo: Make sure 24bpp code works right with big-endian cpus */
//takes a pointer to XBuf and applies fully modern deemph palettizing
template<int SCALE> static u32 _ModernDeemphColorMap(u8* src, u8* srcbuf)
template<int SCALE> static u32 _ModernDeemphColorMap(const u8* src, const u8* srcbuf)
{
u8 pixel = *src;
@@ -492,7 +492,7 @@ template<int SCALE> static u32 _ModernDeemphColorMap(u8* src, u8* srcbuf)
return color;
}
u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int scale)
u32 ModernDeemphColorMap(const u8* src, const u8* srcbuf, int scale)
{
if(scale == 1) return _ModernDeemphColorMap<1>(src,srcbuf);
else if(scale == 2) return _ModernDeemphColorMap<2>(src,srcbuf);
@@ -503,14 +503,14 @@ u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int scale)
else if(scale == 7) return _ModernDeemphColorMap<7>(src,srcbuf);
else if(scale == 8) return _ModernDeemphColorMap<8>(src,srcbuf);
else if(scale == 9) return _ModernDeemphColorMap<9>(src,srcbuf);
else { abort(); return 0; }
else { FCEU_abort("unhandled ModernDeemphColorMap scale"); return 0; }
}
typedef u32 (*ModernDeemphColorMapFuncPtr)( u8*, u8* );
typedef u32 (*ModernDeemphColorMapFuncPtr)( const u8*, const u8* );
static ModernDeemphColorMapFuncPtr getModernDeemphColorMapFunc(int scale)
{
ModernDeemphColorMapFuncPtr ptr = NULL;
ModernDeemphColorMapFuncPtr ptr;
if(scale == 1) ptr = &_ModernDeemphColorMap<1>;
else if(scale == 2) ptr = &_ModernDeemphColorMap<2>;
@@ -521,7 +521,7 @@ static ModernDeemphColorMapFuncPtr getModernDeemphColorMapFunc(int scale)
else if(scale == 7) ptr = &_ModernDeemphColorMap<7>;
else if(scale == 8) ptr = &_ModernDeemphColorMap<8>;
else if(scale == 9) ptr = &_ModernDeemphColorMap<9>;
else { abort(); ptr = NULL; }
else { FCEU_abort("unhandled ModernDeemphColorMap scale"); ptr = nullptr; }
return ptr;
}
+1 -1
View File
@@ -29,4 +29,4 @@ void Blit32to16(uint32 *src, uint16 *dest, int xr, int yr, int dpitch,
int shiftr[3], int shiftl[3]);
u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int scale);
u32 ModernDeemphColorMap(const u8* src, const u8* srcbuf, int scale);
+9 -5
View File
@@ -23,21 +23,22 @@ THE SOFTWARE.
#include "emufile.h"
#include "utils/xstring.h"
#include <stdio.h>
#include <vector>
bool EMUFILE::readAllBytes(std::vector<u8>* dstbuf, const std::string& fname)
{
EMUFILE_FILE file(fname.c_str(),"rb");
if(file.fail()) return false;
int size = file.size();
size_t size = file.size();
dstbuf->resize(size);
file.fread(&dstbuf->at(0),size);
return true;
}
size_t EMUFILE_MEMORY::_fread(const void *ptr, size_t bytes){
u32 remain = len-pos;
u32 todo = std::min<u32>(remain,(u32)bytes);
size_t remain = len-pos;
size_t todo = std::min<size_t>(remain,bytes);
if(len==0)
{
failbit = true;
@@ -78,13 +79,16 @@ void EMUFILE_FILE::open(const char* fname, const char* mode)
}
void EMUFILE_FILE::truncate(s32 length)
void EMUFILE_FILE::truncate(size_t length)
{
::fflush(fp);
#ifdef _MSC_VER
_chsize(_fileno(fp),length);
#else
ftruncate(fileno(fp),length);
if ( ftruncate(fileno(fp),length) != 0 )
{
printf("Warning: EMUFILE_FILE::truncate failed\n");
}
#endif
// this is probably wrong if mode is "wb"
fclose(fp);
+31 -30
View File
@@ -59,7 +59,7 @@ public:
bool fail(bool unset=false) { bool ret = failbit; if(unset) unfail(); return ret; }
void unfail() { failbit=false; }
bool eof() { return size()==ftell(); }
bool eof() { return size() == static_cast<size_t>(ftell()); }
size_t fread(const void *ptr, size_t bytes){
return _fread(ptr,bytes);
@@ -109,13 +109,13 @@ public:
double readdouble();
size_t readdouble(double* val);
virtual int fseek(int offset, int origin) = 0;
virtual int fseek(long int offset, int origin) = 0;
virtual int ftell() = 0;
virtual int size() = 0;
virtual long int ftell() = 0;
virtual size_t size() = 0;
virtual void fflush() = 0;
virtual void truncate(s32 length) = 0;
virtual void truncate(size_t length) = 0;
};
//todo - handle read-only specially?
@@ -123,9 +123,10 @@ class EMUFILE_MEMORY : public EMUFILE {
protected:
std::vector<u8> *vec;
bool ownvec;
s32 pos, len;
long int pos;
size_t len;
void reserve(u32 amt) {
void reserve(size_t amt) {
if(vec->size() < amt)
vec->resize(amt);
}
@@ -133,12 +134,12 @@ protected:
public:
EMUFILE_MEMORY(std::vector<u8> *underlying) : vec(underlying), ownvec(false), pos(0), len((s32)underlying->size()) { }
EMUFILE_MEMORY(u32 preallocate) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) {
EMUFILE_MEMORY(size_t preallocate) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) {
vec->resize(preallocate);
len = preallocate;
}
EMUFILE_MEMORY() : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) { vec->reserve(1024); }
EMUFILE_MEMORY(void* buf, s32 size) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(size) {
EMUFILE_MEMORY(void* buf, size_t size) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(size) {
vec->resize(size);
if(size != 0)
memcpy(&vec->front(),buf,size);
@@ -150,11 +151,11 @@ public:
virtual EMUFILE* memwrap();
virtual void truncate(s32 length)
virtual void truncate(size_t length)
{
vec->resize(length);
len = length;
if(pos>length) pos=length;
if (static_cast<size_t>(pos) > length) pos=static_cast<long int>(length);
}
u8* buf() {
@@ -192,7 +193,7 @@ public:
//if(_fread(&temp,1) != 1)
// return EOF;
//else return temp;
u32 remain = len-pos;
size_t remain = len-pos;
if(remain<1) {
failbit = true;
return -1;
@@ -216,13 +217,13 @@ public:
//they handle the return values correctly
virtual void fwrite(const void *ptr, size_t bytes){
reserve(pos+(s32)bytes);
reserve(pos+bytes);
memcpy(buf()+pos,ptr,bytes);
pos += (s32)bytes;
len = std::max<int>(pos,len);
pos += static_cast<long>(bytes);
len = std::max<size_t>(pos,len);
}
virtual int fseek(int offset, int origin){
virtual int fseek(long int offset, int origin){
//work differently for read-only...?
switch(origin) {
case SEEK_SET:
@@ -232,7 +233,7 @@ public:
pos += offset;
break;
case SEEK_END:
pos = size()+offset;
pos = (long int)(size()+offset);
break;
default:
assert(false);
@@ -241,24 +242,24 @@ public:
return 0;
}
virtual int ftell() {
virtual long int ftell() {
return pos;
}
virtual void fflush() {}
void set_len(s32 length)
void set_len(size_t length)
{
len = length;
if(pos > length)
pos = length;
if (static_cast<size_t>(pos) > length)
pos = static_cast<long>(length);
}
void trim()
{
vec->resize(len);
}
virtual int size() { return (int)len; }
virtual size_t size() { return len; }
};
class EMUFILE_FILE : public EMUFILE {
@@ -288,7 +289,7 @@ public:
bool is_open() { return fp != NULL; }
virtual void truncate(s32 length);
virtual void truncate(size_t length);
virtual int fprintf(const char *format, ...) {
va_list argptr;
@@ -321,20 +322,20 @@ public:
failbit = true;
}
virtual int fseek(int offset, int origin) {
virtual int fseek(long int offset, int origin) {
return ::fseek(fp, offset, origin);
}
virtual int ftell() {
return (u32)::ftell(fp);
virtual long int ftell() {
return ::ftell(fp);
}
virtual int size() {
int oldpos = ftell();
virtual size_t size() {
long int oldpos = ftell();
fseek(0,SEEK_END);
int len = ftell();
long int len = ftell();
fseek(oldpos,SEEK_SET);
return len;
return static_cast<size_t>(len);
}
virtual void fflush() {
+33 -23
View File
@@ -181,7 +181,6 @@ static void FCEU_CloseGame(void)
}
#ifdef __WIN_DRIVER__
extern char LoadedRomFName[2048];
if (storePreferences(mass_replace(LoadedRomFName, "|", ".").c_str()))
FCEUD_PrintError("Couldn't store debugging data");
CDLoggerROMClosed();
@@ -226,10 +225,10 @@ static void FCEU_CloseGame(void)
currFrameCounter = 0;
//Reset flags for Undo/Redo/Auto Savestating //adelikat: TODO: maybe this stuff would be cleaner as a struct or class
lastSavestateMade[0] = 0;
lastSavestateMade.clear();
undoSS = false;
redoSS = false;
lastLoadstateMade[0] = 0;
lastLoadstateMade.clear();
undoLS = false;
redoLS = false;
AutoSS = false;
@@ -421,7 +420,7 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
//----------
//attempt to open the files
FCEUFILE *fp;
char fullname[2048]; // this name contains both archive name and ROM file name
std::string fullname; // this name contains both archive name and ROM file name
int lastpal = PAL;
int lastdendy = dendy;
@@ -431,7 +430,7 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
// currently there's only one situation:
// the user clicked cancel form the open from archive dialog
int userCancel = 0;
fp = FCEU_fopen(name, 0, "rb", 0, -1, romextensions, &userCancel);
fp = FCEU_fopen(name, LoadedRomFNamePatchToUse[0] ? LoadedRomFNamePatchToUse : nullptr, "rb", 0, -1, romextensions, &userCancel);
if (!fp)
{
@@ -443,16 +442,19 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
}
else if (fp->archiveFilename != "")
{
strcpy(fullname, fp->archiveFilename.c_str());
strcat(fullname, "|");
strcat(fullname, fp->filename.c_str());
} else
strcpy(fullname, name);
fullname.assign(fp->archiveFilename.c_str());
fullname.append("|");
fullname.append(fp->filename.c_str());
}
else
{
fullname.assign(name);
}
// reset loaded game BEFORE it's loading.
ResetGameLoaded();
//file opened ok. start loading.
FCEU_printf("Loading %s...\n\n", fullname);
FCEU_printf("Loading %s...\n\n", fullname.c_str());
GetFileBase(fp->filename.c_str());
//reset parameters so they're cleared just in case a format's loader doesn't know to do the clearing
MasterRomInfoParams = TMasterRomInfoParams();
@@ -484,16 +486,16 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
bool FCEUXLoad(const char *name, FCEUFILE * fp);
int load_result;
load_result = iNESLoad(fullname, fp, OverwriteVidMode);
load_result = iNESLoad(fullname.c_str(), fp, OverwriteVidMode);
if (load_result == LOADER_INVALID_FORMAT)
{
load_result = NSFLoad(fullname, fp);
load_result = NSFLoad(fullname.c_str(), fp);
if (load_result == LOADER_INVALID_FORMAT)
{
load_result = UNIFLoad(fullname, fp);
load_result = UNIFLoad(fullname.c_str(), fp);
if (load_result == LOADER_INVALID_FORMAT)
{
load_result = FDSLoad(fullname, fp);
load_result = FDSLoad(fullname.c_str(), fp);
}
}
}
@@ -502,7 +504,6 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
#ifdef __WIN_DRIVER__
// ################################## Start of SP CODE ###########################
extern char LoadedRomFName[2048];
extern int loadDebugDataFailed;
if ((loadDebugDataFailed = loadPreferences(mass_replace(LoadedRomFName, "|", ".").c_str())))
@@ -725,7 +726,8 @@ extern unsigned int frameAdvHoldTimer;
///Skip may be passed in, if FRAMESKIP is #defined, to cause this to emulate more than one frame
void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int skip) {
//skip initiates frame skip if 1, or frame skip and sound skip if 2
int r, ssize;
FCEU_MAYBE_UNUSED int r;
int ssize;
JustFrameAdvanced = false;
@@ -742,7 +744,7 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
{
EmulationPaused = EMULATIONPAUSED_FA;
}
if (frameAdvance_Delay_count < frameAdvanceDelayScaled)
if ( static_cast<unsigned int>(frameAdvance_Delay_count) < frameAdvanceDelayScaled)
{
frameAdvance_Delay_count++;
}
@@ -808,6 +810,9 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
if (skip != 2) ssize = FlushEmulateSound(); //If skip = 2 we are skipping sound processing
//flush tracer once a frame, since we're likely to end up back at a user interaction loop after this with emulation paused
FCEUD_FlushTrace();
#ifdef _S9XLUA_H
CallRegisteredLuaFunctions(LUACALL_AFTEREMULATION);
#endif
@@ -887,7 +892,8 @@ void ResetNES(void) {
extern uint8 *XBackBuf;
memset(XBackBuf, 0, 256 * 256);
FCEU_DispMessage("Reset", 0);
// OpenEmu
//FCEU_DispMessage("Reset", 0);
}
@@ -1061,7 +1067,7 @@ void FCEU_ResetVidSys(void) {
FCEUS FSettings;
void FCEU_printf(const char *format, ...)
void FCEU_printf( __FCEU_PRINTF_FORMAT const char *format, ...)
{
char temp[2048];
@@ -1081,7 +1087,7 @@ void FCEU_printf(const char *format, ...)
va_end(ap);
}
void FCEU_PrintError(const char *format, ...)
void FCEU_PrintError( __FCEU_PRINTF_FORMAT const char *format, ...)
{
char temp[2048];
@@ -1228,12 +1234,16 @@ void FCEUI_ClearEmulationFrameStepped()
//ideally maybe we shouldnt be using this, but i need it for quick merging
void FCEUI_SetEmulationPaused(int val) {
EmulationPaused = val;
if(EmulationPaused)
FCEUD_FlushTrace();
}
void FCEUI_ToggleEmulationPause(void)
{
EmulationPaused = (EmulationPaused & EMULATIONPAUSED_PAUSED) ^ EMULATIONPAUSED_PAUSED;
DebuggerWasUpdated = false;
if(EmulationPaused)
FCEUD_FlushTrace();
}
void FCEUI_FrameAdvanceEnd(void) {
@@ -1241,8 +1251,8 @@ void FCEUI_FrameAdvanceEnd(void) {
}
void FCEUI_FrameAdvance(void) {
frameAdvanceRequested = true;
frameAdvance_Delay_count = 0;
frameAdvanceRequested = true;
}
static int AutosaveCounter = 0;
@@ -1259,7 +1269,7 @@ void UpdateAutosave(void) {
FCEUSS_Save(f, false);
AutoSS = true; //Flag that an auto-savestate was made
free(f);
f = NULL;
f = NULL;
AutosaveStatus[AutosaveIndex] = 1;
}
}
+4 -4
View File
@@ -139,10 +139,10 @@ extern FCEUS FSettings;
bool CheckFileExists(const char* filename); //Receives a filename (fullpath) and checks to see if that file exists
void FCEU_PrintError(const char *format, ...);
void FCEU_printf(const char *format, ...);
void FCEU_DispMessage(const char *format, int disppos, ...);
void FCEU_DispMessageOnMovie(const char *format, ...);
void FCEU_PrintError( __FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 2 );
void FCEU_printf( __FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 2 );
void FCEU_DispMessage( __FCEU_PRINTF_FORMAT const char *format, int disppos, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 3 );
void FCEU_DispMessageOnMovie( __FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 2 );
void FCEU_TogglePPU();
void SetNESDeemph_OldHacky(uint8 d, int force);
+28 -10
View File
@@ -29,6 +29,7 @@
#include "state.h"
#include "file.h"
#include "cart.h"
#include "ines.h"
#include "netplay.h"
#include "driver.h"
#include "movie.h"
@@ -223,14 +224,23 @@ void FCEU_FDSSelect(void)
FCEU_DispMessage("Disk %d Side %c Selected", 0, SelectDisk >> 1, (SelectDisk & 1) ? 'B' : 'A');
}
#define IRQ_Repeat (IRQa & 0x01)
#define IRQ_Enabled (IRQa & 0x02)
#define IRQ_Repeat 0x01
#define IRQ_Enabled 0x02
static void FDSFix(int a) {
if ((IRQa & IRQ_Enabled) && IRQCount) {
if (IRQa & IRQ_Enabled) {
IRQCount -= a;
if (IRQCount <= 0) {
IRQCount = IRQLatch;
/* Puff Puff Golf notes:
Game freezes while music playing ingame after inserting Disk Side B.
IRQ is usually fired at scanline 169 and 183 for music to work.
At some point after inserting disk B, an IRQ is fired at scanline 174 which
will just freeze game while music plays.
If you ignore triggering IRQ altogether, game plays but no music
*/
X6502_IRQBegin(FCEU_IQEXT);
if (!(IRQa & IRQ_Repeat)) {
IRQa &= ~IRQ_Enabled;
@@ -574,21 +584,30 @@ void FDSSoundReset(void) {
static DECLFW(FDSWrite) {
switch (A) {
case 0x4020:
X6502_IRQEnd(FCEU_IQEXT);
IRQLatch &= 0xFF00;
IRQLatch |= V;
break;
case 0x4021:
X6502_IRQEnd(FCEU_IQEXT);
IRQLatch &= 0xFF;
IRQLatch |= V << 8;
break;
case 0x4022:
X6502_IRQEnd(FCEU_IQEXT);
IRQCount = IRQLatch;
IRQa = V & 3;
if (FDSRegs[3] & 1) {
IRQa = V & 0x03;
if (IRQa & IRQ_Enabled) {
IRQCount = IRQLatch;
} else {
X6502_IRQEnd(FCEU_IQEXT);
}
}
break;
case 0x4023:
if (!(V & 0x01)) {
IRQa &= ~IRQ_Enabled;
X6502_IRQEnd(FCEU_IQEXT);
X6502_IRQEnd(FCEU_IQEXT2);
}
break;
case 0x4023: break;
case 0x4024:
if (mapperFDS_diskinsert && ~mapperFDS_control & 0x04) {
@@ -834,7 +853,6 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
free(fn);
}
extern char LoadedRomFName[2048];
strcpy(LoadedRomFName, name); //For the debugger list
GameInfo->type = GIT_FDS;
+17 -26
View File
@@ -69,7 +69,7 @@ void ApplyIPS(FILE *ips, FCEUFILE* fp)
if(!ips) return;
char* buf = (char*)FCEU_dmalloc(fp->size);
char* buf = (char*)FCEU_malloc(fp->size);
memcpy(buf,fp->EnsureMemorystream()->buf(),fp->size);
@@ -108,13 +108,7 @@ void ApplyIPS(FILE *ips, FCEUFILE* fp)
if((offset+size)>(uint32)fp->size)
{
// Probably a little slow.
char *newbuf=(char *)realloc(buf,offset+size);
if(!newbuf)
{
free(buf); buf=NULL;
FCEU_printf(" Oops. IPS patch %d(type RLE) goes beyond end of file. Could not allocate memory.\n",count);
goto end;
}
char *newbuf=(char *)FCEU_realloc(buf,offset+size);
buf=newbuf;
memset(buf+fp->size,0,offset+size-fp->size);
fp->size=offset+size;
@@ -133,17 +127,15 @@ void ApplyIPS(FILE *ips, FCEUFILE* fp)
if((offset+size)>(uint32)fp->size)
{
// Probably a little slow.
char *newbuf=(char *)realloc(buf,offset+size);
if(!newbuf)
{
free(buf); buf=NULL;
FCEU_printf(" Oops. IPS patch %d(type normal) goes beyond end of file. Could not allocate memory.\n",count);
goto end;
}
char *newbuf=(char *)FCEU_realloc(buf,offset+size);
buf=newbuf;
memset(buf+fp->size,0,offset+size-fp->size);
fp->size=offset+size;
}
if ( fread(buf+offset,1,size,ips) != static_cast<size_t>(size) )
{
FCEU_printf(" Warn IPS data read came up short!\n");
}
fread(buf+offset,1,size,ips);
}
count++;
}
@@ -326,9 +318,9 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, const char *mode, cha
{
uint32 magic;
magic = fp->fgetc();
magic|=fp->fgetc()<<8;
magic|=fp->fgetc()<<16;
magic = (fp->fgetc() & 0x00ff);
magic|= (fp->fgetc() & 0x00ff) << 8;
magic|= (fp->fgetc() & 0x00ff) << 16;
fp->fseek(0,SEEK_SET);
if(magic==0x088b1f) {
@@ -338,7 +330,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, const char *mode, cha
if(gzfile) {
delete fp;
int size;
size_t size;
for(size=0; gzgetc(gzfile) != EOF; size++) {}
EMUFILE_MEMORY* ms = new EMUFILE_MEMORY(size);
gzseek(gzfile,0,SEEK_SET);
@@ -457,13 +449,12 @@ int FCEU_fisarchive(FCEUFILE *fp)
std::string GetMfn() //Retrieves the movie filename from curMovieFilename (for adding to savestate and auto-save files)
{
std::string movieFilenamePart;
extern char curMovieFilename[512];
if(*curMovieFilename)
{
if (!curMovieFilename.empty())
{
char drv[PATH_MAX], dir[PATH_MAX], name[PATH_MAX], ext[PATH_MAX];
splitpath(curMovieFilename,drv,dir,name,ext);
splitpath(curMovieFilename.c_str(),drv,dir,name,ext);
movieFilenamePart = std::string(".") + name;
}
}
return movieFilenamePart;
}
@@ -495,7 +486,7 @@ void FCEUI_SetDirOverride(int which, char *n)
va_list ap;
int ret;
if(!(*strp=(char*)FCEU_dmalloc(2048))) //mbg merge 7/17/06 cast to char*
if(!(*strp=(char*)FCEU_malloc(2048))) //mbg merge 7/17/06 cast to char*
return(0);
va_start(ap,fmt);
ret=vsnprintf(*strp,2048,fmt,ap);
+1 -1
View File
@@ -35,7 +35,7 @@ struct FCEUFILE {
int archiveIndex;
//the size of the file
int size;
size_t size;
//whether the file is contained in an archive
bool isArchive() { return archiveCount > 0; }
+28 -1
View File
@@ -16,12 +16,34 @@ enum EGIV
GIV_USER = 2, //What was set by FCEUI_SetVidSys().
};
enum EGIPPU
{
GIPPU_USER = 0,
GIPPU_RP2C04_0001 = 1,
GIPPU_RP2C04_0002 = 2,
GIPPU_RP2C04_0003 = 3,
GIPPU_RP2C04_0004 = 4,
GIPPU_RC2C03B = 5,
GIPPU_RC2C05_01 = 6,
GIPPU_RC2C05_02 = 7,
GIPPU_RC2C05_03 = 8,
GIPPU_RC2C05_04 = 9,
};
enum EGIVS
{
EGIVS_NORMAL = 0,
EGIVS_RBI = 1, // RBI Baseball protection
EGIVS_TKO = 2, // TKO Boxing protection
EGIVS_XEVIOUS = 3, // Super Xevious protection
};
enum ESIS
{
SIS_NONE = 0,
SIS_DATACH = 1,
SIS_NWC = 2,
SIS_VSUNISYSTEM = 3,
SIS_VSUNISYSTEM = 3, // Is it used?
SIS_NSF = 4,
};
@@ -44,6 +66,8 @@ enum ESI
SI_COUNT = SI_LCDCOMP_ZAPPER
};
inline const char* ESI_Name(ESI esi)
{
static const char * const names[] =
@@ -137,6 +161,9 @@ struct FCEUGI
ESI input[2]; //Desired input for emulated input ports 1 and 2; -1 for unknown desired input.
ESIFC inputfc; //Desired Famicom expansion port device. -1 for unknown desired input.
ESIS cspecial; //Special cart expansion: DIP switches, barcode reader, etc.
EGIPPU vs_ppu; //PPU type for Vs. System
EGIVS vs_type; //Vs. System type
uint8 vs_cswitch; // Switch first and second controllers for Vs. System
MD5DATA MD5;
+152 -41
View File
@@ -37,6 +37,7 @@
#include "cheat.h"
#include "vsuni.h"
#include "driver.h"
#include "input.h"
#include <cstdio>
#include <cstdlib>
@@ -54,9 +55,11 @@ iNES_HEADER head;
static CartInfo iNESCart;
uint8 Mirroring = 0;
uint8 MirroringAs2bits = 0;
uint32 ROM_size = 0;
uint32 VROM_size = 0;
char LoadedRomFName[2048]; //mbg merge 7/17/06 added
char LoadedRomFName[4096]; //mbg merge 7/17/06 added
char LoadedRomFNamePatchToUse[4096];
static int CHRRAMSize = -1;
static int iNES_Init(int num);
@@ -107,11 +110,11 @@ void iNESGI(GI h) { //bbit edited: removed static keyword
if (iNESCart.Close)
iNESCart.Close();
if (ROM) {
free(ROM);
FCEU_free(ROM);
ROM = NULL;
}
if (VROM) {
free(VROM);
FCEU_free(VROM);
VROM = NULL;
}
if (trainerpoo) {
@@ -141,6 +144,9 @@ struct INPSEL {
ESIFC inputfc;
};
/*
* Function to set input controllers based on CRC
*/
static void SetInput(void) {
static struct INPSEL moo[] =
{
@@ -153,9 +159,9 @@ static void SetInput(void) {
{0x48ca0ee1, SI_GAMEPAD, SI_GAMEPAD, SIFC_BWORLD }, // Barcode World
{0x4318a2f8, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Barker Bill's Trick Shooting
{0x6cca1c1f, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Dai Undoukai
{0x24598791, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Duck Hunt
{0x24598791, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // Duck Hunt
{0xd5d6eac4, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Edu (As)
{0xe9a7fe9e, SI_UNSET, SI_MOUSE, SIFC_NONE }, // Educational Computer 2000
{0xe9a7fe9e, SI_UNSET, SI_MOUSE, SIFC_SUBORKB }, // Educational Computer 2000
{0x8f7b1669, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // FP BASIC 3.3 by maxzhou88
{0xf7606810, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC 2.0A
{0x895037bc, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC 2.1a
@@ -215,6 +221,7 @@ static void SetInput(void) {
{0x67b126b9, SI_GAMEPAD, SI_GAMEPAD, SIFC_FAMINETSYS }, // Famicom Network System
{0x00000000, SI_UNSET, SI_UNSET, SIFC_UNSET }
};
int x = 0;
while (moo[x].input1 >= 0 || moo[x].input2 >= 0 || moo[x].inputfc >= 0) {
@@ -228,6 +235,64 @@ static void SetInput(void) {
}
}
struct INPSEL_NES20 {
uint8 expansion_id;
ESI input1;
ESI input2;
ESIFC inputfc;
};
/*
* Function to set input controllers based on NES 2.0 header
*/
extern int eoptions;
static void SetInputNes20(uint8 expansion) {
static struct INPSEL_NES20 moo[] =
{
{0x01, SI_GAMEPAD, SI_GAMEPAD, SIFC_UNSET }, // Standard NES/Famicom controllers
{0x02, SI_GAMEPAD, SI_GAMEPAD, SIFC_NONE }, // NES Four Score/Satellite with two additional standard controllers
{0x03, SI_GAMEPAD, SI_GAMEPAD, SIFC_4PLAYER }, // Famicom Four Players Adapter with two additional standard controllers using the "simple" protocol
{0x04, SI_GAMEPAD, SI_GAMEPAD, SIFC_NONE }, // Vs. System (1P via $4016)
{0x05, SI_GAMEPAD, SI_GAMEPAD, SIFC_NONE }, // Vs. System (1P via $4017)
{0x07, SI_ZAPPER, SI_NONE, SIFC_NONE }, // Vs. Zapper
{0x08, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Zapper ($4017)
{0x0A, SI_UNSET, SI_UNSET, SIFC_SHADOW }, // Bandai Hyper Shot Lightgun
{0x0B, SI_UNSET, SI_POWERPADA, SIFC_UNSET }, // Power Pad Side A
{0x0C, SI_UNSET, SI_POWERPADB, SIFC_UNSET }, // Power Pad Side B
{0x0D, SI_UNSET, SI_UNSET, SIFC_FTRAINERA }, // Family Trainer Side A
{0x0E, SI_UNSET, SI_UNSET, SIFC_FTRAINERB }, // Family Trainer Side B
{0x0F, SI_UNSET, SI_ARKANOID, SIFC_UNSET }, // Arkanoid Vaus Controller (NES)
{0x10, SI_UNSET, SI_UNSET, SIFC_ARKANOID }, // Arkanoid Vaus Controller (Famicom)
{0x12, SI_UNSET, SI_UNSET, SIFC_HYPERSHOT }, // Konami Hyper Shot Controller
{0x15, SI_UNSET, SI_UNSET, SIFC_MAHJONG }, // Jissen Mahjong Controller
{0x17, SI_UNSET, SI_UNSET, SIFC_OEKAKIDS }, // Oeka Kids Tablet
{0x18, SI_UNSET, SI_UNSET, SIFC_BWORLD }, // Sunsoft Barcode Battler
{0x1B, SI_UNSET, SI_UNSET, SIFC_TOPRIDER }, // Top Rider (Inflatable Bicycle)
{0x23, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC Keyboard plus Famicom Data Recorder
{0x24, SI_UNSET, SI_UNSET, SIFC_PEC586KB }, // Dongda PEC-586 Keyboard
{0x26, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Subor Keyboard
//{0x27, SI_UNSET, SI_MOUSE, SIFC_SUBORKB }, // Subor Keyboard plus mouse (3x8-bit protocol)
{0x28, SI_UNSET, SI_MOUSE, SIFC_SUBORKB }, // Subor Keyboard plus mouse (24-bit protocol)
{0x29, SI_UNSET, SI_SNES_MOUSE, SIFC_UNSET }, // SNES Mouse
{0, SI_UNSET, SI_UNSET, SIFC_UNSET }
};
int x = 0;
if (expansion == 0x02)
eoptions |= 32768; // dirty hack to enable Four-Score
GameInfo->vs_cswitch = expansion == 0x05;
while (moo[x].expansion_id) {
if (moo[x].expansion_id == expansion) {
GameInfo->input[0] = moo[x].input1;
GameInfo->input[1] = moo[x].input2;
GameInfo->inputfc = moo[x].inputfc;
break; }
x++;
}
}
#define INESB_INCOMPLETE 1
#define INESB_CORRUPT 2
#define INESB_HACKED 4
@@ -276,7 +341,7 @@ static const TMasterRomInfo sMasterRomInfo[] = {
const TMasterRomInfo* MasterRomInfo;
TMasterRomInfoParams MasterRomInfoParams;
static void CheckHInfo(void) {
static void CheckHInfo(uint64 partialmd5) {
/* ROM images that have the battery-backed bit set in the header that really
don't have battery-backed RAM is not that big of a problem, so I'll
treat this differently by only listing games that should have battery-backed RAM.
@@ -327,14 +392,9 @@ static void CheckHInfo(void) {
#include "ines-correct.h"
};
int32 tofix = 0, x, mask;
uint64 partialmd5 = 0;
for (x = 0; x < 8; x++)
partialmd5 |= (uint64)iNESCart.MD5[15 - x] << (x * 8);
CheckBad(partialmd5);
MasterRomInfo = NULL;
for (int i = 0; i < ARRAY_SIZE(sMasterRomInfo); i++) {
for (size_t i = 0; i < ARRAY_SIZE(sMasterRomInfo); i++) {
const TMasterRomInfo& info = sMasterRomInfo[i];
if (info.md5lower != partialmd5)
continue;
@@ -343,7 +403,7 @@ static void CheckHInfo(void) {
if (!info.params) break;
std::vector<std::string> toks = tokenize_str(info.params, ",");
for (int j = 0; j < (int)toks.size(); j++) {
for (size_t j = 0; j < toks.size(); j++) {
std::vector<std::string> parts = tokenize_str(toks[j], "=");
MasterRomInfoParams[parts[0]] = parts[1];
}
@@ -673,7 +733,7 @@ BMAPPINGLocal bmap[] = {
{"", 215, UNL8237_Init},
{"", 216, Mapper216_Init},
{"", 217, Mapper217_Init}, // Redefined to a new Discrete BMC mapper
// {"", 218, Mapper218_Init},
{"", 218, Mapper218_Init},
{"UNLA9746", 219, UNLA9746_Init},
{"Debug Mapper", 220, QTAi_Init},
{"UNLN625092", 221, UNLN625092_Init},
@@ -710,7 +770,7 @@ BMAPPINGLocal bmap[] = {
{"SAN GUO ZHI PIRATE", 252, Mapper252_Init},
{"DRAGON BALL PIRATE", 253, Mapper253_Init},
{"", 254, Mapper254_Init},
// {"", 255, Mapper255_Init}, // No good dumps for this mapper
{"", 255, Mapper255_Init}, // dupe of 225
//-------- Mappers 256-511 is the Supplementary Multilingual Plane ----------
//-------- Mappers 512-767 is the Supplementary Ideographic Plane -----------
@@ -727,9 +787,12 @@ BMAPPINGLocal bmap[] = {
{"F-15 MMC3 Based", 259, BMCF15_Init},
{"HP10xx/H20xx Boards", 260, BMCHPxx_Init},
{"810544-CA-1", 261, BMC810544CA1_Init},
{"SMD132/SMD133", 268, SMD132_SMD133_Init},
{"AA6023/AA6023B", 268, AA6023_Init},
{"COOLGIRL", 342, COOLGIRL_Init },
{"FAM250/81-01-39-C/SCHI-24", 354, Mapper354_Init },
{"Impact Soft MMC3 Flash Board", 406, Mapper406_Init },
{"INX_007T_V01", 470, INX_007T_Init },
{"KONAMI QTAi Board", 547, QTAi_Init },
@@ -737,7 +800,10 @@ BMAPPINGLocal bmap[] = {
};
int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
int result;
struct md5_context md5;
uint64 partialmd5 = 0;
const char* mappername = "Not Listed";
if (FCEU_fread(&head, 1, 16, fp) != 16 || memcmp(&head, "NES\x1A", 4))
return LOADER_INVALID_FORMAT;
@@ -766,6 +832,9 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
} else
Mirroring = (head.ROM_type & 1);
MirroringAs2bits = head.ROM_type & 1;
if (head.ROM_type & 8) MirroringAs2bits |= 2;
int not_round_size;
if (!iNES2) {
not_round_size = head.ROM_size;
@@ -809,20 +878,64 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
}
}
if ((ROM = (uint8*)FCEU_malloc(ROM_size << 14)) == NULL)
return 0;
ROM = (uint8*)FCEU_malloc(ROM_size << 14);
memset(ROM, 0xFF, ROM_size << 14);
if (VROM_size) {
if ((VROM = (uint8*)FCEU_malloc(VROM_size << 13)) == NULL) {
free(ROM);
ROM = NULL;
FCEU_PrintError("Unable to allocate memory.");
return LOADER_HANDLED_ERROR;
}
VROM = (uint8*)FCEU_malloc(VROM_size << 13);
memset(VROM, 0xFF, VROM_size << 13);
}
// Set Vs. System flag if need
if (!iNES2) {
GameInfo->type = !(head.ROM_type2 & 1) ? GIT_CART : GIT_VSUNI;
}
else {
switch (!(head.ROM_type2 & 2) ? (head.ROM_type2 & 3) : (head.VS_hardware & 0xF)) {
case 0:
GameInfo->type = GIT_CART;
break;
case 1:
GameInfo->type = GIT_VSUNI;
break;
default:
FCEU_PrintError("Game type is not supported at all.");
goto init_error;
}
}
// Set Vs. System PPU type if need
if (GameInfo->type == GIT_VSUNI && !(head.ROM_type2 & 2)) {
switch (head.VS_hardware & 0xF) {
case 0x0: GameInfo->vs_ppu = GIPPU_RC2C03B; break;
//case 0x1: GameInfo->vs_ppu = GIPPU_RPC2C03C; break;
case 0x2: GameInfo->vs_ppu = GIPPU_RP2C04_0001; break;
case 0x3: GameInfo->vs_ppu = GIPPU_RP2C04_0002; break;
case 0x4: GameInfo->vs_ppu = GIPPU_RP2C04_0003; break;
case 0x5: GameInfo->vs_ppu = GIPPU_RP2C04_0004; break;
case 0x6: GameInfo->vs_ppu = GIPPU_RC2C03B; break;
//case 0x7: GameInfo->ppu = GIPPU_RPC2C03C; break;
case 0x8: GameInfo->vs_ppu = GIPPU_RC2C05_01; break;
case 0x9: GameInfo->vs_ppu = GIPPU_RC2C05_02; break;
case 0xA: GameInfo->vs_ppu = GIPPU_RC2C05_03; break;
case 0xB: GameInfo->vs_ppu = GIPPU_RC2C05_04; break;
//case 0xC: GameInfo->ppu = GIPPU_RPC2C05_05; break;
default:
FCEU_PrintError("Vs. System PPU type is not supported at all.");
goto init_error;
}
switch (head.VS_hardware >> 4) {
case 0x0: GameInfo->vs_type = EGIVS_NORMAL; break;
case 0x1: GameInfo->vs_type = EGIVS_RBI; break;
case 0x2: GameInfo->vs_type = EGIVS_TKO; break;
case 0x3: GameInfo->vs_type = EGIVS_XEVIOUS; break;
default:
FCEU_PrintError("Vs. System type is not supported at all.");
goto init_error;
}
}
if (head.ROM_type & 4) { /* Trainer */
trainerpoo = (uint8*)FCEU_gmalloc(512);
FCEU_fread(trainerpoo, 512, 1, fp);
@@ -838,7 +951,7 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
if (VROM_size)
FCEU_fread(VROM, 0x2000, VROM_size, fp);
md5_starts(&md5);
md5_starts(&md5);
md5_update(&md5, ROM, ROM_size << 14);
iNESGameCRC32 = CalcCRC32(0, ROM, ROM_size << 14);
@@ -849,12 +962,14 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
}
md5_finish(&md5, iNESCart.MD5);
memcpy(&GameInfo->MD5, &iNESCart.MD5, sizeof(iNESCart.MD5));
for (int x = 0; x < 8; x++)
partialmd5 |= (uint64)iNESCart.MD5[7 - x] << (x * 8);
iNESCart.CRC32 = iNESGameCRC32;
FCEU_printf(" PRG ROM: %d x 16KiB = %d KiB\n", round ? ROM_size : not_round_size, (round ? ROM_size : not_round_size) * 16);
FCEU_printf(" CHR ROM: %d x 8KiB = %d KiB\n", VROM_size, VROM_size * 8);
FCEU_printf(" ROM CRC32: 0x%08lx\n", iNESGameCRC32);
FCEU_printf(" ROM CRC32: 0x%08x\n", iNESGameCRC32);
{
int x;
FCEU_printf(" ROM MD5: 0x");
@@ -863,9 +978,7 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
FCEU_printf("\n");
}
const char* mappername = "Not Listed";
for (int mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) {
for (size_t mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) {
if (bmap[mappertest].number == MapperNo) {
mappername = bmap[mappertest].name;
break;
@@ -891,17 +1004,12 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
}
SetInput();
CheckHInfo();
{
int x;
uint64 partialmd5 = 0;
// Input can be overriden by NES 2.0 header
if (iNES2) SetInputNes20(head.expansion);
CheckHInfo(partialmd5);
FCEU_VSUniCheck(partialmd5, &MapperNo, &Mirroring);
CheckBad(partialmd5);
for (x = 0; x < 8; x++) {
partialmd5 |= (uint64)iNESCart.MD5[7 - x] << (x * 8);
}
FCEU_VSUniCheck(partialmd5, &MapperNo, &Mirroring);
}
/* Must remain here because above functions might change value of
VROM_size and free(VROM).
*/
@@ -918,8 +1026,9 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
iNESCart.battery = (head.ROM_type & 2) ? 1 : 0;
iNESCart.mirror = Mirroring;
iNESCart.mirrorAs2Bits = MirroringAs2bits;
int result = iNES_Init(MapperNo);
result = iNES_Init(MapperNo);
switch(result)
{
case 0:
@@ -931,6 +1040,8 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
FCEU_PrintError("Unable to allocate CHR-RAM.");
break;
}
init_error:
if (ROM) free(ROM);
if (VROM) free(VROM);
if (trainerpoo) free(trainerpoo);
@@ -995,7 +1106,7 @@ int iNesSaveAs(const char* name)
//caitsith2: done. iNesSave() now gets filename and calls iNesSaveAs with that filename.
FILE *fp;
if (GameInfo->type != GIT_CART) return 0;
if ((GameInfo->type != GIT_CART) && (GameInfo->type != GIT_VSUNI)) return 0;
if (GameInterface != iNESGI) return 0;
fp = fopen(name, "wb");
+23 -13
View File
@@ -25,6 +25,8 @@
#include <string.h>
#include <map>
#include "cart.h"
struct TMasterRomInfo
{
uint64 md5lower;
@@ -43,27 +45,30 @@ extern uint8 *VROM;
extern uint32 VROM_size;
extern uint32 ROM_size;
extern uint8 *ExtraNTARAM;
extern uint8 **VPageR;
extern int iNesSave(void); //bbit Edited: line added
extern int iNesSaveAs(const char* name);
extern char LoadedRomFName[2048]; //bbit Edited: line added
extern char LoadedRomFName[4096]; //bbit Edited: line added
extern char LoadedRomFNamePatchToUse[4096];
extern char *iNesShortFName(void);
extern const TMasterRomInfo* MasterRomInfo;
extern TMasterRomInfoParams MasterRomInfoParams;
//mbg merge 7/19/06 changed to c++ decl format
struct iNES_HEADER {
char ID[4]; /*NES^Z*/ // 0-3
uint8 ROM_size; // 4
uint8 VROM_size; // 5
uint8 ROM_type; // 6
uint8 ROM_type2; // 7
uint8 ROM_type3; // 8
uint8 Upper_ROM_VROM_size; // 9
uint8 RAM_size; // 10
uint8 VRAM_size; // 11
uint8 TV_system; // 12
uint8 VS_hardware; // 13
uint8 reserved[2]; // 14, 15
char ID[4]; /*NES^Z*/ // 0-3
uint8 ROM_size; // 4
uint8 VROM_size; // 5
uint8 ROM_type; // 6
uint8 ROM_type2; // 7
uint8 ROM_type3; // 8
uint8 Upper_ROM_VROM_size; // 9
uint8 RAM_size; // 10
uint8 VRAM_size; // 11
uint8 TV_system; // 12
uint8 VS_hardware; // 13
uint8 misc_roms; // 14
uint8 expansion; // 15
void cleanup()
{
@@ -242,6 +247,7 @@ void Mapper213_Init(CartInfo *);
void Mapper214_Init(CartInfo *);
void Mapper216_Init(CartInfo *);
void Mapper217_Init(CartInfo *);
void Mapper218_Init(CartInfo *);
void Mapper220_Init(CartInfo *);
void Mapper222_Init(CartInfo *);
void Mapper225_Init(CartInfo *);
@@ -268,8 +274,12 @@ void Mapper250_Init(CartInfo *);
void Mapper252_Init(CartInfo *);
void Mapper253_Init(CartInfo *);
void Mapper254_Init(CartInfo *);
void Mapper255_Init(CartInfo *);
void Mapper354_Init(CartInfo *);
void Mapper406_Init(CartInfo *);
void INX_007T_Init(CartInfo* info);
typedef struct {
const char *name;
int32 number;
+60 -22
View File
@@ -106,6 +106,8 @@ uint8 FCEU_GetJoyJoy(void)
}
extern uint8 coinon;
extern uint8 coinon2;
extern uint8 service;
//set to true if the fourscore is attached
static bool FSAttached = false;
@@ -431,8 +433,11 @@ void FCEU_UpdateInput(void)
portFC.driver->Update(portFC.ptr,portFC.attrib);
}
if(GameInfo->type==GIT_VSUNI)
if(coinon) coinon--;
if (GameInfo->type == GIT_VSUNI) {
if (coinon) coinon--;
if (coinon2) coinon2--;
if (service) service--;
}
if(FCEUnetplay)
NetplayUpdate(joy);
@@ -454,7 +459,11 @@ static DECLFR(VSUNIRead0)
ret|=(vsdip&3)<<3;
if(coinon)
ret|=0x4;
ret |= 0x20;
if (coinon2)
ret |= 0x40;
if (service)
ret |= 0x04;
return ret;
}
@@ -668,7 +677,9 @@ void FCEU_DoSimpleCommand(int cmd)
{
case FCEUNPCMD_FDSINSERT: FCEU_FDSInsert();break;
case FCEUNPCMD_FDSSELECT: FCEU_FDSSelect();break;
case FCEUNPCMD_VSUNICOIN: FCEU_VSUniCoin(); break;
case FCEUNPCMD_VSUNICOIN: FCEU_VSUniCoin(0); break;
case FCEUNPCMD_VSUNICOIN2: FCEU_VSUniCoin(1); break;
case FCEUNPCMD_VSUNISERVICE: FCEU_VSUniService(); break;
case FCEUNPCMD_VSUNIDIP0:
case FCEUNPCMD_VSUNIDIP0+1:
case FCEUNPCMD_VSUNIDIP0+2:
@@ -726,6 +737,22 @@ void FCEUI_VSUniCoin(void)
FCEU_QSimpleCommand(FCEUNPCMD_VSUNICOIN);
}
void FCEUI_VSUniCoin2(void)
{
if (!FCEU_IsValidUI(FCEUI_INSERT_COIN))
return;
FCEU_QSimpleCommand(FCEUNPCMD_VSUNICOIN2);
}
void FCEUI_VSUniService(void)
{
if (!FCEU_IsValidUI(FCEUI_INSERT_COIN))
return;
FCEU_QSimpleCommand(FCEUNPCMD_VSUNISERVICE);
}
//Resets the frame counter if movie inactive and rom is reset or power-cycle
void ResetFrameCounter()
{
@@ -798,6 +825,7 @@ static void RamSearchOpLTE(void);
static void RamSearchOpGTE(void);
static void RamSearchOpEQ(void);
static void RamSearchOpNE(void);
static void ToggleCheats(void);
static void DebuggerStepInto(void);
static void FA_SkipLag(void);
static void OpenRom(void);
@@ -900,17 +928,17 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
{ EMUCMD_FDS_EJECT_INSERT, EMUCMDTYPE_FDS, FCEUI_FDSInsert, 0, 0, "Eject or Insert FDS Disk", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_FDS_SIDE_SELECT, EMUCMDTYPE_FDS, FCEUI_FDSSelect, 0, 0, "Switch FDS Disk Side", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_VSUNI_COIN, EMUCMDTYPE_VSUNI, FCEUI_VSUniCoin, 0, 0, "Insert Coin", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_VSUNI_TOGGLE_DIP_0, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 0", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_1, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 1", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_2, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 2", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_3, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 3", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_4, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 4", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_5, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 5", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_6, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 6", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_7, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 7", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_8, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 8", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_9, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 9", 0 },
{ EMUCMD_VSUNI_COIN, EMUCMDTYPE_VSUNI, FCEUI_VSUniCoin, 0, 0, "Insert Coin #1", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_VSUNI_COIN_2, EMUCMDTYPE_VSUNI, FCEUI_VSUniCoin2, 0, 0, "Insert Coin #2", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_VSUNI_SERVICE_BUTTON, EMUCMDTYPE_VSUNI, FCEUI_VSUniService, 0, 0, "Service Button", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_VSUNI_TOGGLE_DIP_0, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 0", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_1, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 1", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_2, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 2", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_3, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 3", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_4, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 4", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_5, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 5", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_6, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 6", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_7, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 7", 0 },
{ EMUCMD_MISC_AUTOSAVE, EMUCMDTYPE_MISC, FCEUI_RewindToLastAutosave, 0, 0, "Load Last Auto-save", 0},
{ EMUCMD_MISC_SHOWSTATES, EMUCMDTYPE_MISC, ViewSlots, 0, 0, "View save slots", 0 },
@@ -945,6 +973,7 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
{ EMUCMD_TOOL_RAMSEARCHGTE, EMUCMDTYPE_TOOL, RamSearchOpGTE, 0, 0, "Ram Search - Greater Than or Equal", 0},
{ EMUCMD_TOOL_RAMSEARCHEQ, EMUCMDTYPE_TOOL, RamSearchOpEQ, 0, 0, "Ram Search - Equal", 0},
{ EMUCMD_TOOL_RAMSEARCHNE, EMUCMDTYPE_TOOL, RamSearchOpNE, 0, 0, "Ram Search - Not Equal", 0},
{ EMUCMD_TOOL_TOGGLECHEATS, EMUCMDTYPE_TOOL, ToggleCheats, 0, 0, "Toggle Cheats", 0},
{ EMUCMD_RERECORD_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_MovieToggleRerecordDisplay,0, 0, "Toggle Rerecord Display", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TASEDITOR_REWIND, EMUCMDTYPE_TASEDITOR, TaseditorRewindOn, TaseditorRewindOff, 0, "Frame Rewind", EMUCMDFLAG_TASEDITOR },
@@ -960,12 +989,12 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
#define NUM_EMU_CMDS (sizeof(FCEUI_CommandTable)/sizeof(FCEUI_CommandTable[0]))
static int execcmd, i;
static int execcmd;
void FCEUI_HandleEmuCommands(TestCommandState* testfn)
{
bool taseditor = FCEUMOV_Mode(MOVIEMODE_TASEDITOR);
for(i=0; i<NUM_EMU_CMDS; ++i)
for(size_t i=0; i<NUM_EMU_CMDS; ++i)
{
int new_state;
int old_state = FCEUI_CommandTable[i].state;
@@ -1268,6 +1297,18 @@ static void RamSearchOpNE(void) {
#endif
}
extern int globalCheatDisabled;
extern unsigned int FrozenAddressCount;
static void ToggleCheats()
{
FCEUI_GlobalToggleCheat(globalCheatDisabled);
FCEU_DispMessage("%d cheats active", 0, FrozenAddressCount);
#ifdef __WIN_DRIVER__
UpdateCheatRelatedWindow();
UpdateCheatListGroupBoxUI();
#endif
}
static void DebuggerStepInto()
{
#ifdef __WIN_DRIVER__
@@ -1324,10 +1365,7 @@ static void MovieSubtitleToggle(void)
static void UndoRedoSavestate(void)
{
// FIXME this will always evaluate to true, should this be
// if (*lastSavestateMade...) to check if it holds a string or just
// a '\0'?
if (lastSavestateMade && (undoSS || redoSS))
if ( !lastSavestateMade.empty() && (undoSS || redoSS))
SwapSaveState();
}
@@ -1380,7 +1418,7 @@ static void TaseditorCommand(void)
**/
EMUCMDTABLE* GetEmuCommandById(int cmd)
{
for (i = 0; i<NUM_EMU_CMDS; ++i)
for (size_t i = 0; i<NUM_EMU_CMDS; ++i)
{
if (FCEUI_CommandTable[i].cmd == cmd)
return &FCEUI_CommandTable[i];
+4 -2
View File
@@ -197,8 +197,8 @@ enum EMUCMD
EMUCMD_VSUNI_TOGGLE_DIP_5,
EMUCMD_VSUNI_TOGGLE_DIP_6,
EMUCMD_VSUNI_TOGGLE_DIP_7,
EMUCMD_VSUNI_TOGGLE_DIP_8,
EMUCMD_VSUNI_TOGGLE_DIP_9,
EMUCMD_VSUNI_COIN_2,
EMUCMD_VSUNI_SERVICE_BUTTON,
EMUCMD_MISC_AUTOSAVE,
EMUCMD_MISC_SHOWSTATES,
EMUCMD_MISC_USE_INPUT_PRESET_1,
@@ -259,6 +259,8 @@ enum EMUCMD
EMUCMD_MOVIE_RECORD_MODE_OVERWRITE,
EMUCMD_MOVIE_RECORD_MODE_INSERT,
EMUCMD_TOOL_TOGGLECHEATS,
EMUCMD_MAX
};
+189 -31
View File
@@ -24,6 +24,7 @@
#include "file.h"
#include "video.h"
#include "debug.h"
#include "debugsymboltable.h"
#include "sound.h"
#include "drawing.h"
#include "state.h"
@@ -54,6 +55,9 @@ extern TASEDITOR_LUA taseditor_lua;
#ifdef __SDL__
#ifdef __QT_DRIVER__
#include "drivers/Qt/sdl.h"
#include "drivers/Qt/main.h"
#include "drivers/Qt/input.h"
#include "drivers/Qt/fceuWrapper.h"
#include "drivers/Qt/TasEditor/selection.h"
#include "drivers/Qt/TasEditor/laglog.h"
@@ -182,10 +186,13 @@ struct LuaSaveState {
persisted = true;
FILE* inf = fopen(filename.c_str(),"rb");
fseek(inf,0,SEEK_END);
int len = ftell(inf);
long int len = ftell(inf);
fseek(inf,0,SEEK_SET);
data = new EMUFILE_MEMORY(len);
fread(data->buf(),1,len,inf);
if ( fread(data->buf(),1,len,inf) != static_cast<size_t>(len) )
{
FCEU_printf("Warning: LuaSaveState::ensureLoad failed to load full buffer.\n");
}
fclose(inf);
}
};
@@ -250,7 +257,7 @@ static const char *guiCallbackTable = "FCEU.GUI";
static int frameAdvanceWaiting = FALSE;
// We save our pause status in the case of a natural death.
static int wasPaused = FALSE;
//static int wasPaused = FALSE;
// Transparency strength. 255=opaque, 0=so transparent it's invisible
static int transparencyModifier = 255;
@@ -656,12 +663,11 @@ static int emu_loadrom(lua_State *L)
return 0;
#elif defined(__QT_DRIVER__)
const char *nameo2 = luaL_checkstring(L,1);
char nameo[2048];
std::string nameo;
strncpy(nameo, nameo2, sizeof(nameo));
nameo[sizeof(nameo)-1] = 0;
nameo.assign( nameo2 );
LoadGameFromLua( nameo );
LoadGameFromLua( nameo.c_str() );
//lua_cpcall(L, emu_wait_for_rom_load, NULL);
//printf("Attempting to Load ROM: '%s'\n", nameo );
@@ -743,7 +749,7 @@ static int emu_addgamegenie(lua_State *L) {
while (FCEUI_GetCheat(i,NULL,&Caddr,&Cval,&Ccompare,NULL,&Ctype)) {
if ((GGaddr == Caddr) && (GGval == Cval) && (GGcomp == Ccompare) && (Ctype == 1)) {
if ((static_cast<uint32>(GGaddr) == Caddr) && (GGval == static_cast<int>(Cval)) && (GGcomp == Ccompare) && (Ctype == 1)) {
// Already Added, so consider it a success
lua_pushboolean(L, true);
return 1;
@@ -773,7 +779,7 @@ static int emu_delgamegenie(lua_State *L) {
int GGaddr, GGcomp, GGval;
uint32 i=0;
char * Cname;
std::string Cname;
uint32 Caddr;
uint8 Cval;
int Ccompare, Ctype;
@@ -786,7 +792,7 @@ static int emu_delgamegenie(lua_State *L) {
while (FCEUI_GetCheat(i,&Cname,&Caddr,&Cval,&Ccompare,NULL,&Ctype)) {
if ((!strcmp(msg,Cname)) && (GGaddr == Caddr) && (GGval == Cval) && (GGcomp == Ccompare) && (Ctype == 1)) {
if ((Cname == msg) && (static_cast<uint32>(GGaddr) == Caddr) && (GGval == static_cast<int>(Cval)) && (GGcomp == Ccompare) && (Ctype == 1)) {
// Delete cheat code
if (FCEUI_DelCheat(i)) {
lua_pushboolean(L, true);
@@ -1302,7 +1308,10 @@ void freadint(unsigned int& value, FILE* file)
for(int i=0;i<4;i++)
{
int r = 0;
fread(&r, 1, 1, file);
if ( fread(&r, 1, 1, file) == 0)
{
break;
}
rv |= r << (i*8);
}
value = rv;
@@ -1346,7 +1355,10 @@ void LuaSaveData::ImportRecords(void* fileV)
break;
cur->data = new unsigned char [cur->size];
fread(cur->data, cur->size, 1, file);
if ( fread(cur->data, cur->size, 1, file) == 0 )
{
memset( cur->data, 0, cur->size );
}
Record* next = new Record();
memcpy(next, cur, sizeof(Record));
@@ -1632,7 +1644,7 @@ static void toCStringConverter(lua_State* L, int i, char*& ptr, int& remaining)
if(remaining <= 0)
return;
const char* str = ptr; // for debugging
//const char* str = ptr; // for debugging
// if there is a __tostring metamethod then call it
int usedMeta = luaL_callmeta(L, i, "__tostring");
@@ -1994,7 +2006,7 @@ static int memory_getregister(lua_State *L)
{
const char* qualifiedRegisterName = luaL_checkstring(L,1);
lua_settop(L,0);
for(int cpu = 0; cpu < sizeof(cpuToRegisterMaps)/sizeof(*cpuToRegisterMaps); cpu++)
for(size_t cpu = 0; cpu < sizeof(cpuToRegisterMaps)/sizeof(*cpuToRegisterMaps); cpu++)
{
cpuToRegisterMap ctrm = cpuToRegisterMaps[cpu];
int cpuNameLen = strlen(ctrm.cpuName);
@@ -2028,7 +2040,7 @@ static int memory_setregister(lua_State *L)
const char* qualifiedRegisterName = luaL_checkstring(L,1);
unsigned long value = (unsigned long)(luaL_checkinteger(L,2));
lua_settop(L,0);
for(int cpu = 0; cpu < sizeof(cpuToRegisterMaps)/sizeof(*cpuToRegisterMaps); cpu++)
for(size_t cpu = 0; cpu < sizeof(cpuToRegisterMaps)/sizeof(*cpuToRegisterMaps); cpu++)
{
cpuToRegisterMap ctrm = cpuToRegisterMaps[cpu];
int cpuNameLen = strlen(ctrm.cpuName);
@@ -2244,7 +2256,7 @@ static void CallRegisteredLuaMemHook_LuaMatch(unsigned int address, int size, un
#endif
lua_settop(L, 0);
lua_getfield(L, LUA_REGISTRYINDEX, luaMemHookTypeStrings[hookType]);
for(int i = address; i != address+size; i++)
for(unsigned int i = address; i != address+size; i++)
{
lua_rawgeti(L, -1, i);
if (lua_isfunction(L, -1))
@@ -2448,6 +2460,7 @@ LuaMemHookType MatchHookTypeToCPU(lua_State* L, LuaMemHookType hookType)
case LUAMEMHOOK_WRITE: return LUAMEMHOOK_WRITE_SUB;
case LUAMEMHOOK_READ: return LUAMEMHOOK_READ_SUB;
case LUAMEMHOOK_EXEC: return LUAMEMHOOK_EXEC_SUB;
default: return hookType;
}
}
return hookType;
@@ -2457,6 +2470,7 @@ static int memory_registerwrite(lua_State *L)
{
return memory_registerHook(L, MatchHookTypeToCPU(L,LUAMEMHOOK_WRITE), 1);
}
FCEU_MAYBE_UNUSED
static int memory_registerread(lua_State *L)
{
return memory_registerHook(L, MatchHookTypeToCPU(L,LUAMEMHOOK_READ), 1);
@@ -2638,6 +2652,112 @@ static int input_get(lua_State *L) {
}
}
}
#elif defined(__QT_DRIVER__)
// Qt/SDL
{
const uint8_t *keyBuf = QtSDL_getKeyboardState(nullptr);
if (keyBuf)
{
char keyName[64];
const char *keyOut = nullptr;
for (int i=0; i<SDL_NUM_SCANCODES; i++)
{
if (keyBuf[i])
{
SDL_Keycode k = SDL_GetKeyFromScancode( static_cast<SDL_Scancode>(i) );
const char* name = SDL_GetKeyName(k);
//printf("Key:%i '%s'\n", i, name);
if ( isalpha(name[0]) || isdigit(name[0]) )
{ // If name starts with letters or number, copy name without spaces
int ii=0, jj=0;
while (name[ii] != 0)
{
if ( isalpha(name[ii]) || isdigit(name[ii]) || (name[ii] == '_') )
{
keyName[jj] = name[ii]; jj++;
}
ii++;
}
keyName[jj] = 0;
keyOut = keyName;
}
else
{ // Handle special char names
switch (name[0])
{
case '[':
keyOut = "LeftBracket";
break;
case ']':
keyOut = "RightBracket";
break;
case '{':
keyOut = "LeftBrace";
break;
case '}':
keyOut = "RightBrace";
break;
case ',':
keyOut = "Comma";
break;
case '.':
keyOut = "Period";
break;
case '~':
keyOut = "Tilde";
break;
case '`':
keyOut = "Backtick";
break;
case '|':
keyOut = "VerticalBar";
break;
case '/':
keyOut = "Slash";
break;
case '\\':
keyOut = "BackSlash";
break;
case '+':
keyOut = "Plus";
break;
case '=':
keyOut = "Equals";
break;
case '_':
keyOut = "Underscore";
break;
case '-':
keyOut = "Minus";
break;
case ';':
keyOut = "SemiColon";
break;
case ':':
keyOut = "Colon";
break;
case '\'':
case '\"':
keyOut = "Quote";
break;
default:
keyOut = name;
break;
}
}
lua_pushboolean(L, true);
lua_setfield(L, -2, keyOut);
}
}
}
}
#else
//SDL TODO: implement this for keyboard!!
#endif
@@ -3117,11 +3237,10 @@ static int savestate_loadscriptdata(lua_State *L) {
{
LuaSaveData saveData;
char luaSaveFilename [512];
strncpy(luaSaveFilename, filename, 512);
luaSaveFilename[512-(1+7/*strlen(".luasav")*/)] = '\0';
strcat(luaSaveFilename, ".luasav");
FILE* luaSaveFile = fopen(luaSaveFilename, "rb");
std::string luaSaveFilename;
luaSaveFilename.assign( filename );
luaSaveFilename.append( ".luasav");
FILE* luaSaveFile = fopen(luaSaveFilename.c_str(), "rb");
if(luaSaveFile)
{
saveData.ImportRecords(luaSaveFile);
@@ -3743,7 +3862,7 @@ static inline bool str2colour(uint32 *colour, lua_State *L, const char *str) {
*colour = ((rand()*255/RAND_MAX) << 8) | ((rand()*255/RAND_MAX) << 16) | ((rand()*255/RAND_MAX) << 24) | 0xFF;
return true;
}
for(int i = 0; i < sizeof(s_colorMapping)/sizeof(*s_colorMapping); i++) {
for(size_t i = 0; i < sizeof(s_colorMapping)/sizeof(*s_colorMapping); i++) {
if(!stricmp(str,s_colorMapping[i].name)) {
*colour = s_colorMapping[i].value;
return true;
@@ -3779,7 +3898,6 @@ static inline uint32 gui_getcolour_wrapped(lua_State *L, int offset, bool hasDef
lua_pushnil(L); // first key
int keyIndex = lua_gettop(L);
int valueIndex = keyIndex + 1;
bool first = true;
while(lua_next(L, offset))
{
bool keyIsString = (lua_type(L, keyIndex) == LUA_TSTRING);
@@ -3985,6 +4103,7 @@ static int gui_box(lua_State *L) {
}
// (old) gui.box(x1, y1, x2, y2, color)
FCEU_MAYBE_UNUSED
static int gui_box_old(lua_State *L) {
int x1,y1,x2,y2;
@@ -4314,6 +4433,7 @@ draw_outline:
}
}
FCEU_MAYBE_UNUSED
static int strlinelen(const char* string)
{
const char* s = string;
@@ -4324,6 +4444,7 @@ static int strlinelen(const char* string)
return s - string;
}
FCEU_MAYBE_UNUSED
static void LuaDisplayString (const char *string, int y, int x, uint32 color, uint32 outlineColor)
{
if(!string)
@@ -4491,7 +4612,7 @@ void LuaDrawTextTransWH(const char *str, size_t l, int &x, int y, uint32 color,
return;
size_t len = l;
int defaultAlpha = std::max<int>(0, std::min<int>(transparencyModifier, 255));
//int defaultAlpha = std::max<int>(0, std::min<int>(transparencyModifier, 255));
int diffx;
int diffy = std::max<int>(0, std::min<int>(7, LUA_SCREEN_HEIGHT - y));
@@ -4560,7 +4681,7 @@ void LuaDrawTextTransWH(const char *str, size_t l, int &x, int y, uint32 color,
// main HUD.
static int gui_text(lua_State *L) {
extern int font_height;
//extern int font_height;
const char *msg;
int x, y;
size_t l;
@@ -4957,6 +5078,27 @@ static int debugger_resetinstructionscount(lua_State *L)
return 0;
}
// debugger.getsymboloffset()
static int debugger_getsymboloffset(lua_State *L)
{
debugSymbol_t *sym = NULL;
const char *name = luaL_checkstring(L, 1);
if (lua_type(L, 2) == LUA_TNUMBER)
{
int bank = luaL_checkinteger(L, 2);
sym = debugSymbolTable.getSymbol(bank, name);
}
else
{
sym = debugSymbolTable.getSymbolAtAnyBank(name);
}
lua_pushinteger(L, sym ? sym->offset() : -1);
return 1;
}
// TAS Editor functions library
// bool taseditor.registerauto()
@@ -4978,7 +5120,7 @@ static int taseditor_registermanual(lua_State *L)
if (!lua_isnil(L,1))
luaL_checktype(L, 1, LUA_TFUNCTION);
const char* caption = NULL;
FCEU_MAYBE_UNUSED const char* caption = NULL;
if (!lua_isnil(L, 2))
caption = lua_tostring(L, 2);
@@ -5364,10 +5506,10 @@ static int doPopup(lua_State *L, const char* deftype, const char* deficon) {
assert(iicon >= 0 && iicon <= 3);
if(!(iicon >= 0 && iicon <= 3)) iicon = 0;
#ifdef __WIN_DRIVER__
static const char * const titles [] = {"Notice", "Question", "Warning", "Error"};
const char* answer = "ok";
#ifdef __WIN_DRIVER__
static const int etypes [] = {MB_OK, MB_YESNO, MB_YESNOCANCEL, MB_OKCANCEL, MB_ABORTRETRYIGNORE};
static const int eicons [] = {MB_ICONINFORMATION, MB_ICONQUESTION, MB_ICONWARNING, MB_ICONERROR};
//StopSound(); //mbg merge 7/27/08
@@ -5512,13 +5654,20 @@ use_console:
// We don't want parameters
if (!t[0]) {
fprintf(stderr, "[Press Enter]");
fgets(buffer, sizeof(buffer), stdin);
if ( fgets(buffer, sizeof(buffer), stdin) == nullptr )
{
FCEU_printf("Error: fgets from stdin failed\n");
}
// We're done
return 0;
}
fprintf(stderr, "(%s): ", t);
fgets(buffer, sizeof(buffer), stdin);
if ( fgets(buffer, sizeof(buffer), stdin) == nullptr )
{
FCEU_printf("Error: fgets from stdin failed\n");
buffer[0] = 0;
}
// Check if the option is in the list
if (strchr(t, tolower(buffer[0]))) {
@@ -5571,7 +5720,11 @@ static int doOpenFilePopup(lua_State *L, bool saveFile) {
// TODO: more sophisticated interface
char filename[PATH_MAX];
printf("Enter %s filename: ", saveFile ? "save" : "open");
fgets(filename, PATH_MAX, stdin);
if ( fgets(filename, PATH_MAX, stdin) == nullptr )
{
FCEU_printf("Warning: fgets from stdin failed\n");
filename[0] = 0;
}
lua_newtable(L);
lua_pushstring(L, filename);
lua_rawseti(L, -2, 1);
@@ -5802,6 +5955,7 @@ static int bitbit(lua_State *L)
}
// The function called periodically to ensure Lua doesn't run amok.
FCEU_MAYBE_UNUSED
static void FCEU_LuaHookFunction(lua_State *L, lua_Debug *dbg) {
if (numTries-- == 0) {
@@ -6127,6 +6281,7 @@ static const struct luaL_reg debuggerlib[] = {
{"getinstructionscount", debugger_getinstructionscount},
{"resetcyclescount", debugger_resetcyclescount},
{"resetinstructionscount", debugger_resetinstructionscount},
{"getsymboloffset", debugger_getsymboloffset},
{NULL,NULL}
};
@@ -6288,7 +6443,10 @@ int FCEU_LoadLuaCode(const char *filename, const char *arg)
getfilepath = getfilepath.substr(0,getfilepath.find_last_of("/\\") + 1);
SetCurrentDir(getfilepath.c_str());
if ( SetCurrentDir(getfilepath.c_str()) != 0 )
{
FCEU_printf("Warning: Failed chdir failed to set current dir to: %s\n", getfilepath.c_str() );
}
//stop any lua we might already have had running
FCEU_LuaStop();
+36 -22
View File
@@ -114,7 +114,7 @@ SFORMAT FCEUMOV_STATEINFO[]={
{ 0 }
};
char curMovieFilename[512] = {0};
std::string curMovieFilename;
MovieData currMovieData;
MovieData defaultMovieData;
int currRerecordCount; // Keep the global value
@@ -409,6 +409,7 @@ MovieData::MovieData()
, rerecordCount(0)
, binaryFlag(false)
, loadFrameCount(-1)
, fourscore(false)
, microphone(false)
, RAMInitOption(0)
, RAMInitSeed(0)
@@ -692,7 +693,7 @@ bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader)
{
LoadFM2_binarychunk(movieData, fp, size);
return true;
} else if (isnewline && movieData.loadFrameCount == movieData.records.size())
} else if (isnewline && static_cast<size_t>(movieData.loadFrameCount) == movieData.records.size())
// exit prematurely if loaded the specified amound of records
return true;
switch(state)
@@ -806,7 +807,10 @@ static EMUFILE *openRecordingMovie(const char* fname)
FCEU_PrintError("Error opening movie output file: %s", fname);
return NULL;
}
strcpy(curMovieFilename, fname);
if ( fname != curMovieFilename.c_str() )
{
curMovieFilename.assign(fname);
}
return osRecordingMovie;
}
@@ -826,7 +830,7 @@ static void RedumpWholeMovieFile(bool justToggledRecording = false)
bool recording = (movieMode == MOVIEMODE_RECORD);
assert((NULL != osRecordingMovie) == (recording != justToggledRecording) && "osRecordingMovie should be consistent with movie mode!");
if (NULL == openRecordingMovie(curMovieFilename))
if (NULL == openRecordingMovie(curMovieFilename.c_str()))
return;
currMovieData.dump(osRecordingMovie, false/*currMovieData.binaryFlag*/, recording);
@@ -874,7 +878,7 @@ static void OnMovieClosed()
{
assert(movieMode == MOVIEMODE_INACTIVE);
curMovieFilename[0] = 0; //No longer a current movie filename
curMovieFilename.clear(); //No longer a current movie filename
freshMovie = false; //No longer a fresh movie loaded
if (bindSavestate) AutoSS = false; //If bind movies to savestates is true, then there is no longer a valid auto-save to load
@@ -990,7 +994,7 @@ bool MovieData::loadSaveramFrom(std::vector<uint8>* buf)
return false;
}
if(currCartInfo->SaveGameLen[i] != len)
if(currCartInfo->SaveGameLen[i] != static_cast<unsigned int>(len))
{
FCEU_PrintError("movie battery load mismatch 3");
return false;
@@ -1039,7 +1043,7 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
currMovieData = MovieData();
strcpy(curMovieFilename, fname);
curMovieFilename.assign(fname);
FCEUFILE *fp = FCEU_fopen(fname,0,"rb",0);
if (!fp) return false;
if(fp->isArchive() && !_read_only) {
@@ -1220,7 +1224,11 @@ void FCEUMOV_AddInputState()
if (mr->command_fds_select())
FCEU_FDSSelect();
if (mr->command_vs_insertcoin())
FCEU_VSUniCoin();
FCEU_VSUniCoin(0);
if (mr->command_vs_insertcoin2())
FCEU_VSUniCoin(1);
if (mr->command_vs_service())
FCEU_VSUniService();
_currCommand = 0;
} else
#endif
@@ -1248,14 +1256,18 @@ void FCEUMOV_AddInputState()
if(mr->command_fds_select())
FCEU_FDSSelect();
if (mr->command_vs_insertcoin())
FCEU_VSUniCoin();
FCEU_VSUniCoin(0);
if (mr->command_vs_insertcoin2())
FCEU_VSUniCoin(1);
if (mr->command_vs_service())
FCEU_VSUniService();
joyports[0].load(mr);
joyports[1].load(mr);
}
//if we are on the last frame, then pause the emulator if the player requested it
if (currFrameCounter == currMovieData.records.size()-1)
if ( static_cast<size_t>(currFrameCounter) == currMovieData.records.size()-1)
{
if(FCEUD_PauseAfterPlayback())
{
@@ -1326,6 +1338,8 @@ void FCEUMOV_AddCommand(int cmd)
case FCEUNPCMD_FDSINSERT: cmd = MOVIECMD_FDS_INSERT; break;
case FCEUNPCMD_FDSSELECT: cmd = MOVIECMD_FDS_SELECT; break;
case FCEUNPCMD_VSUNICOIN: cmd = MOVIECMD_VS_INSERTCOIN; break;
case FCEUNPCMD_VSUNICOIN2: cmd = MOVIECMD_VS_INSERTCOIN2; break;
case FCEUNPCMD_VSUNISERVICE: cmd = MOVIECMD_VS_SERVICE; break;
// all other netplay commands (e.g. FCEUNPCMD_VSUNIDIP0) are not supported by movie recorder for now
default: return;
}
@@ -1434,7 +1448,7 @@ bool FCEUMOV_ReadState(EMUFILE* is, uint32 size)
#endif
movie_readonly = true;
}
if (FCEU_isFileInArchive(curMovieFilename))
if (FCEU_isFileInArchive(curMovieFilename.c_str()))
{
//a little rule: cant load states in read+write mode with a movie from an archive.
//so we are going to switch it to readonly mode in that case
@@ -1569,10 +1583,10 @@ bool FCEUMOV_ReadState(EMUFILE* is, uint32 size)
//TODO: turn frame counter to red to get attention
if (!backupSavestates) //If backups are disabled we can just resume normally since we can't restore so stop movie and inform user
{
FCEU_PrintError("Error: Savestate taken from a frame (%d) after the final frame in the savestated movie (%d) cannot be verified against current movie (%d). This is not permitted.\nUnable to restore backup, movie playback stopped.", currFrameCounter, tempMovieData.records.size() - 1, currMovieData.records.size() - 1);
FCEU_PrintError("Error: Savestate taken from a frame (%d) after the final frame in the savestated movie (%zi) cannot be verified against current movie (%zi). This is not permitted.\nUnable to restore backup, movie playback stopped.", currFrameCounter, tempMovieData.records.size() - 1, currMovieData.records.size() - 1);
FCEUI_StopMovie();
} else
FCEU_PrintError("Savestate taken from a frame (%d) after the final frame in the savestated movie (%d) cannot be verified against current movie (%d). This is not permitted.", currFrameCounter, tempMovieData.records.size() - 1, currMovieData.records.size() - 1);
FCEU_PrintError("Savestate taken from a frame (%d) after the final frame in the savestated movie (%zi) cannot be verified against current movie (%zi). This is not permitted.", currFrameCounter, tempMovieData.records.size() - 1, currMovieData.records.size() - 1);
return false;
}
}
@@ -1728,7 +1742,7 @@ void FCEUI_MovieToggleReadOnly()
strcpy(message, "Movie is now Read+Write");
strcat(message, GetMovieModeStr());
FCEU_DispMessage(message,0);
FCEU_DispMessage("%s",0,message);
}
void FCEUI_MovieToggleRecording()
@@ -1772,7 +1786,7 @@ void FCEUI_MovieToggleRecording()
strcat(message, GetMovieModeStr());
FCEU_DispMessage(message, 0);
FCEU_DispMessage("%s",0,message);
}
void FCEUI_MovieInsertFrame()
@@ -1799,7 +1813,7 @@ void FCEUI_MovieInsertFrame()
strcat(message, GetMovieModeStr());
}
FCEU_DispMessage(message, 0);
FCEU_DispMessage("%s",0,message);
}
void FCEUI_MovieDeleteFrame()
@@ -1837,7 +1851,7 @@ void FCEUI_MovieDeleteFrame()
strcat(message, GetMovieModeStr());
}
FCEU_DispMessage(message, 0);
FCEU_DispMessage("%s",0,message);
}
void FCEUI_MovieTruncate()
@@ -1875,7 +1889,7 @@ void FCEUI_MovieTruncate()
strcat(message, GetMovieModeStr());
}
FCEU_DispMessage(message, 0);
FCEU_DispMessage("%s",0,message);
}
void FCEUI_MovieNextRecordMode()
@@ -1945,7 +1959,7 @@ void FCEUI_MoviePlayFromBeginning(void)
#endif
}
string FCEUI_GetMovieName(void)
std::string FCEUI_GetMovieName(void)
{
return curMovieFilename;
}
@@ -2039,9 +2053,9 @@ void FCEUI_CreateMovieFile(std::string fn)
void FCEUI_MakeBackupMovie(bool dispMessage)
{
//This function generates backup movie files
string currentFn; //Current movie fillename
string backupFn; //Target backup filename
string tempFn; //temp used in back filename creation
std::string currentFn; //Current movie fillename
std::string backupFn; //Target backup filename
std::string tempFn; //temp used in back filename creation
stringstream stream;
int x; //Temp variable for string manip
bool exist = false; //Used to test if filename exists
+7 -3
View File
@@ -81,7 +81,9 @@ enum EMOVIECMD
MOVIECMD_POWER = 2,
MOVIECMD_FDS_INSERT = 4,
MOVIECMD_FDS_SELECT = 8,
MOVIECMD_VS_INSERTCOIN = 16
MOVIECMD_VS_INSERTCOIN = 16,
MOVIECMD_VS_INSERTCOIN2 = 32,
MOVIECMD_VS_SERVICE = 64
};
EMOVIEMODE FCEUMOV_Mode();
@@ -131,6 +133,8 @@ public:
bool command_fds_insert() { return (commands & MOVIECMD_FDS_INSERT) != 0; }
bool command_fds_select() { return (commands & MOVIECMD_FDS_SELECT) != 0; }
bool command_vs_insertcoin() { return (commands & MOVIECMD_VS_INSERTCOIN) != 0; }
bool command_vs_insertcoin2() { return (commands & MOVIECMD_VS_INSERTCOIN2) != 0; }
bool command_vs_service() { return (commands & MOVIECMD_VS_SERVICE) != 0; }
void toggleBit(int joy, int bit)
{
@@ -210,7 +214,7 @@ public:
//whether microphone is enabled
bool microphone;
int getNumRecords() { return (int)records.size(); }
int getNumRecords() { return static_cast<int>( records.size() ); }
int RAMInitOption, RAMInitSeed;
@@ -272,7 +276,7 @@ private:
extern EMOVIEMODE movieMode;
extern MovieData currMovieData;
extern int currFrameCounter;
extern char curMovieFilename[512];
extern std::string curMovieFilename;
extern bool subtitlesOnAVI;
extern bool freshMovie;
extern bool movie_readonly;
+4 -1
View File
@@ -122,7 +122,10 @@ int FCEUNET_SendFile(uint8 cmd, char *fn)
FCEUX_fstat(fileno(fp),&sb);
len = sb.st_size;
buf = (char*)FCEU_dmalloc(len); //mbg merge 7/17/06 added cast
fread(buf, 1, len, fp);
if ( fread(buf, 1, len, fp) != static_cast<size_t>(len) )
{
FCEU_printf("Warning: FCEUNET_SendFile failed to load complete file.\n");
}
fclose(fp);
cbuf = (char*)FCEU_dmalloc(4 + len + len / 1000 + 12); //mbg merge 7/17/06 added cast
+4 -1
View File
@@ -7,7 +7,10 @@ extern int FCEUnetplay;
#define FCEUNPCMD_POWER 0x02
#define FCEUNPCMD_VSUNICOIN 0x07
#define FCEUNPCMD_VSUNIDIP0 0x08
#define FCEUNPCMD_VSUNIDIP0 0x08
#define FCEUNPCMD_VSUNICOIN2 0x20
#define FCEUNPCMD_VSUNISERVICE 0x21
#define FCEUNPCMD_FDSINSERTx 0x10
#define FCEUNPCMD_FDSINSERT 0x18
//#define FCEUNPCMD_FDSEJECT 0x19
+1 -2
View File
@@ -32,6 +32,7 @@
#include "file.h"
#include "fds.h"
#include "cart.h"
#include "ines.h"
#include "input.h"
#include "state.h"
#include "driver.h"
@@ -123,8 +124,6 @@ static uint16 PlayAddr; //configuration
static uint16 InitAddr; //configuration
static uint16 LoadAddr; //configuration
extern char LoadedRomFName[2048];
NSF_HEADER NSFHeader; //mbg merge 6/29/06 - needs to be global
void NSFMMC5_Close(void);
+19 -4
View File
@@ -48,7 +48,7 @@ static uint8 joop[4];
static uint8 joopcmd;
static uint32 framets = 0;
static uint32 frameptr = 0;
static uint8* moviedata = NULL;
static uint8* moviedata = nullptr;
static uint32 moviedatasize = 0;
static uint32 firstframeoffset = 0;
static uint32 savestate_offset = 0;
@@ -626,7 +626,19 @@ EFCM_CONVERTRESULT convert_fcm(MovieData& md, std::string fname)
//ResetInputTypes();
fp->fseek(firstframeoffset,SEEK_SET);
moviedata = (uint8*)realloc(moviedata, moviedatasize);
uint8 *newMovieData = (uint8*)realloc(moviedata, moviedatasize);
if (newMovieData)
{
moviedata = newMovieData;
}
else
{
if (moviedata)
{
free(moviedata); moviedata = nullptr;
}
return FCM_CONVERTRESULT_REALLOC_FAIL;
}
fp->fread((char*)moviedata,moviedatasize);
frameptr = 0;
@@ -669,8 +681,11 @@ EFCM_CONVERTRESULT convert_fcm(MovieData& md, std::string fname)
md.ports[0] = md.ports[1] = SI_GAMEPAD;
}
free(moviedata);
moviedata = 0;
if (moviedata)
{
free(moviedata);
moviedata = nullptr;
}
delete fp;
return FCM_CONVERTRESULT_SUCCESS;
+1
View File
@@ -10,6 +10,7 @@ enum EFCM_CONVERTRESULT
FCM_CONVERTRESULT_OLDVERSION,
FCM_CONVERTRESULT_UNSUPPORTEDVERSION,
FCM_CONVERTRESULT_STARTFROMSAVESTATENOTSUPPORTED,
FCM_CONVERTRESULT_REALLOC_FAIL,
};
inline const char * EFCM_CONVERTRESULT_message(EFCM_CONVERTRESULT e)
+2
View File
@@ -87,6 +87,7 @@ pal *palo = NULL;
(type) (y + to_rgb [4] * i + to_rgb [5] * q)\
)
FCEU_MAYBE_UNUSED
static void ApplyDeemphasisNTSC(int entry, u8& r, u8& g, u8& b)
{
static float const to_float = 1.0f / 0xFF;
@@ -252,6 +253,7 @@ static void ApplyDeemphasisBisqwit(int entry, u8& r, u8& g, u8& b)
}
//classic algorithm
FCEU_MAYBE_UNUSED
static void ApplyDeemphasisClassic(int entry, u8& r, u8& g, u8& b)
{
//DEEMPH BITS MAY BE ORDERED WRONG. PLEASE CHECK
+76 -68
View File
@@ -4,6 +4,9 @@
#define EMPTY_PALETTE_64 EMPTY_PALETTE_16 EMPTY_PALETTE_16 EMPTY_PALETTE_16 EMPTY_PALETTE_16
#define EMPTY_PALETTE_DEEMPH_X_7 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64
//this assumes the color is already shifted <<2, as it is in these cases
#define P64RPC(x) ( ((x)&~3) | (((x)>>6)&3))
pal rp2c04001[512] = {
#include "rp2c04001.h"
EMPTY_PALETTE_DEEMPH_X_7
@@ -23,12 +26,14 @@ pal rp2c05004[512] = {
EMPTY_PALETTE_DEEMPH_X_7
};
#undef P64RPC
// Fixed palette entries used by the GUI
pal palette_unvarying[] = {
{ 0x00<<2,0x00<<2,0x00<<2}, // 0 = Black
{ 0x3F<<2,0x3F<<2,0x34<<2}, // 1 = White
{ 0x00<<2,0x00<<2,0x00<<2}, // 2 = Black
{ 0x1d<<2,0x1d<<2,0x24<<2}, // 3 = Greyish
{ 0x00,0x00,0x00}, // 0 = Black
{ 0xFF,0xFF,0xD3}, // 1 = White
{ 0x00,0x00,0x00}, // 2 = Black
{ 0x75,0x75,0x92}, // 3 = Greyish
{ 190, 0, 0}, // 4 = Reddish
{ 51,255, 51}, // 5 = Bright green
{ 49, 14,200}, // 6 = Ultramarine Blue
@@ -52,73 +57,76 @@ pal palette_unvarying[] = {
};
#define P64(x) (((x)<<2)|((x>>4)&3))
// Default palette
pal palette[512] = {
{ P64(0x1D), P64(0x1D), P64(0x1D)}, /* Value 0 */
{ P64(0x09), P64(0x06), P64(0x23)}, /* Value 1 */
{ P64(0x00), P64(0x00), P64(0x2A)}, /* Value 2 */
{ P64(0x11), P64(0x00), P64(0x27)}, /* Value 3 */
{ P64(0x23), P64(0x00), P64(0x1D)}, /* Value 4 */
{ P64(0x2A), P64(0x00), P64(0x04)}, /* Value 5 */
{ P64(0x29), P64(0x00), P64(0x00)}, /* Value 6 */
{ P64(0x1F), P64(0x02), P64(0x00)}, /* Value 7 */
{ P64(0x10), P64(0x0B), P64(0x00)}, /* Value 8 */
{ P64(0x00), P64(0x11), P64(0x00)}, /* Value 9 */
{ P64(0x00), P64(0x14), P64(0x00)}, /* Value 10 */
{ P64(0x00), P64(0x0F), P64(0x05)}, /* Value 11 */
{ P64(0x06), P64(0x0F), P64(0x17)}, /* Value 12 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 13 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 14 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 15 */
{ P64(0x2F), P64(0x2F), P64(0x2F)}, /* Value 16 */
{ P64(0x00), P64(0x1C), P64(0x3B)}, /* Value 17 */
{ P64(0x08), P64(0x0E), P64(0x3B)}, /* Value 18 */
{ P64(0x20), P64(0x00), P64(0x3C)}, /* Value 19 */
{ P64(0x2F), P64(0x00), P64(0x2F)}, /* Value 20 */
{ P64(0x39), P64(0x00), P64(0x16)}, /* Value 21 */
{ P64(0x36), P64(0x0A), P64(0x00)}, /* Value 22 */
{ P64(0x32), P64(0x13), P64(0x03)}, /* Value 23 */
{ P64(0x22), P64(0x1C), P64(0x00)}, /* Value 24 */
{ P64(0x00), P64(0x25), P64(0x00)}, /* Value 25 */
{ P64(0x00), P64(0x2A), P64(0x00)}, /* Value 26 */
{ P64(0x00), P64(0x24), P64(0x0E)}, /* Value 27 */
{ P64(0x00), P64(0x20), P64(0x22)}, /* Value 28 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 29 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 30 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 31 */
{ P64(0x3F), P64(0x3F), P64(0x3F)}, /* Value 32 */
{ P64(0x0F), P64(0x2F), P64(0x3F)}, /* Value 33 */
{ P64(0x17), P64(0x25), P64(0x3F)}, /* Value 34 */
{ P64(0x33), P64(0x22), P64(0x3F)}, /* Value 35 */
{ P64(0x3D), P64(0x1E), P64(0x3F)}, /* Value 36 */
{ P64(0x3F), P64(0x1D), P64(0x2D)}, /* Value 37 */
{ P64(0x3F), P64(0x1D), P64(0x18)}, /* Value 38 */
{ P64(0x3F), P64(0x26), P64(0x0E)}, /* Value 39 */
{ P64(0x3C), P64(0x2F), P64(0x0F)}, /* Value 40 */
{ P64(0x20), P64(0x34), P64(0x04)}, /* Value 41 */
{ P64(0x13), P64(0x37), P64(0x12)}, /* Value 42 */
{ P64(0x16), P64(0x3E), P64(0x26)}, /* Value 43 */
{ P64(0x00), P64(0x3A), P64(0x36)}, /* Value 44 */
{ P64(0x1E), P64(0x1E), P64(0x1E)}, /* Value 45 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 46 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 47 */
{ P64(0x3F), P64(0x3F), P64(0x3F)}, /* Value 48 */
{ P64(0x2A), P64(0x39), P64(0x3F)}, /* Value 49 */
{ P64(0x31), P64(0x35), P64(0x3F)}, /* Value 50 */
{ P64(0x35), P64(0x32), P64(0x3F)}, /* Value 51 */
{ P64(0x3F), P64(0x31), P64(0x3F)}, /* Value 52 */
{ P64(0x3F), P64(0x31), P64(0x36)}, /* Value 53 */
{ P64(0x3F), P64(0x2F), P64(0x2C)}, /* Value 54 */
{ P64(0x3F), P64(0x36), P64(0x2A)}, /* Value 55 */
{ P64(0x3F), P64(0x39), P64(0x28)}, /* Value 56 */
{ P64(0x38), P64(0x3F), P64(0x28)}, /* Value 57 */
{ P64(0x2A), P64(0x3C), P64(0x2F)}, /* Value 58 */
{ P64(0x2C), P64(0x3F), P64(0x33)}, /* Value 59 */
{ P64(0x27), P64(0x3F), P64(0x3C)}, /* Value 60 */
{ P64(0x31), P64(0x31), P64(0x31)}, /* Value 61 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 62 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 63 */
{ 0x1D<<2, 0x1D<<2, 0x1D<<2 }, /* Value 0 */
{ 0x09<<2, 0x06<<2, 0x23<<2 }, /* Value 1 */
{ 0x00<<2, 0x00<<2, 0x2A<<2 }, /* Value 2 */
{ 0x11<<2, 0x00<<2, 0x27<<2 }, /* Value 3 */
{ 0x23<<2, 0x00<<2, 0x1D<<2 }, /* Value 4 */
{ 0x2A<<2, 0x00<<2, 0x04<<2 }, /* Value 5 */
{ 0x29<<2, 0x00<<2, 0x00<<2 }, /* Value 6 */
{ 0x1F<<2, 0x02<<2, 0x00<<2 }, /* Value 7 */
{ 0x10<<2, 0x0B<<2, 0x00<<2 }, /* Value 8 */
{ 0x00<<2, 0x11<<2, 0x00<<2 }, /* Value 9 */
{ 0x00<<2, 0x14<<2, 0x00<<2 }, /* Value 10 */
{ 0x00<<2, 0x0F<<2, 0x05<<2 }, /* Value 11 */
{ 0x06<<2, 0x0F<<2, 0x17<<2 }, /* Value 12 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 13 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 14 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 15 */
{ 0x2F<<2, 0x2F<<2, 0x2F<<2 }, /* Value 16 */
{ 0x00<<2, 0x1C<<2, 0x3B<<2 }, /* Value 17 */
{ 0x08<<2, 0x0E<<2, 0x3B<<2 }, /* Value 18 */
{ 0x20<<2, 0x00<<2, 0x3C<<2 }, /* Value 19 */
{ 0x2F<<2, 0x00<<2, 0x2F<<2 }, /* Value 20 */
{ 0x39<<2, 0x00<<2, 0x16<<2 }, /* Value 21 */
{ 0x36<<2, 0x0A<<2, 0x00<<2 }, /* Value 22 */
{ 0x32<<2, 0x13<<2, 0x03<<2 }, /* Value 23 */
{ 0x22<<2, 0x1C<<2, 0x00<<2 }, /* Value 24 */
{ 0x00<<2, 0x25<<2, 0x00<<2 }, /* Value 25 */
{ 0x00<<2, 0x2A<<2, 0x00<<2 }, /* Value 26 */
{ 0x00<<2, 0x24<<2, 0x0E<<2 }, /* Value 27 */
{ 0x00<<2, 0x20<<2, 0x22<<2 }, /* Value 28 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 29 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 30 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 31 */
{ 0x3F<<2, 0x3F<<2, 0x3F<<2 }, /* Value 32 */
{ 0x0F<<2, 0x2F<<2, 0x3F<<2 }, /* Value 33 */
{ 0x17<<2, 0x25<<2, 0x3F<<2 }, /* Value 34 */
{ 0x33<<2, 0x22<<2, 0x3F<<2 }, /* Value 35 */
{ 0x3D<<2, 0x1E<<2, 0x3F<<2 }, /* Value 36 */
{ 0x3F<<2, 0x1D<<2, 0x2D<<2 }, /* Value 37 */
{ 0x3F<<2, 0x1D<<2, 0x18<<2 }, /* Value 38 */
{ 0x3F<<2, 0x26<<2, 0x0E<<2 }, /* Value 39 */
{ 0x3C<<2, 0x2F<<2, 0x0F<<2 }, /* Value 40 */
{ 0x20<<2, 0x34<<2, 0x04<<2 }, /* Value 41 */
{ 0x13<<2, 0x37<<2, 0x12<<2 }, /* Value 42 */
{ 0x16<<2, 0x3E<<2, 0x26<<2 }, /* Value 43 */
{ 0x00<<2, 0x3A<<2, 0x36<<2 }, /* Value 44 */
{ 0x1E<<2, 0x1E<<2, 0x1E<<2 }, /* Value 45 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 46 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 47 */
{ 0x3F<<2, 0x3F<<2, 0x3F<<2 }, /* Value 48 */
{ 0x2A<<2, 0x39<<2, 0x3F<<2 }, /* Value 49 */
{ 0x31<<2, 0x35<<2, 0x3F<<2 }, /* Value 50 */
{ 0x35<<2, 0x32<<2, 0x3F<<2 }, /* Value 51 */
{ 0x3F<<2, 0x31<<2, 0x3F<<2 }, /* Value 52 */
{ 0x3F<<2, 0x31<<2, 0x36<<2 }, /* Value 53 */
{ 0x3F<<2, 0x2F<<2, 0x2C<<2 }, /* Value 54 */
{ 0x3F<<2, 0x36<<2, 0x2A<<2 }, /* Value 55 */
{ 0x3F<<2, 0x39<<2, 0x28<<2 }, /* Value 56 */
{ 0x38<<2, 0x3F<<2, 0x28<<2 }, /* Value 57 */
{ 0x2A<<2, 0x3C<<2, 0x2F<<2 }, /* Value 58 */
{ 0x2C<<2, 0x3F<<2, 0x33<<2 }, /* Value 59 */
{ 0x27<<2, 0x3F<<2, 0x3C<<2 }, /* Value 60 */
{ 0x31<<2, 0x31<<2, 0x31<<2 }, /* Value 61 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 62 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 63 */
#undef P64
//luke's .16+ palette
//{0x60, 0x60, 0x60}, /* Value 0 */
+64 -64
View File
@@ -1,64 +1,64 @@
{0xfc, 0xc4, 0xd8},
{0x40, 0x88, 0xfc},
{0xd8, 0x28, 0x00},
{0x5c, 0x94, 0xfc},
{0x00, 0x80, 0x88},
{0x00, 0x44, 0x00},
{0x00, 0x00, 0x00},
{0xe4, 0x00, 0x58},
{0xfc, 0xfc, 0xfc},
{0x74, 0x74, 0x74},
{0xfc, 0x98, 0x38},
{0xa8, 0x00, 0x10},
{0x8c, 0x00, 0x74},
{0xfc, 0x98, 0x38},
{0x40, 0x2c, 0x00},
{0xfc, 0xfc, 0xfc},
{0x3c, 0xbc, 0xfc},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x80, 0xd0, 0x10},
{0x9c, 0xfc, 0xf0},
{0xc4, 0xd4, 0xfc},
{0xfc, 0xbc, 0xb0},
{0x20, 0x38, 0xec},
{0x00, 0x00, 0x00},
{0x58, 0xf8, 0x98},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0xfc, 0xfc},
{0xbc, 0xbc, 0xbc},
{0xf4, 0x78, 0xfc},
{0x24, 0x18, 0x8c},
{0x00, 0x00, 0x00},
{0xa8, 0xe4, 0xfc},
{0x00, 0x00, 0x00},
{0x4c, 0xdc, 0x48},
{0x00, 0xe8, 0xd8},
{0x18, 0x3c, 0x5c},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x7c, 0x08, 0x00},
{0xfc, 0xc4, 0xfc},
{0xa4, 0x00, 0x00},
{0x80, 0x00, 0xf0},
{0x00, 0x00, 0xa8},
{0xfc, 0x74, 0x60},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x94, 0x00},
{0xbc, 0xbc, 0xbc},
{0x00, 0x50, 0x00},
{0xe0, 0xfc, 0xa0},
{0x00, 0x00, 0x00},
{0xfc, 0xd8, 0xa8},
{0xc8, 0x4c, 0x0c},
{0x00, 0x00, 0x00},
{0x00, 0x70, 0xec},
{0x00, 0x44, 0x00},
{0x00, 0x00, 0x00},
{0xe0, 0xfc, 0xa0},
{0xfc, 0x74, 0xb4},
{0x88, 0x70, 0x00},
{0x00, 0x00, 0x00},
{P64RPC(0xfc), P64RPC(0xc4), P64RPC(0xd8)},
{P64RPC(0x40), P64RPC(0x88), P64RPC(0xfc)},
{P64RPC(0xd8), P64RPC(0x28), P64RPC(0x00)},
{P64RPC(0x5c), P64RPC(0x94), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x80), P64RPC(0x88)},
{P64RPC(0x00), P64RPC(0x44), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xe4), P64RPC(0x00), P64RPC(0x58)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x74), P64RPC(0x74), P64RPC(0x74)},
{P64RPC(0xfc), P64RPC(0x98), P64RPC(0x38)},
{P64RPC(0xa8), P64RPC(0x00), P64RPC(0x10)},
{P64RPC(0x8c), P64RPC(0x00), P64RPC(0x74)},
{P64RPC(0xfc), P64RPC(0x98), P64RPC(0x38)},
{P64RPC(0x40), P64RPC(0x2c), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x3c), P64RPC(0xbc), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x80), P64RPC(0xd0), P64RPC(0x10)},
{P64RPC(0x9c), P64RPC(0xfc), P64RPC(0xf0)},
{P64RPC(0xc4), P64RPC(0xd4), P64RPC(0xfc)},
{P64RPC(0xfc), P64RPC(0xbc), P64RPC(0xb0)},
{P64RPC(0x20), P64RPC(0x38), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x58), P64RPC(0xf8), P64RPC(0x98)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0xbc), P64RPC(0xbc), P64RPC(0xbc)},
{P64RPC(0xf4), P64RPC(0x78), P64RPC(0xfc)},
{P64RPC(0x24), P64RPC(0x18), P64RPC(0x8c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xa8), P64RPC(0xe4), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x4c), P64RPC(0xdc), P64RPC(0x48)},
{P64RPC(0x00), P64RPC(0xe8), P64RPC(0xd8)},
{P64RPC(0x18), P64RPC(0x3c), P64RPC(0x5c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x7c), P64RPC(0x08), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xc4), P64RPC(0xfc)},
{P64RPC(0xa4), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x80), P64RPC(0x00), P64RPC(0xf0)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0xa8)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0x60)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x94), P64RPC(0x00)},
{P64RPC(0xbc), P64RPC(0xbc), P64RPC(0xbc)},
{P64RPC(0x00), P64RPC(0x50), P64RPC(0x00)},
{P64RPC(0xe0), P64RPC(0xfc), P64RPC(0xa0)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xd8), P64RPC(0xa8)},
{P64RPC(0xc8), P64RPC(0x4c), P64RPC(0x0c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x70), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x44), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xe0), P64RPC(0xfc), P64RPC(0xa0)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0xb4)},
{P64RPC(0x88), P64RPC(0x70), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
+64 -64
View File
@@ -1,64 +1,64 @@
{0x00, 0x00, 0x00},
{0xfc, 0x98, 0x38},
{0x88, 0x70, 0x00},
{0x00, 0x00, 0x00},
{0xa8, 0xf0, 0xbc},
{0xfc, 0x74, 0xb4},
{0x00, 0x00, 0x00},
{0xa8, 0xe4, 0xfc},
{0xd8, 0x28, 0x00},
{0x80, 0x00, 0xf0},
{0xfc, 0xe4, 0xa0},
{0xfc, 0xc4, 0xfc},
{0xfc, 0xfc, 0xfc},
{0x40, 0x88, 0xfc},
{0x00, 0x00, 0x00},
{0x00, 0x3c, 0x14},
{0x00, 0x00, 0x00},
{0x3c, 0xbc, 0xfc},
{0xa4, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x90, 0x38},
{0x80, 0xd0, 0x10},
{0x00, 0x00, 0x00},
{0x5c, 0x94, 0xfc},
{0x00, 0x00, 0x00},
{0xf4, 0x78, 0xfc},
{0x00, 0x00, 0x00},
{0x58, 0xf8, 0x98},
{0x00, 0x00, 0x00},
{0x40, 0x2c, 0x00},
{0x00, 0x00, 0x00},
{0x44, 0x00, 0x9c},
{0x00, 0x00, 0x00},
{0xfc, 0xbc, 0xb0},
{0xfc, 0x74, 0x60},
{0xd4, 0xc8, 0xfc},
{0x00, 0x70, 0xec},
{0x00, 0x00, 0x00},
{0xbc, 0xbc, 0xbc},
{0x00, 0x00, 0xa8},
{0xbc, 0x00, 0xbc},
{0x00, 0x00, 0x00},
{0x74, 0x74, 0x74},
{0x00, 0x44, 0x00},
{0x20, 0x38, 0xec},
{0x00, 0x00, 0x00},
{0xfc, 0xd8, 0xa8},
{0xfc, 0xfc, 0xfc},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x4c, 0xdc, 0x48},
{0xc8, 0x4c, 0x0c},
{0x18, 0x3c, 0x5c},
{0x24, 0x18, 0x8c},
{0xe4, 0x00, 0x58},
{0x00, 0x94, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0xe8, 0xd8},
{0x7c, 0x08, 0x00},
{0xfc, 0xd8, 0xa8},
{0x00, 0x00, 0x00},
{0xa8, 0x00, 0x10},
{0x00, 0x50, 0x00},
{0x74, 0x74, 0x74},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0x98), P64RPC(0x38)},
{P64RPC(0x88), P64RPC(0x70), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xa8), P64RPC(0xf0), P64RPC(0xbc)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0xb4)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xa8), P64RPC(0xe4), P64RPC(0xfc)},
{P64RPC(0xd8), P64RPC(0x28), P64RPC(0x00)},
{P64RPC(0x80), P64RPC(0x00), P64RPC(0xf0)},
{P64RPC(0xfc), P64RPC(0xe4), P64RPC(0xa0)},
{P64RPC(0xfc), P64RPC(0xc4), P64RPC(0xfc)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x40), P64RPC(0x88), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x3c), P64RPC(0x14)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x3c), P64RPC(0xbc), P64RPC(0xfc)},
{P64RPC(0xa4), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x90), P64RPC(0x38)},
{P64RPC(0x80), P64RPC(0xd0), P64RPC(0x10)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x5c), P64RPC(0x94), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xf4), P64RPC(0x78), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x58), P64RPC(0xf8), P64RPC(0x98)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x40), P64RPC(0x2c), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x44), P64RPC(0x00), P64RPC(0x9c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xbc), P64RPC(0xb0)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0x60)},
{P64RPC(0xd4), P64RPC(0xc8), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x70), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xbc), P64RPC(0xbc), P64RPC(0xbc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0xa8)},
{P64RPC(0xbc), P64RPC(0x00), P64RPC(0xbc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x74), P64RPC(0x74), P64RPC(0x74)},
{P64RPC(0x00), P64RPC(0x44), P64RPC(0x00)},
{P64RPC(0x20), P64RPC(0x38), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xd8), P64RPC(0xa8)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x4c), P64RPC(0xdc), P64RPC(0x48)},
{P64RPC(0xc8), P64RPC(0x4c), P64RPC(0x0c)},
{P64RPC(0x18), P64RPC(0x3c), P64RPC(0x5c)},
{P64RPC(0x24), P64RPC(0x18), P64RPC(0x8c)},
{P64RPC(0xe4), P64RPC(0x00), P64RPC(0x58)},
{P64RPC(0x00), P64RPC(0x94), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0xe8), P64RPC(0xd8)},
{P64RPC(0x7c), P64RPC(0x08), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xd8), P64RPC(0xa8)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xa8), P64RPC(0x00), P64RPC(0x10)},
{P64RPC(0x00), P64RPC(0x50), P64RPC(0x00)},
{P64RPC(0x74), P64RPC(0x74), P64RPC(0x74)},
+64 -64
View File
@@ -1,64 +1,64 @@
{0x44, 0x00, 0x9c},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x74, 0x74, 0x74},
{0x00, 0xa8, 0x00},
{0xfc, 0xfc, 0xfc},
{0xa8, 0xe4, 0xfc},
{0x00, 0x44, 0x00},
{0x24, 0x18, 0x8c},
{0x00, 0x00, 0x00},
{0xfc, 0xbc, 0xb0},
{0x40, 0x2c, 0x00},
{0xe4, 0x00, 0x58},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0xfc, 0xfc},
{0x5c, 0x94, 0xfc},
{0x00, 0x80, 0x88},
{0x00, 0x00, 0x00},
{0x20, 0x38, 0xec},
{0x00, 0x94, 0x00},
{0x88, 0x70, 0x00},
{0xc8, 0x4c, 0x0c},
{0x00, 0x90, 0x38},
{0x74, 0x74, 0x74},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0xa8},
{0xd8, 0x28, 0x00},
{0xa4, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0xc4, 0xd8},
{0x40, 0x88, 0xfc},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0xd8, 0xa8},
{0x00, 0x00, 0x00},
{0xfc, 0x98, 0x38},
{0xfc, 0x74, 0x60},
{0xfc, 0xfc, 0xfc},
{0x80, 0xd0, 0x10},
{0x00, 0x00, 0x00},
{0x3c, 0xbc, 0xfc},
{0xf4, 0x78, 0xfc},
{0x00, 0x70, 0xec},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0xe8, 0xd8},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x7c, 0x08, 0x00},
{0x4c, 0xdc, 0x48},
{0xf0, 0xbc, 0x3c},
{0x00, 0x00, 0x00},
{0x00, 0x50, 0x00},
{0x00, 0x00, 0x00},
{0xc4, 0xd4, 0xfc},
{0xfc, 0xd8, 0xa8},
{0x80, 0x00, 0xf0},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x18, 0x3c, 0x5c},
{P64RPC(0x44), P64RPC(0x00), P64RPC(0x9c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x74), P64RPC(0x74), P64RPC(0x74)},
{P64RPC(0x00), P64RPC(0xa8), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0xa8), P64RPC(0xe4), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x44), P64RPC(0x00)},
{P64RPC(0x24), P64RPC(0x18), P64RPC(0x8c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xbc), P64RPC(0xb0)},
{P64RPC(0x40), P64RPC(0x2c), P64RPC(0x00)},
{P64RPC(0xe4), P64RPC(0x00), P64RPC(0x58)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x5c), P64RPC(0x94), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x80), P64RPC(0x88)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x20), P64RPC(0x38), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x94), P64RPC(0x00)},
{P64RPC(0x88), P64RPC(0x70), P64RPC(0x00)},
{P64RPC(0xc8), P64RPC(0x4c), P64RPC(0x0c)},
{P64RPC(0x00), P64RPC(0x90), P64RPC(0x38)},
{P64RPC(0x74), P64RPC(0x74), P64RPC(0x74)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0xa8)},
{P64RPC(0xd8), P64RPC(0x28), P64RPC(0x00)},
{P64RPC(0xa4), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xc4), P64RPC(0xd8)},
{P64RPC(0x40), P64RPC(0x88), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xd8), P64RPC(0xa8)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0x98), P64RPC(0x38)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0x60)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x80), P64RPC(0xd0), P64RPC(0x10)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x3c), P64RPC(0xbc), P64RPC(0xfc)},
{P64RPC(0xf4), P64RPC(0x78), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x70), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0xe8), P64RPC(0xd8)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x7c), P64RPC(0x08), P64RPC(0x00)},
{P64RPC(0x4c), P64RPC(0xdc), P64RPC(0x48)},
{P64RPC(0xf0), P64RPC(0xbc), P64RPC(0x3c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x50), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xc4), P64RPC(0xd4), P64RPC(0xfc)},
{P64RPC(0xfc), P64RPC(0xd8), P64RPC(0xa8)},
{P64RPC(0x80), P64RPC(0x00), P64RPC(0xf0)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x18), P64RPC(0x3c), P64RPC(0x5c)},
+64 -64
View File
@@ -1,64 +1,64 @@
{0x88, 0x70, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x80, 0x88},
{0xf0, 0xbc, 0x3c},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x24, 0x18, 0x8c},
{0xc8, 0x4c, 0x0c},
{0xbc, 0xbc, 0xbc},
{0x00, 0x00, 0x00},
{0x4c, 0xdc, 0x48},
{0x00, 0x00, 0x00},
{0xfc, 0xbc, 0xb0},
{0xfc, 0xd8, 0xa8},
{0x00, 0xa8, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0x74, 0xb4},
{0x00, 0x00, 0x00},
{0x20, 0x38, 0xec},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0x74, 0x60},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x5c, 0x94, 0xfc},
{0x00, 0x94, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xa8, 0xf0, 0xbc},
{0x3c, 0xbc, 0xfc},
{0xa8, 0x00, 0x10},
{0x00, 0x50, 0x00},
{0x7c, 0x08, 0x00},
{0x00, 0x00, 0xa8},
{0x80, 0x00, 0xf0},
{0x00, 0x00, 0x00},
{0x74, 0x74, 0x74},
{0xe4, 0x00, 0x58},
{0x18, 0x3c, 0x5c},
{0x00, 0x00, 0x00},
{0x00, 0x70, 0xec},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0xe4, 0xa0},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x40, 0x2c, 0x00},
{0xd8, 0x28, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0xfc, 0xfc},
{0x9c, 0xfc, 0xf0},
{0x00, 0x00, 0x00},
{0xfc, 0x98, 0x38},
{0x00, 0x00, 0x00},
{0xa8, 0xe4, 0xfc},
{0x80, 0xd0, 0x10},
{0x00, 0x00, 0x00},
{0xfc, 0xfc, 0xfc},
{0x00, 0x44, 0x00},
{P64RPC(0x88), P64RPC(0x70), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x80), P64RPC(0x88)},
{P64RPC(0xf0), P64RPC(0xbc), P64RPC(0x3c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x24), P64RPC(0x18), P64RPC(0x8c)},
{P64RPC(0xc8), P64RPC(0x4c), P64RPC(0x0c)},
{P64RPC(0xbc), P64RPC(0xbc), P64RPC(0xbc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x4c), P64RPC(0xdc), P64RPC(0x48)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xbc), P64RPC(0xb0)},
{P64RPC(0xfc), P64RPC(0xd8), P64RPC(0xa8)},
{P64RPC(0x00), P64RPC(0xa8), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0xb4)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x20), P64RPC(0x38), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0x60)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x5c), P64RPC(0x94), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x94), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xa8), P64RPC(0xf0), P64RPC(0xbc)},
{P64RPC(0x3c), P64RPC(0xbc), P64RPC(0xfc)},
{P64RPC(0xa8), P64RPC(0x00), P64RPC(0x10)},
{P64RPC(0x00), P64RPC(0x50), P64RPC(0x00)},
{P64RPC(0x7c), P64RPC(0x08), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0xa8)},
{P64RPC(0x80), P64RPC(0x00), P64RPC(0xf0)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x74), P64RPC(0x74), P64RPC(0x74)},
{P64RPC(0xe4), P64RPC(0x00), P64RPC(0x58)},
{P64RPC(0x18), P64RPC(0x3c), P64RPC(0x5c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x70), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xe4), P64RPC(0xa0)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x40), P64RPC(0x2c), P64RPC(0x00)},
{P64RPC(0xd8), P64RPC(0x28), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x9c), P64RPC(0xfc), P64RPC(0xf0)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0x98), P64RPC(0x38)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xa8), P64RPC(0xe4), P64RPC(0xfc)},
{P64RPC(0x80), P64RPC(0xd0), P64RPC(0x10)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x44), P64RPC(0x00)},
+67 -16
View File
@@ -57,6 +57,7 @@
#define PPU_status (PPU[2])
#define READPALNOGS(ofs) (PALRAM[(ofs)])
#define READPAL(ofs) (PALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF))
#define READUPAL(ofs) (UPALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF))
@@ -455,13 +456,24 @@ volatile int rendercount, vromreadcount, undefinedvromcount, LogAddress = -1;
unsigned char *cdloggervdata = NULL;
unsigned int cdloggerVideoDataSize = 0;
int GetCHRAddress(int A) {
if (cdloggerVideoDataSize) {
int result = &VPage[A >> 10][A] - CHRptr[0];
int GetCHRAddress(int A)
{
if (cdloggerVideoDataSize)
{
int result = -1;
if ( (A >= 0) && (A < 0x2000) )
{
result = &VPage[A >> 10][A] - CHRptr[0];
}
if ((result >= 0) && (result < (int)cdloggerVideoDataSize))
{
return result;
} else
if(A < 0x2000) return A;
}
}
else
{
if ( (A >= 0) && (A < 0x2000) ) return A;
}
return -1;
}
@@ -1987,6 +1999,7 @@ void runppu(int x) {
struct BGData {
struct Record {
uint8 nt, pecnt, at, pt[2], qtnt;
uint8 ppu1[8];
INLINE void Read() {
NTRefreshAddr = RefreshAddr = ppur.get_ntread();
@@ -1998,7 +2011,12 @@ struct BGData {
}
pecnt = (RefreshAddr & 1) << 3;
nt = CALL_PPUREAD(RefreshAddr);
runppu(kFetchTime);
ppu1[0] = PPU[1];
runppu(1);
ppu1[1] = PPU[1];
runppu(1);
RefreshAddr = ppur.get_atread();
at = CALL_PPUREAD(RefreshAddr);
@@ -2010,37 +2028,57 @@ struct BGData {
at <<= 2;
//horizontal scroll clocked at cycle 3 and then
//vertical scroll at 251
ppu1[2] = PPU[1];
runppu(1);
if (PPUON) {
ppur.increment_hsc();
if (ppur.status.cycle == 251)
ppur.increment_vs();
}
ppu1[3] = PPU[1];
runppu(1);
ppur.par = nt;
RefreshAddr = ppur.get_ptread();
if (PEC586Hack) {
pt[0] = CALL_PPUREAD(RefreshAddr | pecnt);
runppu(kFetchTime);
ppu1[4] = PPU[1];
runppu(1);
ppu1[5] = PPU[1];
runppu(1);
pt[1] = CALL_PPUREAD(RefreshAddr | pecnt);
runppu(kFetchTime);
ppu1[6] = PPU[1];
runppu(1);
ppu1[7] = PPU[1];
runppu(1);
} else if (QTAIHack && (qtnt & 0x40)) {
pt[0] = *(CHRptr[0] + RefreshAddr);
runppu(kFetchTime);
ppu1[4] = PPU[1];
runppu(1);
ppu1[5] = PPU[1];
runppu(1);
RefreshAddr |= 8;
pt[1] = *(CHRptr[0] + RefreshAddr);
runppu(kFetchTime);
ppu1[6] = PPU[1];
runppu(1);
ppu1[7] = PPU[1];
runppu(1);
} else {
if (ScreenON)
RENDER_LOG(RefreshAddr);
pt[0] = CALL_PPUREAD(RefreshAddr);
runppu(kFetchTime);
ppu1[4] = PPU[1];
runppu(1);
ppu1[5] = PPU[1];
runppu(1);
RefreshAddr |= 8;
if (ScreenON)
RENDER_LOG(RefreshAddr);
pt[1] = CALL_PPUREAD(RefreshAddr);
runppu(kFetchTime);
ppu1[6] = PPU[1];
runppu(1);
ppu1[7] = PPU[1];
runppu(1);
}
}
};
@@ -2216,7 +2254,7 @@ int FCEUX_PPU_Loop(int skip) {
pixel = ((pt[0] >> (7 - bgpx)) & 1) | (((pt[1] >> (7 - bgpx)) & 1) << 1) | bgdata.main[bgtile].at;
}
if (renderbg)
pixelcolor = READPAL(pixel);
pixelcolor = READPALNOGS(pixel);
//look for a sprite to be drawn
bool havepixel = false;
@@ -2261,12 +2299,25 @@ int FCEUX_PPU_Loop(int skip) {
spixel |= (oam[2] & 3) << 2;
if (rendersprites)
pixelcolor = READPAL(0x10 + spixel);
pixelcolor = READPALNOGS(0x10 + spixel);
}
}
*ptr++ = PaletteAdjustPixel(pixelcolor);
*dptr++= PPU[1]>>5; //grab deemph
//apply grayscale.. kind of clunky
//really we need to read the entire palette instead of just ppu1
//this will be needed for special color effects probably (very fine rainbows and whatnot?)
//are you allowed to chang the palette mid-line anyway? well you can definitely change the grayscale flag as we know from the FF1 "polygon" effect
if(bgdata.main[xt+2].ppu1[xp]&1)
pixelcolor &= 0x30;
//this does deemph stuff inside it.. which is probably wrong...
*ptr = PaletteAdjustPixel(pixelcolor);
ptr++;
//grab deemph..
//I guess this works the same way as the grayscale, ideally?
*dptr++ = bgdata.main[xt+2].ppu1[xp]>>5;
}
}
}
+1 -1
View File
@@ -6,7 +6,7 @@ uint8 tmpd;
#endif
#ifndef PPUT_MMC5SP
uint8 zz;
FCEU_MAYBE_UNUSED uint8 zz;
#else
uint8 xs, ys;
xs = X1;
+3 -2
View File
@@ -534,9 +534,10 @@ static INLINE void DMCDMA(void)
PrepDPCM();
else
{
SIRQStat|=0x80;
if(DMCFormat&0x80)
if(DMCFormat&0x80) {
SIRQStat|=0x80;
X6502_IRQBegin(FCEU_IQDPCM);
}
}
}
}
+81 -71
View File
@@ -70,11 +70,11 @@ static int StateShow;
//tells the save system innards that we're loading the old format
bool FCEU_state_loading_old_format = false;
char lastSavestateMade[2048]; //Stores the filename of the last savestate made (needed for UndoSavestate)
std::string lastSavestateMade; //Stores the filename of the last savestate made (needed for UndoSavestate)
bool undoSS = false; //This will be true if there is lastSavestateMade, it was made since ROM was loaded, a backup state for lastSavestateMade exists
bool redoSS = false; //This will be true if UndoSaveState is run, will turn false when a new savestate is made
char lastLoadstateMade[2048]; //Stores the filename of the last state loaded (needed for Undo/Redo loadstate)
std::string lastLoadstateMade; //Stores the filename of the last state loaded (needed for Undo/Redo loadstate)
bool undoLS = false; //This will be true if a backupstate was made and it was made since ROM was loaded
bool redoLS = false; //This will be true if a backupstate was loaded, meaning redoLoadState can be run
@@ -88,7 +88,7 @@ EMUFILE_MEMORY memory_savestate;
// temporary buffer for compressed data of a savestate
std::vector<uint8> compressed_buf;
#define SFMDATA_SIZE (64)
#define SFMDATA_SIZE (128)
static SFORMAT SFMDATA[SFMDATA_SIZE];
static int SFEXINDEX;
@@ -110,7 +110,7 @@ SFORMAT SFCPU[]={
{ &X.Y, 1, "Y\0\0"},
{ &X.S, 1, "S\0\0"},
{ &X.P, 1, "P\0\0"},
{ &X.DB, 1, "DB"},
{ &X.DB, 1, "DB\0"},
{ &RAM, 0x800 | FCEUSTATE_INDIRECT, "RAM", },
{ 0 }
};
@@ -133,7 +133,7 @@ static int SubWrite(EMUFILE* os, SFORMAT *sf)
while(sf->v)
{
if(sf->s==~0) //Link to another struct
if(sf->s==~0u) //Link to another struct
{
uint32 tmp;
@@ -191,7 +191,7 @@ static SFORMAT *CheckS(SFORMAT *sf, uint32 tsize, char *desc)
{
while(sf->v)
{
if(sf->s==~0) // Link to another SFORMAT structure.
if(sf->s==~0u) // Link to another SFORMAT structure.
{
SFORMAT *tmp;
if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) ))
@@ -307,13 +307,24 @@ static bool ReadStateChunks(EMUFILE* is, int32 totalsize)
// load back buffer
{
extern uint8 *XBackBuf;
if(is->fread((char*)XBackBuf,size) != size)
ret = false;
//ignore 8 garbage bytes, whose idea was it to write these or even have them there in the first place
if(size == 256*256+8)
{
if(is->fread((char*)XBackBuf,256*256) != 256*256)
ret = false;
is->fseek(8,SEEK_CUR);
}
else
{
if(is->fread((char*)XBackBuf,size) != size)
ret = false;
}
//MBG TODO - can this be moved to a better place?
//does it even make sense, displaying XBuf when its XBackBuf we just loaded?
#ifdef __WIN_DRIVER__
else
if(ret)
{
FCEUD_BlitScreen(XBuf);
UpdateFCEUWindow();
@@ -404,7 +415,7 @@ bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel)
// save back buffer
{
extern uint8 *XBackBuf;
uint32 size = 256 * 256 + 8;
uint32 size = 256 * 256;
os->fputc(8);
write32le(size, os);
os->fwrite((char*)XBackBuf,size);
@@ -416,7 +427,7 @@ bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel)
if(SPostSave) SPostSave();
//save the length of the file
int len = memory_savestate.size();
size_t len = memory_savestate.size();
//sanity check: len and totalsize should be the same
if(len != totalsize)
@@ -427,7 +438,7 @@ bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel)
int error = Z_OK;
uint8* cbuf = (uint8*)memory_savestate.buf();
uLongf comprlen = -1;
uLongf comprlen = ~0lu;
if(compressionLevel != Z_NO_COMPRESSION && (compressSavestates || FCEUMOV_Mode(MOVIEMODE_TASEDITOR)))
{
// worst case compression: zlib says "0.1% larger than sourceLen plus 12 bytes"
@@ -446,7 +457,7 @@ bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel)
//dump it to the destination file
outstream->fwrite((char*)header,16);
outstream->fwrite((char*)cbuf,comprlen==-1?totalsize:comprlen);
outstream->fwrite((char*)cbuf,comprlen==~0lu?totalsize:comprlen);
return error == Z_OK;
}
@@ -455,7 +466,7 @@ bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel)
void FCEUSS_Save(const char *fname, bool display_message)
{
EMUFILE* st = 0;
char fn[2048];
std::string fn;
if (geniestage==1)
{
@@ -467,24 +478,24 @@ void FCEUSS_Save(const char *fname, bool display_message)
if(fname) //If filename is given use it.
{
st = FCEUD_UTF8_fstream(fname, "wb");
strcpy(fn, fname);
fn.assign(fname);
}
else //Else, generate one
{
//FCEU_PrintError("daCurrentState=%d",CurrentState);
strcpy(fn, FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0).c_str());
fn = FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0);
//backup existing savestate first
if (CheckFileExists(fn) && backupSavestates) //adelikat: If the files exists and we are allowed to make backup savestates
if (CheckFileExists(fn.c_str()) && backupSavestates) //adelikat: If the files exists and we are allowed to make backup savestates
{
CreateBackupSaveState(fn); //Make a backup of previous savestate before overwriting it
strcpy(lastSavestateMade,fn); //Remember what the last savestate filename was (for undoing later)
CreateBackupSaveState(fn.c_str()); //Make a backup of previous savestate before overwriting it
lastSavestateMade.assign(fn); //Remember what the last savestate filename was (for undoing later)
undoSS = true; //Backup was created so undo is possible
}
else
undoSS = false; //so backup made so lastSavestateMade does have a backup file, so no undo
st = FCEUD_UTF8_fstream(fn,"wb");
st = FCEUD_UTF8_fstream(fn.c_str(),"wb");
}
if (st == NULL || st->get_fp() == NULL)
@@ -500,13 +511,12 @@ void FCEUSS_Save(const char *fname, bool display_message)
LuaSaveData saveData;
CallRegisteredLuaSaveFunctions(CurrentState, saveData);
char luaSaveFilename [512];
strncpy(luaSaveFilename, fn, 512);
luaSaveFilename[512-(1+7/*strlen(".luasav")*/)] = '\0';
strcat(luaSaveFilename, ".luasav");
std::string luaSaveFilename;
luaSaveFilename.assign(fn.c_str());
luaSaveFilename.append(".luasav");
if(saveData.recordList)
{
FILE* luaSaveFile = fopen(luaSaveFilename, "wb");
FILE* luaSaveFile = fopen(luaSaveFilename.c_str(), "wb");
if(luaSaveFile)
{
saveData.ExportRecords(luaSaveFile);
@@ -515,7 +525,7 @@ void FCEUSS_Save(const char *fname, bool display_message)
}
else
{
unlink(luaSaveFilename);
unlink(luaSaveFilename.c_str());
}
}
#endif
@@ -655,22 +665,22 @@ bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params)
return ret;
}
int totalsize = FCEU_de32lsb(header + 4);
int stateversion = FCEU_de32lsb(header + 8);
int comprlen = FCEU_de32lsb(header + 12);
size_t totalsize = FCEU_de32lsb(header + 4);
int stateversion = FCEU_de32lsb(header + 8);
uint32_t comprlen = FCEU_de32lsb(header + 12);
// reinit memory_savestate
// memory_savestate is global variable which already has its vector of bytes, so no need to allocate memory every time we use save/loadstate
if ((int)(memory_savestate.get_vec())->size() < totalsize)
if ((memory_savestate.get_vec())->size() < totalsize)
(memory_savestate.get_vec())->resize(totalsize);
memory_savestate.set_len(totalsize);
memory_savestate.unfail();
memory_savestate.fseek(0, SEEK_SET);
if(comprlen != -1)
if(comprlen != ~0u)
{
// the savestate is compressed: read from is to compressed_buf, then decompress from compressed_buf to memory_savestate.vec
if ((int)compressed_buf.size() < comprlen) compressed_buf.resize(comprlen);
if (compressed_buf.size() < comprlen) compressed_buf.resize(comprlen);
is->fread(&compressed_buf[0], comprlen);
uLongf uncomprlen = totalsize;
@@ -712,8 +722,8 @@ bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params)
bool FCEUSS_Load(const char *fname, bool display_message)
{
EMUFILE* st;
char fn[2048];
fceuScopedPtr <EMUFILE> st; // fceuScopedPtr will auto delete the allocated EMUFILE at function return.
std::string fn;
//mbg movie - this needs to be overhauled
////this fixes read-only toggle problems
@@ -731,20 +741,21 @@ bool FCEUSS_Load(const char *fname, bool display_message)
if (fname)
{
st = FCEUD_UTF8_fstream(fname, "rb");
strcpy(fn, fname);
} else
fn.assign(fname);
}
else
{
strcpy(fn, FCEU_MakeFName(FCEUMKF_STATE,CurrentState,fname).c_str());
st=FCEUD_UTF8_fstream(fn,"rb");
strcpy(lastLoadstateMade,fn);
fn = FCEU_MakeFName(FCEUMKF_STATE,CurrentState,fname);
st=FCEUD_UTF8_fstream(fn.c_str(),"rb");
lastLoadstateMade.assign(fn);
}
if (st == NULL || (st->get_fp() == NULL))
if (st.get() == NULL || (st.get()->get_fp() == NULL))
{
if (display_message)
{
FCEU_DispMessage("State %d load error.", 0, CurrentState);
//FCEU_DispMessage("State %d load error. Filename: %s", 0, CurrentState, fn);
//FCEU_DispMessage("State %d load error. Filename: %s", 0, CurrentState, fn.c_str());
}
SaveStateStatus[CurrentState] = 0;
return false;
@@ -753,38 +764,37 @@ bool FCEUSS_Load(const char *fname, bool display_message)
//If in bot mode, don't do a backup when loading.
//Otherwise you eat at the hard disk, since so many
//states are being loaded.
if (FCEUSS_LoadFP(st, backupSavestates ? SSLOADPARAM_BACKUP : SSLOADPARAM_NOBACKUP))
if (FCEUSS_LoadFP(st.get(), backupSavestates ? SSLOADPARAM_BACKUP : SSLOADPARAM_NOBACKUP))
{
if (fname)
{
char szFilename[260]={0};
splitpath(fname, 0, 0, szFilename, 0);
if (display_message)
if (display_message)
{
FCEU_DispMessage("State %s loaded.", 0, szFilename);
//FCEU_DispMessage("State %s loaded. Filename: %s", 0, szFilename, fn);
}
} else
FCEU_DispMessage("State %s loaded.", 0, szFilename);
//FCEU_DispMessage("State %s loaded. Filename: %s", 0, szFilename, fn.c_str());
}
}
else
{
if (display_message)
if (display_message)
{
FCEU_DispMessage("State %d loaded.", 0, CurrentState);
//FCEU_DispMessage("State %d loaded. Filename: %s", 0, CurrentState, fn);
}
FCEU_DispMessage("State %d loaded.", 0, CurrentState);
//FCEU_DispMessage("State %d loaded. Filename: %s", 0, CurrentState, fn.c_str());
}
SaveStateStatus[CurrentState] = 1;
}
delete st;
#ifdef _S9XLUA_H
if (!internalSaveLoad)
{
LuaSaveData saveData;
char luaSaveFilename [512];
strncpy(luaSaveFilename, fn, 512);
luaSaveFilename[512-(1+7/*strlen(".luasav")*/)] = '\0';
strcat(luaSaveFilename, ".luasav");
FILE* luaSaveFile = fopen(luaSaveFilename, "rb");
std::string luaSaveFilename;
luaSaveFilename.assign(fn.c_str());
luaSaveFilename.append(".luasav");
FILE* luaSaveFile = fopen(luaSaveFilename.c_str(), "rb");
if(luaSaveFile)
{
saveData.ImportRecords(luaSaveFile);
@@ -796,7 +806,7 @@ bool FCEUSS_Load(const char *fname, bool display_message)
#endif
#ifdef __WIN_DRIVER__
Update_RAM_Search(); // Update_RAM_Watch() is also called.
Update_RAM_Search(); // Update_RAM_Watch() is also called.
#endif
//Update input display if movie is loaded
@@ -806,7 +816,8 @@ bool FCEUSS_Load(const char *fname, bool display_message)
cur_input_display = FCEU_GetJoyJoy(); //Input display should show the last buttons pressed (stored in the savestate)
return true;
} else
}
else
{
if(!fname)
SaveStateStatus[CurrentState] = 1;
@@ -816,7 +827,6 @@ bool FCEUSS_Load(const char *fname, bool display_message)
FCEU_DispMessage("Error(s) reading state %d!", 0, CurrentState);
//FCEU_DispMessage("Error(s) reading state %d! Filename: %s", 0, CurrentState, fn);
}
delete st;
return 0;
}
}
@@ -848,7 +858,7 @@ void ResetExState(void (*PreSave)(void), void (*PostSave)(void))
for(x=0;x<SFEXINDEX;x++)
{
if(SFMDATA[x].desc)
free( (void*)SFMDATA[x].desc);
FCEU_free( (void*)SFMDATA[x].desc);
}
// adelikat, 3/14/09: had to add this to clear out the size parameter. NROM(mapper 0) games were having savestate crashes if loaded after a non NROM game because the size variable was carrying over and causing savestates to save too much data
SFMDATA[0].s = 0;
@@ -863,7 +873,7 @@ void AddExState(void *v, uint32 s, int type, const char *desc)
//do not accept extra state information if a null pointer was provided for v, so list won't terminate early
if (v == 0) return;
if(s==~0)
if(s==~0u)
{
SFORMAT* sf = (SFORMAT*)v;
std::map<std::string,bool> names;
@@ -1056,13 +1066,13 @@ void SwapSaveState()
//Both files must exist
//--------------------------------------------------------------------------------------------
if (!lastSavestateMade)
if (lastSavestateMade.empty())
{
FCEUI_DispMessage("Can't Undo",0);
FCEUI_printf("Undo savestate was attempted but unsuccessful because there was not a recently used savestate.\n");
return; //If there is no last savestate, can't undo
}
string backup = GenerateBackupSaveStateFn(lastSavestateMade); //Get filename of backup state
string backup = GenerateBackupSaveStateFn(lastSavestateMade.c_str()); //Get filename of backup state
if (!CheckFileExists(backup.c_str()))
{
FCEUI_DispMessage("Can't Undo",0);
@@ -1076,9 +1086,9 @@ void SwapSaveState()
string temp = backup; //Put backup filename in temp
temp.append("x"); //Add x
rename(backup.c_str(),temp.c_str()); //rename backup file to temp file
rename(lastSavestateMade,backup.c_str()); //rename current as backup
rename(temp.c_str(),lastSavestateMade); //rename backup as current
rename(backup.c_str(),temp.c_str()); //rename backup file to temp file
rename(lastSavestateMade.c_str(),backup.c_str()); //rename current as backup
rename(temp.c_str(),lastSavestateMade.c_str()); //rename backup as current
undoSS = true; //Just in case, if this was run, then there is definately a last savestate and backup
if (redoSS) //This was a redo function, so if run again it will be an undo again
@@ -1103,7 +1113,7 @@ string GetBackupFileName()
string filename;
int x;
filename = strdup(FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0).c_str()); //Generate normal savestate filename
filename = FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0); //Generate normal savestate filename
x = filename.find_last_of("."); //Find last dot
filename = filename.substr(0,x); //Chop off file extension
filename.append(".bak.fc0"); //add .bak
@@ -1161,10 +1171,10 @@ void LoadBackup()
void RedoLoadState()
{
if (!redoLS) return;
if (lastLoadstateMade && redoLS)
if (!lastLoadstateMade.empty() && redoLS)
{
FCEUSS_Load(lastLoadstateMade);
FCEUI_printf("Redoing %s\n",lastLoadstateMade);
FCEUSS_Load(lastLoadstateMade.c_str());
FCEUI_printf("Redoing %s\n",lastLoadstateMade.c_str());
}
redoLS = false; //Flag that RedoLoadState can not be run again
undoLS = true; //Flag that LoadBackup can be run again
+3 -2
View File
@@ -17,6 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <string>
enum ENUM_SSLOADPARAMS
{
@@ -67,10 +68,10 @@ void LoadBackup(); //Loads the backupsavestate
void RedoLoadState(); //reloads a loadstate if backupsavestate was run
void SwapSaveState(); //Swaps a savestate with its backup state
extern char lastSavestateMade[2048]; //Filename of last savestate used
extern std::string lastSavestateMade; //Filename of last savestate used
extern bool undoSS; //undo savestate flag
extern bool redoSS; //redo savestate flag
extern char lastLoadstateMade[2048]; //Filename of last state loaded
extern std::string lastLoadstateMade; //Filename of last state loaded
extern bool undoLS; //undo loadstate flag
extern bool redoLS; //redo savestate flag
extern bool backupSavestates; //Whether or not to make backups, true by default
+85 -1
View File
@@ -62,6 +62,8 @@ typedef signed int int32;
#define alloca __builtin_alloca
#endif
//#include <typeinfo>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -131,7 +133,7 @@ typedef uint32_t uint32;
#endif
#if defined(WIN32) && !defined(__QT_DRIVER__)
#if defined(WIN32) && !defined(__QT_DRIVER__) && !defined(__WIN_DRIVER__)
#define __WIN_DRIVER__
#endif
@@ -143,6 +145,88 @@ typedef uint8 (*readfunc)(uint32 A);
#define CTASSERT(x) typedef char __assert ## y[(x) ? 1 : -1];
#endif
#define __FCEU_STRINGIZE2(x) #x
#define __FCEU_STRINGIZE(x) __FCEU_STRINGIZE2(x)
#define FCEU_CPP_HAS_STD(x) ( defined(__cplusplus) && (__cplusplus >= x) )
#ifdef __has_cpp_attribute
#define FCEU_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
#define FCEU_HAS_CPP_ATTRIBUTE(x) 0
#endif
#define FCEU_UNUSED(x) (void)(x)
#if FCEU_CPP_HAS_STD(201603L) || FCEU_HAS_CPP_ATTRIBUTE(maybe_unused)
#define FCEU_MAYBE_UNUSED [[maybe_unused]]
#else
#define FCEU_MAYBE_UNUSED
#endif
#if defined(_MSC_VER)
// Microsoft compiler won't catch format issues, but VS IDE can catch on analysis mode
#define __FCEU_PRINTF_FORMAT _In_z_ _Printf_format_string_
#define __FCEU_PRINTF_ATTRIBUTE( fmt, va )
#elif defined(__GNUC__) || defined(__clang__) || FCEU_HAS_CPP_ATTRIBUTE(format)
// GCC and Clang compilers will perform printf format type checks, useful for catching format errors.
#define __FCEU_PRINTF_FORMAT
#define __FCEU_PRINTF_ATTRIBUTE( fmt, va ) __attribute__((__format__(__printf__, fmt, va)))
#else
#define __FCEU_PRINTF_FORMAT
#define __FCEU_PRINTF_ATTRIBUTE( fmt, va )
#endif
// Scoped pointer ensures that memory pointed to by this object gets cleaned up
// and deallocated when this object goes out of scope. Helps prevent memory leaks
// on temporary memory allocations in functions with early outs.
template <typename T>
class fceuScopedPtr
{
public:
fceuScopedPtr( T *ptrIn = nullptr )
{
//printf("Scoped Pointer Constructor <%s>: %p\n", typeid(T).name(), ptrIn );
ptr = ptrIn;
}
~fceuScopedPtr(void)
{
//printf("Scoped Pointer Destructor <%s>: %p\n", typeid(T).name(), ptr );
if (ptr)
{
delete ptr;
ptr = nullptr;
}
}
T* operator= (T *ptrIn)
{
ptr = ptrIn;
return ptr;
}
T* get(void)
{
return ptr;
}
void Delete(void)
{
if (ptr)
{
delete ptr;
ptr = nullptr;
}
}
private:
T *ptr;
};
#include "utils/endian.h"
#endif
+2 -1
View File
@@ -140,7 +140,7 @@ static int DoMirroring(FCEUFILE *fp) {
return(0);
FCEU_printf(" %02x", t);
}
FCEU_printf("\n Default Name/Attribute Table Mirroring: Horizontal\n", uchead.info);
FCEU_printf("\n Default Name/Attribute Table Mirroring: Horizontal\n");
mirrortodo = 0;
}
return(1);
@@ -475,6 +475,7 @@ static BMAPPING bmap[] = {
{ "FNS", FNS_Init, BMCFLAG_16KCHRR },
{ "BS-400R", BS400R_Init, 0 },
{ "BS-4040R", BS4040R_Init, 0 },
{ "COOLGIRL", COOLGIRL_Init, 0 },
{ 0, 0, 0 }
};
+2 -1
View File
@@ -162,7 +162,8 @@ void MINDKIDS_Init(CartInfo *info);
void FNS_Init(CartInfo *info);
void BS400R_Init(CartInfo *info);
void BS4040R_Init(CartInfo *info);
void SMD132_SMD133_Init(CartInfo *info);
void AA6023_Init(CartInfo *info);
void COOLGIRL_Init(CartInfo* info);
extern uint8 *UNIFchrrama; // Meh. So I can stop CHR RAM
// bank switcherooing with certain boards...
+65 -28
View File
@@ -28,53 +28,90 @@
#include "../fceu.h"
#include "memory.h"
///allocates the specified number of bytes. exits process if this fails
void *FCEU_amalloc(size_t size, size_t alignment)
{
size = (size + alignment - 1) & ~(alignment-1);
#ifdef _MSC_VER
void *ret = _aligned_malloc(size,alignment);
#else
void *ret = aligned_alloc(alignment,size);
#endif
if(!ret)
FCEU_abort("Error allocating memory!");
return ret;
}
void FCEU_afree(void* ptr)
{
#ifdef _MSC_VER
_aligned_free(ptr);
#else
free(ptr);
#endif
}
static void *_FCEU_malloc(uint32 size)
{
void* ret = malloc(size);
if(!ret)
FCEU_abort("Error allocating memory!");
return ret;
}
static void _FCEU_free(void* ptr)
{
free(ptr);
}
void *FCEU_gmalloc(uint32 size)
{
void *ret;
ret=malloc(size);
if(!ret)
{
FCEU_PrintError("Error allocating memory! Doing a hard exit.");
exit(1);
}
FCEU_MemoryRand((uint8*)ret,size,true); // initialize according to RAMInitOption, default zero
return ret;
void *ret = _FCEU_malloc(size);
// initialize according to RAMInitOption, default zero
FCEU_MemoryRand((uint8*)ret,size,true);
return ret;
}
///allocates the specified number of bytes. returns null if this fails
void *FCEU_malloc(uint32 size)
{
void *ret;
ret=malloc(size);
if(!ret)
{
FCEU_PrintError("Error allocating memory!");
return(0);
}
memset(ret,0,size); // initialize to 0
return ret;
void *ret = _FCEU_malloc(size);
memset(ret, 0, size);
return ret;
}
///frees memory allocated with FCEU_gmalloc
void FCEU_gfree(void *ptr)
{
free(ptr);
_FCEU_free(ptr);
}
///frees memory allocated with FCEU_malloc
void FCEU_free(void *ptr) // Might do something with this and FCEU_malloc later...
void FCEU_free(void *ptr)
{
free(ptr);
_FCEU_free(ptr);
}
void *FCEU_dmalloc(uint32 size)
{
return malloc(size);
return FCEU_malloc(size);
}
void FCEU_dfree(void *ptr)
{
free(ptr);
return FCEU_free(ptr);
}
void* FCEU_realloc(void* ptr, size_t size)
{
return realloc(ptr,size);
}
void FCEU_abort(const char* message)
{
if(message) FCEU_PrintError("%s", message);
abort();
}
+28 -7
View File
@@ -24,13 +24,34 @@
#define FCEU_dwmemset(d,c,n) {int _x; for(_x=n-4;_x>=0;_x-=4) *(uint32 *)&(d)[_x]=c;}
void *FCEU_malloc(uint32 size); // initialized to 0
void *FCEU_gmalloc(uint32 size); // used by boards for WRAM etc, initialized to 0 (default) or other via RAMInitOption
void FCEU_gfree(void *ptr);
void FCEU_free(void *ptr);
void FCEU_memmove(void *d, void *s, uint32 l);
//returns a buffer initialized to 0
void *FCEU_malloc(uint32 size);
// wrapper for debugging when its needed, otherwise act like
// normal malloc/free
//returns a buffer, with jumbled initial contents
//used by boards for WRAM etc, initialized to 0 (default) or other via RAMInitOption
void *FCEU_gmalloc(uint32 size);
//free memory allocated with FCEU_gmalloc
void FCEU_gfree(void *ptr);
//returns an aligned buffer, initialized to 0
//the alignment will default to the largest thing you could ever sensibly want for massively aligned cache friendly buffers
void *FCEU_amalloc(size_t size, size_t alignment = 256);
//frees memory allocated with FCEU_amalloc
void FCEU_afree(void* ptr);
//free memory allocated with FCEU_malloc
void FCEU_free(void *ptr);
//reallocate memory allocated with FCEU_malloc
void* FCEU_realloc(void* ptr, size_t size);
//don't use these. change them if you find them.
void *FCEU_dmalloc(uint32 size);
//don't use these. change them if you find them.
void FCEU_dfree(void *ptr);
//aborts the process for fatal errors
void FCEU_abort(const char* message = nullptr);
+71
View File
@@ -0,0 +1,71 @@
// mutex.cpp
#include <cstdio>
#include "mutex.h"
namespace FCEU
{
//-----------------------------------------------------
// Cross platform mutex
// __QT_DRIVER__ multi-threaded application that uses Qt mutex implementation for synchronization
// __WIN_DRIVER__ is single thread application so sync methods are unimplemented.
//-----------------------------------------------------
mutex::mutex(void)
{
#ifdef __QT_DRIVER__
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
mtx = new QRecursiveMutex();
#else
mtx = new QMutex( QMutex::Recursive );
#endif
#endif
}
mutex::~mutex(void)
{
#ifdef __QT_DRIVER__
if (mtx)
{
delete mtx;
mtx = nullptr;
}
#endif
}
void mutex::lock(void)
{
#ifdef __QT_DRIVER__
mtx->lock();
#endif
}
void mutex::unlock(void)
{
#ifdef __QT_DRIVER__
mtx->unlock();
#endif
}
//-----------------------------------------------------
// Scoped AutoLock
//-----------------------------------------------------
autoScopedLock::autoScopedLock( mutex *mtx )
{
m = mtx;
if (m)
{
m->lock();
}
}
autoScopedLock::~autoScopedLock(void)
{
if (m)
{
m->unlock();
}
}
};
+41
View File
@@ -0,0 +1,41 @@
// mutex.h
#ifdef __QT_DRIVER__
#include <QMutex>
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
#include <QRecursiveMutex>
#endif
#endif
namespace FCEU
{
class mutex
{
public:
mutex(void);
~mutex(void);
void lock(void);
void unlock(void);
private:
#ifdef __QT_DRIVER__
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
QRecursiveMutex *mtx;
#else
QMutex *mtx;
#endif
#endif
};
class autoScopedLock
{
public:
autoScopedLock( mutex *mtx );
~autoScopedLock(void);
private:
mutex *m;
};
};
+1 -1
View File
@@ -194,7 +194,7 @@ static const struct Base64Table
data[62] = '+'; // 62
data[63] = '/'; // 63
// create ascii->value mapping (but due to overlap, write it to highbit region)
for(a=0; a<64; ++a) data[data[a]^0x80] = a; //
for(a=0; a<64; ++a) data[data[a]^0x80] = static_cast<unsigned char>(a); //
data[((unsigned char)'=') ^ 0x80] = 0;
}
unsigned char operator[] (size_t pos) const { return data[pos]; }
+2 -2
View File
@@ -62,14 +62,14 @@
#define FCEU_VERSION_MAJOR 2
#define FCEU_VERSION_MINOR 6
#define FCEU_VERSION_PATCH 3
#define FCEU_VERSION_PATCH 5
#define FCEU_VERSION_NUMERIC ( (FCEU_VERSION_MAJOR*10000) + (FCEU_VERSION_MINOR*100) + (FCEU_VERSION_PATCH) )
#define FCEU_VERSION_MAJOR_DECODE(x) ( (x / 10000) )
#define FCEU_VERSION_MINOR_DECODE(x) ( (x / 100) % 100 )
#define FCEU_VERSION_PATCH_DECODE(x) (x % 100)
#define FCEU_VERSION_STRING "2.6.3" FCEU_SUBVERSION_STRING FCEU_FEATURE_STRING FCEU_COMPILER
#define FCEU_VERSION_STRING "2.6.5" FCEU_SUBVERSION_STRING FCEU_FEATURE_STRING FCEU_COMPILER
#define FCEU_NAME_AND_VERSION FCEU_NAME " " FCEU_VERSION_STRING
#endif
+15 -25
View File
@@ -91,19 +91,19 @@ void FCEU_KillVirtualVideo(void)
{
if ( XBuf )
{
FCEU_free(XBuf); XBuf = NULL;
FCEU_afree(XBuf); XBuf = NULL;
}
if ( XBackBuf )
{
FCEU_free(XBackBuf); XBackBuf = NULL;
FCEU_afree(XBackBuf); XBackBuf = NULL;
}
if ( XDBuf )
{
FCEU_free(XDBuf); XDBuf = NULL;
FCEU_afree(XDBuf); XDBuf = NULL;
}
if ( XDBackBuf )
{
FCEU_free(XDBackBuf); XDBackBuf = NULL;
FCEU_afree(XDBackBuf); XDBackBuf = NULL;
}
//printf("Video Core Cleanup\n");
}
@@ -116,32 +116,22 @@ void FCEU_KillVirtualVideo(void)
int FCEU_InitVirtualVideo(void)
{
//Some driver code may allocate XBuf externally.
//256 bytes per scanline, * 240 scanline maximum, +16 for alignment,
//256 bytes per scanline, * 240 scanline maximum
if(XBuf)
return 1;
XBuf = (u8*)FCEU_malloc(256 * 256 + 16);
XBackBuf = (u8*)FCEU_malloc(256 * 256 + 16);
XDBuf = (u8*)FCEU_malloc(256 * 256 + 16);
XDBackBuf = (u8*)FCEU_malloc(256 * 256 + 16);
if(!XBuf || !XBackBuf || !XDBuf || !XDBackBuf)
{
return 0;
}
XBuf = (u8*)FCEU_amalloc(256 * 256);
XBackBuf = (u8*)FCEU_amalloc(256 * 256);
XDBuf = (u8*)FCEU_amalloc(256 * 256);
XDBackBuf = (u8*)FCEU_amalloc(256 * 256);
xbsave = XBuf;
if( sizeof(uint8*) == 4 )
{
uintptr_t m = (uintptr_t)XBuf;
m = ( 8 - m) & 7;
XBuf+=m;
}
memset(XBuf,128,256*256);
memset(XBackBuf,128,256*256);
memset(XBuf,128,256*256);
memset(XBackBuf,128,256*256);
memset(XDBuf,0,256*256);
memset(XDBackBuf,0,256*256);
return 1;
}
@@ -400,7 +390,7 @@ void snapAVI()
FCEUI_AviVideoUpdate(XBuf);
}
void FCEU_DispMessageOnMovie(const char *format, ...)
void FCEU_DispMessageOnMovie( __FCEU_PRINTF_FORMAT const char *format, ...)
{
va_list ap;
@@ -419,7 +409,7 @@ void FCEU_DispMessageOnMovie(const char *format, ...)
guiMessage.howlong = 0;
}
void FCEU_DispMessage(const char *format, int disppos=0, ...)
void FCEU_DispMessage( __FCEU_PRINTF_FORMAT const char *format, int disppos=0, ...)
{
va_list ap;
@@ -432,7 +422,7 @@ void FCEU_DispMessage(const char *format, int disppos=0, ...)
vsnprintf(temp,sizeof(temp),format,ap);
va_end(ap);
strcat(temp, "\n");
FCEU_printf(temp);
FCEU_printf("%s",temp);
if ( vidGuiMsgEna )
{
+10
View File
@@ -7,10 +7,20 @@ int SaveSnapshot(char[]);
void ResetScreenshotsCounter();
uint32 GetScreenPixel(int x, int y, bool usebackup);
int GetScreenPixelPalette(int x, int y, bool usebackup);
//in case we need more flags in the future we can change the size here
//bit0 : monochrome bit
//bit5 : emph red
//bit6 : emph green
//bit7 : emph blue
typedef uint8 xfbuf_t;
extern uint8 *XBuf;
extern uint8 *XBackBuf;
extern uint8 *XDBuf;
extern uint8 *XDBackBuf;
extern xfbuf_t *XFBuf;
extern int ClipSidesOffset;
struct GUIMESSAGE
+168 -114
View File
@@ -26,35 +26,23 @@
#include "vsuni.h"
#include "state.h"
#include "driver.h"
#include "cart.h"
#include "ines.h"
#include <cstring>
#include <cstdio>
#define IOPTION_GUN 0x1
#define IOPTION_SWAPDIRAB 0x2
#define IOPTION_PREDIP 0x10
typedef struct {
const char *name;
uint64 md5partial;
int mapper;
int mirroring;
int ppu;
int ioption;
int predip;
} VSUNIENTRY;
VSUNIENTRY *curvs;
static uint8 DIPS = 0;
static int DIPS_howlong = 0;
uint8 vsdip = 0;
void FCEUI_VSUniToggleDIPView(void) {
DIPS = !DIPS;
}
void FCEU_VSUniToggleDIP(int w) {
if (GameInfo->type != GIT_VSUNI) {
FCEU_DispMessage("Not Vs. System; toggle DIP switch.", 0);
return;
}
vsdip ^= 1 << w;
DIPS_howlong = 180;
FCEU_DispMessage("DIP switch %d is %s.", 0, w, vsdip & (1 << w) ? "on" : "off");
}
void FCEUI_VSUniSetDIP(int w, int state) {
@@ -66,20 +54,19 @@ uint8 FCEUI_VSUniGetDIPs(void) {
return(vsdip);
}
static uint8 secdata[2][32] =
static uint8 secdata_tko[32] =
{
{
0xff, 0xbf, 0xb7, 0x97, 0x97, 0x17, 0x57, 0x4f,
0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, 0x94, 0x14,
0x56, 0x4e, 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90,
0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00
},
{
0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00,
0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}
0xff, 0xbf, 0xb7, 0x97, 0x97, 0x17, 0x57, 0x4f,
0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, 0x94, 0x14,
0x56, 0x4e, 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90,
0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00
};
static uint8 secdata_rbi[32] =
{
0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00,
0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static uint8 *secptr;
@@ -93,24 +80,30 @@ static DECLFR(VSSecRead) {
}
return(0x00);
}
uint8 coinon = 0;
void FCEU_VSUniCoin(void) {
coinon = 6;
uint8 coinon = 0;
uint8 coinon2 = 0;
uint8 service = 0;
void FCEU_VSUniCoin(uint8 slot) {
if (GameInfo->type != GIT_VSUNI)
FCEU_DispMessage("Not Vs. System; can't insert coin.", 0);
else {
switch (slot) {
case 0:
coinon = 6; break;
case 1:
coinon2 = 6; break;
}
}
}
static int curppu;
static int64 curmd5;
#define RP2C04_001 1
#define RP2C04_002 2
#define RP2C04_003 3
#define RP2C05_004 4
#define RCP2C03B 5
#define RC2C05_01 6
#define RC2C05_02 7
#define RC2C05_03 8
#define RC2C05_04 9
void FCEU_VSUniService() {
if (GameInfo->type != GIT_VSUNI)
FCEU_DispMessage("Not Vs. System; can't press service button.", 0);
else
service = 6;
}
static readfunc OldReadPPU;
static writefunc OldWritePPU[2];
@@ -126,10 +119,10 @@ static DECLFR(A2002_Topgun) {
static DECLFR(A2002_MBJ) { // Mighty Bomb Jack
return((OldReadPPU(A) & ~0x3F) | 0x3D);
}
static DECLFW(B2000_2001_2C05) {
OldWritePPU[(A & 1) ^ 1](A ^ 1, V);
}
static uint8 xevselect = 0;
static DECLFR(XevRead) {
if (A == 0x54FF) {
@@ -146,7 +139,7 @@ static DECLFR(XevRead) {
}
void FCEU_VSUniSwap(uint8 *j0, uint8 *j1) {
if (curvs->ioption & IOPTION_SWAPDIRAB) {
if (GameInfo->vs_cswitch) {
uint16 t = *j0;
*j0 = (*j0 & 0xC) | (*j1 & 0xF3);
*j1 = (*j1 & 0xC) | (t & 0xF3);
@@ -154,28 +147,39 @@ void FCEU_VSUniSwap(uint8 *j0, uint8 *j1) {
}
void FCEU_VSUniPower(void) {
coinon = 0;
coinon = coinon2 = service = 0;
VSindex = 0;
if (secptr)
SetReadHandler(0x5e00, 0x5e01, VSSecRead);
if (curppu == RC2C05_04) {
switch (GameInfo->vs_ppu) {
case GIPPU_RP2C04_0001:
case GIPPU_RP2C04_0002:
case GIPPU_RP2C04_0003:
case GIPPU_RP2C04_0004:
default_palette_selection = GameInfo->vs_ppu;
break;
default:
// nothing todo
break;
}
if (GameInfo->vs_ppu == GIPPU_RC2C05_04) {
OldReadPPU = GetReadHandler(0x2002);
SetReadHandler(0x2002, 0x2002, A2002_Topgun);
} else if (curppu == RC2C05_03) {
} else if (GameInfo->vs_ppu == GIPPU_RC2C05_03) {
OldReadPPU = GetReadHandler(0x2002);
SetReadHandler(0x2002, 0x2002, A2002_Gumshoe);
} else if (curppu == RC2C05_02) {
} else if (GameInfo->vs_ppu == GIPPU_RC2C05_02) {
OldReadPPU = GetReadHandler(0x2002);
SetReadHandler(0x2002, 0x2002, A2002_MBJ);
}
if (curppu == RC2C05_04 || curppu == RC2C05_01 || curppu == RC2C05_03 || curppu == RC2C05_02) {
if (GameInfo->vs_ppu == GIPPU_RC2C05_01 || GameInfo->vs_ppu == GIPPU_RC2C05_02 || GameInfo->vs_ppu == GIPPU_RC2C05_03 || GameInfo->vs_ppu == GIPPU_RC2C05_04) {
OldWritePPU[0] = GetWriteHandler(0x2000);
OldWritePPU[1] = GetWriteHandler(0x2001);
SetWriteHandler(0x2000, 0x2001, B2000_2001_2C05);
}
if (curmd5 == 0x2d396247cf58f9faLL) { /* Super Xevious */
if (GameInfo->vs_type == EGIVS_XEVIOUS) { /* Super Xevious */
SetReadHandler(0x5400, 0x57FF, XevRead);
}
}
@@ -252,47 +256,47 @@ RC2C05-04:
VSUNIENTRY VSUniGames[] =
{
{ "Baseball", 0x691d4200ea42be45ULL, 99, 2, RP2C04_001, 0 },
{ "Battle City", 0x8540949d74c4d0ebULL, 99, 2, RP2C04_001, 0 },
{ "Battle City(Bootleg)", 0x8093cbe7137ac031ULL, 99, 2, RP2C04_001, 0 },
{ "Baseball", 0x691d4200ea42be45ULL, 99, 2, GIPPU_RP2C04_0001, 0, 0, EGIVS_NORMAL },
{ "Battle City", 0x8540949d74c4d0ebULL, 99, 2, GIPPU_RP2C04_0001, 0, 0, EGIVS_NORMAL },
{ "Battle City(Bootleg)", 0x8093cbe7137ac031ULL, 99, 2, GIPPU_RP2C04_0001, 0, 0, EGIVS_NORMAL },
{ "Clu Clu Land", 0x1b8123218f62b1eeULL, 99, 2, RP2C05_004, IOPTION_SWAPDIRAB },
{ "Dr Mario", 0xe1af09c477dc0081ULL, 1, 0, RP2C04_003, IOPTION_SWAPDIRAB },
{ "Duck Hunt", 0x47735d1e5f1205bbULL, 99, 2, RCP2C03B, IOPTION_GUN },
{ "Excitebike", 0x3dcd1401bcafde77ULL, 99, 2, RP2C04_003, 0 },
{ "Excitebike (J)", 0x7ea51c9d007375f0ULL, 99, 2, RP2C05_004, 0 },
{ "Freedom Force", 0xed96436bd1b5e688ULL, 4, 0, RP2C04_001, IOPTION_GUN }, /* Wrong color in game select screen? */
{ "Stroke and Match Golf", 0x612325606e82bc66ULL, 99, 2, RP2C04_002, IOPTION_SWAPDIRAB | IOPTION_PREDIP, 0x01 },
{ "Clu Clu Land", 0x1b8123218f62b1eeULL, 99, 2, GIPPU_RP2C04_0004, VS_OPTION_SWAPDIRAB, 0, EGIVS_NORMAL },
{ "Dr Mario", 0xe1af09c477dc0081ULL, 1, 0, GIPPU_RP2C04_0003, VS_OPTION_SWAPDIRAB, 0, EGIVS_NORMAL },
{ "Duck Hunt", 0x47735d1e5f1205bbULL, 99, 2, GIPPU_RC2C03B, VS_OPTION_GUN, 0, EGIVS_NORMAL },
{ "Excitebike", 0x3dcd1401bcafde77ULL, 99, 2, GIPPU_RP2C04_0003, 0, 0, EGIVS_NORMAL },
{ "Excitebike (J)", 0x7ea51c9d007375f0ULL, 99, 2, GIPPU_RP2C04_0004, 0, 0, EGIVS_NORMAL },
{ "Freedom Force", 0xed96436bd1b5e688ULL, 4, 0, GIPPU_RP2C04_0001, VS_OPTION_GUN, 0, EGIVS_NORMAL }, /* Wrong color in game select screen? */
{ "Stroke and Match Golf", 0x612325606e82bc66ULL, 99, 2, GIPPU_RP2C04_0002, VS_OPTION_SWAPDIRAB | VS_OPTION_PREDIP, 0x01, EGIVS_NORMAL },
{ "Goonies", 0xb4032d694e1d2733ULL, 151, 1, RP2C04_003, 0 },
{ "Gradius", 0x50687ae63bdad976ULL, 151, 1, RP2C04_001, IOPTION_SWAPDIRAB },
{ "Gumshoe", 0x87161f8ee37758d3ULL, 99, 2, RC2C05_03, IOPTION_GUN },
{ "Gumshoe", 0xb8500780bf69ce29ULL, 99, 2, RC2C05_03, IOPTION_GUN },
{ "Hogan's Alley", 0xd78b7f0bb621fb45ULL, 99, 2, RP2C04_001, IOPTION_GUN },
{ "Ice Climber", 0xd21e999513435e2aULL, 99, 2, RP2C05_004, IOPTION_SWAPDIRAB },
{ "Ladies Golf", 0x781b24be57ef6785ULL, 99, 2, RP2C04_002, IOPTION_SWAPDIRAB | IOPTION_PREDIP, 0x1 },
{ "Goonies", 0xb4032d694e1d2733ULL, 151, 1, GIPPU_RP2C04_0003, 0, 0, EGIVS_NORMAL },
{ "Gradius", 0x50687ae63bdad976ULL, 151, 1, GIPPU_RP2C04_0001, VS_OPTION_SWAPDIRAB, 0, EGIVS_NORMAL },
{ "Gumshoe", 0x87161f8ee37758d3ULL, 99, 2, GIPPU_RC2C05_03, VS_OPTION_GUN, 0, EGIVS_NORMAL },
{ "Gumshoe", 0xb8500780bf69ce29ULL, 99, 2, GIPPU_RC2C05_03, VS_OPTION_GUN, 0, EGIVS_NORMAL },
{ "Hogan's Alley", 0xd78b7f0bb621fb45ULL, 99, 2, GIPPU_RP2C04_0001, VS_OPTION_GUN, 0, EGIVS_NORMAL },
{ "Ice Climber", 0xd21e999513435e2aULL, 99, 2, GIPPU_RP2C04_0004, VS_OPTION_SWAPDIRAB, 0, EGIVS_NORMAL },
{ "Ladies Golf", 0x781b24be57ef6785ULL, 99, 2, GIPPU_RP2C04_0002, VS_OPTION_SWAPDIRAB | VS_OPTION_PREDIP, 0x1, EGIVS_NORMAL },
{ "Mach Rider", 0x015672618af06441ULL, 99, 2, RP2C04_002, 0 },
{ "Mach Rider (J)", 0xa625afb399811a8aULL, 99, 2, RP2C04_001, 0 },
{ "Mighty Bomb Jack", 0xe6a89f4873fac37bULL, 0, 2, RC2C05_02, 0 },
{ "Ninja Jajamaru Kun", 0xb26a2c31474099c0ULL, 99, 2, RC2C05_01, IOPTION_SWAPDIRAB },
{ "Pinball", 0xc5f49d3de7f2e9b8ULL, 99, 2, RP2C04_001, IOPTION_PREDIP, 0x01 },
{ "Pinball (J)", 0x66ab1a3828cc901cULL, 99, 2, RCP2C03B, IOPTION_PREDIP, 0x1 },
{ "Platoon", 0x160f237351c19f1fULL, 68, 1, RP2C04_001, 0 },
{ "RBI Baseball", 0x6a02d345812938afULL, 4, 1, RP2C04_001, IOPTION_SWAPDIRAB },
{ "Soccer", 0xd4e7a9058780eda3ULL, 99, 2, RP2C04_003, IOPTION_SWAPDIRAB },
{ "Star Luster", 0x8360e134b316d94cULL, 99, 2, RCP2C03B, 0 },
{ "Stroke and Match Golf (J)", 0x869bb83e02509747ULL, 99, 2, RCP2C03B, IOPTION_SWAPDIRAB | IOPTION_PREDIP, 0x1 },
{ "Super Sky Kid", 0x78d04c1dd4ec0101ULL, 4, 1, RCP2C03B, IOPTION_SWAPDIRAB | IOPTION_PREDIP, 0x20 },
{ "Mach Rider", 0x015672618af06441ULL, 99, 2, GIPPU_RP2C04_0002, 0, 0, EGIVS_NORMAL },
{ "Mach Rider (J)", 0xa625afb399811a8aULL, 99, 2, GIPPU_RP2C04_0001, 0, 0, EGIVS_NORMAL },
{ "Mighty Bomb Jack", 0xe6a89f4873fac37bULL, 0, 2, GIPPU_RC2C05_02, 0, 0, EGIVS_NORMAL },
{ "Ninja Jajamaru Kun", 0xb26a2c31474099c0ULL, 99, 2, GIPPU_RC2C05_01, VS_OPTION_SWAPDIRAB, 0, EGIVS_NORMAL },
{ "Pinball", 0xc5f49d3def2e9b8ULL, 99, 2, GIPPU_RP2C04_0001, VS_OPTION_PREDIP, 0x01, EGIVS_NORMAL },
{ "Pinball (J)", 0x66ab1a3828cc901cULL, 99, 2, GIPPU_RC2C03B, VS_OPTION_PREDIP, 0x01, EGIVS_NORMAL },
{ "Platoon", 0x160f237351c19f1fULL, 68, 1, GIPPU_RP2C04_0001, 0, 0, EGIVS_NORMAL },
{ "RBI Baseball", 0x6a02d345812938afULL, 4, 1, GIPPU_RP2C04_0001, VS_OPTION_SWAPDIRAB, 0, EGIVS_RBI },
{ "Soccer", 0xd4e7a9058780eda3ULL, 99, 2, GIPPU_RP2C04_0003, VS_OPTION_SWAPDIRAB, 0, EGIVS_NORMAL },
{ "Star Luster", 0x8360e134b316d94cULL, 99, 2, GIPPU_RC2C03B, 0, 0, EGIVS_NORMAL },
{ "Stroke and Match Golf (J)", 0x869bb83e02509747ULL, 99, 2, GIPPU_RC2C03B, VS_OPTION_SWAPDIRAB | VS_OPTION_PREDIP, 0x01, EGIVS_NORMAL },
{ "Super Sky Kid", 0x78d04c1dd4ec0101ULL, 4, 1, GIPPU_RC2C03B, VS_OPTION_SWAPDIRAB | VS_OPTION_PREDIP, 0x20, EGIVS_NORMAL },
{ "Super Xevious", 0x2d396247cf58f9faULL, 206, 0, RP2C04_001, 0 },
{ "Tetris", 0x531a5e8eea4ce157ULL, 99, 2, RCP2C03B, IOPTION_PREDIP, 0x20 },
{ "Top Gun", 0xf1dea36e6a7b531dULL, 2, 0, RC2C05_04, 0 },
{ "VS Castlevania", 0x92fd6909c81305b9ULL, 2, 1, RP2C04_002, 0 },
{ "VS Slalom", 0x4889b5a50a623215ULL, 0, 1, RP2C04_002, 0 },
{ "VS Super Mario Bros", 0x39d8cfa788e20b6cULL, 99, 2, RP2C05_004, 0 },
{ "VS Super Mario Bros [a1]", 0xfc182e5aefbce14dULL, 99, 2, RP2C05_004, 0 },
{ "VS TKO Boxing", 0x6e1ee06171d8ce3aULL, 4, 1, RP2C04_003, IOPTION_PREDIP, 0x00 },
{ "Super Xevious", 0x2d396247cf58f9faULL, 206, 0, GIPPU_RP2C04_0001, 0, 0, EGIVS_XEVIOUS },
{ "Tetris", 0x531a5e8eea4ce157ULL, 99, 2, GIPPU_RC2C03B, VS_OPTION_PREDIP, 0x20, EGIVS_NORMAL },
{ "Top Gun", 0xf1dea36e6a7b531dULL, 2, 0, GIPPU_RC2C05_04, 0, 0, EGIVS_NORMAL },
{ "VS Castlevania", 0x92fd6909c81305b9ULL, 2, 1, GIPPU_RP2C04_0002, 0, 0, EGIVS_NORMAL },
{ "VS Slalom", 0x4889b5a50a623215ULL, 0, 1, GIPPU_RP2C04_0002, 0, 0, EGIVS_NORMAL },
{ "VS Super Mario Bros", 0x39d8cfa788e20b6cULL, 99, 2, GIPPU_RP2C04_0004, 0, 0, EGIVS_NORMAL },
{ "VS Super Mario Bros [a1]", 0xfc182e5aefbce14dULL, 99, 2, GIPPU_RP2C04_0004, 0, 0, EGIVS_NORMAL },
{ "VS TKO Boxing", 0x6e1ee06171d8ce3aULL, 4, 1, GIPPU_RP2C04_0003, VS_OPTION_PREDIP, 0x00, EGIVS_TKO },
{ 0 }
};
@@ -301,36 +305,84 @@ void FCEU_VSUniCheck(uint64 md5partial, int *MapperNo, uint8 *Mirroring) {
while (vs->name) {
if (md5partial == vs->md5partial) {
if (vs->ppu < RCP2C03B) default_palette_selection = vs->ppu;
*MapperNo = vs->mapper;
*Mirroring = vs->mirroring;
GameInfo->type = GIT_VSUNI;
GameInfo->cspecial = SIS_VSUNISYSTEM;
GameInfo->inputfc = SIFC_NONE;
curppu = vs->ppu;
curmd5 = md5partial;
int32 tofix = 0;
if (*MapperNo != vs->mapper) {
tofix |= 1;
*MapperNo = vs->mapper;
}
if (*Mirroring != vs->mirroring) {
tofix |= 2;
*Mirroring = vs->mirroring;
}
if (GameInfo->type != GIT_VSUNI) {
tofix |= 4;
GameInfo->type = GIT_VSUNI;
}
if (GameInfo->vs_type != vs->type) {
tofix |= 8;
GameInfo->vs_type = vs->type;
}
if (vs->ppu && (GameInfo->vs_ppu != vs->ppu)) {
tofix |= 16;
GameInfo->vs_ppu = vs->ppu;
}
secptr = 0;
switch (GameInfo->vs_type)
{
static int64 tko = 0x6e1ee06171d8ce3aULL, rbi = 0x6a02d345812938afULL;
if (md5partial == tko)
secptr = secdata[0];
if (md5partial == rbi)
secptr = secdata[1];
case EGIVS_RBI: secptr = secdata_rbi; break;
case EGIVS_TKO: secptr = secdata_tko; break;
default: secptr = 0; break;
}
vsdip = 0x0;
if (vs->ioption & IOPTION_PREDIP) {
if (vs->ioption & VS_OPTION_PREDIP) {
vsdip = vs->predip;
}
if (vs->ioption & IOPTION_GUN) {
if ((vs->ioption & VS_OPTION_GUN) && !head.expansion) {
tofix |= 32;
GameInfo->input[0] = SI_ZAPPER;
GameInfo->input[1] = SI_NONE;
} else {
GameInfo->input[0] = GameInfo->input[1] = SI_GAMEPAD;
GameInfo->inputfc = SIFC_NONE;
}
curvs = vs;
else if (!head.expansion) {
GameInfo->input[0] = GameInfo->input[1] = SI_GAMEPAD;
GameInfo->inputfc = SIFC_NONE;
}
if ((vs->ioption & VS_OPTION_SWAPDIRAB) && !GameInfo->vs_cswitch) {
tofix |= 64;
GameInfo->vs_cswitch = 1;
}
if (tofix) {
char gigastr[768];
strcpy(gigastr, "The iNES header contains incorrect information. For now, the information will be corrected in RAM. ");
if (tofix & 4) {
sprintf(gigastr + strlen(gigastr), "Game type should be set to Vs. System. ");
}
if (tofix & 1)
sprintf(gigastr + strlen(gigastr), "The mapper number should be set to %d. ", *MapperNo);
if (tofix & 2) {
const char* mstr[3] = { "Horizontal", "Vertical", "Four-screen" };
sprintf(gigastr + strlen(gigastr), "Mirroring should be set to \"%s\". ", mstr[vs->mirroring & 3]);
}
if (tofix & 8) {
const char* mstr[4] = { "Normal", "RBI Baseball protection", "TKO Boxing protection", "Super Xevious protection"};
sprintf(gigastr + strlen(gigastr), "Vs. System type should be set to \"%s\". ", mstr[vs->type]);
}
if (tofix & 16)
{
const char* mstr[10] = { "Default", "RP2C04-0001", "RP2C04-0002", "RP2C04-0003", "RP2C04-0004", "RC2C03B", "RC2C05-01", "RC2C05-02" , "RC2C05-03" , "RC2C05-04" };
sprintf(gigastr + strlen(gigastr), "Vs. System PPU should be set to \"%s\". ", mstr[vs->ppu]);
}
if (tofix & 32)
sprintf(gigastr + strlen(gigastr), "The controller type should be set to zapper. ");
if (tofix & 64)
sprintf(gigastr + strlen(gigastr), "The controllers should be swapped. ");
strcat(gigastr, "\n");
FCEU_printf("%s", gigastr);
}
return;
}
vs++;
@@ -341,7 +393,7 @@ void FCEU_VSUniDraw(uint8 *XBuf) {
uint32 *dest;
int y, x;
if (!DIPS) return;
if (DIPS_howlong-- <= 0) return;
dest = (uint32*)(XBuf + 256 * 12 + 164);
for (y = 24; y; y--, dest += (256 - 72) >> 2) {
@@ -371,6 +423,8 @@ void FCEU_VSUniDraw(uint8 *XBuf) {
SFORMAT FCEUVSUNI_STATEINFO[] = {
{ &vsdip, 1, "vsdp" },
{ &coinon, 1, "vscn" },
{ &coinon2, 1, "vsc2" },
{ &service, 1, "vssv" },
{ &VSindex, 1, "vsin" },
{ 0 }
};
+19 -1
View File
@@ -1,7 +1,25 @@
enum IOPTION {
VS_OPTION_GUN = 0x1,
VS_OPTION_SWAPDIRAB = 0x2,
VS_OPTION_PREDIP = 0x10,
};
typedef struct {
const char* name;
uint64 md5partial;
int mapper;
int mirroring;
EGIPPU ppu;
int ioption;
int predip;
EGIVS type;
} VSUNIENTRY;
void FCEU_VSUniPower(void);
void FCEU_VSUniCheck(uint64 md5partial, int *, uint8 *);
void FCEU_VSUniDraw(uint8 *XBuf);
void FCEU_VSUniToggleDIP(int); /* For movies and netplay */
void FCEU_VSUniCoin(void);
void FCEU_VSUniCoin(uint8 slot);
void FCEU_VSUniService();
void FCEU_VSUniSwap(uint8 *j0, uint8 *j1);
+2 -2
View File
@@ -318,8 +318,8 @@ static uint8 ZNTable[256];
#define LD_ZP(op) {uint8 A; uint8 x; GetZP(A); x=RdRAM(A); op; break;}
#define LD_ZPX(op) {uint8 A; uint8 x; GetZPI(A,_X); x=RdRAM(A); op; break;}
#define LD_ZPY(op) {uint8 A; uint8 x; GetZPI(A,_Y); x=RdRAM(A); op; break;}
#define LD_AB(op) {unsigned int A; uint8 x; GetAB(A); x=RdMem(A); op; break; }
#define LD_ABI(reg,op) {unsigned int A; uint8 x; GetABIRD(A,reg); x=RdMem(A); op; break;}
#define LD_AB(op) {unsigned int A; FCEU_MAYBE_UNUSED uint8 x; GetAB(A); x=RdMem(A); op; break; }
#define LD_ABI(reg,op) {unsigned int A; FCEU_MAYBE_UNUSED uint8 x; GetABIRD(A,reg); x=RdMem(A); op; break;}
#define LD_ABX(op) LD_ABI(_X,op)
#define LD_ABY(op) LD_ABI(_Y,op)
#define LD_IX(op) {unsigned int A; uint8 x; GetIX(A); x=RdMem(A); op; break;}