sync to latest FCEUX SVN

This commit is contained in:
dborth 2010-08-29 21:15:42 +00:00
parent 9dadc743d1
commit 647bf81a74
51 changed files with 2470 additions and 1005 deletions

View File

@ -10,6 +10,7 @@
***************************************************************************/ ***************************************************************************/
#include <malloc.h> #include <malloc.h>
#include <gctypes.h>
#include "fceugx.h" #include "fceugx.h"
#include "fceusupport.h" #include "fceusupport.h"

View File

@ -310,7 +310,7 @@ void USBGeckoOutput()
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
//USBGeckoOutput(); // uncomment to enable USB gecko output USBGeckoOutput(); // uncomment to enable USB gecko output
__exception_setreload(8); __exception_setreload(8);
#ifdef HW_DOL #ifdef HW_DOL

View File

@ -16,6 +16,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include <gctypes.h>
#include "fceultra/file.h" #include "fceultra/file.h"
@ -64,7 +65,7 @@ int GCMemROM(int size)
fceufp->size = size; fceufp->size = size;
fceufp->filename = romFilename; fceufp->filename = romFilename;
fceufp->mode = FCEUFILE::READ; // read only fceufp->mode = FCEUFILE::READ; // read only
memorystream * fceumem = new memorystream((char *) nesrom, size); EMUFILE_MEMFILE *fceumem = new EMUFILE_MEMFILE(nesrom, size);
fceufp->stream = fceumem; fceufp->stream = fceumem;
romLoaded = iNESLoad(romFilename, fceufp, 1); romLoaded = iNESLoad(romFilename, fceufp, 1);

View File

@ -139,7 +139,7 @@ static uint64 lreset;
static DECLFW(MMC1_write) static DECLFW(MMC1_write)
{ {
int n=(A>>13)-4; int n=(A>>13)-4;
//FCEU_DispMessage("%016x",timestampbase+timestamp); //FCEU_DispMessage("%016x",0,timestampbase+timestamp);
// FCEU_printf("$%04x:$%02x, $%04x\n",A,V,X.PC); // FCEU_printf("$%04x:$%02x, $%04x\n",A,V,X.PC);
//DumpMem("out",0xe000,0xffff); //DumpMem("out",0xe000,0xffff);

View File

@ -467,4 +467,5 @@ void Mapper210_Init(CartInfo *info)
GameStateRestore=Mapper210_StateRestore; GameStateRestore=Mapper210_StateRestore;
info->Power=N106_Power; info->Power=N106_Power;
AddExState(WRAM, 8192, 0, "WRAM"); AddExState(WRAM, 8192, 0, "WRAM");
AddExState(N106_StateRegs, ~0, 0, 0);
} }

View File

@ -132,7 +132,7 @@ void RebuildSubCheats(void)
if(GetReadHandler(c->addr)==SubCheatsRead) if(GetReadHandler(c->addr)==SubCheatsRead)
{ {
/* Prevent a catastrophe by this check. */ /* Prevent a catastrophe by this check. */
//FCEU_DispMessage("oops"); //FCEU_DispMessage("oops",0);
} }
else else
{ {
@ -148,7 +148,7 @@ void RebuildSubCheats(void)
} }
FrozenAddressCount = numsubcheats; //Update the frozen address list FrozenAddressCount = numsubcheats; //Update the frozen address list
UpdateFrozenList(); UpdateFrozenList();
//FCEUI_DispMessage("Active Cheats: %d", FrozenAddresses.size()/*FrozenAddressCount*/); //Debug //FCEUI_DispMessage("Active Cheats: %d",0, FrozenAddresses.size()/*FrozenAddressCount*/); //Debug
} }
void FCEU_PowerCheats() void FCEU_PowerCheats()
@ -217,8 +217,8 @@ void FCEU_LoadGameCheats(FILE *override)
if(!fp) return; if(!fp) return;
} }
FCEU_DispMessage("Cheats file loaded."); //Tells user a cheats file was loaded. FCEU_DispMessage("Cheats file loaded.",0); //Tells user a cheats file was loaded.
FCEU_printf("Cheats file loaded.\n"); //Sends message to message log. FCEU_printf("Cheats file loaded.\n",0); //Sends message to message log.
while(fgets(linebuf,2048,fp)>0) while(fgets(linebuf,2048,fp)>0)
{ {
char *tbuf=linebuf; char *tbuf=linebuf;
@ -951,5 +951,5 @@ void UpdateFrozenList(void)
FrozenAddresses.push_back(SubCheats[x].addr); FrozenAddresses.push_back(SubCheats[x].addr);
//FCEU_printf("Address %d: %d \n",x,FrozenAddresses[x]); //Debug //FCEU_printf("Address %d: %d \n",x,FrozenAddresses[x]); //Debug
} }
//FCEUI_DispMessage("FrozenCount: %d",FrozenAddressCount);//Debug //FCEUI_DispMessage("FrozenCount: %d",0,FrozenAddressCount);//Debug
} }

View File

