diff --git a/pipelines/linux_build.sh b/pipelines/linux_build.sh
index 4d8e7474..77922b5e 100755
--- a/pipelines/linux_build.sh
+++ b/pipelines/linux_build.sh
@@ -98,7 +98,7 @@ sudo apt-get --assume-yes install libavcodec-dev
sudo apt-get --assume-yes install libavformat-dev
sudo apt-get --assume-yes install libavutil-dev
sudo apt-get --assume-yes install libswscale-dev
-sudo apt-get --assume-yes install libavresample-dev
+sudo apt-get --assume-yes install libswresample-dev
# Install cppcheck
echo '****************************************'
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 60dba054..8ef081d4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -85,6 +85,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)
@@ -578,7 +587,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 .
-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 +622,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}
diff --git a/src/boards/235.cpp b/src/boards/235.cpp
index 98ce11bb..aba619ad 100644
--- a/src/boards/235.cpp
+++ b/src/boards/235.cpp
@@ -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;
}
diff --git a/src/boards/datalatch.cpp b/src/boards/datalatch.cpp
index 026354d3..69803a9c 100644
--- a/src/boards/datalatch.cpp
+++ b/src/boards/datalatch.cpp
@@ -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) {
diff --git a/src/cart.h b/src/cart.h
index e78c87ea..ecc67948 100644
--- a/src/cart.h
+++ b/src/cart.h
@@ -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
diff --git a/src/cheat.cpp b/src/cheat.cpp
index 708fe3a1..8ae0e985 100644
--- a/src/cheat.cpp
+++ b/src/cheat.cpp
@@ -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)
@@ -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;
diff --git a/src/cheat.h b/src/cheat.h
index 82037fc7..3e11e9d3 100644
--- a/src/cheat.h
+++ b/src/cheat.h
@@ -42,7 +42,7 @@ typedef struct {
struct CHEATF {
struct CHEATF *next;
- char *name;
+ std::string name;
uint16 addr;
uint8 val;
int compare; /* -1 for no compare. */
diff --git a/src/driver.h b/src/driver.h
index e82f7445..6f183f06 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -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);
diff --git a/src/drivers/Qt/AviRecord.cpp b/src/drivers/Qt/AviRecord.cpp
index f6a096a9..97652c41 100644
--- a/src/drivers/Qt/AviRecord.cpp
+++ b/src/drivers/Qt/AviRecord.cpp
@@ -841,6 +841,8 @@ static void log_callback( void *avcl, int level, const char *fmt, va_list vl)
va_copy( vl2, vl );
vfprintf( avLogFp, fmt, vl2 );
+
+ va_end(vl2);
}
av_log_default_callback( avcl, level, fmt, vl );
diff --git a/src/drivers/Qt/AviRiffViewer.cpp b/src/drivers/Qt/AviRiffViewer.cpp
index 6d1e6afa..2f9b28c3 100644
--- a/src/drivers/Qt/AviRiffViewer.cpp
+++ b/src/drivers/Qt/AviRiffViewer.cpp
@@ -848,9 +848,11 @@ int AviRiffViewerDialog::processChunk( AviRiffTreeItem *item )
}
else if ( strcmp( strhType, "auds" ) == 0 )
{
- data.malloc( item->getSize()+8 );
+ size_t dataSize = item->getSize()+8;
- avi->getChunkData( item->filePos(), data.buf, item->getSize()+8 );
+ data.malloc( dataSize );
+
+ avi->getChunkData( item->filePos(), data.buf, dataSize );
sprintf( stmp, "%c%c%c%c", data.buf[0], data.buf[1], data.buf[2], data.buf[3] );
@@ -907,13 +909,6 @@ int AviRiffViewerDialog::processChunk( AviRiffTreeItem *item )
twi->setText( 0, tr("nBitsPerSample") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
-
- sprintf( stmp, "%u", data.readU16(24) );
-
- twi = new QTreeWidgetItem();
- twi->setText( 0, tr("cbSize") );
- twi->setText( 2, tr(stmp) );
- item->addChild(twi);
}
}
else if ( isRiffTag( item->getFourcc(), &riffIdx ) )
diff --git a/src/drivers/Qt/CheatsConf.cpp b/src/drivers/Qt/CheatsConf.cpp
index f9af2ad1..79cc3c60 100644
--- a/src/drivers/Qt/CheatsConf.cpp
+++ b/src/drivers/Qt/CheatsConf.cpp
@@ -52,6 +52,9 @@ void openCheatDialog(QWidget *parent)
{
if (win != NULL)
{
+ win->activateWindow();
+ win->raise();
+ win->setFocus();
return;
}
win = new GuiCheatsDialog_t(parent);
@@ -198,6 +201,18 @@ GuiCheatsDialog_t::GuiCheatsDialog_t(QWidget *parent)
vbox1->addLayout(hbox);
+ hbox = new QHBoxLayout();
+ lbl = new QLabel(tr("Type:"));
+ typeEntry = new QComboBox();
+ typeEntry->addItem(tr("0: Periodic Set (Every Frame)"), 0 );
+ typeEntry->addItem(tr("1: Substitute/Freeze"), 1 );
+ typeEntry->setCurrentIndex(1);
+
+ hbox->addWidget(lbl,1);
+ hbox->addWidget(typeEntry,10);
+
+ vbox1->addLayout(hbox);
+
hbox = new QHBoxLayout();
addCheatBtn = new QPushButton(tr("Add"));
@@ -435,6 +450,8 @@ GuiCheatsDialog_t::GuiCheatsDialog_t(QWidget *parent)
setLayout(mainLayout);
+ modCheatBtn->setDefault(true);
+
connect(srchResetBtn, SIGNAL(clicked(void)), this, SLOT(resetSearchCallback(void)));
connect(knownValBtn, SIGNAL(clicked(void)), this, SLOT(knownValueCallback(void)));
connect(eqValBtn, SIGNAL(clicked(void)), this, SLOT(equalValueCallback(void)));
@@ -670,7 +687,7 @@ void GuiCheatsDialog_t::lessThanValueCallback(void)
FCEU_WRAPPER_UNLOCK();
}
//----------------------------------------------------------------------------
-int GuiCheatsDialog_t::activeCheatListCB(char *name, uint32 a, uint8 v, int c, int s, int type, void *data)
+int GuiCheatsDialog_t::activeCheatListCB(const char *name, uint32 a, uint8 v, int c, int s, int type, void *data)
{
QTreeWidgetItem *item;
char codeStr[32];
@@ -710,7 +727,7 @@ int GuiCheatsDialog_t::activeCheatListCB(char *name, uint32 a, uint8 v, int c, i
return 1;
}
//----------------------------------------------------------------------------
-static int activeCheatListCB(char *name, uint32 a, uint8 v, int c, int s, int type, void *data)
+static int activeCheatListCB(const char *name, uint32 a, uint8 v, int c, int s, int type, void *data)
{
return win->activeCheatListCB(name, a, v, c, s, type, data);
}
@@ -719,6 +736,8 @@ void GuiCheatsDialog_t::showActiveCheatList(bool redraw)
{
win = this;
+ enaCheats->setChecked(!globalCheatDisabled);
+
actvCheatRedraw = redraw;
if (redraw)
@@ -871,6 +890,7 @@ void GuiCheatsDialog_t::addActvCheat(void)
uint32 a = 0;
uint8 v = 0;
int c = -1;
+ int t = 1;
std::string name, cmpStr;
a = strtoul(cheatAddrEntry->displayText().toStdString().c_str(), NULL, 16);
@@ -890,8 +910,10 @@ void GuiCheatsDialog_t::addActvCheat(void)
name = cheatNameEntry->text().toStdString();
+ t = typeEntry->currentData().toInt();
+
FCEU_WRAPPER_LOCK();
- FCEUI_AddCheat(name.c_str(), a, v, c, 1);
+ FCEUI_AddCheat(name.c_str(), a, v, c, t);
FCEU_WRAPPER_UNLOCK();
showActiveCheatList(true);
@@ -921,6 +943,7 @@ void GuiCheatsDialog_t::deleteActvCheat(void)
cheatAddrEntry->setText(tr(""));
cheatValEntry->setText(tr(""));
cheatCmpEntry->setText(tr(""));
+ typeEntry->setCurrentIndex(0);
}
//----------------------------------------------------------------------------
void GuiCheatsDialog_t::updateCheatParameters(void)
@@ -969,9 +992,11 @@ void GuiCheatsDialog_t::updateCheatParameters(void)
//printf("Name: %s \n", name.c_str() );
+ type = typeEntry->currentData().toInt();
+
FCEU_WRAPPER_LOCK();
- FCEUI_SetCheat(row, name.c_str(), a, v, c, s, type);
+ FCEUI_SetCheat(row, &name, a, v, c, s, type);
FCEU_WRAPPER_UNLOCK();
@@ -983,7 +1008,7 @@ void GuiCheatsDialog_t::actvCheatItemClicked(QTreeWidgetItem *item, int column)
uint32 a = 0;
uint8 v = 0;
int c = -1, s = 0, type = 0;
- char *name = NULL;
+ std::string name;
char stmp[64];
int row = actvCheatList->indexOfTopLevelItem(item);
@@ -1021,14 +1046,9 @@ void GuiCheatsDialog_t::actvCheatItemClicked(QTreeWidgetItem *item, int column)
cheatCmpEntry->setText(tr(""));
}
- if (name != NULL)
- {
- cheatNameEntry->setText(tr(name));
- }
- else
- {
- cheatNameEntry->setText(tr(""));
- }
+ cheatNameEntry->setText(tr(name.c_str()));
+
+ typeEntry->setCurrentIndex(type);
}
//----------------------------------------------------------------------------
void GuiCheatsDialog_t::globalEnableCheats(int state)
diff --git a/src/drivers/Qt/CheatsConf.h b/src/drivers/Qt/CheatsConf.h
index 40b2836a..4eab63a9 100644
--- a/src/drivers/Qt/CheatsConf.h
+++ b/src/drivers/Qt/CheatsConf.h
@@ -30,7 +30,7 @@ public:
int addSearchResult(uint32_t a, uint8_t last, uint8_t current);
- int activeCheatListCB(char *name, uint32 a, uint8 v, int c, int s, int type, void *data);
+ int activeCheatListCB(const char *name, uint32 a, uint8 v, int c, int s, int type, void *data);
void showActiveCheatList(bool redraw);
@@ -67,6 +67,7 @@ protected:
QLineEdit *neValEntry;
QLineEdit *grValEntry;
QLineEdit *ltValEntry;
+ QComboBox *typeEntry;
QFont font;
int fontCharWidth;
diff --git a/src/drivers/Qt/ConsoleViewerGL.cpp b/src/drivers/Qt/ConsoleViewerGL.cpp
index c473895a..f836dd88 100644
--- a/src/drivers/Qt/ConsoleViewerGL.cpp
+++ b/src/drivers/Qt/ConsoleViewerGL.cpp
@@ -84,6 +84,7 @@ ConsoleViewGL_t::ConsoleViewGL_t(QWidget *parent)
setMinimumWidth( 256 );
setMinimumHeight( 224 );
setFocusPolicy(Qt::StrongFocus);
+ //setAttribute(Qt::WA_OpaquePaintEvent);
localBufSize = (4 * GL_NES_WIDTH) * (4 * GL_NES_HEIGHT) * sizeof(uint32_t);
@@ -272,6 +273,9 @@ void ConsoleViewGL_t::buildTextures(void)
GL_BGRA, GL_UNSIGNED_BYTE, 0 );
}
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
+ //glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//printf("Texture Built: %ix%i\n", w, h);
}
@@ -347,7 +351,7 @@ void ConsoleViewGL_t::initializeGL(void)
initializeOpenGLFunctions();
// Set up the rendering context, load shaders and other resources, etc.:
//QOpenGLFunctions *gl = QOpenGLContext::currentContext()->functions();
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
chkExtnsGL();
//printf("GL Init!\n");
@@ -666,6 +670,9 @@ void ConsoleViewGL_t::paintGL(void)
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
+ //glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if ( textureType == GL_TEXTURE_RECTANGLE )
{
diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp
index 02ad1059..fd5119c4 100644
--- a/src/drivers/Qt/ConsoleWindow.cpp
+++ b/src/drivers/Qt/ConsoleWindow.cpp
@@ -862,6 +862,7 @@ void consoleWin_t::initHotKeys(void)
connect( Hotkeys[ HK_TOGGLE_BG ].getShortcut(), SIGNAL(activated()), this, SLOT(toggleBackground(void)) );
connect( Hotkeys[ HK_TOGGLE_FG ].getShortcut(), SIGNAL(activated()), this, SLOT(toggleForeground(void)) );
connect( Hotkeys[ HK_FKB_ENABLE ].getShortcut(), SIGNAL(activated()), this, SLOT(toggleFamKeyBrdEnable(void)) );
+ connect( Hotkeys[ HK_TOGGLE_ALL_CHEATS ].getShortcut(), SIGNAL(activated()), this, SLOT(toggleGlobalCheatEnable(void)) );
connect( Hotkeys[ HK_SAVE_STATE_0 ].getShortcut(), SIGNAL(activated()), this, SLOT(saveState0(void)) );
connect( Hotkeys[ HK_SAVE_STATE_1 ].getShortcut(), SIGNAL(activated()), this, SLOT(saveState1(void)) );
@@ -1281,16 +1282,16 @@ void consoleWin_t::createMainMenu(void)
connect( Hotkeys[ HK_POWER ].getShortcut(), SIGNAL(activated()), this, SLOT(powerConsoleCB(void)) );
// Emulation -> Reset
- resetAct = new QAction(tr("&Reset"), this);
+ resetAct = new QAction(tr("Hard &Reset"), this);
//resetAct->setShortcut( QKeySequence(tr("Ctrl+R")));
- resetAct->setStatusTip(tr("Reset Console"));
+ resetAct->setStatusTip(tr("Hard Reset of Console"));
resetAct->setIcon( style()->standardIcon( QStyle::SP_DialogResetButton ) );
connect(resetAct, SIGNAL(triggered()), this, SLOT(consoleHardReset(void)) );
emuMenu->addAction(resetAct);
- Hotkeys[ HK_RESET ].setAction( resetAct );
- connect( Hotkeys[ HK_RESET ].getShortcut(), SIGNAL(activated()), this, SLOT(consoleHardReset(void)) );
+ Hotkeys[ HK_HARD_RESET ].setAction( resetAct );
+ connect( Hotkeys[ HK_HARD_RESET ].getShortcut(), SIGNAL(activated()), this, SLOT(consoleHardReset(void)) );
// Emulation -> Soft Reset
sresetAct = new QAction(tr("&Soft Reset"), this);
@@ -1301,6 +1302,9 @@ void consoleWin_t::createMainMenu(void)
emuMenu->addAction(sresetAct);
+ Hotkeys[ HK_SOFT_RESET ].setAction( sresetAct );
+ connect( Hotkeys[ HK_SOFT_RESET ].getShortcut(), SIGNAL(activated()), this, SLOT(consoleSoftReset(void)) );
+
// Emulation -> Pause
pauseAct = new QAction(tr("&Pause"), this);
//pauseAct->setShortcut( QKeySequence(tr("Pause")));
@@ -1730,10 +1734,10 @@ void consoleWin_t::createMainMenu(void)
debugMenu->addAction(ggEncodeAct);
- // Debug -> iNES Header Editor
- iNesEditAct = new QAction(tr("&iNES Header Editor..."), this);
+ // Debug -> NES Header Editor
+ iNesEditAct = new QAction(tr("NES Header Edito&r..."), this);
//iNesEditAct->setShortcut( QKeySequence(tr("Shift+F7")));
- iNesEditAct->setStatusTip(tr("Open iNES Header Editor"));
+ iNesEditAct->setStatusTip(tr("Open NES Header Editor"));
connect(iNesEditAct, SIGNAL(triggered()), this, SLOT(openNesHeaderEditor(void)) );
debugMenu->addAction(iNesEditAct);
@@ -3055,7 +3059,7 @@ void consoleWin_t::openNesHeaderEditor(void)
{
iNesHeaderEditor_t *win;
- //printf("Open iNES Header Editor Window\n");
+ //printf("Open NES Header Editor Window\n");
win = new iNesHeaderEditor_t(this);
@@ -3173,6 +3177,20 @@ void consoleWin_t::toggleFamKeyBrdEnable(void)
toggleFamilyKeyboardFunc();
}
+extern int globalCheatDisabled;
+
+void consoleWin_t::toggleGlobalCheatEnable(void)
+{
+ FCEU_WRAPPER_LOCK();
+ FCEUI_GlobalToggleCheat(globalCheatDisabled);
+ FCEU_WRAPPER_UNLOCK();
+
+ g_config->setOption("SDL.CheatsDisabled", globalCheatDisabled);
+ g_config->save();
+
+ updateCheatDialog();
+}
+
void consoleWin_t::warnAmbiguousShortcut( QShortcut *shortcut)
{
char stmp[256];
diff --git a/src/drivers/Qt/ConsoleWindow.h b/src/drivers/Qt/ConsoleWindow.h
index 4586e06b..d4451965 100644
--- a/src/drivers/Qt/ConsoleWindow.h
+++ b/src/drivers/Qt/ConsoleWindow.h
@@ -415,6 +415,7 @@ class consoleWin_t : public QMainWindow
void toggleBackground(void);
void toggleForeground(void);
void toggleFamKeyBrdEnable(void);
+ void toggleGlobalCheatEnable(void);
void saveState0(void);
void saveState1(void);
void saveState2(void);
diff --git a/src/drivers/Qt/HexEditor.cpp b/src/drivers/Qt/HexEditor.cpp
index 0c763382..38473f43 100644
--- a/src/drivers/Qt/HexEditor.cpp
+++ b/src/drivers/Qt/HexEditor.cpp
@@ -322,6 +322,8 @@ static void PalettePoke(uint32 addr, uint8 data)
//----------------------------------------------------------------------------
static int writeMem( int mode, unsigned int addr, int value )
{
+ bool updateDebugger = false;
+
value = value & 0x000000ff;
switch ( mode )
@@ -339,6 +341,8 @@ static int writeMem( int mode, unsigned int addr, int value )
{
wfunc ((uint32) addr,
(uint8) (value & 0x000000ff));
+
+ updateDebugger = true;
}
}
else
@@ -374,7 +378,7 @@ static int writeMem( int mode, unsigned int addr, int value )
{
if (addr < 16)
{
- fprintf( stdout, "You can't edit ROM header here, however you can use iNES Header Editor to edit the header if it's an iNES format file.");
+ fprintf( stdout, "You can't edit ROM header here, however you can use NES Header Editor to edit the header if it's an iNES or NES2.0 format file.");
}
else if ( (addr >= 16) && (addr < PRGsize[0]+16) )
{
@@ -384,23 +388,32 @@ static int writeMem( int mode, unsigned int addr, int value )
{
*(uint8 *)(GetNesCHRPointer(addr-16-PRGsize[0])) = value;
}
+ updateDebugger = true;
}
break;
}
hexEditorRequestUpdateAll();
- return 0;
+ if ( updateDebugger )
+ {
+ if (debuggerWindowIsOpen())
+ {
+ updateAllDebuggerWindows();
+ }
+ }
+
+ return 0;
}
//----------------------------------------------------------------------------
static int convToXchar( int i )
{
- int c = 0;
+ int c = 0;
if ( (i >= 0) && (i < 10) )
{
- c = i + '0';
+ c = i + '0';
}
else if ( i < 16 )
{
@@ -3243,7 +3256,7 @@ void QHexEdit::addBookMarkCB(void)
}
}
//----------------------------------------------------------------------------
-static int RamFreezeCB(char *name, uint32 a, uint8 v, int compare,int s,int type, void *data)
+static int RamFreezeCB(const char *name, uint32 a, uint8 v, int compare,int s,int type, void *data)
{
return ((QHexEdit*)data)->FreezeRam( name, a, v, compare, s, type );
}
@@ -4205,6 +4218,12 @@ int hexEditorOpenFromDebugger( int mode, int addr )
win->show();
}
+ else
+ {
+ win->activateWindow();
+ win->raise();
+ win->setFocus();
+ }
win->editor->setMode( mode );
win->editor->setAddr( addr );
diff --git a/src/drivers/Qt/TraceLogger.cpp b/src/drivers/Qt/TraceLogger.cpp
index 47528131..8107eee7 100644
--- a/src/drivers/Qt/TraceLogger.cpp
+++ b/src/drivers/Qt/TraceLogger.cpp
@@ -26,6 +26,7 @@
#ifdef WIN32
#include
#else
+#include
#include
#include
#include
@@ -111,8 +112,11 @@ static int recBufHead = 0;
static int recBufNum = 0;
static traceRecord_t *logBuf = NULL;
static int logBufMax = 3000000;
-static int logBufHead = 0;
-static int logBufTail = 0;
+// logBufHead and logBufTail are volatile because they are shared use by both the emulation and disk logger threads.
+// Ensure that the compiler doesn't do any thread caching optimizations on them so that changes to these
+// variables are immediately visible by the other thread.
+static volatile int logBufHead = 0;
+static volatile int logBufTail = 0;
static bool overrunWarningArmed = true;
static TraceLoggerDialog_t *traceLogWindow = NULL;
static void pushMsgToLogBuffer(const char *msg);
@@ -2515,6 +2519,8 @@ void TraceLogDiskThread_t::run(void)
char buf[8192];
int i,idx=0;
int blockSize = 4 * 1024;
+ bool dataNeedsFlush = true;
+ bool isPaused = false;
//printf("Trace Log Disk Start\n");
@@ -2557,6 +2563,8 @@ void TraceLogDiskThread_t::run(void)
while ( !isInterruptionRequested() )
{
+ isPaused = FCEUI_EmulationPaused() ? true : false;
+
while (logBufHead != logBufTail)
{
logBuf[logBufTail].convToText(line);
@@ -2582,6 +2590,41 @@ void TraceLogDiskThread_t::run(void)
}
idx = 0;
#endif
+ dataNeedsFlush = true;
+ }
+ }
+
+ if (isPaused)
+ {
+ // If paused, the user might be at a breakpoint or doing some
+ // debugging. So make sure all data is flushed to disk for viewing.
+ // Only flush data when paused, to keep write efficiency up.
+ if ( idx > 0 )
+ {
+ #ifdef WIN32
+ DWORD bytesWritten;
+ WriteFile( logFile, buf, idx, &bytesWritten, NULL ); idx = 0;
+ #else
+ if ( write( logFile, buf, idx ) < 0 )
+ {
+ // HANDLE ERROR TODO
+ }
+ idx = 0;
+ #endif
+ dataNeedsFlush = true;
+ }
+ if (dataNeedsFlush)
+ {
+ //printf("Flushing Trace Log Disk Buffers\n");
+ #ifdef WIN32
+ FlushFileBuffers( logFile );
+ #else
+ if ( fsync( logFile ) )
+ {
+ printf("Trace Log fsync error\n");
+ }
+ #endif
+ dataNeedsFlush = false;
}
}
SDL_Delay(1);
diff --git a/src/drivers/Qt/config.cpp b/src/drivers/Qt/config.cpp
index 386571ee..fff49ff4 100644
--- a/src/drivers/Qt/config.cpp
+++ b/src/drivers/Qt/config.cpp
@@ -83,6 +83,9 @@ int getHotKeyConfig( int i, const char **nameOut, const char **keySeqOut, const
case HK_CHEAT_MENU:
name = "CheatMenu"; keySeq = ""; title = "Open Cheat Window"; group = "Tools";
break;
+ case HK_TOGGLE_ALL_CHEATS:
+ name = "ToggleCheats"; keySeq = ""; title = "Toggle Global Cheat Enable"; group = "Tools";
+ break;
case HK_BIND_STATE:
name = "BindState"; keySeq = ""; title = "Bind Save State to Movie"; group = "Movie";
break;
@@ -184,8 +187,11 @@ int getHotKeyConfig( int i, const char **nameOut, const char **keySeqOut, const
case HK_POWER:
name = "Power"; keySeq = ""; title = "Power"; group = "Emulation";
break;
- case HK_RESET:
- name = "Reset"; keySeq = "Ctrl+R"; title = "Reset"; group = "Emulation";
+ case HK_SOFT_RESET:
+ name = "SoftReset"; keySeq = "Ctrl+R"; title = "Soft Reset"; group = "Emulation";
+ break;
+ case HK_HARD_RESET:
+ name = "HardReset"; keySeq = "Ctrl+Shift+R"; title = "Hard Reset"; group = "Emulation";
break;
case HK_PAUSE:
name = "Pause"; keySeq = "Pause"; title = "Pause"; group = "Emulation";
diff --git a/src/drivers/Qt/config.h b/src/drivers/Qt/config.h
index 0bb68e78..5b2beb92 100644
--- a/src/drivers/Qt/config.h
+++ b/src/drivers/Qt/config.h
@@ -14,7 +14,7 @@ enum HOTKEY {
HK_OPEN_ROM=0, HK_CLOSE_ROM,
// Emulation power, reset, pause, quit
- HK_POWER, HK_RESET, HK_PAUSE, HK_QUIT,
+ HK_POWER, HK_SOFT_RESET, HK_HARD_RESET, HK_PAUSE, HK_QUIT,
// Emulation Execution Control
HK_FRAME_ADVANCE, HK_DECREASE_SPEED, HK_INCREASE_SPEED, HK_TURBO,
@@ -53,7 +53,7 @@ enum HOTKEY {
// Display
HK_TOGGLE_FG, HK_TOGGLE_BG, HK_TOGGLE_INPUT_DISPLAY, HK_LAG_COUNTER_DISPLAY,
- HK_CHEAT_MENU, HK_LOAD_LUA,
+ HK_CHEAT_MENU, HK_TOGGLE_ALL_CHEATS, HK_LOAD_LUA,
HK_MUTE_CAPTURE,
HK_FA_LAG_SKIP,
HK_VOLUME_DOWN, HK_VOLUME_UP,
diff --git a/src/drivers/Qt/fceuWrapper.cpp b/src/drivers/Qt/fceuWrapper.cpp
index d701fcfb..12790b69 100644
--- a/src/drivers/Qt/fceuWrapper.cpp
+++ b/src/drivers/Qt/fceuWrapper.cpp
@@ -39,6 +39,7 @@
#include "Qt/unix-netplay.h"
#include "Qt/AviRecord.h"
#include "Qt/HexEditor.h"
+#include "Qt/CheatsConf.h"
#include "Qt/SymbolicDebug.h"
#include "Qt/CodeDataLogger.h"
#include "Qt/ConsoleDebugger.h"
@@ -352,6 +353,8 @@ int LoadGame(const char *path, bool silent)
debugSymbolTable.loadGameSymbols();
+ updateCheatDialog();
+
CDLoggerROMChanged();
int state_to_load;
@@ -642,6 +645,7 @@ static const char *DriverUsage =
static void ShowUsage(const char *prog)
{
int i,j;
+ FCEUD_Message("Starting " FCEU_NAME_AND_VERSION "...\n");
printf("\nUsage is as follows:\n%s filename\n\n",prog);
puts(DriverUsage);
#ifdef _S9XLUA_H
@@ -681,11 +685,9 @@ static void ShowUsage(const char *prog)
}
-int fceuWrapperInit( int argc, char *argv[] )
+// Pre-GUI initialization.
+int fceuWrapperPreInit( int argc, char *argv[] )
{
- int opt, error;
- std::string s;
-
for (int i=0; iaddWidget( hdrBox );
@@ -550,7 +550,7 @@ iNesHeaderEditor_t::~iNesHeaderEditor_t(void)
//----------------------------------------------------------------------------
void iNesHeaderEditor_t::closeEvent(QCloseEvent *event)
{
- //printf("iNES Header Editor Close Window Event\n");
+ //printf("NES Header Editor Close Window Event\n");
done(0);
deleteLater();
event->accept();
@@ -701,21 +701,21 @@ bool iNesHeaderEditor_t::loadHeader(iNES_HEADER* header)
break;
}
case errors::INVALID_HEADER:
- //MessageBox(parent, "Invalid iNES header.", "iNES Header Editor", MB_OK | MB_ICONERROR);
- showErrorMsgWindow( "Invalid iNES header." );
+ //MessageBox(parent, "Invalid NES header.", "NES Header Editor", MB_OK | MB_ICONERROR);
+ showErrorMsgWindow( "Invalid NES header." );
break;
case errors::FDS_HEADER:
- //MessageBox(parent, "Editing header of an FDS file is not supported.", "iNES Header Editor", MB_OK | MB_ICONERROR);
+ //MessageBox(parent, "Editing header of an FDS file is not supported.", "NES Header Editor", MB_OK | MB_ICONERROR);
showErrorMsgWindow("Editing header of an FDS file is not supported.");
break;
case errors::UNIF_HEADER:
- //MessageBox(parent, "Editing header of a UNIF file is not supported.", "iNES Header Editor", MB_OK | MB_ICONERROR);
+ //MessageBox(parent, "Editing header of a UNIF file is not supported.", "NES Header Editor", MB_OK | MB_ICONERROR);
showErrorMsgWindow("Editing header of a UNIF file is not supported.");
break;
case errors::NSF_HEADER:
// case errors::NSF2_HEADER:
// case errors::NSFE_HEADER:
- //MessageBox(parent, "Editing header of an NSF file is not supported.", "iNES Header Editor", MB_OK | MB_ICONERROR);
+ //MessageBox(parent, "Editing header of an NSF file is not supported.", "NES Header Editor", MB_OK | MB_ICONERROR);
showErrorMsgWindow("Editing header of an NSF file is not supported.");
break;
}
diff --git a/src/drivers/Qt/input.cpp b/src/drivers/Qt/input.cpp
index 5cd1f347..9bddbc7c 100644
--- a/src/drivers/Qt/input.cpp
+++ b/src/drivers/Qt/input.cpp
@@ -158,6 +158,15 @@ int getKeyState(int k)
return 0;
}
+const uint8_t *QtSDL_getKeyboardState( int *bufSize )
+{
+ if (bufSize != nullptr)
+ {
+ *bufSize = SDL_NUM_SCANCODES;
+ }
+ return g_keyState;
+}
+
//static int
//_keyonly(int a)
//{
@@ -1909,7 +1918,7 @@ static void UpdateFKB(void)
}
}
-const uint8 *getFamilyKeyboardState(void)
+const uint8_t *getFamilyKeyboardState(void)
{
return fkbkeys;
}
diff --git a/src/drivers/Qt/input.h b/src/drivers/Qt/input.h
index 023d41fe..8ed5ff38 100644
--- a/src/drivers/Qt/input.h
+++ b/src/drivers/Qt/input.h
@@ -148,7 +148,8 @@ int saveInputSettingsToFile( const char *fileBase = NULL );
int loadInputSettingsFromFile( const char *filename = NULL );
void toggleFamilyKeyboardFunc(void);
bool isFamilyKeyboardActv(void);
-const uint8 *getFamilyKeyboardState(void);
+const uint8_t *getFamilyKeyboardState(void);
+const uint8_t *QtSDL_getKeyboardState( int *bufSize );
#endif
diff --git a/src/drivers/Qt/main.cpp b/src/drivers/Qt/main.cpp
index 0c2f1f69..1974ac29 100644
--- a/src/drivers/Qt/main.cpp
+++ b/src/drivers/Qt/main.cpp
@@ -95,7 +95,10 @@ static bool showSplashScreen(void)
int main( int argc, char *argv[] )
{
- int retval;
+ int retval = 0;
+
+ fceuWrapperPreInit(argc, argv);
+
qInstallMessageHandler(MessageOutput);
QApplication app(argc, argv);
diff --git a/src/drivers/Qt/ppuViewer.cpp b/src/drivers/Qt/ppuViewer.cpp
index 101e26de..d151da42 100644
--- a/src/drivers/Qt/ppuViewer.cpp
+++ b/src/drivers/Qt/ppuViewer.cpp
@@ -1133,7 +1133,7 @@ void ppuPatternView_t::paintEvent(QPaintEvent *event)
xx = 0; yy = 0;
- showSelector = (cycleCount < 20);
+ showSelector = (cycleCount < 20) && (selTile.x() >= 0) && (selTile.y() >= 0);
if ( mode == 1 )
{
diff --git a/src/drivers/common/cheat.cpp b/src/drivers/common/cheat.cpp
index 2cff0cd6..e6803f9d 100644
--- a/src/drivers/common/cheat.cpp
+++ b/src/drivers/common/cheat.cpp
@@ -199,7 +199,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 +212,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 +220,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 +241,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 +321,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;
diff --git a/src/drivers/common/config.cpp b/src/drivers/common/config.cpp
index 7f1157e1..319067fc 100644
--- a/src/drivers/common/config.cpp
+++ b/src/drivers/common/config.cpp
@@ -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;
diff --git a/src/drivers/common/vidblit.cpp b/src/drivers/common/vidblit.cpp
index 9b6f1c22..6fcdac4e 100644
--- a/src/drivers/common/vidblit.cpp
+++ b/src/drivers/common/vidblit.cpp
@@ -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 static u32 _ModernDeemphColorMap(u8* src, u8* srcbuf)
+template static u32 _ModernDeemphColorMap(const u8* src, const u8* srcbuf)
{
u8 pixel = *src;
@@ -492,7 +492,7 @@ template 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;
}
diff --git a/src/drivers/common/vidblit.h b/src/drivers/common/vidblit.h
index d9581b0b..ba35b937 100644
--- a/src/drivers/common/vidblit.h
+++ b/src/drivers/common/vidblit.h
@@ -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);
\ No newline at end of file
+u32 ModernDeemphColorMap(const u8* src, const u8* srcbuf, int scale);
diff --git a/src/drivers/sdl/memview.cpp b/src/drivers/sdl/memview.cpp
index c89dbf3c..bc17ee3d 100644
--- a/src/drivers/sdl/memview.cpp
+++ b/src/drivers/sdl/memview.cpp
@@ -277,7 +277,7 @@ struct memViewWin_t
{
if (addr < 16)
{
- fprintf( stdout, "You can't edit ROM header here, however you can use iNES Header Editor to edit the header if it's an iNES format file.");
+ fprintf( stdout, "You can't edit ROM header here, however you can use NES Header Editor to edit the header if it's an iNES or NES2.0 format file.");
}
else if ( (addr >= 16) && (addr < PRGsize[0]+16) )
{
diff --git a/src/drivers/win/aviout.cpp b/src/drivers/win/aviout.cpp
index b5ce0333..e0d347be 100644
--- a/src/drivers/win/aviout.cpp
+++ b/src/drivers/win/aviout.cpp
@@ -291,6 +291,8 @@ static void do_video_conversion(const unsigned char* buffer)
{
// memset(avi_file->convert_buffer, 0, VIDEO_WIDTH*(avi_file->end_scanline-avi_file->start_scanline)*3);
+ const unsigned char* mybuffer = buffer;
+
buffer += avi_file->start_scanline * VIDEO_WIDTH;
for(int y=avi_file->start_scanline; yend_scanline; ++y)
@@ -300,10 +302,11 @@ static void do_video_conversion(const unsigned char* buffer)
for(int x=0; x>0x00)&0xFF;
+ *pix++=(color>>0x08)&0xFF;
+ *pix++=(color>>0x10)&0xFF;
+ buffer++;
}
buffer = prevbuf + VIDEO_WIDTH;
diff --git a/src/drivers/win/cheat.cpp b/src/drivers/win/cheat.cpp
index f2d6c83e..0153d281 100644
--- a/src/drivers/win/cheat.cpp
+++ b/src/drivers/win/cheat.cpp
@@ -108,7 +108,7 @@ char *U8ToStr(uint8 a)
}
//int RedoCheatsCallB(char *name, uint32 a, uint8 v, int s) { //bbit edited: this commented out line was changed to the below for the new fceud
-int RedoCheatsCallB(char *name, uint32 a, uint8 v, int c, int s, int type, void* data)
+int RedoCheatsCallB(const char *name, uint32 a, uint8 v, int c, int s, int type, void* data)
{
char str[256] = { 0 };
GetCheatStr(str, a, v, c);
@@ -123,7 +123,7 @@ int RedoCheatsCallB(char *name, uint32 a, uint8 v, int c, int s, int type, void*
else
lvi.iItem = SendDlgItemMessage(hCheat, IDC_LIST_CHEATS, LVM_INSERTITEM, 0, (LPARAM)&lvi);
lvi.iSubItem = 1;
- lvi.pszText = name;
+ lvi.pszText = (LPSTR)name;
SendDlgItemMessage(hCheat, IDC_LIST_CHEATS, LVM_SETITEM, 0, (LPARAM)&lvi);
lvi.mask = LVIF_STATE;
@@ -483,11 +483,12 @@ INT_PTR CALLBACK CheatConsoleCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
lvi.stateMask = LVIS_STATEIMAGEMASK;
int tmpsel = SendDlgItemMessage(hCheat, IDC_LIST_CHEATS, LVM_GETNEXTITEM, -1, LVNI_ALL | LVNI_SELECTED);
- char* name = ""; int s;
+ std::string name;
+ int s;
while (tmpsel != -1)
{
FCEUI_GetCheat(tmpsel, &name, NULL, NULL, NULL, &s, NULL);
- FCEUI_SetCheat(tmpsel, name, -1, -1, -2, s ^= 1, 1);
+ FCEUI_SetCheat(tmpsel, &name, -1, -1, -2, s ^= 1, 1);
lvi.iItem = tmpsel;
lvi.state = INDEXTOSTATEIMAGEMASK(s ? 2 : 1);
@@ -645,12 +646,14 @@ INT_PTR CALLBACK CheatConsoleCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
if (selcheat < 0)
break;
- char name[256]; uint32 a; uint8 v; int s; int c;
- GetUICheatInfo(hwndDlg, name, &a, &v, &c);
+ std::string name; uint32 a; uint8 v; int s; int c;
+ char namebuf[256] = {0};
+ GetUICheatInfo(hwndDlg, namebuf, &a, &v, &c);
+ name = namebuf;
- FCEUI_SetCheat(selcheat, name, a, v, c, -1, 1);
- FCEUI_GetCheat(selcheat, NULL, &a, &v, &c, &s, NULL);
- RedoCheatsCallB(name, a, v, c, s, 1, &selcheat);
+ FCEUI_SetCheat(selcheat, &name, a, v, c, -1, 1);
+ FCEUI_GetCheat(selcheat, nullptr, &a, &v, &c, &s, NULL);
+ RedoCheatsCallB(name.c_str(), a, v, c, s, 1, &selcheat);
SendDlgItemMessage(hwndDlg, IDC_LIST_CHEATS, LVM_SETSELECTIONMARK, 0, selcheat);
SetDlgItemText(hwndDlg, IDC_CHEAT_ADDR, (LPCSTR)U16ToStr(a));
@@ -902,9 +905,9 @@ INT_PTR CALLBACK CheatConsoleCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
selcheat = pNMListView->iItem;
if (selcheat >= 0)
{
- char* name = ""; uint32 a; uint8 v; int s; int c;
+ std::string name; uint32 a; uint8 v; int s; int c;
FCEUI_GetCheat(selcheat, &name, &a, &v, &c, &s, NULL);
- SetDlgItemText(hwndDlg, IDC_CHEAT_NAME, (LPCSTR)name);
+ SetDlgItemText(hwndDlg, IDC_CHEAT_NAME, (LPCSTR)name.c_str());
SetDlgItemText(hwndDlg, IDC_CHEAT_ADDR, (LPCSTR)U16ToStr(a));
SetDlgItemText(hwndDlg, IDC_CHEAT_VAL, (LPCSTR)U8ToStr(v));
SetDlgItemText(hwndDlg, IDC_CHEAT_COM, (LPCSTR)(c == -1 ? "" : U8ToStr(c)));
@@ -930,11 +933,11 @@ INT_PTR CALLBACK CheatConsoleCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
pNMListView->uNewState & INDEXTOSTATEIMAGEMASK(2))
{
int tmpsel = pNMListView->iItem;
- char* name = ""; int s;
+ std::string name; int s;
FCEUI_GetCheat(tmpsel, &name, NULL, NULL, NULL, &s, NULL);
if (!s)
{
- FCEUI_SetCheat(tmpsel, name, -1, -1, -2, s ^= 1, 1);
+ FCEUI_SetCheat(tmpsel, &name, -1, -1, -2, s ^= 1, 1);
UpdateCheatRelatedWindow();
UpdateCheatListGroupBoxUI();
}
@@ -944,11 +947,11 @@ INT_PTR CALLBACK CheatConsoleCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
pNMListView->uNewState & INDEXTOSTATEIMAGEMASK(1))
{
int tmpsel = pNMListView->iItem;
- char* name = ""; int s;
+ std::string name; int s;
FCEUI_GetCheat(tmpsel, &name, NULL, NULL, NULL, &s, NULL);
if (s)
{
- FCEUI_SetCheat(tmpsel, name, -1, -1, -2, s ^= 1, 1);
+ FCEUI_SetCheat(tmpsel, &name, -1, -1, -2, s ^= 1, 1);
UpdateCheatRelatedWindow();
UpdateCheatListGroupBoxUI();
@@ -1081,6 +1084,8 @@ void UpdateCheatListGroupBoxUI()
SetDlgItemText(hCheat, IDC_GROUPBOX_CHEATLIST, temp);
EnableWindow(GetDlgItem(hCheat, IDC_BTN_CHEAT_EXPORTTOFILE), cheats != 0);
+
+ CheckDlgButton(hCheat,IDC_CHEAT_GLOBAL_SWITCH,globalCheatDisabled?BST_UNCHECKED:BST_CHECKED);
}
//Used by cheats and external dialogs such as hex editor to update items in the cheat search dialog
diff --git a/src/drivers/win/debugger.cpp b/src/drivers/win/debugger.cpp
index 4bc61e5b..8c3156a2 100644
--- a/src/drivers/win/debugger.cpp
+++ b/src/drivers/win/debugger.cpp
@@ -1471,7 +1471,7 @@ INT_PTR CALLBACK PatcherCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
else
iapoffset = GetNesFileAddress(GetEditHex(hwndDlg,IDC_ROMPATCHER_OFFSET));
if((iapoffset < 16) && (iapoffset != -1)){
- MessageBox(hDebug, "Sorry, iNES Header editing isn't supported by this tool. If you want to edit the header, please use iNES Header Editor", "Error", MB_OK | MB_ICONASTERISK);
+ MessageBox(hDebug, "Sorry, NES Header editing isn't supported by this tool. If you want to edit the header, please use NES Header Editor", "Error", MB_OK | MB_ICONASTERISK);
iapoffset = -1;
}
if((iapoffset > PRGsize[0]) && (iapoffset != -1)){
diff --git a/src/drivers/win/debuggersp.cpp b/src/drivers/win/debuggersp.cpp
index 1f78660f..8cf8c093 100644
--- a/src/drivers/win/debuggersp.cpp
+++ b/src/drivers/win/debuggersp.cpp
@@ -21,6 +21,7 @@
#include "common.h"
#include "utils/xstring.h"
#include "debuggersp.h"
+#include "window.h"
#include "../../fceu.h"
#include "../../debug.h"
#include "../../conddebug.h"
@@ -60,6 +61,7 @@ bool symbRegNames = true;
int debuggerWasActive = 0;
char temp_chr[40] = {0};
char delimiterChar[2] = "#";
+
INT_PTR CALLBACK nameDebuggerBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
extern WNDPROC DefaultEditCtrlProc;
@@ -153,10 +155,10 @@ int parseLine(char* line, Name* n)
if (llen == 5) // Offset size of normal lines of the form $XXXX
{
if (line[0] != '$'
- || !IsLetterLegalHex(line[1])
- || !IsLetterLegalHex(line[2])
- || !IsLetterLegalHex(line[3])
- || !IsLetterLegalHex(line[4])
+ || !IsLetterLegalHex(0,line[1])
+ || !IsLetterLegalHex(1,line[2])
+ || !IsLetterLegalHex(2,line[3])
+ || !IsLetterLegalHex(3,line[4])
)
{
return 4;
@@ -166,10 +168,10 @@ int parseLine(char* line, Name* n)
{
int i;
if (line[0] != '$'
- || !IsLetterLegalHex(line[1])
- || !IsLetterLegalHex(line[2])
- || !IsLetterLegalHex(line[3])
- || !IsLetterLegalHex(line[4])
+ || !IsLetterLegalHex(0,line[1])
+ || !IsLetterLegalHex(1,line[2])
+ || !IsLetterLegalHex(2,line[3])
+ || !IsLetterLegalHex(3,line[4])
|| line[5] != '/'
)
{
@@ -178,7 +180,7 @@ int parseLine(char* line, Name* n)
for (i=6;line[i];i++)
{
- if (!IsLetterLegalHex(line[i]))
+ if (!IsLetterLegalHex(i,line[i]))
{
return 6;
}
diff --git a/src/drivers/win/debuggersp.h b/src/drivers/win/debuggersp.h
index 01b7d907..3bd04d65 100644
--- a/src/drivers/win/debuggersp.h
+++ b/src/drivers/win/debuggersp.h
@@ -61,7 +61,6 @@ void DeleteAllDebuggerBookmarks();
void FillDebuggerBookmarkListbox(HWND hwnd);
void GoToDebuggerBookmark(HWND hwnd);
-extern bool IsLetterLegalHex(char c);
bool DoSymbolicDebugNaming(int offset, HWND parentHWND);
bool DoSymbolicDebugNaming(int offset, int size, HWND parentHWND);
diff --git a/src/drivers/win/header_editor.cpp b/src/drivers/win/header_editor.cpp
index 8893b7d9..168a6170 100644
--- a/src/drivers/win/header_editor.cpp
+++ b/src/drivers/win/header_editor.cpp
@@ -186,22 +186,22 @@ bool LoadHeader(HWND parent, iNES_HEADER* header)
{
char buf[1024];
sprintf(buf, "Error opening %s!", LoadedRomFName);
- MessageBox(parent, buf, "iNES Header Editor", MB_OK | MB_ICONERROR);
+ MessageBox(parent, buf, "NES Header Editor", MB_OK | MB_ICONERROR);
break;
}
case errors::INVALID_HEADER:
- MessageBox(parent, "Invalid iNES header.", "iNES Header Editor", MB_OK | MB_ICONERROR);
+ MessageBox(parent, "Invalid NES header.", "NES Header Editor", MB_OK | MB_ICONERROR);
break;
case errors::FDS_HEADER:
- MessageBox(parent, "Editing header of an FDS file is not supported.", "iNES Header Editor", MB_OK | MB_ICONERROR);
+ MessageBox(parent, "Editing header of an FDS file is not supported.", "NES Header Editor", MB_OK | MB_ICONERROR);
break;
case errors::UNIF_HEADER:
- MessageBox(parent, "Editing header of a UNIF file is not supported.", "iNES Header Editor", MB_OK | MB_ICONERROR);
+ MessageBox(parent, "Editing header of a UNIF file is not supported.", "NES Header Editor", MB_OK | MB_ICONERROR);
break;
case errors::NSF_HEADER:
// case errors::NSF2_HEADER:
// case errors::NSFE_HEADER:
- MessageBox(parent, "Editing header of an NSF file is not supported.", "iNES Header Editor", MB_OK | MB_ICONERROR);
+ MessageBox(parent, "Editing header of an NSF file is not supported.", "NES Header Editor", MB_OK | MB_ICONERROR);
break;
}
return false;
@@ -1735,7 +1735,7 @@ int GetComboBoxByteSize(HWND hwnd, UINT id, int* value, iNES_HEADER* header)
sprintf(buf, "The unit of %s size you entered is invalid, it must be B, KB or MB", name);
break;
case errors::MINUS_ERR:
- sprintf(buf, "Negative value of %s is not supported by iNES header.", name);
+ sprintf(buf, "Negative value of %s is not supported by NES header.", name);
break;
}
@@ -1880,7 +1880,7 @@ bool SaveINESFile(HWND hwnd, char* path, iNES_HEADER* header)
if (!source)
{
sprintf(buf, "Opening source file %s failed.", LoadedRomFName);
- MessageBox(hwnd, buf, "iNES Header Editor", MB_OK | MB_ICONERROR);
+ MessageBox(hwnd, buf, "NES Header Editor", MB_OK | MB_ICONERROR);
return false;
}
@@ -1889,7 +1889,7 @@ bool SaveINESFile(HWND hwnd, char* path, iNES_HEADER* header)
if (!target)
{
sprintf(buf, "Creating target file %s failed.", path);
- MessageBox(hwnd, buf, "iNES Header Editor", MB_OK | MB_ICONERROR);
+ MessageBox(hwnd, buf, "NES Header Editor", MB_OK | MB_ICONERROR);
FCEU_fclose(source);
return false;
}
diff --git a/src/drivers/win/memview.cpp b/src/drivers/win/memview.cpp
index 0eb55579..70b8b704 100644
--- a/src/drivers/win/memview.cpp
+++ b/src/drivers/win/memview.cpp
@@ -346,7 +346,7 @@ static int GetFileData(uint32 offset){
}
static int WriteFileData(uint32 addr,int data){
- if (addr < 16) MessageBox(hMemView, "You can't edit ROM header here, however you can use iNES Header Editor to edit the header if it's an iNES format file.", "Sorry", MB_OK | MB_ICONERROR);
+ if (addr < 16) MessageBox(hMemView, "You can't edit ROM header here, however you can use NES Header Editor to edit the header if it's an iNES format file.", "Sorry", MB_OK | MB_ICONERROR);
if((addr >= 16) && (addr < PRGsize[0]+16)) *(uint8 *)(GetNesPRGPointer(addr-16)) = data;
if((addr >= PRGsize[0]+16) && (addr < CHRsize[0]+PRGsize[0]+16)) *(uint8 *)(GetNesCHRPointer(addr-16-PRGsize[0])) = data;
@@ -736,7 +736,7 @@ void UpdateColorTable()
int temp_offset;
for (i = 0; i < DataAmount; i++)
{
- temp_offset = CurOffset + i - 16; // (minus iNES header)
+ temp_offset = CurOffset + i - 16; // (minus NES header)
if (temp_offset >= 0)
{
if ((unsigned int)temp_offset < cdloggerdataSize)
@@ -822,7 +822,7 @@ void UpdateColorTable()
int addrtodelete; // This is a very ugly hackish method of doing this
int cheatwasdeleted; // but it works and that is all that matters here.
-int DeleteCheatCallB(char *name, uint32 a, uint8 v, int compare,int s,int type, void *data){ //mbg merge 6/29/06 - added arg
+int DeleteCheatCallB(const char *name, uint32 a, uint8 v, int compare,int s,int type, void *data){ //mbg merge 6/29/06 - added arg
if(cheatwasdeleted == -1)return 1;
cheatwasdeleted++;
if(a == addrtodelete){
@@ -901,7 +901,7 @@ void UnfreezeAllRam() {
int i=0;
- char * Cname;
+ std::string Cname;
uint32 Caddr;
int Ctype;
@@ -919,7 +919,7 @@ void UnfreezeAllRam() {
// would be added by the freeze command. Manual unfreeze should let them
// make that mistake once or twice, in case they like it that way.
FCEUI_GetCheat(i,&Cname,&Caddr,NULL,NULL,NULL,&Ctype);
- if ((Cname[0] == '\0') && ((Caddr < 0x2000) || ((Caddr >= 0x6000) && (Caddr < 0x8000))) && (Ctype == 1)) {
+ if ((Cname.empty()) && ((Caddr < 0x2000) || ((Caddr >= 0x6000) && (Caddr < 0x8000))) && (Ctype == 1)) {
// Already Added, so consider it a success
FreezeRam(Caddr,-1,1);
@@ -960,14 +960,14 @@ void FreezeRam(int address, int mode, int final){
//input is expected to be an ASCII string
void InputData(char *input){
//CursorEndAddy = -1;
- int addr, i, j, datasize = 0;
+ int addr, datasize = 0;
unsigned char *data;
char inputc;
//char str[100];
//mbg merge 7/18/06 added cast:
data = (uint8 *)malloc(strlen(input) + 1); //it can't be larger than the input string, so use that as the size
- for(i = 0;input[i] != 0;i++){
+ for(int i = 0;input[i] != 0;i++){
if(!EditingText){
inputc = -1;
if((input[i] >= 'a') && (input[i] <= 'f')) inputc = input[i]-('a'-0xA);
@@ -983,9 +983,15 @@ void InputData(char *input){
{
TempData = inputc;
}
- } else {
- for(j = 0;j < 256;j++)if(chartable[j] == input[i])break;
- if(j == 256)continue;
+ }
+ else
+ {
+ int j;
+ for(j = 0; j < 256; j++)
+ if(chartable[j] == input[i])
+ break;
+ if(j == 256)
+ continue;
data[datasize++] = j;
}
}
@@ -1003,35 +1009,43 @@ void InputData(char *input){
//sprintf(str,"datasize = %d",datasize);
//MessageBox(hMemView,str, "debug", MB_OK);
- for(i = 0;i < datasize;i++){
- addr = CursorStartAddy+i;
-
- if (addr >= MaxSize) continue;
-
- switch(EditingMode)
+ if(EditingMode == MODE_NES_FILE)
+ {
+ ApplyPatch(CursorStartAddy, datasize, data);
+ }
+ else
+ {
+ for(int i = 0;i < datasize;i++)
{
- case MODE_NES_MEMORY:
- // RAM (system bus)
- BWrite[addr](addr, data[i]);
- break;
- case MODE_NES_PPU:
- // PPU
- addr &= 0x3FFF;
- if (addr < 0x2000)
- VPage[addr >> 10][addr] = data[i]; //todo: detect if this is vrom and turn it red if so
- if ((addr >= 0x2000) && (addr < 0x3F00))
- vnapage[(addr >> 10) & 0x3][addr & 0x3FF] = data[i]; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct?
- if ((addr >= 0x3F00) && (addr < 0x3FFF))
- PalettePoke(addr, data[i]);
- break;
- case MODE_NES_OAM:
- addr &= 0xFF;
- SPRAM[addr] = data[i];
- break;
- case MODE_NES_FILE:
- // ROM
- ApplyPatch(addr, 1, &data[i]);
- break;
+ addr = CursorStartAddy+i;
+
+ if (addr >= MaxSize) continue;
+
+ switch(EditingMode)
+ {
+ case MODE_NES_MEMORY:
+ // RAM (system bus)
+ BWrite[addr](addr, data[i]);
+ break;
+ case MODE_NES_PPU:
+ // PPU
+ addr &= 0x3FFF;
+ if (addr < 0x2000)
+ VPage[addr >> 10][addr] = data[i]; //todo: detect if this is vrom and turn it red if so
+ if ((addr >= 0x2000) && (addr < 0x3F00))
+ vnapage[(addr >> 10) & 0x3][addr & 0x3FF] = data[i]; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct?
+ if ((addr >= 0x3F00) && (addr < 0x3FFF))
+ PalettePoke(addr, data[i]);
+ break;
+ case MODE_NES_OAM:
+ addr &= 0xFF;
+ SPRAM[addr] = data[i];
+ break;
+ case MODE_NES_FILE:
+ // ROM
+ ApplyPatch(addr, 1, &data[i]);
+ break;
+ }
}
}
CursorStartAddy+=datasize;
diff --git a/src/drivers/win/monitor.cpp b/src/drivers/win/monitor.cpp
index 376e96e5..037f5b73 100644
--- a/src/drivers/win/monitor.cpp
+++ b/src/drivers/win/monitor.cpp
@@ -3,6 +3,7 @@
#include "debugger.h"
#include "debuggersp.h"
#include "memwatch.h"
+#include "window.h"
#include "../../fceu.h"
#include "../../debug.h"
#include "../../conddebug.h"
@@ -120,7 +121,7 @@ BOOL updateResults(HWND hwndDlg, int rule)
for (unsigned int j=0;j 65536) return 1;
+
bookmarks.resize(size);
// Read the data of those bookmarks
char buffer[256];
@@ -295,6 +298,8 @@ int loadDebuggerPreferences(FILE* f)
// Read the length of the BP condition
if (fread(&len, sizeof(len), 1, f) != 1) return 1;
+ // Windows enforces 32767 max characters for a textbox by default, if it exceeds that, it's probably a corrupt file
+ if (len > 32767) return 1;
// Delete eventual older conditions
if (watchpoint[myNumWPs].condText)
@@ -312,7 +317,9 @@ int loadDebuggerPreferences(FILE* f)
// Read length of the BP description
if (fread(&len, sizeof(len), 1, f) != 1) return 1;
-
+ // Windows enforces 32767 max characters for a textbox by default, if it exceeds that, it's probably a corrupt file
+ if (len > 32767) return 1;
+
// Delete eventual older description
if (watchpoint[myNumWPs].desc)
free(watchpoint[myNumWPs].desc);
@@ -373,6 +380,8 @@ int loadHexPreferences(FILE* f, HexBookmarkList& target = hexBookmarks)
if (fread(&target[i].address, sizeof(target[i].address), 1, f) != 1) return 1;
// Read length of description
if (fread(&len, sizeof(len), 1, f) != 1) return 1;
+ const int max_len = sizeof(target[i].description)/sizeof(target[i].description[0]) - 1; //value of 50
+ if (len > max_len) return 1;
// Read the bookmark description
if (fread(target[i].description, 1, len, f) != len) return 1;
}
@@ -384,6 +393,8 @@ int loadHexPreferences(FILE* f, HexBookmarkList& target = hexBookmarks)
if (!feof(f))
{
fread(&target.shortcutCount, sizeof(target.shortcutCount), 1, f);
+ const int max_shortcuts = sizeof(target.shortcuts) / sizeof(target.shortcuts[0]); //value of 10
+ if (target.shortcutCount > max_shortcuts) return 1;
unsigned int bookmark_index, shortcut_index;
// read the matching index list of the shortcuts
diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc
index 2b467b92..88d77f03 100644
--- a/src/drivers/win/res.rc
+++ b/src/drivers/win/res.rc
@@ -684,53 +684,53 @@ FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
GROUPBOX "",IDC_STATIC,3,0,126,200
GROUPBOX "",IDC_STATIC,131,0,128,200
- EDITTEXT MW_ADDR00,6,17,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR00,6,17,30,14,0
EDITTEXT MW_NAME00,41,17,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR01,6,32,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR01,6,32,30,14,0
EDITTEXT MW_NAME01,41,32,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR02,6,47,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR02,6,47,30,14,0
EDITTEXT MW_NAME02,41,47,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR03,6,62,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR03,6,62,30,14,0
EDITTEXT MW_NAME03,41,62,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR04,6,77,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR04,6,77,30,14,0
EDITTEXT MW_NAME04,41,77,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR05,6,92,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR05,6,92,30,14,0
EDITTEXT MW_NAME05,41,92,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR06,6,107,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR06,6,107,30,14,0
EDITTEXT MW_NAME06,41,107,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR07,6,122,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR07,6,122,30,14,0
EDITTEXT MW_NAME07,41,122,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR08,6,137,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR08,6,137,30,14,0
EDITTEXT MW_NAME08,41,137,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR09,6,152,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR09,6,152,30,14,0
EDITTEXT MW_NAME09,41,152,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR10,6,167,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR10,6,167,30,14,0
EDITTEXT MW_NAME10,41,167,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR11,6,182,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR11,6,182,30,14,0
EDITTEXT MW_NAME11,41,182,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR12,135,17,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR12,135,17,30,14,0
EDITTEXT MW_NAME12,171,17,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR13,135,32,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR13,135,32,30,14,0
EDITTEXT MW_NAME13,171,32,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR14,135,47,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR14,135,47,30,14,0
EDITTEXT MW_NAME14,171,47,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR15,135,62,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR15,135,62,30,14,0
EDITTEXT MW_NAME15,171,62,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR16,135,77,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR16,135,77,30,14,0
EDITTEXT MW_NAME16,171,77,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR17,135,92,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR17,135,92,30,14,0
EDITTEXT MW_NAME17,171,92,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR18,135,107,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR18,135,107,30,14,0
EDITTEXT MW_NAME18,171,107,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR19,135,122,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR19,135,122,30,14,0
EDITTEXT MW_NAME19,171,122,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR20,135,137,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR20,135,137,30,14,0
EDITTEXT MW_NAME20,171,137,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR21,135,152,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR21,135,152,30,14,0
EDITTEXT MW_NAME21,171,152,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR22,135,167,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR22,135,167,30,14,0
EDITTEXT MW_NAME22,171,167,55,14,ES_AUTOHSCROLL
- EDITTEXT MW_ADDR23,135,182,30,14,ES_UPPERCASE
+ EDITTEXT MW_ADDR23,135,182,30,14,0
EDITTEXT MW_NAME23,171,182,55,14,ES_AUTOHSCROLL
LTEXT "Name",IDC_STATIC,41,7,20,8
LTEXT "Address",IDC_STATIC,6,7,26,8
diff --git a/src/drivers/win/sound.cpp b/src/drivers/win/sound.cpp
index c751c586..f47e5efe 100644
--- a/src/drivers/win/sound.cpp
+++ b/src/drivers/win/sound.cpp
@@ -58,7 +58,7 @@ public:
Buffer(int size) { length = 0; this->size = size; data = OAKRA_Module::malloc(size); }
int getRemaining() { return size-length; }
void *data;
- ~Buffer() { delete data; }
+ ~Buffer() { if (data){ OAKRA_Module::free(data); data = nullptr; } }
};
std::vector liveBuffers;
diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp
index b36e74bc..82c845b5 100644
--- a/src/drivers/win/window.cpp
+++ b/src/drivers/win/window.cpp
@@ -38,6 +38,9 @@
#include "video.h"
#include "input.h"
#include "fceu.h"
+#include "types.h"
+#include "cart.h"
+#include "ines.h"
#include "cheat.h"
#include "ram_search.h"
@@ -404,7 +407,7 @@ void updateGameDependentMenus()
for (unsigned int i = 0; i < sizeof(menu_ids) / sizeof(*menu_ids); i++)
EnableMenuItem(fceumenu, menu_ids[i], MF_BYCOMMAND | enable ? MF_ENABLED : MF_GRAYED | MF_DISABLED);
- // Special treatment for the iNES head editor, only when no game is loaded or an NES game is loaded
+ // Special treatment for the NES header editor, only when no game is loaded or an NES game is loaded
extern iNES_HEADER head;
enable = GameInfo == 0 || !strncmp((const char*)&head, "NES\x1A", 4);
EnableMenuItem(fceumenu, MENU_INESHEADEREDITOR, MF_BYCOMMAND | enable ? MF_ENABLED : MF_GRAYED | MF_DISABLED);
@@ -1075,6 +1078,37 @@ void CloseGame()
bool ALoad(const char *nameo, char* innerFilename, bool silent)
{
+ FCEUFILE* patchTrial = FCEU_fopen(nameo,nullptr,"rb",nullptr,-1);
+ if(patchTrial)
+ {
+ char sig[10] = {0};
+ FCEU_fread(sig,1,5,patchTrial);
+ FCEU_fclose(patchTrial);
+ if(!strcmp(sig,"PATCH"))
+ {
+ //assuming it's a patch:
+
+ //if nothing's loaded, we can't load this
+ if(!LoadedRomFName[0])
+ return false;
+
+ //ok, set this as a patch and load it
+ //use a temp std::string to avoid problems copying from LoadedRomFName, to LoadedRomFName
+ //pass nullptr as innerFilename -- see, it's not used here anyway
+ strcpy(LoadedRomFNamePatchToUse,nameo);
+ std::string tmp_LoadedRomFName = LoadedRomFName;
+ bool ret = ALoad(tmp_LoadedRomFName.c_str(),nullptr,silent);
+
+ //clear the patch file. FCEUX doesn't seem to ever reload the roms (?) so it can't need to reuse it
+ //and if it does.. well.. it won't be patched.
+ //there's only so much we can do with this old framework
+ LoadedRomFNamePatchToUse[0] = 0;
+
+ return ret;
+ }
+ }
+
+
int oldPaused = EmulationPaused;
// loading is not started yet, so the game can continue;
@@ -3283,176 +3317,97 @@ POINT CalcSubWindowPos(HWND hDlg, POINT* conf)
return pt;
}
-LRESULT APIENTRY FilterEditCtrlProc(HWND hwnd, UINT msg, WPARAM wP, LPARAM lP)
+static bool IsInputLegal(IsLetterLegalProc proc, int index, char letter)
{
- bool through = true;
- INT_PTR result = 0;
+ return !proc || letter == VK_BACK || GetKeyState(VK_CONTROL) & 0x8000 || proc(index,letter);
+}
- switch (msg)
+bool IsLetterLegalGG(int index, char letter)
+{
+ char ch = toupper(letter);
+ for (int i = 0; GameGenieLetters[i]; ++i)
+ if (GameGenieLetters[i] == ch)
+ return true;
+ return false;
+}
+
+bool IsLetterLegalHex(int index, char letter)
+{
+ return letter >= '0' && letter <= '9' || letter >= 'A' && letter <= 'F' || letter >= 'a' && letter <= 'f';
+}
+
+bool IsLetterLegalMemwatchAddress(int index, char letter)
+{
+ //accept normal hex stuff
+ if(letter >= '0' && letter <= '9' || letter >= 'A' && letter <= 'F' || letter >= 'a' && letter <= 'f')
+ return true;
+
+ //accept prefixes
+ if(index == 0)
{
- case WM_PASTE:
- {
-
- bool (*IsLetterLegal)(char) = GetIsLetterLegal(GetDlgCtrlID(hwnd));
-
- if (IsLetterLegal)
- {
- if (OpenClipboard(hwnd))
- {
- HANDLE handle = GetClipboardData(CF_TEXT);
- if (handle)
- {
-
- // get the original clipboard string
- char* clipStr = (char*)GlobalLock(handle);
-
- // check if the text in clipboard has illegal characters
- int len = strlen(clipStr);
- for (int i = 0; i < len; ++i)
- {
- if (!IsLetterLegal(clipStr[i]))
- {
- through = false;
- // Show Edit control tip, just like the control with ES_NUMBER do
- ShowLetterIllegalBalloonTip(hwnd, IsLetterLegal);
- break;
- }
- }
- GlobalUnlock(handle);
- CloseClipboard();
- }
- }
- }
- }
- break;
- case WM_CHAR:
- {
- bool(*IsLetterLegal)(char) = GetIsLetterLegal(GetDlgCtrlID(hwnd));
- through = IsInputLegal(IsLetterLegal, wP);
- if (!through)
- ShowLetterIllegalBalloonTip(hwnd, IsLetterLegal);
- }
+ if(letter == 'x' || letter == 'X' || letter == '!')
+ return true;
}
- return through ? CallWindowProc(DefaultEditCtrlProc, hwnd, msg, wP, lP) : result;
+ return false;
}
-// return a letter legal checking function for the specified control with the given id
-bool inline (*GetIsLetterLegal(UINT id))(char letter)
+bool IsLetterLegalHexList(int index, char letter)
{
- switch (id)
- {
-
- // Game genie text in Cheat and Game Genie Encoder/Decoder
- case IDC_CHEAT_GAME_GENIE_TEXT:
- case IDC_GAME_GENIE_CODE:
- return IsLetterLegalGG;
-
- // Addresses in Debugger
- case IDC_DEBUGGER_VAL_PCSEEK:
- case IDC_DEBUGGER_VAL_PC:
- case IDC_DEBUGGER_VAL_A:
- case IDC_DEBUGGER_VAL_X:
- case IDC_DEBUGGER_VAL_Y:
- case IDC_DEBUGGER_BOOKMARK:
-
- // Debugger -> Add breakpoint
- case IDC_ADDBP_ADDR_START: case IDC_ADDBP_ADDR_END:
-
- // Array Size, Init value in Symbolic Name in Debugger
- case IDC_EDIT_SYMBOLIC_ARRAY: case IDC_EDIT_SYMBOLIC_INIT:
-
- // Address, Value, Compare, Known Value, Note equal, Greater than and Less than in Cheat
- case IDC_CHEAT_ADDR: case IDC_CHEAT_VAL: case IDC_CHEAT_COM:
- case IDC_CHEAT_VAL_KNOWN: case IDC_CHEAT_VAL_NE_BY:
- case IDC_CHEAT_VAL_GT_BY: case IDC_CHEAT_VAL_LT_BY:
-
- // Address, Value and Compare in Game Genie Encoder/Decoder
- case IDC_GAME_GENIE_ADDR: case IDC_GAME_GENIE_VAL: case IDC_GAME_GENIE_COMP:
-
- // Address controls in Memory watch
- case MW_ADDR00: case MW_ADDR01: case MW_ADDR02: case MW_ADDR03:
- case MW_ADDR04: case MW_ADDR05: case MW_ADDR06: case MW_ADDR07:
- case MW_ADDR08: case MW_ADDR09: case MW_ADDR10: case MW_ADDR11:
- case MW_ADDR12: case MW_ADDR13: case MW_ADDR14: case MW_ADDR15:
- case MW_ADDR16: case MW_ADDR17: case MW_ADDR18: case MW_ADDR19:
- case MW_ADDR20: case MW_ADDR21: case MW_ADDR22: case MW_ADDR23:
- case IDC_EDIT_COMPAREADDRESS:
- return IsLetterLegalHex;
-
- // Specific Address in RAM Search
- // RAM Watch / RAM Search / Cheat -> Add watch (current only in adding watch operation)
- case IDC_EDIT_COMPAREADDRESSES:
- return IsLetterLegalHexList;
-
- // Size multiplier and TV Aspect in Video Config
- case IDC_WINSIZE_MUL_X: case IDC_WINSIZE_MUL_Y:
- case IDC_TVASPECT_X: case IDC_TVASPECT_Y:
- return IsLetterLegalFloat;
-
- // Cheat code in Cheat
- case IDC_CHEAT_TEXT:
- return IsLetterLegalCheat;
-
- // PRG ROM, PRG RAM, PRG NVRAM, CHR ROM, CHR RAM and CHR NVRAM in iNES Header Editor
- case IDC_PRGROM_EDIT: case IDC_PRGRAM_EDIT: case IDC_PRGNVRAM_EDIT:
- case IDC_CHRROM_EDIT: case IDC_CHRRAM_EDIT: case IDC_CHRNVRAM_EDIT:
- return IsLetterLegalSize;
-
- // Specific value, Different by and Modulo in RAM search
- case IDC_EDIT_COMPAREVALUE:
- case IDC_EDIT_DIFFBY:
- case IDC_EDIT_MODBY:
- {
- extern char rs_t;
- switch (rs_t)
- {
- case 's': return IsLetterLegalDecHexMixed;
- case 'u': return IsLetterLegalUnsignedDecHexMixed;
- case 'h': return IsLetterLegalHex;
- }
- }
- }
- return NULL;
+ return IsLetterLegalHex(index,letter) || letter == ',' || letter == ' ';
}
-void ShowLetterIllegalBalloonTip(HWND hwnd, bool(*IsLetterLegal)(char letter))
+bool IsLetterLegalCheat(int index, char letter)
{
- wchar_t* title = L"Unacceptable Character";
- wchar_t* msg = GetLetterIllegalErrMsg(IsLetterLegal);
-
- EDITBALLOONTIP tip;
- tip.cbStruct = sizeof(EDITBALLOONTIP);
- tip.pszText = msg;
- tip.pszTitle = title;
- tip.ttiIcon = TTI_ERROR;
- SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&tip);
-
- // make a sound
- MessageBeep(0xFFFFFFFF);
+ return letter >= '0' && letter <= ':' || letter >= 'A' && letter <= 'F' || letter >= 'a' && letter <= 'f' || letter == '?';
}
-inline wchar_t* GetLetterIllegalErrMsg(bool(*IsLetterLegal)(char letter))
+bool IsLetterLegalSize(int index, char letter)
{
- if (IsLetterLegal == IsLetterLegalGG)
+ return letter >= '0' && letter <= '9' || letter == 'm' || letter == 'M' || letter == 'k' || letter == 'K' || letter == 'b' || letter == 'B';
+}
+
+bool IsLetterLegalDec(int index, char letter)
+{
+ return letter >= '0' && letter <= '9' || letter == '-' || letter == '+';
+}
+
+bool IsLetterLegalFloat(int index, char letter)
+{
+ return letter >= '0' && letter <= '9' || letter == '.' || letter == '-' || letter == '+';
+}
+
+bool IsLetterLegalDecHexMixed(int index, char letter)
+{
+ return letter >= '0' && letter <= '9' || letter >= 'A' && letter <= 'F' || letter >= 'a' && letter <= 'f' || letter == '$' || letter == '-' || letter == '+';
+}
+
+bool IsLetterLegalUnsignedDecHexMixed(int index, char letter)
+{
+ return letter >= '0' && letter <= '9' || letter >= 'A' && letter <= 'F' || letter >= 'a' && letter <= 'f' || letter == '$';
+}
+
+wchar_t* GetLetterIllegalErrMsg(IsLetterLegalProc proc)
+{
+ if (proc == &IsLetterLegalGG)
return L"You can only type Game Genie characters:\nA P Z L G I T Y E O X U K S V N";
- if (IsLetterLegal == IsLetterLegalHex)
+ if (proc == &IsLetterLegalHex)
return L"You can only type characters for hexadecimal number (0-9,A-F).";
- if (IsLetterLegal == IsLetterLegalHexList)
+ if (proc == &IsLetterLegalHexList)
return L"You can only type characters for hexademical number (0-9,A-F), each number is separated by a comma (,)";
- if (IsLetterLegal == IsLetterLegalCheat)
+ if (proc == &IsLetterLegalCheat)
return
L"The cheat code comes into the following 2 formats:\n"
"AAAA:VV freezes the value in Address $AAAA to $VV.\n"
"AAAA?CC:VV changes the value in Address $AAAA to $VV only when it's $CC.\n"
"All the characters are hexadecimal number (0-9,A-F).\n";
- if (IsLetterLegal == IsLetterLegalFloat)
+ if (proc == &IsLetterLegalFloat)
return L"You can only type decimal number (decimal point is acceptable).";
- if (IsLetterLegal == IsLetterLegalSize)
+ if (proc == &IsLetterLegalSize)
return L"You can only type decimal number followed with B, KB or MB.";
- if (IsLetterLegal == IsLetterLegalDec)
+ if (proc == &IsLetterLegalDec)
return L"You can only type decimal number (sign character is acceptable).";
- if (IsLetterLegal == IsLetterLegalDecHexMixed)
+ if (proc == &IsLetterLegalDecHexMixed)
return
L"You can only type decimal or hexademical number\n"
"(sign character is acceptable).\n\n"
@@ -3463,7 +3418,7 @@ inline wchar_t* GetLetterIllegalErrMsg(bool(*IsLetterLegal)(char letter))
"you must add a $ prefix to prevent ambiguous.\n"
"eg. 10 is a decimal number,\n"
"$10 means a hexademical number that is 16 in decimal.";
- if (IsLetterLegal == IsLetterLegalUnsignedDecHexMixed)
+ if (proc == &IsLetterLegalUnsignedDecHexMixed)
return
L"You can only type decimal or hexademical number.\n\n"
"When your number contains letter A-F,\n"
@@ -3477,56 +3432,155 @@ inline wchar_t* GetLetterIllegalErrMsg(bool(*IsLetterLegal)(char letter))
return L"Your input contains invalid characters.";
}
-inline bool IsInputLegal(bool (*IsLetterLegal)(char letter), char letter)
+// return a letter legal checking function for the specified control with the given id
+IsLetterLegalProc GetIsLetterLegalProc(UINT id)
{
- return !IsLetterLegal || letter == VK_BACK || GetKeyState(VK_CONTROL) & 0x8000 || IsLetterLegal(letter);
+ switch (id)
+ {
+ // Game genie text in Cheat and Game Genie Encoder/Decoder
+ case IDC_CHEAT_GAME_GENIE_TEXT:
+ case IDC_GAME_GENIE_CODE:
+ return &IsLetterLegalGG;
+
+ // Addresses in Debugger
+ case IDC_DEBUGGER_VAL_PCSEEK:
+ case IDC_DEBUGGER_VAL_PC:
+ case IDC_DEBUGGER_VAL_A:
+ case IDC_DEBUGGER_VAL_X:
+ case IDC_DEBUGGER_VAL_Y:
+ case IDC_DEBUGGER_BOOKMARK:
+
+ // Debugger -> Add breakpoint
+ case IDC_ADDBP_ADDR_START: case IDC_ADDBP_ADDR_END:
+
+ // Array Size, Init value in Symbolic Name in Debugger
+ case IDC_EDIT_SYMBOLIC_ARRAY: case IDC_EDIT_SYMBOLIC_INIT:
+
+ // Address, Value, Compare, Known Value, Note equal, Greater than and Less than in Cheat
+ case IDC_CHEAT_ADDR: case IDC_CHEAT_VAL: case IDC_CHEAT_COM:
+ case IDC_CHEAT_VAL_KNOWN: case IDC_CHEAT_VAL_NE_BY:
+ case IDC_CHEAT_VAL_GT_BY: case IDC_CHEAT_VAL_LT_BY:
+
+ // Address, Value and Compare in Game Genie Encoder/Decoder
+ case IDC_GAME_GENIE_ADDR: case IDC_GAME_GENIE_VAL: case IDC_GAME_GENIE_COMP:
+
+ // Address controls in Memory watch
+ case MW_ADDR00: case MW_ADDR01: case MW_ADDR02: case MW_ADDR03:
+ case MW_ADDR04: case MW_ADDR05: case MW_ADDR06: case MW_ADDR07:
+ case MW_ADDR08: case MW_ADDR09: case MW_ADDR10: case MW_ADDR11:
+ case MW_ADDR12: case MW_ADDR13: case MW_ADDR14: case MW_ADDR15:
+ case MW_ADDR16: case MW_ADDR17: case MW_ADDR18: case MW_ADDR19:
+ case MW_ADDR20: case MW_ADDR21: case MW_ADDR22: case MW_ADDR23:
+ return &IsLetterLegalMemwatchAddress;
+
+ case IDC_EDIT_COMPAREADDRESS:
+ return &IsLetterLegalHex;
+
+ // Specific Address in RAM Search
+ // RAM Watch / RAM Search / Cheat -> Add watch (current only in adding watch operation)
+ case IDC_EDIT_COMPAREADDRESSES:
+ return &IsLetterLegalHexList;
+
+ // Size multiplier and TV Aspect in Video Config
+ case IDC_WINSIZE_MUL_X: case IDC_WINSIZE_MUL_Y:
+ case IDC_TVASPECT_X: case IDC_TVASPECT_Y:
+ return &IsLetterLegalFloat;
+
+ // Cheat code in Cheat
+ case IDC_CHEAT_TEXT:
+ return &IsLetterLegalCheat;
+
+ // PRG ROM, PRG RAM, PRG NVRAM, CHR ROM, CHR RAM and CHR NVRAM in NES Header Editor
+ case IDC_PRGROM_EDIT: case IDC_PRGRAM_EDIT: case IDC_PRGNVRAM_EDIT:
+ case IDC_CHRROM_EDIT: case IDC_CHRRAM_EDIT: case IDC_CHRNVRAM_EDIT:
+ return &IsLetterLegalSize;
+
+ // Specific value, Different by and Modulo in RAM search
+ case IDC_EDIT_COMPAREVALUE:
+ case IDC_EDIT_DIFFBY:
+ case IDC_EDIT_MODBY:
+ {
+ extern char rs_t;
+ switch (rs_t)
+ {
+ case 's': return &IsLetterLegalDecHexMixed;
+ case 'u': return &IsLetterLegalUnsignedDecHexMixed;
+ case 'h': return &IsLetterLegalHex;
+ }
+ }
+ }
+ return NULL;
}
-inline bool IsLetterLegalGG(char letter)
+LRESULT APIENTRY FilterEditCtrlProc(HWND hwnd, UINT msg, WPARAM wP, LPARAM lP)
{
- char ch = toupper(letter);
- for (int i = 0; GameGenieLetters[i]; ++i)
- if (GameGenieLetters[i] == ch)
- return true;
- return false;
+ bool through = true;
+ INT_PTR result = 0;
+
+ switch (msg)
+ {
+ case WM_PASTE:
+ {
+
+ IsLetterLegalProc isLetterLegal = GetIsLetterLegalProc(GetDlgCtrlID(hwnd));
+
+ if (isLetterLegal)
+ {
+ if (OpenClipboard(hwnd))
+ {
+ HANDLE handle = GetClipboardData(CF_TEXT);
+ if (handle)
+ {
+
+ // get the original clipboard string
+ char* clipStr = (char*)GlobalLock(handle);
+
+ // check if the text in clipboard has illegal characters
+ int len = strlen(clipStr);
+ for (int i = 0; i < len; ++i)
+ {
+ if (!isLetterLegal(i,clipStr[i]))
+ {
+ through = false;
+ // Show Edit control tip, just like the control with ES_NUMBER do
+ ShowLetterIllegalBalloonTip(hwnd, isLetterLegal);
+ break;
+ }
+ }
+ GlobalUnlock(handle);
+ CloseClipboard();
+ }
+ }
+ }
+ }
+ break;
+
+ case WM_CHAR:
+ {
+ DWORD cpBegin, cpEnd;
+ SendMessage(hwnd, EM_GETSEL, (LPARAM)&cpBegin, (LPARAM)&cpEnd);
+ IsLetterLegalProc isLetterLegal = GetIsLetterLegalProc(GetDlgCtrlID(hwnd));
+ through = IsInputLegal(isLetterLegal, (int)cpBegin, wP);
+ if (!through)
+ ShowLetterIllegalBalloonTip(hwnd, isLetterLegal);
+ }
+ }
+
+ return through ? CallWindowProc(DefaultEditCtrlProc, hwnd, msg, wP, lP) : result;
}
-inline bool IsLetterLegalHex(char letter)
+void ShowLetterIllegalBalloonTip(HWND hwnd, IsLetterLegalProc proc)
{
- return letter >= '0' && letter <= '9' || letter >= 'A' && letter <= 'F' || letter >= 'a' && letter <= 'f';
-}
+ wchar_t* title = L"Unacceptable Character";
+ wchar_t* msg = GetLetterIllegalErrMsg(proc);
-inline bool IsLetterLegalHexList(char letter)
-{
- return IsLetterLegalHex(letter) || letter == ',' || letter == ' ';
-}
+ EDITBALLOONTIP tip;
+ tip.cbStruct = sizeof(EDITBALLOONTIP);
+ tip.pszText = msg;
+ tip.pszTitle = title;
+ tip.ttiIcon = TTI_ERROR;
+ SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&tip);
-inline bool IsLetterLegalCheat(char letter)
-{
- return letter >= '0' && letter <= ':' || letter >= 'A' && letter <= 'F' || letter >= 'a' && letter <= 'f' || letter == '?';
-}
-
-inline bool IsLetterLegalSize(char letter)
-{
- return letter >= '0' && letter <= '9' || letter == 'm' || letter == 'M' || letter == 'k' || letter == 'K' || letter == 'b' || letter == 'B';
-}
-
-inline bool IsLetterLegalDec(char letter)
-{
- return letter >= '0' && letter <= '9' || letter == '-' || letter == '+';
-}
-
-inline bool IsLetterLegalFloat(char letter)
-{
- return letter >= '0' && letter <= '9' || letter == '.' || letter == '-' || letter == '+';
-}
-
-inline bool IsLetterLegalDecHexMixed(char letter)
-{
- return letter >= '0' && letter <= '9' || letter >= 'A' && letter <= 'F' || letter >= 'a' && letter <= 'f' || letter == '$' || letter == '-' || letter == '+';
-}
-
-inline bool IsLetterLegalUnsignedDecHexMixed(char letter)
-{
- return letter >= '0' && letter <= '9' || letter >= 'A' && letter <= 'F' || letter >= 'a' && letter <= 'f' || letter == '$';
+ // make a sound
+ MessageBeep(0xFFFFFFFF);
}
diff --git a/src/drivers/win/window.h b/src/drivers/win/window.h
index 0127ad97..da716a69 100644
--- a/src/drivers/win/window.h
+++ b/src/drivers/win/window.h
@@ -128,19 +128,9 @@ struct HOTKEYMENUINDEX {
void UpdateMenuHotkeys(FCEUMENU_INDEX index);
int GetCurrentContextIndex();
-inline bool (*GetIsLetterLegal(UINT id))(char letter);
-inline wchar_t* GetLetterIllegalErrMsg(bool(*IsLetterLegal)(char letter));
-void ShowLetterIllegalBalloonTip(HWND hwnd, bool(*IsLetterLegal)(char letter));
-inline bool IsInputLegal(bool(*IsLetterLegal)(char letter), char letter);
-inline bool IsLetterLegalGG(char letter);
-inline bool IsLetterLegalHex(char letter);
-inline bool IsLetterLegalHexList(char letter);
-inline bool IsLetterLegalCheat(char letter);
-inline bool IsLetterLegalDec(char letter);
-inline bool IsLetterLegalSize(char letter);
-inline bool IsLetterLegalFloat(char letter);
-inline bool IsLetterLegalDecHexMixed(char letter);
-inline bool IsLetterLegalUnsignedDecHexMixed(char letter);
+typedef bool (*IsLetterLegalProc)(int index, char ch);
+bool IsLetterLegalHex(int index, char letter);
+void ShowLetterIllegalBalloonTip(HWND hwnd, IsLetterLegalProc);
extern WNDPROC DefaultEditCtrlProc;
extern LRESULT APIENTRY FilterEditCtrlProc(HWND hDlg, UINT msg, WPARAM wP, LPARAM lP);
diff --git a/src/fceu.cpp b/src/fceu.cpp
index 83b8c223..28396c34 100644
--- a/src/fceu.cpp
+++ b/src/fceu.cpp
@@ -431,7 +431,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)
{
diff --git a/src/fds.cpp b/src/fds.cpp
index 35924a4a..f608436f 100644
--- a/src/fds.cpp
+++ b/src/fds.cpp
@@ -223,14 +223,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 +583,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) {
diff --git a/src/file.cpp b/src/file.cpp
index c927be7b..e4d5b4f6 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -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,15 +127,10 @@ 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;
}
fread(buf+offset,1,size,ips);
}
@@ -495,7 +484,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);
diff --git a/src/ines.cpp b/src/ines.cpp
index a14b1add..92fa0bdf 100644
--- a/src/ines.cpp
+++ b/src/ines.cpp
@@ -54,9 +54,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 LoadedRomFNamePatchToUse[2048];
static int CHRRAMSize = -1;
static int iNES_Init(int num);
@@ -107,11 +109,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) {
@@ -673,7 +675,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},
@@ -766,6 +768,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,17 +814,11 @@ 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);
}
@@ -918,6 +917,7 @@ 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);
switch(result)
diff --git a/src/ines.h b/src/ines.h
index 5561aef9..267ab963 100644
--- a/src/ines.h
+++ b/src/ines.h
@@ -43,9 +43,11 @@ 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 LoadedRomFNamePatchToUse[2048];
extern char *iNesShortFName(void);
extern const TMasterRomInfo* MasterRomInfo;
extern TMasterRomInfoParams MasterRomInfoParams;
@@ -242,6 +244,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 *);
diff --git a/src/input.cpp b/src/input.cpp
index 530f6948..592d5e50 100644
--- a/src/input.cpp
+++ b/src/input.cpp
@@ -798,6 +798,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);
@@ -945,6 +946,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 },
@@ -1268,6 +1270,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__
diff --git a/src/input.h b/src/input.h
index 0f89fca9..9928839f 100644
--- a/src/input.h
+++ b/src/input.h
@@ -259,6 +259,8 @@ enum EMUCMD
EMUCMD_MOVIE_RECORD_MODE_OVERWRITE,
EMUCMD_MOVIE_RECORD_MODE_INSERT,
+ EMUCMD_TOOL_TOGGLECHEATS,
+
EMUCMD_MAX
};
diff --git a/src/lua-engine.cpp b/src/lua-engine.cpp
index b647831b..88950e61 100644
--- a/src/lua-engine.cpp
+++ b/src/lua-engine.cpp
@@ -54,6 +54,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"
@@ -773,7 +776,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 +789,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) && (GGaddr == Caddr) && (GGval == Cval) && (GGcomp == Ccompare) && (Ctype == 1)) {
// Delete cheat code
if (FCEUI_DelCheat(i)) {
lua_pushboolean(L, true);
@@ -2638,6 +2641,113 @@ static int input_get(lua_State *L) {
}
}
}
+#elif defined(__QT_DRIVER__)
+ // Qt/SDL
+ {
+ const uint8_t *keyBuf = QtSDL_getKeyboardState(nullptr);
+
+ if (keyBuf)
+ {
+ int i=0;
+ char keyName[64];
+ const char *keyOut = nullptr;
+
+ for (int i=0; i(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
diff --git a/src/movie.cpp b/src/movie.cpp
index 6e6140cd..9bc3eb99 100644
--- a/src/movie.cpp
+++ b/src/movie.cpp
@@ -409,6 +409,7 @@ MovieData::MovieData()
, rerecordCount(0)
, binaryFlag(false)
, loadFrameCount(-1)
+ , fourscore(false)
, microphone(false)
, RAMInitOption(0)
, RAMInitSeed(0)
diff --git a/src/palettes/palettes.h b/src/palettes/palettes.h
index 7721bec9..7739d120 100644
--- a/src/palettes/palettes.h
+++ b/src/palettes/palettes.h
@@ -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 */
diff --git a/src/palettes/rp2c04001.h b/src/palettes/rp2c04001.h
index a7bdb7c0..399a5f27 100644
--- a/src/palettes/rp2c04001.h
+++ b/src/palettes/rp2c04001.h
@@ -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)},
diff --git a/src/palettes/rp2c04002.h b/src/palettes/rp2c04002.h
index a6e448c7..299c3eaf 100644
--- a/src/palettes/rp2c04002.h
+++ b/src/palettes/rp2c04002.h
@@ -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)},
diff --git a/src/palettes/rp2c04003.h b/src/palettes/rp2c04003.h
index 71170876..964a6d6f 100644
--- a/src/palettes/rp2c04003.h
+++ b/src/palettes/rp2c04003.h
@@ -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)},
diff --git a/src/palettes/rp2c05004.h b/src/palettes/rp2c05004.h
index a50ed704..36ae702e 100644
--- a/src/palettes/rp2c05004.h
+++ b/src/palettes/rp2c05004.h
@@ -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)},
diff --git a/src/ppu.cpp b/src/ppu.cpp
index 01a03a79..89bd1af9 100644
--- a/src/ppu.cpp
+++ b/src/ppu.cpp
@@ -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))
@@ -1987,6 +1988,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 +2000,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 +2017,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 +2243,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 +2288,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;
}
}
}
diff --git a/src/sound.cpp b/src/sound.cpp
index e17dae72..040132b0 100644
--- a/src/sound.cpp
+++ b/src/sound.cpp
@@ -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);
+ }
}
}
}
diff --git a/src/state.cpp b/src/state.cpp
index a29a46d0..78279c4b 100644
--- a/src/state.cpp
+++ b/src/state.cpp
@@ -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 }
};
@@ -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);
@@ -848,7 +859,7 @@ void ResetExState(void (*PreSave)(void), void (*PostSave)(void))
for(x=0;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);
diff --git a/src/video.cpp b/src/video.cpp
index 531c5f3c..20a48e76 100644
--- a/src/video.cpp
+++ b/src/video.cpp
@@ -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,28 +116,18 @@ 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);
diff --git a/src/video.h b/src/video.h
index 64e0688b..7fbb6bad 100644
--- a/src/video.h
+++ b/src/video.h
@@ -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
diff --git a/vc/vc14_fceux.vcxproj b/vc/vc14_fceux.vcxproj
index 29cb00b5..4611ee98 100644
--- a/vc/vc14_fceux.vcxproj
+++ b/vc/vc14_fceux.vcxproj
@@ -146,7 +146,7 @@
- "%windir%\Sysnative\cscript" /nologo /E:JScript "defaultconfig\make_scmrev.h.js"
+ "%windir%\system32\cscript" /nologo /E:JScript "defaultconfig\make_scmrev.h.js"
Disabled
@@ -186,7 +186,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)"
- "%windir%\Sysnative\cscript" /nologo /E:JScript "defaultconfig\make_scmrev.h.js"
+ "%windir%\system32\cscript" /nologo /E:JScript "defaultconfig\make_scmrev.h.js"
write current revision number to placeholders
@@ -229,7 +229,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)"
- "%windir%\Sysnative\cscript" /nologo /E:JScript "defaultconfig\make_scmrev.h.js"
+ "%windir%\system32\cscript" /nologo /E:JScript "defaultconfig\make_scmrev.h.js"
write current revision number to placeholders
@@ -298,7 +298,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)"
lua51.dll;%(DelayLoadDLLs)
- "%windir%\Sysnative\cscript" /nologo /E:JScript "defaultconfig\make_scmrev.h.js"
+ "%windir%\system32\cscript" /nologo /E:JScript "defaultconfig\make_scmrev.h.js"
xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z.dll" "$(OutDir)"
@@ -335,7 +335,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)"
lua51.dll;%(DelayLoadDLLs)
- "%windir%\Sysnative\cscript" /nologo /E:JScript "defaultconfig\make_scmrev.h.js"
+ "%windir%\system32\cscript" /nologo /E:JScript "defaultconfig\make_scmrev.h.js"
xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z.dll" "$(OutDir)"
@@ -372,7 +372,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)"
lua51.dll;%(DelayLoadDLLs)
- "%windir%\Sysnative\cscript" /nologo /E:JScript "defaultconfig\make_scmrev.h.js"
+ "%windir%\system32\cscript" /nologo /E:JScript "defaultconfig\make_scmrev.h.js"
xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z.dll" "$(OutDir)"