mirror of
https://github.com/dborth/fceugx.git
synced 2024-10-31 22:45:05 +01:00
sync to latest FCEUX SVN
This commit is contained in:
parent
9dadc743d1
commit
647bf81a74
@ -10,6 +10,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include <malloc.h>
|
||||
#include <gctypes.h>
|
||||
|
||||
#include "fceugx.h"
|
||||
#include "fceusupport.h"
|
||||
|
@ -310,7 +310,7 @@ void USBGeckoOutput()
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
//USBGeckoOutput(); // uncomment to enable USB gecko output
|
||||
USBGeckoOutput(); // uncomment to enable USB gecko output
|
||||
__exception_setreload(8);
|
||||
|
||||
#ifdef HW_DOL
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <gctypes.h>
|
||||
|
||||
#include "fceultra/file.h"
|
||||
|
||||
@ -64,7 +65,7 @@ int GCMemROM(int size)
|
||||
fceufp->size = size;
|
||||
fceufp->filename = romFilename;
|
||||
fceufp->mode = FCEUFILE::READ; // read only
|
||||
memorystream * fceumem = new memorystream((char *) nesrom, size);
|
||||
EMUFILE_MEMFILE *fceumem = new EMUFILE_MEMFILE(nesrom, size);
|
||||
fceufp->stream = fceumem;
|
||||
|
||||
romLoaded = iNESLoad(romFilename, fceufp, 1);
|
||||
|
@ -139,7 +139,7 @@ static uint64 lreset;
|
||||
static DECLFW(MMC1_write)
|
||||
{
|
||||
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);
|
||||
//DumpMem("out",0xe000,0xffff);
|
||||
|
||||
|
@ -467,4 +467,5 @@ void Mapper210_Init(CartInfo *info)
|
||||
GameStateRestore=Mapper210_StateRestore;
|
||||
info->Power=N106_Power;
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(N106_StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ void RebuildSubCheats(void)
|
||||
if(GetReadHandler(c->addr)==SubCheatsRead)
|
||||
{
|
||||
/* Prevent a catastrophe by this check. */
|
||||
//FCEU_DispMessage("oops");
|
||||
//FCEU_DispMessage("oops",0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -148,7 +148,7 @@ void RebuildSubCheats(void)
|
||||
}
|
||||
FrozenAddressCount = numsubcheats; //Update the frozen address list
|
||||
UpdateFrozenList();
|
||||
//FCEUI_DispMessage("Active Cheats: %d", FrozenAddresses.size()/*FrozenAddressCount*/); //Debug
|
||||
//FCEUI_DispMessage("Active Cheats: %d",0, FrozenAddresses.size()/*FrozenAddressCount*/); //Debug
|
||||
}
|
||||
|
||||
void FCEU_PowerCheats()
|
||||
@ -217,8 +217,8 @@ void FCEU_LoadGameCheats(FILE *override)
|
||||
if(!fp) return;
|
||||
}
|
||||
|
||||
FCEU_DispMessage("Cheats file loaded."); //Tells user a cheats file was loaded.
|
||||
FCEU_printf("Cheats file loaded.\n"); //Sends message to message log.
|
||||
FCEU_DispMessage("Cheats file loaded.",0); //Tells user a cheats file was loaded.
|
||||
FCEU_printf("Cheats file loaded.\n",0); //Sends message to message log.
|
||||
while(fgets(linebuf,2048,fp)>0)
|
||||
{
|
||||
char *tbuf=linebuf;
|
||||
@ -380,7 +380,7 @@ int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int ty
|
||||
}
|
||||
savecheats=1;
|
||||
RebuildSubCheats();
|
||||
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -943,7 +943,7 @@ void UpdateFrozenList(void)
|
||||
//The purpose of this function is to keep an up to date list of addresses that are currently frozen
|
||||
//and make these accessible to other dialogs that deal with memory addresses such as
|
||||
//memwatch, hex editor, ramfilter, etc.
|
||||
|
||||
|
||||
int x;
|
||||
FrozenAddresses.clear(); //Clear vector and repopulate
|
||||
for(x=0;x<numsubcheats;x++)
|
||||
@ -951,5 +951,5 @@ void UpdateFrozenList(void)
|
||||
FrozenAddresses.push_back(SubCheats[x].addr);
|
||||
//FCEU_printf("Address %d: %d \n",x,FrozenAddresses[x]); //Debug
|
||||
}
|
||||
//FCEUI_DispMessage("FrozenCount: %d",FrozenAddressCount);//Debug
|
||||
}
|
||||
//FCEUI_DispMessage("FrozenCount: %d",0,FrozenAddressCount);//Debug
|
||||
}
|
@ -36,6 +36,7 @@
|
||||
* Address -> '$' [1-9A-F]* | '$' '[' Connect ']'
|
||||
* Register -> 'A' | 'X' | 'Y' | 'R'
|
||||
* Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V'
|
||||
* PC Bank -> 'K'
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -131,6 +132,12 @@ int isRegister(char c)
|
||||
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
|
||||
int getNumber(unsigned int* number, const char** str)
|
||||
{
|
||||
@ -217,6 +224,23 @@ Condition* Primitive(const char** str, Condition* 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 */
|
||||
{
|
||||
unsigned int number = 0;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define TYPE_FLAG 2
|
||||
#define TYPE_NUM 3
|
||||
#define TYPE_ADDR 4
|
||||
#define TYPE_BANK 5
|
||||
|
||||
#define OP_NO 0
|
||||
#define OP_EQ 1
|
||||
|
@ -195,13 +195,36 @@ unsigned int NewBreak(const char* name, int start, int end, unsigned int type, c
|
||||
}
|
||||
|
||||
int GetPRGAddress(int A){
|
||||
unsigned int result;
|
||||
int result;
|
||||
if((A < 0x8000) || (A > 0xFFFF))return -1;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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){
|
||||
unsigned int result;
|
||||
if((A < 0x8000) || (A > 0xFFFF))return -1;
|
||||
@ -272,15 +295,16 @@ int evaluate(Condition* c)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
@ -295,16 +319,17 @@ int evaluate(Condition* c)
|
||||
{
|
||||
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;
|
||||
default: value2 = getValue(c->type2);
|
||||
default: value2 = getValue(c->type2); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->type2 == TYPE_ADDR)
|
||||
{
|
||||
value2 = GetMem(value2);
|
||||
}
|
||||
switch(c->type2)
|
||||
{
|
||||
case TYPE_ADDR: value2 = GetMem(value2); break;
|
||||
case TYPE_BANK: value2 = getBank(_PC); break;
|
||||
}
|
||||
|
||||
switch (c->op)
|
||||
{
|
||||
@ -335,93 +360,94 @@ int condition(watchpointinfo* wp)
|
||||
//---------------------
|
||||
|
||||
volatile int codecount, datacount, undefinedcount;
|
||||
//HWND hCDLogger=0;
|
||||
unsigned char *cdloggerdata;
|
||||
char *cdlogfilename;
|
||||
//char loadedcdfile[MAX_PATH];
|
||||
static int indirectnext;
|
||||
|
||||
int debug_loggingCD;
|
||||
|
||||
//called by the cpu to perform logging if CDLogging is enabled
|
||||
void LogCDVectors(int which){
|
||||
int i = 0xFFFA+(which*2);
|
||||
int j;
|
||||
j = GetPRGAddress(i);
|
||||
j = GetPRGAddress(which);
|
||||
if(j == -1){
|
||||
return;
|
||||
}
|
||||
|
||||
if(cdloggerdata[j] == 0){
|
||||
cdloggerdata[j] |= 0x0E; // we're in the last bank and recording it as data so 0x1110 or 0xE should be what we need
|
||||
datacount++;
|
||||
undefinedcount--;
|
||||
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
|
||||
datacount++;
|
||||
if(!(cdloggerdata[j] & 1))undefinedcount--;
|
||||
}
|
||||
j++;
|
||||
|
||||
if(cdloggerdata[j] == 0){
|
||||
cdloggerdata[j] |= 0x0E; // we're in the last bank and recording it as data so 0x1110 or 0xE should be what we need
|
||||
datacount++;
|
||||
undefinedcount--;
|
||||
if(!(cdloggerdata[j] & 2)){
|
||||
cdloggerdata[j] |= 0x0E;
|
||||
datacount++;
|
||||
if(!(cdloggerdata[j] & 1))undefinedcount--;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void LogCDData(){
|
||||
int i, j;
|
||||
uint16 A=0;
|
||||
uint8 opcode[3] = {0};
|
||||
uint16 A = 0;
|
||||
uint8 opcode[3] = {0}, memop = 0;
|
||||
|
||||
j = GetPRGAddress(_PC);
|
||||
|
||||
opcode[0] = GetMem(_PC);
|
||||
for (i = 1; i < opsize[opcode[0]]; i++) opcode[i] = GetMem(_PC+i);
|
||||
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;
|
||||
}
|
||||
|
||||
if(j != -1){
|
||||
for (i = 0; i < opsize[opcode[0]]; i++){
|
||||
if(cdloggerdata[j+i] & 1)continue; //this has been logged so skip
|
||||
cdloggerdata[j+i] |= 1;
|
||||
cdloggerdata[j+i] |=((_PC+i)>>11)&12;
|
||||
cdloggerdata[j+i] |=((_PC+i)>>11)&0x0c;
|
||||
if(indirectnext)cdloggerdata[j+i] |= 0x10;
|
||||
codecount++;
|
||||
if(!(cdloggerdata[j+i] & 0x42))undefinedcount--;
|
||||
if(!(cdloggerdata[j+i] & 2))undefinedcount--;
|
||||
}
|
||||
|
||||
//log instruction jumped to in an indirect jump
|
||||
if(opcode[0] == 0x6c) indirectnext = 1; else indirectnext = 0;
|
||||
|
||||
switch (optype[opcode[0]]) {
|
||||
case 0: break;
|
||||
case 1:
|
||||
A = (opcode[1]+_X) & 0xFF;
|
||||
A = GetMem(A) | (GetMem(A+1)<<8);
|
||||
memop = 0x20;
|
||||
break;
|
||||
case 2: A = opcode[1]; break;
|
||||
case 3: A = opcode[1] | opcode[2]<<8; break;
|
||||
case 4:
|
||||
A = (GetMem(opcode[1]) | (GetMem(opcode[1]+1)<<8))+_Y;
|
||||
memop = 0x20;
|
||||
break;
|
||||
case 5: A = opcode[1]+_X; break;
|
||||
case 6: A = (opcode[1] | (opcode[2]<<8))+_Y; break;
|
||||
case 7: A = (opcode[1] | (opcode[2]<<8))+_X; break;
|
||||
case 8: A = opcode[1]+_Y; break;
|
||||
}
|
||||
|
||||
if((j = GetPRGAddress(A)) != -1) {
|
||||
if(!(cdloggerdata[j] & 2)) {
|
||||
cdloggerdata[j] |= 2;
|
||||
cdloggerdata[j] |=(A>>11)&0x0c;
|
||||
cdloggerdata[j] |= memop;
|
||||
datacount++;
|
||||
if(!(cdloggerdata[j] & 1))undefinedcount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
indirectnext = 0;
|
||||
//log instruction jumped to in an indirect jump
|
||||
if(opcode[0] == 0x6c){
|
||||
indirectnext = 1;
|
||||
}
|
||||
|
||||
switch (optype[opcode[0]]) {
|
||||
case 0: break;
|
||||
case 1:
|
||||
A = (opcode[1]+_X) & 0xFF;
|
||||
A = GetMem(A) | (GetMem(A+1))<<8;
|
||||
break;
|
||||
case 2: A = opcode[1]; break;
|
||||
case 3: A = opcode[1] | opcode[2]<<8; break;
|
||||
case 4: A = (GetMem(opcode[1]) | (GetMem(opcode[1]+1))<<8)+_Y; break;
|
||||
case 5: A = opcode[1]+_X; break;
|
||||
case 6: A = (opcode[1] | opcode[2]<<8)+_Y; break;
|
||||
case 7: A = (opcode[1] | opcode[2]<<8)+_X; break;
|
||||
case 8: A = opcode[1]+_Y; break;
|
||||
}
|
||||
|
||||
//if(opbrktype[opcode[0]] != WP_R)return; //we only want reads
|
||||
|
||||
if((j = GetPRGAddress(A)) == -1)return;
|
||||
//if(j == 0)BreakHit();
|
||||
|
||||
|
||||
if(cdloggerdata[j] & 2)return;
|
||||
cdloggerdata[j] |= 2;
|
||||
cdloggerdata[j] |=((A/*+i*/)>>11)&12;
|
||||
if((optype[opcode[0]] == 1) || (optype[opcode[0]] == 4))cdloggerdata[j] |= 0x20;
|
||||
datacount++;
|
||||
if(!(cdloggerdata[j+i] & 1))undefinedcount--;
|
||||
return;
|
||||
}
|
||||
|
||||
//-----------debugger stuff
|
||||
@ -444,7 +470,7 @@ void BreakHit(bool force = false) {
|
||||
//check to see whether we fall in any forbid zone
|
||||
for (int i = 0; i < numWPs; i++) {
|
||||
watchpointinfo& wp = watchpoint[i];
|
||||
if(!(wp.flags & WP_F))
|
||||
if(!(wp.flags & WP_F) || !(wp.flags & WP_E))
|
||||
continue;
|
||||
|
||||
if (condition(&wp))
|
||||
@ -467,51 +493,21 @@ void BreakHit(bool force = false) {
|
||||
|
||||
FCEUD_DebugBreakpoint();
|
||||
}
|
||||
/*
|
||||
//very ineffecient, but this shouldn't get executed THAT much
|
||||
if(!(cdloggerdata[GetPRGAddress(0xFFFA)] & 2)){
|
||||
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;
|
||||
}
|
||||
*/
|
||||
|
||||
uint8 StackAddrBackup = X.S;
|
||||
uint16 StackNextIgnorePC = 0xFFFF;
|
||||
|
||||
///fires a breakpoint
|
||||
void breakpoint() {
|
||||
int i;
|
||||
int i,j;
|
||||
uint16 A=0;
|
||||
uint8 brk_type,opcode[3] = {0};
|
||||
uint8 stackop=0;
|
||||
uint8 stackopstartaddr,stackopendaddr;
|
||||
|
||||
//inspect the current opcode
|
||||
opcode[0] = GetMem(_PC);
|
||||
|
||||
|
||||
//if the current instruction is bad, and we are breaking on bad opcodes, then hit the breakpoint
|
||||
if(dbgstate.badopbreak && (opsize[opcode[0]] == 0)) BreakHit(true);
|
||||
|
||||
@ -572,6 +568,21 @@ void breakpoint() {
|
||||
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++) {
|
||||
// ################################## Start of SP CODE ###########################
|
||||
if (condition(&watchpoint[i]))
|
||||
@ -597,17 +608,67 @@ void breakpoint() {
|
||||
else { //CPU mem breaks
|
||||
if ((watchpoint[i].flags & WP_E) && (watchpoint[i].flags & brk_type)) {
|
||||
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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
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 ###########################
|
||||
}
|
||||
// ################################## 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
|
||||
|
||||
@ -617,8 +678,8 @@ void DebugCycle() {
|
||||
|
||||
if (scanline == 240)
|
||||
{
|
||||
vblankScanLines = (timestamp / 114); //114 approximates the number of timestamps per scanline during vblank. Approx 2508
|
||||
if (vblankScanLines) vblankPixel = 341 / vblankScanLines; //314 pixels per scanline
|
||||
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; //341 pixels per scanline
|
||||
//FCEUI_printf("vbPixel = %d",vblankPixel); //Debug
|
||||
//FCEUI_printf("ts: %d line: %d\n", timestamp, vblankScanLines); //Debug
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ typedef struct {
|
||||
//mbg merge 7/18/06 had to make this extern
|
||||
extern watchpointinfo watchpoint[65]; //64 watchpoints, + 1 reserved for step over
|
||||
|
||||
int getBank(int offs);
|
||||
int GetNesFileAddress(int A);
|
||||
int GetPRGAddress(int A);
|
||||
int GetRomAddress(int A);
|
||||
|
@ -135,7 +135,11 @@ void DrawMessage(bool beforeMovie)
|
||||
|
||||
uint8 *t;
|
||||
guiMessage.howlong--;
|
||||
t=XBuf+FCEU_TextScanlineOffsetFromBottom(20)+1;
|
||||
|
||||
if (guiMessage.linesFromBottom > 0)
|
||||
t=XBuf+FCEU_TextScanlineOffsetFromBottom(guiMessage.linesFromBottom)+1;
|
||||
else
|
||||
t=XBuf+FCEU_TextScanlineOffsetFromBottom(20)+1;
|
||||
|
||||
/*
|
||||
FCEU palette:
|
||||
@ -336,7 +340,7 @@ void FCEU_DrawRecordingStatus(uint8* XBuf)
|
||||
drawstatus(XBuf-ClipSidesOffset,2,28,0);
|
||||
hasPlayRecIcon = true;
|
||||
}
|
||||
else if(FCEUMOV_Mode(MOVIEMODE_PLAY))
|
||||
else if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_FINISHED))
|
||||
{
|
||||
drawstatus(XBuf-ClipSidesOffset,1,28,0);
|
||||
hasPlayRecIcon = true;
|
||||
|
@ -11,8 +11,8 @@
|
||||
|
||||
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); }
|
||||
std::fstream* 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); }
|
||||
EMUFILE_FILE* FCEUD_UTF8_fstream(const char *n, const char *m);
|
||||
inline EMUFILE_FILE* FCEUD_UTF8_fstream(const std::string &n, const char *m) { return FCEUD_UTF8_fstream(n.c_str(),m); }
|
||||
FCEUFILE* FCEUD_OpenArchiveIndex(ArchiveScanRecord& asr, std::string& fname, int innerIndex);
|
||||
FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename);
|
||||
ArchiveScanRecord FCEUD_ScanArchive(std::string fname);
|
||||
@ -77,6 +77,8 @@ void FCEUI_SetInputFC(ESIFC type, void *ptr, int attrib);
|
||||
void FCEUI_SetInputFourscore(bool attachFourscore);
|
||||
//tells whether a fourscore is attached
|
||||
bool FCEUI_GetInputFourscore();
|
||||
//tells whether the microphone is used
|
||||
bool FCEUI_GetInputMicrophone();
|
||||
|
||||
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
|
||||
//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);
|
||||
@ -176,7 +178,8 @@ void FCEUD_LuaRunFrom(void);
|
||||
|
||||
int32 FCEUI_GetDesiredFPS(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
|
||||
|
||||
int FCEUI_DecodePAR(const char *code, int *a, int *v, int *c, int *type);
|
||||
|
28
source/fceultra/emufile.cpp
Normal file
28
source/fceultra/emufile.cpp
Normal 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
428
source/fceultra/emufile.h
Normal 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
|
@ -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 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 DebuggerWasUpdated = false; //To prevent the debugger from updating things without being updated.
|
||||
|
||||
FCEUGI::FCEUGI()
|
||||
: filename(0)
|
||||
@ -99,20 +100,53 @@ FCEUGI::~FCEUGI()
|
||||
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)
|
||||
{
|
||||
if(GameInfo)
|
||||
{
|
||||
|
||||
#ifdef WIN32
|
||||
// ################################## Start of SP CODE ###########################
|
||||
//SP CODE
|
||||
extern char LoadedRomFName[2048];
|
||||
|
||||
if (storePreferences(LoadedRomFName))
|
||||
{
|
||||
FCEUD_PrintError("Couldn't store debugging data");
|
||||
}
|
||||
// ################################## End of SP CODE ###########################
|
||||
#endif
|
||||
|
||||
if(FCEUnetplay)
|
||||
@ -128,11 +162,7 @@ static void FCEU_CloseGame(void)
|
||||
|
||||
if(GameInfo->type!=GIT_NSF)
|
||||
{
|
||||
#ifdef GEKKO
|
||||
FCEU_FlushGameCheats(0,1); // don't save cheats
|
||||
#else
|
||||
FCEU_FlushGameCheats(0,0);
|
||||
#endif
|
||||
}
|
||||
|
||||
GameInterface(GI_CLOSE);
|
||||
@ -141,8 +171,7 @@ static void FCEU_CloseGame(void)
|
||||
|
||||
ResetExState(0,0);
|
||||
|
||||
//mbg 5/9/08 - clear screen when game is closed
|
||||
//http://sourceforge.net/tracker/index.php?func=detail&aid=1787298&group_id=13536&atid=113536
|
||||
//clear screen when game is closed
|
||||
extern uint8 *XBuf;
|
||||
if(XBuf)
|
||||
memset(XBuf,0,256*256);
|
||||
@ -151,11 +180,10 @@ static void FCEU_CloseGame(void)
|
||||
|
||||
delete GameInfo;
|
||||
GameInfo = 0;
|
||||
|
||||
//Reset frame counter
|
||||
|
||||
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;
|
||||
undoSS = false;
|
||||
redoSS = false;
|
||||
@ -318,7 +346,8 @@ static void AllocBuffers()
|
||||
#endif
|
||||
}
|
||||
|
||||
static void FreeBuffers() {
|
||||
static void FreeBuffers()
|
||||
{
|
||||
#ifdef _USE_SHARED_MEMORY_
|
||||
void win_FreeBuffers(uint8 *GameMemBlock, uint8 *RAM);
|
||||
win_FreeBuffers(GameMemBlock, RAM);
|
||||
@ -493,7 +522,7 @@ endlseq:
|
||||
FCEU_LoadGameCheats(0);
|
||||
|
||||
#if defined (WIN32) || defined (WIN64)
|
||||
DoDebuggerRunCheck(); //Can't safely do it in loadPreferences
|
||||
DoDebuggerDataReload(); // Reloads data without reopening window
|
||||
#endif
|
||||
|
||||
return GameInfo;
|
||||
@ -590,12 +619,13 @@ void SetAutoFireOffset(int offset)
|
||||
void AutoFire(void)
|
||||
{
|
||||
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
|
||||
//doesn't get screwed up when loading.
|
||||
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
|
||||
{
|
||||
@ -661,12 +691,15 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
|
||||
|
||||
#ifdef WIN32
|
||||
//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();
|
||||
Update_RAM_Search(); // Update_RAM_Watch() is also called.
|
||||
RamChange();
|
||||
UpdateLogWindow();
|
||||
//FCEUI_AviVideoUpdate(XBuf);
|
||||
extern int KillFCEUXonFrame;
|
||||
if (KillFCEUXonFrame && (FCEUMOV_GetFrame() >= KillFCEUXonFrame))
|
||||
DoFCEUExit();
|
||||
#endif
|
||||
|
||||
timestampbase += timestamp;
|
||||
@ -928,6 +961,7 @@ void FCEUI_SetEmulationPaused(int val)
|
||||
void FCEUI_ToggleEmulationPause(void)
|
||||
{
|
||||
EmulationPaused = (EmulationPaused&1)^1;
|
||||
DebuggerWasUpdated = false;
|
||||
}
|
||||
|
||||
void FCEUI_FrameAdvanceEnd(void)
|
||||
@ -945,7 +979,7 @@ static int AutosaveCounter = 0;
|
||||
|
||||
void UpdateAutosave(void)
|
||||
{
|
||||
if(!EnableAutosave)
|
||||
if(!EnableAutosave || turbo)
|
||||
return;
|
||||
|
||||
char * f;
|
||||
@ -963,7 +997,7 @@ void UpdateAutosave(void)
|
||||
|
||||
void FCEUI_Autosave(void)
|
||||
{
|
||||
if(!EnableAutosave || !AutoSS)
|
||||
if(!EnableAutosave || !AutoSS || FCEUMOV_Mode(MOVIEMODE_TASEDIT))
|
||||
return;
|
||||
|
||||
if(AutosaveStatus[AutosaveIndex] == 1)
|
||||
@ -1016,7 +1050,7 @@ bool FCEU_IsValidUI(EFCEUI ui)
|
||||
|
||||
case FCEUI_STOPMOVIE:
|
||||
case FCEUI_PLAYFROMBEGINNING:
|
||||
return FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD);
|
||||
return (FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED));
|
||||
|
||||
case FCEUI_STOPAVI:
|
||||
return FCEUI_AviIsRecording();
|
||||
@ -1027,7 +1061,7 @@ bool FCEU_IsValidUI(EFCEUI ui)
|
||||
|
||||
case FCEUI_RESET:
|
||||
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;
|
||||
|
||||
case FCEUI_POWER:
|
||||
|
@ -108,10 +108,13 @@ int FCEU_TextScanlineOffsetFromBottom(int y);
|
||||
|
||||
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_printf(char *format, ...);
|
||||
void FCEU_DispMessage(char *format, ...);
|
||||
void FCEU_DispMessage(char *format, int disppos, ...);
|
||||
void FCEU_DispMessageOnMovie(char *format, ...);
|
||||
void FCEU_TogglePPU();
|
||||
|
||||
void SetNESDeemph(uint8 d, int force);
|
||||
void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor);
|
||||
|
@ -161,17 +161,17 @@ void FCEU_FDSInsert(void)
|
||||
|
||||
if(TotalSides==0)
|
||||
{
|
||||
FCEU_DispMessage("Not FDS; can't eject disk.");
|
||||
FCEU_DispMessage("Not FDS; can't eject disk.",0);
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -190,16 +190,16 @@ void FCEU_FDSSelect(void)
|
||||
|
||||
if(TotalSides==0)
|
||||
{
|
||||
FCEU_DispMessage("Not FDS; can't select disk.");
|
||||
FCEU_DispMessage("Not FDS; can't select disk.",0);
|
||||
return;
|
||||
}
|
||||
if(InDisk!=255)
|
||||
{
|
||||
FCEU_DispMessage("Eject disk before selecting.");
|
||||
FCEU_DispMessage("Eject disk before selecting.",0);
|
||||
return;
|
||||
}
|
||||
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)
|
||||
@ -797,6 +797,15 @@ int FDSLoad(const char *name, FCEUFILE *fp)
|
||||
|
||||
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)
|
||||
{
|
||||
fclose(zp);
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include "movie.h"
|
||||
#include "driver.h"
|
||||
#include "utils/xstring.h"
|
||||
#include "utils/memorystream.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -143,8 +142,7 @@ void ApplyIPS(FILE *ips, FCEUFILE* fp)
|
||||
FCEU_printf(" Hard IPS end!\n");
|
||||
end:
|
||||
fclose(ips);
|
||||
memorystream* ms = new memorystream(buf,fp->size);
|
||||
ms->giveBuf();
|
||||
EMUFILE_MEMORY* ms = new EMUFILE_MEMORY(buf,fp->size);
|
||||
fp->SetStream(ms);
|
||||
}
|
||||
|
||||
@ -224,7 +222,9 @@ static FCEUFILE * TryUnzip(const std::string& path) {
|
||||
if(unzGoToNextFile(tz)!=UNZ_OK)
|
||||
{
|
||||
if(unzGoToFirstFile(tz)!=UNZ_OK) goto zpfail;
|
||||
break;
|
||||
unzCloseCurrentFile(tz);
|
||||
unzClose(tz);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(unzOpenCurrentFile(tz)!=UNZ_OK)
|
||||
@ -241,7 +241,7 @@ zpfail:
|
||||
unzGetCurrentFileInfo(tz,&ufo,0,0,0,0,0,0);
|
||||
|
||||
int size = ufo.uncompressed_size;
|
||||
memorystream* ms = new memorystream(size);
|
||||
EMUFILE_MEMORY* ms = new EMUFILE_MEMORY(size);
|
||||
unzReadCurrentFile(tz,ms->buf(),ufo.uncompressed_size);
|
||||
unzCloseCurrentFile(tz);
|
||||
unzClose(tz);
|
||||
@ -283,7 +283,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
|
||||
if(!asr.isArchive())
|
||||
{
|
||||
//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)
|
||||
{
|
||||
return 0;
|
||||
@ -306,10 +306,10 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
|
||||
{
|
||||
uint32 magic;
|
||||
|
||||
magic = fp->get();
|
||||
magic|=fp->get()<<8;
|
||||
magic|=fp->get()<<16;
|
||||
fp->seekg(0,std::ios::beg);
|
||||
magic = fp->fgetc();
|
||||
magic|=fp->fgetc()<<8;
|
||||
magic|=fp->fgetc()<<16;
|
||||
fp->fseek(0,SEEK_SET);
|
||||
|
||||
if(magic==0x088b1f) {
|
||||
// maybe gzip...
|
||||
@ -320,7 +320,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
|
||||
|
||||
int 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);
|
||||
gzread(gzfile,ms->buf(),size);
|
||||
gzclose(gzfile);
|
||||
@ -344,7 +344,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
|
||||
fceufp->logicalPath = fileToOpen;
|
||||
fceufp->fullFilename = fileToOpen;
|
||||
fceufp->archiveIndex = -1;
|
||||
fceufp->stream = (std::iostream*)fp;
|
||||
fceufp->stream = fp;
|
||||
FCEU_fseek(fceufp,0,SEEK_END);
|
||||
fceufp->size = FCEU_ftell(fceufp);
|
||||
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)
|
||||
{
|
||||
fp->stream->read((char*)ptr,size*nmemb);
|
||||
uint32 read = fp->stream->gcount();
|
||||
return read/size;
|
||||
return fp->stream->fread((char*)ptr,size*nmemb);
|
||||
}
|
||||
|
||||
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?
|
||||
return nmemb;
|
||||
}
|
||||
|
||||
int FCEU_fseek(FCEUFILE *fp, long offset, int whence)
|
||||
{
|
||||
//if(fp->type==1)
|
||||
//{
|
||||
// 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);
|
||||
fp->stream->fseek(offset,whence);
|
||||
|
||||
return FCEU_ftell(fp);
|
||||
}
|
||||
|
||||
uint64 FCEU_ftell(FCEUFILE *fp)
|
||||
{
|
||||
if(fp->mode == FCEUFILE::READ)
|
||||
return fp->stream->tellg();
|
||||
else
|
||||
return fp->stream->tellp();
|
||||
return fp->stream->ftell();
|
||||
}
|
||||
|
||||
int FCEU_read16le(uint16 *val, FCEUFILE *fp)
|
||||
@ -452,7 +420,7 @@ int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp)
|
||||
|
||||
int FCEU_fgetc(FCEUFILE *fp)
|
||||
{
|
||||
return fp->stream->get();
|
||||
return fp->stream->fgetc();
|
||||
}
|
||||
|
||||
uint64 FCEU_fgetsize(FCEUFILE *fp)
|
||||
|
@ -4,13 +4,14 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "types.h"
|
||||
#include "utils/memorystream.h"
|
||||
#include "emufile.h"
|
||||
|
||||
extern bool bindSavestate;
|
||||
|
||||
struct FCEUFILE {
|
||||
//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
|
||||
std::string filename;
|
||||
@ -51,25 +52,25 @@ struct FCEUFILE {
|
||||
} mode;
|
||||
|
||||
//guarantees that the file contains a memorystream, and returns it for your convenience
|
||||
memorystream* EnsureMemorystream() {
|
||||
memorystream* ret = dynamic_cast<memorystream*>(stream);
|
||||
EMUFILE_MEMORY* EnsureMemorystream() {
|
||||
|
||||
EMUFILE_MEMORY* ret = dynamic_cast<EMUFILE_MEMORY*>(stream);
|
||||
if(ret) return ret;
|
||||
|
||||
//nope, we need to create it: copy the contents
|
||||
ret = new memorystream(size);
|
||||
stream->read(ret->buf(),size);
|
||||
ret = new EMUFILE_MEMORY(size);
|
||||
stream->fread(ret->buf(),size);
|
||||
delete stream;
|
||||
stream = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SetStream(std::iostream *newstream) {
|
||||
void SetStream(EMUFILE *newstream) {
|
||||
if(stream) delete stream;
|
||||
stream = newstream;
|
||||
//get the size of the stream
|
||||
stream->seekg(0,std::ios::end);
|
||||
size = stream->tellg();
|
||||
stream->seekg(0,std::ios::beg);
|
||||
stream->fseek(0,SEEK_SET);
|
||||
size = stream->size();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -56,7 +56,7 @@ void SexyFilter(int32 *in, int32 *out, int32 count)
|
||||
mul2=(24<<16)/FSettings.SndRate;
|
||||
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;
|
||||
else vmul*=2; /* TODO: Increase volume in low quality sound rendering code itself */
|
||||
|
||||
|
@ -23,8 +23,8 @@
|
||||
{0xdd8ced31,209,-1}, /* Power Rangers 3 */
|
||||
|
||||
{0x0c47946d,210,1}, /* Chibi Maruko Chan */
|
||||
{0xbd523011,210,0}, /* Dream Master */
|
||||
{0xc247cc80,210,1}, /* Family Circuit '91 */
|
||||
{0xbd523011,210,2}, /* Dream Master */ // may be wrong, but seems it solve most problems
|
||||
{0xc247cc80,210,1}, /* Family Circuit '91 */
|
||||
{0x6ec51de5,210,1}, /* Famista '92 */
|
||||
{0xadffd64f,210,1}, /* Famista '93 */
|
||||
{0x429103c9,210,1}, /* Famista '94 */
|
||||
|
@ -50,13 +50,13 @@ extern SFORMAT FCEUVSUNI_STATEINFO[];
|
||||
|
||||
//mbg merge 6/29/06 - these need to be global
|
||||
uint8 *trainerpoo=0;
|
||||
uint8 *ROM=NULL;
|
||||
uint8 *VROM=NULL;
|
||||
uint8 *ROM = NULL;
|
||||
uint8 *VROM = NULL;
|
||||
iNES_HEADER head ;
|
||||
|
||||
|
||||
#ifdef _USE_SHARED_MEMORY_
|
||||
HANDLE mapROM, mapVROM;
|
||||
HANDLE mapROM = NULL, mapVROM = NULL;
|
||||
#endif
|
||||
|
||||
CartInfo iNESCart;
|
||||
@ -129,36 +129,32 @@ void iNESGI(GI h) //bbit edited: removed static keyword
|
||||
if(iNESCart.Close) iNESCart.Close();
|
||||
#ifdef _USE_SHARED_MEMORY_
|
||||
if(ROM)
|
||||
{
|
||||
{
|
||||
if(mapROM)
|
||||
{
|
||||
UnmapViewOfFile(mapROM);
|
||||
CloseHandle(mapROM);
|
||||
ROM=0;
|
||||
mapROM = NULL;
|
||||
UnmapViewOfFile(ROM);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(ROM);
|
||||
ROM = NULL;
|
||||
}
|
||||
}
|
||||
ROM = NULL;
|
||||
}
|
||||
if(VROM)
|
||||
{
|
||||
{
|
||||
if(mapVROM)
|
||||
{
|
||||
UnmapViewOfFile(mapVROM);
|
||||
CloseHandle(mapVROM);
|
||||
VROM=0;
|
||||
mapVROM = NULL;
|
||||
UnmapViewOfFile(VROM);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(VROM);
|
||||
VROM = NULL;
|
||||
}
|
||||
}
|
||||
VROM = NULL;
|
||||
}
|
||||
#else
|
||||
if(ROM) {free(ROM);ROM=0;}
|
||||
if(VROM) {free(VROM);VROM=0;}
|
||||
if(ROM) {free(ROM); ROM = NULL;}
|
||||
if(VROM) {free(VROM); VROM = NULL;}
|
||||
#endif
|
||||
if(MapClose) MapClose();
|
||||
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
|
||||
{0xedc3662b,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Operation Wolf
|
||||
{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
|
||||
{0xb8b9aca3,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Wild Gunman
|
||||
@ -390,7 +387,7 @@ static void CheckHInfo(void)
|
||||
0x1b084107d0878bd0LL, /* Startropics 2*/
|
||||
|
||||
0x836c0ff4f3e06e45LL, /* Zelda 2 */
|
||||
|
||||
|
||||
0x82000965f04a71bbLL, /* Mirai Shinwa Jarvas */
|
||||
|
||||
0 /* Abandon all hope if the game has 0 in the lower 64-bits of its MD5 hash */
|
||||
@ -425,8 +422,9 @@ static void CheckHInfo(void)
|
||||
#ifdef _USE_SHARED_MEMORY_
|
||||
if(mapVROM)
|
||||
{
|
||||
UnmapViewOfFile(mapVROM);
|
||||
CloseHandle(mapVROM);
|
||||
UnmapViewOfFile(VROM);
|
||||
mapVROM = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -435,7 +433,7 @@ static void CheckHInfo(void)
|
||||
#else
|
||||
free(VROM);
|
||||
#endif
|
||||
VROM=0;
|
||||
VROM = NULL;
|
||||
tofix|=8;
|
||||
}
|
||||
if(MapperNo!=(moo[x].mapper&0xFF))
|
||||
@ -536,9 +534,9 @@ typedef struct {
|
||||
char* name;
|
||||
int number;
|
||||
void (*init)(CartInfo *);
|
||||
} BMAPPING;
|
||||
} BMAPPINGLocal;
|
||||
|
||||
static BMAPPING bmap[] = {
|
||||
static BMAPPINGLocal bmap[] = {
|
||||
{"NROM", 0, NROM_Init},
|
||||
{"MMC1", 1, Mapper1_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");
|
||||
if(mapROM == NULL || GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
mapROM = NULL;
|
||||
CloseHandle(mapROM);
|
||||
|
||||
if(!(ROM=(uint8 *)FCEU_malloc(ROM_size<<14)))
|
||||
return 0;
|
||||
|
||||
if(VROM_size)
|
||||
if((ROM = (uint8 *)FCEU_malloc(ROM_size<<14)) == NULL) return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((ROM = (uint8 *)MapViewOfFile(mapROM, FILE_MAP_WRITE, 0, 0, 0)) == NULL)
|
||||
{
|
||||
if(!(VROM=(uint8 *)FCEU_malloc(VROM_size<<13)))
|
||||
CloseHandle(mapROM);
|
||||
mapROM = NULL;
|
||||
if((ROM = (uint8 *)FCEU_malloc(ROM_size<<14)) == NULL) return 0;
|
||||
}
|
||||
}
|
||||
if(VROM_size)
|
||||
{
|
||||
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)
|
||||
{
|
||||
free(ROM);
|
||||
if(mapROM)
|
||||
{
|
||||
UnmapViewOfFile(mapROM);
|
||||
mapROM = NULL;
|
||||
CloseHandle(ROM);
|
||||
}
|
||||
else
|
||||
free(ROM);
|
||||
ROM = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ROM = (uint8 *)MapViewOfFile(mapROM, FILE_MAP_WRITE, 0, 0, 0);
|
||||
if( !ROM ) return 0;
|
||||
|
||||
if(VROM_size)
|
||||
else
|
||||
{
|
||||
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 )
|
||||
if((VROM = (uint8 *)MapViewOfFile(mapVROM, FILE_MAP_WRITE, 0, 0, 0)) == NULL)
|
||||
{
|
||||
UnmapViewOfFile(mapROM);
|
||||
CloseHandle(mapROM);
|
||||
return 0;
|
||||
CloseHandle(mapVROM);
|
||||
mapVROM = NULL;
|
||||
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(!(ROM=(uint8 *)FCEU_malloc(ROM_size<<14)))
|
||||
return 0;
|
||||
if((ROM = (uint8 *)FCEU_malloc(ROM_size<<14)) == NULL) return 0;
|
||||
|
||||
if(VROM_size)
|
||||
{
|
||||
if(!(VROM=(uint8 *)FCEU_malloc(VROM_size<<13)))
|
||||
if((VROM = (uint8 *)FCEU_malloc(VROM_size<<13)) == NULL)
|
||||
{
|
||||
free(ROM);
|
||||
ROM = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -831,10 +848,23 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode)
|
||||
FCEU_printf("%02x",iNESCart.MD5[x]);
|
||||
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",
|
||||
MapperNo, bmap[MapperNo].name, 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");
|
||||
MapperNo, mappername, Mirroring==2?"None (Four-screen)":Mirroring?"Vertical":"Horizontal");
|
||||
|
||||
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();
|
||||
CheckHInfo();
|
||||
@ -880,6 +910,14 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode)
|
||||
#endif
|
||||
|
||||
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;
|
||||
FCEU_printf("\n");
|
||||
|
||||
@ -1443,11 +1481,11 @@ static void iNESPower(void)
|
||||
|
||||
static int NewiNES_Init(int num)
|
||||
{
|
||||
BMAPPING *tmp=bmap;
|
||||
BMAPPINGLocal *tmp=bmap;
|
||||
|
||||
if(GameInfo->type == GIT_VSUNI)
|
||||
AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);
|
||||
|
||||
|
||||
while(tmp->init)
|
||||
{
|
||||
if(num==tmp->number)
|
||||
@ -1470,14 +1508,19 @@ static int NewiNES_Init(int num)
|
||||
{
|
||||
CloseHandle(mapVROM);
|
||||
mapVROM = NULL;
|
||||
VROM=(uint8 *)malloc(CHRRAMSize);
|
||||
if((VROM = (uint8 *)malloc(CHRRAMSize)) == NULL) return 0;
|
||||
}
|
||||
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
|
||||
VROM=(uint8 *)malloc(CHRRAMSize);
|
||||
if((VROM = (uint8 *)malloc(CHRRAMSize)) == NULL) return 0;
|
||||
#endif
|
||||
UNIFchrrama=VROM;
|
||||
SetupCartCHRMapping(0,VROM,CHRRAMSize,1);
|
||||
@ -1486,9 +1529,9 @@ static int NewiNES_Init(int num)
|
||||
if(head.ROM_type&8)
|
||||
AddExState(ExtraNTARAM, 2048, 0, "EXNR");
|
||||
tmp->init(&iNESCart);
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -85,6 +85,8 @@ static uint8 joy_readbit[2];
|
||||
uint8 joy[4]={0,0,0,0}; //HACK - should be static but movie needs it
|
||||
static uint8 LastStrobe;
|
||||
|
||||
bool replaceP2StartWithMicrophone = false;
|
||||
|
||||
#ifdef _USE_SHARED_MEMORY_
|
||||
static uint32 BotPointer = 0; //mbg merge 7/18/06 changed to uint32
|
||||
#endif
|
||||
@ -107,13 +109,36 @@ static DECLFR(JPRead)
|
||||
{
|
||||
lagFlag = 0;
|
||||
uint8 ret=0;
|
||||
static bool microphone = false;
|
||||
|
||||
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)
|
||||
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;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@ -471,6 +496,10 @@ bool FCEUI_GetInputFourscore()
|
||||
{
|
||||
return FSAttached;
|
||||
}
|
||||
bool FCEUI_GetInputMicrophone()
|
||||
{
|
||||
return replaceP2StartWithMicrophone;
|
||||
}
|
||||
void FCEUI_SetInputFourscore(bool attachFourscore)
|
||||
{
|
||||
FSAttached = attachFourscore;
|
||||
@ -603,6 +632,12 @@ static void LaunchTraceLogger(void);
|
||||
static void LaunchCodeDataLogger(void);
|
||||
static void LaunchRamWatch(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 OpenRom(void);
|
||||
static void CloseRom(void);
|
||||
@ -723,8 +758,14 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
|
||||
{ EMUCMD_MISC_DISPLAY_MOVIESUBTITLES, EMUCMDTYPE_MISC, MovieSubtitleToggle,0,0,"Toggle Movie Subtitles", 0},
|
||||
{ EMUCMD_MISC_UNDOREDOSAVESTATE, EMUCMDTYPE_MISC, UndoRedoSavestate, 0,0,"Undo/Redo Savestate", 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_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]))
|
||||
@ -758,7 +799,7 @@ void FCEUI_HandleEmuCommands(TestCommandState* testfn)
|
||||
|
||||
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)
|
||||
@ -925,7 +966,59 @@ static void LaunchRamSearch(void)
|
||||
#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)
|
||||
{
|
||||
@ -950,8 +1043,8 @@ static void CloseRom(void)
|
||||
static void MovieSubtitleToggle(void)
|
||||
{
|
||||
movieSubtitles ^= 1;
|
||||
if (movieSubtitles) FCEU_DispMessage("Movie subtitles on");
|
||||
else FCEU_DispMessage("Movie subtitles off");
|
||||
if (movieSubtitles) FCEU_DispMessage("Movie subtitles on",0);
|
||||
else FCEU_DispMessage("Movie subtitles off",0);
|
||||
}
|
||||
|
||||
static void UndoRedoSavestate(void)
|
||||
@ -981,4 +1074,4 @@ static void ToggleFullscreen(void)
|
||||
SetVideoMode(oldmode);
|
||||
changerecursive=0;
|
||||
#endif
|
||||
}
|
||||
}
|
@ -221,6 +221,12 @@ enum EMUCMD
|
||||
EMUCMD_MISC_TOGGLEFULLSCREEN,
|
||||
EMUCMD_TOOL_OPENRAMWATCH,
|
||||
EMUCMD_TOOL_OPENRAMSEARCH,
|
||||
EMUCMD_TOOL_RAMSEARCHLT,
|
||||
EMUCMD_TOOL_RAMSEARCHGT,
|
||||
EMUCMD_TOOL_RAMSEARCHLTE,
|
||||
EMUCMD_TOOL_RAMSEARCHGTE,
|
||||
EMUCMD_TOOL_RAMSEARCHEQ,
|
||||
EMUCMD_TOOL_RAMSEARCHNE,
|
||||
EMUCMD_MAX
|
||||
};
|
||||
|
||||
@ -269,4 +275,3 @@ extern bool turbo;
|
||||
void LagCounterReset();
|
||||
|
||||
#endif //_INPUT_H_
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* (VRC4 mapper)
|
||||
* (VRCII mapper)
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
@ -26,9 +26,21 @@
|
||||
#define K4sel mapbyte1[0]
|
||||
|
||||
static int acount=0;
|
||||
static int weirdo=0;
|
||||
static DECLFW(Mapper25_write)
|
||||
{
|
||||
A=(A&0xF003)|((A&0xC)>>2);
|
||||
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);
|
||||
|
||||
if((A&0xF000)==0xA000)
|
||||
ROM_BANK8(0xA000,V);
|
||||
@ -38,7 +50,10 @@ static DECLFW(Mapper25_write)
|
||||
|
||||
K4buf[x]&=(0xF0)>>((A&2)<<1);
|
||||
K4buf[x]|=(V&0xF)<<((A&2)<<1);
|
||||
VROM_BANK1(x<<10,K4buf[x]);
|
||||
if(weirdo)
|
||||
weirdo--;
|
||||
else
|
||||
VROM_BANK1(x<<10,K4buf[x]);
|
||||
}
|
||||
else if((A&0xF000)==0x8000)
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ static DECLFR(SUN5AWRAM)
|
||||
{
|
||||
if((sungah&0xC0)==0x40)
|
||||
return X.DB;
|
||||
return CartBR(A);
|
||||
return CartBROB(A);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper69_SWL)
|
||||
|
@ -87,8 +87,8 @@ static void booga(int version)
|
||||
|
||||
void Mapper80_init(void)
|
||||
{
|
||||
SetWriteHandler(0x4020,0x7eff,Mapper80_write);// 7f00-7fff battery backed ram inside mapper chip,
|
||||
// controlled by 7ef8 register, A8 - enable, FF - disable (?)
|
||||
SetWriteHandler(0x4020,0x7eff,Mapper80_write);// 7f00-7fff battery backed ram inside mapper chip,
|
||||
// controlled by 7ef8 register, A8 - enable, FF - disable (?)
|
||||
MapStateRestore=booga;
|
||||
isfu=0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -37,7 +37,7 @@ typedef struct
|
||||
int movie_version; // version of the movie format in the file
|
||||
uint32 num_frames;
|
||||
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
|
||||
uint32 emu_version_used; // 9813 = 0.98.13
|
||||
MD5DATA md5_of_rom_used;
|
||||
@ -58,7 +58,8 @@ enum EMOVIEMODE
|
||||
MOVIEMODE_INACTIVE = 1,
|
||||
MOVIEMODE_RECORD = 2,
|
||||
MOVIEMODE_PLAY = 4,
|
||||
MOVIEMODE_TASEDIT = 8
|
||||
MOVIEMODE_TASEDIT = 8,
|
||||
MOVIEMODE_FINISHED = 16
|
||||
};
|
||||
|
||||
enum EMOVIECMD
|
||||
@ -72,27 +73,31 @@ enum EMOVIECMD
|
||||
EMOVIEMODE FCEUMOV_Mode();
|
||||
bool FCEUMOV_Mode(EMOVIEMODE 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_IsFinished() { return FCEUMOV_Mode(MOVIEMODE_FINISHED);}
|
||||
inline bool FCEUMOV_IsLoaded() { return (FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED)); }
|
||||
|
||||
bool FCEUMOV_ShouldPause(void);
|
||||
int FCEUMOV_GetFrame(void);
|
||||
int FCEUI_GetLagCount(void);
|
||||
bool FCEUI_GetLagged(void);
|
||||
|
||||
int FCEUMOV_WriteState(std::ostream* os);
|
||||
bool FCEUMOV_ReadState(std::istream* is, uint32 size);
|
||||
int FCEUMOV_WriteState(EMUFILE* os);
|
||||
bool FCEUMOV_ReadState(EMUFILE* is, uint32 size);
|
||||
void FCEUMOV_PreLoad();
|
||||
bool FCEUMOV_PostLoad();
|
||||
|
||||
void FCEUMOV_EnterTasEdit();
|
||||
void FCEUMOV_ExitTasEdit();
|
||||
bool FCEUMOV_FromPoweron();
|
||||
|
||||
class MovieData;
|
||||
class MovieRecord
|
||||
{
|
||||
|
||||
public:
|
||||
MovieRecord();
|
||||
ValueArray<uint8,4> joysticks;
|
||||
|
||||
struct {
|
||||
@ -135,17 +140,15 @@ public:
|
||||
return (joysticks[joy] & mask(bit))!=0;
|
||||
}
|
||||
|
||||
bool Compare(MovieRecord& compareRec);
|
||||
void clear();
|
||||
|
||||
//a waste of memory in lots of cases.. maybe make it a pointer later?
|
||||
std::vector<char> savestate;
|
||||
|
||||
void parse(MovieData* md, std::istream* is);
|
||||
bool parseBinary(MovieData* md, std::istream* is);
|
||||
void dump(MovieData* md, std::ostream* os, int index);
|
||||
void dumpBinary(MovieData* md, std::ostream* os, int index);
|
||||
void parseJoy(std::istream* is, uint8& joystate);
|
||||
void dumpJoy(std::ostream* os, uint8 joystate);
|
||||
void parse(MovieData* md, EMUFILE* is);
|
||||
bool parseBinary(MovieData* md, EMUFILE* is);
|
||||
void dump(MovieData* md, EMUFILE* os, int index);
|
||||
void dumpBinary(MovieData* md, EMUFILE* os, int index);
|
||||
void parseJoy(EMUFILE* is, uint8& joystate);
|
||||
void dumpJoy(EMUFILE* os, uint8 joystate);
|
||||
|
||||
static const char mnemonics[8];
|
||||
|
||||
@ -157,17 +160,19 @@ class MovieData
|
||||
{
|
||||
public:
|
||||
MovieData();
|
||||
|
||||
// Default Values: MovieData::MovieData()
|
||||
|
||||
int version;
|
||||
int emuVersion;
|
||||
int fds;
|
||||
//todo - somehow force mutual exclusion for poweron and reset (with an error in the parser)
|
||||
bool palFlag;
|
||||
bool PPUflag;
|
||||
MD5DATA romChecksum;
|
||||
std::string romFilename;
|
||||
std::vector<char> savestate;
|
||||
std::vector<uint8> savestate;
|
||||
std::vector<MovieRecord> records;
|
||||
std::vector<std::vector<uint8> > savestates;
|
||||
std::vector<std::wstring> comments;
|
||||
std::vector<std::string> subtitles;
|
||||
//this is the RERECORD COUNT. please rename variable.
|
||||
@ -181,6 +186,8 @@ public:
|
||||
int ports[3];
|
||||
//whether fourscore is enabled
|
||||
bool fourscore;
|
||||
//whether microphone is enabled
|
||||
bool microphone;
|
||||
|
||||
//----TasEdit stuff---
|
||||
int greenZoneCount;
|
||||
@ -219,15 +226,18 @@ public:
|
||||
|
||||
void truncateAt(int frame);
|
||||
void installValue(std::string& key, std::string& val);
|
||||
int dump(std::ostream* os, bool binary);
|
||||
int dumpGreenzone(std::ostream *os, bool binary);
|
||||
int loadGreenzone(std::istream *is, bool binary);
|
||||
int dump(EMUFILE* os, bool binary);
|
||||
int dumpGreenzone(EMUFILE *os, bool binary);
|
||||
int loadGreenzone(EMUFILE *is, bool binary);
|
||||
|
||||
void clearRecordRange(int start, int len);
|
||||
void insertEmpty(int at, int frames);
|
||||
|
||||
static bool loadSavestateFrom(std::vector<char>* buf);
|
||||
static void dumpSavestateTo(std::vector<char>* buf, int compressionLevel);
|
||||
static bool loadSavestateFrom(std::vector<uint8>* buf);
|
||||
static void dumpSavestateTo(std::vector<uint8>* buf, int compressionLevel);
|
||||
|
||||
bool loadTasSavestate(int frame);
|
||||
void storeTasSavestate(int frame, int compression_level);
|
||||
void TryDumpIncremental();
|
||||
|
||||
private:
|
||||
@ -250,8 +260,8 @@ extern bool freshMovie;
|
||||
extern bool movie_readonly;
|
||||
extern bool autoMovieBackup;
|
||||
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_CreateMovieFile(std::string fn);
|
||||
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_StopMovie(void);
|
||||
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);
|
||||
bool FCEUI_GetMovieToggleReadOnly();
|
||||
void FCEUI_SetMovieToggleReadOnly(bool which);
|
||||
@ -269,7 +279,7 @@ std::string FCEUI_GetMovieName(void);
|
||||
void FCEUI_MovieToggleFrameDisplay();
|
||||
void FCEUI_ToggleInputDisplay(void);
|
||||
|
||||
void LoadSubtitles(MovieData);
|
||||
void LoadSubtitles(MovieData &);
|
||||
void ProcessSubtitles(void);
|
||||
void FCEU_DisplaySubtitles(char *format, ...);
|
||||
|
||||
|
@ -50,7 +50,7 @@ static int netdcount;
|
||||
|
||||
static void NetError(void)
|
||||
{
|
||||
FCEU_DispMessage("Network error/connection lost!");
|
||||
FCEU_DispMessage("Network error/connection lost!",0);
|
||||
FCEUD_NetworkClose();
|
||||
}
|
||||
|
||||
@ -310,7 +310,7 @@ void NetplayUpdate(uint8 *joyp)
|
||||
if(FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP))
|
||||
{
|
||||
fclose(fp);
|
||||
FCEU_DispMessage("Remote state loaded.");
|
||||
FCEU_DispMessage("Remote state loaded.",0);
|
||||
} else FCEUD_PrintError("File error. (K)ill, (M)aim, (D)estroy?");
|
||||
}
|
||||
break;*/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -201,8 +201,6 @@ void LogDPCM(int romaddress, int dpcmsize){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Instantaneous? Maybe the new freq value is being calculated all of the time... */
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include "sound.h"
|
||||
#include "utils/endian.h"
|
||||
#include "utils/memory.h"
|
||||
#include "utils/memorystream.h"
|
||||
#include "utils/xstring.h"
|
||||
#include "file.h"
|
||||
#include "fds.h"
|
||||
@ -120,7 +119,7 @@ SFORMAT SFCPUC[]={
|
||||
|
||||
void foo(uint8* test) { (void)test; }
|
||||
|
||||
static int SubWrite(std::ostream* os, SFORMAT *sf)
|
||||
static int SubWrite(EMUFILE* os, SFORMAT *sf)
|
||||
{
|
||||
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?
|
||||
{
|
||||
os->write(sf->desc,4);
|
||||
os->fwrite(sf->desc,4);
|
||||
write32le(sf->s&(~FCEUSTATE_FLAGS),os);
|
||||
|
||||
#ifndef LSB_FIRST
|
||||
@ -151,9 +150,9 @@ static int SubWrite(std::ostream* os, SFORMAT *sf)
|
||||
#endif
|
||||
|
||||
if(sf->s&FCEUSTATE_INDIRECT)
|
||||
os->write(*(char **)sf->v,sf->s&(~FCEUSTATE_FLAGS));
|
||||
os->fwrite(*(char **)sf->v,sf->s&(~FCEUSTATE_FLAGS));
|
||||
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.
|
||||
#ifndef LSB_FIRST
|
||||
@ -167,10 +166,10 @@ static int SubWrite(std::ostream* os, SFORMAT *sf)
|
||||
return(acc);
|
||||
}
|
||||
|
||||
static int WriteStateChunk(std::ostream* os, int type, SFORMAT *sf)
|
||||
static int WriteStateChunk(EMUFILE* os, int type, SFORMAT *sf)
|
||||
{
|
||||
os->put(type);
|
||||
int bsize = SubWrite((std::ostream*)0,sf);
|
||||
os->fputc(type);
|
||||
int bsize = SubWrite((EMUFILE*)0,sf);
|
||||
write32le(bsize,os);
|
||||
|
||||
if(!SubWrite(os,sf))
|
||||
@ -203,16 +202,16 @@ static SFORMAT *CheckS(SFORMAT *sf, uint32 tsize, char *desc)
|
||||
return(0);
|
||||
}
|
||||
|
||||
static bool ReadStateChunk(std::istream* is, SFORMAT *sf, int size)
|
||||
static bool ReadStateChunk(EMUFILE* is, SFORMAT *sf, int size)
|
||||
{
|
||||
SFORMAT *tmp;
|
||||
int temp = is->tellg();
|
||||
int temp = is->ftell();
|
||||
|
||||
while(is->tellg()<temp+size)
|
||||
while(is->ftell()<temp+size)
|
||||
{
|
||||
uint32 tsize;
|
||||
char toa[4];
|
||||
if(is->read(toa,4).gcount()<4)
|
||||
if(is->fread(toa,4)<4)
|
||||
return false;
|
||||
|
||||
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->s&FCEUSTATE_INDIRECT)
|
||||
is->read(*(char **)tmp->v,tmp->s&(~FCEUSTATE_FLAGS));
|
||||
is->fread(*(char **)tmp->v,tmp->s&(~FCEUSTATE_FLAGS));
|
||||
else
|
||||
is->read((char *)tmp->v,tmp->s&(~FCEUSTATE_FLAGS));
|
||||
is->fread((char *)tmp->v,tmp->s&(~FCEUSTATE_FLAGS));
|
||||
|
||||
#ifndef LSB_FIRST
|
||||
if(tmp->s&RLSB)
|
||||
@ -230,7 +229,7 @@ static bool ReadStateChunk(std::istream* is, SFORMAT *sf, int size)
|
||||
#endif
|
||||
}
|
||||
else
|
||||
is->seekg(tsize,std::ios::cur);
|
||||
is->fseek(tsize,SEEK_CUR);
|
||||
} // while(...)
|
||||
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 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;
|
||||
uint32 size;
|
||||
@ -256,7 +255,7 @@ static bool ReadStateChunks(std::istream* is, int32 totalsize)
|
||||
|
||||
while(totalsize > 0)
|
||||
{
|
||||
t=is->get();
|
||||
t=is->fgetc();
|
||||
if(t==EOF) break;
|
||||
if(!read32le(&size,is)) break;
|
||||
totalsize -= size + 5;
|
||||
@ -284,20 +283,20 @@ static bool ReadStateChunks(std::istream* is, int32 totalsize)
|
||||
read_snd=1;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
is->seekg(size,std::ios::cur);
|
||||
is->fseek(size,SEEK_CUR);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
// load back buffer
|
||||
{
|
||||
extern uint8 *XBackBuf;
|
||||
if(is->read((char*)XBackBuf,size).gcount() != size)
|
||||
if(is->fread((char*)XBackBuf,size) != size)
|
||||
ret = false;
|
||||
|
||||
//MBG TODO - can this be moved to a better place?
|
||||
@ -329,7 +328,7 @@ static bool ReadStateChunks(std::istream* is, int32 totalsize)
|
||||
warned=true;
|
||||
}
|
||||
//if(fseek(st,size,SEEK_CUR)<0) goto endo;break;
|
||||
is->seekg(size,std::ios::cur);
|
||||
is->fseek(size,SEEK_CUR);
|
||||
}
|
||||
}
|
||||
//endo:
|
||||
@ -354,17 +353,13 @@ int CurrentState=0;
|
||||
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
|
||||
//TODO - support dumping directly without compressing to save a buffer copy
|
||||
|
||||
#ifdef GEKKO
|
||||
memorystream ms(512*1024); // set aside some space, otherwise expand fails on Wii!
|
||||
#else
|
||||
memorystream ms;
|
||||
#endif
|
||||
std::ostream* os = (std::ostream*)&ms;
|
||||
EMUFILE_MEMORY ms;
|
||||
EMUFILE* os = &ms;
|
||||
|
||||
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,4,FCEUCTRL_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);
|
||||
|
||||
@ -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!
|
||||
if(!FCEUMOV_Mode(MOVIEMODE_TASEDIT))
|
||||
{
|
||||
os->seekp(5,std::ios::cur);
|
||||
os->fseek(5,SEEK_CUR);
|
||||
int size = FCEUMOV_WriteState(os);
|
||||
os->seekp(-(size+5),std::ios::cur);
|
||||
os->put(7);
|
||||
os->fseek(-(size+5),SEEK_CUR);
|
||||
os->fputc(7);
|
||||
write32le(size, os);
|
||||
os->seekp(size,std::ios::cur);
|
||||
os->fseek(size,SEEK_CUR);
|
||||
|
||||
totalsize += 5 + size;
|
||||
}
|
||||
@ -398,9 +393,9 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel)
|
||||
{
|
||||
extern uint8 *XBackBuf;
|
||||
uint32 size = 256 * 256 + 8;
|
||||
os->put(8);
|
||||
os->fputc(8);
|
||||
write32le(size, os);
|
||||
os->write((char*)XBackBuf,size);
|
||||
os->fwrite((char*)XBackBuf,size);
|
||||
totalsize += 5 + size;
|
||||
}
|
||||
|
||||
@ -409,11 +404,7 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel)
|
||||
if(SPreSave) SPostSave();
|
||||
|
||||
//save the length of the file
|
||||
#ifdef GEKKO
|
||||
int len = ms.tellp();
|
||||
#else
|
||||
int len = ms.size();
|
||||
#endif
|
||||
|
||||
//sanity check: len and totalsize should be the same
|
||||
if(len != totalsize)
|
||||
@ -441,8 +432,8 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel)
|
||||
FCEU_en32lsb(header+12, comprlen);
|
||||
|
||||
//dump it to the destination file
|
||||
outstream->write((char*)header,16);
|
||||
outstream->write((char*)cbuf,comprlen==-1?totalsize:comprlen);
|
||||
outstream->fwrite((char*)header,16);
|
||||
outstream->fwrite((char*)cbuf,comprlen==-1?totalsize:comprlen);
|
||||
|
||||
if(cbuf != (uint8*)ms.buf()) delete[] cbuf;
|
||||
return error == Z_OK;
|
||||
@ -451,18 +442,18 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel)
|
||||
|
||||
void FCEUSS_Save(const char *fname)
|
||||
{
|
||||
std::fstream* st = 0;
|
||||
EMUFILE* st = 0;
|
||||
char fn[2048];
|
||||
|
||||
if(geniestage==1)
|
||||
{
|
||||
FCEU_DispMessage("Cannot save FCS in GG screen.");
|
||||
FCEU_DispMessage("Cannot save FCS in GG screen.",0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(fname) //If filename is given use it.
|
||||
{
|
||||
st =FCEUD_UTF8_fstream(fname, "wb");
|
||||
st = FCEUD_UTF8_fstream(fname, "wb");
|
||||
strcpy(fn, fname);
|
||||
}
|
||||
else //Else, generate one
|
||||
@ -485,7 +476,7 @@ void FCEUSS_Save(const char *fname)
|
||||
|
||||
if(st == NULL)
|
||||
{
|
||||
FCEU_DispMessage("State %d save error.",CurrentState);
|
||||
FCEU_DispMessage("State %d save error.",0,CurrentState);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -525,12 +516,12 @@ void FCEUSS_Save(const char *fname)
|
||||
if(!fname)
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
// return 1;
|
||||
@ -566,7 +557,7 @@ int FCEUSS_LoadFP_old(std::istream* is, ENUM_SSLOADPARAMS params)
|
||||
{
|
||||
FCEUMOV_PreLoad();
|
||||
}
|
||||
is->read((char*)&header,16);
|
||||
is->fread((char*)&header,16);
|
||||
if(memcmp(header,"FCS",3))
|
||||
{
|
||||
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
|
||||
memorystream msBackupSavestate;
|
||||
EMUFILE_MEMORY msBackupSavestate;
|
||||
bool backup = (params == SSLOADPARAM_BACKUP);
|
||||
|
||||
if(!is)
|
||||
return false;
|
||||
|
||||
if(backup)
|
||||
FCEUSS_SaveMS(&msBackupSavestate,Z_NO_COMPRESSION);
|
||||
|
||||
uint8 header[16];
|
||||
|
||||
//read and analyze the header
|
||||
is->read((char*)&header,16);
|
||||
is->fread((char*)&header,16);
|
||||
if(memcmp(header,"FCSX",4)) {
|
||||
//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;
|
||||
bool ret = FCEUSS_LoadFP_old(is,params)!=0;
|
||||
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 comprlen = FCEU_de32lsb(header + 12);
|
||||
|
||||
std::vector<char> buf(totalsize);
|
||||
std::vector<uint8> buf(totalsize);
|
||||
|
||||
//not compressed:
|
||||
if(comprlen != -1)
|
||||
{
|
||||
//load the compressed chunk and decompress
|
||||
std::vector<char> cbuf(comprlen);
|
||||
is->read((char*)&cbuf[0],comprlen);
|
||||
is->fread((char*)&cbuf[0],comprlen);
|
||||
|
||||
uLongf uncomprlen = totalsize;
|
||||
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
|
||||
{
|
||||
is->read((char*)&buf[0],totalsize);
|
||||
is->fread((char*)&buf[0],totalsize);
|
||||
}
|
||||
|
||||
FCEUMOV_PreLoad();
|
||||
|
||||
memorystream mstemp(&buf);
|
||||
EMUFILE_MEMORY mstemp(&buf);
|
||||
bool x = ReadStateChunks(&mstemp,totalsize)!=0;
|
||||
|
||||
//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) {
|
||||
msBackupSavestate.sync();
|
||||
msBackupSavestate.fseek(0,SEEK_SET);
|
||||
FCEUSS_LoadFP(&msBackupSavestate,SSLOADPARAM_NOBACKUP);
|
||||
}
|
||||
|
||||
@ -701,7 +696,7 @@ bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params)
|
||||
|
||||
bool FCEUSS_Load(const char *fname)
|
||||
{
|
||||
std::fstream* st;
|
||||
EMUFILE* st;
|
||||
char fn[2048];
|
||||
|
||||
//mbg movie - this needs to be overhauled
|
||||
@ -713,7 +708,7 @@ bool FCEUSS_Load(const char *fname)
|
||||
|
||||
if(geniestage==1)
|
||||
{
|
||||
FCEU_DispMessage("Cannot load FCS in GG screen.");
|
||||
FCEU_DispMessage("Cannot load FCS in GG screen.",0);
|
||||
return false;
|
||||
}
|
||||
if(fname)
|
||||
@ -730,7 +725,7 @@ bool FCEUSS_Load(const char *fname)
|
||||
|
||||
if(st == NULL)
|
||||
{
|
||||
FCEU_DispMessage("State %d load error.",CurrentState);
|
||||
FCEU_DispMessage("State %d load error.",0,CurrentState);
|
||||
SaveStateStatus[CurrentState]=0;
|
||||
return false;
|
||||
}
|
||||
@ -738,20 +733,17 @@ bool FCEUSS_Load(const char *fname)
|
||||
//If in bot mode, don't do a backup when loading.
|
||||
//Otherwise you eat at the hard disk, since so many
|
||||
//states are being loaded.
|
||||
if(FCEUSS_LoadFP(st,SSLOADPARAM_BACKUP))
|
||||
if(FCEUSS_LoadFP(st, backupSavestates ? SSLOADPARAM_BACKUP : SSLOADPARAM_NOBACKUP))
|
||||
{
|
||||
if(fname)
|
||||
{
|
||||
char szFilename[260]={0};
|
||||
splitpath(fname, 0, 0, szFilename, 0);
|
||||
FCEU_DispMessage("State %s loaded.",szFilename);
|
||||
FCEU_DispMessage("State %s loaded.",0,szFilename);
|
||||
}
|
||||
else
|
||||
{
|
||||
//This looks redudant to me... but why bother deleting it:)
|
||||
SaveStateStatus[CurrentState]=1;
|
||||
|
||||
FCEU_DispMessage("State %d loaded.",CurrentState);
|
||||
FCEU_DispMessage("State %d loaded.",0,CurrentState);
|
||||
SaveStateStatus[CurrentState]=1;
|
||||
}
|
||||
delete st;
|
||||
@ -779,6 +771,13 @@ bool FCEUSS_Load(const char *fname)
|
||||
#ifdef WIN32
|
||||
Update_RAM_Search(); // Update_RAM_Watch() is also called.
|
||||
#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;
|
||||
}
|
||||
else
|
||||
@ -787,7 +786,7 @@ bool FCEUSS_Load(const char *fname)
|
||||
{
|
||||
SaveStateStatus[CurrentState]=1;
|
||||
}
|
||||
FCEU_DispMessage("Error(s) reading state %d!",CurrentState);
|
||||
FCEU_DispMessage("Error(s) reading state %d!",0,CurrentState);
|
||||
delete st;
|
||||
return 0;
|
||||
}
|
||||
@ -875,7 +874,7 @@ int FCEUI_SelectState(int w, int show)
|
||||
if(show)
|
||||
{
|
||||
StateShow=180;
|
||||
FCEU_DispMessage("-select state-");
|
||||
FCEU_DispMessage("-select state-",0);
|
||||
}
|
||||
return oldstate;
|
||||
}
|
||||
@ -891,6 +890,15 @@ void FCEUI_SaveState(const char *fname)
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
}
|
||||
if (fname != NULL && !file_exists(fname))
|
||||
{
|
||||
loadStateFailed = 1;
|
||||
return; // state doesn't exist; exit cleanly
|
||||
}
|
||||
if(FCEUSS_Load(fname))
|
||||
{
|
||||
//mbg todo netplay
|
||||
@ -984,14 +997,14 @@ void SwapSaveState()
|
||||
|
||||
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");
|
||||
return; //If there is no last savestate, can't undo
|
||||
}
|
||||
string backup = GenerateBackupSaveStateFn(lastSavestateMade); //Get filename of backup state
|
||||
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");
|
||||
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
|
||||
redoSS = true;
|
||||
|
||||
FCEUI_DispMessage("%s restored",backup.c_str());
|
||||
FCEUI_printf("%s restored\n",backup.c_str());
|
||||
FCEUI_DispMessage("%s restored",0,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
|
||||
}
|
||||
else
|
||||
FCEUI_DispMessage("Error: Could not load %s",filename.c_str());
|
||||
FCEUI_DispMessage("Error: Could not load %s",0,filename.c_str());
|
||||
}
|
||||
|
||||
void RedoLoadState()
|
||||
|
@ -28,9 +28,9 @@ void FCEUSS_Save(const char *);
|
||||
bool FCEUSS_Load(const char *);
|
||||
|
||||
//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;
|
||||
void FCEUSS_CheckStates(void);
|
||||
|
@ -72,6 +72,7 @@ typedef uint32_t uint32;
|
||||
|
||||
#ifdef __GNUC__
|
||||
typedef unsigned long long uint64;
|
||||
typedef uint64 u64;
|
||||
typedef long long int64;
|
||||
#define INLINE inline
|
||||
#define GINLINE inline
|
||||
@ -127,10 +128,10 @@ typedef uint32_t uint32;
|
||||
typedef void (*writefunc)(uint32 A, uint8 V);
|
||||
typedef uint8 (*readfunc)(uint32 A);
|
||||
|
||||
#include "utils/endian.h"
|
||||
|
||||
#ifndef CTASSERT
|
||||
#define CTASSERT(x) typedef char __assert ## y[(x) ? 1 : -1];
|
||||
#endif
|
||||
|
||||
#include "utils/endian.h"
|
||||
|
||||
#endif
|
||||
|
@ -26,6 +26,27 @@
|
||||
#include <fstream>
|
||||
#include "../types.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.
|
||||
void FlipByteOrder(uint8 *src, uint32 count)
|
||||
@ -194,3 +215,99 @@ uint16 FCEU_de16lsb(uint8 *morp)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -3,6 +3,44 @@
|
||||
|
||||
#include <iosfwd>
|
||||
#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);
|
||||
@ -22,5 +60,50 @@ uint64 FCEU_de64lsb(uint8 *morp);
|
||||
uint32 FCEU_de32lsb(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
|
||||
|
||||
|
@ -205,7 +205,7 @@ static const struct Base64Table
|
||||
data[62] = '+'; // 62
|
||||
data[63] = '/'; // 63
|
||||
// create ascii->value mapping (but due to overlap, write it to highbit region)
|
||||
for(a=0; a<64; ++a) data[data[a]^0x80] = a; //
|
||||
for(a=0; a<64; ++a) data[data[a]^0x80] = a; //
|
||||
data[((unsigned char)'=') ^ 0x80] = 0;
|
||||
}
|
||||
unsigned char operator[] (size_t pos) const { return data[pos]; }
|
||||
@ -225,9 +225,9 @@ std::string BytesToString(const void* data, int len)
|
||||
return temp;
|
||||
} else if(len==4) {
|
||||
sprintf(temp,"%d",*(const unsigned int*)data);
|
||||
return temp;
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
std::string ret;
|
||||
if(1) // use base64
|
||||
{
|
||||
@ -279,7 +279,7 @@ int HexStringToBytesLength(const std::string& str)
|
||||
int Base64StringToBytesLength(const std::string& str)
|
||||
{
|
||||
if(str.size() < 7 || (str.size()-7) % 4 || str.substr(0,7) != "base64:") return -1;
|
||||
|
||||
|
||||
size_t c = ((str.size() - 7) / 4) * 3;
|
||||
if(str[str.size()-1] == '=') { --c;
|
||||
if(str[str.size()-2] == '=') --c; }
|
||||
@ -334,12 +334,12 @@ bool StringToBytes(const std::string& str, void* data, int len)
|
||||
else a-='0';
|
||||
if(b>='A') b=b-'A'+10;
|
||||
else b-='0';
|
||||
unsigned char val = ((unsigned char)a<<4)|(unsigned char)b;
|
||||
unsigned char val = ((unsigned char)a<<4)|(unsigned char)b;
|
||||
((unsigned char*)data)[i] = val;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if(len==1) {
|
||||
int x = atoi(str.c_str());
|
||||
*(unsigned char*)data = x;
|
||||
@ -553,13 +553,13 @@ std::string stditoa(int n)
|
||||
}
|
||||
|
||||
|
||||
std::string readNullTerminatedAscii(std::istream* is)
|
||||
std::string readNullTerminatedAscii(EMUFILE* is)
|
||||
{
|
||||
std::string ret;
|
||||
ret.reserve(50);
|
||||
for(;;)
|
||||
for(;;)
|
||||
{
|
||||
int c = is->get();
|
||||
int c = is->fgetc();
|
||||
if(c == 0) break;
|
||||
else ret += (char)c;
|
||||
}
|
||||
@ -723,7 +723,7 @@ namespace UtfConverter
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef GEKKO
|
||||
|
||||
std::wstring FromUtf8(std::string& input) // string -> wstring
|
||||
{
|
||||
std::wstring result;
|
||||
@ -731,7 +731,7 @@ namespace UtfConverter
|
||||
result += DecData(input, pos);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
std::string ToUtf8(std::wstring& input) // wstring -> string
|
||||
{
|
||||
std::string result;
|
||||
@ -739,11 +739,10 @@ namespace UtfConverter
|
||||
SeqValue(result, input[pos]);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef GEKKO
|
||||
|
||||
//convert a std::string to std::wstring
|
||||
std::wstring mbstowcs(std::string str) // UTF8->UTF32
|
||||
{
|
||||
@ -759,7 +758,7 @@ std::string wcstombs(std::wstring str) // UTF32->UTF8
|
||||
{
|
||||
return UtfConverter::ToUtf8(str);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//TODO - dont we already have another function that can do this
|
||||
std::string getExtension(const char* input) {
|
||||
@ -775,3 +774,16 @@ std::string getExtension(const char* input) {
|
||||
ext[k]=tolower(ext[k]);
|
||||
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);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "../types.h"
|
||||
#include "../emufile.h"
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define strcasecmp strcmp
|
||||
@ -62,17 +63,17 @@ char *U16ToHexStr(uint16 a);
|
||||
|
||||
std::string stditoa(int n);
|
||||
|
||||
std::string readNullTerminatedAscii(std::istream* is);
|
||||
std::string readNullTerminatedAscii(EMUFILE* is);
|
||||
|
||||
//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;
|
||||
bool pre = true;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int c = is->get();
|
||||
int c = is->fgetc();
|
||||
if(c == -1) return ret;
|
||||
int d = c - '0';
|
||||
if((d<0 || d>9))
|
||||
@ -91,11 +92,11 @@ template<typename T> T templateIntegerDecFromIstream(std::istream* is)
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline uint32 uint32DecFromIstream(std::istream* is) { return templateIntegerDecFromIstream<uint32>(is); }
|
||||
inline uint64 uint64DecFromIstream(std::istream* is) { return templateIntegerDecFromIstream<uint64>(is); }
|
||||
inline uint32 uint32DecFromIstream(EMUFILE* is) { return templateIntegerDecFromIstream<uint32>(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)
|
||||
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];
|
||||
int ctr = 0;
|
||||
@ -111,18 +112,20 @@ template<typename T, int DIGITS, bool PAD> void putdec(std::ostream* os, T dec)
|
||||
dec = quot;
|
||||
}
|
||||
if(!PAD)
|
||||
os->write(temp+DIGITS-ctr-1,ctr+1);
|
||||
os->fwrite(temp+DIGITS-ctr-1,ctr+1);
|
||||
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);
|
||||
|
||||
#ifndef GEKKO
|
||||
std::wstring mbstowcs(std::string str);
|
||||
std::string wcstombs(std::wstring str);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//TODO - dont we already have another function that can do this
|
||||
std::string getExtension(const char* input);
|
||||
|
||||
std::string StripExtension(std::string filename);
|
||||
std::string StripPath(std::string filename);
|
@ -58,8 +58,8 @@
|
||||
#define FCEU_COMPILER_DETAIL ""
|
||||
#endif
|
||||
|
||||
#define FCEU_VERSION_NUMERIC 21020
|
||||
#define FCEU_VERSION_STRING "2.1.3" FCEU_SUBVERSION_STRING FCEU_FEATURE_STRING FCEU_COMPILER
|
||||
#define FCEU_VERSION_NUMERIC 21040
|
||||
#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
|
||||
|
||||
#endif
|
||||
|
@ -50,6 +50,11 @@
|
||||
#include "fceulua.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include "drivers/win/common.h" //For DirectX constants
|
||||
#include "drivers/win/input.h"
|
||||
#endif
|
||||
|
||||
#ifdef CREATE_AVI
|
||||
#include "drivers/videolog/nesvideos-piece.h"
|
||||
#endif
|
||||
@ -66,10 +71,17 @@ GUIMESSAGE subtitleMessage;
|
||||
extern int input_display;
|
||||
extern uint32 cur_input_display;
|
||||
|
||||
bool oldInputDisplay = false;
|
||||
|
||||
#ifdef _USE_SHARED_MEMORY_
|
||||
HANDLE mapXBuf;
|
||||
#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)
|
||||
{
|
||||
//mbg merge TODO 7/17/06 temporarily removed
|
||||
@ -175,15 +187,19 @@ void FCEUI_SaveSnapshot(void)
|
||||
dosnapsave=1;
|
||||
}
|
||||
|
||||
void FCEUI_SaveSnapshotAs(void)
|
||||
{
|
||||
dosnapsave=2;
|
||||
}
|
||||
|
||||
|
||||
static void ReallySnap(void)
|
||||
{
|
||||
int x=SaveSnapshot();
|
||||
if(!x)
|
||||
FCEU_DispMessage("Error saving screen snapshot.");
|
||||
FCEU_DispMessage("Error saving screen snapshot.",0);
|
||||
else
|
||||
FCEU_DispMessage("Screen snapshot %d saved.",x-1);
|
||||
FCEU_DispMessage("Screen snapshot %d saved.",0,x-1);
|
||||
}
|
||||
|
||||
void FCEU_PutImage(void)
|
||||
@ -191,13 +207,23 @@ void FCEU_PutImage(void)
|
||||
#ifdef SHOWFPS
|
||||
ShowFPS();
|
||||
#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)
|
||||
{
|
||||
DrawNSF(XBuf);
|
||||
|
||||
//Save snapshot after NSF screen is drawn. Why would we want to do it before?
|
||||
if(dosnapsave)
|
||||
if(dosnapsave==1)
|
||||
{
|
||||
ReallySnap();
|
||||
dosnapsave=0;
|
||||
@ -222,7 +248,7 @@ void FCEU_PutImage(void)
|
||||
FCEUI_AviVideoUpdate(XBuf);
|
||||
|
||||
//Save snapshot before overlay stuff is written.
|
||||
if(dosnapsave)
|
||||
if(dosnapsave==1)
|
||||
{
|
||||
ReallySnap();
|
||||
dosnapsave=0;
|
||||
@ -245,9 +271,18 @@ void FCEU_PutImage(void)
|
||||
//Fancy input display code
|
||||
if(input_display)
|
||||
{
|
||||
int controller, c, color;
|
||||
extern uint32 JSAutoHeld;
|
||||
uint32 held;
|
||||
|
||||
int controller, c, ci, color;
|
||||
int i, j;
|
||||
uint8 *t = XBuf+(FSettings.LastSLine-9)*256 + 20; //mbg merge 7/17/06 changed t to uint8*
|
||||
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*
|
||||
if(input_display > 4) input_display = 4;
|
||||
for(controller = 0; controller < input_display; controller++, t += 56)
|
||||
{
|
||||
@ -258,9 +293,32 @@ void FCEU_PutImage(void)
|
||||
for(j = 3; j< 6; j++)
|
||||
t[i+j*256] = 0xCF;
|
||||
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
|
||||
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(j = 0; j < 4; j++)
|
||||
@ -271,7 +329,15 @@ void FCEU_PutImage(void)
|
||||
}
|
||||
}
|
||||
//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(j = 0; j < 4; j++)
|
||||
@ -282,21 +348,45 @@ void FCEU_PutImage(void)
|
||||
}
|
||||
}
|
||||
//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++)
|
||||
{
|
||||
t[11+5*256+i] = color;
|
||||
t[11+6*256+i] = color;
|
||||
}
|
||||
//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++)
|
||||
{
|
||||
t[17+5*256+i] = color;
|
||||
t[17+6*256+i] = color;
|
||||
}
|
||||
//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(j = 0; j < 3; j++)
|
||||
@ -305,7 +395,15 @@ void FCEU_PutImage(void)
|
||||
}
|
||||
}
|
||||
//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(j = 0; j < 3; j++)
|
||||
@ -314,7 +412,15 @@ void FCEU_PutImage(void)
|
||||
}
|
||||
}
|
||||
//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(j = 0; j < 3; j++)
|
||||
@ -323,7 +429,15 @@ void FCEU_PutImage(void)
|
||||
}
|
||||
}
|
||||
//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(j = 0; j < 3; j++)
|
||||
@ -345,21 +459,25 @@ void FCEU_DispMessageOnMovie(char *format, ...)
|
||||
|
||||
guiMessage.howlong = 180;
|
||||
guiMessage.isMovieMessage = true;
|
||||
guiMessage.linesFromBottom = 0;
|
||||
|
||||
if (FCEUI_AviIsRecording() && FCEUI_AviDisableMovieMessages())
|
||||
guiMessage.howlong = 0;
|
||||
}
|
||||
|
||||
void FCEU_DispMessage(char *format, ...)
|
||||
void FCEU_DispMessage(char *format, int disppos=0, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap,format);
|
||||
va_start(ap,disppos);
|
||||
vsnprintf(guiMessage.errmsg,sizeof(guiMessage.errmsg),format,ap);
|
||||
va_end(ap);
|
||||
|
||||
guiMessage.howlong = 180;
|
||||
guiMessage.isMovieMessage = false;
|
||||
|
||||
|
||||
guiMessage.linesFromBottom = disppos;
|
||||
|
||||
//adelikat: Pretty sure this code fails, Movie playback stopped is done with FCEU_DispMessageOnMovie()
|
||||
#ifdef CREATE_AVI
|
||||
if(LoggingEnabled == 2)
|
||||
@ -377,6 +495,7 @@ void FCEU_ResetMessages()
|
||||
{
|
||||
guiMessage.howlong = 0;
|
||||
guiMessage.isMovieMessage = false;
|
||||
guiMessage.linesFromBottom = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -414,6 +533,34 @@ static int WritePNGChunk(FILE *fp, uint32 size, char *type, uint8 *data)
|
||||
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)
|
||||
{
|
||||
unsigned int lastu=0;
|
||||
@ -440,6 +587,7 @@ int SaveSnapshot(void)
|
||||
if(!(pp=FCEUD_UTF8fopen(fn,"wb")))
|
||||
{
|
||||
free(fn);
|
||||
free(compmem);
|
||||
return 0;
|
||||
}
|
||||
free(fn);
|
||||
@ -510,6 +658,101 @@ int SaveSnapshot(void)
|
||||
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:
|
||||
if(compmem)
|
||||
free(compmem);
|
||||
@ -537,4 +780,4 @@ void ShowFPS(void)
|
||||
// It's not averaging FPS over exactly 1 second, but it's close enough.
|
||||
boopcount = (boopcount + 1) % booplimit;
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -1,6 +1,9 @@
|
||||
int FCEU_InitVirtualVideo(void);
|
||||
void FCEU_KillVirtualVideo(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 *XBackBuf;
|
||||
extern int ClipSidesOffset;
|
||||
@ -15,8 +18,14 @@ extern struct GUIMESSAGE
|
||||
//indicates that the movie should be drawn even on top of movies
|
||||
bool isMovieMessage;
|
||||
|
||||
//in case of multiple lines, allow one to move the message
|
||||
int linesFromBottom;
|
||||
|
||||
} guiMessage;
|
||||
|
||||
extern GUIMESSAGE subtitleMessage;
|
||||
|
||||
void FCEU_DrawNumberRow(uint8 *XBuf, int *nstatus, int cur);
|
||||
|
||||
std::string FCEUI_GetSnapshotAsName();
|
||||
void FCEUI_SetSnapshotAsName(std::string name);
|
@ -428,7 +428,7 @@ extern int test; test++;
|
||||
{
|
||||
if(_IRQlow&FCEU_IQRESET)
|
||||
{
|
||||
if(debug_loggingCD) LogCDVectors(0);
|
||||
DEBUG( if(debug_loggingCD) LogCDVectors(0xFFFC); )
|
||||
_PC=RdMem(0xFFFC);
|
||||
_PC|=RdMem(0xFFFD)<<8;
|
||||
_jammed=0;
|
||||
@ -449,7 +449,7 @@ extern int test; test++;
|
||||
PUSH(_PC);
|
||||
PUSH((_P&~B_FLAG)|(U_FLAG));
|
||||
_P|=I_FLAG;
|
||||
DEBUG( if(debug_loggingCD) LogCDVectors(1) );
|
||||
DEBUG( if(debug_loggingCD) LogCDVectors(0xFFFA) );
|
||||
_PC=RdMem(0xFFFA);
|
||||
_PC|=RdMem(0xFFFB)<<8;
|
||||
_IRQlow&=~FCEU_IQNMI;
|
||||
@ -464,7 +464,7 @@ extern int test; test++;
|
||||
PUSH(_PC);
|
||||
PUSH((_P&~B_FLAG)|(U_FLAG));
|
||||
_P|=I_FLAG;
|
||||
DEBUG( if(debug_loggingCD) LogCDVectors(1) );
|
||||
DEBUG( if(debug_loggingCD) LogCDVectors(0xFFFE) );
|
||||
_PC=RdMem(0xFFFE);
|
||||
_PC|=RdMem(0xFFFF)<<8;
|
||||
}
|
||||
|
@ -47,10 +47,9 @@ bool SaveState (char * filepath, bool silent)
|
||||
SaveFile((char *)gameScreenPng, screenpath, gameScreenPngSize, silent);
|
||||
}
|
||||
|
||||
memorystream save(SAVEBUFFERSIZE);
|
||||
EMUFILE_MEMFILE save(SAVEBUFFERSIZE);
|
||||
FCEUSS_SaveMS(&save, Z_BEST_COMPRESSION);
|
||||
save.sync();
|
||||
datasize = save.tellp();
|
||||
datasize = save.size();
|
||||
|
||||
if (datasize)
|
||||
offset = SaveFile(save.buf(), filepath, datasize, silent);
|
||||
@ -90,7 +89,7 @@ bool LoadState (char * filepath, bool silent)
|
||||
|
||||
if (offset > 0)
|
||||
{
|
||||
memorystream save((char *)savebuffer, offset);
|
||||
EMUFILE_MEMFILE save(savebuffer, offset);
|
||||
FCEUSS_LoadFP(&save, SSLOADPARAM_NOBACKUP);
|
||||
retval = true;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
* FCEU Support Functions
|
||||
****************************************************************************/
|
||||
|
||||
#include <gctypes.h>
|
||||
#include "fceugx.h"
|
||||
#include "fceusupport.h"
|
||||
#include "pad.h"
|
||||
@ -16,6 +17,8 @@
|
||||
#include "gcvideo.h"
|
||||
#include "menu.h"
|
||||
|
||||
bool turbo = false;
|
||||
|
||||
/**
|
||||
* Closes a game. Frees memory, and deinitializes the drivers.
|
||||
*/
|
||||
@ -36,7 +39,7 @@ FILE *FCEUD_UTF8fopen(const char *n, const char *m)
|
||||
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;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <di/di.h>
|
||||
#include <ogc/dvd.h>
|
||||
#include <iso9660.h>
|
||||
#include <fat.h>
|
||||
|
||||
#include "fceugx.h"
|
||||
#include "fceusupport.h"
|
||||
|
@ -12,11 +12,8 @@
|
||||
#ifndef _FILEOP_H_
|
||||
#define _FILEOP_H_
|
||||
|
||||
#include <gccore.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ogcsys.h>
|
||||
#include <fat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SAVEBUFFERSIZE (1024 * 512)
|
||||
|
@ -12,8 +12,6 @@
|
||||
#ifndef _MENU_H
|
||||
#define _MENU_H
|
||||
|
||||
#include <ogcsys.h>
|
||||
|
||||
bool GuiLoaded();
|
||||
void InitGUIThreads();
|
||||
void MainMenu (int menuitem);
|
||||
|
@ -19,6 +19,7 @@ ConnectShare (bool silent)
|
||||
|
||||
#else
|
||||
|
||||
#include <gccore.h>
|
||||
#include <network.h>
|
||||
#include <malloc.h>
|
||||
#include <ogc/lwp_watchdog.h>
|
||||
|
@ -12,7 +12,7 @@
|
||||
#ifndef _PAD_H_
|
||||
#define _PAD_H_
|
||||
|
||||
#include <gccore.h>
|
||||
#include <gctypes.h>
|
||||
#include <wiiuse/wpad.h>
|
||||
|
||||
#define PI 3.14159265f
|
||||
|
@ -10,6 +10,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include <zlib.h>
|
||||
#include <gctypes.h>
|
||||
|
||||
#include "fceugx.h"
|
||||
#include "fceusupport.h"
|
||||
|
Loading…
Reference in New Issue
Block a user