@ -36,6 +36,7 @@
* Address -> '$' [1-9A-F]* | '$' '[' Connect ']' * Address -> '$' [1-9A-F]* | '$' '[' Connect ']'
* Register -> 'A' | 'X' | 'Y' | 'R' * Register -> 'A' | 'X' | 'Y' | 'R'
* Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V' * Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V'
* PC Bank -> 'K'
*/ */
#include <stdio.h> #include <stdio.h>
@ -131,6 +132,12 @@ int isRegister(char c)
return c == 'A' || c == 'X' || c == 'Y' || c == 'P'; return c == 'A' || c == 'X' || c == 'Y' || c == 'P';
} }
// Determines if a character is for bank
int isBank(char c)
{
return c == 'K';
}
// Reads a hexadecimal number from str // Reads a hexadecimal number from str
int getNumber(unsigned int* number, const char** str) int getNumber(unsigned int* number, const char** str)
{ {
@ -217,6 +224,23 @@ Condition* Primitive(const char** str, Condition* c)
return c; return c;
} }
else if (isBank(next)) /* Registers */
{
if (c->type1 == TYPE_NO)
{
c->type1 = TYPE_BANK;
c->value1 = next;
}
else
{
c->type2 = TYPE_BANK;
c->value2 = next;
}
scan(str);
return c;
}
else if (next == '#') /* Numbers */ else if (next == '#') /* Numbers */
{ {
unsigned int number = 0; unsigned int number = 0;

View File

@ -26,6 +26,7 @@
#define TYPE_FLAG 2 #define TYPE_FLAG 2
#define TYPE_NUM 3 #define TYPE_NUM 3
#define TYPE_ADDR 4 #define TYPE_ADDR 4
#define TYPE_BANK 5
#define OP_NO 0 #define OP_NO 0
#define OP_EQ 1 #define OP_EQ 1

View File

@ -195,13 +195,36 @@ unsigned int NewBreak(const char* name, int start, int end, unsigned int type, c
} }
int GetPRGAddress(int A){ int GetPRGAddress(int A){
unsigned int result; int result;
if((A < 0x8000) || (A > 0xFFFF))return -1; if((A < 0x8000) || (A > 0xFFFF))return -1;
result = &Page[A>>11][A]-PRGptr[0]; result = &Page[A>>11][A]-PRGptr[0];
if((result > PRGsize[0]) || (result < 0))return -1; if((result > (int)PRGsize[0]) || (result < 0))return -1;
else return result; else return result;
} }
/**
* Returns the bank for a given offset.
* Technically speaking this function does not calculate the actual bank
* where the offset resides but the 0x4000 bytes large chunk of the ROM of the offset.
*
* @param offs The offset
* @return The bank of that offset or -1 if the offset is not part of the ROM.
**/
int getBank(int offs)
{
//NSF data is easy to overflow the return on.
//Anything over FFFFF will kill it.
//GetNesFileAddress doesn't work well with Unif files
int addr = GetNesFileAddress(offs)-16;
if (GameInfo && GameInfo->type==GIT_NSF) {
return addr != -1 ? addr / 0x1000 : -1;
}
return addr != -1 ? addr / 0x4000 : -1;
}
int GetNesFileAddress(int A){ int GetNesFileAddress(int A){
unsigned int result; unsigned int result;
if((A < 0x8000) || (A > 0xFFFF))return -1; if((A < 0x8000) || (A > 0xFFFF))return -1;
@ -272,15 +295,16 @@ int evaluate(Condition* c)
{ {
switch(c->type1) switch(c->type1)
{ {
case TYPE_ADDR: case TYPE_ADDR: // This is intended to not break, and use the TYPE_NUM code
case TYPE_NUM: value1 = c->value1; break; case TYPE_NUM: value1 = c->value1; break;
default: value1 = getValue(c->value1); default: value1 = getValue(c->value1); break;
} }
} }
if (c->type1 == TYPE_ADDR) switch(c->type1)
{ {
value1 = GetMem(value1); case TYPE_ADDR: value1 = GetMem(value1); break;
case TYPE_BANK: value1 = getBank(_PC); break;
} }
f = value1; f = value1;
@ -295,15 +319,16 @@ int evaluate(Condition* c)
{ {
switch(c->type2) switch(c->type2)
{ {
case TYPE_ADDR: case TYPE_ADDR: // This is intended to not break, and use the TYPE_NUM code
case TYPE_NUM: value2 = c->value2; break; case TYPE_NUM: value2 = c->value2; break;
default: value2 = getValue(c->type2); default: value2 = getValue(c->type2); break;
} }
} }
if (c->type2 == TYPE_ADDR) switch(c->type2)
{ {
value2 = GetMem(value2); case TYPE_ADDR: value2 = GetMem(value2); break;
case TYPE_BANK: value2 = getBank(_PC); break;
} }
switch (c->op) switch (c->op)
@ -335,93 +360,94 @@ int condition(watchpointinfo* wp)
//--------------------- //---------------------
volatile int codecount, datacount, undefinedcount; volatile int codecount, datacount, undefinedcount;
//HWND hCDLogger=0;
unsigned char *cdloggerdata; unsigned char *cdloggerdata;
char *cdlogfilename; char *cdlogfilename;
//char loadedcdfile[MAX_PATH];
static int indirectnext; static int indirectnext;
int debug_loggingCD; int debug_loggingCD;
//called by the cpu to perform logging if CDLogging is enabled //called by the cpu to perform logging if CDLogging is enabled
void LogCDVectors(int which){ void LogCDVectors(int which){
int i = 0xFFFA+(which*2);
int j; int j;
j = GetPRGAddress(i); j = GetPRGAddress(which);
if(j == -1){ if(j == -1){
return; return;
} }
if(cdloggerdata[j] == 0){ if(!(cdloggerdata[j] & 2)){
cdloggerdata[j] |= 0x0E; // we're in the last bank and recording it as data so 0x1110 or 0xE should be what we need cdloggerdata[j] |= 0x0E; // we're in the last bank and recording it as data so 0x1110 or 0xE should be what we need
datacount++; datacount++;
undefinedcount--; if(!(cdloggerdata[j] & 1))undefinedcount--;
} }
j++; j++;
if(cdloggerdata[j] == 0){ if(!(cdloggerdata[j] & 2)){
cdloggerdata[j] |= 0x0E; // we're in the last bank and recording it as data so 0x1110 or 0xE should be what we need cdloggerdata[j] |= 0x0E;
datacount++; datacount++;
undefinedcount--; if(!(cdloggerdata[j] & 1))undefinedcount--;
} }
return;
} }
void LogCDData(){ void LogCDData(){
int i, j; int i, j;
uint16 A = 0; uint16 A = 0;
uint8 opcode[3] = {0}; uint8 opcode[3] = {0}, memop = 0;
j = GetPRGAddress(_PC); j = GetPRGAddress(_PC);
opcode[0] = GetMem(_PC);
for (i = 1; i < opsize[opcode[0]]; i++) opcode[i] = GetMem(_PC+i);
if(j != -1) { if(j != -1) {
opcode[0] = GetMem(_PC);
switch (opsize[opcode[0]]) {
case 2:
opcode[1] = GetMem(_PC + 1);
break;
case 3:
opcode[1] = GetMem(_PC + 1);
opcode[2] = GetMem(_PC + 2);
break;
}
for (i = 0; i < opsize[opcode[0]]; i++){ for (i = 0; i < opsize[opcode[0]]; i++){
if(cdloggerdata[j+i] & 1)continue; //this has been logged so skip if(cdloggerdata[j+i] & 1)continue; //this has been logged so skip
cdloggerdata[j+i] |= 1; cdloggerdata[j+i] |= 1;
cdloggerdata[j+i] |=((_PC+i)>>11)&12; cdloggerdata[j+i] |=((_PC+i)>>11)&0x0c;
if(indirectnext)cdloggerdata[j+i] |= 0x10; if(indirectnext)cdloggerdata[j+i] |= 0x10;
codecount++; codecount++;
if(!(cdloggerdata[j+i] & 0x42))undefinedcount--; if(!(cdloggerdata[j+i] & 2))undefinedcount--;
} }
}
indirectnext = 0;
//log instruction jumped to in an indirect jump //log instruction jumped to in an indirect jump
if(opcode[0] == 0x6c){ if(opcode[0] == 0x6c) indirectnext = 1; else indirectnext = 0;
indirectnext = 1;
}
switch (optype[opcode[0]]) { switch (optype[opcode[0]]) {
case 0: break; case 0: break;
case 1: case 1:
A = (opcode[1]+_X) & 0xFF; A = (opcode[1]+_X) & 0xFF;
A = GetMem(A) | (GetMem(A+1))<<8; A = GetMem(A) | (GetMem(A+1)<<8);
memop = 0x20;
break; break;
case 2: A = opcode[1]; break; case 2: A = opcode[1]; break;
case 3: A = opcode[1] | opcode[2]<<8; break; case 3: A = opcode[1] | opcode[2]<<8; break;
case 4: A = (GetMem(opcode[1]) | (GetMem(opcode[1]+1))<<8)+_Y; break; case 4:
A = (GetMem(opcode[1]) | (GetMem(opcode[1]+1)<<8))+_Y;
memop = 0x20;
break;
case 5: A = opcode[1]+_X; break; case 5: A = opcode[1]+_X; break;
case 6: A = (opcode[1] | opcode[2]<<8)+_Y; break; case 6: A = (opcode[1] | (opcode[2]<<8))+_Y; break;
case 7: A = (opcode[1] | opcode[2]<<8)+_X; break; case 7: A = (opcode[1] | (opcode[2]<<8))+_X; break;
case 8: A = opcode[1]+_Y; break; case 8: A = opcode[1]+_Y; break;
} }
//if(opbrktype[opcode[0]] != WP_R)return; //we only want reads if((j = GetPRGAddress(A)) != -1) {
if(!(cdloggerdata[j] & 2)) {
if((j = GetPRGAddress(A)) == -1)return;
//if(j == 0)BreakHit();
if(cdloggerdata[j] & 2)return;
cdloggerdata[j] |= 2; cdloggerdata[j] |= 2;
cdloggerdata[j] |=((A/*+i*/)>>11)&12; cdloggerdata[j] |=(A>>11)&0x0c;
if((optype[opcode[0]] == 1) || (optype[opcode[0]] == 4))cdloggerdata[j] |= 0x20; cdloggerdata[j] |= memop;
datacount++; datacount++;
if(!(cdloggerdata[j+i] & 1))undefinedcount--; if(!(cdloggerdata[j] & 1))undefinedcount--;
return; }
}
}
} }
//-----------debugger stuff //-----------debugger stuff
@ -444,7 +470,7 @@ void BreakHit(bool force = false) {
//check to see whether we fall in any forbid zone //check to see whether we fall in any forbid zone
for (int i = 0; i < numWPs; i++) { for (int i = 0; i < numWPs; i++) {
watchpointinfo& wp = watchpoint[i]; watchpointinfo& wp = watchpoint[i];
if(!(wp.flags & WP_F)) if(!(wp.flags & WP_F) || !(wp.flags & WP_E))
continue; continue;
if (condition(&wp)) if (condition(&wp))
@ -467,47 +493,17 @@ void BreakHit(bool force = false) {
FCEUD_DebugBreakpoint(); FCEUD_DebugBreakpoint();
} }
/*
//very ineffecient, but this shouldn't get executed THAT much uint8 StackAddrBackup = X.S;
if(!(cdloggerdata[GetPRGAddress(0xFFFA)] & 2)){ uint16 StackNextIgnorePC = 0xFFFF;
cdloggerdata[GetPRGAddress(0xFFFA)]|=2;
codecount++;
undefinedcount--;
}
if(!(cdloggerdata[GetPRGAddress(0xFFFB)] & 2)){
cdloggerdata[GetPRGAddress(0xFFFB)]|=2;
codecount++;
undefinedcount--;
}
if(!(cdloggerdata[GetPRGAddress(0xFFFC)] & 2)){
cdloggerdata[GetPRGAddress(0xFFFC)]|=2;
codecount++;
undefinedcount--;
}
if(!(cdloggerdata[GetPRGAddress(0xFFFD)] & 2)){
cdloggerdata[GetPRGAddress(0xFFFD)]|=2;
codecount++;
undefinedcount--;
}
if(!(cdloggerdata[GetPRGAddress(0xFFFE)] & 2)){
cdloggerdata[GetPRGAddress(0xFFFE)]|=2;
codecount++;
undefinedcount--;
}
if(!(cdloggerdata[GetPRGAddress(0xFFFF)] & 2)){
cdloggerdata[GetPRGAddress(0xFFFF)]|=2;
codecount++;
undefinedcount--;
}
return;
}
*/
///fires a breakpoint ///fires a breakpoint
void breakpoint() { void breakpoint() {
int i; int i,j;
uint16 A=0; uint16 A=0;
uint8 brk_type,opcode[3] = {0}; uint8 brk_type,opcode[3] = {0};
uint8 stackop=0;
uint8 stackopstartaddr,stackopendaddr;
//inspect the current opcode //inspect the current opcode
opcode[0] = GetMem(_PC); opcode[0] = GetMem(_PC);
@ -572,6 +568,21 @@ void breakpoint() {
case 8: A = opcode[1]+_Y; break; case 8: A = opcode[1]+_Y; break;
} }
switch (opcode[0]) {
//Push Ops
case 0x08: //Fall to next
case 0x48: stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
//Pull Ops
case 0x28: //Fall to next
case 0x68: stackopstartaddr=stackopendaddr=X.S+1; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
//JSR (Includes return address - 1)
case 0x20: stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=(opcode[1]|opcode[2]<<8); break;
//RTI (Includes processor status, and exact return address)
case 0x40: stackopstartaddr=X.S+1; stackopendaddr=X.S+3; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=(GetMem(X.S+2|0x0100)|GetMem(X.S+3|0x0100)<<8); break;
//RTS (Includes return address - 1)
case 0x60: stackopstartaddr=X.S+1; stackopendaddr=X.S+2; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=(GetMem(stackopstartaddr|0x0100)|GetMem(stackopendaddr|0x0100)<<8)+1; break;
}
for (i = 0; i < numWPs; i++) { for (i = 0; i < numWPs; i++) {
// ################################## Start of SP CODE ########################### // ################################## Start of SP CODE ###########################
if (condition(&watchpoint[i])) if (condition(&watchpoint[i]))
@ -597,17 +608,67 @@ void breakpoint() {
else { //CPU mem breaks else { //CPU mem breaks
if ((watchpoint[i].flags & WP_E) && (watchpoint[i].flags & brk_type)) { if ((watchpoint[i].flags & WP_E) && (watchpoint[i].flags & brk_type)) {
if (watchpoint[i].endaddress) { if (watchpoint[i].endaddress) {
if (((!(watchpoint[i].flags & WP_X)) && (watchpoint[i].address <= A) && (watchpoint[i].endaddress >= A)) || if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address <= A) && (watchpoint[i].endaddress >= A)) ||
((watchpoint[i].flags & WP_X) && (watchpoint[i].address <= _PC) && (watchpoint[i].endaddress >= _PC))) BreakHit(); ((watchpoint[i].flags & WP_X) && (watchpoint[i].address <= _PC) && (watchpoint[i].endaddress >= _PC))) BreakHit();
} }
else if (((!(watchpoint[i].flags & WP_X)) && (watchpoint[i].address == A)) || else if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address == A)) ||
((watchpoint[i].flags & WP_X) && (watchpoint[i].address == _PC))) BreakHit(); ((watchpoint[i].flags & WP_X) && (watchpoint[i].address == _PC))) BreakHit();
} }
else if (watchpoint[i].flags & WP_E) {
//brk_type independant coding
if (stackop>0) {
//Announced stack mem breaks
//PHA, PLA, PHP, and PLP affect the stack data.
//TXS and TSX only deal with the pointer.
if (watchpoint[i].flags & stackop) {
for (j = (stackopstartaddr|0x0100); j <= (stackopendaddr|0x0100); j++) {
if (watchpoint[i].endaddress) {
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j)) BreakHit();
}
else if (watchpoint[i].address == j) BreakHit();
}
}
}
if (StackNextIgnorePC==_PC) {
//Used to make it ignore the unannounced stack code one time
StackNextIgnorePC = 0xFFFF;
} else
{
if ((X.S < StackAddrBackup) && (stackop==0)) {
//Unannounced stack mem breaks
//Pushes to stack
if (watchpoint[i].flags & WP_W) {
for (j = (X.S|0x0100); j < (StackAddrBackup|0x0100); j++) {
if (watchpoint[i].endaddress) {
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j)) BreakHit();
}
else if (watchpoint[i].address == j) BreakHit();
}
}
}
else if ((StackAddrBackup < X.S) && (stackop==0)) {
//Pulls from stack
if (watchpoint[i].flags & WP_R) {
for (j = (StackAddrBackup|0x0100); j < (X.S|0x0100); j++) {
if (watchpoint[i].endaddress) {
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j)) BreakHit();
}
else if (watchpoint[i].address == j) BreakHit();
}
}
}
}
}
} }
// ################################## Start of SP CODE ########################### // ################################## Start of SP CODE ###########################
} }
// ################################## End of SP CODE ########################### // ################################## End of SP CODE ###########################
} }
//Update the stack address with the current one, now that changes have registered.
StackAddrBackup = X.S;
} }
//bbit edited: this is the end of the inserted code //bbit edited: this is the end of the inserted code
@ -617,8 +678,8 @@ void DebugCycle() {
if (scanline == 240) if (scanline == 240)
{ {
vblankScanLines = (timestamp / 114); //114 approximates the number of timestamps per scanline during vblank. Approx 2508 vblankScanLines = (PAL?int((double)timestamp / ((double)341 / (double)3.2)):timestamp / 114); //114 approximates the number of timestamps per scanline during vblank. Approx 2508. NTSC: (341 / 3.0) PAL: (341 / 3.2). Uses (3.? * cpu_cycles) / 341.0, and assumes 1 cpu cycle.
if (vblankScanLines) vblankPixel = 341 / vblankScanLines; //314 pixels per scanline if (vblankScanLines) vblankPixel = 341 / vblankScanLines; //341 pixels per scanline
//FCEUI_printf("vbPixel = %d",vblankPixel); //Debug //FCEUI_printf("vbPixel = %d",vblankPixel); //Debug
//FCEUI_printf("ts: %d line: %d\n", timestamp, vblankScanLines); //Debug //FCEUI_printf("ts: %d line: %d\n", timestamp, vblankScanLines); //Debug
} }

View File

@ -55,6 +55,7 @@ typedef struct {
//mbg merge 7/18/06 had to make this extern //mbg merge 7/18/06 had to make this extern
extern watchpointinfo watchpoint[65]; //64 watchpoints, + 1 reserved for step over extern watchpointinfo watchpoint[65]; //64 watchpoints, + 1 reserved for step over
int getBank(int offs);
int GetNesFileAddress(int A); int GetNesFileAddress(int A);
int GetPRGAddress(int A); int GetPRGAddress(int A);
int GetRomAddress(int A); int GetRomAddress(int A);

View File

@ -135,6 +135,10 @@ void DrawMessage(bool beforeMovie)
uint8 *t; uint8 *t;
guiMessage.howlong--; guiMessage.howlong--;
if (guiMessage.linesFromBottom > 0)
t=XBuf+FCEU_TextScanlineOffsetFromBottom(guiMessage.linesFromBottom)+1;
else
t=XBuf+FCEU_TextScanlineOffsetFromBottom(20)+1; t=XBuf+FCEU_TextScanlineOffsetFromBottom(20)+1;
/* /*
@ -336,7 +340,7 @@ void FCEU_DrawRecordingStatus(uint8* XBuf)
drawstatus(XBuf-ClipSidesOffset,2,28,0); drawstatus(XBuf-ClipSidesOffset,2,28,0);
hasPlayRecIcon = true; hasPlayRecIcon = true;
} }
else if(FCEUMOV_Mode(MOVIEMODE_PLAY)) else if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_FINISHED))
{ {
drawstatus(XBuf-ClipSidesOffset,1,28,0); drawstatus(XBuf-ClipSidesOffset,1,28,0);
hasPlayRecIcon = true; hasPlayRecIcon = true;

View File

@ -11,8 +11,8 @@
FILE *FCEUD_UTF8fopen(const char *fn, const char *mode); FILE *FCEUD_UTF8fopen(const char *fn, const char *mode);
inline FILE *FCEUD_UTF8fopen(const std::string &n, const char *mode) { return FCEUD_UTF8fopen(n.c_str(),mode); } inline FILE *FCEUD_UTF8fopen(const std::string &n, const char *mode) { return FCEUD_UTF8fopen(n.c_str(),mode); }
std::fstream* FCEUD_UTF8_fstream(const char *n, const char *m); EMUFILE_FILE* FCEUD_UTF8_fstream(const char *n, const char *m);
inline std::fstream* FCEUD_UTF8_fstream(const std::string &n, const char *m) { return FCEUD_UTF8_fstream(n.c_str(),m); } inline EMUFILE_FILE* FCEUD_UTF8_fstream(const std::string &n, const char *m) { return FCEUD_UTF8_fstream(n.c_str(),m); }
FCEUFILE* FCEUD_OpenArchiveIndex(ArchiveScanRecord& asr, std::string& fname, int innerIndex); FCEUFILE* FCEUD_OpenArchiveIndex(ArchiveScanRecord& asr, std::string& fname, int innerIndex);
FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename); FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename);
ArchiveScanRecord FCEUD_ScanArchive(std::string fname); ArchiveScanRecord FCEUD_ScanArchive(std::string fname);
@ -77,6 +77,8 @@ void FCEUI_SetInputFC(ESIFC type, void *ptr, int attrib);
void FCEUI_SetInputFourscore(bool attachFourscore); void FCEUI_SetInputFourscore(bool attachFourscore);
//tells whether a fourscore is attached //tells whether a fourscore is attached
bool FCEUI_GetInputFourscore(); bool FCEUI_GetInputFourscore();
//tells whether the microphone is used
bool FCEUI_GetInputMicrophone();
void FCEUI_UseInputPreset(int preset); void FCEUI_UseInputPreset(int preset);
@ -167,7 +169,7 @@ void FCEUD_LoadStateFrom(void);
//at the minimum, you should call FCEUI_SetInput, FCEUI_SetInputFC, and FCEUI_SetInputFourscore //at the minimum, you should call FCEUI_SetInput, FCEUI_SetInputFC, and FCEUI_SetInputFourscore
//you may also need to maintain your own internal state //you may also need to maintain your own internal state
void FCEUD_SetInput(bool fourscore, ESI port0, ESI port1, ESIFC fcexp); void FCEUD_SetInput(bool fourscore, bool microphone, ESI port0, ESI port1, ESIFC fcexp);
void FCEUD_MovieRecordTo(void); void FCEUD_MovieRecordTo(void);
@ -176,7 +178,8 @@ void FCEUD_LuaRunFrom(void);
int32 FCEUI_GetDesiredFPS(void); int32 FCEUI_GetDesiredFPS(void);
void FCEUI_SaveSnapshot(void); void FCEUI_SaveSnapshot(void);
void FCEU_DispMessage(char *format, ...); void FCEUI_SaveSnapshotAs(void);
void FCEU_DispMessage(char *format, int disppos, ...);
#define FCEUI_DispMessage FCEU_DispMessage #define FCEUI_DispMessage FCEU_DispMessage
int FCEUI_DecodePAR(const char *code, int *a, int *v, int *c, int *type); int FCEUI_DecodePAR(const char *code, int *a, int *v, int *c, int *type);

View File

@ -0,0 +1,28 @@
#include "types.h"
#include "emufile.h"
#include <vector>
bool EMUFILE::readAllBytes(std::vector<u8>* dstbuf, const std::string& fname)
{
EMUFILE_FILE file(fname.c_str(),"rb");
if(file.fail()) return false;
int size = file.size();
dstbuf->resize(size);
file.fread(&dstbuf->at(0),size);
return true;
}
EMUFILE* EMUFILE::memwrap(EMUFILE* fp)
{
EMUFILE_FILE* file;
EMUFILE_MEMORY* mem;
file = dynamic_cast<EMUFILE_FILE*>(fp);
mem = dynamic_cast<EMUFILE_MEMORY*>(fp);
if(mem) return mem;
mem = new EMUFILE_MEMORY(file->size());
if(file->size()==0) return mem;
file->fread(mem->buf(),file->size());
delete file;
return mem;
}

428
source/fceultra/emufile.h Normal file
View File

@ -0,0 +1,428 @@
/* Copyright (C) 2009 DeSmuME team
*
* This file is part of DeSmuME
*
* DeSmuME is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* DeSmuME is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DeSmuME; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef EMUFILE_H
#define EMUFILE_H
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
#include <string>
#include <stdarg.h>
#include <malloc.h>
//should be changed to #ifdef FCEUX but too much work
#ifndef DESMUME
#ifndef __GCTYPES_H__
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef char s8;
typedef short s16;
typedef int s32;
#endif
#endif
#ifdef _XBOX
#undef min;
#undef max;
#endif
class EMUFILE {
protected:
bool failbit;
public:
EMUFILE()
: failbit(false)
{}
//takes control of the provided EMUFILE and returns a new EMUFILE which is guranteed to be in memory
static EMUFILE* memwrap(EMUFILE* fp);
virtual ~EMUFILE() {}
static bool readAllBytes(std::vector<u8>* buf, const std::string& fname);
bool fail() { return failbit; }
bool eof() { return size()==ftell(); }
size_t fread(const void *ptr, size_t bytes){
return _fread(ptr,bytes);
}
void unget() { fseek(-1,SEEK_CUR); }
//virtuals
public:
virtual FILE *get_fp() = 0;
virtual int fprintf(const char *format, ...) = 0;
virtual int fgetc() = 0;
virtual int fputc(int c) = 0;
virtual size_t _fread(const void *ptr, size_t bytes) = 0;
//removing these return values for now so we can find any code that might be using them and make sure
//they handle the return values correctly
virtual void fwrite(const void *ptr, size_t bytes) = 0;
virtual int fseek(int offset, int origin) = 0;
virtual int ftell() = 0;
virtual int size() = 0;
};
//todo - handle read-only specially?
class EMUFILE_MEMORY : public EMUFILE {
protected:
std::vector<u8> *vec;
bool ownvec;
s32 pos, len;
void reserve(u32 amt) {
if(vec->size() < amt)
vec->resize(amt);
}
public:
EMUFILE_MEMORY(std::vector<u8> *underlying) : vec(underlying), ownvec(false), pos(0), len(underlying->size()) { }
EMUFILE_MEMORY(u32 preallocate) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) {
vec->resize(preallocate);
len = preallocate;
}
EMUFILE_MEMORY() : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) { vec->reserve(1024); }
EMUFILE_MEMORY(void* buf, s32 size) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(size) {
vec->resize(size);
if(size != 0)
memcpy(&vec[0],buf,size);
}
~EMUFILE_MEMORY() {
if(ownvec) delete vec;
}
u8* buf() { return &(*vec)[0]; }
std::vector<u8>* get_vec() { return vec; };
virtual FILE *get_fp() { return NULL; }
virtual int fprintf(const char *format, ...) {
va_list argptr;
va_start(argptr, format);
//we dont generate straight into the buffer because it will null terminate (one more byte than we want)
int amt = vsnprintf(0,0,format,argptr);
char* tempbuf = new char[amt+1];
vsprintf(tempbuf,format,argptr);
fwrite(tempbuf,amt);
delete[] tempbuf;
va_end(argptr);
return amt;
};
virtual int fgetc() {
u8 temp;
//need an optimized codepath
//if(_fread(&temp,1) != 1)
// return EOF;
//else return temp;
u32 remain = len-pos;
if(remain<1) {
failbit = true;
return -1;
}
temp = buf()[pos];
pos++;
return temp;
}
virtual int fputc(int c) {
u8 temp = (u8)c;
//TODO
//if(fwrite(&temp,1)!=1) return EOF;
fwrite(&temp,1);
return 0;
}
virtual size_t _fread(const void *ptr, size_t bytes){
u32 remain = len-pos;
u32 todo = std::min<u32>(remain,(u32)bytes);
memcpy((void*)ptr,buf()+pos,todo);
pos += todo;
if(todo<bytes)
failbit = true;
return todo;
}
//removing these return values for now so we can find any code that might be using them and make sure
//they handle the return values correctly
virtual void fwrite(const void *ptr, size_t bytes){
reserve(pos+bytes);
memcpy(buf()+pos,ptr,bytes);
pos += bytes;
len = std::max(pos,len);
}
virtual int fseek(int offset, int origin){
//work differently for read-only...?
switch(origin) {
case SEEK_SET:
pos = offset;
break;
case SEEK_CUR:
pos += offset;
break;
case SEEK_END:
pos = size()+offset;
break;
default:
assert(false);
}
reserve(pos);
return 0;
}
virtual int ftell() {
return pos;
}
void trim()
{
vec->resize(len);
}
virtual int size() { return (int)len; }
};
#ifdef GEKKO
class EMUFILE_MEMFILE : public EMUFILE {
protected:
bool own_buffer;
char *buffer;
s32 buffersize, pos, len;
public:
EMUFILE_MEMFILE(u32 preallocate) {
buffer = (char *)memalign(32, preallocate);
own_buffer = true;
buffersize = 0;
len = 0;
pos = 0;
if(!buffer)
return;
buffersize = preallocate;
}
EMUFILE_MEMFILE(void* src, s32 src_size) {
buffer = (char *)src;
own_buffer = false;
buffersize = src_size;
len = src_size;
pos = 0;
}
~EMUFILE_MEMFILE() {
if(own_buffer && buffer) free(buffer);
}
char* buf() { return buffer; }
virtual FILE *get_fp() { return NULL; }
virtual int fprintf(const char *format, ...) {
va_list argptr;
va_start(argptr, format);
//we dont generate straight into the buffer because it will null terminate (one more byte than we want)
int amt = vsnprintf(0,0,format,argptr);
char* tempbuf = new char[amt+1];
vsprintf(tempbuf,format,argptr);
fwrite(tempbuf,amt);
delete[] tempbuf;
va_end(argptr);
return amt;
};
virtual int fgetc() {
if(pos >= len) {
failbit = true;
return -1;
}
return (int)buffer[pos++];
}
virtual int fputc(int c) {
if(pos >= buffersize) {
failbit = true;
return -1;
}
buffer[pos] = (char)c;
pos++;
len++;
return 0;
}
virtual size_t _fread(const void *ptr, size_t bytes){
u32 remain = len-pos;
if(remain == 0)
return 0;
u32 todo = std::min<u32>(remain,(u32)bytes);
memcpy((void*)ptr,buffer+pos,todo);
pos += todo;
return todo;
}
virtual void fwrite(const void *ptr, size_t bytes){
if(pos+bytes > (u32)buffersize) return;
memcpy(buffer+pos,ptr,bytes);
pos += bytes;
len = std::max(pos,len);
}
virtual int fseek(int offset, int origin){
switch(origin) {
case SEEK_SET:
if(offset >= 0 && offset <= len)
pos = offset;
else
return 1; // failure
break;
case SEEK_CUR:
if((pos + offset) >= 0 && (pos + offset) <= len)
pos += offset;
else
return 1; // failure
break;
case SEEK_END:
if((pos + offset) >= 0 && (pos + offset) <= len)
pos = len + offset;
else
return 1; // failure
break;
default:
return 1; // failure
}
return 0;
}
virtual int ftell() {
return pos;
}
void trim()
{
}
virtual int size() { return (int)len; }
};
#endif
class EMUFILE_FILE : public EMUFILE {
protected:
FILE* fp;
private:
void open(const char* fname, const char* mode)
{
fp = fopen(fname,mode);
if(!fp)
failbit = true;
}
public:
EMUFILE_FILE(const std::string& fname, const char* mode) { open(fname.c_str(),mode); }
EMUFILE_FILE(const char* fname, const char* mode) { open(fname,mode); }
virtual ~EMUFILE_FILE() {
if(NULL != fp)
fclose(fp);
}
virtual FILE *get_fp() {
return fp;
}
bool is_open() { return fp != NULL; }
virtual int fprintf(const char *format, ...) {
va_list argptr;
va_start(argptr, format);
int ret = ::vfprintf(fp, format, argptr);
va_end(argptr);
return ret;
};
virtual int fgetc() {
return ::fgetc(fp);
}
virtual int fputc(int c) {
return ::fputc(c, fp);
}
virtual size_t _fread(const void *ptr, size_t bytes){
size_t ret = ::fread((void*)ptr, 1, bytes, fp);
if(ret < bytes)
failbit = true;
return ret;
}
//removing these return values for now so we can find any code that might be using them and make sure
//they handle the return values correctly
virtual void fwrite(const void *ptr, size_t bytes){
size_t ret = ::fwrite((void*)ptr, 1, bytes, fp);
if(ret < bytes)
failbit = true;
}
virtual int fseek(int offset, int origin){
return ::fseek(fp, offset, origin);
}
virtual int ftell() {
return (u32)::ftell(fp);
}
virtual int size() {
int oldpos = ftell();
fseek(0,SEEK_END);
int len = ftell();
fseek(oldpos,SEEK_SET);
return len;
}
};
#endif

View File

@ -85,6 +85,7 @@ bool justLagged = false;
bool frameAdvanceLagSkip = false; //If this is true, frame advance will skip over lag frame (i.e. it will emulate 2 frames instead of 1) bool frameAdvanceLagSkip = false; //If this is true, frame advance will skip over lag frame (i.e. it will emulate 2 frames instead of 1)
bool AutoSS = false; //Flagged true when the first auto-savestate is made while a game is loaded, flagged false on game close bool AutoSS = false; //Flagged true when the first auto-savestate is made while a game is loaded, flagged false on game close
bool movieSubtitles = true; //Toggle for displaying movie subtitles bool movieSubtitles = true; //Toggle for displaying movie subtitles
bool DebuggerWasUpdated = false; //To prevent the debugger from updating things without being updated.
FCEUGI::FCEUGI() FCEUGI::FCEUGI()
: filename(0) : filename(0)
@ -99,20 +100,53 @@ FCEUGI::~FCEUGI()
if(archiveFilename) delete archiveFilename; if(archiveFilename) delete archiveFilename;
} }
bool CheckFileExists(const char* filename)
{
//This function simply checks to see if the given filename exists
if (!filename) return false;
fstream test;
test.open(filename,fstream::in);
if (test.fail())
{
test.close();
return false;
}
else
{
test.close();
return true;
}
}
void FCEU_TogglePPU(void)
{
newppu ^= 1;
if (newppu)
{
FCEU_DispMessage("New PPU loaded", 0);
FCEUI_printf("New PPU loaded");
}
else
{
FCEU_DispMessage("Old PPU loaded", 0);
FCEUI_printf("Old PPU loaded");
}
}
static void FCEU_CloseGame(void) static void FCEU_CloseGame(void)
{ {
if(GameInfo) if(GameInfo)
{ {
#ifdef WIN32 #ifdef WIN32
// ################################## Start of SP CODE ########################### //SP CODE
extern char LoadedRomFName[2048]; extern char LoadedRomFName[2048];
if (storePreferences(LoadedRomFName)) if (storePreferences(LoadedRomFName))
{ {
FCEUD_PrintError("Couldn't store debugging data"); FCEUD_PrintError("Couldn't store debugging data");
} }
// ################################## End of SP CODE ###########################
#endif #endif
if(FCEUnetplay) if(FCEUnetplay)
@ -128,11 +162,7 @@ static void FCEU_CloseGame(void)
if(GameInfo->type!=GIT_NSF) if(GameInfo->type!=GIT_NSF)
{ {
#ifdef GEKKO
FCEU_FlushGameCheats(0,1); // don't save cheats
#else
FCEU_FlushGameCheats(0,0); FCEU_FlushGameCheats(0,0);
#endif
} }
GameInterface(GI_CLOSE); GameInterface(GI_CLOSE);
@ -141,8 +171,7 @@ static void FCEU_CloseGame(void)
ResetExState(0,0); ResetExState(0,0);
//mbg 5/9/08 - clear screen when game is closed //clear screen when game is closed
//http://sourceforge.net/tracker/index.php?func=detail&aid=1787298&group_id=13536&atid=113536
extern uint8 *XBuf; extern uint8 *XBuf;
if(XBuf) if(XBuf)
memset(XBuf,0,256*256); memset(XBuf,0,256*256);
@ -152,10 +181,9 @@ static void FCEU_CloseGame(void)
delete GameInfo; delete GameInfo;
GameInfo = 0; GameInfo = 0;
//Reset frame counter
currFrameCounter = 0; currFrameCounter = 0;
//Reset flags for Undo/Redo/Auto Savestating //Reset flags for Undo/Redo/Auto Savestating //adelikat: TODO: maybe this stuff would be cleaner as a struct or class
lastSavestateMade[0] = 0; lastSavestateMade[0] = 0;
undoSS = false; undoSS = false;
redoSS = false; redoSS = false;
@ -318,7 +346,8 @@ static void AllocBuffers()
#endif #endif
} }
static void FreeBuffers() { static void FreeBuffers()
{
#ifdef _USE_SHARED_MEMORY_ #ifdef _USE_SHARED_MEMORY_
void win_FreeBuffers(uint8 *GameMemBlock, uint8 *RAM); void win_FreeBuffers(uint8 *GameMemBlock, uint8 *RAM);
win_FreeBuffers(GameMemBlock, RAM); win_FreeBuffers(GameMemBlock, RAM);
@ -493,7 +522,7 @@ endlseq:
FCEU_LoadGameCheats(0); FCEU_LoadGameCheats(0);
#if defined (WIN32) || defined (WIN64) #if defined (WIN32) || defined (WIN64)
DoDebuggerRunCheck(); //Can't safely do it in loadPreferences DoDebuggerDataReload(); // Reloads data without reopening window
#endif #endif
return GameInfo; return GameInfo;
@ -590,12 +619,13 @@ void SetAutoFireOffset(int offset)
void AutoFire(void) void AutoFire(void)
{ {
static int counter = 0; static int counter = 0;
if (justLagged == false) counter = (counter + 1) % (8*7*5*3); if (justLagged == false)
counter = (counter + 1) % (8*7*5*3);
//If recording a movie, use the frame # for the autofire so the offset //If recording a movie, use the frame # for the autofire so the offset
//doesn't get screwed up when loading. //doesn't get screwed up when loading.
if(FCEUMOV_Mode(MOVIEMODE_RECORD | MOVIEMODE_PLAY)) if(FCEUMOV_Mode(MOVIEMODE_RECORD | MOVIEMODE_PLAY))
{ {
rapidAlternator= AutoFirePattern[(AutoFireOffset + FCEUMOV_GetFrame())%AutoFirePatternLength]; rapidAlternator= AutoFirePattern[(AutoFireOffset + FCEUMOV_GetFrame())%AutoFirePatternLength]; //adelikat: TODO: Think through this, MOVIEMODE_FINISHED should not use movie data for auto-fire?
} }
else else
{ {
@ -661,12 +691,15 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
#ifdef WIN32 #ifdef WIN32
//These Windows only dialogs need to be updated only once per frame so they are included here //These Windows only dialogs need to be updated only once per frame so they are included here
UpdateCheatList(); UpdateCheatList(); // CaH4e3: can't see why, this is only cause problems with selection - adelikat: selection is only a problem when not paused, it shoudl be paused to select, we want to see the values update
UpdateTextHooker(); UpdateTextHooker();
Update_RAM_Search(); // Update_RAM_Watch() is also called. Update_RAM_Search(); // Update_RAM_Watch() is also called.
RamChange(); RamChange();
UpdateLogWindow(); UpdateLogWindow();
//FCEUI_AviVideoUpdate(XBuf); //FCEUI_AviVideoUpdate(XBuf);
extern int KillFCEUXonFrame;
if (KillFCEUXonFrame && (FCEUMOV_GetFrame() >= KillFCEUXonFrame))
DoFCEUExit();
#endif #endif
timestampbase += timestamp; timestampbase += timestamp;
@ -928,6 +961,7 @@ void FCEUI_SetEmulationPaused(int val)
void FCEUI_ToggleEmulationPause(void) void FCEUI_ToggleEmulationPause(void)
{ {
EmulationPaused = (EmulationPaused&1)^1; EmulationPaused = (EmulationPaused&1)^1;
DebuggerWasUpdated = false;
} }
void FCEUI_FrameAdvanceEnd(void) void FCEUI_FrameAdvanceEnd(void)
@ -945,7 +979,7 @@ static int AutosaveCounter = 0;
void UpdateAutosave(void) void UpdateAutosave(void)
{ {
if(!EnableAutosave) if(!EnableAutosave || turbo)
return; return;
char * f; char * f;
@ -963,7 +997,7 @@ void UpdateAutosave(void)
void FCEUI_Autosave(void) void FCEUI_Autosave(void)
{ {
if(!EnableAutosave || !AutoSS) if(!EnableAutosave || !AutoSS || FCEUMOV_Mode(MOVIEMODE_TASEDIT))
return; return;
if(AutosaveStatus[AutosaveIndex] == 1) if(AutosaveStatus[AutosaveIndex] == 1)
@ -1016,7 +1050,7 @@ bool FCEU_IsValidUI(EFCEUI ui)
case FCEUI_STOPMOVIE: case FCEUI_STOPMOVIE:
case FCEUI_PLAYFROMBEGINNING: case FCEUI_PLAYFROMBEGINNING:
return FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD); return (FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED));
case FCEUI_STOPAVI: case FCEUI_STOPAVI:
return FCEUI_AviIsRecording(); return FCEUI_AviIsRecording();
@ -1027,7 +1061,7 @@ bool FCEU_IsValidUI(EFCEUI ui)
case FCEUI_RESET: case FCEUI_RESET:
if(!GameInfo) return false; if(!GameInfo) return false;
if(FCEUMOV_Mode(MOVIEMODE_TASEDIT|MOVIEMODE_PLAY)) return false; if(FCEUMOV_Mode(MOVIEMODE_FINISHED|MOVIEMODE_TASEDIT|MOVIEMODE_PLAY)) return false;
break; break;
case FCEUI_POWER: case FCEUI_POWER:

View File

@ -108,10 +108,13 @@ int FCEU_TextScanlineOffsetFromBottom(int y);
extern FCEUS FSettings; extern FCEUS FSettings;
bool CheckFileExists(const char* filename); //Receives a filename (fullpath) and checks to see if that file exists
void FCEU_PrintError(char *format, ...); void FCEU_PrintError(char *format, ...);
void FCEU_printf(char *format, ...); void FCEU_printf(char *format, ...);
void FCEU_DispMessage(char *format, ...); void FCEU_DispMessage(char *format, int disppos, ...);
void FCEU_DispMessageOnMovie(char *format, ...); void FCEU_DispMessageOnMovie(char *format, ...);
void FCEU_TogglePPU();
void SetNESDeemph(uint8 d, int force); void SetNESDeemph(uint8 d, int force);
void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor); void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor);

View File

@ -161,17 +161,17 @@ void FCEU_FDSInsert(void)
if(TotalSides==0) if(TotalSides==0)
{ {
FCEU_DispMessage("Not FDS; can't eject disk."); FCEU_DispMessage("Not FDS; can't eject disk.",0);
return; return;
} }
if(InDisk==255) if(InDisk==255)
{ {
FCEU_DispMessage("Disk %d Side %s Inserted",SelectDisk>>1,(SelectDisk&1)?"B":"A"); FCEU_DispMessage("Disk %d Side %s Inserted",0,SelectDisk>>1,(SelectDisk&1)?"B":"A");
InDisk=SelectDisk; InDisk=SelectDisk;
} }
else else
{ {
FCEU_DispMessage("Disk %d Side %s Ejected",SelectDisk>>1,(SelectDisk&1)?"B":"A"); FCEU_DispMessage("Disk %d Side %s Ejected",0,SelectDisk>>1,(SelectDisk&1)?"B":"A");
InDisk=255; InDisk=255;
} }
} }
@ -190,16 +190,16 @@ void FCEU_FDSSelect(void)
if(TotalSides==0) if(TotalSides==0)
{ {
FCEU_DispMessage("Not FDS; can't select disk."); FCEU_DispMessage("Not FDS; can't select disk.",0);
return; return;
} }
if(InDisk!=255) if(InDisk!=255)
{ {
FCEU_DispMessage("Eject disk before selecting."); FCEU_DispMessage("Eject disk before selecting.",0);
return; return;
} }
SelectDisk=((SelectDisk+1)%TotalSides)&3; SelectDisk=((SelectDisk+1)%TotalSides)&3;
FCEU_DispMessage("Disk %d Side %c Selected",SelectDisk>>1,(SelectDisk&1)?'B':'A'); FCEU_DispMessage("Disk %d Side %c Selected",0,SelectDisk>>1,(SelectDisk&1)?'B':'A');
} }
static void FDSFix(int a) static void FDSFix(int a)
@ -797,6 +797,15 @@ int FDSLoad(const char *name, FCEUFILE *fp)
free(fn); free(fn);
fseek( zp, 0L, SEEK_END );
if (ftell( zp ) != 8192 ) {
fclose(zp);
FreeFDSMemory();
FCEU_PrintError("FDS BIOS ROM image incompatible: %s", FCEU_MakeFName(FCEUMKF_FDSROM,0,0).c_str());
return 0;
}
fseek( zp, 0L, SEEK_SET );
if(fread(FDSBIOS,1,8192,zp)!=8192) if(fread(FDSBIOS,1,8192,zp)!=8192)
{ {
fclose(zp); fclose(zp);

View File

@ -48,7 +48,6 @@
#include "movie.h" #include "movie.h"
#include "driver.h" #include "driver.h"
#include "utils/xstring.h" #include "utils/xstring.h"
#include "utils/memorystream.h"
using namespace std; using namespace std;
@ -143,8 +142,7 @@ void ApplyIPS(FILE *ips, FCEUFILE* fp)
FCEU_printf(" Hard IPS end!\n"); FCEU_printf(" Hard IPS end!\n");
end: end:
fclose(ips); fclose(ips);
memorystream* ms = new memorystream(buf,fp->size); EMUFILE_MEMORY* ms = new EMUFILE_MEMORY(buf,fp->size);
ms->giveBuf();
fp->SetStream(ms); fp->SetStream(ms);
} }
@ -224,7 +222,9 @@ static FCEUFILE * TryUnzip(const std::string& path) {
if(unzGoToNextFile(tz)!=UNZ_OK) if(unzGoToNextFile(tz)!=UNZ_OK)
{ {
if(unzGoToFirstFile(tz)!=UNZ_OK) goto zpfail; if(unzGoToFirstFile(tz)!=UNZ_OK) goto zpfail;
break; unzCloseCurrentFile(tz);
unzClose(tz);
return 0;
} }
} }
if(unzOpenCurrentFile(tz)!=UNZ_OK) if(unzOpenCurrentFile(tz)!=UNZ_OK)
@ -241,7 +241,7 @@ zpfail:
unzGetCurrentFileInfo(tz,&ufo,0,0,0,0,0,0); unzGetCurrentFileInfo(tz,&ufo,0,0,0,0,0,0);
int size = ufo.uncompressed_size; int size = ufo.uncompressed_size;
memorystream* ms = new memorystream(size); EMUFILE_MEMORY* ms = new EMUFILE_MEMORY(size);
unzReadCurrentFile(tz,ms->buf(),ufo.uncompressed_size); unzReadCurrentFile(tz,ms->buf(),ufo.uncompressed_size);
unzCloseCurrentFile(tz); unzCloseCurrentFile(tz);
unzClose(tz); unzClose(tz);
@ -283,7 +283,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
if(!asr.isArchive()) if(!asr.isArchive())
{ {
//if the archive contained no files, try to open it the old fashioned way //if the archive contained no files, try to open it the old fashioned way
std::fstream* fp = FCEUD_UTF8_fstream(fileToOpen,mode); EMUFILE_FILE* fp = FCEUD_UTF8_fstream(fileToOpen,mode);
if(!fp) if(!fp)
{ {
return 0; return 0;
@ -306,10 +306,10 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
{ {
uint32 magic; uint32 magic;
magic = fp->get(); magic = fp->fgetc();
magic|=fp->get()<<8; magic|=fp->fgetc()<<8;
magic|=fp->get()<<16; magic|=fp->fgetc()<<16;
fp->seekg(0,std::ios::beg); fp->fseek(0,SEEK_SET);
if(magic==0x088b1f) { if(magic==0x088b1f) {
// maybe gzip... // maybe gzip...
@ -320,7 +320,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
int size; int size;
for(size=0; gzgetc(gzfile) != EOF; size++) {} for(size=0; gzgetc(gzfile) != EOF; size++) {}
memorystream* ms = new memorystream(size); EMUFILE_MEMORY* ms = new EMUFILE_MEMORY(size);
gzseek(gzfile,0,SEEK_SET); gzseek(gzfile,0,SEEK_SET);
gzread(gzfile,ms->buf(),size); gzread(gzfile,ms->buf(),size);
gzclose(gzfile); gzclose(gzfile);
@ -344,7 +344,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
fceufp->logicalPath = fileToOpen; fceufp->logicalPath = fileToOpen;
fceufp->fullFilename = fileToOpen; fceufp->fullFilename = fileToOpen;
fceufp->archiveIndex = -1; fceufp->archiveIndex = -1;
fceufp->stream = (std::iostream*)fp; fceufp->stream = fp;
FCEU_fseek(fceufp,0,SEEK_END); FCEU_fseek(fceufp,0,SEEK_END);
fceufp->size = FCEU_ftell(fceufp); fceufp->size = FCEU_ftell(fceufp);
FCEU_fseek(fceufp,0,SEEK_SET); FCEU_fseek(fceufp,0,SEEK_SET);
@ -386,58 +386,26 @@ int FCEU_fclose(FCEUFILE *fp)
uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp) uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
{ {
fp->stream->read((char*)ptr,size*nmemb); return fp->stream->fread((char*)ptr,size*nmemb);
uint32 read = fp->stream->gcount();
return read/size;
} }
uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp) uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
{ {
fp->stream->write((char*)ptr,size*nmemb); fp->stream->fwrite((char*)ptr,size*nmemb);
//todo - how do we tell how many bytes we wrote? //todo - how do we tell how many bytes we wrote?
return nmemb; return nmemb;
} }
int FCEU_fseek(FCEUFILE *fp, long offset, int whence) int FCEU_fseek(FCEUFILE *fp, long offset, int whence)
{ {
//if(fp->type==1) fp->stream->fseek(offset,whence);
//{
// return( (gzseek(fp->fp,offset,whence)>0)?0:-1);
//}
//else if(fp->type>=2)
//{
// MEMWRAP *wz;
// wz=(MEMWRAP*)fp->fp;
// switch(whence)
// {
// case SEEK_SET:if(offset>=(long)wz->size) //mbg merge 7/17/06 - added cast to long
// return(-1);
// wz->location=offset;break;
// case SEEK_CUR:if(offset+wz->location>wz->size)
// return (-1);
// wz->location+=offset;
// break;
// }
// return 0;
//}
//else
// return fseek((FILE *)fp->fp,offset,whence);
if(fp->mode == FCEUFILE::READ || fp->mode == FCEUFILE::READWRITE)
fp->stream->seekg(offset,(std::ios_base::seekdir)whence);
if(fp->mode == FCEUFILE::WRITE || fp->mode == FCEUFILE::READWRITE)
fp->stream->seekp(offset,(std::ios_base::seekdir)whence);
return FCEU_ftell(fp); return FCEU_ftell(fp);
} }
uint64 FCEU_ftell(FCEUFILE *fp) uint64 FCEU_ftell(FCEUFILE *fp)
{ {
if(fp->mode == FCEUFILE::READ) return fp->stream->ftell();
return fp->stream->tellg();
else
return fp->stream->tellp();
} }
int FCEU_read16le(uint16 *val, FCEUFILE *fp) int FCEU_read16le(uint16 *val, FCEUFILE *fp)
@ -452,7 +420,7 @@ int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp)
int FCEU_fgetc(FCEUFILE *fp) int FCEU_fgetc(FCEUFILE *fp)
{ {
return fp->stream->get(); return fp->stream->fgetc();
} }
uint64 FCEU_fgetsize(FCEUFILE *fp) uint64 FCEU_fgetsize(FCEUFILE *fp)

View File

@ -4,13 +4,14 @@
#include <string> #include <string>
#include <iostream> #include <iostream>
#include "types.h" #include "types.h"
#include "utils/memorystream.h" #include "emufile.h"
extern bool bindSavestate; extern bool bindSavestate;
struct FCEUFILE { struct FCEUFILE {
//the stream you can use to access the data //the stream you can use to access the data
std::iostream *stream; //std::iostream *stream;
EMUFILE *stream;
//the name of the file, or the logical name of the file within the archive //the name of the file, or the logical name of the file within the archive
std::string filename; std::string filename;
@ -51,25 +52,25 @@ struct FCEUFILE {
} mode; } mode;
//guarantees that the file contains a memorystream, and returns it for your convenience //guarantees that the file contains a memorystream, and returns it for your convenience
memorystream* EnsureMemorystream() { EMUFILE_MEMORY* EnsureMemorystream() {
memorystream* ret = dynamic_cast<memorystream*>(stream);
EMUFILE_MEMORY* ret = dynamic_cast<EMUFILE_MEMORY*>(stream);
if(ret) return ret; if(ret) return ret;
//nope, we need to create it: copy the contents //nope, we need to create it: copy the contents
ret = new memorystream(size); ret = new EMUFILE_MEMORY(size);
stream->read(ret->buf(),size); stream->fread(ret->buf(),size);
delete stream; delete stream;
stream = ret; stream = ret;
return ret; return ret;
} }
void SetStream(std::iostream *newstream) { void SetStream(EMUFILE *newstream) {
if(stream) delete stream; if(stream) delete stream;
stream = newstream; stream = newstream;
//get the size of the stream //get the size of the stream
stream->seekg(0,std::ios::end); stream->fseek(0,SEEK_SET);
size = stream->tellg(); size = stream->size();
stream->seekg(0,std::ios::beg);
} }
}; };

View File

@ -56,7 +56,7 @@ void SexyFilter(int32 *in, int32 *out, int32 count)
mul2=(24<<16)/FSettings.SndRate; mul2=(24<<16)/FSettings.SndRate;
vmul=(FSettings.SoundVolume<<16)*3/4/100; vmul=(FSettings.SoundVolume<<16)*3/4/100;
//FCEU_DispMessage("SoundVolume %d, vmul %d",FSettings.SoundVolume,vmul); //FCEU_DispMessage("SoundVolume %d, vmul %d",0,FSettings.SoundVolume,vmul);
if(FSettings.soundq) vmul/=4; if(FSettings.soundq) vmul/=4;
else vmul*=2; /* TODO: Increase volume in low quality sound rendering code itself */ else vmul*=2; /* TODO: Increase volume in low quality sound rendering code itself */

View File

@ -23,7 +23,7 @@
{0xdd8ced31,209,-1}, /* Power Rangers 3 */ {0xdd8ced31,209,-1}, /* Power Rangers 3 */
{0x0c47946d,210,1}, /* Chibi Maruko Chan */ {0x0c47946d,210,1}, /* Chibi Maruko Chan */
{0xbd523011,210,0}, /* Dream Master */ {0xbd523011,210,2}, /* Dream Master */ // may be wrong, but seems it solve most problems
{0xc247cc80,210,1}, /* Family Circuit '91 */ {0xc247cc80,210,1}, /* Family Circuit '91 */
{0x6ec51de5,210,1}, /* Famista '92 */ {0x6ec51de5,210,1}, /* Famista '92 */
{0xadffd64f,210,1}, /* Famista '93 */ {0xadffd64f,210,1}, /* Famista '93 */

View File

@ -56,7 +56,7 @@ iNES_HEADER head ;
#ifdef _USE_SHARED_MEMORY_ #ifdef _USE_SHARED_MEMORY_
HANDLE mapROM, mapVROM; HANDLE mapROM = NULL, mapVROM = NULL;
#endif #endif
CartInfo iNESCart; CartInfo iNESCart;
@ -132,33 +132,29 @@ void iNESGI(GI h) //bbit edited: removed static keyword
{ {
if(mapROM) if(mapROM)
{ {
UnmapViewOfFile(mapROM);
CloseHandle(mapROM); CloseHandle(mapROM);
ROM=0; mapROM = NULL;
UnmapViewOfFile(ROM);
} }
else else
{
free(ROM); free(ROM);
ROM = NULL; ROM = NULL;
} }
}
if(VROM) if(VROM)
{ {
if(mapVROM) if(mapVROM)
{ {
UnmapViewOfFile(mapVROM);
CloseHandle(mapVROM); CloseHandle(mapVROM);
VROM=0; mapVROM = NULL;
UnmapViewOfFile(VROM);
} }
else else
{
free(VROM); free(VROM);
VROM = NULL; VROM = NULL;
} }
}
#else #else
if(ROM) {free(ROM);ROM=0;} if(ROM) {free(ROM); ROM = NULL;}
if(VROM) {free(VROM);VROM=0;} if(VROM) {free(VROM); VROM = NULL;}
#endif #endif
if(MapClose) MapClose(); if(MapClose) MapClose();
if(trainerpoo) {FCEU_gfree(trainerpoo);trainerpoo=0;} if(trainerpoo) {FCEU_gfree(trainerpoo);trainerpoo=0;}
@ -230,6 +226,7 @@ static void SetInput(void)
{0xde8fd935,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // To the Earth {0xde8fd935,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // To the Earth
{0xedc3662b,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Operation Wolf {0xedc3662b,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Operation Wolf
{0x2a6559a1,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Operation Wolf (J) {0x2a6559a1,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Operation Wolf (J)
{0x4e959173,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Gotcha! - The Sport!
{0x23d17f5e,SI_GAMEPAD,SI_ZAPPER,SIFC_NONE}, // The Lone Ranger {0x23d17f5e,SI_GAMEPAD,SI_ZAPPER,SIFC_NONE}, // The Lone Ranger
{0xb8b9aca3,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Wild Gunman {0xb8b9aca3,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Wild Gunman
@ -425,8 +422,9 @@ static void CheckHInfo(void)
#ifdef _USE_SHARED_MEMORY_ #ifdef _USE_SHARED_MEMORY_
if(mapVROM) if(mapVROM)
{ {
UnmapViewOfFile(mapVROM);
CloseHandle(mapVROM); CloseHandle(mapVROM);
UnmapViewOfFile(VROM);
mapVROM = NULL;
} }
else else
{ {
@ -435,7 +433,7 @@ static void CheckHInfo(void)
#else #else
free(VROM); free(VROM);
#endif #endif
VROM=0; VROM = NULL;
tofix|=8; tofix|=8;
} }
if(MapperNo!=(moo[x].mapper&0xFF)) if(MapperNo!=(moo[x].mapper&0xFF))
@ -536,9 +534,9 @@ typedef struct {
char* name; char* name;
int number; int number;
void (*init)(CartInfo *); void (*init)(CartInfo *);
} BMAPPING; } BMAPPINGLocal;
static BMAPPING bmap[] = { static BMAPPINGLocal bmap[] = {
{"NROM", 0, NROM_Init}, {"NROM", 0, NROM_Init},
{"MMC1", 1, Mapper1_Init}, {"MMC1", 1, Mapper1_Init},
{"UNROM", 2, UNROM_Init}, {"UNROM", 2, UNROM_Init},
@ -741,48 +739,67 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode)
mapROM = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, ROM_size<<14,"fceu.ROM"); mapROM = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, ROM_size<<14,"fceu.ROM");
if(mapROM == NULL || GetLastError() == ERROR_ALREADY_EXISTS) if(mapROM == NULL || GetLastError() == ERROR_ALREADY_EXISTS)
{ {
mapROM = NULL; if((ROM = (uint8 *)FCEU_malloc(ROM_size<<14)) == NULL) return 0;
}
else
{
if((ROM = (uint8 *)MapViewOfFile(mapROM, FILE_MAP_WRITE, 0, 0, 0)) == NULL)
{
CloseHandle(mapROM); CloseHandle(mapROM);
mapROM = NULL;
if(!(ROM=(uint8 *)FCEU_malloc(ROM_size<<14))) if((ROM = (uint8 *)FCEU_malloc(ROM_size<<14)) == NULL) return 0;
return 0; }
}
if(VROM_size) if(VROM_size)
{ {
if(!(VROM=(uint8 *)FCEU_malloc(VROM_size<<13))) mapVROM = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, VROM_size<<13,"fceu.VROM");
if(mapVROM == NULL || GetLastError() == ERROR_ALREADY_EXISTS)
{ {
if((VROM=(uint8 *)FCEU_malloc(VROM_size<<13)) == NULL)
{
if(mapROM)
{
UnmapViewOfFile(mapROM);
mapROM = NULL;
CloseHandle(ROM);
}
else
free(ROM);
ROM = NULL;
return 0;
}
}
else
{
if((VROM = (uint8 *)MapViewOfFile(mapVROM, FILE_MAP_WRITE, 0, 0, 0)) == NULL)
{
CloseHandle(mapVROM);
mapVROM = NULL;
if((VROM=(uint8 *)FCEU_malloc(VROM_size<<13)) == NULL)
{
if(mapROM)
{
UnmapViewOfFile(mapROM);
mapROM = NULL;
CloseHandle(ROM);
}
else
free(ROM); free(ROM);
ROM = NULL; ROM = NULL;
return 0; return 0;
} }
} }
} }
else
{
ROM = (uint8 *)MapViewOfFile(mapROM, FILE_MAP_WRITE, 0, 0, 0);
if( !ROM ) return 0;
if(VROM_size)
{
mapVROM = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, VROM_size<<13,"fceu.VROM");
VROM = (uint8 *)MapViewOfFile(mapVROM, FILE_MAP_WRITE, 0, 0, 0);
if( !VROM )
{
UnmapViewOfFile(mapROM);
CloseHandle(mapROM);
return 0;
}
}
} }
#else #else
if(!(ROM=(uint8 *)FCEU_malloc(ROM_size<<14))) if((ROM = (uint8 *)FCEU_malloc(ROM_size<<14)) == NULL) return 0;
return 0;
if(VROM_size) if(VROM_size)
{ {
if(!(VROM=(uint8 *)FCEU_malloc(VROM_size<<13))) if((VROM = (uint8 *)FCEU_malloc(VROM_size<<13)) == NULL)
{ {
free(ROM); free(ROM);
ROM = NULL;
return 0; return 0;
} }
} }
@ -831,10 +848,23 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode)
FCEU_printf("%02x",iNESCart.MD5[x]); FCEU_printf("%02x",iNESCart.MD5[x]);
FCEU_printf("\n"); FCEU_printf("\n");
} }
char* mappername = "Not Listed";
for(int mappertest=0;mappertest< (sizeof bmap / sizeof bmap[0]) - 1;mappertest++)
{
if (bmap[mappertest].number == MapperNo) {
mappername = bmap[mappertest].name;
break;
}
}
FCEU_printf(" Mapper #: %d\n Mapper name: %s\n Mirroring: %s\n", FCEU_printf(" Mapper #: %d\n Mapper name: %s\n Mirroring: %s\n",
MapperNo, bmap[MapperNo].name, Mirroring==2?"None(Four-screen)":Mirroring?"Vertical":"Horizontal"); MapperNo, mappername, Mirroring==2?"None (Four-screen)":Mirroring?"Vertical":"Horizontal");
if(head.ROM_type&2) FCEU_printf(" Battery-backed.\n");
if(head.ROM_type&4) FCEU_printf(" Trained.\n"); FCEU_printf(" Battery-backed: %s\n", (head.ROM_type&2)?"Yes":"No");
FCEU_printf(" Trained: %s\n", (head.ROM_type&4)?"Yes":"No");
// (head.ROM_type&8) = Mirroring: None(Four-screen)
SetInput(); SetInput();
CheckHInfo(); CheckHInfo();
@ -880,6 +910,14 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode)
#endif #endif
strcpy(LoadedRomFName,name); //bbit edited: line added strcpy(LoadedRomFName,name); //bbit edited: line added
// Extract Filename only. Should account for Windows/Unix this way.
if (strrchr(name, '/')) {
name = strrchr(name, '/') + 1;
} else if(strrchr(name, '\\')) {
name = strrchr(name, '\\') + 1;
}
GameInterface=iNESGI; GameInterface=iNESGI;
FCEU_printf("\n"); FCEU_printf("\n");
@ -1443,7 +1481,7 @@ static void iNESPower(void)
static int NewiNES_Init(int num) static int NewiNES_Init(int num)
{ {
BMAPPING *tmp=bmap; BMAPPINGLocal *tmp=bmap;
if(GameInfo->type == GIT_VSUNI) if(GameInfo->type == GIT_VSUNI)
AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0); AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);
@ -1470,14 +1508,19 @@ static int NewiNES_Init(int num)
{ {
CloseHandle(mapVROM); CloseHandle(mapVROM);
mapVROM = NULL; mapVROM = NULL;
VROM=(uint8 *)malloc(CHRRAMSize); if((VROM = (uint8 *)malloc(CHRRAMSize)) == NULL) return 0;
} }
else else
{ {
VROM = (uint8 *)MapViewOfFile(mapVROM, FILE_MAP_WRITE, 0, 0, 0); if((VROM = (uint8 *)MapViewOfFile(mapVROM, FILE_MAP_WRITE, 0, 0, 0)) == NULL)
{
CloseHandle(mapVROM);
mapVROM = NULL;
if((VROM = (uint8 *)malloc(CHRRAMSize)) == NULL) return 0;
}
} }
#else #else
VROM=(uint8 *)malloc(CHRRAMSize); if((VROM = (uint8 *)malloc(CHRRAMSize)) == NULL) return 0;
#endif #endif
UNIFchrrama=VROM; UNIFchrrama=VROM;
SetupCartCHRMapping(0,VROM,CHRRAMSize,1); SetupCartCHRMapping(0,VROM,CHRRAMSize,1);
@ -1486,9 +1529,9 @@ static int NewiNES_Init(int num)
if(head.ROM_type&8) if(head.ROM_type&8)
AddExState(ExtraNTARAM, 2048, 0, "EXNR"); AddExState(ExtraNTARAM, 2048, 0, "EXNR");
tmp->init(&iNESCart); tmp->init(&iNESCart);
return(1); return 1;
} }
tmp++; tmp++;
} }
return(0); return 0;
} }

View File

@ -85,6 +85,8 @@ static uint8 joy_readbit[2];
uint8 joy[4]={0,0,0,0}; //HACK - should be static but movie needs it uint8 joy[4]={0,0,0,0}; //HACK - should be static but movie needs it
static uint8 LastStrobe; static uint8 LastStrobe;
bool replaceP2StartWithMicrophone = false;
#ifdef _USE_SHARED_MEMORY_ #ifdef _USE_SHARED_MEMORY_
static uint32 BotPointer = 0; //mbg merge 7/18/06 changed to uint32 static uint32 BotPointer = 0; //mbg merge 7/18/06 changed to uint32
#endif #endif
@ -107,13 +109,36 @@ static DECLFR(JPRead)
{ {
lagFlag = 0; lagFlag = 0;
uint8 ret=0; uint8 ret=0;
static bool microphone = false;
ret|=joyports[A&1].driver->Read(A&1); ret|=joyports[A&1].driver->Read(A&1);
// Test if the port 2 start button is being pressed.
// On a famicom, port 2 start shouldn't exist, so this removes it.
// Games can't automatically be checked for NES/Famicom status,
// so it's an all-encompassing change in the input config menu.
if ((replaceP2StartWithMicrophone) && (A&1) && (joy_readbit[1] == 4)) {
// Nullify Port 2 Start Button
ret&=0xFE;
}
if(portFC.driver) if(portFC.driver)
ret = portFC.driver->Read(A&1,ret); ret = portFC.driver->Read(A&1,ret);
// Not verified against hardware.
if (replaceP2StartWithMicrophone) {
if (joy[1]&8) {
microphone = !microphone;
if (microphone) {
ret|=4;
}
} else {
microphone = false;
}
}
ret|=X.DB&0xC0; ret|=X.DB&0xC0;
return(ret); return(ret);
} }
@ -471,6 +496,10 @@ bool FCEUI_GetInputFourscore()
{ {
return FSAttached; return FSAttached;
} }
bool FCEUI_GetInputMicrophone()
{
return replaceP2StartWithMicrophone;
}
void FCEUI_SetInputFourscore(bool attachFourscore) void FCEUI_SetInputFourscore(bool attachFourscore)
{ {
FSAttached = attachFourscore; FSAttached = attachFourscore;
@ -603,6 +632,12 @@ static void LaunchTraceLogger(void);
static void LaunchCodeDataLogger(void); static void LaunchCodeDataLogger(void);
static void LaunchRamWatch(void); static void LaunchRamWatch(void);
static void LaunchRamSearch(void); static void LaunchRamSearch(void);
static void RamSearchOpLT(void);
static void RamSearchOpGT(void);
static void RamSearchOpLTE(void);
static void RamSearchOpGTE(void);
static void RamSearchOpEQ(void);
static void RamSearchOpNE(void);
static void FA_SkipLag(void); static void FA_SkipLag(void);
static void OpenRom(void); static void OpenRom(void);
static void CloseRom(void); static void CloseRom(void);
@ -725,6 +760,12 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
{ EMUCMD_MISC_TOGGLEFULLSCREEN, EMUCMDTYPE_MISC, ToggleFullscreen, 0, 0, "Toggle Fullscreen", 0}, { EMUCMD_MISC_TOGGLEFULLSCREEN, EMUCMDTYPE_MISC, ToggleFullscreen, 0, 0, "Toggle Fullscreen", 0},
{ EMUCMD_TOOL_OPENRAMWATCH, EMUCMDTYPE_TOOL, LaunchRamWatch, 0, 0, "Open Ram Watch", 0}, { EMUCMD_TOOL_OPENRAMWATCH, EMUCMDTYPE_TOOL, LaunchRamWatch, 0, 0, "Open Ram Watch", 0},
{ EMUCMD_TOOL_OPENRAMSEARCH, EMUCMDTYPE_TOOL, LaunchRamSearch, 0, 0, "Open Ram Search", 0}, { EMUCMD_TOOL_OPENRAMSEARCH, EMUCMDTYPE_TOOL, LaunchRamSearch, 0, 0, "Open Ram Search", 0},
{ EMUCMD_TOOL_RAMSEARCHLT, EMUCMDTYPE_TOOL, RamSearchOpLT, 0, 0, "Ram Search - Less Than", 0},
{ EMUCMD_TOOL_RAMSEARCHGT, EMUCMDTYPE_TOOL, RamSearchOpGT, 0, 0, "Ram Search - Greater Than", 0},
{ EMUCMD_TOOL_RAMSEARCHLTE, EMUCMDTYPE_TOOL, RamSearchOpLTE, 0, 0, "Ram Search - Less Than or Equal", 0},
{ 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},
}; };
#define NUM_EMU_CMDS (sizeof(FCEUI_CommandTable)/sizeof(FCEUI_CommandTable[0])) #define NUM_EMU_CMDS (sizeof(FCEUI_CommandTable)/sizeof(FCEUI_CommandTable[0]))
@ -758,7 +799,7 @@ void FCEUI_HandleEmuCommands(TestCommandState* testfn)
static void CommandUnImpl(void) static void CommandUnImpl(void)
{ {
FCEU_DispMessage("command '%s' unimplemented.", FCEUI_CommandTable[i].name); FCEU_DispMessage("command '%s' unimplemented.",0, FCEUI_CommandTable[i].name);
} }
static void CommandToggleDip(void) static void CommandToggleDip(void)
@ -925,7 +966,59 @@ static void LaunchRamSearch(void)
#endif #endif
} }
static void RamSearchOpLT(void) {
#ifdef WIN32
extern void SetSearchType(int SearchType);
extern void DoRamSearchOperation();
SetSearchType(0);
DoRamSearchOperation();
#endif
}
static void RamSearchOpGT(void) {
#ifdef WIN32
extern void SetSearchType(int SearchType);
extern void DoRamSearchOperation();
SetSearchType(1);
DoRamSearchOperation();
#endif
}
static void RamSearchOpLTE(void) {
#ifdef WIN32
extern void SetSearchType(int SearchType);
extern void DoRamSearchOperation();
SetSearchType(2);
DoRamSearchOperation();
#endif
}
static void RamSearchOpGTE(void) {
#ifdef WIN32
extern void SetSearchType(int SearchType);
extern void DoRamSearchOperation();
SetSearchType(3);
DoRamSearchOperation();
#endif
}
static void RamSearchOpEQ(void) {
#ifdef WIN32
extern void SetSearchType(int SearchType);
extern void DoRamSearchOperation();
SetSearchType(4);
DoRamSearchOperation();
#endif
}
static void RamSearchOpNE(void) {
#ifdef WIN32
extern void SetSearchType(int SearchType);
extern void DoRamSearchOperation();
SetSearchType(5);
DoRamSearchOperation();
#endif
}
static void FA_SkipLag(void) static void FA_SkipLag(void)
{ {
@ -950,8 +1043,8 @@ static void CloseRom(void)
static void MovieSubtitleToggle(void) static void MovieSubtitleToggle(void)
{ {
movieSubtitles ^= 1; movieSubtitles ^= 1;
if (movieSubtitles) FCEU_DispMessage("Movie subtitles on"); if (movieSubtitles) FCEU_DispMessage("Movie subtitles on",0);
else FCEU_DispMessage("Movie subtitles off"); else FCEU_DispMessage("Movie subtitles off",0);
} }
static void UndoRedoSavestate(void) static void UndoRedoSavestate(void)

View File

@ -221,6 +221,12 @@ enum EMUCMD
EMUCMD_MISC_TOGGLEFULLSCREEN, EMUCMD_MISC_TOGGLEFULLSCREEN,
EMUCMD_TOOL_OPENRAMWATCH, EMUCMD_TOOL_OPENRAMWATCH,
EMUCMD_TOOL_OPENRAMSEARCH, EMUCMD_TOOL_OPENRAMSEARCH,
EMUCMD_TOOL_RAMSEARCHLT,
EMUCMD_TOOL_RAMSEARCHGT,
EMUCMD_TOOL_RAMSEARCHLTE,
EMUCMD_TOOL_RAMSEARCHGTE,
EMUCMD_TOOL_RAMSEARCHEQ,
EMUCMD_TOOL_RAMSEARCHNE,
EMUCMD_MAX EMUCMD_MAX
}; };
@ -269,4 +275,3 @@ extern bool turbo;
void LagCounterReset(); void LagCounterReset();
#endif //_INPUT_H_ #endif //_INPUT_H_

View File

@ -16,7 +16,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* (VRC4 mapper) * (VRCII mapper)
*/ */
#include "mapinc.h" #include "mapinc.h"
@ -26,8 +26,20 @@
#define K4sel mapbyte1[0] #define K4sel mapbyte1[0]
static int acount=0; static int acount=0;
static int weirdo=0;
static DECLFW(Mapper25_write) static DECLFW(Mapper25_write)
{ {
if(A==0xC007)
{
weirdo=8; // Ganbare Goemon Gaiden does strange things!!! at the end credits
// quick dirty hack, seems there is no other games with such PCB, so
// we never know if it will not work for something else lol
VROM_BANK1(0x0000,0xFC);
VROM_BANK1(0x0400,0xFD);
VROM_BANK1(0x0800,0xFF);
VROM_BANK1(0x0c00,0xCF);
}
A=(A&0xF003)|((A&0xC)>>2); A=(A&0xF003)|((A&0xC)>>2);
if((A&0xF000)==0xA000) if((A&0xF000)==0xA000)
@ -38,6 +50,9 @@ static DECLFW(Mapper25_write)
K4buf[x]&=(0xF0)>>((A&2)<<1); K4buf[x]&=(0xF0)>>((A&2)<<1);
K4buf[x]|=(V&0xF)<<((A&2)<<1); K4buf[x]|=(V&0xF)<<((A&2)<<1);
if(weirdo)
weirdo--;
else
VROM_BANK1(x<<10,K4buf[x]); VROM_BANK1(x<<10,K4buf[x]);
} }
else if((A&0xF000)==0x8000) else if((A&0xF000)==0x8000)

View File

@ -39,7 +39,7 @@ static DECLFR(SUN5AWRAM)
{ {
if((sungah&0xC0)==0x40) if((sungah&0xC0)==0x40)
return X.DB; return X.DB;
return CartBR(A); return CartBROB(A);
} }
static DECLFW(Mapper69_SWL) static DECLFW(Mapper69_SWL)

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,7 @@ typedef struct
int movie_version; // version of the movie format in the file int movie_version; // version of the movie format in the file
uint32 num_frames; uint32 num_frames;
uint32 rerecord_count; uint32 rerecord_count;
bool poweron, pal, nosynchack; bool poweron, pal, nosynchack, ppuflag;
bool reset; //mbg 6/21/08 - this flag isnt used anymore.. but maybe one day we can scan it out of the first record in the movie file bool reset; //mbg 6/21/08 - this flag isnt used anymore.. but maybe one day we can scan it out of the first record in the movie file
uint32 emu_version_used; // 9813 = 0.98.13 uint32 emu_version_used; // 9813 = 0.98.13
MD5DATA md5_of_rom_used; MD5DATA md5_of_rom_used;
@ -58,7 +58,8 @@ enum EMOVIEMODE
MOVIEMODE_INACTIVE = 1, MOVIEMODE_INACTIVE = 1,
MOVIEMODE_RECORD = 2, MOVIEMODE_RECORD = 2,
MOVIEMODE_PLAY = 4, MOVIEMODE_PLAY = 4,
MOVIEMODE_TASEDIT = 8 MOVIEMODE_TASEDIT = 8,
MOVIEMODE_FINISHED = 16
}; };
enum EMOVIECMD enum EMOVIECMD
@ -72,27 +73,31 @@ enum EMOVIECMD
EMOVIEMODE FCEUMOV_Mode(); EMOVIEMODE FCEUMOV_Mode();
bool FCEUMOV_Mode(EMOVIEMODE modemask); bool FCEUMOV_Mode(EMOVIEMODE modemask);
bool FCEUMOV_Mode(int modemask); bool FCEUMOV_Mode(int modemask);
inline bool FCEUMOV_IsPlaying() { return FCEUMOV_Mode(MOVIEMODE_PLAY); } inline bool FCEUMOV_IsPlaying() { return (FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_FINISHED)); }
inline bool FCEUMOV_IsRecording() { return FCEUMOV_Mode(MOVIEMODE_RECORD); } inline bool FCEUMOV_IsRecording() { return FCEUMOV_Mode(MOVIEMODE_RECORD); }
inline bool FCEUMOV_IsFinished() { return FCEUMOV_Mode(MOVIEMODE_FINISHED);}
inline bool FCEUMOV_IsLoaded() { return (FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED)); }
bool FCEUMOV_ShouldPause(void); bool FCEUMOV_ShouldPause(void);
int FCEUMOV_GetFrame(void); int FCEUMOV_GetFrame(void);
int FCEUI_GetLagCount(void); int FCEUI_GetLagCount(void);
bool FCEUI_GetLagged(void); bool FCEUI_GetLagged(void);
int FCEUMOV_WriteState(std::ostream* os); int FCEUMOV_WriteState(EMUFILE* os);
bool FCEUMOV_ReadState(std::istream* is, uint32 size); bool FCEUMOV_ReadState(EMUFILE* is, uint32 size);
void FCEUMOV_PreLoad(); void FCEUMOV_PreLoad();
bool FCEUMOV_PostLoad(); bool FCEUMOV_PostLoad();
void FCEUMOV_EnterTasEdit(); void FCEUMOV_EnterTasEdit();
void FCEUMOV_ExitTasEdit(); void FCEUMOV_ExitTasEdit();
bool FCEUMOV_FromPoweron();
class MovieData; class MovieData;
class MovieRecord class MovieRecord
{ {
public: public:
MovieRecord();
ValueArray<uint8,4> joysticks; ValueArray<uint8,4> joysticks;
struct { struct {
@ -135,17 +140,15 @@ public:
return (joysticks[joy] & mask(bit))!=0; return (joysticks[joy] & mask(bit))!=0;
} }
bool Compare(MovieRecord& compareRec);
void clear(); void clear();
//a waste of memory in lots of cases.. maybe make it a pointer later? void parse(MovieData* md, EMUFILE* is);
std::vector<char> savestate; bool parseBinary(MovieData* md, EMUFILE* is);
void dump(MovieData* md, EMUFILE* os, int index);
void parse(MovieData* md, std::istream* is); void dumpBinary(MovieData* md, EMUFILE* os, int index);
bool parseBinary(MovieData* md, std::istream* is); void parseJoy(EMUFILE* is, uint8& joystate);
void dump(MovieData* md, std::ostream* os, int index); void dumpJoy(EMUFILE* os, uint8 joystate);
void dumpBinary(MovieData* md, std::ostream* os, int index);
void parseJoy(std::istream* is, uint8& joystate);
void dumpJoy(std::ostream* os, uint8 joystate);
static const char mnemonics[8]; static const char mnemonics[8];
@ -157,17 +160,19 @@ class MovieData
{ {
public: public:
MovieData(); MovieData();
// Default Values: MovieData::MovieData()
int version; int version;
int emuVersion; int emuVersion;
int fds; int fds;
//todo - somehow force mutual exclusion for poweron and reset (with an error in the parser) //todo - somehow force mutual exclusion for poweron and reset (with an error in the parser)
bool palFlag; bool palFlag;
bool PPUflag;
MD5DATA romChecksum; MD5DATA romChecksum;
std::string romFilename; std::string romFilename;
std::vector<char> savestate; std::vector<uint8> savestate;
std::vector<MovieRecord> records; std::vector<MovieRecord> records;
std::vector<std::vector<uint8> > savestates;
std::vector<std::wstring> comments; std::vector<std::wstring> comments;
std::vector<std::string> subtitles; std::vector<std::string> subtitles;
//this is the RERECORD COUNT. please rename variable. //this is the RERECORD COUNT. please rename variable.
@ -181,6 +186,8 @@ public:
int ports[3]; int ports[3];
//whether fourscore is enabled //whether fourscore is enabled
bool fourscore; bool fourscore;
//whether microphone is enabled
bool microphone;
//----TasEdit stuff--- //----TasEdit stuff---
int greenZoneCount; int greenZoneCount;
@ -219,15 +226,18 @@ public:
void truncateAt(int frame); void truncateAt(int frame);
void installValue(std::string& key, std::string& val); void installValue(std::string& key, std::string& val);
int dump(std::ostream* os, bool binary); int dump(EMUFILE* os, bool binary);
int dumpGreenzone(std::ostream *os, bool binary); int dumpGreenzone(EMUFILE *os, bool binary);
int loadGreenzone(std::istream *is, bool binary); int loadGreenzone(EMUFILE *is, bool binary);
void clearRecordRange(int start, int len); void clearRecordRange(int start, int len);
void insertEmpty(int at, int frames); void insertEmpty(int at, int frames);
static bool loadSavestateFrom(std::vector<char>* buf); static bool loadSavestateFrom(std::vector<uint8>* buf);
static void dumpSavestateTo(std::vector<char>* buf, int compressionLevel); static void dumpSavestateTo(std::vector<uint8>* buf, int compressionLevel);
bool loadTasSavestate(int frame);
void storeTasSavestate(int frame, int compression_level);
void TryDumpIncremental(); void TryDumpIncremental();
private: private:
@ -250,8 +260,8 @@ extern bool freshMovie;
extern bool movie_readonly; extern bool movie_readonly;
extern bool autoMovieBackup; extern bool autoMovieBackup;
extern int pauseframe; extern int pauseframe;
extern bool fullSaveStateLoads;
//-------------------------------------------------- //--------------------------------------------------
bool CheckFileExists(const char* filename); //Receives a filename (fullpath) and checks to see if that file exists
void FCEUI_MakeBackupMovie(bool dispMessage); void FCEUI_MakeBackupMovie(bool dispMessage);
void FCEUI_CreateMovieFile(std::string fn); void FCEUI_CreateMovieFile(std::string fn);
void FCEUI_SaveMovie(const char *fname, EMOVIE_FLAG flags, std::wstring author); void FCEUI_SaveMovie(const char *fname, EMOVIE_FLAG flags, std::wstring author);
@ -259,7 +269,7 @@ bool FCEUI_LoadMovie(const char *fname, bool read_only, bool tasedit, int _stopf
void FCEUI_MoviePlayFromBeginning(void); void FCEUI_MoviePlayFromBeginning(void);
void FCEUI_StopMovie(void); void FCEUI_StopMovie(void);
bool FCEUI_MovieGetInfo(FCEUFILE* fp, MOVIE_INFO& info, bool skipFrameCount = false); bool FCEUI_MovieGetInfo(FCEUFILE* fp, MOVIE_INFO& info, bool skipFrameCount = false);
char* FCEUI_MovieGetCurrentName(int addSlotNumber); //char* FCEUI_MovieGetCurrentName(int addSlotNumber);
void FCEUI_MovieToggleReadOnly(void); void FCEUI_MovieToggleReadOnly(void);
bool FCEUI_GetMovieToggleReadOnly(); bool FCEUI_GetMovieToggleReadOnly();
void FCEUI_SetMovieToggleReadOnly(bool which); void FCEUI_SetMovieToggleReadOnly(bool which);
@ -269,7 +279,7 @@ std::string FCEUI_GetMovieName(void);
void FCEUI_MovieToggleFrameDisplay(); void FCEUI_MovieToggleFrameDisplay();
void FCEUI_ToggleInputDisplay(void); void FCEUI_ToggleInputDisplay(void);
void LoadSubtitles(MovieData); void LoadSubtitles(MovieData &);
void ProcessSubtitles(void); void ProcessSubtitles(void);
void FCEU_DisplaySubtitles(char *format, ...); void FCEU_DisplaySubtitles(char *format, ...);

View File

@ -50,7 +50,7 @@ static int netdcount;
static void NetError(void) static void NetError(void)
{ {
FCEU_DispMessage("Network error/connection lost!"); FCEU_DispMessage("Network error/connection lost!",0);
FCEUD_NetworkClose(); FCEUD_NetworkClose();
} }
@ -310,7 +310,7 @@ void NetplayUpdate(uint8 *joyp)
if(FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP)) if(FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP))
{ {
fclose(fp); fclose(fp);
FCEU_DispMessage("Remote state loaded."); FCEU_DispMessage("Remote state loaded.",0);
} else FCEUD_PrintError("File error. (K)ill, (M)aim, (D)estroy?"); } else FCEUD_PrintError("File error. (K)ill, (M)aim, (D)estroy?");
} }
break;*/ break;*/

View File

@ -790,8 +790,31 @@ static DECLFR(A2007)
if(!fceuindbg) if(!fceuindbg)
#endif #endif
{ {
if(INC32) RefreshAddr+=32; if((ScreenON || SpriteON) && (scanline < 240))
else RefreshAddr++; {
uint32 rad=RefreshAddr;
if((rad&0x7000)==0x7000)
{
rad^=0x7000;
if((rad&0x3E0)==0x3A0)
rad^=0xBA0;
else if((rad&0x3E0)==0x3e0)
rad^=0x3e0;
else
rad+=0x20;
}
else
rad+=0x1000;
RefreshAddr=rad;
}
else
{
if (INC32)
RefreshAddr+=32;
else
RefreshAddr++;
}
if(PPU_hook) PPU_hook(RefreshAddr&0x3fff); if(PPU_hook) PPU_hook(RefreshAddr&0x3fff);
} }
@ -1337,21 +1360,15 @@ static void Fixit1(void)
{ {
rad ^= 0x7000; rad ^= 0x7000;
if((rad & 0x3E0) == 0x3A0) if((rad & 0x3E0) == 0x3A0)
{ rad ^= 0xBA0;
rad^=0x3A0; else if((rad & 0x3E0) == 0x3e0)
rad^=0x800;
}
else
{
if((rad&0x3E0)==0x3e0)
rad ^= 0x3e0; rad ^= 0x3e0;
else rad+=0x20; else
} rad += 0x20;
} }
else else
rad += 0x1000; rad += 0x1000;
RefreshAddr = rad; RefreshAddr = rad;
//PPU_hook(RefreshAddr); //,-1);
} }
} }
@ -2002,7 +2019,7 @@ int FCEUPPU_Loop(int skip)
} }
deempcnt[x]=0; deempcnt[x]=0;
} }
//FCEU_DispMessage("%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x %d",deempcnt[0],deempcnt[1],deempcnt[2],deempcnt[3],deempcnt[4],deempcnt[5],deempcnt[6],deempcnt[7],maxref); //FCEU_DispMessage("%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x %d",0,deempcnt[0],deempcnt[1],deempcnt[2],deempcnt[3],deempcnt[4],deempcnt[5],deempcnt[6],deempcnt[7],maxref);
//memset(deempcnt,0,sizeof(deempcnt)); //memset(deempcnt,0,sizeof(deempcnt));
SetNESDeemph(maxref,0); SetNESDeemph(maxref,0);
} }

View File

@ -201,8 +201,6 @@ void LogDPCM(int romaddress, int dpcmsize){
} }
} }
} }
return;
} }
/* Instantaneous? Maybe the new freq value is being calculated all of the time... */ /* Instantaneous? Maybe the new freq value is being calculated all of the time... */

View File

@ -36,7 +36,6 @@
#include "sound.h" #include "sound.h"
#include "utils/endian.h" #include "utils/endian.h"
#include "utils/memory.h" #include "utils/memory.h"
#include "utils/memorystream.h"
#include "utils/xstring.h" #include "utils/xstring.h"
#include "file.h" #include "file.h"
#include "fds.h" #include "fds.h"
@ -120,7 +119,7 @@ SFORMAT SFCPUC[]={
void foo(uint8* test) { (void)test; } void foo(uint8* test) { (void)test; }
static int SubWrite(std::ostream* os, SFORMAT *sf) static int SubWrite(EMUFILE* os, SFORMAT *sf)
{ {
uint32 acc=0; uint32 acc=0;
@ -142,7 +141,7 @@ static int SubWrite(std::ostream* os, SFORMAT *sf)
if(os) //Are we writing or calculating the size of this block? if(os) //Are we writing or calculating the size of this block?
{ {
os->write(sf->desc,4); os->fwrite(sf->desc,4);
write32le(sf->s&(~FCEUSTATE_FLAGS),os); write32le(sf->s&(~FCEUSTATE_FLAGS),os);
#ifndef LSB_FIRST #ifndef LSB_FIRST
@ -151,9 +150,9 @@ static int SubWrite(std::ostream* os, SFORMAT *sf)
#endif #endif
if(sf->s&FCEUSTATE_INDIRECT) if(sf->s&FCEUSTATE_INDIRECT)
os->write(*(char **)sf->v,sf->s&(~FCEUSTATE_FLAGS)); os->fwrite(*(char **)sf->v,sf->s&(~FCEUSTATE_FLAGS));
else else
os->write((char*)sf->v,sf->s&(~FCEUSTATE_FLAGS)); os->fwrite((char*)sf->v,sf->s&(~FCEUSTATE_FLAGS));
//Now restore the original byte order. //Now restore the original byte order.
#ifndef LSB_FIRST #ifndef LSB_FIRST
@ -167,10 +166,10 @@ static int SubWrite(std::ostream* os, SFORMAT *sf)
return(acc); return(acc);
} }
static int WriteStateChunk(std::ostream* os, int type, SFORMAT *sf) static int WriteStateChunk(EMUFILE* os, int type, SFORMAT *sf)
{ {
os->put(type); os->fputc(type);
int bsize = SubWrite((std::ostream*)0,sf); int bsize = SubWrite((EMUFILE*)0,sf);
write32le(bsize,os); write32le(bsize,os);
if(!SubWrite(os,sf)) if(!SubWrite(os,sf))
@ -203,16 +202,16 @@ static SFORMAT *CheckS(SFORMAT *sf, uint32 tsize, char *desc)
return(0); return(0);
} }
static bool ReadStateChunk(std::istream* is, SFORMAT *sf, int size) static bool ReadStateChunk(EMUFILE* is, SFORMAT *sf, int size)
{ {
SFORMAT *tmp; SFORMAT *tmp;
int temp = is->tellg(); int temp = is->ftell();
while(is->tellg()<temp+size) while(is->ftell()<temp+size)
{ {
uint32 tsize; uint32 tsize;
char toa[4]; char toa[4];
if(is->read(toa,4).gcount()<4) if(is->fread(toa,4)<4)
return false; return false;
read32le(&tsize,is); read32le(&tsize,is);
@ -220,9 +219,9 @@ static bool ReadStateChunk(std::istream* is, SFORMAT *sf, int size)
if((tmp=CheckS(sf,tsize,toa))) if((tmp=CheckS(sf,tsize,toa)))
{ {
if(tmp->s&FCEUSTATE_INDIRECT) if(tmp->s&FCEUSTATE_INDIRECT)
is->read(*(char **)tmp->v,tmp->s&(~FCEUSTATE_FLAGS)); is->fread(*(char **)tmp->v,tmp->s&(~FCEUSTATE_FLAGS));
else else
is->read((char *)tmp->v,tmp->s&(~FCEUSTATE_FLAGS)); is->fread((char *)tmp->v,tmp->s&(~FCEUSTATE_FLAGS));
#ifndef LSB_FIRST #ifndef LSB_FIRST
if(tmp->s&RLSB) if(tmp->s&RLSB)
@ -230,7 +229,7 @@ static bool ReadStateChunk(std::istream* is, SFORMAT *sf, int size)
#endif #endif
} }
else else
is->seekg(tsize,std::ios::cur); is->fseek(tsize,SEEK_CUR);
} // while(...) } // while(...)
return true; return true;
} }
@ -239,7 +238,7 @@ static int read_sfcpuc=0, read_snd=0;
void FCEUD_BlitScreen(uint8 *XBuf); //mbg merge 7/17/06 YUCKY had to add void FCEUD_BlitScreen(uint8 *XBuf); //mbg merge 7/17/06 YUCKY had to add
void UpdateFCEUWindow(void); //mbg merge 7/17/06 YUCKY had to add void UpdateFCEUWindow(void); //mbg merge 7/17/06 YUCKY had to add
static bool ReadStateChunks(std::istream* is, int32 totalsize) static bool ReadStateChunks(EMUFILE* is, int32 totalsize)
{ {
int t; int t;
uint32 size; uint32 size;
@ -256,7 +255,7 @@ static bool ReadStateChunks(std::istream* is, int32 totalsize)
while(totalsize > 0) while(totalsize > 0)
{ {
t=is->get(); t=is->fgetc();
if(t==EOF) break; if(t==EOF) break;
if(!read32le(&size,is)) break; if(!read32le(&size,is)) break;
totalsize -= size + 5; totalsize -= size + 5;
@ -284,20 +283,20 @@ static bool ReadStateChunks(std::istream* is, int32 totalsize)
read_snd=1; read_snd=1;
break; break;
case 6: case 6:
if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD)) if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED))
{ {
if(!ReadStateChunk(is,FCEUMOV_STATEINFO,size)) ret=false; if(!ReadStateChunk(is,FCEUMOV_STATEINFO,size)) ret=false;
} }
else else
{ {
is->seekg(size,std::ios::cur); is->fseek(size,SEEK_CUR);
} }
break; break;
case 8: case 8:
// load back buffer // load back buffer
{ {
extern uint8 *XBackBuf; extern uint8 *XBackBuf;
if(is->read((char*)XBackBuf,size).gcount() != size) if(is->fread((char*)XBackBuf,size) != size)
ret = false; ret = false;
//MBG TODO - can this be moved to a better place? //MBG TODO - can this be moved to a better place?
@ -329,7 +328,7 @@ static bool ReadStateChunks(std::istream* is, int32 totalsize)
warned=true; warned=true;
} }
//if(fseek(st,size,SEEK_CUR)<0) goto endo;break; //if(fseek(st,size,SEEK_CUR)<0) goto endo;break;
is->seekg(size,std::ios::cur); is->fseek(size,SEEK_CUR);
} }
} }
//endo: //endo:
@ -354,17 +353,13 @@ int CurrentState=0;
extern int geniestage; extern int geniestage;
bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel) bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel)
{ {
//a temp memory stream. we'll dump some data here and then compress //a temp memory stream. we'll dump some data here and then compress
//TODO - support dumping directly without compressing to save a buffer copy //TODO - support dumping directly without compressing to save a buffer copy
#ifdef GEKKO EMUFILE_MEMORY ms;
memorystream ms(512*1024); // set aside some space, otherwise expand fails on Wii! EMUFILE* os = &ms;
#else
memorystream ms;
#endif
std::ostream* os = (std::ostream*)&ms;
uint32 totalsize = 0; uint32 totalsize = 0;
@ -376,7 +371,7 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel)
totalsize+=WriteStateChunk(os,31,FCEU_NEWPPU_STATEINFO); totalsize+=WriteStateChunk(os,31,FCEU_NEWPPU_STATEINFO);
totalsize+=WriteStateChunk(os,4,FCEUCTRL_STATEINFO); totalsize+=WriteStateChunk(os,4,FCEUCTRL_STATEINFO);
totalsize+=WriteStateChunk(os,5,FCEUSND_STATEINFO); totalsize+=WriteStateChunk(os,5,FCEUSND_STATEINFO);
if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD)) if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED))
{ {
totalsize+=WriteStateChunk(os,6,FCEUMOV_STATEINFO); totalsize+=WriteStateChunk(os,6,FCEUMOV_STATEINFO);
@ -384,12 +379,12 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel)
//do not save the movie state if we are in tasedit! that is a huge waste of time and space! //do not save the movie state if we are in tasedit! that is a huge waste of time and space!
if(!FCEUMOV_Mode(MOVIEMODE_TASEDIT)) if(!FCEUMOV_Mode(MOVIEMODE_TASEDIT))
{ {
os->seekp(5,std::ios::cur); os->fseek(5,SEEK_CUR);
int size = FCEUMOV_WriteState(os); int size = FCEUMOV_WriteState(os);
os->seekp(-(size+5),std::ios::cur); os->fseek(-(size+5),SEEK_CUR);
os->put(7); os->fputc(7);
write32le(size, os); write32le(size, os);
os->seekp(size,std::ios::cur); os->fseek(size,SEEK_CUR);
totalsize += 5 + size; totalsize += 5 + size;
} }
@ -398,9 +393,9 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel)
{ {
extern uint8 *XBackBuf; extern uint8 *XBackBuf;
uint32 size = 256 * 256 + 8; uint32 size = 256 * 256 + 8;
os->put(8); os->fputc(8);
write32le(size, os); write32le(size, os);
os->write((char*)XBackBuf,size); os->fwrite((char*)XBackBuf,size);
totalsize += 5 + size; totalsize += 5 + size;
} }
@ -409,11 +404,7 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel)
if(SPreSave) SPostSave(); if(SPreSave) SPostSave();
//save the length of the file //save the length of the file
#ifdef GEKKO
int len = ms.tellp();
#else
int len = ms.size(); int len = ms.size();
#endif
//sanity check: len and totalsize should be the same //sanity check: len and totalsize should be the same
if(len != totalsize) if(len != totalsize)
@ -441,8 +432,8 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel)
FCEU_en32lsb(header+12, comprlen); FCEU_en32lsb(header+12, comprlen);
//dump it to the destination file //dump it to the destination file
outstream->write((char*)header,16); outstream->fwrite((char*)header,16);
outstream->write((char*)cbuf,comprlen==-1?totalsize:comprlen); outstream->fwrite((char*)cbuf,comprlen==-1?totalsize:comprlen);
if(cbuf != (uint8*)ms.buf()) delete[] cbuf; if(cbuf != (uint8*)ms.buf()) delete[] cbuf;
return error == Z_OK; return error == Z_OK;
@ -451,12 +442,12 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel)
void FCEUSS_Save(const char *fname) void FCEUSS_Save(const char *fname)
{ {
std::fstream* st = 0; EMUFILE* st = 0;
char fn[2048]; char fn[2048];
if(geniestage==1) if(geniestage==1)
{ {
FCEU_DispMessage("Cannot save FCS in GG screen."); FCEU_DispMessage("Cannot save FCS in GG screen.",0);
return; return;
} }
@ -485,7 +476,7 @@ void FCEUSS_Save(const char *fname)
if(st == NULL) if(st == NULL)
{ {
FCEU_DispMessage("State %d save error.",CurrentState); FCEU_DispMessage("State %d save error.",0,CurrentState);
return; return;
} }
@ -525,12 +516,12 @@ void FCEUSS_Save(const char *fname)
if(!fname) if(!fname)
{ {
SaveStateStatus[CurrentState]=1; SaveStateStatus[CurrentState]=1;
FCEU_DispMessage("State %d saved.",CurrentState); FCEU_DispMessage("State %d saved.",0,CurrentState);
} }
redoSS = false; //we have a new savestate so redo is not possible redoSS = false; //we have a new savestate so redo is not possible
} }
int FCEUSS_LoadFP_old(std::istream* is, ENUM_SSLOADPARAMS params) int FCEUSS_LoadFP_old(EMUFILE* is, ENUM_SSLOADPARAMS params)
{ {
//if(params==SSLOADPARAM_DUMMY && suppress_scan_chunks) //if(params==SSLOADPARAM_DUMMY && suppress_scan_chunks)
// return 1; // return 1;
@ -566,7 +557,7 @@ int FCEUSS_LoadFP_old(std::istream* is, ENUM_SSLOADPARAMS params)
{ {
FCEUMOV_PreLoad(); FCEUMOV_PreLoad();
} }
is->read((char*)&header,16); is->fread((char*)&header,16);
if(memcmp(header,"FCS",3)) if(memcmp(header,"FCS",3))
{ {
return(0); return(0);
@ -624,21 +615,25 @@ int FCEUSS_LoadFP_old(std::istream* is, ENUM_SSLOADPARAMS params)
} }
bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params) bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params)
{ {
//maybe make a backup savestate //maybe make a backup savestate
memorystream msBackupSavestate; EMUFILE_MEMORY msBackupSavestate;
bool backup = (params == SSLOADPARAM_BACKUP); bool backup = (params == SSLOADPARAM_BACKUP);
if(!is)
return false;
if(backup) if(backup)
FCEUSS_SaveMS(&msBackupSavestate,Z_NO_COMPRESSION); FCEUSS_SaveMS(&msBackupSavestate,Z_NO_COMPRESSION);
uint8 header[16]; uint8 header[16];
//read and analyze the header //read and analyze the header
is->read((char*)&header,16); is->fread((char*)&header,16);
if(memcmp(header,"FCSX",4)) { if(memcmp(header,"FCSX",4)) {
//its not an fceux save file.. perhaps it is an fceu savefile //its not an fceux save file.. perhaps it is an fceu savefile
is->seekg(0); is->fseek(0,SEEK_SET);
FCEU_state_loading_old_format = true; FCEU_state_loading_old_format = true;
bool ret = FCEUSS_LoadFP_old(is,params)!=0; bool ret = FCEUSS_LoadFP_old(is,params)!=0;
FCEU_state_loading_old_format = false; FCEU_state_loading_old_format = false;
@ -650,14 +645,14 @@ bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params)
int stateversion = FCEU_de32lsb(header + 8); int stateversion = FCEU_de32lsb(header + 8);
int comprlen = FCEU_de32lsb(header + 12); int comprlen = FCEU_de32lsb(header + 12);
std::vector<char> buf(totalsize); std::vector<uint8> buf(totalsize);
//not compressed: //not compressed:
if(comprlen != -1) if(comprlen != -1)
{ {
//load the compressed chunk and decompress //load the compressed chunk and decompress
std::vector<char> cbuf(comprlen); std::vector<char> cbuf(comprlen);
is->read((char*)&cbuf[0],comprlen); is->fread((char*)&cbuf[0],comprlen);
uLongf uncomprlen = totalsize; uLongf uncomprlen = totalsize;
int error = uncompress((uint8*)&buf[0],&uncomprlen,(uint8*)&cbuf[0],comprlen); int error = uncompress((uint8*)&buf[0],&uncomprlen,(uint8*)&cbuf[0],comprlen);
@ -667,12 +662,12 @@ bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params)
} }
else else
{ {
is->read((char*)&buf[0],totalsize); is->fread((char*)&buf[0],totalsize);
} }
FCEUMOV_PreLoad(); FCEUMOV_PreLoad();
memorystream mstemp(&buf); EMUFILE_MEMORY mstemp(&buf);
bool x = ReadStateChunks(&mstemp,totalsize)!=0; bool x = ReadStateChunks(&mstemp,totalsize)!=0;
//mbg 5/24/08 - we don't support old states, so this shouldnt matter. //mbg 5/24/08 - we don't support old states, so this shouldnt matter.
@ -691,7 +686,7 @@ bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params)
} }
if(!x && backup) { if(!x && backup) {
msBackupSavestate.sync(); msBackupSavestate.fseek(0,SEEK_SET);
FCEUSS_LoadFP(&msBackupSavestate,SSLOADPARAM_NOBACKUP); FCEUSS_LoadFP(&msBackupSavestate,SSLOADPARAM_NOBACKUP);
} }
@ -701,7 +696,7 @@ bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params)
bool FCEUSS_Load(const char *fname) bool FCEUSS_Load(const char *fname)
{ {
std::fstream* st; EMUFILE* st;
char fn[2048]; char fn[2048];
//mbg movie - this needs to be overhauled //mbg movie - this needs to be overhauled
@ -713,7 +708,7 @@ bool FCEUSS_Load(const char *fname)
if(geniestage==1) if(geniestage==1)
{ {
FCEU_DispMessage("Cannot load FCS in GG screen."); FCEU_DispMessage("Cannot load FCS in GG screen.",0);
return false; return false;
} }
if(fname) if(fname)
@ -730,7 +725,7 @@ bool FCEUSS_Load(const char *fname)
if(st == NULL) if(st == NULL)
{ {
FCEU_DispMessage("State %d load error.",CurrentState); FCEU_DispMessage("State %d load error.",0,CurrentState);
SaveStateStatus[CurrentState]=0; SaveStateStatus[CurrentState]=0;
return false; return false;
} }
@ -738,20 +733,17 @@ bool FCEUSS_Load(const char *fname)
//If in bot mode, don't do a backup when loading. //If in bot mode, don't do a backup when loading.
//Otherwise you eat at the hard disk, since so many //Otherwise you eat at the hard disk, since so many
//states are being loaded. //states are being loaded.
if(FCEUSS_LoadFP(st,SSLOADPARAM_BACKUP)) if(FCEUSS_LoadFP(st, backupSavestates ? SSLOADPARAM_BACKUP : SSLOADPARAM_NOBACKUP))
{ {
if(fname) if(fname)
{ {
char szFilename[260]={0}; char szFilename[260]={0};
splitpath(fname, 0, 0, szFilename, 0); splitpath(fname, 0, 0, szFilename, 0);
FCEU_DispMessage("State %s loaded.",szFilename); FCEU_DispMessage("State %s loaded.",0,szFilename);
} }
else else
{ {
//This looks redudant to me... but why bother deleting it:) FCEU_DispMessage("State %d loaded.",0,CurrentState);
SaveStateStatus[CurrentState]=1;
FCEU_DispMessage("State %d loaded.",CurrentState);
SaveStateStatus[CurrentState]=1; SaveStateStatus[CurrentState]=1;
} }
delete st; delete st;
@ -779,6 +771,13 @@ bool FCEUSS_Load(const char *fname)
#ifdef WIN32 #ifdef WIN32
Update_RAM_Search(); // Update_RAM_Watch() is also called. Update_RAM_Search(); // Update_RAM_Watch() is also called.
#endif #endif
//Update input display if movie is loaded
extern uint32 cur_input_display;
extern uint8 FCEU_GetJoyJoy(void);
cur_input_display = FCEU_GetJoyJoy(); //Input display should show the last buttons pressed (stored in the savestate)
return true; return true;
} }
else else
@ -787,7 +786,7 @@ bool FCEUSS_Load(const char *fname)
{ {
SaveStateStatus[CurrentState]=1; SaveStateStatus[CurrentState]=1;
} }
FCEU_DispMessage("Error(s) reading state %d!",CurrentState); FCEU_DispMessage("Error(s) reading state %d!",0,CurrentState);
delete st; delete st;
return 0; return 0;
} }
@ -875,7 +874,7 @@ int FCEUI_SelectState(int w, int show)
if(show) if(show)
{ {
StateShow=180; StateShow=180;
FCEU_DispMessage("-select state-"); FCEU_DispMessage("-select state-",0);
} }
return oldstate; return oldstate;
} }
@ -891,6 +890,15 @@ void FCEUI_SaveState(const char *fname)
int loadStateFailed = 0; // hack, this function should return a value instead int loadStateFailed = 0; // hack, this function should return a value instead
bool file_exists(const char * filename)
{
if (FILE * file = fopen(filename, "r")) //I'm sure, you meant for READING =)
{
fclose(file);
return true;
}
return false;
}
void FCEUI_LoadState(const char *fname) void FCEUI_LoadState(const char *fname)
{ {
if(!FCEU_IsValidUI(FCEUI_LOADSTATE)) return; if(!FCEU_IsValidUI(FCEUI_LOADSTATE)) return;
@ -909,6 +917,11 @@ void FCEUI_LoadState(const char *fname)
{ {
FCEUI_MakeBackupMovie(false); //Backup the movie before the contents get altered, but do not display messages FCEUI_MakeBackupMovie(false); //Backup the movie before the contents get altered, but do not display messages
} }
if (fname != NULL && !file_exists(fname))
{
loadStateFailed = 1;
return; // state doesn't exist; exit cleanly
}
if(FCEUSS_Load(fname)) if(FCEUSS_Load(fname))
{ {
//mbg todo netplay //mbg todo netplay
@ -984,14 +997,14 @@ void SwapSaveState()
if (!lastSavestateMade) if (!lastSavestateMade)
{ {
FCEUI_DispMessage("Can't Undo"); FCEUI_DispMessage("Can't Undo",0);
FCEUI_printf("Undo savestate was attempted but unsuccessful because there was not a recently used savestate.\n"); FCEUI_printf("Undo savestate was attempted but unsuccessful because there was not a recently used savestate.\n");
return; //If there is no last savestate, can't undo return; //If there is no last savestate, can't undo
} }
string backup = GenerateBackupSaveStateFn(lastSavestateMade); //Get filename of backup state string backup = GenerateBackupSaveStateFn(lastSavestateMade); //Get filename of backup state
if (!CheckFileExists(backup.c_str())) if (!CheckFileExists(backup.c_str()))
{ {
FCEUI_DispMessage("Can't Undo"); FCEUI_DispMessage("Can't Undo",0);
FCEUI_printf("Undo savestate was attempted but unsuccessful because there was not a backup of the last used savestate.\n"); FCEUI_printf("Undo savestate was attempted but unsuccessful because there was not a backup of the last used savestate.\n");
return; //If no backup, can't undo return; //If no backup, can't undo
} }
@ -1012,8 +1025,8 @@ void SwapSaveState()
else //This was an undo function so next will be redo, so flag it else //This was an undo function so next will be redo, so flag it
redoSS = true; redoSS = true;
FCEUI_DispMessage("%s restored",backup.c_str()); FCEUI_DispMessage("%s restored",0,backup.c_str());
FCEUI_printf("%s restored\n",backup.c_str()); FCEUI_printf("%s restored\n",0,backup.c_str());
} }
//------------------------------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------------------------------
@ -1081,7 +1094,7 @@ void LoadBackup()
undoLS = false; //Flag that LoadBackup cannot be run again undoLS = false; //Flag that LoadBackup cannot be run again
} }
else else
FCEUI_DispMessage("Error: Could not load %s",filename.c_str()); FCEUI_DispMessage("Error: Could not load %s",0,filename.c_str());
} }
void RedoLoadState() void RedoLoadState()

View File

@ -28,9 +28,9 @@ void FCEUSS_Save(const char *);
bool FCEUSS_Load(const char *); bool FCEUSS_Load(const char *);
//zlib values: 0 (none) through 9 (max) or -1 (default) //zlib values: 0 (none) through 9 (max) or -1 (default)
bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel); bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel);
bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params); bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params);
extern int CurrentState; extern int CurrentState;
void FCEUSS_CheckStates(void); void FCEUSS_CheckStates(void);

View File

@ -72,6 +72,7 @@ typedef uint32_t uint32;
#ifdef __GNUC__ #ifdef __GNUC__
typedef unsigned long long uint64; typedef unsigned long long uint64;
typedef uint64 u64;
typedef long long int64; typedef long long int64;
#define INLINE inline #define INLINE inline
#define GINLINE inline #define GINLINE inline
@ -127,10 +128,10 @@ typedef uint32_t uint32;
typedef void (*writefunc)(uint32 A, uint8 V); typedef void (*writefunc)(uint32 A, uint8 V);
typedef uint8 (*readfunc)(uint32 A); typedef uint8 (*readfunc)(uint32 A);
#include "utils/endian.h"
#ifndef CTASSERT #ifndef CTASSERT
#define CTASSERT(x) typedef char __assert ## y[(x) ? 1 : -1]; #define CTASSERT(x) typedef char __assert ## y[(x) ? 1 : -1];
#endif #endif
#include "utils/endian.h"
#endif #endif

View File

@ -26,6 +26,27 @@
#include <fstream> #include <fstream>
#include "../types.h" #include "../types.h"
#include "endian.h" #include "endian.h"
#include "../emufile.h"
//OMG ! configure this correctly
#define LOCAL_BE
/* little endian to local endianess convert macros */
#ifdef LOCAL_BE /* local arch is big endian */
# define LE_TO_LOCAL_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
# define LE_TO_LOCAL_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
# define LE_TO_LOCAL_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00)|(((x)>>40)&0xff00)|(((x)>>56)&0xff))
# define LOCAL_TO_LE_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
# define LOCAL_TO_LE_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
# define LOCAL_TO_LE_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00)|(((x)>>40)&0xff00)|(((x)>>56)&0xff))
#else /* local arch is little endian */
# define LE_TO_LOCAL_16(x) (x)
# define LE_TO_LOCAL_32(x) (x)
# define LE_TO_LOCAL_64(x) (x)
# define LOCAL_TO_LE_16(x) (x)
# define LOCAL_TO_LE_32(x) (x)
# define LOCAL_TO_LE_64(x) (x)
#endif
///endian-flips count bytes. count should be even and nonzero. ///endian-flips count bytes. count should be even and nonzero.
void FlipByteOrder(uint8 *src, uint32 count) void FlipByteOrder(uint8 *src, uint32 count)
@ -194,3 +215,99 @@ uint16 FCEU_de16lsb(uint8 *morp)
{ {
return morp[0]|(morp[1]<<8); return morp[0]|(morp[1]<<8);
} }
//well. just for the sake of consistency
int write8le(u8 b, EMUFILE*os)
{
os->fwrite((char*)&b,1);
return 1;
}
//well. just for the sake of consistency
int read8le(u8 *Bufo, EMUFILE*is)
{
if(is->_fread((char*)Bufo,1) != 1)
return 0;
return 1;
}
///writes a little endian 16bit value to the specified file
int write16le(u16 b, EMUFILE *fp)
{
u8 s[2];
s[0]=(u8)b;
s[1]=(u8)(b>>8);
fp->fwrite(s,2);
return 2;
}
///writes a little endian 32bit value to the specified file
int write32le(u32 b, EMUFILE *fp)
{
uint8 s[4];
s[0]=(u8)b;
s[1]=(u8)(b>>8);
s[2]=(u8)(b>>16);
s[3]=(u8)(b>>24);
fp->fwrite(s,4);
return 4;
}
void writebool(bool b, EMUFILE* os) { write32le(b?1:0,os); }
int write64le(uint64 b, EMUFILE* os)
{
uint8 s[8];
s[0]=(u8)b;
s[1]=(u8)(b>>8);
s[2]=(u8)(b>>16);
s[3]=(u8)(b>>24);
s[4]=(u8)(b>>32);
s[5]=(u8)(b>>40);
s[6]=(u8)(b>>48);
s[7]=(u8)(b>>56);
os->fwrite((char*)&s,8);
return 8;
}
int read32le(uint32 *Bufo, EMUFILE *fp)
{
uint32 buf;
if(fp->_fread(&buf,4)<4)
return 0;
#ifdef LOCAL_LE
*(u32*)Bufo=buf;
#else
*(u32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24);
#endif
return 1;
}
int read16le(u16 *Bufo, EMUFILE *is)
{
u16 buf;
if(is->_fread((char*)&buf,2) != 2)
return 0;
#ifdef LOCAL_LE
*Bufo=buf;
#else
*Bufo = LE_TO_LOCAL_16(buf);
#endif
return 1;
}
int read64le(uint64 *Bufo, EMUFILE *is)
{
uint64 buf;
if(is->_fread((char*)&buf,8) != 8)
return 0;
#ifdef LOCAL_LE
*Bufo=buf;
#else
*Bufo = LE_TO_LOCAL_64(buf);
#endif
return 1;
}

View File

@ -3,6 +3,44 @@
#include <iosfwd> #include <iosfwd>
#include <stdio.h> #include <stdio.h>
#include "../emufile.h"
#include "../types.h"
inline uint64 double_to_u64(double d) {
union {
uint64 a;
double b;
} fuxor;
fuxor.b = d;
return fuxor.a;
}
inline double u64_to_double(uint64 u) {
union {
uint64 a;
double b;
} fuxor;
fuxor.a = u;
return fuxor.b;
}
inline uint32 float_to_u32(float f) {
union {
uint32 a;
float b;
} fuxor;
fuxor.b = f;
return fuxor.a;
}
inline float u32_to_float(uint32 u) {
union {
uint32 a;
float b;
} fuxor;
fuxor.a = u;
return fuxor.b;
}
int write16le(uint16 b, FILE *fp); int write16le(uint16 b, FILE *fp);
@ -22,5 +60,50 @@ uint64 FCEU_de64lsb(uint8 *morp);
uint32 FCEU_de32lsb(uint8 *morp); uint32 FCEU_de32lsb(uint8 *morp);
uint16 FCEU_de16lsb(uint8 *morp); uint16 FCEU_de16lsb(uint8 *morp);
#endif //well. just for the sake of consistency
int write8le(uint8 b, EMUFILE *fp);
inline int write8le(uint8* b, EMUFILE *fp) { return write8le(*b,fp); }
int write16le(uint16 b, EMUFILE* os);
int write32le(uint32 b, EMUFILE* os);
int write64le(uint64 b, EMUFILE* os);
inline int write_double_le(double b, EMUFILE*is) { uint64 temp = double_to_u64(b); int ret = write64le(temp,is); return ret; }
int read8le(uint8 *Bufo, EMUFILE*is);
int read16le(uint16 *Bufo, EMUFILE*is);
inline int read16le(int16 *Bufo, EMUFILE*is) { return read16le((u16*)Bufo,is); }
int read32le(uint32 *Bufo, EMUFILE*is);
inline int read32le(int32 *Bufo, EMUFILE*is) { return read32le((u32*)Bufo,is); }
int read64le(uint64 *Bufo, EMUFILE*is);
inline int read_double_le(double *Bufo, EMUFILE*is) { uint64 temp; int ret = read64le(&temp,is); *Bufo = u64_to_double(temp); return ret; }
template<typename T>
int readle(T *Bufo, EMUFILE*is)
{
CTASSERT(sizeof(T)==1||sizeof(T)==2||sizeof(T)==4||sizeof(T)==8);
switch(sizeof(T)) {
case 1: return read8le((u8*)Bufo,is);
case 2: return read16le((u16*)Bufo,is);
case 4: return read32le((u32*)Bufo,is);
case 8: return read64le((u64*)Bufo,is);
default:
return 0;
}
}
template<typename T>
int writele(T *Bufo, EMUFILE*os)
{
CTASSERT(sizeof(T)==1||sizeof(T)==2||sizeof(T)==4||sizeof(T)==8);
switch(sizeof(T)) {
case 1: return write8le((u8*)Bufo,os);
case 2: return write16le((u16*)Bufo,os);
case 4: return write32le((u32*)Bufo,os);
case 8: return write64le((u64*)Bufo,os);
default:
return 0;
}
}
#endif //__FCEU_ENDIAN

View File

@ -553,13 +553,13 @@ std::string stditoa(int n)
} }
std::string readNullTerminatedAscii(std::istream* is) std::string readNullTerminatedAscii(EMUFILE* is)
{ {
std::string ret; std::string ret;
ret.reserve(50); ret.reserve(50);
for(;;) for(;;)
{ {
int c = is->get(); int c = is->fgetc();
if(c == 0) break; if(c == 0) break;
else ret += (char)c; else ret += (char)c;
} }
@ -723,7 +723,7 @@ namespace UtfConverter
return result; return result;
} }
#ifndef GEKKO
std::wstring FromUtf8(std::string& input) // string -> wstring std::wstring FromUtf8(std::string& input) // string -> wstring
{ {
std::wstring result; std::wstring result;
@ -739,11 +739,10 @@ namespace UtfConverter
SeqValue(result, input[pos]); SeqValue(result, input[pos]);
return result; return result;
} }
#endif
} }
#endif #endif
#ifndef GEKKO
//convert a std::string to std::wstring //convert a std::string to std::wstring
std::wstring mbstowcs(std::string str) // UTF8->UTF32 std::wstring mbstowcs(std::string str) // UTF8->UTF32
{ {
@ -759,7 +758,7 @@ std::string wcstombs(std::wstring str) // UTF32->UTF8
{ {
return UtfConverter::ToUtf8(str); return UtfConverter::ToUtf8(str);
} }
#endif
//TODO - dont we already have another function that can do this //TODO - dont we already have another function that can do this
std::string getExtension(const char* input) { std::string getExtension(const char* input) {
@ -775,3 +774,16 @@ std::string getExtension(const char* input) {
ext[k]=tolower(ext[k]); ext[k]=tolower(ext[k]);
return ext; return ext;
} }
//strips the file extension off a filename
std::string StripExtension(std::string filename)
{
return filename.substr(0, filename.find_last_of("."));
}
//strips the path off a filename
std::string StripPath(std::string filename)
{
int x = filename.find_last_of("\\") + 1;
return filename.substr(x, filename.length() - x);
}

View File

@ -24,6 +24,7 @@
#include <iostream> #include <iostream>
#include "../types.h" #include "../types.h"
#include "../emufile.h"
#ifndef __GNUC__ #ifndef __GNUC__
#define strcasecmp strcmp #define strcasecmp strcmp
@ -62,17 +63,17 @@ char *U16ToHexStr(uint16 a);
std::string stditoa(int n); std::string stditoa(int n);
std::string readNullTerminatedAscii(std::istream* is); std::string readNullTerminatedAscii(EMUFILE* is);
//extracts a decimal uint from an istream //extracts a decimal uint from an istream
template<typename T> T templateIntegerDecFromIstream(std::istream* is) template<typename T> T templateIntegerDecFromIstream(EMUFILE* is)
{ {
unsigned int ret = 0; unsigned int ret = 0;
bool pre = true; bool pre = true;
for(;;) for(;;)
{ {
int c = is->get(); int c = is->fgetc();
if(c == -1) return ret; if(c == -1) return ret;
int d = c - '0'; int d = c - '0';
if((d<0 || d>9)) if((d<0 || d>9))
@ -91,11 +92,11 @@ template<typename T> T templateIntegerDecFromIstream(std::istream* is)
return ret; return ret;
} }
inline uint32 uint32DecFromIstream(std::istream* is) { return templateIntegerDecFromIstream<uint32>(is); } inline uint32 uint32DecFromIstream(EMUFILE* is) { return templateIntegerDecFromIstream<uint32>(is); }
inline uint64 uint64DecFromIstream(std::istream* is) { return templateIntegerDecFromIstream<uint64>(is); } inline uint64 uint64DecFromIstream(EMUFILE* is) { return templateIntegerDecFromIstream<uint64>(is); }
//puts an optionally 0-padded decimal integer of type T into the ostream (0-padding is quicker) //puts an optionally 0-padded decimal integer of type T into the ostream (0-padding is quicker)
template<typename T, int DIGITS, bool PAD> void putdec(std::ostream* os, T dec) template<typename T, int DIGITS, bool PAD> void putdec(EMUFILE* os, T dec)
{ {
char temp[DIGITS]; char temp[DIGITS];
int ctr = 0; int ctr = 0;
@ -111,18 +112,20 @@ template<typename T, int DIGITS, bool PAD> void putdec(std::ostream* os, T dec)
dec = quot; dec = quot;
} }
if(!PAD) if(!PAD)
os->write(temp+DIGITS-ctr-1,ctr+1); os->fwrite(temp+DIGITS-ctr-1,ctr+1);
else else
os->write(temp,DIGITS); os->fwrite(temp,DIGITS);
} }
std::string mass_replace(const std::string &source, const std::string &victim, const std::string &replacement); std::string mass_replace(const std::string &source, const std::string &victim, const std::string &replacement);
#ifndef GEKKO
std::wstring mbstowcs(std::string str); std::wstring mbstowcs(std::string str);
std::string wcstombs(std::wstring str); std::string wcstombs(std::wstring str);
#endif
//TODO - dont we already have another function that can do this //TODO - dont we already have another function that can do this
std::string getExtension(const char* input); std::string getExtension(const char* input);
std::string StripExtension(std::string filename);
std::string StripPath(std::string filename);

View File

@ -58,8 +58,8 @@
#define FCEU_COMPILER_DETAIL "" #define FCEU_COMPILER_DETAIL ""
#endif #endif
#define FCEU_VERSION_NUMERIC 21020 #define FCEU_VERSION_NUMERIC 21040
#define FCEU_VERSION_STRING "2.1.3" FCEU_SUBVERSION_STRING FCEU_FEATURE_STRING FCEU_COMPILER #define FCEU_VERSION_STRING "2.1.5" FCEU_SUBVERSION_STRING FCEU_FEATURE_STRING FCEU_COMPILER
#define FCEU_NAME_AND_VERSION FCEU_NAME " " FCEU_VERSION_STRING #define FCEU_NAME_AND_VERSION FCEU_NAME " " FCEU_VERSION_STRING
#endif #endif

View File

@ -50,6 +50,11 @@
#include "fceulua.h" #include "fceulua.h"
#endif #endif
#ifdef WIN32
#include "drivers/win/common.h" //For DirectX constants
#include "drivers/win/input.h"
#endif
#ifdef CREATE_AVI #ifdef CREATE_AVI
#include "drivers/videolog/nesvideos-piece.h" #include "drivers/videolog/nesvideos-piece.h"
#endif #endif
@ -66,10 +71,17 @@ GUIMESSAGE subtitleMessage;
extern int input_display; extern int input_display;
extern uint32 cur_input_display; extern uint32 cur_input_display;
bool oldInputDisplay = false;
#ifdef _USE_SHARED_MEMORY_ #ifdef _USE_SHARED_MEMORY_
HANDLE mapXBuf; HANDLE mapXBuf;
#endif #endif
std::string AsSnapshotName =""; //adelikat:this will set the snapshot name when for s savesnapshot as function
void FCEUI_SetSnapshotAsName(std::string name) { AsSnapshotName = name; }
std::string FCEUI_GetSnapshotAsName() { return AsSnapshotName; }
void FCEU_KillVirtualVideo(void) void FCEU_KillVirtualVideo(void)
{ {
//mbg merge TODO 7/17/06 temporarily removed //mbg merge TODO 7/17/06 temporarily removed
@ -175,15 +187,19 @@ void FCEUI_SaveSnapshot(void)
dosnapsave=1; dosnapsave=1;
} }
void FCEUI_SaveSnapshotAs(void)
{
dosnapsave=2;
}
static void ReallySnap(void) static void ReallySnap(void)
{ {
int x=SaveSnapshot(); int x=SaveSnapshot();
if(!x) if(!x)
FCEU_DispMessage("Error saving screen snapshot."); FCEU_DispMessage("Error saving screen snapshot.",0);
else else
FCEU_DispMessage("Screen snapshot %d saved.",x-1); FCEU_DispMessage("Screen snapshot %d saved.",0,x-1);
} }
void FCEU_PutImage(void) void FCEU_PutImage(void)
@ -191,13 +207,23 @@ void FCEU_PutImage(void)
#ifdef SHOWFPS #ifdef SHOWFPS
ShowFPS(); ShowFPS();
#endif #endif
if(dosnapsave==2) //Save screenshot as, currently only flagged & run by the Win32 build. //TODO SDL: implement this?
{
char nameo[512];
strcpy(nameo,FCEUI_GetSnapshotAsName().c_str());
if (nameo)
{
SaveSnapshot(nameo);
FCEU_DispMessage("Snapshot Saved.",0);
}
dosnapsave=0;
}
if(GameInfo->type==GIT_NSF) if(GameInfo->type==GIT_NSF)
{ {
DrawNSF(XBuf); DrawNSF(XBuf);
//Save snapshot after NSF screen is drawn. Why would we want to do it before? //Save snapshot after NSF screen is drawn. Why would we want to do it before?
if(dosnapsave) if(dosnapsave==1)
{ {
ReallySnap(); ReallySnap();
dosnapsave=0; dosnapsave=0;
@ -222,7 +248,7 @@ void FCEU_PutImage(void)
FCEUI_AviVideoUpdate(XBuf); FCEUI_AviVideoUpdate(XBuf);
//Save snapshot before overlay stuff is written. //Save snapshot before overlay stuff is written.
if(dosnapsave) if(dosnapsave==1)
{ {
ReallySnap(); ReallySnap();
dosnapsave=0; dosnapsave=0;
@ -245,8 +271,17 @@ void FCEU_PutImage(void)
//Fancy input display code //Fancy input display code
if(input_display) if(input_display)
{ {
int controller, c, color; extern uint32 JSAutoHeld;
uint32 held;
int controller, c, ci, color;
int i, j; int i, j;
uint32 on = FCEUMOV_Mode(MOVIEMODE_PLAY) ? 0x90:0xA7; //Standard, or Gray depending on movie mode
uint32 oni = 0xA0; //Color for immediate keyboard buttons
uint32 blend = 0xB6; //Blend of immiate and last held buttons
uint32 ahold = 0x87; //Auto hold
uint32 off = 0xCF;
uint8 *t = XBuf+(FSettings.LastSLine-9)*256 + 20; //mbg merge 7/17/06 changed t to uint8* uint8 *t = XBuf+(FSettings.LastSLine-9)*256 + 20; //mbg merge 7/17/06 changed t to uint8*
if(input_display > 4) input_display = 4; if(input_display > 4) input_display = 4;
for(controller = 0; controller < input_display; controller++, t += 56) for(controller = 0; controller < input_display; controller++, t += 56)
@ -258,9 +293,32 @@ void FCEU_PutImage(void)
for(j = 3; j< 6; j++) for(j = 3; j< 6; j++)
t[i+j*256] = 0xCF; t[i+j*256] = 0xCF;
c = cur_input_display >> (controller * 8); c = cur_input_display >> (controller * 8);
c &= 255;
// This doesn't work in anything except windows for now.
// It doesn't get set anywhere in other ports.
#ifdef WIN32
if (!oldInputDisplay) ci = FCEUMOV_Mode(MOVIEMODE_PLAY) ? 0:GetGamepadPressedImmediate() >> (controller * 8);
else ci = 0;
if (!oldInputDisplay && !FCEUMOV_Mode(MOVIEMODE_PLAY)) held = (JSAutoHeld >> (controller * 8));
else held = 0;
#else
// Put other port info here
ci = 0;
held = 0;
#endif
//adelikat: I apologize to anyone who ever sifts through this color assignment
//A //A
color = c&1?0xA7:0xCF; if (held&1) { //If auto-hold
if (!(ci&1) ) color = ahold;
else
color = (c&1) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed!
}
else {
if (c&1) color = (ci&1) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors
else color = (ci&1) ? oni : off;
}
for(i=0; i < 4; i++) for(i=0; i < 4; i++)
{ {
for(j = 0; j < 4; j++) for(j = 0; j < 4; j++)
@ -271,7 +329,15 @@ void FCEU_PutImage(void)
} }
} }
//B //B
color = c&2?0xA7:0xCF; if (held&2) { //If auto-hold
if (!(ci&2) ) color = ahold;
else
color = (c&2) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed!
}
else {
if (c&2) color = (ci&2) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors
else color = (ci&2) ? oni : off;
}
for(i=0; i < 4; i++) for(i=0; i < 4; i++)
{ {
for(j = 0; j < 4; j++) for(j = 0; j < 4; j++)
@ -282,21 +348,45 @@ void FCEU_PutImage(void)
} }
} }
//Select //Select
color = c&4?0xA7:0xCF; if (held&4) { //If auto-hold
if (!(ci&4) ) color = ahold;
else
color = (c&4) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed!
}
else {
if (c&4) color = (ci&4) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors
else color = (ci&4) ? oni : off;
}
for(i = 0; i < 4; i++) for(i = 0; i < 4; i++)
{ {
t[11+5*256+i] = color; t[11+5*256+i] = color;
t[11+6*256+i] = color; t[11+6*256+i] = color;
} }
//Start //Start
color = c&8?0xA7:0xCF; if (held&8) { //If auto-hold
if (!(ci&8) ) color = ahold;
else
color = (c&8) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed!
}
else {
if (c&8) color = (ci&8) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors
else color = (ci&8) ? oni : off;
}
for(i = 0; i < 4; i++) for(i = 0; i < 4; i++)
{ {
t[17+5*256+i] = color; t[17+5*256+i] = color;
t[17+6*256+i] = color; t[17+6*256+i] = color;
} }
//Up //Up
color = c&16?0xA7:0xCF; if (held&16) { //If auto-hold
if (!(ci&16) ) color = ahold;
else
color = (c&16) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed!
}
else {
if (c&16) color = (ci&16) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors
else color = (ci&16) ? oni : off;
}
for(i = 0; i < 3; i++) for(i = 0; i < 3; i++)
{ {
for(j = 0; j < 3; j++) for(j = 0; j < 3; j++)
@ -305,7 +395,15 @@ void FCEU_PutImage(void)
} }
} }
//Down //Down
color = c&32?0xA7:0xCF; if (held&32) { //If auto-hold
if (!(ci&32) ) color = ahold;
else
color = (c&32) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed!
}
else {
if (c&32) color = (ci&32) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors
else color = (ci&32) ? oni : off;
}
for(i = 0; i < 3; i++) for(i = 0; i < 3; i++)
{ {
for(j = 0; j < 3; j++) for(j = 0; j < 3; j++)
@ -314,7 +412,15 @@ void FCEU_PutImage(void)
} }
} }
//Left //Left
color = c&64?0xA7:0xCF; if (held&64) { //If auto-hold
if (!(ci&64) ) color = ahold;
else
color = (c&64) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed!
}
else {
if (c&64) color = (ci&64) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors
else color = (ci&64) ? oni : off;
}
for(i = 0; i < 3; i++) for(i = 0; i < 3; i++)
{ {
for(j = 0; j < 3; j++) for(j = 0; j < 3; j++)
@ -323,7 +429,15 @@ void FCEU_PutImage(void)
} }
} }
//Right //Right
color = c&128?0xA7:0xCF; if (held&128) { //If auto-hold
if (!(ci&128) ) color = ahold;
else
color = (c&128) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed!
}
else {
if (c&128) color = (ci&128) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors
else color = (ci&128) ? oni : off;
}
for(i = 0; i < 3; i++) for(i = 0; i < 3; i++)
{ {
for(j = 0; j < 3; j++) for(j = 0; j < 3; j++)
@ -345,21 +459,25 @@ void FCEU_DispMessageOnMovie(char *format, ...)
guiMessage.howlong = 180; guiMessage.howlong = 180;
guiMessage.isMovieMessage = true; guiMessage.isMovieMessage = true;
guiMessage.linesFromBottom = 0;
if (FCEUI_AviIsRecording() && FCEUI_AviDisableMovieMessages()) if (FCEUI_AviIsRecording() && FCEUI_AviDisableMovieMessages())
guiMessage.howlong = 0; guiMessage.howlong = 0;
} }
void FCEU_DispMessage(char *format, ...) void FCEU_DispMessage(char *format, int disppos=0, ...)
{ {
va_list ap; va_list ap;
va_start(ap,format); va_start(ap,disppos);
vsnprintf(guiMessage.errmsg,sizeof(guiMessage.errmsg),format,ap); vsnprintf(guiMessage.errmsg,sizeof(guiMessage.errmsg),format,ap);
va_end(ap); va_end(ap);
guiMessage.howlong = 180; guiMessage.howlong = 180;
guiMessage.isMovieMessage = false; guiMessage.isMovieMessage = false;
guiMessage.linesFromBottom = disppos;
//adelikat: Pretty sure this code fails, Movie playback stopped is done with FCEU_DispMessageOnMovie() //adelikat: Pretty sure this code fails, Movie playback stopped is done with FCEU_DispMessageOnMovie()
#ifdef CREATE_AVI #ifdef CREATE_AVI
if(LoggingEnabled == 2) if(LoggingEnabled == 2)
@ -377,6 +495,7 @@ void FCEU_ResetMessages()
{ {
guiMessage.howlong = 0; guiMessage.howlong = 0;
guiMessage.isMovieMessage = false; guiMessage.isMovieMessage = false;
guiMessage.linesFromBottom = 0;
} }
@ -414,6 +533,34 @@ static int WritePNGChunk(FILE *fp, uint32 size, char *type, uint8 *data)
return 1; return 1;
} }
uint32 GetScreenPixel(int x, int y, bool usebackup) {
uint8 r,g,b;
if (((x < 0) || (x > 255)) || ((y < 0) || (y > 255)))
return -1;
if (usebackup)
FCEUD_GetPalette(XBackBuf[(y*256)+x],&r,&g,&b);
else
FCEUD_GetPalette(XBuf[(y*256)+x],&r,&g,&b);
return ((int) (r) << 16) | ((int) (g) << 8) | (int) (b);
}
int GetScreenPixelPalette(int x, int y, bool usebackup) {
if (((x < 0) || (x > 255)) || ((y < 0) || (y > 255)))
return -1;
if (usebackup)
return XBackBuf[(y*256)+x] & 0x3f;
else
return XBuf[(y*256)+x] & 0x3f;
}
int SaveSnapshot(void) int SaveSnapshot(void)
{ {
unsigned int lastu=0; unsigned int lastu=0;
@ -440,6 +587,7 @@ int SaveSnapshot(void)
if(!(pp=FCEUD_UTF8fopen(fn,"wb"))) if(!(pp=FCEUD_UTF8fopen(fn,"wb")))
{ {
free(fn); free(fn);
free(compmem);
return 0; return 0;
} }
free(fn); free(fn);
@ -510,6 +658,101 @@ int SaveSnapshot(void)
return u+1; return u+1;
PNGerr:
if(compmem)
free(compmem);
if(pp)
fclose(pp);
return(0);
}
//overloaded SaveSnapshot for "Savesnapshot As" function
int SaveSnapshot(char fileName[512])
{
int totallines=FSettings.LastSLine-FSettings.FirstSLine+1;
int x,y;
FILE *pp=NULL;
uint8 *compmem=NULL;
uLongf compmemsize=totallines*263+12;
if(!(compmem=(uint8 *)FCEU_malloc(compmemsize)))
return 0;
pp = fopen(fileName, "w");
if(!(pp=FCEUD_UTF8fopen(fileName,"wb")))
{
free(compmem);
return 0;
}
{
static uint8 header[8]={137,80,78,71,13,10,26,10};
if(fwrite(header,8,1,pp)!=1)
goto PNGerr;
}
{
uint8 chunko[13];
chunko[0]=chunko[1]=chunko[3]=0;
chunko[2]=0x1; // Width of 256
chunko[4]=chunko[5]=chunko[6]=0;
chunko[7]=totallines; // Height
chunko[8]=8; // bit depth
chunko[9]=3; // Color type; indexed 8-bit
chunko[10]=0; // compression: deflate
chunko[11]=0; // Basic adapative filter set(though none are used).
chunko[12]=0; // No interlace.
if(!WritePNGChunk(pp,13,"IHDR",chunko))
goto PNGerr;
}
{
uint8 pdata[256*3];
for(x=0;x<256;x++)
FCEUD_GetPalette(x,pdata+x*3,pdata+x*3+1,pdata+x*3+2);
if(!WritePNGChunk(pp,256*3,"PLTE",pdata))
goto PNGerr;
}
{
uint8 *tmp=XBuf+FSettings.FirstSLine*256;
uint8 *dest,*mal,*mork;
if(!(mal=mork=dest=(uint8 *)malloc((totallines<<8)+totallines)))
goto PNGerr;
// mork=dest=XBuf;
for(y=0;y<totallines;y++)
{
*dest=0; // No filter.
dest++;
for(x=256;x;x--,tmp++,dest++)
*dest=*tmp;
}
if(compress(compmem,&compmemsize,mork,(totallines<<8)+totallines)!=Z_OK)
{
if(mal) free(mal);
goto PNGerr;
}
if(mal) free(mal);
if(!WritePNGChunk(pp,compmemsize,"IDAT",compmem))
goto PNGerr;
}
if(!WritePNGChunk(pp,0,"IEND",0))
goto PNGerr;
free(compmem);
fclose(pp);
return 0;
PNGerr: PNGerr:
if(compmem) if(compmem)
free(compmem); free(compmem);

View File

@ -1,6 +1,9 @@
int FCEU_InitVirtualVideo(void); int FCEU_InitVirtualVideo(void);
void FCEU_KillVirtualVideo(void); void FCEU_KillVirtualVideo(void);
int SaveSnapshot(void); int SaveSnapshot(void);
int SaveSnapshot(char[]);
uint32 GetScreenPixel(int x, int y, bool usebackup);
int GetScreenPixelPalette(int x, int y, bool usebackup);
extern uint8 *XBuf; extern uint8 *XBuf;
extern uint8 *XBackBuf; extern uint8 *XBackBuf;
extern int ClipSidesOffset; extern int ClipSidesOffset;
@ -15,8 +18,14 @@ extern struct GUIMESSAGE
//indicates that the movie should be drawn even on top of movies //indicates that the movie should be drawn even on top of movies
bool isMovieMessage; bool isMovieMessage;
//in case of multiple lines, allow one to move the message
int linesFromBottom;
} guiMessage; } guiMessage;
extern GUIMESSAGE subtitleMessage; extern GUIMESSAGE subtitleMessage;
void FCEU_DrawNumberRow(uint8 *XBuf, int *nstatus, int cur); void FCEU_DrawNumberRow(uint8 *XBuf, int *nstatus, int cur);
std::string FCEUI_GetSnapshotAsName();
void FCEUI_SetSnapshotAsName(std::string name);

View File

@ -428,7 +428,7 @@ extern int test; test++;
{ {
if(_IRQlow&FCEU_IQRESET) if(_IRQlow&FCEU_IQRESET)
{ {
if(debug_loggingCD) LogCDVectors(0); DEBUG( if(debug_loggingCD) LogCDVectors(0xFFFC); )
_PC=RdMem(0xFFFC); _PC=RdMem(0xFFFC);
_PC|=RdMem(0xFFFD)<<8; _PC|=RdMem(0xFFFD)<<8;
_jammed=0; _jammed=0;
@ -449,7 +449,7 @@ extern int test; test++;
PUSH(_PC); PUSH(_PC);
PUSH((_P&~B_FLAG)|(U_FLAG)); PUSH((_P&~B_FLAG)|(U_FLAG));
_P|=I_FLAG; _P|=I_FLAG;
DEBUG( if(debug_loggingCD) LogCDVectors(1) ); DEBUG( if(debug_loggingCD) LogCDVectors(0xFFFA) );
_PC=RdMem(0xFFFA); _PC=RdMem(0xFFFA);
_PC|=RdMem(0xFFFB)<<8; _PC|=RdMem(0xFFFB)<<8;
_IRQlow&=~FCEU_IQNMI; _IRQlow&=~FCEU_IQNMI;
@ -464,7 +464,7 @@ extern int test; test++;
PUSH(_PC); PUSH(_PC);
PUSH((_P&~B_FLAG)|(U_FLAG)); PUSH((_P&~B_FLAG)|(U_FLAG));
_P|=I_FLAG; _P|=I_FLAG;
DEBUG( if(debug_loggingCD) LogCDVectors(1) ); DEBUG( if(debug_loggingCD) LogCDVectors(0xFFFE) );
_PC=RdMem(0xFFFE); _PC=RdMem(0xFFFE);
_PC|=RdMem(0xFFFF)<<8; _PC|=RdMem(0xFFFF)<<8;
} }

View File

@ -47,10 +47,9 @@ bool SaveState (char * filepath, bool silent)
SaveFile((char *)gameScreenPng, screenpath, gameScreenPngSize, silent); SaveFile((char *)gameScreenPng, screenpath, gameScreenPngSize, silent);
} }
memorystream save(SAVEBUFFERSIZE); EMUFILE_MEMFILE save(SAVEBUFFERSIZE);
FCEUSS_SaveMS(&save, Z_BEST_COMPRESSION); FCEUSS_SaveMS(&save, Z_BEST_COMPRESSION);
save.sync(); datasize = save.size();
datasize = save.tellp();
if (datasize) if (datasize)
offset = SaveFile(save.buf(), filepath, datasize, silent); offset = SaveFile(save.buf(), filepath, datasize, silent);
@ -90,7 +89,7 @@ bool LoadState (char * filepath, bool silent)
if (offset > 0) if (offset > 0)
{ {
memorystream save((char *)savebuffer, offset); EMUFILE_MEMFILE save(savebuffer, offset);
FCEUSS_LoadFP(&save, SSLOADPARAM_NOBACKUP); FCEUSS_LoadFP(&save, SSLOADPARAM_NOBACKUP);
retval = true; retval = true;
} }

View File

@ -9,6 +9,7 @@
* FCEU Support Functions * FCEU Support Functions
****************************************************************************/ ****************************************************************************/
#include <gctypes.h>
#include "fceugx.h" #include "fceugx.h"
#include "fceusupport.h" #include "fceusupport.h"
#include "pad.h" #include "pad.h"
@ -16,6 +17,8 @@
#include "gcvideo.h" #include "gcvideo.h"
#include "menu.h" #include "menu.h"
bool turbo = false;
/** /**
* Closes a game. Frees memory, and deinitializes the drivers. * Closes a game. Frees memory, and deinitializes the drivers.
*/ */
@ -36,7 +39,7 @@ FILE *FCEUD_UTF8fopen(const char *n, const char *m)
return NULL; return NULL;
} }
std::fstream* FCEUD_UTF8_fstream(const char *fn, const char *m) EMUFILE_FILE* FCEUD_UTF8_fstream(const char *n, const char *m)
{ {
return NULL; return NULL;
} }

View File

@ -24,6 +24,7 @@
#include <di/di.h> #include <di/di.h>
#include <ogc/dvd.h> #include <ogc/dvd.h>
#include <iso9660.h> #include <iso9660.h>
#include <fat.h>
#include "fceugx.h" #include "fceugx.h"
#include "fceusupport.h" #include "fceusupport.h"

View File

@ -12,11 +12,8 @@
#ifndef _FILEOP_H_ #ifndef _FILEOP_H_
#define _FILEOP_H_ #define _FILEOP_H_
#include <gccore.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ogcsys.h>
#include <fat.h>
#include <unistd.h> #include <unistd.h>
#define SAVEBUFFERSIZE (1024 * 512) #define SAVEBUFFERSIZE (1024 * 512)

View File

@ -12,8 +12,6 @@
#ifndef _MENU_H #ifndef _MENU_H
#define _MENU_H #define _MENU_H
#include <ogcsys.h>
bool GuiLoaded(); bool GuiLoaded();
void InitGUIThreads(); void InitGUIThreads();
void MainMenu (int menuitem); void MainMenu (int menuitem);

View File

@ -19,6 +19,7 @@ ConnectShare (bool silent)
#else #else
#include <gccore.h>
#include <network.h> #include <network.h>
#include <malloc.h> #include <malloc.h>
#include <ogc/lwp_watchdog.h> #include <ogc/lwp_watchdog.h>

View File

@ -12,7 +12,7 @@
#ifndef _PAD_H_ #ifndef _PAD_H_
#define _PAD_H_ #define _PAD_H_
#include <gccore.h> #include <gctypes.h>
#include <wiiuse/wpad.h> #include <wiiuse/wpad.h>
#define PI 3.14159265f #define PI 3.14159265f

View File

@ -10,6 +10,7 @@
***************************************************************************/ ***************************************************************************/
#include <zlib.h> #include <zlib.h>
#include <gctypes.h>
#include "fceugx.h" #include "fceugx.h"
#include "fceusupport.h" #include "fceusupport.h"