update to the latest FCEUX core from git head.

This commit is contained in:
Daryl Borth 2018-08-13 09:04:20 -06:00
parent a9c3f8c631
commit 50b3150515
78 changed files with 4392 additions and 3081 deletions

View File

@ -30,7 +30,7 @@ https://github.com/dborth/fceugx/releases
* Cheat support (.CHT files and Game Genie) * Cheat support (.CHT files and Game Genie)
* Famicom 3D System support * Famicom 3D System support
* IPS/UPS automatic patching support * IPS/UPS automatic patching support
* NES Compatibility Based on FCEUX 2.2.0+ (r2951) * NES Compatibility Based on FCEUX 2.2.3+ (git 21c0971)
* Open Source! * Open Source!
×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ ×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬
@ -39,6 +39,7 @@ https://github.com/dborth/fceugx/releases
[3.4.0] [3.4.0]
* Update to the latest FCEUX core
* Allow loader to pass two arguments instead of three (libertyernie) * Allow loader to pass two arguments instead of three (libertyernie)
* Add PocketNES interoperability (load ROMs and read/write SRAM) * Add PocketNES interoperability (load ROMs and read/write SRAM)
* Add option to not append " Auto" on saves * Add option to not append " Auto" on saves

View File

@ -272,7 +272,7 @@ char *Disassemble(int addr, uint8 *opcode) {
(a) = opcode[1] | opcode[2]<<8; \ (a) = opcode[1] | opcode[2]<<8; \
} }
#define zpIndex(a,i) { \ #define zpIndex(a,i) { \
(a) = opcode[1]+(i); \ (a) = (opcode[1]+(i))&0xFF; \
} }
#define indirectX(a) { \ #define indirectX(a) { \
(a) = (opcode[1]+RX)&0xFF; \ (a) = (opcode[1]+RX)&0xFF; \
@ -360,8 +360,8 @@ char *Disassemble(int addr, uint8 *opcode) {
case 0xE6: strcpy(chr,"INC"); goto _zeropage; case 0xE6: strcpy(chr,"INC"); goto _zeropage;
_zeropage: _zeropage:
// ################################## Start of SP CODE ########################### // ################################## Start of SP CODE ###########################
// Change width to %04X // Change width to %04X // don't!
sprintf(str,"%s $%04X = #$%02X", chr,opcode[1],GetMem(opcode[1])); sprintf(str,"%s $%02X = #$%02X", chr,opcode[1],GetMem(opcode[1]));
// ################################## End of SP CODE ########################### // ################################## End of SP CODE ###########################
break; break;
@ -457,7 +457,7 @@ char *Disassemble(int addr, uint8 *opcode) {
_zeropagex: _zeropagex:
zpIndex(tmp,RX); zpIndex(tmp,RX);
// ################################## Start of SP CODE ########################### // ################################## Start of SP CODE ###########################
// Change width to %04X // Change width to %04X // don't!
sprintf(str,"%s $%02X,X @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp)); sprintf(str,"%s $%02X,X @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
// ################################## End of SP CODE ########################### // ################################## End of SP CODE ###########################
break; break;
@ -515,8 +515,8 @@ char *Disassemble(int addr, uint8 *opcode) {
_zeropagey: _zeropagey:
zpIndex(tmp,RY); zpIndex(tmp,RY);
// ################################## Start of SP CODE ########################### // ################################## Start of SP CODE ###########################
// Change width to %04X // Change width to %04X // don't!
sprintf(str,"%s $%04X,Y @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp)); sprintf(str,"%s $%02X,Y @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
// ################################## End of SP CODE ########################### // ################################## End of SP CODE ###########################
break; break;

View File

@ -19,6 +19,7 @@
* *
* TXC mappers, originally much complex banksitching * TXC mappers, originally much complex banksitching
* *
* P/N PRG MAP, UNIF Name
* 01-22111-000 (05-00002-010) (132, 22211) - MGC-001 Qi Wang * 01-22111-000 (05-00002-010) (132, 22211) - MGC-001 Qi Wang
* 01-22110-000 (52S ) - MGC-002 2-in-1 Gun * 01-22110-000 (52S ) - MGC-002 2-in-1 Gun
* 01-22111-100 (02-00002-010) (173 ) - MGC-008 Mahjong Block * 01-22111-100 (02-00002-010) (173 ) - MGC-008 Mahjong Block
@ -27,6 +28,7 @@
* 01-22000-400 (05-00002-010) (036 ) - MGC-015 Policeman * 01-22000-400 (05-00002-010) (036 ) - MGC-015 Policeman
* 01-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior * 01-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior
* 01-11160-000 (04-02310-000) ( , 11160) - MGC-023 6-in-1 * 01-11160-000 (04-02310-000) ( , 11160) - MGC-023 6-in-1
* 01-22026-000 (05-04010-090) ( ) - MGC-026 4-in-1
* 01-22270-000 (05-00002-010) (132, 22211) - MGC-xxx Creatom * 01-22270-000 (05-00002-010) (132, 22211) - MGC-xxx Creatom
* 01-22200-400 (------------) (079 ) - ET.03 F-15 City War * 01-22200-400 (------------) (079 ) - ET.03 F-15 City War
* (172 ) - 1991 Du Ma Racing * (172 ) - 1991 Du Ma Racing

View File

@ -72,7 +72,7 @@ static void M112Power(void) {
SetWriteHandler(0x4020, 0x5FFF, M112Write); SetWriteHandler(0x4020, 0x5FFF, M112Write);
SetReadHandler(0x6000, 0x7FFF, CartBR); SetReadHandler(0x6000, 0x7FFF, CartBR);
SetWriteHandler(0x6000, 0x7FFF, CartBW); SetWriteHandler(0x6000, 0x7FFF, CartBW);
FCEU_CheatAddRAM(8, 0x6000, WRAM); FCEU_CheatAddRAM(8, 0x6000, WRAM);
} }
static void StateRestore(int version) { static void StateRestore(int version) {

View File

@ -102,7 +102,7 @@ static void Power(void) {
SetWriteHandler(0x5000, 0x5FFF, Write); SetWriteHandler(0x5000, 0x5FFF, Write);
SetReadHandler(0x6000, 0xFFFF, CartBR); SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(0x6000, 0x7FFF, CartBW); SetWriteHandler(0x6000, 0x7FFF, CartBW);
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
WSync(); WSync();
} }
@ -156,7 +156,7 @@ static void Power2(void) {
SetWriteHandler(0x5000, 0x5FFF, Write2); SetWriteHandler(0x5000, 0x5FFF, Write2);
SetReadHandler(0x6000, 0xFFFF, CartBR); SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(0x6000, 0x7FFF, CartBW); SetWriteHandler(0x6000, 0x7FFF, CartBW);
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
WSync(); WSync();
} }
@ -208,7 +208,7 @@ static void Power3(void) {
SetWriteHandler(0x5000, 0x5FFF, Write3); SetWriteHandler(0x5000, 0x5FFF, Write3);
SetReadHandler(0x6000, 0xFFFF, CartBR); SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(0x6000, 0x7FFF, CartBW); SetWriteHandler(0x6000, 0x7FFF, CartBW);
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
WSync(); WSync();
} }

View File

@ -55,7 +55,7 @@ static void M168Power(void) {
SetReadHandler(0x8000, 0xFFFF, CartBR); SetReadHandler(0x8000, 0xFFFF, CartBR);
} }
static void MNNNClose(void) { static void M168Close(void) {
if (CHRRAM) if (CHRRAM)
FCEU_gfree(CHRRAM); FCEU_gfree(CHRRAM);
CHRRAM = NULL; CHRRAM = NULL;
@ -67,7 +67,7 @@ static void StateRestore(int version) {
void Mapper168_Init(CartInfo *info) { void Mapper168_Init(CartInfo *info) {
info->Power = M168Power; info->Power = M168Power;
info->Close = MNNNClose; info->Close = M168Close;
GameStateRestore = StateRestore; GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0); AddExState(&StateRegs, ~0, 0, 0);

View File

@ -29,6 +29,12 @@ static uint8 reg[4];
static uint8 *WRAM = NULL; static uint8 *WRAM = NULL;
static uint32 WRAMSIZE; static uint32 WRAMSIZE;
// Tennis with VR sensor, very simple behaviour
extern void GetMouseData(uint32 (&md)[3]);
static uint32 MouseData[3], click, lastclick;
static int32 SensorDelay;
// highly experimental, not actually working, just curious if it hapen to work with some other decoder
// SND Registers // SND Registers
static uint8 pcm_enable = 0; static uint8 pcm_enable = 0;
static int16 pcm_latch = 0x3F6, pcm_clock = 0x3F6; static int16 pcm_latch = 0x3F6, pcm_clock = 0x3F6;
@ -40,41 +46,41 @@ static SFORMAT StateRegs[] =
{ 0 } { 0 }
}; };
static int16 step_size[49] = { //static int16 step_size[49] = {
16, 17, 19, 21, 23, 25, 28, 31, 34, 37, // 16, 17, 19, 21, 23, 25, 28, 31, 34, 37,
41, 45, 50, 55, 60, 66, 73, 80, 88, 97, // 41, 45, 50, 55, 60, 66, 73, 80, 88, 97,
107, 118, 130, 143, 157, 173, 190, 209, 230, 253, // 107, 118, 130, 143, 157, 173, 190, 209, 230, 253,
279, 307, 337, 371, 408, 449, 494, 544, 598, 658, // 279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552 // 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
}; //49 items //}; //49 items
static int32 step_adj[16] = { -1, -1, -1, -1, 2, 5, 7, 9, -1, -1, -1, -1, 2, 5, 7, 9 }; //static int32 step_adj[16] = { -1, -1, -1, -1, 2, 5, 7, 9, -1, -1, -1, -1, 2, 5, 7, 9 };
//decode stuff //decode stuff
static int32 jedi_table[16 * 49]; //static int32 jedi_table[16 * 49];
static int32 acc = 0; //ADPCM accumulator, initial condition must be 0 //static int32 acc = 0; //ADPCM accumulator, initial condition must be 0
static int32 decstep = 0; //ADPCM decoding step, initial condition must be 0 //static int32 decstep = 0; //ADPCM decoding step, initial condition must be 0
static void jedi_table_init() { //static void jedi_table_init() {
int step, nib; // int step, nib;
//
// for (step = 0; step < 49; step++) {
// for (nib = 0; nib < 16; nib++) {
// int value = (2 * (nib & 0x07) + 1) * step_size[step] / 8;
// jedi_table[step * 16 + nib] = ((nib & 0x08) != 0) ? -value : value;
// }
// }
//}
for (step = 0; step < 49; step++) { //static uint8 decode(uint8 code) {
for (nib = 0; nib < 16; nib++) { // acc += jedi_table[decstep + code];
int value = (2 * (nib & 0x07) + 1) * step_size[step] / 8; // if ((acc & ~0x7ff) != 0) // acc is > 2047
jedi_table[step * 16 + nib] = ((nib & 0x08) != 0) ? -value : value; // acc |= ~0xfff;
} // else acc &= 0xfff;
} // decstep += step_adj[code & 7] * 16;
} // if (decstep < 0) decstep = 0;
// if (decstep > 48 * 16) decstep = 48 * 16;
static uint8 decode(uint8 code) { // return (acc >> 8) & 0xff;
acc += jedi_table[decstep + code]; //}
if ((acc & ~0x7ff) != 0) // acc is > 2047
acc |= ~0xfff;
else acc &= 0xfff;
decstep += step_adj[code & 7] * 16;
if (decstep < 0) decstep = 0;
if (decstep > 48 * 16) decstep = 48 * 16;
return (acc >> 8) & 0xff;
}
static void Sync(void) { static void Sync(void) {
uint32 sbank = reg[1] & 0x7; uint32 sbank = reg[1] & 0x7;
@ -109,11 +115,11 @@ static DECLFW(M178WriteSnd) {
if (V & 0xF0) { if (V & 0xF0) {
pcm_enable = 1; pcm_enable = 1;
// pcmwrite(0x4011, (V & 0xF) << 3); // pcmwrite(0x4011, (V & 0xF) << 3);
pcmwrite(0x4011, decode(V & 0xf)); // pcmwrite(0x4011, decode(V & 0xf));
} else } else
pcm_enable = 0; pcm_enable = 0;
} else }// else
FCEU_printf("misc %04x:%02x\n", A, V); // FCEU_printf("misc %04x:%02x\n", A, V);
} }
static DECLFR(M178ReadSnd) { static DECLFR(M178ReadSnd) {
@ -123,13 +129,19 @@ static DECLFR(M178ReadSnd) {
return X.DB; return X.DB;
} }
static DECLFR(M178ReadSensor) {
X6502_IRQEnd(FCEU_IQEXT); // hacky-hacky, actual reg is 6000 and it clear IRQ while reading, but then I need another mapper lol
return 0x00;
}
static void M178Power(void) { static void M178Power(void) {
reg[0] = reg[1] = reg[2] = reg[3] = 0; reg[0] = reg[1] = reg[2] = reg[3] = SensorDelay = 0;
Sync(); Sync();
pcmwrite = GetWriteHandler(0x4011); // pcmwrite = GetWriteHandler(0x4011);
SetWriteHandler(0x4800, 0x4fff, M178Write); SetWriteHandler(0x4800, 0x4fff, M178Write);
SetWriteHandler(0x5800, 0x5fff, M178WriteSnd); SetWriteHandler(0x5800, 0x5fff, M178WriteSnd);
SetReadHandler(0x5800, 0x5fff, M178ReadSnd); SetReadHandler(0x5800, 0x5fff, M178ReadSnd);
SetReadHandler(0x5000, 0x5000, M178ReadSensor);
SetReadHandler(0x6000, 0x7fff, CartBR); SetReadHandler(0x6000, 0x7fff, CartBR);
SetWriteHandler(0x6000, 0x7fff, CartBW); SetWriteHandler(0x6000, 0x7fff, CartBW);
SetReadHandler(0x8000, 0xffff, CartBR); SetReadHandler(0x8000, 0xffff, CartBR);
@ -137,13 +149,25 @@ static void M178Power(void) {
} }
static void M178SndClk(int a) { static void M178SndClk(int a) {
if (pcm_enable) { SensorDelay += a;
pcm_latch -= a; if(SensorDelay > 0x32768) {
if (pcm_latch <= 0) { SensorDelay -= 32768;
pcm_latch += pcm_clock; GetMouseData (MouseData);
pcm_enable = 0; lastclick = click;
} click = MouseData[2] & 1; // to prevent from continuos IRQ trigger if button is held.
// actual circuit is just a D-C-R edge detector for IR-sensor
// triggered by the active IR bat.
if(lastclick && !click)
X6502_IRQBegin(FCEU_IQEXT);
} }
// if (pcm_enable) {
// pcm_latch -= a;
// if (pcm_latch <= 0) {
// pcm_latch += pcm_clock;
// pcm_enable = 0;
// }
// }
} }
static void M178Close(void) { static void M178Close(void) {
@ -162,7 +186,7 @@ void Mapper178_Init(CartInfo *info) {
GameStateRestore = StateRestore; GameStateRestore = StateRestore;
MapIRQHook = M178SndClk; MapIRQHook = M178SndClk;
jedi_table_init(); // jedi_table_init();
WRAMSIZE = 32768; WRAMSIZE = 32768;
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);

View File

@ -1,5 +1,5 @@
/* /*
Copyright (C) 2012 FCEUX team Copyright (C) 2012-2017 FCEUX team
This file is free software: you can redistribute it and/or modify This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -141,6 +141,7 @@ static DECLFW(WritePRG)
case 0x00: case 0x00:
chr = value & 3; chr = value & 3;
Mirror(value); Mirror(value);
Sync();
break; break;
case 0x01: case 0x01:
prg = value & 15; prg = value & 15;

View File

@ -22,11 +22,12 @@
#include "mapinc.h" #include "mapinc.h"
static uint8 latche; static uint8 latche, mirr;
static SFORMAT StateRegs[] = static SFORMAT StateRegs[] =
{ {
{ &latche, 1, "LATC" }, { &latche, 1, "LATC" },
{ &mirr, 1, "MIRR" },
{ 0 } { 0 }
}; };
@ -36,6 +37,11 @@ static void Sync(void) {
} }
static DECLFW(M36Write) { static DECLFW(M36Write) {
switch((A>>12)&7) { // need to 4-in-1 MGC-26 BMC, doesnt break other games though
case 0: mirr = MI_V; setmirror(mirr); break;
case 4: mirr = MI_H; setmirror(mirr); break;
}
latche = V; latche = V;
Sync(); Sync();
} }

View File

@ -41,7 +41,7 @@ static SFORMAT StateRegs[] =
static void Sync(void) { static void Sync(void) {
uint8 i; uint8 i;
if ((preg[3] & 0xC0) == 0xC0) if ((preg[3] & 0xC0) == 0xC0)
setprg8r(0x10, 0x6000, 0); setprg8r(0x10, 0x6000, preg[3] & 0x3F);
else else
setprg8(0x6000, preg[3] & 0x3F); setprg8(0x6000, preg[3] & 0x3F);
setprg8(0x8000, preg[0]); setprg8(0x8000, preg[0]);
@ -258,7 +258,10 @@ void Mapper69_Init(CartInfo *info) {
info->Power = M69Power; info->Power = M69Power;
info->Close = M69Close; info->Close = M69Close;
MapIRQHook = M69IRQHook; MapIRQHook = M69IRQHook;
WRAMSIZE = 8192; if(info->ines2)
WRAMSIZE = info->wram_size + info->battery_wram_size;
else
WRAMSIZE = 8192;
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM"); AddExState(WRAM, WRAMSIZE, 0, "WRAM");

View File

@ -303,14 +303,20 @@ static void M212Sync(void) {
} }
void Mapper212_Init(CartInfo *info) { void Mapper212_Init(CartInfo *info) {
Latch_Init(info, M212Sync, M212Read, 0xFFFF, 0x8000, 0xFFFF, 0); Latch_Init(info, M212Sync, M212Read, 0x0000, 0x8000, 0xFFFF, 0);
} }
//------------------ Map 213 --------------------------- //------------------ Map 213 ---------------------------
static void M213Sync(void) { static void M213Sync(void) {
setprg32(0x8000, (latche >> 1) & 3); if(latche & 0x40) {
setprg16(0x8000, (latche & 7));
setprg16(0xC000, (latche & 7));
} else {
setprg32(0x8000, (latche >> 1) & 3);
}
setchr8((latche >> 3) & 7); setchr8((latche >> 3) & 7);
setmirror(((latche & 1)^((latche >> 6) & 1)) ^ 1);
} }
void Mapper213_Init(CartInfo *info) { void Mapper213_Init(CartInfo *info) {

View File

@ -1,108 +1,146 @@
/* FCE Ultra - NES/Famicom Emulator /* FCE Ultra - NES/Famicom Emulator
* *
* Copyright notice for this file: * Copyright notice for this file:
* Copyright (C) 2015 CaH4e3 * Copyright (C) 2015 CaH4e3, ClusteR
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
* CoolBoy 400-in-1 FK23C-mimic mapper 16Mb/32Mb PROM + 128K/256K CHR RAM, optional SRAM, optional NTRAM * CoolBoy 400-in-1 FK23C-mimic mapper 16Mb/32Mb PROM + 128K/256K CHR RAM, optional SRAM, optional NTRAM
* only MMC3 mode * only MMC3 mode
* *
* 6000 (õõ76x210) | 0õÑ0 * 6000 (xx76x210) | 0xC0
* 6001 (õõõ354õõ) * 6001 (xxx354x)
* 6002 = 0 * 6002 = 0
* 6003 = 0 * 6003 = 0
* *
*/ * hardware tested logic, don't try to understand lol
*/
#include "mapinc.h"
#include "mmc3.h" #include "mapinc.h"
#include "mmc3.h"
static void COOLBOYCW(uint32 A, uint8 V) {
if(EXPREGS[3] & 0x10) static void COOLBOYCW(uint32 A, uint8 V) {
setchr8(EXPREGS[2] & 0xF); uint32 mask = 0xFF ^ (EXPREGS[0] & 0x80);
else { if (EXPREGS[3] & 0x10) {
uint32 mask = 0xFF; if (EXPREGS[3] & 0x40) { // Weird mode
switch(EXPREGS[0] & 0xC0) { int cbase = (MMC3_cmd & 0x80) << 5;
case 0xC0: switch (cbase ^ A) { // Don't even try do understand
mask = 0x7F; case 0x0400:
break; case 0x0C00: V &= 0x7F; break;
} }
setchr1(A, V & mask); }
} // Highest bit goes from MMC3 registers when EXPREGS[3]&0x80==0 or from EXPREGS[0]&0x08 otherwise
} setchr1(A,
(V & 0x80 & mask) | ((((EXPREGS[0] & 0x08) << 4) & ~mask)) // 7th bit
static void COOLBOYPW(uint32 A, uint8 V) { | ((EXPREGS[2] & 0x0F) << 3) // 6-3 bits
uint32 mask, shift; | ((A >> 10) & 7) // 2-0 bits
uint32 base = ((EXPREGS[0] & 0x07) >> 0) | ((EXPREGS[1] & 0x10) >> 1) | ((EXPREGS[1] & 0x0C) << 2) | ((EXPREGS[0] & 0x30) << 2); );
switch(EXPREGS[0] & 0xC0) { } else {
case 0x00: if (EXPREGS[3] & 0x40) { // Weird mode, again
mask = 0x3F; int cbase = (MMC3_cmd & 0x80) << 5;
break; switch (cbase ^ A) { // Don't even try do understand
case 0x80: case 0x0000: V = DRegBuf[0]; break;
mask = 0x1F; case 0x0800: V = DRegBuf[1]; break;
break; case 0x0400:
case 0xC0: case 0x0C00: V = 0; break;
if(EXPREGS[3] & 0x10) { }
mask = 0x01 | (EXPREGS[1] & 2); }
} else { // Simple MMC3 mode
mask = 0x0F; // Highest bit goes from MMC3 registers when EXPREGS[3]&0x80==0 or from EXPREGS[0]&0x08 otherwise
} setchr1(A, (V & mask) | (((EXPREGS[0] & 0x08) << 4) & ~mask));
break; }
} }
if(EXPREGS[3] & 0x10)
setprg8(A, (base << 4) | (V & mask) | ((EXPREGS[3] & (0x0E ^ (EXPREGS[1] & 2))) )); static void COOLBOYPW(uint32 A, uint8 V) {
else uint32 mask = ((0x3F | (EXPREGS[1] & 0x40) | ((EXPREGS[1] & 0x20) << 2)) ^ ((EXPREGS[0] & 0x40) >> 2)) ^ ((EXPREGS[1] & 0x80) >> 2);
setprg8(A, (base << 4) | (V & mask)); uint32 base = ((EXPREGS[0] & 0x07) >> 0) | ((EXPREGS[1] & 0x10) >> 1) | ((EXPREGS[1] & 0x0C) << 2) | ((EXPREGS[0] & 0x30) << 2);
}
// Very weird mode
static DECLFW(COOLBOYWrite) { // Last banks are first in this mode, ignored when MMC3_cmd&0x40
if(A001B & 0x80) if ((EXPREGS[3] & 0x40) && (V >= 0xFE) && !((MMC3_cmd & 0x40) != 0)) {
CartBW(A,V); switch (A & 0xE000) {
else case 0xA000:
if((EXPREGS[3] & 0x80) == 0) { if ((MMC3_cmd & 0x40)) V = 0;
EXPREGS[A & 3] = V; break;
FixMMC3PRG(MMC3_cmd); case 0xC000:
FixMMC3CHR(MMC3_cmd); if (!(MMC3_cmd & 0x40)) V = 0;
uint32 base = ((EXPREGS[0] & 0x07) >> 0) | ((EXPREGS[1] & 0x10) >> 1) | ((EXPREGS[1] & 0x0C) << 2) | ((EXPREGS[0] & 0x30) << 2); break;
FCEU_printf("exp %02x %02x (base %03d)\n",A,V,base); case 0xE000:
} V = 0;
} break;
}
static void COOLBOYReset(void) { }
MMC3RegReset();
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; // Regular MMC3 mode, internal ROM size can be up to 2048kb!
FixMMC3PRG(MMC3_cmd); if (!(EXPREGS[3] & 0x10))
FixMMC3CHR(MMC3_cmd); setprg8(A, (((base << 4) & ~mask)) | (V & mask));
} else { // NROM mode
mask &= 0xF0;
static void COOLBOYPower(void) { uint8 emask;
GenMMC3Power(); if ((((EXPREGS[1] & 2) != 0))) // 32kb mode
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; emask = (EXPREGS[3] & 0x0C) | ((A & 0x4000) >> 13);
FixMMC3PRG(MMC3_cmd); else // 16kb mode
FixMMC3CHR(MMC3_cmd); emask = EXPREGS[3] & 0x0E;
SetWriteHandler(0x5000, 0x5fff, CartBW); // some games access random unmapped areas and crashes because of KT-008 PCB hack in MMC3 source lol setprg8(A, ((base << 4) & ~mask) // 7-4 bits are from base (see below)
SetWriteHandler(0x6000, 0x6fff, COOLBOYWrite); | (V & mask) // ... or from MM3 internal regs, depends on mask
} | emask // 3-1 (or 3-2 when (EXPREGS[3]&0x0C is set) from EXPREGS[3]
| ((A & 0x2000) >> 13)); // 0th just as is
void COOLBOY_Init(CartInfo *info) { }
GenMMC3_Init(info, 512, 128, 8, 0); }
pwrap = COOLBOYPW;
cwrap = COOLBOYCW; static DECLFW(COOLBOYWrite) {
info->Power = COOLBOYPower; if(A001B & 0x80)
info->Reset = COOLBOYReset; CartBW(A,V);
AddExState(EXPREGS, 4, 0, "EXPR");
} // Deny any further writes when 7th bit is 1 AND 4th is 0
if ((EXPREGS[3] & 0x90) != 0x80) {
EXPREGS[A & 3] = V;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
}
static void COOLBOYReset(void) {
MMC3RegReset();
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
// EXPREGS[0] = 0;
// EXPREGS[1] = 0x60;
// EXPREGS[2] = 0;
// EXPREGS[3] = 0;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
static void COOLBOYPower(void) {
GenMMC3Power();
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
// EXPREGS[0] = 0;
// EXPREGS[1] = 0x60;
// EXPREGS[2] = 0;
// EXPREGS[3] = 0;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
SetWriteHandler(0x5000, 0x5fff, CartBW); // some games access random unmapped areas and crashes because of KT-008 PCB hack in MMC3 source lol
SetWriteHandler(0x6000, 0x7fff, COOLBOYWrite);
}
void COOLBOY_Init(CartInfo *info) {
GenMMC3_Init(info, 512, 256, 8, 0);
pwrap = COOLBOYPW;
cwrap = COOLBOYCW;
info->Power = COOLBOYPower;
info->Reset = COOLBOYReset;
AddExState(EXPREGS, 4, 0, "EXPR");
}

View File

@ -30,7 +30,7 @@ static void (*WSync)(void);
static DECLFW(LatchWrite) { static DECLFW(LatchWrite) {
// FCEU_printf("bs %04x %02x\n",A,V); // FCEU_printf("bs %04x %02x\n",A,V);
if (bus_conflict) if (bus_conflict)
latche = (V == CartBR(A)) ? V : 0; latche = V & CartBR(A);
else else
latche = V; latche = V;
WSync(); WSync();
@ -68,15 +68,58 @@ static void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 ad
info->Power = LatchPower; info->Power = LatchPower;
info->Close = LatchClose; info->Close = LatchClose;
GameStateRestore = StateRestore; GameStateRestore = StateRestore;
if (wram) { if(info->ines2)
WRAMSIZE = 8192; if(info->battery_wram_size + info->wram_size > 0)
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); wram = 1;
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); if (wram)
if (info->battery) { {
info->SaveGame[0] = WRAM; if(info->ines2)
info->SaveGameLen[0] = WRAMSIZE; {
//I would like to do it in this way, but FCEUX is woefully inadequate
//for instance if WRAMSIZE is large, the cheat pointers may get overwritten. and it's just a giant mess.
//WRAMSIZE = info->battery_wram_size + info->wram_size;
//WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
//if(!info->wram_size && !info->battery_wram_size) {}
//else if(info->wram_size && !info->battery_wram_size)
// SetupCartPRGMapping(0x10, WRAM, info->wram_size, 1);
//else if(!info->wram_size && info->battery_wram_size)
//{
// SetupCartPRGMapping(0x10, WRAM, info->battery_wram_size, 1);
// info->SaveGame[0] = WRAM;
// info->SaveGameLen[0] = info->battery_wram_size;
//} else {
// //well, this is annoying
// SetupCartPRGMapping(0x10, WRAM, info->wram_size, 1);
// SetupCartPRGMapping(0x11, WRAM, info->battery_wram_size, 1); //? ? ? there probably isnt even a way to select this
// info->SaveGame[0] = WRAM + info->wram_size;
// info->SaveGameLen[0] = info->battery_wram_size;
//}
//this is more likely the only practical scenario
WRAMSIZE = 8192;
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
SetReadHandler(0x6000, 0x7FFF, CartBR);
SetWriteHandler(0x6000, 0x7FFF, CartBW);
setprg8r(0x10, 0x6000, 0);
if(info->battery_wram_size)
{
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = 8192;
}
} }
AddExState(WRAM, WRAMSIZE, 0, "WRAM"); else
{
WRAMSIZE = 8192;
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
}
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
}
} }
AddExState(&latche, 1, 0, "LATC"); AddExState(&latche, 1, 0, "LATC");
AddExState(&bus_conflict, 1, 0, "BUSC"); AddExState(&bus_conflict, 1, 0, "BUSC");
@ -93,7 +136,7 @@ static DECLFW(NROMWrite) {
static void NROMPower(void) { static void NROMPower(void) {
setprg8r(0x10, 0x6000, 0); // Famili BASIC (v3.0) need it (uses only 4KB), FP-BASIC uses 8KB setprg8r(0x10, 0x6000, 0); // Famili BASIC (v3.0) need it (uses only 4KB), FP-BASIC uses 8KB
setprg16(0x8000, 0); setprg16(0x8000, ~1);
setprg16(0xC000, ~0); setprg16(0xC000, ~0);
setchr8(0); setchr8(0);
@ -101,7 +144,7 @@ static void NROMPower(void) {
SetWriteHandler(0x6000, 0x7FFF, CartBW); SetWriteHandler(0x6000, 0x7FFF, CartBW);
SetReadHandler(0x8000, 0xFFFF, CartBR); SetReadHandler(0x8000, 0xFFFF, CartBR);
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
#ifdef DEBUG_MAPPER #ifdef DEBUG_MAPPER
SetWriteHandler(0x4020, 0xFFFF, NROMWrite); SetWriteHandler(0x4020, 0xFFFF, NROMWrite);

View File

@ -1,24 +1,23 @@
#ifndef _EMU2413_H_ #ifndef _EMU2413_H_
#define _EMU2413_H_ #define _EMU2413_H_
#ifndef INLINE #ifndef INLINE
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define INLINE __forceinline #define INLINE __forceinline
#elif defined(__GNUC__) #elif defined(__GNUC__)
#define INLINE __inline__ #define INLINE __inline__
#elif defined(_MWERKS_) #elif defined(_MWERKS_)
#define INLINE inline #define INLINE inline
#else #else
#define INLINE #define INLINE
#endif #endif
#endif #endif
#include <stdint.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#ifdef GEKKO
typedef uint8_t uint8 ; typedef uint8_t uint8 ;
typedef int8_t int8 ; typedef int8_t int8 ;
@ -27,6 +26,16 @@ typedef int16_t int16 ;
typedef uint32_t uint32 ; typedef uint32_t uint32 ;
typedef int32_t int32 ; typedef int32_t int32 ;
#else
typedef unsigned char uint8 ;
typedef signed char int8 ;
typedef unsigned short uint16 ;
typedef signed short int16 ;
typedef unsigned int uint32 ;
typedef signed int int32 ;
#endif
#define PI 3.14159265358979323846 #define PI 3.14159265358979323846

View File

@ -70,7 +70,7 @@ static void SSSNROMPower(void) {
regs[0] = regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0; regs[0] = regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0;
regs[7] = 0xff; regs[7] = 0xff;
Sync(); Sync();
memset(WRAM, 0x00, WRAMSIZE); FCEU_MemoryRand(WRAM, WRAMSIZE, true);
// SetWriteHandler(0x0000,0x1FFF,SSSNROMRamWrite); // SetWriteHandler(0x0000,0x1FFF,SSSNROMRamWrite);
SetReadHandler(0x0800, 0x1FFF, CartBR); SetReadHandler(0x0800, 0x1FFF, CartBR);
SetWriteHandler(0x0800, 0x1FFF, CartBW); SetWriteHandler(0x0800, 0x1FFF, CartBW);

View File

@ -30,26 +30,22 @@ static uint32 CHRRAMSize;
static void BMCFK23CCW(uint32 A, uint8 V) static void BMCFK23CCW(uint32 A, uint8 V)
{ {
if(EXPREGS[0]&0x40) if(EXPREGS[0]&0x40)
setchr8(EXPREGS[2]|unromchr); setchr8(EXPREGS[2]|unromchr);
else if(EXPREGS[0]&0x20) { else if(EXPREGS[0]&0x20) {
setchr1r(0x10, A, V); setchr1r(0x10, A, V);
} } else {
else uint16 base=(EXPREGS[2]&0x7F)<<3;
{ if(EXPREGS[3]&2) {
uint16 base=(EXPREGS[2]&0x7F)<<3; int cbase=(MMC3_cmd&0x80)<<5;
if(EXPREGS[3]&2) setchr1(A,V|base);
{ setchr1(0x0000^cbase,DRegBuf[0]|base);
int cbase=(MMC3_cmd&0x80)<<5; setchr1(0x0400^cbase,EXPREGS[6]|base);
setchr1(A,V|base); setchr1(0x0800^cbase,DRegBuf[1]|base);
setchr1(0x0000^cbase,DRegBuf[0]|base); setchr1(0x0c00^cbase,EXPREGS[7]|base);
setchr1(0x0400^cbase,EXPREGS[6]|base); } else
setchr1(0x0800^cbase,DRegBuf[1]|base); setchr1(A,V|base);
setchr1(0x0c00^cbase,EXPREGS[7]|base); }
}
else
setchr1(A,V|base);
}
} }
//some games are wired differently, and this will need to be changed. //some games are wired differently, and this will need to be changed.
@ -86,110 +82,110 @@ static int prg_mask;
//PRG wrapper //PRG wrapper
static void BMCFK23CPW(uint32 A, uint8 V) static void BMCFK23CPW(uint32 A, uint8 V)
{ {
uint32 bank = (EXPREGS[1] & 0x1F); uint32 bank = (EXPREGS[1] & 0x1F);
uint32 hiblock = ((EXPREGS[0] & 8) << 4)|((EXPREGS[0] & 0x80) << 1)|(UNIFchrrama?((EXPREGS[2] & 0x40)<<3):0); uint32 hiblock = ((EXPREGS[0] & 8) << 4)|((EXPREGS[0] & 0x80) << 1)|(UNIFchrrama?((EXPREGS[2] & 0x40)<<3):0);
uint32 block = (EXPREGS[1] & 0x60) | hiblock; uint32 block = (EXPREGS[1] & 0x60) | hiblock;
uint32 extra = (EXPREGS[3] & 2); uint32 extra = (EXPREGS[3] & 2);
// FCEU_printf("0:%04X:%02X\n",A,V);
if((EXPREGS[0]&7)==4) if((EXPREGS[0]&7)==4)
setprg32(0x8000,EXPREGS[1]>>1); setprg32(0x8000,EXPREGS[1]>>1);
else if ((EXPREGS[0]&7)==3) else if ((EXPREGS[0]&7)==3) {
{ setprg16(0x8000,EXPREGS[1]);
setprg16(0x8000,EXPREGS[1]); setprg16(0xC000,EXPREGS[1]);
setprg16(0xC000,EXPREGS[1]); } else {
} if(EXPREGS[0]&3) {
else
{
if(EXPREGS[0]&3)
{
uint32 blocksize = (6)-(EXPREGS[0]&3); uint32 blocksize = (6)-(EXPREGS[0]&3);
uint32 mask = (1<<blocksize)-1; uint32 mask = (1<<blocksize)-1;
V &= mask; V &= mask;
//V &= 63; //? is this a good idea? //V &= 63; //? is this a good idea?
V |= (EXPREGS[1]<<1); V |= (EXPREGS[1]<<1);
setprg8(A,V); // FCEU_printf("1:%04X:%02X\n",A,V);
setprg8(A,V);
} else {
setprg8(A,V & prg_mask);
// FCEU_printf("2:%04X:%02X\n",A,V);
} }
else
setprg8(A,V & prg_mask);
if(EXPREGS[3]&2) if(EXPREGS[3]&2) {
{ setprg8(0xC000,EXPREGS[4]);
setprg8(0xC000,EXPREGS[4]); setprg8(0xE000,EXPREGS[5]);
setprg8(0xE000,EXPREGS[5]); }
} }
}
setprg8r(0x10,0x6000,A001B&3); setprg8r(0x10,0x6000,A001B&3);
} }
//PRG handler ($8000-$FFFF) //PRG handler ($8000-$FFFF)
static DECLFW(BMCFK23CHiWrite) static DECLFW(BMCFK23CHiWrite)
{ {
if(EXPREGS[0]&0x40) // FCEU_printf("K4:(exp0=%02x)\n",EXPREGS[0]);
{ // FCEU_printf("W0:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
if((EXPREGS[0]&0x60)==0x40) {
// FCEU_printf("W2:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
if(EXPREGS[0]&0x30) if(EXPREGS[0]&0x30)
unromchr=0; unromchr=0;
else else {
{
unromchr=V&3; unromchr=V&3;
FixMMC3CHR(MMC3_cmd); FixMMC3CHR(MMC3_cmd);
} }
} } else {
else if((A==0x8001)&&(EXPREGS[3]&2)&&(MMC3_cmd&8)) {
{ // FCEU_printf("W3:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
if((A==0x8001)&&(EXPREGS[3]&2&&MMC3_cmd&8))
{
EXPREGS[4|(MMC3_cmd&3)]=V; EXPREGS[4|(MMC3_cmd&3)]=V;
FixMMC3PRG(MMC3_cmd); FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd); FixMMC3CHR(MMC3_cmd);
} } else
else if(A<0xC000) {
if(A<0xC000) { if(UNIFchrrama) { // hacky... strange behaviour, must be bit scramble due to pcb layot restrictions
if(UNIFchrrama) { // hacky... strange behaviour, must be bit scramble due to pcb layot restrictions // check if it not interfer with other dumps
// check if it not interfer with other dumps if((A==0x8000)&&(V==0x46))
if((A==0x8000)&&(V==0x46)) V=0x47;
V=0x47; else if((A==0x8000)&&(V==0x47))
else if((A==0x8000)&&(V==0x47)) V=0x46;
V=0x46; }
} // FCEU_printf("W1:%04X:%02X\n",A,V);
MMC3_CMDWrite(A,V); MMC3_CMDWrite(A,V);
FixMMC3PRG(MMC3_cmd); FixMMC3PRG(MMC3_cmd);
} } else {
else MMC3_IRQWrite(A,V);
MMC3_IRQWrite(A,V); // FCEU_printf("W4:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
} }
}
} }
//EXP handler ($5000-$5FFF) //EXP handler ($5000-$5FFF)
static DECLFW(BMCFK23CWrite) static DECLFW(BMCFK23CWrite)
{ {
if(A&(1<<(dipswitch+4))) if(A&(1<<(dipswitch+4))) {
{
//printf("+ "); //printf("+ ");
EXPREGS[A&3]=V; EXPREGS[A&3]=V;
// BUT WHY is there any rom that need it actually?
bool remap = false; bool remap = false;
// FCEU_printf("K3:(exp0=%02x)\n",EXPREGS[0]);
// FCEU_printf("WH0:%04X:%02X\n",A,V);
//sometimes writing to reg0 causes remappings to occur. we think the 2 signifies this. //sometimes writing to reg0 causes remappings to occur. we think the 2 signifies this.
//if not, 0x24 is a value that is known to work //if not, 0x24 is a value that is known to work
//however, the low 4 bits are known to control the mapping mode, so 0x20 is more likely to be the immediate remap flag //however, the low 4 bits are known to control the mapping mode, so 0x20 is more likely to be the immediate remap flag
remap |= ((EXPREGS[0]&0xF0)==0x20); // remap |= ((EXPREGS[0]&0xF0)==0x20);
//this is an actual mapping reg. i think reg0 controls what happens when reg1 is written. anyway, we have to immediately remap these //this is an actual mapping reg. i think reg0 controls what happens when reg1 is written. anyway, we have to immediately remap these
remap |= (A&3)==1; // remap |= (A&3)==1;
//this too. //this too.
remap |= (A&3)==2; // remap |= (A&3)==2;
if(remap) // if(remap) {
{ // FCEU_printf("WH1:%04X:%02X\n",A,V);
FixMMC3PRG(MMC3_cmd); FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd); FixMMC3CHR(MMC3_cmd);
} // }
} }
if(is_BMCFK23CA) if(is_BMCFK23CA) {
{
if(EXPREGS[3]&2) if(EXPREGS[3]&2)
EXPREGS[0] &= ~7; // hacky hacky! if someone wants extra banking, then for sure doesn't want mode 4 for it! (allow to run A version boards on normal mapper) // FCEU_printf("EXTRA!\n",A);
EXPREGS[0] &= ~7; // hacky hacky! if someone wants extra banking, then for sure doesn't want mode 4 for it! (allow to run A version boards on normal mapper)
} }
//printf("%04X = $%02X\n",A,V); //printf("%04X = $%02X\n",A,V);
@ -199,62 +195,65 @@ static DECLFW(BMCFK23CWrite)
static void BMCFK23CReset(void) static void BMCFK23CReset(void)
{ {
//NOT NECESSARY ANYMORE //NOT NECESSARY ANYMORE
// BUT WHY?
//this little hack makes sure that we try all the dip switch settings eventually, if we reset enough //this little hack makes sure that we try all the dip switch settings eventually, if we reset enough
// dipswitch++; dipswitch++;
// dipswitch&=7; dipswitch&=7;
//printf("BMCFK23C dipswitch set to %d\n",dipswitch); printf("BMCFK23C dipswitch set to %d\n",dipswitch);
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0; EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF; EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
MMC3RegReset(); // FCEU_printf("K0:(exp0=%02x)\n",EXPREGS[0]);
FixMMC3PRG(MMC3_cmd); MMC3RegReset();
FixMMC3CHR(MMC3_cmd); FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
} }
static void BMCFK23CPower(void) static void BMCFK23CPower(void)
{ {
GenMMC3Power();
dipswitch = 0; dipswitch = 0;
GenMMC3Power(); EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0; EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF; // FCEU_printf("K1:(exp0=%02x)\n",EXPREGS[0]);
GenMMC3Power(); FixMMC3PRG(MMC3_cmd);
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite); FixMMC3CHR(MMC3_cmd);
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite); SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
FixMMC3PRG(MMC3_cmd); SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
FixMMC3CHR(MMC3_cmd);
} }
static void BMCFK23CAPower(void) static void BMCFK23CAPower(void)
{ {
GenMMC3Power(); GenMMC3Power();
dipswitch = 0; dipswitch = 0;
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0; EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF; EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite); // FCEU_printf("K2:(exp0=%02x)\n",EXPREGS[0]);
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite); FixMMC3PRG(MMC3_cmd);
FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd);
FixMMC3CHR(MMC3_cmd); SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
} }
static void BMCFK23CAClose(void) static void BMCFK23CAClose(void)
{ {
if(CHRRAM) if(CHRRAM)
FCEU_gfree(CHRRAM); FCEU_gfree(CHRRAM);
CHRRAM=NULL; CHRRAM=NULL;
} }
void BMCFK23C_Init(CartInfo *info) void BMCFK23C_Init(CartInfo *info)
{ {
is_BMCFK23CA = false; is_BMCFK23CA = false;
GenMMC3_Init(info, 512, 256, 8, 0); GenMMC3_Init(info, 512, 256, 8, 0);
cwrap=BMCFK23CCW; cwrap=BMCFK23CCW;
pwrap=BMCFK23CPW; pwrap=BMCFK23CPW;
info->Power=BMCFK23CPower; info->Power=BMCFK23CPower;
info->Reset=BMCFK23CReset; info->Reset=BMCFK23CReset;
AddExState(EXPREGS, 8, 0, "EXPR"); AddExState(EXPREGS, 8, 0, "EXPR");
AddExState(&unromchr, 1, 0, "UCHR"); AddExState(&unromchr, 1, 0, "UCHR");
AddExState(&dipswitch, 1, 0, "DPSW"); AddExState(&dipswitch, 1, 0, "DPSW");
prg_bonus = 1; prg_bonus = 1;
if(MasterRomInfoParams.find("bonus") != MasterRomInfoParams.end()) if(MasterRomInfoParams.find("bonus") != MasterRomInfoParams.end())
@ -267,21 +266,21 @@ void BMCFK23CA_Init(CartInfo *info)
{ {
is_BMCFK23CA = true; is_BMCFK23CA = true;
GenMMC3_Init(info, 512, 256, 8, 0); GenMMC3_Init(info, 512, 256, 8, 0);
cwrap=BMCFK23CCW; cwrap=BMCFK23CCW;
pwrap=BMCFK23CPW; pwrap=BMCFK23CPW;
info->Power=BMCFK23CAPower; info->Power=BMCFK23CAPower;
info->Reset=BMCFK23CReset; info->Reset=BMCFK23CReset;
info->Close=BMCFK23CAClose; info->Close=BMCFK23CAClose;
CHRRAMSize=8192; CHRRAMSize=8192;
CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize); CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
AddExState(CHRRAM, CHRRAMSize, 0, "CRAM"); AddExState(CHRRAM, CHRRAMSize, 0, "CRAM");
AddExState(EXPREGS, 8, 0, "EXPR"); AddExState(EXPREGS, 8, 0, "EXPR");
AddExState(&unromchr, 1, 0, "UCHR"); AddExState(&unromchr, 1, 0, "UCHR");
AddExState(&dipswitch, 1, 0, "DPSW"); AddExState(&dipswitch, 1, 0, "DPSW");
prg_bonus = 1; prg_bonus = 1;
if(MasterRomInfoParams.find("bonus") != MasterRomInfoParams.end()) if(MasterRomInfoParams.find("bonus") != MasterRomInfoParams.end())

View File

@ -18,45 +18,45 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "mapinc.h" #include "mapinc.h"
static uint8 regs[8]; static uint8 regs[8];
static SFORMAT StateRegs[] = static SFORMAT StateRegs[] =
{ {
{ regs, 8, "REGS" }, { regs, 8, "REGS" },
{ 0 } { 0 }
}; };
static void Sync(void) { static void Sync(void) {
for (int i=0; i < 8; ++i) for (int i=0; i < 8; ++i)
{ {
setprg4(0x8000 + (0x1000 * i), regs[i]); setprg4(0x8000 + (0x1000 * i), regs[i]);
} }
} }
static DECLFW(M31Write) { static DECLFW(M31Write) {
if (A >= 0x5000 && A <= 0x5FFF) if (A >= 0x5000 && A <= 0x5FFF)
{ {
regs[A&7] = V; regs[A&7] = V;
Sync(); Sync();
} }
} }
static void M31Power(void) { static void M31Power(void) {
setchr8(0); setchr8(0);
regs[7] = 0xFF; regs[7] = 0xFF;
Sync(); Sync();
SetReadHandler(0x8000, 0xffff, CartBR); SetReadHandler(0x8000, 0xffff, CartBR);
SetWriteHandler(0x5000, 0x5fff, M31Write); SetWriteHandler(0x5000, 0x5fff, M31Write);
} }
static void StateRestore(int version) { static void StateRestore(int version) {
Sync(); Sync();
} }
void Mapper31_Init(CartInfo *info) { void Mapper31_Init(CartInfo *info) {
info->Power = M31Power; info->Power = M31Power;
GameStateRestore = StateRestore; GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0); AddExState(&StateRegs, ~0, 0, 0);
} }

View File

@ -1,85 +1,85 @@
/* FCE Ultra - NES/Famicom Emulator /* FCE Ultra - NES/Famicom Emulator
* *
* Copyright notice for this file: * Copyright notice for this file:
* Copyright (C) 2007 CaH4e3 * Copyright (C) 2007 CaH4e3
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "mapinc.h" #include "mapinc.h"
static uint8 preg[4], creg, mirr; static uint8 preg[4], creg, mirr;
static SFORMAT StateRegs[] = static SFORMAT StateRegs[] =
{ {
{ preg, 4, "PREG" }, { preg, 4, "PREG" },
{ &creg, 1, "CREG" }, { &creg, 1, "CREG" },
{ &mirr, 1, "MIRR" }, { &mirr, 1, "MIRR" },
{ 0 } { 0 }
}; };
static void Sync(void) { static void Sync(void) {
setprg8(0x6000, preg[0]); setprg8(0x6000, preg[0]);
setprg8(0x8000, 0xa); setprg8(0x8000, 0xa);
setprg8(0xa000, 0xb); setprg8(0xa000, 0xb);
setprg8(0xc000, 0x6); setprg8(0xc000, 0x6);
setprg8(0xe000, 0x7); setprg8(0xe000, 0x7);
setchr8(0x0c); setchr8(0x0c);
setmirror(mirr); setmirror(mirr);
} }
static DECLFW(UNLKS7010Write) { static DECLFW(UNLKS7010Write) {
switch (A) { switch (A) {
case 0x4025: mirr = (((V >> 3) & 1) ^ 1); Sync(); break; case 0x4025: mirr = (((V >> 3) & 1) ^ 1); Sync(); break;
default: default:
FCEU_printf("bs %04x %02x\n",A,V); FCEU_printf("bs %04x %02x\n",A,V);
break; break;
} }
} }
static void UNLKS7010Reset(void) { static void UNLKS7010Reset(void) {
preg[0]++; preg[0]++;
if(preg[0] == 0x10) { if(preg[0] == 0x10) {
preg[0] = 0; preg[0] = 0;
preg[1]++; preg[1]++;
if(preg[1] == 0x10) { if(preg[1] == 0x10) {
preg[1] = 0; preg[1] = 0;
preg[2]++; preg[2]++;
} }
} }
FCEU_printf("preg %02x %02x %02x\n",preg[0], preg[1], preg[2]); FCEU_printf("preg %02x %02x %02x\n",preg[0], preg[1], preg[2]);
Sync(); Sync();
} }
static void UNLKS7010Power(void) { static void UNLKS7010Power(void) {
preg[0] = preg[1] = preg[2] = 0; preg[0] = preg[1] = preg[2] = 0;
Sync(); Sync();
SetReadHandler(0x6000, 0x7fff, CartBR); SetReadHandler(0x6000, 0x7fff, CartBR);
SetWriteHandler(0x6000, 0x7fff, CartBW); SetWriteHandler(0x6000, 0x7fff, CartBW);
SetReadHandler(0x8000, 0xffff, CartBR); SetReadHandler(0x8000, 0xffff, CartBR);
SetWriteHandler(0x4020, 0xffff, UNLKS7010Write); SetWriteHandler(0x4020, 0xffff, UNLKS7010Write);
} }
static void StateRestore(int version) { static void StateRestore(int version) {
Sync(); Sync();
} }
void UNLKS7010_Init(CartInfo *info) { void UNLKS7010_Init(CartInfo *info) {
info->Power = UNLKS7010Power; info->Power = UNLKS7010Power;
info->Reset = UNLKS7010Reset; info->Reset = UNLKS7010Reset;
GameStateRestore = StateRestore; GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0); AddExState(&StateRegs, ~0, 0, 0);
} }

View File

@ -35,6 +35,7 @@ static void MALEEPower(void) {
void MALEE_Init(CartInfo *info) { void MALEE_Init(CartInfo *info) {
info->Power = MALEEPower; info->Power = MALEEPower;
FCEU_MemoryRand(WRAM,sizeof(WRAM),true);
SetupCartPRGMapping(0x10, WRAM, 2048, 1); SetupCartPRGMapping(0x10, WRAM, 2048, 1);
AddExState(WRAM, 2048, 0, "WRAM"); AddExState(WRAM, 2048, 0, "WRAM");
} }

View File

@ -1,68 +1,68 @@
/* FCE Ultra - NES/Famicom Emulator /* FCE Ultra - NES/Famicom Emulator
* *
* Copyright notice for this file: * Copyright notice for this file:
* Copyright (C) 2013 CaH4e3 * Copyright (C) 2013 CaH4e3
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "mapinc.h" #include "mapinc.h"
static uint16 latche; static uint16 latche;
static SFORMAT StateRegs[] = static SFORMAT StateRegs[] =
{ {
{ &latche, 2, "LATC" }, { &latche, 2, "LATC" },
{ 0 } { 0 }
}; };
static void Sync(void) { static void Sync(void) {
setprg32(0x8000, 0); setprg32(0x8000, 0);
if(CHRsize[0] == 8192) { if(CHRsize[0] == 8192) {
setchr4(0x0000, latche & 1); setchr4(0x0000, latche & 1);
setchr4(0x1000, latche & 1); setchr4(0x1000, latche & 1);
} else { } else {
setchr8(latche & 1); // actually, my bad, overdumped roms, the real CHR size if 8K setchr8(latche & 1); // actually, my bad, overdumped roms, the real CHR size if 8K
} }
setmirror(MI_0 + (latche & 1)); setmirror(MI_0 + (latche & 1));
} }
static DECLFW(UNLCC21Write1) { static DECLFW(UNLCC21Write1) {
latche = A; latche = A;
Sync(); Sync();
} }
static DECLFW(UNLCC21Write2) { static DECLFW(UNLCC21Write2) {
latche = V; latche = V;
Sync(); Sync();
} }
static void UNLCC21Power(void) { static void UNLCC21Power(void) {
latche = 0; latche = 0;
Sync(); Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR); SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8001, 0xFFFF, UNLCC21Write1); SetWriteHandler(0x8001, 0xFFFF, UNLCC21Write1);
SetWriteHandler(0x8000, 0x8000, UNLCC21Write2); // another one many-in-1 mapper, there is a lot of similar carts with little different wirings SetWriteHandler(0x8000, 0x8000, UNLCC21Write2); // another one many-in-1 mapper, there is a lot of similar carts with little different wirings
} }
static void StateRestore(int version) { static void StateRestore(int version) {
Sync(); Sync();
} }
void UNLCC21_Init(CartInfo *info) { void UNLCC21_Init(CartInfo *info) {
info->Power = UNLCC21Power; info->Power = UNLCC21Power;
GameStateRestore = StateRestore; GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0); AddExState(&StateRegs, ~0, 0, 0);
} }

View File

@ -22,12 +22,13 @@
#include "mapinc.h" #include "mapinc.h"
static void GenMMC1Power(void); static void GenMMC1Power(void);
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery); static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int bram);
static uint8 DRegs[4]; static uint8 DRegs[4];
static uint8 Buffer, BufferShift; static uint8 Buffer, BufferShift;
static int mmc1opts; static uint32 WRAMSIZE;
static uint32 NONBRAMSIZE; // size of non-battery-backed portion of WRAM
static void (*MMC1CHRHook4)(uint32 A, uint8 V); static void (*MMC1CHRHook4)(uint32 A, uint8 V);
static void (*MMC1PRGHook16)(uint32 A, uint8 V); static void (*MMC1PRGHook16)(uint32 A, uint8 V);
@ -48,9 +49,9 @@ static DECLFR(MAWRAM) {
} }
static void MMC1CHR(void) { static void MMC1CHR(void) {
if (mmc1opts & 4) { if (WRAMSIZE > 0x2000) {
if (DRegs[0] & 0x10) if (WRAMSIZE > 0x4000)
setprg8r(0x10, 0x6000, (DRegs[1] >> 4) & 1); setprg8r(0x10, 0x6000, (DRegs[1] >> 2) & 3);
else else
setprg8r(0x10, 0x6000, (DRegs[1] >> 3) & 1); setprg8r(0x10, 0x6000, (DRegs[1] >> 3) & 1);
} }
@ -73,37 +74,38 @@ static void MMC1CHR(void) {
} }
static void MMC1PRG(void) { static void MMC1PRG(void) {
uint8 offs = DRegs[1] & 0x10; uint8 offs_16banks = DRegs[1] & 0x10;
uint8 prg_reg = DRegs[3] & 0xF; //homebrewers arent allowed to use more banks on MMC1. use another mapper.
if (MMC1PRGHook16) { if (MMC1PRGHook16) {
switch (DRegs[0] & 0xC) { switch (DRegs[0] & 0xC) {
case 0xC: case 0xC:
MMC1PRGHook16(0x8000, (DRegs[3] + offs)); MMC1PRGHook16(0x8000, (prg_reg + offs_16banks));
MMC1PRGHook16(0xC000, 0xF + offs); MMC1PRGHook16(0xC000, 0xF + offs_16banks);
break; break;
case 0x8: case 0x8:
MMC1PRGHook16(0xC000, (DRegs[3] + offs)); MMC1PRGHook16(0xC000, (prg_reg + offs_16banks));
MMC1PRGHook16(0x8000, offs); MMC1PRGHook16(0x8000, offs_16banks);
break; break;
case 0x0: case 0x0:
case 0x4: case 0x4:
MMC1PRGHook16(0x8000, ((DRegs[3] & ~1) + offs)); MMC1PRGHook16(0x8000, ((prg_reg & ~1) + offs_16banks));
MMC1PRGHook16(0xc000, ((DRegs[3] & ~1) + offs + 1)); MMC1PRGHook16(0xc000, ((prg_reg & ~1) + offs_16banks + 1));
break; break;
} }
} else { } else {
switch (DRegs[0] & 0xC) { switch (DRegs[0] & 0xC) {
case 0xC: case 0xC:
setprg16(0x8000, (DRegs[3] + offs)); setprg16(0x8000, (prg_reg + offs_16banks));
setprg16(0xC000, 0xF + offs); setprg16(0xC000, 0xF + offs_16banks);
break; break;
case 0x8: case 0x8:
setprg16(0xC000, (DRegs[3] + offs)); setprg16(0xC000, (prg_reg + offs_16banks));
setprg16(0x8000, offs); setprg16(0x8000, offs_16banks);
break; break;
case 0x0: case 0x0:
case 0x4: case 0x4:
setprg16(0x8000, ((DRegs[3] & ~1) + offs)); setprg16(0x8000, ((prg_reg & ~1) + offs_16banks));
setprg16(0xc000, ((DRegs[3] & ~1) + offs + 1)); setprg16(0xc000, ((prg_reg & ~1) + offs_16banks + 1));
break; break;
} }
} }
@ -178,20 +180,39 @@ static void MMC1CMReset(void) {
MMC1PRG(); MMC1PRG();
} }
static int DetectMMC1WRAMSize(uint32 crc32) { static int DetectMMC1WRAMSize(CartInfo *info, int *bs) {
switch (crc32) { int ws = 8;
switch (info->CRC32) {
case 0xc6182024: // Romance of the 3 Kingdoms case 0xc6182024: // Romance of the 3 Kingdoms
case 0xabbf7217: // "" "" (J) (PRG0)
case 0xccf35c02: // "" "" (J) (PRG1)
case 0x2225c20f: // Genghis Khan case 0x2225c20f: // Genghis Khan
case 0xfb69743a: // "" "" (J)
case 0x4642dda6: // Nobunaga's Ambition case 0x4642dda6: // Nobunaga's Ambition
case 0x29449ba9: // "" "" (J) case 0x3f7ad415: // "" "" (J) (PRG0)
case 0x2b11e0b0: // "" "" (J) case 0x2b11e0b0: // "" "" (J) (PRG1)
case 0xb8747abf: // Best Play Pro Yakyuu Special (J) *bs = 8;
case 0xc9556b36: // Final Fantasy I & II (J) [!] ws = 16;
FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n");
return(16);
break; break;
default: return(8); case 0xb8747abf: // Best Play Pro Yakyuu Special (J) (PRG0)
case 0xc3de7c69: // "" "" (J) (PRG1)
case 0xc9556b36: // Final Fantasy I & II (J) [!]
*bs = 32;
ws = 32;
break;
default:
if(info->ines2) {
ws = (info->wram_size + info->battery_wram_size) / 1024;
*bs = info->battery_wram_size / 1024;
// we only support sizes between 8K and 32K
if (ws > 0 && ws < 8) ws = 8;
if (ws > 32) ws = 32;
if (*bs > ws) *bs = ws;
}
} }
if (ws > 8)
FCEU_printf(" >8KB external WRAM present. Use NES 2.0 if you hack the ROM image.\n");
return ws;
} }
static uint32 NWCIRQCount; static uint32 NWCIRQCount;
@ -243,17 +264,16 @@ void Mapper105_Init(CartInfo *info) {
static void GenMMC1Power(void) { static void GenMMC1Power(void) {
lreset = 0; lreset = 0;
if (mmc1opts & 1) {
FCEU_CheatAddRAM(8, 0x6000, WRAM);
if (mmc1opts & 4)
FCEU_dwmemset(WRAM, 0, 8192)
else if (!(mmc1opts & 2))
FCEU_dwmemset(WRAM, 0, 8192); // wtf?
}
SetWriteHandler(0x8000, 0xFFFF, MMC1_write); SetWriteHandler(0x8000, 0xFFFF, MMC1_write);
SetReadHandler(0x8000, 0xFFFF, CartBR); SetReadHandler(0x8000, 0xFFFF, CartBR);
if (mmc1opts & 1) { if (WRAMSIZE) {
FCEU_CheatAddRAM(8, 0x6000, WRAM);
// clear non-battery-backed portion of WRAM
if (NONBRAMSIZE)
FCEU_MemoryRand(WRAM, NONBRAMSIZE, true);
SetReadHandler(0x6000, 0x7FFF, MAWRAM); SetReadHandler(0x6000, 0x7FFF, MAWRAM);
SetWriteHandler(0x6000, 0x7FFF, MBWRAM); SetWriteHandler(0x6000, 0x7FFF, MBWRAM);
setprg8r(0x10, 0x6000, 0); setprg8r(0x10, 0x6000, 0);
@ -270,31 +290,24 @@ static void GenMMC1Close(void) {
CHRRAM = WRAM = NULL; CHRRAM = WRAM = NULL;
} }
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery) { static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int bram) {
is155 = 0; is155 = 0;
info->Close = GenMMC1Close; info->Close = GenMMC1Close;
MMC1PRGHook16 = MMC1CHRHook4 = 0; MMC1PRGHook16 = MMC1CHRHook4 = 0;
mmc1opts = 0; WRAMSIZE = wram * 1024;
NONBRAMSIZE = (wram - bram) * 1024;
PRGmask16[0] &= (prg >> 14) - 1; PRGmask16[0] &= (prg >> 14) - 1;
CHRmask4[0] &= (chr >> 12) - 1; CHRmask4[0] &= (chr >> 12) - 1;
CHRmask8[0] &= (chr >> 13) - 1; CHRmask8[0] &= (chr >> 13) - 1;
if (wram) { if (WRAMSIZE) {
WRAM = (uint8*)FCEU_gmalloc(wram * 1024); WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
//mbg 17-jun-08 - this shouldve been cleared to re-initialize save ram SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
//ch4 10-dec-08 - nope, this souldn't AddExState(WRAM, WRAMSIZE, 0, "WRAM");
//mbg 29-mar-09 - no time to debate this, we need to keep from breaking some old stuff. if (bram) {
//we really need to make up a policy for how compatibility and accuracy can be resolved. info->SaveGame[0] = WRAM + NONBRAMSIZE;
memset(WRAM, 0, wram * 1024); info->SaveGameLen[0] = bram * 1024;
mmc1opts |= 1;
if (wram > 8) mmc1opts |= 4;
SetupCartPRGMapping(0x10, WRAM, wram * 1024, 1);
AddExState(WRAM, wram * 1024, 0, "WRAM");
if (battery) {
mmc1opts |= 2;
info->SaveGame[0] = WRAM + ((mmc1opts & 4) ? 8192 : 0);
info->SaveGameLen[0] = 8192;
} }
} }
if (!chr) { if (!chr) {
@ -312,13 +325,14 @@ static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery)
} }
void Mapper1_Init(CartInfo *info) { void Mapper1_Init(CartInfo *info) {
int ws = DetectMMC1WRAMSize(info->CRC32); int bs = info->battery ? 8 : 0;
GenMMC1Init(info, 512, 256, ws, info->battery); int ws = DetectMMC1WRAMSize(info, &bs);
GenMMC1Init(info, 512, 256, ws, bs);
} }
/* Same as mapper 1, without respect for WRAM enable bit. */ /* Same as mapper 1, without respect for WRAM enable bit. */
void Mapper155_Init(CartInfo *info) { void Mapper155_Init(CartInfo *info) {
GenMMC1Init(info, 512, 256, 8, info->battery); GenMMC1Init(info, 512, 256, 8, info->battery ? 8 : 0);
is155 = 1; is155 = 1;
} }
@ -330,7 +344,7 @@ void Mapper171_Init(CartInfo *info) {
} }
void SAROM_Init(CartInfo *info) { void SAROM_Init(CartInfo *info) {
GenMMC1Init(info, 128, 64, 8, info->battery); GenMMC1Init(info, 128, 64, 8, info->battery ? 8 : 0);
} }
void SBROM_Init(CartInfo *info) { void SBROM_Init(CartInfo *info) {
@ -350,7 +364,7 @@ void SGROM_Init(CartInfo *info) {
} }
void SKROM_Init(CartInfo *info) { void SKROM_Init(CartInfo *info) {
GenMMC1Init(info, 256, 64, 8, info->battery); GenMMC1Init(info, 256, 64, 8, info->battery ? 8 : 0);
} }
void SLROM_Init(CartInfo *info) { void SLROM_Init(CartInfo *info) {
@ -382,11 +396,9 @@ void SHROM_Init(CartInfo *info) {
/* */ /* */
void SNROM_Init(CartInfo *info) { void SNROM_Init(CartInfo *info) {
GenMMC1Init(info, 256, 0, 8, info->battery); GenMMC1Init(info, 256, 0, 8, info->battery ? 8 : 0);
} }
void SOROM_Init(CartInfo *info) { void SOROM_Init(CartInfo *info) {
GenMMC1Init(info, 256, 0, 16, info->battery); GenMMC1Init(info, 256, 0, 16, info->battery ? 8 : 0);
} }

View File

@ -279,11 +279,11 @@ void GenMMC3Power(void) {
setprg8r(0x10, 0x6000, 0); setprg8r(0x10, 0x6000, 0);
} }
if (!(mmc3opts & 2)) if (!(mmc3opts & 2))
FCEU_dwmemset(WRAM, 0, WRAMSIZE); FCEU_MemoryRand(WRAM, WRAMSIZE, true);
} }
MMC3RegReset(); MMC3RegReset();
if (CHRRAM) if (CHRRAM)
FCEU_dwmemset(CHRRAM, 0, CHRRAMSIZE); FCEU_MemoryRand(CHRRAM, CHRRAMSIZE, true);
} }
static void GenMMC3Close(void) { static void GenMMC3Close(void) {
@ -498,13 +498,18 @@ static void M45CW(uint32 A, uint8 V) {
NV &= 0; // hack ;( don't know exactly how it should be NV &= 0; // hack ;( don't know exactly how it should be
NV |= EXPREGS[0] | ((EXPREGS[2] & 0xF0) << 4); NV |= EXPREGS[0] | ((EXPREGS[2] & 0xF0) << 4);
setchr1(A, NV); setchr1(A, NV);
} } else
// setchr8(0); // i don't know what cart need this, but a new one need other lol
setchr1(A, V);
} }
static void M45PW(uint32 A, uint8 V) { static void M45PW(uint32 A, uint8 V) {
V &= (EXPREGS[3] & 0x3F) ^ 0x3F; uint32 MV = V & ((EXPREGS[3] & 0x3F) ^ 0x3F);
V |= EXPREGS[1]; MV |= EXPREGS[1];
setprg8(A, V); if(UNIFchrrama)
MV |= ((EXPREGS[2] & 0x40) << 2);
setprg8(A, MV);
// FCEU_printf("1:%02x 2:%02x 3:%02x A=%04x V=%03x\n",EXPREGS[1],EXPREGS[2],EXPREGS[3],A,MV);
} }
static DECLFW(M45Write) { static DECLFW(M45Write) {
@ -534,7 +539,6 @@ static void M45Reset(void) {
} }
static void M45Power(void) { static void M45Power(void) {
setchr8(0);
GenMMC3Power(); GenMMC3Power();
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = EXPREGS[4] = EXPREGS[5] = 0; EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = EXPREGS[4] = EXPREGS[5] = 0;
SetWriteHandler(0x5000, 0x7FFF, M45Write); SetWriteHandler(0x5000, 0x7FFF, M45Write);
@ -1039,8 +1043,8 @@ static DECLFW(Mapper196Write) {
} }
static DECLFW(Mapper196WriteLo) { static DECLFW(Mapper196WriteLo) {
EXPREGS[0] = 1; EXPREGS[0] = 1; // hacky
EXPREGS[1] = (V & 0xf) | (V >> 4); EXPREGS[1] = (V & 0xf) | (V >> 4); // this is the same as 189 mapper, but with addr permutations
FixMMC3PRG(MMC3_cmd); FixMMC3PRG(MMC3_cmd);
} }

View File

@ -22,6 +22,13 @@
#include "mapinc.h" #include "mapinc.h"
#define ABANKS MMC5SPRVPage
#define BBANKS MMC5BGVPage
#define SpriteON (PPU[1] & 0x10) //Show Sprite
#define ScreenON (PPU[1] & 0x08) //Show screen
#define PPUON (PPU[1] & 0x18) //PPU should operate
#define Sprite16 (PPU[0] & 0x20) //Sprites 8x16/8x8
static void (*sfun)(int P); static void (*sfun)(int P);
static void (*psfun)(void); static void (*psfun)(void);
@ -107,15 +114,33 @@ typedef struct __cartdata {
uint8 size; uint8 size;
} cartdata; } cartdata;
#define Sprite16 (PPU[0]& 0x20) //Sprites 8x16/8x8 #define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)]
//#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V)>>10][(V)]
static inline uint8 * MMC5BGVRAMADR(uint32 A) { uint8* MMC5BGVRAMADR(uint32 A)
{
if(newppu)
{
if(Sprite16)
{
bool isPattern = PPUON != 0;
if (ppuphase == PPUPHASE_OBJ && isPattern)
return &ABANKS[(A) >> 10][(A)];
if (ppuphase == PPUPHASE_BG && isPattern)
return &BBANKS[(A) >> 10][(A)];
else if(mmc5ABMode == 0)
return &ABANKS[(A) >> 10][(A)];
else
return &BBANKS[(A) >> 10][(A)];
}
else return &ABANKS[(A) >> 10][(A)];;
}
if (!Sprite16) { if (!Sprite16) {
if (mmc5ABMode == 0) if (mmc5ABMode == 0)
return &MMC5SPRVPage[(A) >> 10][(A)]; return &ABANKS[(A) >> 10][(A)];
else else
return &MMC5BGVPage[(A) >> 10][(A)]; return &BBANKS[(A) >> 10][(A)];
} else return &MMC5BGVPage[(A) >> 10][(A)]; } else return &BBANKS[(A) >> 10][(A)];
} }
static void mmc5_PPUWrite(uint32 A, uint8 V) { static void mmc5_PPUWrite(uint32 A, uint8 V) {
@ -136,16 +161,105 @@ static void mmc5_PPUWrite(uint32 A, uint8 V) {
} }
} }
uint8 FASTCALL mmc5_PPURead(uint32 A) { extern uint32 NTRefreshAddr;
if (A < 0x2000) { uint8 FASTCALL mmc5_PPURead(uint32 A)
if (ppuphase == PPUPHASE_BG {
//zero 03-aug-2014 - added this to fix Uchuu Keibitai SDF. The game reads NT entries from CHR rom while PPU is disabled. bool split = false;
//obviously we have enormous numbers of bugs springing from our terrible emulation of ppu-disabled states, but this does the job for fixing this one if(newppu)
&& (PPU[1] & 0x10) {
) if((MMC5HackSPMode&0x80) && !(MMC5HackCHRMode&2))
return *MMC5BGVRAMADR(A); {
else return MMC5SPRVPage[(A) >> 10][(A)]; int target = MMC5HackSPMode&0x1f;
} else { int side = MMC5HackSPMode&0x40;
int ht = NTRefreshAddr&31;
if(side==0)
{
if(ht<target) split = true;
}
else
{
if(ht>=target) split = true;
}
}
}
if (A < 0x2000)
{
if(Sprite16)
{
bool isPattern = !!PPUON;
if (ppuphase == PPUPHASE_OBJ && isPattern)
return ABANKS[(A) >> 10][(A)];
if (ppuphase == PPUPHASE_BG && isPattern)
{
if(split)
return MMC5HackVROMPTR[MMC5HackSPPage*0x1000 + (A&0xFFF)];
//uhhh call through to this more sophisticated function, only if it's really needed?
//we should probably reuse it completely, if we can
if (MMC5HackCHRMode == 1)
return *FCEUPPU_GetCHR(A,NTRefreshAddr);
return BBANKS[(A) >> 10][(A)];
}
else if(mmc5ABMode == 0)
return ABANKS[(A) >> 10][(A)];
else
return BBANKS[(A) >> 10][(A)];
}
else
{
if (ppuphase == PPUPHASE_BG && ScreenON)
{
if(split)
return MMC5HackVROMPTR[MMC5HackSPPage*0x1000 + (A&0xFFF)];
//uhhh call through to this more sophisticated function, only if it's really needed?
//we should probably reuse it completely, if we can
if (MMC5HackCHRMode == 1)
return *FCEUPPU_GetCHR(A,NTRefreshAddr);
}
return ABANKS[(A) >> 10][(A)];
}
}
else
{
if(split)
{
static const int kHack = -1; //dunno if theres science to this or if it just fixes SDF (cant be bothered to think about it)
int linetile = (newppu_get_scanline()+kHack)/8 + MMC5HackSPScroll;
//REF NT: return 0x2000 | (v << 0xB) | (h << 0xA) | (vt << 5) | ht;
//REF AT: return 0x2000 | (v << 0xB) | (h << 0xA) | 0x3C0 | ((vt & 0x1C) << 1) | ((ht & 0x1C) >> 2);
if((A&0x3FF)>=0x3C0)
{
A &= ~(0x1C<<1); //mask off VT
A |= (linetile&0x1C)<<1; //mask on adjusted VT
return ExRAM[A & 0x3FF];
}
else
{
A &= ~((0x1F<<5) | (1<<0xB)); //mask off VT and V
A |= (linetile&31)<<5; //mask on adjusted VT (V doesnt make any sense, I think)
return ExRAM[A & 0x3FF];
}
}
if (MMC5HackCHRMode == 1)
{
if((A&0x3FF)>=0x3C0)
{
uint8 byte = ExRAM[NTRefreshAddr & 0x3ff];
//get attribute part and paste it 4x across the byte
byte >>= 6;
byte *= 0x55;
return byte;
}
}
return vnapage[(A >> 10) & 0x3][A & 0x3FF]; return vnapage[(A >> 10) & 0x3][A & 0x3FF];
} }
} }
@ -844,6 +958,12 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
MMC5fill = (uint8*)FCEU_gmalloc(1024); MMC5fill = (uint8*)FCEU_gmalloc(1024);
ExRAM = (uint8*)FCEU_gmalloc(1024); ExRAM = (uint8*)FCEU_gmalloc(1024);
// MMC5fill is and 8-bit tile index, and a 2-bit attribute implented as a mirrored nametable
u8 nval = MMC5fill[0x000];
u8 aval = MMC5fill[0x3C0] & 3; aval = aval | (aval << 2) | (aval << 4) | (aval << 6);
FCEU_dwmemset(MMC5fill + 0x000, nval | (nval<<8) | (nval<<16) | (nval<<24), 0x3C0);
FCEU_dwmemset(MMC5fill + 0x3C0, aval | (aval<<8) | (aval<<16) | (aval<<24), 0x040);
AddExState(ExRAM, 1024, 0, "ERAM"); AddExState(ExRAM, 1024, 0, "ERAM");
AddExState(&MMC5HackSPMode, 1, 0, "SPLM"); AddExState(&MMC5HackSPMode, 1, 0, "SPLM");
AddExState(&MMC5HackSPScroll, 1, 0, "SPLS"); AddExState(&MMC5HackSPScroll, 1, 0, "SPLS");
@ -858,8 +978,13 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
if (battery) { if (battery) {
info->SaveGame[0] = WRAM; info->SaveGame[0] = WRAM;
//this is more complex than it looks because it MUST BE, I guess. is there an assumption that only 8KB of 16KB is battery backed? That's NES mappers for you
//I added 64KB for the new 64KB homebrews
if (wsize <= 16) if (wsize <= 16)
info->SaveGameLen[0] = 8192; info->SaveGameLen[0] = 8192;
else if(wsize == 64)
info->SaveGameLen[0] = 64*1024;
else else
info->SaveGameLen[0] = 32768; info->SaveGameLen[0] = 32768;
} }

View File

@ -57,9 +57,23 @@ static SFORMAT N106_StateRegs[] = {
{ PRG, 3, "PRG" }, { PRG, 3, "PRG" },
{ CHR, 8, "CHR" }, { CHR, 8, "CHR" },
{ NTAPage, 4, "NTA" }, { NTAPage, 4, "NTA" },
{ &gorfus, 1, "GORF" },
{ &dopol, 1, "DOPO" },
{ &gorko, 1, "GORK" },
{ 0 } { 0 }
}; };
static void SyncMirror()
{
switch(gorko) {
case 0: setmirror(MI_0); break;
case 1: setmirror(MI_V); break;
case 2: setmirror(MI_H); break;
case 3: setmirror(MI_0); break;
}
}
static void SyncPRG(void) { static void SyncPRG(void) {
setprg8(0x8000, PRG[0]); setprg8(0x8000, PRG[0]);
setprg8(0xa000, PRG[1]); setprg8(0xa000, PRG[1]);
@ -179,8 +193,11 @@ static DECLFW(Mapper19_write) {
X6502_IRQEnd(FCEU_IQEXT); X6502_IRQEnd(FCEU_IQEXT);
break; break;
case 0xE000: case 0xE000:
gorko = V & 0xC0;
PRG[0] = V & 0x3F; PRG[0] = V & 0x3F;
if(is210) {
gorko = V>>6;
SyncMirror();
}
SyncPRG(); SyncPRG();
break; break;
case 0xE800: case 0xE800:
@ -333,6 +350,7 @@ static void Mapper19_StateRestore(int version) {
SyncPRG(); SyncPRG();
FixNTAR(); FixNTAR();
FixCRR(); FixCRR();
SyncMirror();
int x; int x;
for (x = 0x40; x < 0x80; x++) for (x = 0x40; x < 0x80; x++)
FixCache(x, IRAM[x]); FixCache(x, IRAM[x]);
@ -382,8 +400,8 @@ static void N106_Power(void) {
FixCRR(); FixCRR();
if (!battery) { if (!battery) {
FCEU_dwmemset(WRAM, 0, 8192); FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
FCEU_dwmemset(IRAM, 0, 128); FCEU_MemoryRand(IRAM, sizeof(IRAM), true);
} }
for (x = 0x40; x < 0x80; x++) for (x = 0x40; x < 0x80; x++)
FixCache(x, IRAM[x]); FixCache(x, IRAM[x]);
@ -401,6 +419,8 @@ void Mapper19_Init(CartInfo *info) {
if (FSettings.SndRate) if (FSettings.SndRate)
Mapper19_ESI(); Mapper19_ESI();
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
FCEU_MemoryRand(IRAM, sizeof(IRAM), true);
AddExState(WRAM, 8192, 0, "WRAM"); AddExState(WRAM, 8192, 0, "WRAM");
AddExState(IRAM, 128, 0, "IRAM"); AddExState(IRAM, 128, 0, "IRAM");
AddExState(N106_StateRegs, ~0, 0, 0); AddExState(N106_StateRegs, ~0, 0, 0);
@ -422,6 +442,7 @@ void Mapper210_Init(CartInfo *info) {
is210 = 1; is210 = 1;
GameStateRestore = Mapper210_StateRestore; GameStateRestore = Mapper210_StateRestore;
info->Power = N106_Power; info->Power = N106_Power;
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
AddExState(WRAM, 8192, 0, "WRAM"); AddExState(WRAM, 8192, 0, "WRAM");
AddExState(N106_StateRegs, ~0, 0, 0); AddExState(N106_StateRegs, ~0, 0, 0);
} }

View File

@ -113,7 +113,7 @@ static void CSync(void) {
setchr1(0x1800 ^ cswap, block | (bank6 & mask)); setchr1(0x1800 ^ cswap, block | (bank6 & mask));
setchr1(0x1c00 ^ cswap, block | (bank7 & mask)); setchr1(0x1c00 ^ cswap, block | (bank7 & mask));
setmirror(mirror & 1); setmirror((mirror ^ 1) & 1);
} }
static void Sync(void) { static void Sync(void) {
@ -158,7 +158,7 @@ static DECLFW(UNLOneBusWriteMMC3) {
} }
break; break;
} }
case 0xa000: mirror = V ^ 1; CSync(); break; case 0xa000: mirror = V; CSync(); break;
case 0xc000: IRQLatch = V & 0xfe; break; case 0xc000: IRQLatch = V & 0xfe; break;
case 0xc001: IRQReload = 1; break; case 0xc001: IRQReload = 1; break;
case 0xe000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break; case 0xe000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break;

View File

@ -1,195 +1,195 @@
/* FCE Ultra - NES/Famicom Emulator /* FCE Ultra - NES/Famicom Emulator
* *
* Copyright notice for this file: * Copyright notice for this file:
* Copyright (C) 2014 CaH4e3 * Copyright (C) 2014 CaH4e3
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "mapinc.h" #include "mapinc.h"
static uint8 preg[8]; static uint8 preg[8];
static uint8 IRQa; static uint8 IRQa;
static int16 IRQCount, IRQLatch; static int16 IRQCount, IRQLatch;
static uint8 *WRAM = NULL; static uint8 *WRAM = NULL;
static uint32 WRAMSIZE; static uint32 WRAMSIZE;
/* /*
static uint8 *CHRRAM = NULL; static uint8 *CHRRAM = NULL;
static uint32 CHRRAMSIZE; static uint32 CHRRAMSIZE;
*/ */
static SFORMAT StateRegs[] = static SFORMAT StateRegs[] =
{ {
{ preg, 8, "PREG" }, { preg, 8, "PREG" },
{ &IRQa, 1, "IRQA" }, { &IRQa, 1, "IRQA" },
{ &IRQCount, 2, "IRQC" }, { &IRQCount, 2, "IRQC" },
{ &IRQLatch, 2, "IRQL" }, { &IRQLatch, 2, "IRQL" },
{ 0 } { 0 }
}; };
static void Sync(void) { static void Sync(void) {
setchr8(0); setchr8(0);
setprg8r(0x10, 0x6000, 0); setprg8r(0x10, 0x6000, 0);
if(preg[0] & 0x80) if(preg[0] & 0x80)
setprg4r(0x10,0x8000,preg[0] & 0x7f); setprg4r(0x10,0x8000,preg[0] & 0x7f);
else else
setprg4(0x8000,preg[0] & 0x7f); setprg4(0x8000,preg[0] & 0x7f);
if(preg[1] & 0x80) if(preg[1] & 0x80)
setprg4r(0x10,0x9000,preg[1] & 0x7f); setprg4r(0x10,0x9000,preg[1] & 0x7f);
else else
setprg4(0x9000,preg[1] & 0x7f); setprg4(0x9000,preg[1] & 0x7f);
if(preg[2] & 0x80) if(preg[2] & 0x80)
setprg4r(0x10,0xa000,preg[2] & 0x7f); setprg4r(0x10,0xa000,preg[2] & 0x7f);
else else
setprg4(0xa000,preg[2] & 0x7f); setprg4(0xa000,preg[2] & 0x7f);
if(preg[3] & 0x80) if(preg[3] & 0x80)
setprg4r(0x10,0xb000,preg[3] & 0x7f); setprg4r(0x10,0xb000,preg[3] & 0x7f);
else else
setprg4(0xb000,preg[3] & 0x7f); setprg4(0xb000,preg[3] & 0x7f);
/* /*
if(preg[4] & 0x80) if(preg[4] & 0x80)
setprg4r(0x10,0xc000,preg[4] & 0x7f); setprg4r(0x10,0xc000,preg[4] & 0x7f);
else else
setprg4(0xc000,preg[4] & 0x7f); setprg4(0xc000,preg[4] & 0x7f);
if(preg[5] & 0x80) if(preg[5] & 0x80)
setprg4r(0x10,0xd000,preg[5] & 0x7f); setprg4r(0x10,0xd000,preg[5] & 0x7f);
else else
setprg4(0xd000,preg[5] & 0x7f); setprg4(0xd000,preg[5] & 0x7f);
if(preg[6] & 0x80) if(preg[6] & 0x80)
setprg4r(0x10,0xe000,preg[6] & 0x7f); setprg4r(0x10,0xe000,preg[6] & 0x7f);
else else
setprg4(0xe000,preg[6] & 0x7f); setprg4(0xe000,preg[6] & 0x7f);
if(preg[7] & 0x80) if(preg[7] & 0x80)
setprg4r(0x10,0xf000,preg[7] & 0x7f); setprg4r(0x10,0xf000,preg[7] & 0x7f);
else else
setprg4(0xf000,preg[7] & 0x7f); setprg4(0xf000,preg[7] & 0x7f);
*/ */
setprg16(0xC000,1); setprg16(0xC000,1);
} }
static DECLFR(UNLSB2000Read) { static DECLFR(UNLSB2000Read) {
switch(A) { switch(A) {
case 0x4033: // IRQ flags case 0x4033: // IRQ flags
X6502_IRQEnd(FCEU_IQFCOUNT); X6502_IRQEnd(FCEU_IQFCOUNT);
return 0xff; return 0xff;
// case 0x4204: // unk // case 0x4204: // unk
// return 0xff; // return 0xff;
// case 0x4205: // unk // case 0x4205: // unk
// return 0xff; // return 0xff;
default: default:
FCEU_printf("unk read: %04x\n",A); FCEU_printf("unk read: %04x\n",A);
// break; // break;
return 0xff; // needed to prevent C4715 warning? return 0xff; // needed to prevent C4715 warning?
} }
} }
static DECLFW(UNLSB2000Write) { static DECLFW(UNLSB2000Write) {
switch(A) { switch(A) {
case 0x4027: // PCM output case 0x4027: // PCM output
BWrite[0x4015](0x4015, 0x10); BWrite[0x4015](0x4015, 0x10);
BWrite[0x4011](0x4011, V >> 1); BWrite[0x4011](0x4011, V >> 1);
break; break;
case 0x4032: // IRQ mask case 0x4032: // IRQ mask
IRQa &= ~V; IRQa &= ~V;
// X6502_IRQEnd(FCEU_IQEXT); // X6502_IRQEnd(FCEU_IQEXT);
break; break;
case 0x4040: case 0x4040:
case 0x4041: case 0x4041:
case 0x4042: case 0x4042:
case 0x4043: case 0x4043:
case 0x4044: case 0x4044:
case 0x4045: case 0x4045:
case 0x4046: case 0x4046:
case 0x4047: case 0x4047:
// FCEU_printf("bank write: %04x:%02x\n",A,V); // FCEU_printf("bank write: %04x:%02x\n",A,V);
preg[A&7] = V; preg[A&7] = V;
Sync(); Sync();
break; break;
default: default:
// FCEU_printf("unk write: %04x:%02x\n",A,V); // FCEU_printf("unk write: %04x:%02x\n",A,V);
break; break;
} }
} }
static void UNLSB2000Reset(void) { static void UNLSB2000Reset(void) {
preg[0] = 0; preg[0] = 0;
preg[1] = 1; preg[1] = 1;
preg[2] = 2; preg[2] = 2;
preg[3] = 3; preg[3] = 3;
preg[4] = 4; preg[4] = 4;
preg[5] = 5; preg[5] = 5;
preg[6] = 6; preg[6] = 6;
preg[7] = 7; preg[7] = 7;
IRQa = 0; IRQa = 0;
// BWrite[0x4017](0x4017,0xC0); // BWrite[0x4017](0x4017,0xC0);
// BWrite[0x4015](0x4015,0x1F); // BWrite[0x4015](0x4015,0x1F);
} }
static void UNLSB2000Power(void) { static void UNLSB2000Power(void) {
UNLSB2000Reset(); UNLSB2000Reset();
Sync(); Sync();
SetReadHandler(0x6000, 0x7fff, CartBR); SetReadHandler(0x6000, 0x7fff, CartBR);
SetWriteHandler(0x6000, 0x7fff, CartBW); SetWriteHandler(0x6000, 0x7fff, CartBW);
SetReadHandler(0x8000, 0xffff, CartBR); SetReadHandler(0x8000, 0xffff, CartBR);
SetWriteHandler(0x8000, 0xbfff, CartBW); SetWriteHandler(0x8000, 0xbfff, CartBW);
SetWriteHandler(0x4020, 0x5fff, UNLSB2000Write); SetWriteHandler(0x4020, 0x5fff, UNLSB2000Write);
SetReadHandler(0x4020, 0x5fff, UNLSB2000Read); SetReadHandler(0x4020, 0x5fff, UNLSB2000Read);
} }
static void UNLSB2000Close(void) static void UNLSB2000Close(void)
{ {
if (WRAM) if (WRAM)
FCEU_gfree(WRAM); FCEU_gfree(WRAM);
/* /*
if (CHRRAM) if (CHRRAM)
FCEU_gfree(CHRRAM); FCEU_gfree(CHRRAM);
*/ */
WRAM = /*CHRRAM = */NULL; WRAM = /*CHRRAM = */NULL;
} }
/* /*
static void UNLSB2000IRQHook() { static void UNLSB2000IRQHook() {
X6502_IRQBegin(FCEU_IQEXT); X6502_IRQBegin(FCEU_IQEXT);
} }
*/ */
static void StateRestore(int version) { static void StateRestore(int version) {
Sync(); Sync();
} }
void UNLSB2000_Init(CartInfo *info) { void UNLSB2000_Init(CartInfo *info) {
info->Reset = UNLSB2000Reset; info->Reset = UNLSB2000Reset;
info->Power = UNLSB2000Power; info->Power = UNLSB2000Power;
info->Close = UNLSB2000Close; info->Close = UNLSB2000Close;
// GameHBIRQHook = UNLSB2000IRQHook; // GameHBIRQHook = UNLSB2000IRQHook;
GameStateRestore = StateRestore; GameStateRestore = StateRestore;
/* /*
CHRRAMSIZE = 8192; CHRRAMSIZE = 8192;
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE);
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM");
*/ */
// SetupCartCHRMapping(0, PRGptr[0], PRGsize[0], 0); // SetupCartCHRMapping(0, PRGptr[0], PRGsize[0], 0);
WRAMSIZE = 512 * 1024; WRAMSIZE = 512 * 1024;
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM"); AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) { if (info->battery) {
info->SaveGame[0] = WRAM; info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE; info->SaveGameLen[0] = WRAMSIZE;
} }
AddExState(&StateRegs, ~0, 0, 0); AddExState(&StateRegs, ~0, 0, 0);
} }

View File

@ -1,52 +1,52 @@
/* FCE Ultra - NES/Famicom Emulator /* FCE Ultra - NES/Famicom Emulator
* *
* Copyright notice for this file: * Copyright notice for this file:
* Copyright (C) 2014 CaitSith2 * Copyright (C) 2014 CaitSith2
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
/* /*
* Roms still using NES 1.0 format should be loaded as 32K CHR RAM. * Roms still using NES 1.0 format should be loaded as 32K CHR RAM.
* Roms defined under NES 2.0 should use the VRAM size field, defining 7, 8 or 9, based on how much VRAM should be present. * Roms defined under NES 2.0 should use the VRAM size field, defining 7, 8 or 9, based on how much VRAM should be present.
* UNIF doesn't have this problem, because unique board names can define this information. * UNIF doesn't have this problem, because unique board names can define this information.
* The UNIF names are UNROM-512-8K, UNROM-512-16K and UNROM-512-32K * The UNIF names are UNROM-512-8K, UNROM-512-16K and UNROM-512-32K
* *
* The battery flag in the NES header enables flash, Mirrror mode 2 Enables MI_0 and MI_1 mode. * The battery flag in the NES header enables flash, Mirrror mode 2 Enables MI_0 and MI_1 mode.
* Known games to use this board are: * Known games to use this board are:
* Battle Kid 2: Mountain of Torment (512K PRG, 8K CHR RAM, Horizontal Mirroring, Flash disabled) * Battle Kid 2: Mountain of Torment (512K PRG, 8K CHR RAM, Horizontal Mirroring, Flash disabled)
* Study Hall (128K PRG (in 512K flash chip), 8K CHR RAM, Horizontal Mirroring, Flash enabled) * Study Hall (128K PRG (in 512K flash chip), 8K CHR RAM, Horizontal Mirroring, Flash enabled)
* Although Xmas 2013 uses a different board, where LEDs can be controlled (with writes to the $8000-BFFF space), * Although Xmas 2013 uses a different board, where LEDs can be controlled (with writes to the $8000-BFFF space),
* it otherwise functions identically. * it otherwise functions identically.
*/ */
#include "mapinc.h" #include "mapinc.h"
#include "../ines.h" #include "../ines.h"
static uint8 latche, latcheinit, bus_conflict, chrram_mask, software_id=false; static uint8 latche, latcheinit, bus_conflict, chrram_mask, software_id=false;
static uint16 latcha; static uint16 latcha;
static uint8 *flashdata; static uint8 *flashdata;
static uint32 *flash_write_count; static uint32 *flash_write_count;
static uint8 *FlashPage[32]; static uint8 *FlashPage[32];
static uint32 *FlashWriteCountPage[32]; static uint32 *FlashWriteCountPage[32];
static uint8 flashloaded = false; static uint8 flashloaded = false;
static uint8 flash_save=0, flash_state=0, flash_mode=0, flash_bank; static uint8 flash_save=0, flash_state=0, flash_mode=0, flash_bank;
static void (*WLSync)(void); static void (*WLSync)(void);
static void (*WHSync)(void); static void (*WHSync)(void);
static INLINE void setfpageptr(int s, uint32 A, uint8 *p) { static INLINE void setfpageptr(int s, uint32 A, uint8 *p) {
uint32 AB = A >> 11; uint32 AB = A >> 11;
int x; int x;
@ -59,8 +59,8 @@ static INLINE void setfpageptr(int s, uint32 A, uint8 *p) {
for (x = (s >> 1) - 1; x >= 0; x--) { for (x = (s >> 1) - 1; x >= 0; x--) {
FlashPage[AB + x] = 0; FlashPage[AB + x] = 0;
} }
} }
void setfprg16(uint32 A, uint32 V) { void setfprg16(uint32 A, uint32 V) {
if (PRGsize[0] >= 16384) { if (PRGsize[0] >= 16384) {
V &= PRGmask16[0]; V &= PRGmask16[0];
@ -72,198 +72,214 @@ void setfprg16(uint32 A, uint32 V) {
for (x = 0; x < 8; x++) for (x = 0; x < 8; x++)
setfpageptr(2, A + (x << 11), flashdata ? (&flashdata[((VA + x) & PRGmask2[0]) << 11]) : 0); setfpageptr(2, A + (x << 11), flashdata ? (&flashdata[((VA + x) & PRGmask2[0]) << 11]) : 0);
} }
} }
void inc_flash_write_count(uint8 bank, uint32 A) void inc_flash_write_count(uint8 bank, uint32 A)
{ {
flash_write_count[(bank*4) + ((A&0x3000)>>12)]++; flash_write_count[(bank*4) + ((A&0x3000)>>12)]++;
if(!flash_write_count[(bank*4) + ((A&0x3000)>>12)]) if(!flash_write_count[(bank*4) + ((A&0x3000)>>12)])
flash_write_count[(bank*4) + ((A&0x3000)>>12)]++; flash_write_count[(bank*4) + ((A&0x3000)>>12)]++;
} }
uint32 GetFlashWriteCount(uint8 bank, uint32 A) uint32 GetFlashWriteCount(uint8 bank, uint32 A)
{ {
return flash_write_count[(bank*4) + ((A&0x3000)>>12)]; return flash_write_count[(bank*4) + ((A&0x3000)>>12)];
} }
static void StateRestore(int version) { static void StateRestore(int version) {
WHSync(); WHSync();
} }
static DECLFW(UNROM512LLatchWrite) static DECLFW(UNROM512LLatchWrite)
{ {
latche = V; latche = V;
latcha = A; latcha = A;
WLSync(); WLSync();
} }
static DECLFW(UNROM512HLatchWrite) static DECLFW(UNROM512HLatchWrite)
{ {
if (bus_conflict) if (bus_conflict)
latche = (V == CartBR(A)) ? V : 0; latche = (V == CartBR(A)) ? V : 0;
else else
latche = V; latche = V;
latcha = A; latcha = A;
WHSync(); WHSync();
} }
static DECLFR(UNROM512LatchRead) static DECLFR(UNROM512LatchRead)
{ {
uint8 flash_id[3]={0xB5,0xB6,0xB7}; uint8 flash_id[3]={0xB5,0xB6,0xB7};
if(software_id) if(software_id)
{ {
if(A&1) if(A&1)
return flash_id[ROM_size>>4]; return flash_id[ROM_size>>4];
else else
return 0xBF; return 0xBF;
} }
if(flash_save) if(flash_save)
{ {
if(A < 0xC000) if(A < 0xC000)
{ {
if(GetFlashWriteCount(flash_bank,A)) if(GetFlashWriteCount(flash_bank,A))
return FlashPage[A >> 11][A]; return FlashPage[A >> 11][A];
} }
else else
{ {
if(GetFlashWriteCount(ROM_size-1,A)) if(GetFlashWriteCount(ROM_size-1,A))
return FlashPage[A >> 11][A]; return FlashPage[A >> 11][A];
} }
} }
return Page[A >> 11][A]; return Page[A >> 11][A];
} }
static void UNROM512LatchPower(void) { static void UNROM512LatchPower(void) {
latche = latcheinit; latche = latcheinit;
WHSync(); WHSync();
SetReadHandler(0x8000, 0xFFFF, UNROM512LatchRead); SetReadHandler(0x8000, 0xFFFF, UNROM512LatchRead);
if(!flash_save) if(!flash_save)
SetWriteHandler(0x8000, 0xFFFF, UNROM512HLatchWrite); SetWriteHandler(0x8000, 0xFFFF, UNROM512HLatchWrite);
else else
{ {
SetWriteHandler(0x8000,0xBFFF,UNROM512LLatchWrite); SetWriteHandler(0x8000,0xBFFF,UNROM512LLatchWrite);
SetWriteHandler(0xC000,0xFFFF,UNROM512HLatchWrite); SetWriteHandler(0xC000,0xFFFF,UNROM512HLatchWrite);
} }
} }
static void UNROM512LatchClose(void) { static void UNROM512LatchClose(void) {
if(flash_write_count) if(flash_write_count)
FCEU_gfree(flash_write_count); FCEU_gfree(flash_write_count);
if(flashdata) if(flashdata)
FCEU_gfree(flashdata); FCEU_gfree(flashdata);
flash_write_count = NULL; flash_write_count = NULL;
flashdata = NULL; flashdata = NULL;
} }
static void UNROM512LSync() { static void UNROM512LSync() {
int erase_a[5]={0x9555,0xAAAA,0x9555,0x9555,0xAAAA}; int erase_a[5]={0x9555,0xAAAA,0x9555,0x9555,0xAAAA};
int erase_d[5]={0xAA,0x55,0x80,0xAA,0x55}; int erase_d[5]={0xAA,0x55,0x80,0xAA,0x55};
int erase_b[5]={1,0,1,1,0}; int erase_b[5]={1,0,1,1,0};
if(flash_mode==0) if(flash_mode==0)
{ {
if((latcha == erase_a[flash_state]) && (latche == erase_d[flash_state]) && (flash_bank == erase_b[flash_state])) if((latcha == erase_a[flash_state]) && (latche == erase_d[flash_state]) && (flash_bank == erase_b[flash_state]))
{ {
flash_state++; flash_state++;
if(flash_state == 5) if(flash_state == 5)
{ {
flash_mode=1; flash_mode=1;
} }
} }
else if ((flash_state==2)&&(latcha==0x9555)&&(latche==0xA0)&&(flash_bank==1)) else if ((flash_state==2)&&(latcha==0x9555)&&(latche==0xA0)&&(flash_bank==1))
{ {
flash_state++; flash_state++;
flash_mode=2; flash_mode=2;
} }
else if ((flash_state==2)&&(latcha==0x9555)&&(latche==0x90)&&(flash_bank==1)) else if ((flash_state==2)&&(latcha==0x9555)&&(latche==0x90)&&(flash_bank==1))
{ {
flash_state=0; flash_state=0;
software_id=true; software_id=true;
} }
else else
{ {
if(latche==0xF0) if(latche==0xF0)
software_id=false; software_id=false;
flash_state=0; flash_state=0;
} }
} }
else if(flash_mode==1) //Chip Erase or Sector Erase else if(flash_mode==1) //Chip Erase or Sector Erase
{ {
if(latche==0x30) if(latche==0x30)
{ {
inc_flash_write_count(flash_bank,latcha); inc_flash_write_count(flash_bank,latcha);
memset(&FlashPage[(latcha & 0xF000) >> 11][latcha & 0xF000],0xFF,0x1000); memset(&FlashPage[(latcha & 0xF000) >> 11][latcha & 0xF000],0xFF,0x1000);
} }
else if (latche==0x10) else if (latche==0x10)
{ {
for(int i=0;i<(ROM_size*4);i++) for(uint32 i=0;i<(ROM_size*4);i++)
inc_flash_write_count(i>>2,i<<12); inc_flash_write_count(i>>2,i<<12);
memset(flashdata,0xFF,ROM_size*0x4000); //Erasing the rom chip as instructed. Crash rate calulated to be 99.9% :) memset(flashdata,0xFF,ROM_size*0x4000); //Erasing the rom chip as instructed. Crash rate calulated to be 99.9% :)
} }
flash_state=0; flash_state=0;
flash_mode=0; flash_mode=0;
} }
else if(flash_mode==2) //Byte Program else if(flash_mode==2) //Byte Program
{ {
if(!GetFlashWriteCount(flash_bank,latcha)) if(!GetFlashWriteCount(flash_bank,latcha))
{ {
inc_flash_write_count(flash_bank,latcha); inc_flash_write_count(flash_bank,latcha);
memcpy(&FlashPage[(latcha & 0xF000) >> 11][latcha & 0xF000],&Page[(latcha & 0xF000)>>11][latcha & 0xF000],0x1000); memcpy(&FlashPage[(latcha & 0xF000) >> 11][latcha & 0xF000],&Page[(latcha & 0xF000)>>11][latcha & 0xF000],0x1000);
} }
FlashPage[latcha>>11][latcha]&=latche; FlashPage[latcha>>11][latcha]&=latche;
flash_state=0; flash_state=0;
flash_mode=0; flash_mode=0;
} }
} }
static void UNROM512HSync() static void UNROM512HSync()
{ {
flash_bank=latche&(ROM_size-1); flash_bank=latche&(ROM_size-1);
setprg16(0x8000, flash_bank); setprg16(0x8000, flash_bank);
setprg16(0xc000, ~0); setprg16(0xc000, ~0);
setfprg16(0x8000, flash_bank); setfprg16(0x8000, flash_bank);
setfprg16(0xC000, ~0); setfprg16(0xC000, ~0);
setchr8r(0, (latche & chrram_mask) >> 5); setchr8r(0, (latche & chrram_mask) >> 5);
setmirror(MI_0+(latche>>7)); setmirror(MI_0+(latche>>7));
} }
void UNROM512_Init(CartInfo *info) { void UNROM512_Init(CartInfo *info) {
flash_state=0; flash_state=0;
flash_bank=0; flash_bank=0;
flash_save=info->battery; flash_save=info->battery;
if(info->vram_size == 8192) if(info->vram_size == 8192)
chrram_mask = 0; chrram_mask = 0;
else if (info->vram_size == 16384) else if (info->vram_size == 16384)
chrram_mask = 0x20; chrram_mask = 0x20;
else else
chrram_mask = 0x60; chrram_mask = 0x60;
SetupCartMirroring(info->mirror,(info->mirror>=MI_0)?0:1,0); int mirror = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2);
bus_conflict = !info->battery; switch (mirror)
latcheinit = 0; {
WLSync = UNROM512LSync; case 0: // hard horizontal, internal
WHSync = UNROM512HSync; SetupCartMirroring(MI_H, 1, NULL);
info->Power = UNROM512LatchPower; break;
info->Close = UNROM512LatchClose; case 1: // hard vertical, internal
GameStateRestore = StateRestore; SetupCartMirroring(MI_V, 1, NULL);
if(flash_save) break;
{ case 2: // switchable 1-screen, internal (flags: 4-screen + horizontal)
flashdata = (uint8*)FCEU_gmalloc(ROM_size*0x4000); SetupCartMirroring(MI_0, 0, NULL);
flash_write_count = (uint32*)FCEU_gmalloc(ROM_size*4*sizeof(uint32)); break;
info->SaveGame[0] = (uint8*)flash_write_count; case 3: // hard four screen, last 8k of 32k RAM (flags: 4-screen + vertical)
info->SaveGame[1] = flashdata; SetupCartMirroring( 4, 1, VROM + (info->vram_size - 8192));
info->SaveGameLen[0] = ROM_size*4*sizeof(uint32); break;
info->SaveGameLen[1] = ROM_size*0x4000; }
AddExState(flash_write_count,ROM_size*4*sizeof(uint32),0,"FLASH_WRITE_COUNT");
AddExState(flashdata,ROM_size*0x4000,0,"FLASH_DATA"); bus_conflict = !info->battery;
AddExState(&flash_state,1,0,"FLASH_STATE"); latcheinit = 0;
AddExState(&flash_mode,1,0,"FLASH_MODE"); WLSync = UNROM512LSync;
AddExState(&flash_bank,1,0,"FLASH_BANK"); WHSync = UNROM512HSync;
AddExState(&latcha,2,0,"LATA"); info->Power = UNROM512LatchPower;
} info->Close = UNROM512LatchClose;
AddExState(&latche, 1, 0, "LATC"); GameStateRestore = StateRestore;
AddExState(&bus_conflict, 1, 0, "BUSC"); if(flash_save)
{
flashdata = (uint8*)FCEU_gmalloc(ROM_size*0x4000);
flash_write_count = (uint32*)FCEU_gmalloc(ROM_size*4*sizeof(uint32));
info->SaveGame[0] = (uint8*)flash_write_count;
info->SaveGame[1] = flashdata;
info->SaveGameLen[0] = ROM_size*4*sizeof(uint32);
info->SaveGameLen[1] = ROM_size*0x4000;
AddExState(flash_write_count,ROM_size*4*sizeof(uint32),0,"FLASH_WRITE_COUNT");
AddExState(flashdata,ROM_size*0x4000,0,"FLASH_DATA");
AddExState(&flash_state,1,0,"FLASH_STATE");
AddExState(&flash_mode,1,0,"FLASH_MODE");
AddExState(&flash_bank,1,0,"FLASH_BANK");
AddExState(&latcha,2,0,"LATA");
}
AddExState(&latche, 1, 0, "LATC");
AddExState(&bus_conflict, 1, 0, "BUSC");
} }

View File

@ -20,7 +20,8 @@
#include "mapinc.h" #include "mapinc.h"
static uint8 isPirate, is22; static bool isPirate;
static uint8 is22, reg1mask, reg2mask;
static uint16 IRQCount; static uint16 IRQCount;
static uint8 IRQLatch, IRQa; static uint8 IRQLatch, IRQa;
static uint8 prgreg[2], chrreg[8]; static uint8 prgreg[2], chrreg[8];
@ -61,15 +62,15 @@ static void Sync(void) {
setchr8(0); setchr8(0);
else{ else{
uint8 i; uint8 i;
if(!weirdo) //if(!weirdo)
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
setchr1(i << 10, (chrhi[i] | chrreg[i]) >> is22); setchr1(i << 10, (chrhi[i] | chrreg[i]) >> is22);
else { //else {
setchr1(0x0000, 0xFC); // setchr1(0x0000, 0xFC);
setchr1(0x0400, 0xFD); // setchr1(0x0400, 0xFD);
setchr1(0x0800, 0xFF); // setchr1(0x0800, 0xFF);
weirdo--; // weirdo--;
} //}
} }
switch (mirr & 0x3) { switch (mirr & 0x3) {
case 0: setmirror(MI_V); break; case 0: setmirror(MI_V); break;
@ -80,7 +81,7 @@ static void Sync(void) {
} }
static DECLFW(VRC24Write) { static DECLFW(VRC24Write) {
A &= 0xF003; A = A & 0xF000 | !!(A & reg2mask) << 1 | !!(A & reg1mask);
if ((A >= 0xB000) && (A <= 0xE003)) { if ((A >= 0xB000) && (A <= 0xE003)) {
if (UNIFchrrama) if (UNIFchrrama)
big_bank = (V & 8) << 2; // my personally many-in-one feature ;) just for support pirate cart 2-in-1 big_bank = (V & 8) << 2; // my personally many-in-one feature ;) just for support pirate cart 2-in-1
@ -126,61 +127,17 @@ static DECLFW(VRC24Write) {
} }
} }
static DECLFW(M21Write) { static void VRC24Power(void) {
A = (A & 0xF000) | ((A >> 1) & 0x3); // Ganbare Goemon Gaiden 2 - Tenka no Zaihou (J) [!] isn't mapper 21 actually, big_bank = 0x20;
// it's mapper 23 by wirings Sync();
VRC24Write(A, V); if (WRAM) {
} setprg8r(0x10, 0x6000, 0);
SetReadHandler(0x6000, 0x7FFF, CartBR);
static DECLFW(M22Write) { SetWriteHandler(0x6000, 0x7FFF, CartBW);
if (A == 0xC007) { // Ganbare Goemon Gaiden does strange things!!! at the end credits FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
weirdo = 8; // quick dirty hack, seems there is no other games with such PCB, so
// we never know if it will not work for something else lol
} }
A |= ((A >> 2) & 0x3); // It's just swapped lines from 21 mapper
//
VRC24Write((A & 0xF000) | ((A >> 1) & 1) | ((A << 1) & 2), V);
}
static DECLFW(M23Write) {
A |= ((A >> 2) & 0x3) | ((A >> 4) & 0x3) | ((A >> 6) & 0x3);// actually there is many-in-one mapper source, some pirate or
// licensed games use various address bits for registers
VRC24Write(A, V);
}
static void M21Power(void) {
Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR); SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xFFFF, M21Write); SetWriteHandler(0x8000, 0xFFFF, VRC24Write);
}
static void M22Power(void) {
Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xFFFF, M22Write);
}
static void M23Power(void) {
big_bank = 0x20;
Sync();
setprg8r(0x10, 0x6000, 0); // Only two Goemon games are have battery backed RAM, three more shooters
// (Parodius Da!, Gradius 2 and Crisis Force uses 2k or SRAM at 6000-67FF only
SetReadHandler(0x6000, 0x7FFF, CartBR);
SetWriteHandler(0x6000, 0x7FFF, CartBW);
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xFFFF, M23Write);
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
}
static void M25Power(void) {
big_bank = 0x20;
Sync();
setprg8r(0x10, 0x6000, 0);
SetReadHandler(0x6000, 0x7FFF, CartBR);
SetWriteHandler(0x6000, 0x7FFF, CartBW);
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xFFFF, M22Write);
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
} }
void VRC24IRQHook(int a) { void VRC24IRQHook(int a) {
@ -210,26 +167,8 @@ static void VRC24Close(void) {
WRAM = NULL; WRAM = NULL;
} }
void Mapper21_Init(CartInfo *info) { static void VRC24_Init(CartInfo *info) {
isPirate = 0; info->Power = VRC24Power;
is22 = 0;
info->Power = M21Power;
MapIRQHook = VRC24IRQHook;
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}
void Mapper22_Init(CartInfo *info) {
isPirate = 0;
is22 = 1;
info->Power = M22Power;
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}
void VRC24_Init(CartInfo *info) {
info->Close = VRC24Close; info->Close = VRC24Close;
MapIRQHook = VRC24IRQHook; MapIRQHook = VRC24IRQHook;
GameStateRestore = StateRestore; GameStateRestore = StateRestore;
@ -247,23 +186,48 @@ void VRC24_Init(CartInfo *info) {
AddExState(&StateRegs, ~0, 0, 0); AddExState(&StateRegs, ~0, 0, 0);
} }
void Mapper23_Init(CartInfo *info) { void Mapper21_Init(CartInfo *info) {
isPirate = 0; isPirate = false;
is22 = 0; is22 = 0;
info->Power = M23Power; reg1mask = 0x42;
reg2mask = 0x84;
VRC24_Init(info);
}
void Mapper22_Init(CartInfo *info) {
isPirate = false;
is22 = 1;
reg1mask = 2;
reg2mask = 1;
// no IRQ (all mapper 22 games are VRC2)
// no WRAM
info->Power = VRC24Power;
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}
void Mapper23_Init(CartInfo *info) {
isPirate = false;
is22 = 0;
reg1mask = 0x15;
reg2mask = 0x2a;
VRC24_Init(info); VRC24_Init(info);
} }
void Mapper25_Init(CartInfo *info) { void Mapper25_Init(CartInfo *info) {
isPirate = 0; isPirate = false;
is22 = 0; is22 = 0;
info->Power = M25Power; reg1mask = 0xa;
reg2mask = 0x5;
VRC24_Init(info); VRC24_Init(info);
} }
void UNLT230_Init(CartInfo *info) { void UNLT230_Init(CartInfo *info) {
isPirate = 1; isPirate = true;
is22 = 0; is22 = 0;
info->Power = M23Power; reg1mask = 0x15;
reg2mask = 0x2a;
VRC24_Init(info); VRC24_Init(info);
} }

View File

@ -1,226 +1,202 @@
/* FCE Ultra - NES/Famicom Emulator /* FCE Ultra - NES/Famicom Emulator
* *
* Copyright notice for this file: * Copyright notice for this file:
* Copyright (C) 2005 CaH4e3 * Copyright (C) 2005 CaH4e3
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
* VRC-5 (CAI Shogakko no Sansu) * VRC-5 (CAI Shogakko no Sansu)
* *
*/ */
#include "mapinc.h" #include "mapinc.h"
static uint8 QTAINTRAM[2048]; static uint8 QTAINTRAM[2048];
static writefunc old2007wrap; static writefunc old2007wrap;
static uint16 CHRSIZE = 8192; static uint16 CHRSIZE = 8192;
static uint16 WRAMSIZE = 8192 + 4096; static uint16 WRAMSIZE = 8192 + 4096;
static uint8 *CHRRAM = NULL; static uint8 *CHRRAM = NULL;
static uint8 *WRAM = NULL; static uint8 *WRAM = NULL;
static uint8 IRQa, K4IRQ; static uint8 IRQa, K4IRQ;
static uint32 IRQLatch, IRQCount; static uint32 IRQLatch, IRQCount;
static uint8 regs[16]; static uint8 regs[16];
//static uint8 test[8]; //static uint8 test[8];
static SFORMAT StateRegs[] = static SFORMAT StateRegs[] =
{ {
{ &IRQCount, 1, "IRQC" }, { &IRQCount, 1, "IRQC" },
{ &IRQLatch, 1, "IRQL" }, { &IRQLatch, 1, "IRQL" },
{ &IRQa, 1, "IRQA" }, { &IRQa, 1, "IRQA" },
{ &K4IRQ, 1, "KIRQ" }, { &K4IRQ, 1, "KIRQ" },
{ regs, 16, "REGS" }, { regs, 16, "REGS" },
{ 0 } { 0 }
}; };
static void chrSync(void) { static void chrSync(void) {
setchr4r(0x10, 0x0000, regs[5] & 1); setchr4r(0x10, 0x0000, regs[5] & 1);
setchr4r(0x10, 0x1000, 0); setchr4r(0x10, 0x1000, 0);
} }
static void Sync(void) { static void Sync(void) {
chrSync(); chrSync();
// if(regs[0xA]&0x10) // if(regs[0xA]&0x10)
// { // {
/* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0); /* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0);
setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1); setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1);
setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2); setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2);
setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3); setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3);
setchr1r(0x10,0x1000,0); setchr1r(0x10,0x1000,0);
setchr1r(0x10,0x1400,1); setchr1r(0x10,0x1400,1);
setchr1r(0x10,0x1800,2); setchr1r(0x10,0x1800,2);
setchr1r(0x10,0x1c00,3);*/ setchr1r(0x10,0x1c00,3);*/
/* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0); /* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0);
setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1); setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1);
setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2); setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2);
setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3); setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3);
setchr1r(0x10,0x1000,(((regs[5]&1)^1)<<2)+4); setchr1r(0x10,0x1000,(((regs[5]&1)^1)<<2)+4);
setchr1r(0x10,0x1400,(((regs[5]&1)^1)<<2)+5); setchr1r(0x10,0x1400,(((regs[5]&1)^1)<<2)+5);
setchr1r(0x10,0x1800,(((regs[5]&1)^1)<<2)+6); setchr1r(0x10,0x1800,(((regs[5]&1)^1)<<2)+6);
setchr1r(0x10,0x1c00,(((regs[5]&1)^1)<<2)+7); setchr1r(0x10,0x1c00,(((regs[5]&1)^1)<<2)+7);
*/ */
// } // }
// else // else
// { // {
/* /*
setchr1r(0x10,0x0000,(((regs[5]&1)^1)<<2)+0); setchr1r(0x10,0x0000,(((regs[5]&1)^1)<<2)+0);
setchr1r(0x10,0x0400,(((regs[5]&1)^1)<<2)+1); setchr1r(0x10,0x0400,(((regs[5]&1)^1)<<2)+1);
setchr1r(0x10,0x0800,(((regs[5]&1)^1)<<2)+2); setchr1r(0x10,0x0800,(((regs[5]&1)^1)<<2)+2);
setchr1r(0x10,0x0c00,(((regs[5]&1)^1)<<2)+3); setchr1r(0x10,0x0c00,(((regs[5]&1)^1)<<2)+3);
setchr1r(0x10,0x1000,(((regs[5]&1))<<2)+4); setchr1r(0x10,0x1000,(((regs[5]&1))<<2)+4);
setchr1r(0x10,0x1400,(((regs[5]&1))<<2)+5); setchr1r(0x10,0x1400,(((regs[5]&1))<<2)+5);
setchr1r(0x10,0x1800,(((regs[5]&1))<<2)+6); setchr1r(0x10,0x1800,(((regs[5]&1))<<2)+6);
setchr1r(0x10,0x1c00,(((regs[5]&1))<<2)+7); setchr1r(0x10,0x1c00,(((regs[5]&1))<<2)+7);
// } // }
//*/ //*/
/* setchr1r(1,0x0000,test[0]); /* setchr1r(1,0x0000,test[0]);
setchr1r(1,0x0400,test[1]); setchr1r(1,0x0400,test[1]);
setchr1r(1,0x0800,test[2]); setchr1r(1,0x0800,test[2]);
setchr1r(1,0x0c00,test[3]); setchr1r(1,0x0c00,test[3]);
setchr1r(1,0x1000,test[4]); setchr1r(1,0x1000,test[4]);
setchr1r(1,0x1400,test[5]); setchr1r(1,0x1400,test[5]);
setchr1r(1,0x1800,test[6]); setchr1r(1,0x1800,test[6]);
setchr1r(1,0x1c00,test[7]); setchr1r(1,0x1c00,test[7]);
*/ */
setprg4r(0x10, 0x6000, regs[0] & 1); setprg4r(0x10, 0x6000, regs[0] & 1);
if (regs[2] >= 0x40) if (regs[2] >= 0x40)
setprg8r(1, 0x8000, (regs[2] - 0x40)); setprg8r(1, 0x8000, (regs[2] - 0x40));
else else
setprg8r(0, 0x8000, (regs[2] & 0x3F)); setprg8r(0, 0x8000, (regs[2] & 0x3F));
if (regs[3] >= 0x40) if (regs[3] >= 0x40)
setprg8r(1, 0xA000, (regs[3] - 0x40)); setprg8r(1, 0xA000, (regs[3] - 0x40));
else else
setprg8r(0, 0xA000, (regs[3] & 0x3F)); setprg8r(0, 0xA000, (regs[3] & 0x3F));
if (regs[4] >= 0x40) if (regs[4] >= 0x40)
setprg8r(1, 0xC000, (regs[4] - 0x40)); setprg8r(1, 0xC000, (regs[4] - 0x40));
else else
setprg8r(0, 0xC000, (regs[4] & 0x3F)); setprg8r(0, 0xC000, (regs[4] & 0x3F));
setprg8r(1, 0xE000, ~0); setprg8r(1, 0xE000, ~0);
setmirror(MI_V); setmirror(MI_V);
} }
/*static DECLFW(TestWrite) /*static DECLFW(TestWrite)
{ {
test[A&7] = V; test[A&7] = V;
Sync(); Sync();
}*/ }*/
static DECLFW(M190Write) { static DECLFW(M190Write) {
// FCEU_printf("write %04x:%04x %d, %d\n",A,V,scanline,timestamp); // FCEU_printf("write %04x:%04x %d, %d\n",A,V,scanline,timestamp);
regs[(A & 0x0F00) >> 8] = V; regs[(A & 0x0F00) >> 8] = V;
switch (A) { switch (A) {
case 0xd600: IRQLatch &= 0xFF00; IRQLatch |= V; break; case 0xd600: IRQLatch &= 0xFF00; IRQLatch |= V; break;
case 0xd700: IRQLatch &= 0x00FF; IRQLatch |= V << 8; break; case 0xd700: IRQLatch &= 0x00FF; IRQLatch |= V << 8; break;
case 0xd900: IRQCount = IRQLatch; IRQa = V & 2; K4IRQ = V & 1; X6502_IRQEnd(FCEU_IQEXT); break; case 0xd900: IRQCount = IRQLatch; IRQa = V & 2; K4IRQ = V & 1; X6502_IRQEnd(FCEU_IQEXT); break;
case 0xd800: IRQa = K4IRQ; X6502_IRQEnd(FCEU_IQEXT); break; case 0xd800: IRQa = K4IRQ; X6502_IRQEnd(FCEU_IQEXT); break;
} }
Sync(); Sync();
} }
static DECLFR(M190Read) { static DECLFR(M190Read) {
// FCEU_printf("read %04x:%04x %d, %d\n",A,regs[(A&0x0F00)>>8],scanline,timestamp); // FCEU_printf("read %04x:%04x %d, %d\n",A,regs[(A&0x0F00)>>8],scanline,timestamp);
return regs[(A & 0x0F00) >> 8] + regs[0x0B]; return regs[(A & 0x0F00) >> 8] + regs[0x0B];
} }
static void VRC5IRQ(int a) { static void VRC5IRQ(int a) {
if (IRQa) { if (IRQa) {
IRQCount += a; IRQCount += a;
if (IRQCount & 0x10000) { if (IRQCount & 0x10000) {
X6502_IRQBegin(FCEU_IQEXT); X6502_IRQBegin(FCEU_IQEXT);
IRQCount = IRQLatch; IRQCount = IRQLatch;
} }
} }
} }
//static void Mapper190_PPU(uint32 A) //static void Mapper190_PPU(uint32 A)
//{ //{
// if(A<0x2000) // if(A<0x2000)
// setchr4r(0x10,0x1000,QTAINTRAM[A&0x1FFF]&1); // setchr4r(0x10,0x1000,QTAINTRAM[A&0x1FFF]&1);
// else // else
// chrSync(); // chrSync();
//} //}
static DECLFW(M1902007Wrap) { static DECLFW(M1902007Wrap) {
if (A >= 0x2000) { if (A >= 0x2000) {
if (regs[0xA] & 1) if (regs[0xA] & 1)
QTAINTRAM[A & 0x1FFF] = V; QTAINTRAM[A & 0x1FFF] = V;
else else
old2007wrap(A, V); old2007wrap(A, V);
} }
} }
static void M190Power(void) { static void M190Power(void) {
/* test[0]=0; /* test[0]=0;
test[1]=1; test[1]=1;
test[2]=2; test[2]=2;
test[3]=3; test[3]=3;
test[4]=4; test[4]=4;
test[5]=5; test[5]=5;
test[6]=6; test[6]=6;
test[7]=7; test[7]=7;
*/ */
setprg4r(0x10, 0x7000, 2); setprg4r(0x10, 0x7000, 2);
old2007wrap = GetWriteHandler(0x2007); old2007wrap = GetWriteHandler(0x2007);
SetWriteHandler(0x2007, 0x2007, M1902007Wrap); SetWriteHandler(0x2007, 0x2007, M1902007Wrap);
SetReadHandler(0x6000, 0xFFFF, CartBR); SetReadHandler(0x6000, 0xFFFF, CartBR);
// SetWriteHandler(0x5000,0x5007,TestWrite); // SetWriteHandler(0x5000,0x5007,TestWrite);
SetWriteHandler(0x6000, 0x7FFF, CartBW); SetWriteHandler(0x6000, 0x7FFF, CartBW);
SetWriteHandler(0x8000, 0xFFFF, M190Write); SetWriteHandler(0x8000, 0xFFFF, M190Write);
SetReadHandler(0xDC00, 0xDC00, M190Read); SetReadHandler(0xDC00, 0xDC00, M190Read);
SetReadHandler(0xDD00, 0xDD00, M190Read); SetReadHandler(0xDD00, 0xDD00, M190Read);
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
Sync(); Sync();
} }
static void M190Close(void) { static void M190Close(void) {
if (CHRRAM) if (CHRRAM)
FCEU_gfree(CHRRAM); FCEU_gfree(CHRRAM);
CHRRAM = NULL; CHRRAM = NULL;
if (WRAM) if (WRAM)
FCEU_gfree(WRAM); FCEU_gfree(WRAM);
WRAM = NULL; WRAM = NULL;
} }
static void StateRestore(int version) { static void StateRestore(int version) {
Sync(); Sync();
} }
void Mapper190_Init(CartInfo *info) {
info->Power = M190Power;
info->Close = M190Close;
GameStateRestore = StateRestore;
MapIRQHook = VRC5IRQ;
// PPU_hook=Mapper190_PPU;
CHRRAM = (uint8*)FCEU_gmalloc(CHRSIZE);
SetupCartCHRMapping(0x10, CHRRAM, CHRSIZE, 1);
AddExState(CHRRAM, CHRSIZE, 0, "CRAM");
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE - 4096;
}
AddExState(&StateRegs, ~0, 0, 0);
}

View File

@ -86,7 +86,7 @@ static void VRC7SKill(void) {
static void VRC7_ESI(void) { static void VRC7_ESI(void) {
GameExpSound.RChange = VRC7SC; GameExpSound.RChange = VRC7SC;
GameExpSound.Kill = VRC7SKill; GameExpSound.Kill = VRC7SKill;
VRC7Sound = OPLL_new(3579545, FSettings.SndRate ? FSettings.SndRate : 44100); VRC7Sound = OPLL_new(3579545, FSettings.SndRate ? FSettings.SndRate : 48000);
OPLL_reset(VRC7Sound); OPLL_reset(VRC7Sound);
OPLL_reset(VRC7Sound); OPLL_reset(VRC7Sound);
} }

View File

@ -76,6 +76,8 @@ uint8 geniech[3];
uint32 genieaddr[3]; uint32 genieaddr[3];
CartInfo *currCartInfo;
static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram) { static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram) {
uint32 AB = A >> 11; uint32 AB = A >> 11;
int x; int x;

View File

@ -25,6 +25,8 @@ typedef struct {
// other code in the future. // other code in the future.
} CartInfo; } CartInfo;
extern CartInfo *currCartInfo;
void FCEU_SaveGameSave(CartInfo *LocalHWInfo); void FCEU_SaveGameSave(CartInfo *LocalHWInfo);
void FCEU_LoadGameSave(CartInfo *LocalHWInfo); void FCEU_LoadGameSave(CartInfo *LocalHWInfo);
void FCEU_ClearGameSave(CartInfo *LocalHWInfo); void FCEU_ClearGameSave(CartInfo *LocalHWInfo);

View File

@ -216,7 +216,7 @@ void FCEU_LoadGameCheats(FILE *override)
} }
FCEU_DispMessage("Cheats file loaded.",0); //Tells user a cheats file was loaded. FCEU_DispMessage("Cheats file loaded.",0); //Tells user a cheats file was loaded.
while(fgets(linebuf,2048,fp)>0) while(fgets(linebuf,2048,fp) != nullptr)
{ {
char *tbuf=linebuf; char *tbuf=linebuf;
int doc=0; int doc=0;
@ -931,12 +931,14 @@ void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2)
int FCEU_CheatGetByte(uint32 A) int FCEU_CheatGetByte(uint32 A)
{ {
// if(CheatRPtrs[A>>10]) if(A < 0x10000) {
// return CheatRPtrs[A>>10][A]; //adelikat-commenting this stuff out so that lua can see frozen addresses, I hope this doesn't bork stuff. uint32 ret;
/*else*/ if(A < 0x10000) fceuindbg=1;
return ARead[A](A); ret = ARead[A](A);
else fceuindbg=0;
return 0; return ret;
} else
return 0;
} }
void FCEU_CheatSetByte(uint32 A, uint8 V) void FCEU_CheatSetByte(uint32 A, uint8 V)

View File

@ -34,10 +34,11 @@
* Primitive -> Number | Address | Register | Flag | PC Bank | '(' Connect ')' * Primitive -> Number | Address | Register | Flag | PC Bank | '(' Connect ')'
* Number -> '#' [1-9A-F]* * Number -> '#' [1-9A-F]*
* Address -> '$' [1-9A-F]* | '$' '[' Connect ']' * Address -> '$' [1-9A-F]* | '$' '[' Connect ']'
* Register -> 'A' | 'X' | 'Y' | 'P' * Register -> 'A' | 'X' | 'Y' | 'P' | 'S'
* Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V' * Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V' | 'U' | 'D'
* PC Bank -> 'K' * PC Bank -> 'K'
* Data Bank -> 'T' * Data Bank -> 'T'
* Value -> 'R' | 'W'
*/ */
#include "types.h" #include "types.h"
@ -50,8 +51,9 @@
#include <cassert> #include <cassert>
#include <cctype> #include <cctype>
// hack: this address is used by 'T' condition uint16 debugLastAddress = 0; // used by 'T' and 'R' conditions
uint16 addressOfTheLastAccessedData = 0; uint8 debugLastOpcode; // used to evaluate 'W' condition
// Next non-whitespace character in string // Next non-whitespace character in string
char next; char next;
@ -137,7 +139,7 @@ int isFlag(char c)
// Determines if a character is a register // Determines if a character is a register
int isRegister(char c) int isRegister(char c)
{ {
return c == 'A' || c == 'X' || c == 'Y' || c == 'P'; return c == 'A' || c == 'X' || c == 'Y' || c == 'P' || c == 'S';
} }
// Determines if a character is for PC bank // Determines if a character is for PC bank
@ -152,6 +154,18 @@ int isDataBank(char c)
return c == 'T'; return c == 'T';
} }
// Determines if a character is for value read
int isValueRead(char c)
{
return c == 'R';
}
// Determines if a character is for value write
int isValueWrite(char c)
{
return c == 'W';
}
// Reads a hexadecimal number from str // Reads a hexadecimal number from str
int getNumber(unsigned int* number, const char** str) int getNumber(unsigned int* number, const char** str)
{ {
@ -272,6 +286,40 @@ Condition* Primitive(const char** str, Condition* c)
return c; return c;
} }
else if (isValueRead(next))
{
if (c->type1 == TYPE_NO)
{
c->type1 = TYPE_VALUE_READ;
c->value1 = next;
}
else
{
c->type2 = TYPE_VALUE_READ;
c->value2 = next;
}
scan(str);
return c;
}
else if (isValueWrite(next))
{
if (c->type1 == TYPE_NO)
{
c->type1 = TYPE_VALUE_WRITE;
c->value1 = next;
}
else
{
c->type2 = TYPE_VALUE_WRITE;
c->value2 = next;
}
scan(str);
return c;
}
else if (next == '#') /* Numbers */ else if (next == '#') /* Numbers */
{ {
unsigned int number = 0; unsigned int number = 0;

View File

@ -28,6 +28,8 @@
#define TYPE_ADDR 4 #define TYPE_ADDR 4
#define TYPE_PC_BANK 5 #define TYPE_PC_BANK 5
#define TYPE_DATA_BANK 6 #define TYPE_DATA_BANK 6
#define TYPE_VALUE_READ 7
#define TYPE_VALUE_WRITE 8
#define OP_NO 0 #define OP_NO 0
#define OP_EQ 1 #define OP_EQ 1
@ -43,7 +45,9 @@
#define OP_OR 11 #define OP_OR 11
#define OP_AND 12 #define OP_AND 12
extern uint16 addressOfTheLastAccessedData; extern uint16 debugLastAddress;
extern uint8 debugLastOpcode;
//mbg merge 7/18/06 turned into sane c++ //mbg merge 7/18/06 turned into sane c++
struct Condition struct Condition
{ {

View File

@ -18,10 +18,13 @@ char *FCEUI_GetAboutString() {
const char *aboutTemplate = const char *aboutTemplate =
FCEU_NAME_AND_VERSION "\n\n" FCEU_NAME_AND_VERSION "\n\n"
"Administrators:\n" "Administrators:\n"
"zeromus, adelikat, AnS\n\n" "zeromus, punkrockguy318 (Lukas Sabota), feos\n"
"\n"
"Current Contributors:\n" "Current Contributors:\n"
"punkrockguy318 (Lukas Sabota)\n" "CaH4e3, rainwarrior\n"
"CaH4e3, gocha, xhainingx, feos\n" "\n"
"Past Contributors:\n"
"xhainingx, gocha, AnS\n"
"\n" "\n"
"FCEUX 2.0:\n" "FCEUX 2.0:\n"
"mz, nitsujrehtona, SP, Ugly Joe,\n" "mz, nitsujrehtona, SP, Ugly Joe,\n"

View File

@ -77,6 +77,7 @@ int getValue(int type)
case 'Z': return _P & Z_FLAG ? 1 : 0; case 'Z': return _P & Z_FLAG ? 1 : 0;
case 'C': return _P & C_FLAG ? 1 : 0; case 'C': return _P & C_FLAG ? 1 : 0;
case 'P': return _PC; case 'P': return _PC;
case 'S': return _S;
} }
return 0; return 0;
@ -290,9 +291,13 @@ uint8 GetMem(uint16 A) {
} }
else if ((A >= 0x4018) && (A < 0x5000)) // AnS: changed the range, so MMC5 ExRAM can be watched in the Hexeditor else if ((A >= 0x4018) && (A < 0x5000)) // AnS: changed the range, so MMC5 ExRAM can be watched in the Hexeditor
return 0xFF; return 0xFF;
if (GameInfo) //adelikat: 11/17/09: Prevent crash if this is called with no game loaded. if (GameInfo) { //adelikat: 11/17/09: Prevent crash if this is called with no game loaded.
return ARead[A](A); uint32 ret;
else return 0; fceuindbg=1;
ret = ARead[A](A);
fceuindbg=0;
return ret;
} else return 0;
} }
uint8 GetPPUMem(uint8 A) { uint8 GetPPUMem(uint8 A) {
@ -305,6 +310,32 @@ uint8 GetPPUMem(uint8 A) {
//--------------------- //---------------------
uint8 evaluateWrite(uint8 opcode, uint16 address)
{
// predicts value written by this opcode
switch (opwrite[opcode])
{
default:
case 0: return 0; // no write
case 1: return _A; // STA, PHA
case 2: return _X; // STX
case 3: return _Y; // STY
case 4: return _P; // PHP
case 5: return GetMem(address) << 1; // ASL (SLO)
case 6: return GetMem(address) >> 1; // LSR (SRE)
case 7: return (GetMem(address) << 1) | (_P & 1); // ROL (RLA)
case 8: return (GetMem(address) >> 1) | ((_P & 1) << 7); // ROL (RRA)
case 9: return GetMem(address) + 1; // INC (ISC)
case 10: return GetMem(address) - 1; // DEC (DCP)
case 11: return _A & _X; // (SAX)
case 12: return _A&_X&(((address-_Y)>>8)+1); // (AHX)
case 13: return _Y&(((address-_X)>>8)+1); // (SHY)
case 14: return _X&(((address-_Y)>>8)+1); // (SHX)
case 15: return _S& (((address-_Y)>>8)+1); // (TAS)
}
return 0;
}
// Evaluates a condition // Evaluates a condition
int evaluate(Condition* c) int evaluate(Condition* c)
{ {
@ -330,7 +361,9 @@ int evaluate(Condition* c)
{ {
case TYPE_ADDR: value1 = GetMem(value1); break; case TYPE_ADDR: value1 = GetMem(value1); break;
case TYPE_PC_BANK: value1 = getBank(_PC); break; case TYPE_PC_BANK: value1 = getBank(_PC); break;
case TYPE_DATA_BANK: value1 = getBank(addressOfTheLastAccessedData); break; case TYPE_DATA_BANK: value1 = getBank(debugLastAddress); break;
case TYPE_VALUE_READ: value1 = GetMem(debugLastAddress); break;
case TYPE_VALUE_WRITE: value1 = evaluateWrite(debugLastOpcode, debugLastAddress); break;
} }
f = value1; f = value1;
@ -355,7 +388,9 @@ int evaluate(Condition* c)
{ {
case TYPE_ADDR: value2 = GetMem(value2); break; case TYPE_ADDR: value2 = GetMem(value2); break;
case TYPE_PC_BANK: value2 = getBank(_PC); break; case TYPE_PC_BANK: value2 = getBank(_PC); break;
case TYPE_DATA_BANK: value2 = getBank(addressOfTheLastAccessedData); break; case TYPE_DATA_BANK: value2 = getBank(debugLastAddress); break;
case TYPE_VALUE_READ: value2 = GetMem(debugLastAddress); break;
case TYPE_VALUE_WRITE: value2 = evaluateWrite(debugLastOpcode, debugLastAddress); break;
} }
switch (c->op) switch (c->op)
@ -367,7 +402,7 @@ int evaluate(Condition* c)
case OP_G: f = value1 > value2; break; case OP_G: f = value1 > value2; break;
case OP_L: f = value1 < value2; break; case OP_L: f = value1 < value2; break;
case OP_MULT: f = value1 * value2; break; case OP_MULT: f = value1 * value2; break;
case OP_DIV: f = value1 / value2; break; case OP_DIV: f = (value2==0) ? 0 : (value1 / value2); break;
case OP_PLUS: f = value1 + value2; break; case OP_PLUS: f = value1 + value2; break;
case OP_MINUS: f = value1 - value2; break; case OP_MINUS: f = value1 - value2; break;
case OP_OR: f = value1 || value2; break; case OP_OR: f = value1 || value2; break;
@ -502,6 +537,11 @@ void BreakHit(int bp_num, bool force)
{ {
if(!force) if(!force)
{ {
if (bp_num >= 0 && !condition(&watchpoint[bp_num]))
{
return; // condition rejected
}
//check to see whether we fall in any forbid zone //check to see whether we fall in any forbid zone
for (int i = 0; i < numWPs; i++) for (int i = 0; i < numWPs; i++)
{ {
@ -529,7 +569,7 @@ void BreakHit(int bp_num, bool force)
#endif #endif
} }
uint8 StackAddrBackup = X.S; int StackAddrBackup;
uint16 StackNextIgnorePC = 0xFFFF; uint16 StackNextIgnorePC = 0xFFFF;
///fires a breakpoint ///fires a breakpoint
@ -539,6 +579,9 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
uint8 stackop=0; uint8 stackop=0;
uint8 stackopstartaddr,stackopendaddr; uint8 stackopstartaddr,stackopendaddr;
debugLastAddress = A;
debugLastOpcode = opcode[0];
if (break_asap) if (break_asap)
{ {
break_asap = false; break_asap = false;
@ -601,24 +644,25 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
switch (opcode[0]) { switch (opcode[0]) {
//Push Ops //Push Ops
case 0x08: //Fall to next case 0x08: //Fall to next
case 0x48: stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break; case 0x48: debugLastAddress=stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
//Pull Ops //Pull Ops
case 0x28: //Fall to next case 0x28: //Fall to next
case 0x68: stackopstartaddr=stackopendaddr=X.S+1; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break; case 0x68: debugLastAddress=stackopstartaddr=stackopendaddr=X.S+1; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
//JSR (Includes return address - 1) //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; 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) //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; 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) //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; case 0x60: stackopstartaddr=X.S+1; stackopendaddr=X.S+2; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=(GetMem(stackopstartaddr|0x0100)|GetMem(stackopendaddr|0x0100)<<8)+1; break;
default: break;
} }
#define BREAKHIT(x) { breakHit = (x); goto STOPCHECKING; }
int breakHit = -1;
for (i = 0; i < numWPs; i++) for (i = 0; i < numWPs; i++)
{ {
// ################################## Start of SP CODE ########################### if ((watchpoint[i].flags & WP_E))
if ((watchpoint[i].flags & WP_E) && condition(&watchpoint[i]))
{ {
// ################################## End of SP CODE ###########################
if (watchpoint[i].flags & BT_P) if (watchpoint[i].flags & BT_P)
{ {
// PPU Mem breaks // PPU Mem breaks
@ -628,11 +672,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
if (watchpoint[i].endaddress) if (watchpoint[i].endaddress)
{ {
if ((watchpoint[i].address <= PPUAddr) && (watchpoint[i].endaddress >= PPUAddr)) if ((watchpoint[i].address <= PPUAddr) && (watchpoint[i].endaddress >= PPUAddr))
BreakHit(i); BREAKHIT(i);
} else } else
{ {
if (watchpoint[i].address == PPUAddr) if (watchpoint[i].address == PPUAddr)
BreakHit(i); BREAKHIT(i);
} }
} }
} else if (watchpoint[i].flags & BT_S) } else if (watchpoint[i].flags & BT_S)
@ -643,16 +687,16 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
if (watchpoint[i].endaddress) if (watchpoint[i].endaddress)
{ {
if ((watchpoint[i].address <= PPU[3]) && (watchpoint[i].endaddress >= PPU[3])) if ((watchpoint[i].address <= PPU[3]) && (watchpoint[i].endaddress >= PPU[3]))
BreakHit(i); BREAKHIT(i);
} else } else
{ {
if (watchpoint[i].address == PPU[3]) if (watchpoint[i].address == PPU[3])
BreakHit(i); BREAKHIT(i);
} }
} else if ((watchpoint[i].flags & WP_W) && (A == 0x4014)) } else if ((watchpoint[i].flags & WP_W) && (A == 0x4014))
{ {
// Sprite DMA! :P // Sprite DMA! :P
BreakHit(i); BREAKHIT(i);
} }
} else } else
{ {
@ -663,12 +707,12 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
{ {
if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address <= A) && (watchpoint[i].endaddress >= A)) || 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))) ((watchpoint[i].flags & WP_X) && (watchpoint[i].address <= _PC) && (watchpoint[i].endaddress >= _PC)))
BreakHit(i); BREAKHIT(i);
} else } else
{ {
if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address == A)) || if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address == A)) ||
((watchpoint[i].flags & WP_X) && (watchpoint[i].address == _PC))) ((watchpoint[i].flags & WP_X) && (watchpoint[i].address == _PC)))
BreakHit(i); BREAKHIT(i);
} }
} else } else
{ {
@ -685,11 +729,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
if (watchpoint[i].endaddress) if (watchpoint[i].endaddress)
{ {
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j)) if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
BreakHit(i); BREAKHIT(i);
} else } else
{ {
if (watchpoint[i].address == j) if (watchpoint[i].address == j)
BreakHit(i); BREAKHIT(i);
} }
} }
} }
@ -700,7 +744,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
StackNextIgnorePC = 0xFFFF; StackNextIgnorePC = 0xFFFF;
} else } else
{ {
if ((X.S < StackAddrBackup) && (stackop==0)) if (StackAddrBackup != -1 && (X.S < StackAddrBackup) && (stackop==0))
{ {
// Unannounced stack mem breaks // Unannounced stack mem breaks
// Pushes to stack // Pushes to stack
@ -711,15 +755,15 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
if (watchpoint[i].endaddress) if (watchpoint[i].endaddress)
{ {
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j)) if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
BreakHit(i); BREAKHIT(i);
} else } else
{ {
if (watchpoint[i].address == j) if (watchpoint[i].address == j)
BreakHit(i); BREAKHIT(i);
} }
} }
} }
} else if ((StackAddrBackup < X.S) && (stackop==0)) } else if (StackAddrBackup != -1 && (StackAddrBackup < X.S) && (stackop==0))
{ {
// Pulls from stack // Pulls from stack
if (watchpoint[i].flags & WP_R) if (watchpoint[i].flags & WP_R)
@ -729,11 +773,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
if (watchpoint[i].endaddress) if (watchpoint[i].endaddress)
{ {
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j)) if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
BreakHit(i); BREAKHIT(i);
} else } else
{ {
if (watchpoint[i].address == j) if (watchpoint[i].address == j)
BreakHit(i); BREAKHIT(i);
} }
} }
} }
@ -742,13 +786,20 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
} }
} }
// ################################## Start of SP CODE ###########################
} }
// ################################## End of SP CODE ########################### } //loop across all breakpoints
}
STOPCHECKING:
//Update the stack address with the current one, now that changes have registered. //Update the stack address with the current one, now that changes have registered.
//ZEROMUS THINKS IT MAKES MORE SENSE HERE
StackAddrBackup = X.S; StackAddrBackup = X.S;
if(breakHit != -1)
BreakHit(i);
////Update the stack address with the current one, now that changes have registered.
//StackAddrBackup = X.S;
} }
//bbit edited: this is the end of the inserted code //bbit edited: this is the end of the inserted code
@ -777,9 +828,12 @@ void DebugCycle()
size = opsize[opcode[0]]; size = opsize[opcode[0]];
switch (size) switch (size)
{ {
default:
case 1: break;
case 2: case 2:
opcode[1] = GetMem(_PC + 1); opcode[1] = GetMem(_PC + 1);
break; break;
case 0: // illegal instructions may have operands
case 3: case 3:
opcode[1] = GetMem(_PC + 1); opcode[1] = GetMem(_PC + 1);
opcode[2] = GetMem(_PC + 2); opcode[2] = GetMem(_PC + 2);
@ -803,7 +857,6 @@ void DebugCycle()
case 7: A = (opcode[1] | (opcode[2] << 8)) + _X; break; case 7: A = (opcode[1] | (opcode[2] << 8)) + _X; break;
case 8: A = opcode[1] + _Y; break; case 8: A = opcode[1] + _Y; break;
} }
addressOfTheLastAccessedData = A;
if (numWPs || dbgstate.step || dbgstate.runline || dbgstate.stepout || watchpoint[64].flags || dbgstate.badopbreak || break_on_cycles || break_on_instructions || break_asap) if (numWPs || dbgstate.step || dbgstate.runline || dbgstate.stepout || watchpoint[64].flags || dbgstate.badopbreak || break_on_cycles || break_on_instructions || break_asap)
breakpoint(opcode, A, size); breakpoint(opcode, A, size);

View File

@ -49,13 +49,11 @@ typedef struct {
uint16 address; uint16 address;
uint16 endaddress; uint16 endaddress;
uint8 flags; uint8 flags;
// ################################## Start of SP CODE ###########################
Condition* cond; Condition* cond;
char* condText; char* condText;
char* desc; char* desc;
// ################################## End of SP CODE ###########################
} watchpointinfo; } watchpointinfo;
//mbg merge 7/18/06 had to make this extern //mbg merge 7/18/06 had to make this extern
@ -117,8 +115,6 @@ extern void IncrementInstructionsCounters();
extern uint8 *vnapage[4],*VPage[8]; extern uint8 *vnapage[4],*VPage[8];
extern uint8 PPU[4],PALRAM[0x20],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset; extern uint8 PPU[4],PALRAM[0x20],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset;
extern uint32 FCEUPPU_PeekAddress(); extern uint32 FCEUPPU_PeekAddress();
extern int debug_loggingCD;
extern int numWPs; extern int numWPs;
///encapsulates the operational state of the debugger core ///encapsulates the operational state of the debugger core

View File

@ -68,7 +68,7 @@ void FCEUI_NTSCSELTINT(void);
void FCEUI_NTSCDEC(void); void FCEUI_NTSCDEC(void);
void FCEUI_NTSCINC(void); void FCEUI_NTSCINC(void);
void FCEUI_GetNTSCTH(int *tint, int *hue); void FCEUI_GetNTSCTH(int *tint, int *hue);
void FCEUI_SetNTSCTH(int n, int tint, int hue); void FCEUI_SetNTSCTH(bool en, int tint, int hue);
void FCEUI_SetInput(int port, ESI type, void *ptr, int attrib); void FCEUI_SetInput(int port, ESI type, void *ptr, int attrib);
void FCEUI_SetInputFC(ESIFC type, void *ptr, int attrib); void FCEUI_SetInputFC(ESIFC type, void *ptr, int attrib);
@ -122,7 +122,7 @@ void FCEUI_SetVidSystem(int a);
//Set variables for NTSC(0) / PAL(1) / Dendy(2) //Set variables for NTSC(0) / PAL(1) / Dendy(2)
//Dendy has PAL framerate and resolution, but ~NTSC timings, and has 50 dummy scanlines to force 50 fps //Dendy has PAL framerate and resolution, but ~NTSC timings, and has 50 dummy scanlines to force 50 fps
void FCEUI_SetRegion(int region); void FCEUI_SetRegion(int region, int notify = 1);
//Convenience function; returns currently emulated video system(0=NTSC, 1=PAL). //Convenience function; returns currently emulated video system(0=NTSC, 1=PAL).
int FCEUI_GetCurrentVidSystem(int *slstart, int *slend); int FCEUI_GetCurrentVidSystem(int *slstart, int *slend);
@ -141,9 +141,7 @@ void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall);
//Sets the base directory(save states, snapshots, etc. are saved in directories below this directory. //Sets the base directory(save states, snapshots, etc. are saved in directories below this directory.
void FCEUI_SetBaseDirectory(std::string const & dir); void FCEUI_SetBaseDirectory(std::string const & dir);
//Tells FCE Ultra to copy the palette data pointed to by pal and use it. void FCEUI_SetUserPalette(uint8 *pal, int nEntries);
//Data pointed to by pal needs to be 64*3 bytes in length.
void FCEUI_SetPaletteArray(uint8 *pal);
//Sets up sound code to render sound at the specified rate, in samples //Sets up sound code to render sound at the specified rate, in samples
//per second. Only sample rates of 44100, 48000, and 96000 are currently supported. //per second. Only sample rates of 44100, 48000, and 96000 are currently supported.

View File

@ -56,9 +56,10 @@ extern bool isTaseditorRecording();
extern int32 fps_scale; extern int32 fps_scale;
extern int32 fps_scale_unpaused; extern int32 fps_scale_unpaused;
extern int32 fps_scale_frameadvance; extern int32 fps_scale_frameadvance;
extern void RefreshThrottleFPS();
#endif #endif
extern void RefreshThrottleFPS();
#ifdef _S9XLUA_H #ifdef _S9XLUA_H
#include "fceulua.h" #include "fceulua.h"
#endif #endif
@ -93,6 +94,20 @@ extern void RefreshThrottleFPS();
using namespace std; using namespace std;
//-----------
//overclocking-related
// overclock the console by adding dummy scanlines to PPU loop or to vblank
// disables DMC DMA, WaveHi filling and image rendering for these dummies
// doesn't work with new PPU
bool overclock_enabled = 0;
bool overclocking = 0;
bool skip_7bit_overclocking = 1; // 7-bit samples have priority over overclocking
int normalscanlines;
int totalscanlines;
int postrenderscanlines = 0;
int vblankscanlines = 0;
//------------
int AFon = 1, AFoff = 1, AutoFireOffset = 0; //For keeping track of autofire settings int AFon = 1, AFoff = 1, AutoFireOffset = 0; //For keeping track of autofire settings
bool justLagged = false; bool justLagged = false;
bool frameAdvanceLagSkip = false; //If this is true, frame advance will skip over lag frame (i.e. it will emulate 2 frames instead of 1) bool frameAdvanceLagSkip = false; //If this is true, frame advance will skip over lag frame (i.e. it will emulate 2 frames instead of 1)
@ -101,7 +116,6 @@ bool movieSubtitles = true; //Toggle for displaying movie subtitles
bool DebuggerWasUpdated = false; //To prevent the debugger from updating things without being updated. bool DebuggerWasUpdated = false; //To prevent the debugger from updating things without being updated.
bool AutoResumePlay = false; bool AutoResumePlay = false;
char romNameWhenClosingEmulator[2048] = {0}; char romNameWhenClosingEmulator[2048] = {0};
int dendy = 0;
FCEUGI::FCEUGI() FCEUGI::FCEUGI()
: filename(0), : filename(0),
@ -140,10 +154,12 @@ void FCEU_TogglePPU(void) {
if (newppu) { if (newppu) {
FCEU_DispMessage("New PPU loaded", 0); FCEU_DispMessage("New PPU loaded", 0);
FCEUI_printf("New PPU loaded"); FCEUI_printf("New PPU loaded");
overclock_enabled = 0;
} else { } else {
FCEU_DispMessage("Old PPU loaded", 0); FCEU_DispMessage("Old PPU loaded", 0);
FCEUI_printf("Old PPU loaded"); FCEUI_printf("Old PPU loaded");
} }
normalscanlines = (dendy ? 290 : 240)+newppu; // use flag as number!
#ifdef WIN32 #ifdef WIN32
SetMainWindowText(); SetMainWindowText();
#endif #endif
@ -348,16 +364,10 @@ uint8 PAL = 0;
static DECLFW(BRAML) { static DECLFW(BRAML) {
RAM[A] = V; RAM[A] = V;
#ifdef _S9XLUA_H
CallRegisteredLuaMemHook(A, 1, V, LUAMEMHOOK_WRITE);
#endif
} }
static DECLFW(BRAMH) { static DECLFW(BRAMH) {
RAM[A & 0x7FF] = V; RAM[A & 0x7FF] = V;
#ifdef _S9XLUA_H
CallRegisteredLuaMemHook(A & 0x7FF, 1, V, LUAMEMHOOK_WRITE);
#endif
} }
static DECLFR(ARAML) { static DECLFR(ARAML) {
@ -384,7 +394,7 @@ void ResetGameLoaded(void) {
MMC5Hack = 0; MMC5Hack = 0;
PEC586Hack = 0; PEC586Hack = 0;
PAL &= 1; PAL &= 1;
pale = 0; default_palette_selection = 0;
} }
int UNIFLoad(const char *name, FCEUFILE *fp); int UNIFLoad(const char *name, FCEUFILE *fp);
@ -401,6 +411,8 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
//attempt to open the files //attempt to open the files
FCEUFILE *fp; FCEUFILE *fp;
char fullname[2048]; // this name contains both archive name and ROM file name char fullname[2048]; // this name contains both archive name and ROM file name
int lastpal = PAL;
int lastdendy = dendy;
const char* romextensions[] = { "nes", "fds", 0 }; const char* romextensions[] = { "nes", "fds", 0 };
fp = FCEU_fopen(name, 0, "rb", 0, -1, romextensions); fp = FCEU_fopen(name, 0, "rb", 0, -1, romextensions);
@ -488,7 +500,8 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
// ################################## End of SP CODE ########################### // ################################## End of SP CODE ###########################
#endif #endif
FCEU_ResetVidSys(); if (OverwriteVidMode)
FCEU_ResetVidSys();
if (GameInfo->type != GIT_NSF) if (GameInfo->type != GIT_NSF)
{ {
@ -511,6 +524,18 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
FCEU_ResetPalette(); FCEU_ResetPalette();
FCEU_ResetMessages(); // Save state, status messages, etc. FCEU_ResetMessages(); // Save state, status messages, etc.
if (!lastpal && PAL) {
FCEU_DispMessage("PAL mode set", 0);
FCEUI_printf("PAL mode set");
} else if (!lastdendy && dendy) {
// this won't happen, since we don't autodetect dendy, but maybe someday we will?
FCEU_DispMessage("Dendy mode set", 0);
FCEUI_printf("Dendy mode set");
} else if ((lastpal || lastdendy) && !(PAL || dendy)) {
FCEU_DispMessage("NTSC mode set", 0);
FCEUI_printf("NTSC mode set");
}
if (GameInfo->type != GIT_NSF) if (GameInfo->type != GIT_NSF)
FCEU_LoadGameCheats(0); FCEU_LoadGameCheats(0);
@ -712,10 +737,15 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
extern int KillFCEUXonFrame; extern int KillFCEUXonFrame;
if (KillFCEUXonFrame && (FCEUMOV_GetFrame() >= KillFCEUXonFrame)) if (KillFCEUXonFrame && (FCEUMOV_GetFrame() >= KillFCEUXonFrame))
DoFCEUExit(); DoFCEUExit();
#else
extern int KillFCEUXonFrame;
if (KillFCEUXonFrame && (FCEUMOV_GetFrame() >= KillFCEUXonFrame))
exit(0);
#endif #endif
timestampbase += timestamp; timestampbase += timestamp;
timestamp = 0; timestamp = 0;
soundtimestamp = 0;
*pXBuf = skip ? 0 : XBuf; *pXBuf = skip ? 0 : XBuf;
if (skip == 2) { //If skip = 2, then bypass sound if (skip == 2) { //If skip = 2, then bypass sound
@ -769,17 +799,79 @@ void ResetNES(void) {
//FCEU_DispMessage("Reset", 0); //FCEU_DispMessage("Reset", 0);
} }
void FCEU_MemoryRand(uint8 *ptr, uint32 size) {
int RAMInitSeed = 0;
int RAMInitOption = 0;
u64 splitmix64(u32 input) {
u64 z = (input + 0x9e3779b97f4a7c15);
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
return z ^ (z >> 31);
}
static inline u64 xoroshiro128plus_rotl(const u64 x, int k) {
return (x << k) | (x >> (64 - k));
}
u64 xoroshiro128plus_s[2];
void xoroshiro128plus_seed(u32 input)
{
//http://xoroshiro.di.unimi.it/splitmix64.c
u64 x = input;
u64 z = (x += 0x9e3779b97f4a7c15);
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
xoroshiro128plus_s[0] = z ^ (z >> 31);
z = (x += 0x9e3779b97f4a7c15);
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
xoroshiro128plus_s[1] = z ^ (z >> 31);
}
//http://vigna.di.unimi.it/xorshift/xoroshiro128plus.c
u64 xoroshiro128plus_next() {
const u64 s0 = xoroshiro128plus_s[0];
u64 s1 = xoroshiro128plus_s[1];
const u64 result = s0 + s1;
s1 ^= s0;
xoroshiro128plus_s[0] = xoroshiro128plus_rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b
xoroshiro128plus_s[1] = xoroshiro128plus_rotl(s1, 36); // c
return result;
}
void FCEU_MemoryRand(uint8 *ptr, uint32 size, bool default_zero) {
int x = 0; int x = 0;
while (size) { while (size) {
*ptr = (x & 4) ? 0xFF : 0x00; // Huang Di DEBUG MODE enabled by default uint8 v = 0;
// Cybernoid NO MUSIC by default switch (RAMInitOption)
// *ptr = (x & 4) ? 0x7F : 0x00; // Huang Di DEBUG MODE enabled by default {
// Minna no Taabou no Nakayoshi Daisakusen DOESN'T BOOT default:
// Cybernoid NO MUSIC by default case 0:
// *ptr = (x & 1) ? 0x55 : 0xAA; // F-15 Sity War HISCORE is screwed... if (!default_zero) v = (x & 4) ? 0xFF : 0x00;
// 1942 SCORE/HISCORE is screwed... else v = 0x00;
// *ptr = 0xFF; // Work for all cases break;
case 1: v = 0xFF; break;
case 2: v = 0x00; break;
case 3: v = (u8)(xoroshiro128plus_next()); break;
// the default is this 8 byte pattern: 00 00 00 00 FF FF FF FF
// it has been used in FCEUX since time immemorial
// Some games to examine uninitialied RAM problems with:
// * Cybernoid - music option starts turned off with default pattern
// * Huang Di - debug mode is enabled with default pattern
// * Minna no Taabou no Nakayoshi Daisakusen - fails to boot with some patterns
// * F-15 City War - high score table
// * 1942 - high score table
// * Cheetahmen II - may start in different levels with different RAM startup
}
*ptr = v;
x++; x++;
size--; size--;
ptr++; ptr++;
@ -793,18 +885,21 @@ void PowerNES(void) {
FCEUMOV_AddCommand(FCEUNPCMD_POWER); FCEUMOV_AddCommand(FCEUNPCMD_POWER);
if (!GameInfo) return; if (!GameInfo) return;
//reseed random, unless we're in a movie
extern int disableBatteryLoading;
if(FCEUMOV_Mode(MOVIEMODE_INACTIVE) && !disableBatteryLoading)
{
RAMInitSeed = rand() ^ (u32)xoroshiro128plus_next();
}
//always reseed the PRNG with the current seed, for deterministic results (for that seed)
xoroshiro128plus_seed(RAMInitSeed);
FCEU_CheatResetRAM(); FCEU_CheatResetRAM();
FCEU_CheatAddRAM(2, 0, RAM); FCEU_CheatAddRAM(2, 0, RAM);
FCEU_GeniePower(); FCEU_GeniePower();
//dont do this, it breaks some games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; and maybe mechanized attack
//memset(RAM,0xFF,0x800);
//this fixes the above, but breaks Huang Di, which expects $100 to be non-zero or else it believes it has debug cheats enabled, giving you moon jump and other great but likely unwanted things
//FCEU_MemoryRand(RAM,0x800);
//this should work better, based on observational evidence. fixes all of the above:
//for(int i=0;i<0x800;i++) if(i&1) RAM[i] = 0xAA; else RAM[i] = 0x55;
//but we're leaving this for now until we collect some more data
FCEU_MemoryRand(RAM, 0x800); FCEU_MemoryRand(RAM, 0x800);
SetReadHandler(0x0000, 0xFFFF, ANull); SetReadHandler(0x0000, 0xFFFF, ANull);
@ -845,7 +940,7 @@ void PowerNES(void) {
Update_RAM_Search(); // Update_RAM_Watch() is also called. Update_RAM_Search(); // Update_RAM_Watch() is also called.
#endif #endif
//FCEU_DispMessage("Power on", 0); FCEU_DispMessage("Power on", 0);
} }
void FCEU_ResetVidSys(void) { void FCEU_ResetVidSys(void) {
@ -861,6 +956,14 @@ void FCEU_ResetVidSys(void) {
PAL = w ? 1 : 0; PAL = w ? 1 : 0;
if (PAL)
dendy = 0;
if (newppu)
overclock_enabled = 0;
normalscanlines = (dendy ? 290 : 240)+newppu; // use flag as number!
totalscanlines = normalscanlines + (overclock_enabled ? postrenderscanlines : 0);
FCEUPPU_SetVideoSystem(w || dendy); FCEUPPU_SetVideoSystem(w || dendy);
SetSoundVariables(); SetSoundVariables();
} }
@ -877,6 +980,13 @@ void FCEU_printf(char *format, ...) {
vsnprintf(temp, sizeof(temp), format, ap); vsnprintf(temp, sizeof(temp), format, ap);
FCEUD_Message(temp); FCEUD_Message(temp);
#if 0
FILE *ofile;
ofile = fopen("stdout.txt", "ab");
fwrite(temp, 1, strlen(temp), ofile);
fclose(ofile);
#endif
va_end(ap); va_end(ap);
#endif #endif
} }
@ -925,30 +1035,58 @@ int FCEUI_GetCurrentVidSystem(int *slstart, int *slend) {
*slend = FSettings.LastSLine; *slend = FSettings.LastSLine;
return(PAL); return(PAL);
} }
/*
// TODO: make use on SDL #ifndef GEKKO
void FCEUI_SetRegion(int region) { void FCEUI_SetRegion(int region, int notify) {
switch (region) { switch (region) {
case 0: // NTSC case 0: // NTSC
normalscanlines = 240;
pal_emulation = 0; pal_emulation = 0;
dendy = 0; dendy = 0;
// until it's fixed on sdl. see issue #740
#ifdef WIN32
if (notify)
{
FCEU_DispMessage("NTSC mode set", 0);
FCEUI_printf("NTSC mode set");
}
#endif
break; break;
case 1: // PAL case 1: // PAL
normalscanlines = 240;
pal_emulation = 1; pal_emulation = 1;
dendy = 0; dendy = 0;
#ifdef WIN32
if (notify)
{
FCEU_DispMessage("PAL mode set", 0);
FCEUI_printf("PAL mode set");
}
#endif
break; break;
case 2: // Dendy case 2: // Dendy
normalscanlines = 290;
pal_emulation = 0; pal_emulation = 0;
dendy = 1; dendy = 1;
#ifdef WIN32
if (notify)
{
FCEU_DispMessage("Dendy mode set", 0);
FCEUI_printf("Dendy mode set");
}
#endif
break; break;
} }
normalscanlines += newppu;
totalscanlines = normalscanlines + (overclock_enabled ? postrenderscanlines : 0);
FCEUI_SetVidSystem(pal_emulation); FCEUI_SetVidSystem(pal_emulation);
RefreshThrottleFPS(); RefreshThrottleFPS();
#ifdef WIN32 #ifdef WIN32
UpdateCheckedMenuItems(); UpdateCheckedMenuItems();
PushCurrentVideoSettings(); PushCurrentVideoSettings();
#endif #endif
}*/ }
#endif
//Enable or disable Game Genie option. //Enable or disable Game Genie option.
void FCEUI_SetGameGenie(bool a) { void FCEUI_SetGameGenie(bool a) {
@ -1052,9 +1190,7 @@ int FCEU_TextScanlineOffsetFromBottom(int y) {
} }
bool FCEU_IsValidUI(EFCEUI ui) { bool FCEU_IsValidUI(EFCEUI ui) {
#ifdef GEKKO #ifndef GEKKO
return true;
#endif
switch (ui) { switch (ui) {
case FCEUI_OPENGAME: case FCEUI_OPENGAME:
case FCEUI_CLOSEGAME: case FCEUI_CLOSEGAME:
@ -1099,6 +1235,7 @@ bool FCEU_IsValidUI(EFCEUI ui) {
if (!FCEUMOV_Mode(MOVIEMODE_INACTIVE)) return false; if (!FCEUMOV_Mode(MOVIEMODE_INACTIVE)) return false;
break; break;
} }
#endif
return true; return true;
} }
@ -1165,8 +1302,6 @@ void FCEUXGameInterface(GI command) {
} }
} }
bool FCEUXLoad(const char *name, FCEUFILE *fp) { bool FCEUXLoad(const char *name, FCEUFILE *fp) {
//read ines header //read ines header
iNES_HEADER head; iNES_HEADER head;
@ -1218,11 +1353,26 @@ bool FCEUXLoad(const char *name, FCEUFILE *fp) {
return true; return true;
} }
uint8 FCEU_ReadRomByte(uint32 i) { uint8 FCEU_ReadRomByte(uint32 i) {
extern iNES_HEADER head; extern iNES_HEADER head;
if (i < 16) return *((unsigned char*)&head + i); if (i < 16)
if (i < 16 + PRGsize[0]) return PRGptr[0][i - 16]; return *((unsigned char*)&head + i);
if (i < 16 + PRGsize[0] + CHRsize[0]) return CHRptr[0][i - 16 - PRGsize[0]]; if (i < 16 + PRGsize[0])
return PRGptr[0][i - 16];
if (i < 16 + PRGsize[0] + CHRsize[0])
return CHRptr[0][i - 16 - PRGsize[0]];
return 0; return 0;
} }
void FCEU_WriteRomByte(uint32 i, uint8 value) {
if (i < 16)
#ifdef WIN32
MessageBox(hMemView,"Sorry", "You can't edit the ROM header.", MB_OK);
#else
printf("Sorry, you can't edit the ROM header.\n");
#endif
if (i < 16 + PRGsize[0])
PRGptr[0][i - 16] = value;
else if (i < 16 + PRGsize[0] + CHRsize[0])
CHRptr[0][i - 16 - PRGsize[0]] = value;
}

View File

@ -7,13 +7,22 @@ extern int fceuindbg;
extern int newppu; extern int newppu;
void ResetGameLoaded(void); void ResetGameLoaded(void);
//overclocking-related
extern bool overclock_enabled;
extern bool overclocking;
extern bool skip_7bit_overclocking;
extern int normalscanlines;
extern int totalscanlines;
extern int postrenderscanlines;
extern int vblankscanlines;
extern bool AutoResumePlay; extern bool AutoResumePlay;
extern char romNameWhenClosingEmulator[]; extern char romNameWhenClosingEmulator[];
#define DECLFR(x) uint8 x (uint32 A) #define DECLFR(x) uint8 x (uint32 A)
#define DECLFW(x) void x (uint32 A, uint8 V) #define DECLFW(x) void x (uint32 A, uint8 V)
void FCEU_MemoryRand(uint8 *ptr, uint32 size); void FCEU_MemoryRand(uint8 *ptr, uint32 size, bool default_zero=false);
void SetReadHandler(int32 start, int32 end, readfunc func); void SetReadHandler(int32 start, int32 end, readfunc func);
void SetWriteHandler(int32 start, int32 end, writefunc func); void SetWriteHandler(int32 start, int32 end, writefunc func);
writefunc GetWriteHandler(int32 a); writefunc GetWriteHandler(int32 a);
@ -54,6 +63,7 @@ extern uint8 *RAM; //shared memory modifications
extern int EmulationPaused; extern int EmulationPaused;
uint8 FCEU_ReadRomByte(uint32 i); uint8 FCEU_ReadRomByte(uint32 i);
void FCEU_WriteRomByte(uint32 i, uint8 value);
extern readfunc ARead[0x10000]; extern readfunc ARead[0x10000];
extern writefunc BWrite[0x10000]; extern writefunc BWrite[0x10000];
@ -121,7 +131,7 @@ void FCEU_DispMessage(char *format, int disppos, ...);
void FCEU_DispMessageOnMovie(char *format, ...); void FCEU_DispMessageOnMovie(char *format, ...);
void FCEU_TogglePPU(); void FCEU_TogglePPU();
void SetNESDeemph(uint8 d, int force); void SetNESDeemph_OldHacky(uint8 d, int force);
void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor); void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor);
void FCEU_PutImage(void); void FCEU_PutImage(void);
#ifdef FRAMESKIP #ifdef FRAMESKIP
@ -134,7 +144,7 @@ extern void PushCurrentVideoSettings();
#endif #endif
extern uint8 Exit; extern uint8 Exit;
extern uint8 pale; extern int default_palette_selection;
extern uint8 vsdip; extern uint8 vsdip;
//#define FCEUDEF_DEBUGGER //mbg merge 7/17/06 - cleaning out conditional compiles //#define FCEUDEF_DEBUGGER //mbg merge 7/17/06 - cleaning out conditional compiles

View File

@ -18,10 +18,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h" #include "types.h"
#include "x6502.h" #include "x6502.h"
#include "fceu.h" #include "fceu.h"
@ -37,10 +33,14 @@
#include "driver.h" #include "driver.h"
#include "movie.h" #include "movie.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
// TODO: Add code to put a delay in between the time a disk is inserted // TODO: Add code to put a delay in between the time a disk is inserted
// and the when it can be successfully read/written to. This should // and the when it can be successfully read/written to. This should
// prevent writes to wrong places OR add code to prevent disk ejects // prevent writes to wrong places OR add code to prevent disk ejects
// when the virtual motor is on(mmm...virtual motor). // when the virtual motor is on (mmm...virtual motor).
extern int disableBatteryLoading; extern int disableBatteryLoading;
bool isFDS = false; //flag for determining if a FDS game is loaded, movie.cpp needs this bool isFDS = false; //flag for determining if a FDS game is loaded, movie.cpp needs this
@ -147,20 +147,26 @@ static void FDSInit(void) {
SelectDisk = 0; SelectDisk = 0;
} }
void FCEU_FDSInsert(void) { void FCEU_FDSInsert(void)
if (FCEUI_EmulationPaused()) EmulationPaused |= 2; {
if (TotalSides == 0)
{
FCEU_DispMessage("", 0);//FCEU_DispMessage("Not FDS; can't eject disk.", 0);
return;
}
if (FCEUI_EmulationPaused())
EmulationPaused |= EMULATIONPAUSED_FA;
if (FCEUMOV_Mode(MOVIEMODE_RECORD)) if (FCEUMOV_Mode(MOVIEMODE_RECORD))
FCEUMOV_AddCommand(FCEUNPCMD_FDSINSERT); FCEUMOV_AddCommand(FCEUNPCMD_FDSINSERT);
if (TotalSides == 0) { if (InDisk == 255)
FCEU_DispMessage("", 0);// remove text "Not FDS; can't eject disk." {
return;
}
if (InDisk == 255) {
//FCEU_DispMessage("Disk %d Side %s Inserted", 0, SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A"); //FCEU_DispMessage("Disk %d Side %s Inserted", 0, SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
InDisk = SelectDisk; InDisk = SelectDisk;
} else { } else
{
//FCEU_DispMessage("Disk %d Side %s Ejected", 0, SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A"); //FCEU_DispMessage("Disk %d Side %s Ejected", 0, SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
InDisk = 255; InDisk = 255;
} }
@ -171,22 +177,27 @@ void FCEU_FDSEject(void)
InDisk=255; InDisk=255;
} }
*/ */
void FCEU_FDSSelect(void) { void FCEU_FDSSelect(void)
if (FCEUI_EmulationPaused()) EmulationPaused |= 2; {
if (TotalSides == 0)
{
FCEU_DispMessage("", 0); //FCEU_DispMessage("Not FDS; can't select disk.", 0);
return;
}
if (InDisk != 255)
{
FCEU_DispMessage("", 0); //FCEU_DispMessage("Eject disk before selecting.", 0);
return;
}
if (FCEUI_EmulationPaused())
EmulationPaused |= EMULATIONPAUSED_FA;
if (FCEUMOV_Mode(MOVIEMODE_RECORD)) if (FCEUMOV_Mode(MOVIEMODE_RECORD))
FCEUMOV_AddCommand(FCEUNPCMD_FDSSELECT); FCEUMOV_AddCommand(FCEUNPCMD_FDSSELECT);
if (TotalSides == 0) {
FCEU_DispMessage("", 0);//remove text "Not FDS; can't select disk."
return;
}
if (InDisk != 255) {
FCEU_DispMessage("", 0); //remove text "Eject disk before selecting"
return;
}
SelectDisk = ((SelectDisk + 1) % TotalSides) & 3; SelectDisk = ((SelectDisk + 1) % TotalSides) & 3;
FCEU_DispMessage("", 0); //("Disk %d Side %c Selected", 0, SelectDisk >> 1, (SelectDisk & 1) ? 'B' : 'A'); FCEU_DispMessage("", 0); //FCEU_DispMessage("Disk %d Side %c Selected", 0, SelectDisk >> 1, (SelectDisk & 1) ? 'B' : 'A');
} }
static void FDSFix(int a) { static void FDSFix(int a) {
@ -753,13 +764,11 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
CHRRAMSize = 8192; CHRRAMSize = 8192;
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
memset(CHRRAM, 0, CHRRAMSize);
SetupCartCHRMapping(0, CHRRAM, CHRRAMSize, 1); SetupCartCHRMapping(0, CHRRAM, CHRRAMSize, 1);
AddExState(CHRRAM, CHRRAMSize, 0, "CHRR"); AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
FDSRAMSize = 32768; FDSRAMSize = 32768;
FDSRAM = (uint8*)FCEU_gmalloc(FDSRAMSize); FDSRAM = (uint8*)FCEU_gmalloc(FDSRAMSize);
memset(FDSRAM, 0, FDSRAMSize);
SetupCartPRGMapping(1, FDSRAM, FDSRAMSize, 1); SetupCartPRGMapping(1, FDSRAM, FDSRAMSize, 1);
AddExState(FDSRAM, FDSRAMSize, 0, "FDSR"); AddExState(FDSRAM, FDSRAMSize, 0, "FDSR");

View File

@ -27,10 +27,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fstream> #include <fstream>
#ifndef WIN32
#include <zlib.h>
#endif
#include "types.h" #include "types.h"
#include "file.h" #include "file.h"
#include "utils/endian.h" #include "utils/endian.h"
@ -49,6 +45,10 @@
#include "driver.h" #include "driver.h"
#include "utils/xstring.h" #include "utils/xstring.h"
#ifndef WIN32
#include <zlib.h>
#endif
using namespace std; using namespace std;
bool bindSavestate = true; //Toggle that determines if a savestate filename will include the movie filename bool bindSavestate = true; //Toggle that determines if a savestate filename will include the movie filename

View File

@ -36,8 +36,10 @@ enum ESI
SI_POWERPADB = 4, SI_POWERPADB = 4,
SI_ARKANOID = 5, SI_ARKANOID = 5,
SI_MOUSE = 6, SI_MOUSE = 6,
SI_SNES = 7,
SI_SNES_MOUSE = 8,
SI_COUNT = SI_MOUSE SI_COUNT = SI_SNES_MOUSE
}; };
inline const char* ESI_Name(ESI esi) inline const char* ESI_Name(ESI esi)
@ -50,7 +52,9 @@ inline const char* ESI_Name(ESI esi)
"Power Pad A", "Power Pad A",
"Power Pad B", "Power Pad B",
"Arkanoid Paddle", "Arkanoid Paddle",
"Mouse" "Subor Mouse",
"SNES Pad",
"SNES Mouse"
}; };
if(esi >= SI_NONE && esi <= SI_COUNT) if(esi >= SI_NONE && esi <= SI_COUNT)

View File

@ -30,6 +30,7 @@
{ 0x9b4bad37b5498992LL, "Gradius 2", INESB_HACKED }, { 0x9b4bad37b5498992LL, "Gradius 2", INESB_HACKED },
{ 0xb068d4ac10ef848eLL, "Highway Star", INESB_HACKED }, { 0xb068d4ac10ef848eLL, "Highway Star", INESB_HACKED },
{ 0xbf5175271e5019c3LL, "Kaiketsu Yanchamaru 3", INESB_HACKED }, { 0xbf5175271e5019c3LL, "Kaiketsu Yanchamaru 3", INESB_HACKED },
{ 0x81c1de64550a1531LL, "Nobunaga no Yabou Zenkokuban", INESB_HACKED },
{ 0xfb4b508a236bbba3LL, "Salamander", INESB_HACKED }, { 0xfb4b508a236bbba3LL, "Salamander", INESB_HACKED },
{ 0x1895afc6eef26c7dLL, "Super Mario Bros.", INESB_HACKED }, { 0x1895afc6eef26c7dLL, "Super Mario Bros.", INESB_HACKED },
{ 0x3716c4bebf885344LL, "Super Mario Bros.", INESB_HACKED }, { 0x3716c4bebf885344LL, "Super Mario Bros.", INESB_HACKED },

View File

@ -62,6 +62,7 @@
{0x02cc3973, 3, 1}, /* Ninja Kid */ {0x02cc3973, 3, 1}, /* Ninja Kid */
{0xbc065fc3, 3, 1}, /* Pipe Dream */ {0xbc065fc3, 3, 1}, /* Pipe Dream */
{0xc9ee15a7, 3, -1}, /* 3 is probably best. 41 WILL NOT WORK. */ {0xc9ee15a7, 3, -1}, /* 3 is probably best. 41 WILL NOT WORK. */
{0x13e09d7a, 4, 0}, /*Dragon Wars (U) (proto) - comes with erroneous 4-screen mirroring set*/
{0x22d6d5bd, 4, 1}, {0x22d6d5bd, 4, 1},
{0xd97c31b0, 4, 1}, //Rasaaru Ishii no Childs Quest (J) {0xd97c31b0, 4, 1}, //Rasaaru Ishii no Childs Quest (J)
{0x404b2e8b, 4, 2}, /* Rad Racer 2 */ {0x404b2e8b, 4, 2}, /* Rad Racer 2 */
@ -83,7 +84,6 @@
{0x6e68e31a, 16, 8}, /* Dragon Ball 3*/ {0x6e68e31a, 16, 8}, /* Dragon Ball 3*/
{0x33b899c9, 16, -1}, /* Dragon Ball - Dai Maou Fukkatsu (J) [!] */ {0x33b899c9, 16, -1}, /* Dragon Ball - Dai Maou Fukkatsu (J) [!] */
{0xa262a81f, 16, -1}, /* Rokudenashi Blues (J) */ {0xa262a81f, 16, -1}, /* Rokudenashi Blues (J) */
{0x286fcd20, 23, -1}, /* Ganbare Goemon Gaiden 2 - Tenka no Zaihou (J) [!] */
{0xe4a291ce, 23, -1}, /* World Hero (Unl) [!] */ {0xe4a291ce, 23, -1}, /* World Hero (Unl) [!] */
{0x51e9cd33, 23, -1}, /* World Hero (Unl) [b1] */ {0x51e9cd33, 23, -1}, /* World Hero (Unl) [b1] */
{0x105dd586, 27, -1}, /* Mi Hun Che variations... */ {0x105dd586, 27, -1}, /* Mi Hun Che variations... */
@ -257,10 +257,28 @@
{0x345ee51a, 245, -1}, /* DQ4c */ {0x345ee51a, 245, -1}, /* DQ4c */
{0x57514c6c, 245, -1}, /* Yong Zhe Dou E Long - Dragon Quest VI (Ch) */ {0x57514c6c, 245, -1}, /* Yong Zhe Dou E Long - Dragon Quest VI (Ch) */
// added a new mask bit to define these mappers as a dupes of the UNIF format boards
{0x1d75fd35, 256|0x1000,-1}, /* 2-in-1 - Street Dance + Hit Mouse (Unl) [!] */ {0x1d75fd35, 256|0x1000,-1}, /* 2-in-1 - Street Dance + Hit Mouse (Unl) [!] */
{0x6eef8bb7, 257|0x1000,-1}, /* PEC-586 Chinese */ {0x6eef8bb7, 257|0x1000,-1}, /* PEC-586 Chinese */
{0xac7e98fb, 257|0x1000,-1}, /* PEC-586 Chinese No Tape Out */ {0xac7e98fb, 257|0x1000,-1}, /* PEC-586 Chinese No Tape Out */
{0x8d51a23b, 257|0x1000,-1}, /* [KeWang] Chao Ji Wu Bi Han Ka (C) V1 */ {0x8d51a23b, 257|0x1000,-1}, /* [KeWang] Chao Ji Wu Bi Han Ka (C) V1 */
{0x25c76773, 257|0x1000,-1}, /* [KeWang] Chao Ji Wu Bi Han Ka (C) V2 */ {0x25c76773, 257|0x1000,-1}, /* [KeWang] Chao Ji Wu Bi Han Ka (C) V2 */
{0x1ca9c322, 258|0x1000,-1}, /* Blood Of Jurassic (GD-98)(Unl) */
{0x2469c1ae, 259|0x1000,-1}, /* 150-in-1 Unchained FIGHT version */
{0x99d4464f, 260|0x1000,-1}, /* HP10xx/HP20xx board dumps */
{0xb72b2cf4, 260|0x1000,-1},
{0x4dc6107d, 260|0x1000,-1},
{0x0073dbd8, 260|0x1000,-1},
{0x3b098344, 260|0x1000,-1},
{0x1fc640c0, 260|0x1000,-1},
{0x2f1ad1fc, 260|0x1000,-1},
{0xa22214bb, 260|0x1000,-1},
{0x5dd9073b, 260|0x1000,-1},
{0x26a36cc2, 260|0x1000,-1},
{0xd1e52b37, 260|0x1000,-1},
{0x4d4a0e1b, 260|0x1000,-1},
{0xb6dd2c9d, 260|0x1000,-1},
{0x00000000, -1, -1} {0x00000000, -1, -1}

View File

@ -327,7 +327,7 @@ static void CheckHInfo(void) {
{ {
#include "ines-correct.h" #include "ines-correct.h"
}; };
int32 tofix = 0, x; int32 tofix = 0, x, mask;
uint64 partialmd5 = 0; uint64 partialmd5 = 0;
for (x = 0; x < 8; x++) for (x = 0; x < 8; x++)
@ -361,9 +361,13 @@ static void CheckHInfo(void) {
VROM = NULL; VROM = NULL;
tofix |= 8; tofix |= 8;
} }
if (MapperNo != (moo[x].mapper & 0xFF)) { if (moo[x].mapper & 0x1000)
mask = 0xFFF;
else
mask = 0xFF;
if (MapperNo != (moo[x].mapper & mask)) {
tofix |= 1; tofix |= 1;
MapperNo = moo[x].mapper & 0xFF; MapperNo = moo[x].mapper & mask;
} }
} }
if (moo[x].mirror >= 0) { if (moo[x].mirror >= 0) {
@ -561,7 +565,7 @@ static BMAPPINGLocal bmap[] = {
{"FDS UNROM BOARD", 108, Mapper108_Init}, {"FDS UNROM BOARD", 108, Mapper108_Init},
// {"", 109, Mapper109_Init}, // {"", 109, Mapper109_Init},
// {"", 110, Mapper110_Init}, // {"", 110, Mapper110_Init},
// {"", 111, Mapper111_Init}, {"Cheapocabra", 111, Mapper111_Init},
{"ASDER/NTDEC BOARD", 112, Mapper112_Init}, {"ASDER/NTDEC BOARD", 112, Mapper112_Init},
{"HACKER/SACHEN BOARD", 113, Mapper113_Init}, {"HACKER/SACHEN BOARD", 113, Mapper113_Init},
{"MMC3 SG PROT. A", 114, Mapper114_Init}, {"MMC3 SG PROT. A", 114, Mapper114_Init},
@ -640,7 +644,7 @@ static BMAPPINGLocal bmap[] = {
{"", 187, Mapper187_Init}, {"", 187, Mapper187_Init},
{"", 188, Mapper188_Init}, {"", 188, Mapper188_Init},
{"", 189, Mapper189_Init}, {"", 189, Mapper189_Init},
// {"", 190, Mapper190_Init}, {"", 190, Mapper190_Init},
{"", 191, Mapper191_Init}, {"", 191, Mapper191_Init},
{"TW MMC3+VRAM Rev. B", 192, Mapper192_Init}, {"TW MMC3+VRAM Rev. B", 192, Mapper192_Init},
{"NTDEC TC-112", 193, Mapper193_Init}, // War in the Gulf {"NTDEC TC-112", 193, Mapper193_Init}, // War in the Gulf
@ -711,6 +715,18 @@ static BMAPPINGLocal bmap[] = {
//-------- Mappers 512-767 is the Supplementary Ideographic Plane ----------- //-------- Mappers 512-767 is the Supplementary Ideographic Plane -----------
//-------- Mappers 3840-4095 are for rom dumps not publicly released -------- //-------- Mappers 3840-4095 are for rom dumps not publicly released --------
// An attempt to make working the UNIF BOARD ROMs in INES FORMAT
// I don't know if there a complete ines 2.0 mapper list exist, so if it does,
// just redefine these numbers to any others which isn't used before
// see the ines-correct.h files for the ROMs CHR list
{"ONE-BUS Systems", 256, UNLOneBus_Init},
{"PEC-586 Computer", 257, UNLPEC586Init},
{"158B Prot Board", 258, UNL158B_Init},
{"F-15 MMC3 Based", 259, BMCF15_Init},
{"HP10xx/H20xx Boards", 260, BMCHPxx_Init},
{"810544-CA-1", 261, BMC810544CA1_Init},
{"", 0, NULL} {"", 0, NULL}
}; };
@ -845,7 +861,7 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
FCEU_printf(" Total VRAM size: %d\n", iNESCart.vram_size + iNESCart.battery_vram_size); FCEU_printf(" Total VRAM size: %d\n", iNESCart.vram_size + iNESCart.battery_vram_size);
if(head.ROM_type & 2) if(head.ROM_type & 2)
{ {
FCEU_printf(" WRAM backked by battery: %d\n", iNESCart.battery_wram_size); FCEU_printf(" WRAM backed by battery: %d\n", iNESCart.battery_wram_size);
FCEU_printf(" VRAM backed by battery: %d\n", iNESCart.battery_vram_size); FCEU_printf(" VRAM backed by battery: %d\n", iNESCart.battery_vram_size);
} }
} }
@ -895,12 +911,15 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
} }
GameInterface = iNESGI; GameInterface = iNESGI;
currCartInfo = &iNESCart;
FCEU_printf("\n"); FCEU_printf("\n");
// since apparently the iNES format doesn't store this information, // since apparently the iNES format doesn't store this information,
// guess if the settings should be PAL or NTSC from the ROM name // guess if the settings should be PAL or NTSC from the ROM name
// TODO: MD5 check against a list of all known PAL games instead? // TODO: MD5 check against a list of all known PAL games instead?
if (OverwriteVidMode) { if (iNES2) {
FCEUI_SetVidSystem(((head.TV_system & 3) == 1) ? 1 : 0);
} else if (OverwriteVidMode) {
if (strstr(name, "(E)") || strstr(name, "(e)") if (strstr(name, "(E)") || strstr(name, "(e)")
|| strstr(name, "(Europe)") || strstr(name, "(PAL)") || strstr(name, "(Europe)") || strstr(name, "(PAL)")
|| strstr(name, "(F)") || strstr(name, "(f)") || strstr(name, "(F)") || strstr(name, "(f)")
@ -990,6 +1009,7 @@ static int iNES_Init(int num) {
case 6: case 6:
case 29: case 29:
case 30: case 30:
case 45:
case 96: CHRRAMSize = 32 * 1024; break; case 96: CHRRAMSize = 32 * 1024; break;
case 176: CHRRAMSize = 128 * 1024; break; case 176: CHRRAMSize = 128 * 1024; break;
default: CHRRAMSize = 8 * 1024; break; default: CHRRAMSize = 8 * 1024; break;
@ -1004,8 +1024,18 @@ static int iNES_Init(int num) {
FCEU_MemoryRand(VROM, CHRRAMSize); FCEU_MemoryRand(VROM, CHRRAMSize);
UNIFchrrama = VROM; UNIFchrrama = VROM;
SetupCartCHRMapping(0, VROM, CHRRAMSize, 1); if(CHRRAMSize == 0)
AddExState(VROM, CHRRAMSize, 0, "CHRR"); {
//probably a mistake.
//but (for chrram): "Use of $00 with no CHR ROM implies that the game is wired to map nametable memory in CHR space. The value $00 MUST NOT be used if a mapper isn't defined to allow this. "
//well, i'm not going to do that now. we'll save it for when it's needed
//"it's only mapper 218 and no other mappers"
}
else
{
SetupCartCHRMapping(0, VROM, CHRRAMSize, 1);
AddExState(VROM, CHRRAMSize, 0, "CHRR");
}
} }
if (head.ROM_type & 8) if (head.ROM_type & 8)
AddExState(ExtraNTARAM, 2048, 0, "EXNR"); AddExState(ExtraNTARAM, 2048, 0, "EXNR");

View File

@ -177,6 +177,7 @@ void Mapper105_Init(CartInfo *);
void Mapper106_Init(CartInfo *); void Mapper106_Init(CartInfo *);
void Mapper107_Init(CartInfo *); void Mapper107_Init(CartInfo *);
void Mapper108_Init(CartInfo *); void Mapper108_Init(CartInfo *);
void Mapper111_Init(CartInfo *);
void Mapper112_Init(CartInfo *); void Mapper112_Init(CartInfo *);
void Mapper113_Init(CartInfo *); void Mapper113_Init(CartInfo *);
void Mapper114_Init(CartInfo *); void Mapper114_Init(CartInfo *);

View File

@ -62,6 +62,8 @@ extern INPUTC *FCEU_InitZapper(int w);
extern INPUTC *FCEU_InitPowerpadA(int w); extern INPUTC *FCEU_InitPowerpadA(int w);
extern INPUTC *FCEU_InitPowerpadB(int w); extern INPUTC *FCEU_InitPowerpadB(int w);
extern INPUTC *FCEU_InitArkanoid(int w); extern INPUTC *FCEU_InitArkanoid(int w);
extern INPUTC *FCEU_InitMouse(int w);
extern INPUTC *FCEU_InitSNESMouse(int w);
extern INPUTCFC *FCEU_InitArkanoidFC(void); extern INPUTCFC *FCEU_InitArkanoidFC(void);
extern INPUTCFC *FCEU_InitSpaceShadow(void); extern INPUTCFC *FCEU_InitSpaceShadow(void);
@ -88,6 +90,7 @@ extern bool movieSubtitles;
static uint8 joy_readbit[2]; static uint8 joy_readbit[2];
uint8 joy[4]={0,0,0,0}; //HACK - should be static but movie needs it uint8 joy[4]={0,0,0,0}; //HACK - should be static but movie needs it
uint16 snesjoy[4]={0,0,0,0}; //HACK - should be static but movie needs it
static uint8 LastStrobe; static uint8 LastStrobe;
uint8 RawReg4016 = 0; // Joystick strobe (W) uint8 RawReg4016 = 0; // Joystick strobe (W)
@ -107,6 +110,9 @@ static bool FSAttached = false;
JOYPORT joyports[2] = { JOYPORT(0), JOYPORT(1) }; JOYPORT joyports[2] = { JOYPORT(0), JOYPORT(1) };
FCPORT portFC; FCPORT portFC;
FILE* DumpInputFile;
FILE* PlayInputFile;
static DECLFR(JPRead) static DECLFR(JPRead)
{ {
lagFlag = 0; lagFlag = 0;
@ -139,6 +145,12 @@ static DECLFR(JPRead)
} }
} }
if(PlayInputFile)
ret = fgetc(PlayInputFile);
if(DumpInputFile)
fputc(ret,DumpInputFile);
ret|=X.DB&0xC0; ret|=X.DB&0xC0;
return(ret); return(ret);
@ -305,9 +317,64 @@ static void StrobeGP(int w)
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//SNES pad
static void UpdateSNES(int w, void *data, int arg)
{
//LUA NOT SUPPORTED YET
if(w==0)
{
snesjoy[0]= ((uint32 *)joyports[0].ptr)[0];
snesjoy[2]= ((uint32 *)joyports[0].ptr)[2];
}
else
{
snesjoy[1] = ((uint32 *)joyports[0].ptr)[1];
snesjoy[3] = ((uint32 *)joyports[0].ptr)[3];
}
}
static void LogSNES(int w, MovieRecord* mr)
{
//not supported for SNES pad right noe
}
static void LoadSNES(int w, MovieRecord* mr)
{
//not supported for SNES pad right now
}
static uint8 ReadSNES(int w)
{
//no fourscore support on snes (not clear how it would work)
uint8 ret;
if(joy_readbit[w]>=16)
ret = 1;
else
{
ret = ((snesjoy[w]>>(joy_readbit[w]))&1);
}
if(!fceuindbg)
joy_readbit[w]++;
return ret;
}
static void StrobeSNES(int w)
{
joy_readbit[w]=0;
}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
static INPUTC GPC={ReadGP,0,StrobeGP,UpdateGP,0,0,LogGP,LoadGP}; static INPUTC GPC={ReadGP,0,StrobeGP,UpdateGP,0,0,LogGP,LoadGP};
static INPUTC GPCVS={ReadGPVS,0,StrobeGP,UpdateGP,0,0,LogGP,LoadGP}; static INPUTC GPCVS={ReadGPVS,0,StrobeGP,UpdateGP,0,0,LogGP,LoadGP};
static INPUTC GPSNES={ReadSNES,0,StrobeSNES,UpdateSNES,0,0,LogSNES,LoadSNES};
void FCEU_DrawInput(uint8 *buf) void FCEU_DrawInput(uint8 *buf)
{ {
@ -325,7 +392,7 @@ void FCEU_UpdateInput(void)
{ {
for(int port=0;port<2;port++){ for(int port=0;port<2;port++){
joyports[port].driver->Update(port,joyports[port].ptr,joyports[port].attrib); joyports[port].driver->Update(port,joyports[port].ptr,joyports[port].attrib);
} }
portFC.driver->Update(portFC.ptr,portFC.attrib); portFC.driver->Update(portFC.ptr,portFC.attrib);
} }
@ -340,7 +407,7 @@ void FCEU_UpdateInput(void)
//TODO - should this apply to the movie data? should this be displayed in the input hud? //TODO - should this apply to the movie data? should this be displayed in the input hud?
if(GameInfo->type==GIT_VSUNI){ if(GameInfo->type==GIT_VSUNI){
FCEU_VSUniSwap(&joy[0],&joy[1]); FCEU_VSUniSwap(&joy[0],&joy[1]);
} }
} }
static DECLFR(VSUNIRead0) static DECLFR(VSUNIRead0)
@ -386,9 +453,12 @@ static void SetInputStuff(int port)
case SI_GAMEPAD: case SI_GAMEPAD:
if(GameInfo->type==GIT_VSUNI){ if(GameInfo->type==GIT_VSUNI){
joyports[port].driver = &GPCVS; joyports[port].driver = &GPCVS;
} else { } else {
joyports[port].driver= &GPC; joyports[port].driver= &GPC;
} }
break;
case SI_SNES:
joyports[port].driver= &GPSNES;
break; break;
case SI_ARKANOID: case SI_ARKANOID:
joyports[port].driver=FCEU_InitArkanoid(port); joyports[port].driver=FCEU_InitArkanoid(port);
@ -402,6 +472,12 @@ static void SetInputStuff(int port)
case SI_POWERPADB: case SI_POWERPADB:
joyports[port].driver=FCEU_InitPowerpadB(port); joyports[port].driver=FCEU_InitPowerpadB(port);
break; break;
case SI_MOUSE:
joyports[port].driver=FCEU_InitMouse(port);
break;
case SI_SNES_MOUSE:
joyports[port].driver=FCEU_InitSNESMouse(port);
break;
case SI_NONE: case SI_NONE:
joyports[port].driver=&DummyJPort; joyports[port].driver=&DummyJPort;
break; break;
@ -665,10 +741,11 @@ static void RamSearchOpLTE(void);
static void RamSearchOpGTE(void); static void RamSearchOpGTE(void);
static void RamSearchOpEQ(void); static void RamSearchOpEQ(void);
static void RamSearchOpNE(void); static void RamSearchOpNE(void);
static void DebuggerStepInto(void);
static void FA_SkipLag(void); static void FA_SkipLag(void);
static void OpenRom(void); static void OpenRom(void);
static void CloseRom(void); static void CloseRom(void);
static void ReloadRom(void); void ReloadRom(void);
static void MovieSubtitleToggle(void); static void MovieSubtitleToggle(void);
static void UndoRedoSavestate(void); static void UndoRedoSavestate(void);
static void FCEUI_DoExit(void); static void FCEUI_DoExit(void);
@ -680,134 +757,139 @@ extern void FCEUI_ToggleShowFPS();
struct EMUCMDTABLE FCEUI_CommandTable[]= struct EMUCMDTABLE FCEUI_CommandTable[]=
{ {
{ EMUCMD_POWER, EMUCMDTYPE_MISC, FCEUI_PowerNES, 0, 0, "Power", EMUCMDFLAG_TASEDITOR }, { EMUCMD_POWER, EMUCMDTYPE_MISC, FCEUI_PowerNES, 0, 0, "Power", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_RESET, EMUCMDTYPE_MISC, FCEUI_ResetNES, 0, 0, "Reset", EMUCMDFLAG_TASEDITOR }, { EMUCMD_RESET, EMUCMDTYPE_MISC, FCEUI_ResetNES, 0, 0, "Reset", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_PAUSE, EMUCMDTYPE_MISC, FCEUI_ToggleEmulationPause, 0, 0, "Pause", EMUCMDFLAG_TASEDITOR }, { EMUCMD_PAUSE, EMUCMDTYPE_MISC, FCEUI_ToggleEmulationPause, 0, 0, "Pause", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_FRAME_ADVANCE, EMUCMDTYPE_MISC, FCEUI_FrameAdvance, FCEUI_FrameAdvanceEnd, 0, "Frame Advance", EMUCMDFLAG_TASEDITOR }, { EMUCMD_FRAME_ADVANCE, EMUCMDTYPE_MISC, FCEUI_FrameAdvance, FCEUI_FrameAdvanceEnd, 0, "Frame Advance", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SCREENSHOT, EMUCMDTYPE_MISC, FCEUI_SaveSnapshot, 0, 0, "Screenshot", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SCREENSHOT, EMUCMDTYPE_MISC, FCEUI_SaveSnapshot, 0, 0, "Screenshot", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_HIDE_MENU_TOGGLE, EMUCMDTYPE_MISC, FCEUD_HideMenuToggle, 0, 0, "Hide Menu Toggle", 0 }, { EMUCMD_HIDE_MENU_TOGGLE, EMUCMDTYPE_MISC, FCEUD_HideMenuToggle, 0, 0, "Hide Menu Toggle", 0 },
{ EMUCMD_EXIT, EMUCMDTYPE_MISC, FCEUI_DoExit, 0, 0, "Exit", EMUCMDFLAG_TASEDITOR }, { EMUCMD_EXIT, EMUCMDTYPE_MISC, FCEUI_DoExit, 0, 0, "Exit", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SPEED_SLOWEST, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Slowest Speed", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SPEED_SLOWER, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Speed Down", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SPEED_NORMAL, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Normal Speed", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SPEED_FASTER, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Speed Up", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SPEED_FASTEST, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Fastest Speed", 0 },
{ EMUCMD_SPEED_TURBO, EMUCMDTYPE_SPEED, FCEUD_TurboOn, FCEUD_TurboOff, 0, "Turbo", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SPEED_TURBO_TOGGLE, EMUCMDTYPE_SPEED, FCEUD_TurboToggle, 0, 0, "Turbo Toggle", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_0, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 0", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SPEED_SLOWEST, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Slowest Speed", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_1, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 1", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SPEED_SLOWER, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Speed Down", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_2, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 2", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SPEED_NORMAL, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Normal Speed", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_3, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 3", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SPEED_FASTER, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Speed Up", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_4, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 4", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SPEED_FASTEST, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Fastest Speed", 0 },
{ EMUCMD_SAVE_SLOT_5, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 5", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SPEED_TURBO, EMUCMDTYPE_SPEED, FCEUD_TurboOn, FCEUD_TurboOff, 0, "Turbo", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_6, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 6", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SPEED_TURBO_TOGGLE, EMUCMDTYPE_SPEED, FCEUD_TurboToggle, 0, 0, "Turbo Toggle", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_7, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 7", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_8, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 8", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_9, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 9", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_NEXT, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Next Savestate Slot", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_PREV, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Previous Savestate Slot", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_AS, EMUCMDTYPE_STATE, FCEUD_SaveStateAs, 0, 0, "Save State As...", 0 },
{ EMUCMD_SAVE_STATE_SLOT_0, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 0", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_1, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 1", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_2, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 2", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_3, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 3", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_4, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 4", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_5, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 5", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_6, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 6", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_7, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 7", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_8, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 8", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_9, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 9", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_FROM, EMUCMDTYPE_STATE, FCEUD_LoadStateFrom, 0, 0, "Load State From...", 0 },
{ EMUCMD_LOAD_STATE_SLOT_0, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 0", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_1, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 1", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_2, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 2", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_3, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 3", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_4, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 4", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_5, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 5", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_6, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 6", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_7, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 7", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_8, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 8", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_9, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 9", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MOVIE_RECORD_TO, EMUCMDTYPE_MOVIE, FCEUD_MovieRecordTo, 0, 0, "Record Movie To...", 0 }, { EMUCMD_SAVE_SLOT_0, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 0", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MOVIE_REPLAY_FROM, EMUCMDTYPE_MOVIE, FCEUD_MovieReplayFrom, 0, 0, "Play Movie From...", 0 }, { EMUCMD_SAVE_SLOT_1, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 1", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MOVIE_PLAY_FROM_BEGINNING, EMUCMDTYPE_MOVIE, FCEUI_MoviePlayFromBeginning, 0, 0, "Play Movie From Beginning", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SAVE_SLOT_2, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 2", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MOVIE_STOP, EMUCMDTYPE_MOVIE, FCEUI_StopMovie, 0, 0, "Stop Movie", 0 }, { EMUCMD_SAVE_SLOT_3, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 3", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MOVIE_READONLY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleReadOnly, 0, 0, "Toggle Read-Only", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SAVE_SLOT_4, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 4", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MOVIE_FRAME_DISPLAY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleFrameDisplay, 0, 0, "Toggle Frame Display", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SAVE_SLOT_5, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 5", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_6, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 6", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_7, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 7", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_8, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 8", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_9, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 9", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_NEXT, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Next Savestate Slot", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_SLOT_PREV, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Previous Savestate Slot", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_AS, EMUCMDTYPE_STATE, FCEUD_SaveStateAs, 0, 0, "Save State As...", 0 },
{ EMUCMD_SAVE_STATE_SLOT_0, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 0", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_1, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 1", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_2, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 2", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_3, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 3", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_4, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 4", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_5, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 5", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_6, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 6", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_7, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 7", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_8, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 8", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SAVE_STATE_SLOT_9, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 9", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_FROM, EMUCMDTYPE_STATE, FCEUD_LoadStateFrom, 0, 0, "Load State From...", 0 },
{ EMUCMD_LOAD_STATE_SLOT_0, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 0", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_1, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 1", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_2, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 2", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_3, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 3", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_4, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 4", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_5, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 5", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_6, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 6", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_7, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 7", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_8, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 8", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_LOAD_STATE_SLOT_9, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 9", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MOVIE_INPUT_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_ToggleInputDisplay, 0, 0, "Toggle Input Display", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MOVIE_RECORD_TO, EMUCMDTYPE_MOVIE, FCEUD_MovieRecordTo, 0, 0, "Record Movie To...", 0 },
{ EMUCMD_MOVIE_ICON_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUD_ToggleStatusIcon, 0, 0, "Toggle Status Icon", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MOVIE_REPLAY_FROM, EMUCMDTYPE_MOVIE, FCEUD_MovieReplayFrom, 0, 0, "Play Movie From...", 0 },
{ EMUCMD_MOVIE_PLAY_FROM_BEGINNING, EMUCMDTYPE_MOVIE, FCEUI_MoviePlayFromBeginning, 0, 0, "Play Movie From Beginning", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MOVIE_STOP, EMUCMDTYPE_MOVIE, FCEUI_StopMovie, 0, 0, "Stop Movie", 0 },
{ EMUCMD_MOVIE_READONLY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleReadOnly, 0, 0, "Toggle Read-Only", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MOVIE_FRAME_DISPLAY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleFrameDisplay, 0, 0, "Toggle Frame Display", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MOVIE_INPUT_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_ToggleInputDisplay, 0, 0, "Toggle Input Display", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MOVIE_ICON_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUD_ToggleStatusIcon, 0, 0, "Toggle Status Icon", EMUCMDFLAG_TASEDITOR },
#ifdef _S9XLUA_H #ifdef _S9XLUA_H
{ EMUCMD_SCRIPT_RELOAD, EMUCMDTYPE_MISC, FCEU_ReloadLuaCode, 0, 0, "Reload current Lua script", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SCRIPT_RELOAD, EMUCMDTYPE_MISC, FCEU_ReloadLuaCode, 0, 0, "Reload current Lua script", EMUCMDFLAG_TASEDITOR },
#endif #endif
{ EMUCMD_SOUND_TOGGLE, EMUCMDTYPE_SOUND, FCEUD_SoundToggle, 0, 0, "Sound Mute Toggle", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SOUND_TOGGLE, EMUCMDTYPE_SOUND, FCEUD_SoundToggle, 0, 0, "Sound Mute Toggle", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SOUND_VOLUME_UP, EMUCMDTYPE_SOUND, CommandSoundAdjust, 0, 0, "Sound Volume Up", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SOUND_VOLUME_UP, EMUCMDTYPE_SOUND, CommandSoundAdjust, 0, 0, "Sound Volume Up", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SOUND_VOLUME_DOWN, EMUCMDTYPE_SOUND, CommandSoundAdjust, 0, 0, "Sound Volume Down", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SOUND_VOLUME_DOWN, EMUCMDTYPE_SOUND, CommandSoundAdjust, 0, 0, "Sound Volume Down", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_SOUND_VOLUME_NORMAL, EMUCMDTYPE_SOUND, CommandSoundAdjust, 0, 0, "Sound Volume Normal", EMUCMDFLAG_TASEDITOR }, { EMUCMD_SOUND_VOLUME_NORMAL, EMUCMDTYPE_SOUND, CommandSoundAdjust, 0, 0, "Sound Volume Normal", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_AVI_RECORD_AS, EMUCMDTYPE_AVI, FCEUD_AviRecordTo, 0, 0, "Record AVI As...", EMUCMDFLAG_TASEDITOR }, { EMUCMD_AVI_RECORD_AS, EMUCMDTYPE_AVI, FCEUD_AviRecordTo, 0, 0, "Record AVI As...", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_AVI_STOP, EMUCMDTYPE_AVI, FCEUD_AviStop, 0, 0, "Stop AVI", EMUCMDFLAG_TASEDITOR }, { EMUCMD_AVI_STOP, EMUCMDTYPE_AVI, FCEUD_AviStop, 0, 0, "Stop AVI", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_FDS_EJECT_INSERT, EMUCMDTYPE_FDS, FCEUI_FDSInsert, 0, 0, "Eject or Insert FDS Disk", EMUCMDFLAG_TASEDITOR }, { EMUCMD_FDS_EJECT_INSERT, EMUCMDTYPE_FDS, FCEUI_FDSInsert, 0, 0, "Eject or Insert FDS Disk", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_FDS_SIDE_SELECT, EMUCMDTYPE_FDS, FCEUI_FDSSelect, 0, 0, "Switch FDS Disk Side", EMUCMDFLAG_TASEDITOR }, { EMUCMD_FDS_SIDE_SELECT, EMUCMDTYPE_FDS, FCEUI_FDSSelect, 0, 0, "Switch FDS Disk Side", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_VSUNI_COIN, EMUCMDTYPE_VSUNI, FCEUI_VSUniCoin, 0, 0, "Insert Coin", EMUCMDFLAG_TASEDITOR }, { EMUCMD_VSUNI_COIN, EMUCMDTYPE_VSUNI, FCEUI_VSUniCoin, 0, 0, "Insert Coin", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_VSUNI_TOGGLE_DIP_0, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 0", 0 }, { EMUCMD_VSUNI_TOGGLE_DIP_0, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 0", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_1, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 1", 0 }, { EMUCMD_VSUNI_TOGGLE_DIP_1, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 1", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_2, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 2", 0 }, { EMUCMD_VSUNI_TOGGLE_DIP_2, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 2", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_3, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 3", 0 }, { EMUCMD_VSUNI_TOGGLE_DIP_3, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 3", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_4, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 4", 0 }, { EMUCMD_VSUNI_TOGGLE_DIP_4, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 4", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_5, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 5", 0 }, { EMUCMD_VSUNI_TOGGLE_DIP_5, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 5", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_6, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 6", 0 }, { EMUCMD_VSUNI_TOGGLE_DIP_6, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 6", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_7, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 7", 0 }, { EMUCMD_VSUNI_TOGGLE_DIP_7, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 7", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_8, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 8", 0 }, { EMUCMD_VSUNI_TOGGLE_DIP_8, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 8", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_9, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 9", 0 }, { EMUCMD_VSUNI_TOGGLE_DIP_9, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 9", 0 },
{ EMUCMD_MISC_AUTOSAVE, EMUCMDTYPE_MISC, FCEUI_RewindToLastAutosave, 0, 0, "Load Last Auto-save", 0},
{ EMUCMD_MISC_SHOWSTATES, EMUCMDTYPE_MISC, ViewSlots, 0, 0, "View save slots", 0 }, { EMUCMD_MISC_AUTOSAVE, EMUCMDTYPE_MISC, FCEUI_RewindToLastAutosave, 0, 0, "Load Last Auto-save", 0},
{ EMUCMD_MISC_USE_INPUT_PRESET_1, EMUCMDTYPE_MISC, CommandUsePreset, 0, 0, "Use Input Preset 1", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MISC_SHOWSTATES, EMUCMDTYPE_MISC, ViewSlots, 0, 0, "View save slots", 0 },
{ EMUCMD_MISC_USE_INPUT_PRESET_2, EMUCMDTYPE_MISC, CommandUsePreset, 0, 0, "Use Input Preset 2", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MISC_USE_INPUT_PRESET_1, EMUCMDTYPE_MISC, CommandUsePreset, 0, 0, "Use Input Preset 1", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MISC_USE_INPUT_PRESET_3, EMUCMDTYPE_MISC, CommandUsePreset, 0, 0, "Use Input Preset 3", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MISC_USE_INPUT_PRESET_2, EMUCMDTYPE_MISC, CommandUsePreset, 0, 0, "Use Input Preset 2", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MISC_DISPLAY_BG_TOGGLE, EMUCMDTYPE_MISC, BackgroundDisplayToggle, 0, 0, "Toggle Background Display", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MISC_USE_INPUT_PRESET_3, EMUCMDTYPE_MISC, CommandUsePreset, 0, 0, "Use Input Preset 3", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MISC_DISPLAY_OBJ_TOGGLE, EMUCMDTYPE_MISC, ObjectDisplayToggle, 0, 0, "Toggle Object Display", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MISC_DISPLAY_BG_TOGGLE, EMUCMDTYPE_MISC, BackgroundDisplayToggle, 0, 0, "Toggle Background Display", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MISC_DISPLAY_LAGCOUNTER_TOGGLE,EMUCMDTYPE_MISC, LagCounterToggle, 0, 0, "Lag Counter Toggle", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MISC_DISPLAY_OBJ_TOGGLE, EMUCMDTYPE_MISC, ObjectDisplayToggle, 0, 0, "Toggle Object Display", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MISC_OPENTASEDITOR, EMUCMDTYPE_TOOL, LaunchTasEditor, 0, 0, "Open TAS Editor", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MISC_DISPLAY_LAGCOUNTER_TOGGLE,EMUCMDTYPE_MISC, LagCounterToggle, 0, 0, "Lag Counter Toggle", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TOOL_OPENMEMORYWATCH, EMUCMDTYPE_TOOL, LaunchMemoryWatch,0, 0, "Open Memory Watch", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TOOL_OPENCHEATS, EMUCMDTYPE_TOOL, LaunchCheats, 0, 0, "Open Cheats", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MISC_OPENTASEDITOR, EMUCMDTYPE_TOOL, LaunchTasEditor, 0, 0, "Open TAS Editor", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TOOL_OPENDEBUGGER, EMUCMDTYPE_TOOL, LaunchDebugger, 0, 0, "Open Debugger", EMUCMDFLAG_TASEDITOR }, { EMUCMD_TOOL_OPENMEMORYWATCH, EMUCMDTYPE_TOOL, LaunchMemoryWatch, 0, 0, "Open Memory Watch", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TOOL_OPENHEX, EMUCMDTYPE_TOOL, LaunchHex, 0, 0, "Open Hex Editor", EMUCMDFLAG_TASEDITOR }, { EMUCMD_TOOL_OPENCHEATS, EMUCMDTYPE_TOOL, LaunchCheats, 0, 0, "Open Cheats", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TOOL_OPENPPU, EMUCMDTYPE_TOOL, LaunchPPU, 0, 0, "Open PPU Viewer", EMUCMDFLAG_TASEDITOR }, { EMUCMD_TOOL_OPENDEBUGGER, EMUCMDTYPE_TOOL, LaunchDebugger, 0, 0, "Open Debugger", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TOOL_OPENNTVIEW, EMUCMDTYPE_TOOL, LaunchNTView, 0, 0, "Open Name Table Viewer", EMUCMDFLAG_TASEDITOR }, { EMUCMD_TOOL_OPENHEX, EMUCMDTYPE_TOOL, LaunchHex, 0, 0, "Open Hex Editor", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TOOL_OPENTRACELOGGER, EMUCMDTYPE_TOOL, LaunchTraceLogger, 0, 0, "Open Trace Logger", EMUCMDFLAG_TASEDITOR }, { EMUCMD_TOOL_OPENPPU, EMUCMDTYPE_TOOL, LaunchPPU, 0, 0, "Open PPU Viewer", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TOOL_OPENCDLOGGER, EMUCMDTYPE_TOOL, LaunchCodeDataLogger, 0, 0, "Open Code/Data Logger", EMUCMDFLAG_TASEDITOR }, { EMUCMD_TOOL_OPENNTVIEW, EMUCMDTYPE_TOOL, LaunchNTView, 0, 0, "Open Name Table Viewer", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_FRAMEADV_SKIPLAG, EMUCMDTYPE_MISC, FA_SkipLag, 0, 0, "Frame Adv.-Skip Lag", EMUCMDFLAG_TASEDITOR }, { EMUCMD_TOOL_OPENTRACELOGGER, EMUCMDTYPE_TOOL, LaunchTraceLogger, 0, 0, "Open Trace Logger", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_OPENROM, EMUCMDTYPE_TOOL, OpenRom, 0, 0, "Open ROM", 0}, { EMUCMD_TOOL_OPENCDLOGGER, EMUCMDTYPE_TOOL, LaunchCodeDataLogger, 0, 0, "Open Code/Data Logger", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_CLOSEROM, EMUCMDTYPE_TOOL, CloseRom, 0, 0, "Close ROM", 0}, { EMUCMD_FRAMEADV_SKIPLAG, EMUCMDTYPE_MISC, FA_SkipLag, 0, 0, "Frame Adv.-Skip Lag", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_RELOAD, EMUCMDTYPE_TOOL, ReloadRom, 0, 0, "Reload ROM or TAS Editor Project", EMUCMDFLAG_TASEDITOR }, { EMUCMD_OPENROM, EMUCMDTYPE_TOOL, OpenRom, 0, 0, "Open ROM", 0},
{ EMUCMD_MISC_DISPLAY_MOVIESUBTITLES, EMUCMDTYPE_MISC, MovieSubtitleToggle,0,0,"Toggle Movie Subtitles", EMUCMDFLAG_TASEDITOR }, { EMUCMD_CLOSEROM, EMUCMDTYPE_TOOL, CloseRom, 0, 0, "Close ROM", 0},
{ EMUCMD_MISC_UNDOREDOSAVESTATE, EMUCMDTYPE_MISC, UndoRedoSavestate, 0,0,"Undo/Redo Savestate", 0}, { EMUCMD_RELOAD, EMUCMDTYPE_TOOL, ReloadRom, 0, 0, "Reload ROM or TAS Editor Project", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_MISC_TOGGLEFULLSCREEN, EMUCMDTYPE_MISC, ToggleFullscreen, 0, 0, "Toggle Fullscreen", 0}, { EMUCMD_MISC_DISPLAY_MOVIESUBTITLES, EMUCMDTYPE_MISC, MovieSubtitleToggle, 0, 0, "Toggle Movie Subtitles", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TOOL_OPENRAMWATCH, EMUCMDTYPE_TOOL, LaunchRamWatch, 0, 0, "Open Ram Watch", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MISC_UNDOREDOSAVESTATE, EMUCMDTYPE_MISC, UndoRedoSavestate, 0, 0, "Undo/Redo Savestate", 0},
{ EMUCMD_TOOL_OPENRAMSEARCH, EMUCMDTYPE_TOOL, LaunchRamSearch, 0, 0, "Open Ram Search", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MISC_TOGGLEFULLSCREEN, EMUCMDTYPE_MISC, ToggleFullscreen, 0, 0, "Toggle Fullscreen", 0},
{ EMUCMD_TOOL_RAMSEARCHLT, EMUCMDTYPE_TOOL, RamSearchOpLT, 0, 0, "Ram Search - Less Than", 0}, { EMUCMD_TOOL_OPENRAMWATCH, EMUCMDTYPE_TOOL, LaunchRamWatch, 0, 0, "Open Ram Watch", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TOOL_RAMSEARCHGT, EMUCMDTYPE_TOOL, RamSearchOpGT, 0, 0, "Ram Search - Greater Than", 0}, { EMUCMD_TOOL_OPENRAMSEARCH, EMUCMDTYPE_TOOL, LaunchRamSearch, 0, 0, "Open Ram Search", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TOOL_RAMSEARCHLTE, EMUCMDTYPE_TOOL, RamSearchOpLTE, 0, 0, "Ram Search - Less Than or Equal", 0}, { EMUCMD_TOOL_RAMSEARCHLT, EMUCMDTYPE_TOOL, RamSearchOpLT, 0, 0, "Ram Search - Less Than", 0},
{ EMUCMD_TOOL_RAMSEARCHGTE, EMUCMDTYPE_TOOL, RamSearchOpGTE, 0, 0, "Ram Search - Greater Than or Equal", 0}, { EMUCMD_TOOL_RAMSEARCHGT, EMUCMDTYPE_TOOL, RamSearchOpGT, 0, 0, "Ram Search - Greater Than", 0},
{ EMUCMD_TOOL_RAMSEARCHEQ, EMUCMDTYPE_TOOL, RamSearchOpEQ, 0, 0, "Ram Search - Equal", 0}, { EMUCMD_TOOL_RAMSEARCHLTE, EMUCMDTYPE_TOOL, RamSearchOpLTE, 0, 0, "Ram Search - Less Than or Equal", 0},
{ EMUCMD_TOOL_RAMSEARCHNE, EMUCMDTYPE_TOOL, RamSearchOpNE, 0, 0, "Ram Search - Not Equal", 0}, { EMUCMD_TOOL_RAMSEARCHGTE, EMUCMDTYPE_TOOL, RamSearchOpGTE, 0, 0, "Ram Search - Greater Than or Equal", 0},
{ EMUCMD_RERECORD_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_MovieToggleRerecordDisplay, 0, 0, "Toggle Rerecord Display", EMUCMDFLAG_TASEDITOR }, { EMUCMD_TOOL_RAMSEARCHEQ, EMUCMDTYPE_TOOL, RamSearchOpEQ, 0, 0, "Ram Search - Equal", 0},
{ EMUCMD_TASEDITOR_REWIND, EMUCMDTYPE_TASEDITOR, TaseditorRewindOn, TaseditorRewindOff, 0, "Frame Rewind", EMUCMDFLAG_TASEDITOR }, { EMUCMD_TOOL_RAMSEARCHNE, EMUCMDTYPE_TOOL, RamSearchOpNE, 0, 0, "Ram Search - Not Equal", 0},
{ EMUCMD_TASEDITOR_RESTORE_PLAYBACK, EMUCMDTYPE_TASEDITOR, TaseditorCommand, 0, 0, "Restore Playback", EMUCMDFLAG_TASEDITOR }, { EMUCMD_RERECORD_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_MovieToggleRerecordDisplay,0, 0, "Toggle Rerecord Display", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TASEDITOR_CANCEL_SEEKING, EMUCMDTYPE_TASEDITOR, TaseditorCommand, 0, 0, "Cancel Seeking", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TASEDITOR_SWITCH_AUTORESTORING, EMUCMDTYPE_TASEDITOR, TaseditorCommand, 0, 0, "Switch Auto-restore last position", EMUCMDFLAG_TASEDITOR }, { EMUCMD_TASEDITOR_REWIND, EMUCMDTYPE_TASEDITOR, TaseditorRewindOn, TaseditorRewindOff, 0, "Frame Rewind", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TASEDITOR_SWITCH_MULTITRACKING, EMUCMDTYPE_TASEDITOR, TaseditorCommand, 0, 0, "Switch current Multitracking mode", EMUCMDFLAG_TASEDITOR }, { EMUCMD_TASEDITOR_RESTORE_PLAYBACK, EMUCMDTYPE_TASEDITOR, TaseditorCommand, 0, 0, "Restore Playback", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TASEDITOR_RUN_MANUAL_LUA, EMUCMDTYPE_TASEDITOR, TaseditorCommand, 0, 0, "Run Manual Lua function", EMUCMDFLAG_TASEDITOR }, { EMUCMD_TASEDITOR_CANCEL_SEEKING, EMUCMDTYPE_TASEDITOR, TaseditorCommand, 0, 0, "Cancel Seeking", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_FPS_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_ToggleShowFPS, 0, 0, "Toggle FPS Display", EMUCMDFLAG_TASEDITOR }, { EMUCMD_TASEDITOR_SWITCH_AUTORESTORING,EMUCMDTYPE_TASEDITOR, TaseditorCommand, 0, 0, "Switch Auto-restore last position", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TASEDITOR_SWITCH_MULTITRACKING,EMUCMDTYPE_TASEDITOR, TaseditorCommand, 0, 0, "Switch current Multitracking mode", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TASEDITOR_RUN_MANUAL_LUA, EMUCMDTYPE_TASEDITOR, TaseditorCommand, 0, 0, "Run Manual Lua function", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_FPS_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_ToggleShowFPS, 0, 0, "Toggle FPS Display", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TOOL_DEBUGSTEPINTO, EMUCMDTYPE_TOOL, DebuggerStepInto, 0, 0, "Debugger - Step Into", EMUCMDFLAG_TASEDITOR },
}; };
#define NUM_EMU_CMDS (sizeof(FCEUI_CommandTable)/sizeof(FCEUI_CommandTable[0])) #define NUM_EMU_CMDS (sizeof(FCEUI_CommandTable)/sizeof(FCEUI_CommandTable[0]))
@ -1119,6 +1201,17 @@ static void RamSearchOpNE(void) {
#endif #endif
} }
static void DebuggerStepInto()
{
#ifdef WIN32
if (GameInfo)
{
extern void DoDebuggerStepInto();
DoDebuggerStepInto();
}
#endif
}
static void FA_SkipLag(void) static void FA_SkipLag(void)
{ {
frameAdvanceLagSkip ^= 1; frameAdvanceLagSkip ^= 1;
@ -1139,7 +1232,7 @@ static void CloseRom(void)
#endif #endif
} }
static void ReloadRom(void) void ReloadRom(void)
{ {
#ifdef WIN32 #ifdef WIN32
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR)) if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))

View File

@ -8,6 +8,10 @@
void LagCounterToggle(void); void LagCounterToggle(void);
extern FILE* PlayInputFile;
extern FILE* DumpInputFile;
class MovieRecord; class MovieRecord;
//MBG TODO - COMBINE THESE INPUTC AND INPUTCFC //MBG TODO - COMBINE THESE INPUTC AND INPUTCFC
@ -242,6 +246,7 @@ enum EMUCMD
//----------------------------- //-----------------------------
//keep adding these in order of newness or else the hotkey binding configs will get messed up... //keep adding these in order of newness or else the hotkey binding configs will get messed up...
EMUCMD_FPS_DISPLAY_TOGGLE, EMUCMD_FPS_DISPLAY_TOGGLE,
EMUCMD_TOOL_DEBUGSTEPINTO,
EMUCMD_MAX EMUCMD_MAX
}; };

View File

@ -18,64 +18,66 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
// implementation of Subor Mouse
// used in Educational Computer 2000
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "share.h" #include "share.h"
typedef struct { typedef struct {
int32 mzx, mzy, mzxold, mzyold; uint8 latch;
uint32 readbit; int32 dx,dy;
uint32 data; uint32 mb;
} MOUSE; } MOUSE;
static MOUSE Mouse; static MOUSE Mouse;
// since this game only picks up 1 mickey per frame,
// allow a single delta to spread out over a few frames
// to make it easier to move.
const int INERTIA = 32;
static void StrobeMOUSE(int w) static void StrobeMOUSE(int w)
{ {
Mouse.readbit=0; Mouse.latch = Mouse.mb & 0x03;
int32 dx = Mouse.dx;
int32 dy = Mouse.dy;
if (dx > 0) { Mouse.latch |= (0x2 << 2); --Mouse.dx; }
else if (dx < 0) { Mouse.latch |= (0x3 << 2); ++Mouse.dx; }
if (dy > 0) { Mouse.latch |= (0x2 << 4); --Mouse.dy; }
else if (dy < 0) { Mouse.latch |= (0x3 << 4); ++Mouse.dy; }
//FCEU_printf("Subor Mouse: %02X\n",Mouse.latch);
} }
static uint8 ReadMOUSE(int w) static uint8 ReadMOUSE(int w)
{ {
uint8 ret=0; uint8 result = Mouse.latch & 0x01;
if(Mouse.readbit>=8) Mouse.latch = (Mouse.latch >> 1) | 0x80;
ret|=1; return result;
else
{
ret|=(Mouse.data>>Mouse.readbit)&1;
if(!fceuindbg)
Mouse.readbit++;
}
return(ret);
} }
static void UpdateMOUSE(int w, void *data, int arg) static void UpdateMOUSE(int w, void *data, int arg)
{ {
uint32 *ptr=(uint32*)data; uint32 *ptr=(uint32*)data;
Mouse.data=0; Mouse.dx += ptr[0]; ptr[0] = 0;
Mouse.mzxold=Mouse.mzx; Mouse.dy += ptr[1]; ptr[1] = 0;
Mouse.mzyold=Mouse.mzy; Mouse.mb = ptr[2];
Mouse.mzx=ptr[0];
Mouse.mzy=ptr[1]; if (Mouse.dx > INERTIA) Mouse.dx = INERTIA;
Mouse.data|=ptr[2]; else if (Mouse.dx < -INERTIA) Mouse.dx = -INERTIA;
if((Mouse.mzxold-Mouse.mzx)>0)
Mouse.data|=0x0C; if (Mouse.dy > INERTIA) Mouse.dy = INERTIA;
else if((Mouse.mzxold-Mouse.mzx)<0) else if (Mouse.dy < -INERTIA) Mouse.dy = -INERTIA;
Mouse.data|=0x04;
if((Mouse.mzyold-Mouse.mzy)>0)
Mouse.data|=0x30;
else if((Mouse.mzyold-Mouse.mzy)<0)
Mouse.data|=0x10;
} }
static INPUTC MOUSEC={ReadMOUSE,0,StrobeMOUSE,UpdateMOUSE,0,0}; static INPUTC MOUSEC={ReadMOUSE,0,StrobeMOUSE,UpdateMOUSE,0,0};
INPUTC *FCEU_InitMouse(int w) INPUTC *FCEU_InitMouse(int w)
{ {
Mouse.mzx=0; memset(&Mouse,0,sizeof(Mouse));
Mouse.mzy=0; return(&MOUSEC);
Mouse.mzxold=0;
Mouse.mzyold=0;
Mouse.data=0;
return(&MOUSEC);
} }

View File

@ -1,96 +1,96 @@
/* FCE Ultra - NES/Famicom Emulator /* FCE Ultra - NES/Famicom Emulator
* *
* Copyright notice for this file: * Copyright notice for this file:
* Copyright (C) 2002 Xodnizel * Copyright (C) 2002 Xodnizel
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <string.h> #include <string.h>
#include "share.h" #include "share.h"
#include "suborkb.h" #include "suborkb.h"
#define AK(x) FKB_ ## x #define AK(x) FKB_ ## x
static uint8 bufit[0x66]; static uint8 bufit[0x66];
static uint8 kspos, kstrobe; static uint8 kspos, kstrobe;
static uint8 ksindex; static uint8 ksindex;
//TODO: check all keys, some of the are wrong //TODO: check all keys, some of the are wrong
static uint16 matrix[13][8] = static uint16 matrix[13][8] =
{ {
{ AK(ESCAPE),AK(SPACE),AK(LMENU),AK(LCONTROL),AK(LSHIFT),AK(GRAVE),AK(TAB),AK(CAPITAL) }, { AK(ESCAPE),AK(SPACE),AK(LMENU),AK(LCONTROL),AK(LSHIFT),AK(GRAVE),AK(TAB),AK(CAPITAL) },
{ AK(F6),AK(F7),AK(F5),AK(F4),AK(F8),AK(F2),AK(F1),AK(F3) }, { AK(F6),AK(F7),AK(F5),AK(F4),AK(F8),AK(F2),AK(F1),AK(F3) },
{ AK(EQUALS), AK(NUMPAD0),AK(PERIOD),AK(A),AK(RETURN),AK(1),AK(Q),AK(Z) }, { AK(EQUALS), AK(NUMPAD0),AK(PERIOD),AK(A),AK(RETURN),AK(1),AK(Q),AK(Z) },
{ 0, AK(NUMPAD3),AK(NUMPAD6),AK(S),AK(NUMPAD9),AK(2),AK(W),AK(X) }, { 0, AK(NUMPAD3),AK(NUMPAD6),AK(S),AK(NUMPAD9),AK(2),AK(W),AK(X) },
{ AK(SLASH), AK(NUMPAD2),AK(NUMPAD5),AK(D),AK(NUMPAD8),AK(3),AK(E),AK(C) }, { AK(SLASH), AK(NUMPAD2),AK(NUMPAD5),AK(D),AK(NUMPAD8),AK(3),AK(E),AK(C) },
{ AK(BREAK), AK(NUMPAD1),AK(NUMPAD4),AK(F),AK(NUMPAD7),AK(4),AK(R),AK(V) }, { AK(BREAK), AK(NUMPAD1),AK(NUMPAD4),AK(F),AK(NUMPAD7),AK(4),AK(R),AK(V) },
{ AK(BACK),AK(BACKSLASH),AK(GRETURN),AK(G),AK(RBRACKET),AK(5),AK(T),AK(B) }, { AK(BACK),AK(BACKSLASH),AK(GRETURN),AK(G),AK(RBRACKET),AK(5),AK(T),AK(B) },
{ AK(9),AK(PERIOD),AK(L),AK(K),AK(O),AK(8),AK(I),AK(COMMA) }, { AK(9),AK(PERIOD),AK(L),AK(K),AK(O),AK(8),AK(I),AK(COMMA) },
{ AK(0),AK(SLASH),AK(SEMICOLON),AK(J),AK(P),AK(7),AK(U),AK(M) }, { AK(0),AK(SLASH),AK(SEMICOLON),AK(J),AK(P),AK(7),AK(U),AK(M) },
{ AK(MINUS),AK(MINUS),AK(APOSTROPHE),AK(H),AK(LBRACKET),AK(6),AK(Y),AK(N) }, { AK(MINUS),AK(MINUS),AK(APOSTROPHE),AK(H),AK(LBRACKET),AK(6),AK(Y),AK(N) },
{ AK(F11),AK(F12),AK(F10),0,AK(MINUS),AK(F9),0,0 }, { AK(F11),AK(F12),AK(F10),0,AK(MINUS),AK(F9),0,0 },
{ AK(UP),AK(RIGHT),AK(DOWN),AK(DIVIDE),AK(LEFT),AK(MULTIPLY),AK(SUBTRACT),AK(ADD) }, { AK(UP),AK(RIGHT),AK(DOWN),AK(DIVIDE),AK(LEFT),AK(MULTIPLY),AK(SUBTRACT),AK(ADD) },
{ AK(INSERT),AK(NUMPAD1),AK(HOME),AK(PRIOR),AK(DELETE),AK(END),AK(NEXT),AK(NUMLOCK) }, { AK(INSERT),AK(NUMPAD1),AK(HOME),AK(PRIOR),AK(DELETE),AK(END),AK(NEXT),AK(NUMLOCK) },
}; };
static void PEC586KB_Write(uint8 v) { static void PEC586KB_Write(uint8 v) {
if (!(kstrobe & 2) && (v & 2)) { if (!(kstrobe & 2) && (v & 2)) {
kspos = 0; kspos = 0;
} }
if ((kstrobe & 1) && !(v & 1)) { if ((kstrobe & 1) && !(v & 1)) {
ksindex = 0; ksindex = 0;
} }
if ((kstrobe & 4) && !(v & 4)) { if ((kstrobe & 4) && !(v & 4)) {
kspos++; kspos++;
kspos %= 13; kspos %= 13;
} }
kstrobe = v; kstrobe = v;
} }
static uint8 PEC586KB_Read(int w, uint8 ret) { static uint8 PEC586KB_Read(int w, uint8 ret) {
#ifdef FCEUDEF_DEBUGGER #ifdef FCEUDEF_DEBUGGER
if (!fceuindbg) { if (!fceuindbg) {
#endif #endif
if (w) { if (w) {
ret &= ~2; ret &= ~2;
if(bufit[matrix[kspos][7-ksindex]]) if(bufit[matrix[kspos][7-ksindex]])
ret |= 2; ret |= 2;
ksindex++; ksindex++;
ksindex&=7; ksindex&=7;
} }
#ifdef FCEUDEF_DEBUGGER #ifdef FCEUDEF_DEBUGGER
} }
#endif #endif
return(ret); return(ret);
} }
static void PEC586KB_Strobe(void) { static void PEC586KB_Strobe(void) {
// kstrobe = 0; // kstrobe = 0;
// ksindex = 0; // ksindex = 0;
} }
static void PEC586KB_Update(void *data, int arg) { static void PEC586KB_Update(void *data, int arg) {
memcpy(bufit + 1, data, sizeof(bufit) - 1); memcpy(bufit + 1, data, sizeof(bufit) - 1);
} }
static INPUTCFC PEC586KB = { PEC586KB_Read, PEC586KB_Write, PEC586KB_Strobe, PEC586KB_Update, 0, 0 }; static INPUTCFC PEC586KB = { PEC586KB_Read, PEC586KB_Write, PEC586KB_Strobe, PEC586KB_Update, 0, 0 };
INPUTCFC *FCEU_InitPEC586KB(void) { INPUTCFC *FCEU_InitPEC586KB(void) {
memset(bufit, 0, sizeof(bufit)); memset(bufit, 0, sizeof(bufit));
kspos = ksindex = kstrobe = 0; kspos = ksindex = kstrobe = 0;
return(&PEC586KB); return(&PEC586KB);
} }

View File

@ -11,6 +11,7 @@
#include "file.h" #include "file.h"
#include "video.h" #include "video.h"
#include "movie.h" #include "movie.h"
#include "cart.h"
#include "fds.h" #include "fds.h"
#include "vsuni.h" #include "vsuni.h"
#ifdef _S9XLUA_H #ifdef _S9XLUA_H
@ -34,6 +35,9 @@ extern void AddRecentMovieFile(const char *filename);
extern bool mustEngageTaseditor; extern bool mustEngageTaseditor;
#endif #endif
extern int RAMInitOption;
extern int RAMInitSeed;
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
@ -107,7 +111,6 @@ int currRerecordCount; // Keep the global value
char lagcounterbuf[32] = {0}; char lagcounterbuf[32] = {0};
#ifdef GEKKO #ifdef GEKKO
void MovieData::clearRecordRange(int start, int len) { } void MovieData::clearRecordRange(int start, int len) { }
void MovieData::eraseRecords(int at, int frames) { } void MovieData::eraseRecords(int at, int frames) { }
@ -454,8 +457,11 @@ void MovieRecord::dump(MovieData* md, EMUFILE* os, int index)
MovieData::MovieData() MovieData::MovieData()
: version(MOVIE_VERSION) : version(MOVIE_VERSION)
, emuVersion(FCEU_VERSION_NUMERIC) , emuVersion(FCEU_VERSION_NUMERIC)
, fds(false)
, palFlag(false) , palFlag(false)
, PPUflag(false) , PPUflag(false)
, RAMInitOption(0)
, RAMInitSeed(0)
, rerecordCount(0) , rerecordCount(0)
, binaryFlag(false) , binaryFlag(false)
, loadFrameCount(-1) , loadFrameCount(-1)
@ -476,6 +482,10 @@ void MovieData::installValue(std::string& key, std::string& val)
installInt(val,fds); installInt(val,fds);
else if(key == "NewPPU") else if(key == "NewPPU")
installBool(val,PPUflag); installBool(val,PPUflag);
else if(key == "RAMInitOption")
installInt(val,RAMInitOption);
else if(key == "RAMInitSeed")
installInt(val,RAMInitSeed);
else if(key == "version") else if(key == "version")
installInt(val,version); installInt(val,version);
else if(key == "emuVersion") else if(key == "emuVersion")
@ -516,6 +526,16 @@ void MovieData::installValue(std::string& key, std::string& val)
StringToBytes(val,&savestate[0],len); // decodes either base64 or hex StringToBytes(val,&savestate[0],len); // decodes either base64 or hex
} }
} }
else if(key == "saveram")
{
int len = Base64StringToBytesLength(val);
if(len == -1) len = HexStringToBytesLength(val); // wasn't base64, try hex
if(len >= 1)
{
saveram.resize(len);
StringToBytes(val,&saveram[0],len); // decodes either base64 or hex
}
}
else if (key == "length") else if (key == "length")
{ {
installInt(val, loadFrameCount); installInt(val, loadFrameCount);
@ -539,6 +559,8 @@ int MovieData::dump(EMUFILE *os, bool binary)
os->fprintf("port2 %d\n" , ports[2] ); os->fprintf("port2 %d\n" , ports[2] );
os->fprintf("FDS %d\n" , fds?1:0 ); os->fprintf("FDS %d\n" , fds?1:0 );
os->fprintf("NewPPU %d\n" , PPUflag?1:0 ); os->fprintf("NewPPU %d\n" , PPUflag?1:0 );
os->fprintf("RAMInitOption %d\n", RAMInitOption);
os->fprintf("RAMInitSeed %d\n", RAMInitSeed);
for(uint32 i=0;i<comments.size();i++) for(uint32 i=0;i<comments.size();i++)
os->fprintf("comment %s\n" , wcstombs(comments[i]).c_str() ); os->fprintf("comment %s\n" , wcstombs(comments[i]).c_str() );
@ -552,6 +574,9 @@ int MovieData::dump(EMUFILE *os, bool binary)
if(savestate.size()) if(savestate.size())
os->fprintf("savestate %s\n" , BytesToString(&savestate[0],savestate.size()).c_str() ); os->fprintf("savestate %s\n" , BytesToString(&savestate[0],savestate.size()).c_str() );
if(saveram.size())
os->fprintf("saveram %s\n" , BytesToString(&saveram[0],saveram.size()).c_str() );
if (this->loadFrameCount >= 0) if (this->loadFrameCount >= 0)
os->fprintf("length %d\n" , this->loadFrameCount); os->fprintf("length %d\n" , this->loadFrameCount);
@ -831,6 +856,8 @@ void FCEUI_StopMovie()
#endif #endif
} }
bool bogorf;
void poweron(bool shouldDisableBatteryLoading) void poweron(bool shouldDisableBatteryLoading)
{ {
//// make a for-movie-recording power-on clear the game's save data, too //// make a for-movie-recording power-on clear the game's save data, too
@ -855,9 +882,9 @@ void poweron(bool shouldDisableBatteryLoading)
//suppressAddPowerCommand=0; //suppressAddPowerCommand=0;
extern int disableBatteryLoading; extern int disableBatteryLoading;
disableBatteryLoading = 1; if(!bogorf) disableBatteryLoading = 1;
PowerNES(); PowerNES();
disableBatteryLoading = 0; if(!bogorf) disableBatteryLoading = 0;
} }
void FCEUMOV_CreateCleanMovie() void FCEUMOV_CreateCleanMovie()
@ -874,6 +901,8 @@ void FCEUMOV_CreateCleanMovie()
currMovieData.ports[2] = portFC.type; currMovieData.ports[2] = portFC.type;
currMovieData.fds = isFDS; currMovieData.fds = isFDS;
currMovieData.PPUflag = (newppu != 0); currMovieData.PPUflag = (newppu != 0);
currMovieData.RAMInitOption = RAMInitOption;
currMovieData.RAMInitSeed = RAMInitSeed;
} }
void FCEUMOV_ClearCommands() void FCEUMOV_ClearCommands()
{ {
@ -897,6 +926,59 @@ void MovieData::dumpSavestateTo(std::vector<uint8>* buf, int compressionLevel)
ms.trim(); ms.trim();
} }
bool MovieData::loadSaveramFrom(std::vector<uint8>* buf)
{
EMUFILE_MEMORY ms(buf);
bool hasBattery = !!ms.read32le();
if(hasBattery != !!currCartInfo->battery)
{
FCEU_PrintError("movie battery load mismatch 1");
return false;
}
for(int i=0;i<4;i++)
{
int len = ms.read32le();
if(!currCartInfo->SaveGame[i] && len!=0)
{
FCEU_PrintError("movie battery load mismatch 2");
return false;
}
if(currCartInfo->SaveGameLen[i] != len)
{
FCEU_PrintError("movie battery load mismatch 3");
return false;
}
ms.fread(currCartInfo->SaveGame[i], len);
}
return true;
}
void MovieData::dumpSaveramTo(std::vector<uint8>* buf, int compressionLevel)
{
EMUFILE_MEMORY ms(buf);
ms.write32le(currCartInfo->battery?1:0);
for(int i=0;i<4;i++)
{
if(!currCartInfo->SaveGame[i])
{
ms.write32le((u32)0);
continue;
}
ms.write32le(currCartInfo->SaveGameLen[i]);
ms.fwrite(currCartInfo->SaveGame[i], currCartInfo->SaveGameLen[i]);
}
}
//begin playing an existing movie //begin playing an existing movie
bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe) bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
{ {
@ -938,6 +1020,9 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
LoadSubtitles(currMovieData); LoadSubtitles(currMovieData);
delete fp; delete fp;
RAMInitOption = currMovieData.RAMInitOption;
RAMInitSeed = currMovieData.RAMInitSeed;
freshMovie = true; //Movie has been loaded, so it must be unaltered freshMovie = true; //Movie has been loaded, so it must be unaltered
if (bindSavestate) AutoSS = false; //If bind savestate to movie is true, then their isn't a valid auto-save to load, so flag it if (bindSavestate) AutoSS = false; //If bind savestate to movie is true, then their isn't a valid auto-save to load, so flag it
//fully reload the game to reinitialize everything before playing any movie //fully reload the game to reinitialize everything before playing any movie
@ -949,7 +1034,14 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
movieFromPoweron = false; movieFromPoweron = false;
bool success = MovieData::loadSavestateFrom(&currMovieData.savestate); bool success = MovieData::loadSavestateFrom(&currMovieData.savestate);
if(!success) return true; //adelikat: I guess return true here? False is only for a bad movie filename, if it got this far the file was good? if(!success) return true; //adelikat: I guess return true here? False is only for a bad movie filename, if it got this far the file was good?
} else { }
else if(currMovieData.saveram.size())
{
movieFromPoweron = true;
bool success = MovieData::loadSaveramFrom(&currMovieData.saveram);
if(!success) return true; //adelikat: I guess return true here? False is only for a bad movie filename, if it got this far the file was good?
}
else {
movieFromPoweron = true; movieFromPoweron = true;
} }
@ -960,6 +1052,8 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
else else
FCEUI_SetVidSystem(0); FCEUI_SetVidSystem(0);
//force the input configuration stored in the movie to apply //force the input configuration stored in the movie to apply
FCEUD_SetInput(currMovieData.fourscore, currMovieData.microphone, (ESI)currMovieData.ports[0], (ESI)currMovieData.ports[1], (ESIFC)currMovieData.ports[2]); FCEUD_SetInput(currMovieData.fourscore, currMovieData.microphone, (ESI)currMovieData.ports[0], (ESI)currMovieData.ports[1], (ESIFC)currMovieData.ports[2]);
@ -1027,7 +1121,15 @@ void FCEUI_SaveMovie(const char *fname, EMOVIE_FLAG flags, std::wstring author)
movieFromPoweron = true; movieFromPoweron = true;
poweron(true); poweron(true);
} }
else else if(flags & MOVIE_FLAG_FROM_SAVERAM)
{
movieFromPoweron = true;
MovieData::dumpSaveramTo(&currMovieData.saveram,Z_NO_COMPRESSION); //i guess with this there's a chance someone could hack the file, at least, so maybe it's helpfu
bogorf = true;
poweron(false);
bogorf = false;
}
else //from savestate
{ {
movieFromPoweron = false; movieFromPoweron = false;
MovieData::dumpSavestateTo(&currMovieData.savestate,Z_BEST_COMPRESSION); MovieData::dumpSavestateTo(&currMovieData.savestate,Z_BEST_COMPRESSION);
@ -1481,7 +1583,7 @@ void FCEUMOV_IncrementRerecordCount()
else else
currMovieData.rerecordCount++; currMovieData.rerecordCount++;
#else #else
if (movieMode != MOVIEMODE_TASEDITOR)currRerecordCount++; if (movieMode != MOVIEMODE_TASEDITOR)
currRerecordCount++; currRerecordCount++;
else else
currMovieData.rerecordCount++; currMovieData.rerecordCount++;
@ -1627,6 +1729,8 @@ bool FCEUI_MovieGetInfo(FCEUFILE* fp, MOVIE_INFO& info, bool skipFrameCount)
info.reset = false; //Soft-reset isn't used from starting movies anymore, so this will be false, better for FCEUFILE to have that info (as |1| on the first frame indicates it info.reset = false; //Soft-reset isn't used from starting movies anymore, so this will be false, better for FCEUFILE to have that info (as |1| on the first frame indicates it
info.pal = md.palFlag; info.pal = md.palFlag;
info.ppuflag = md.PPUflag; info.ppuflag = md.PPUflag;
info.RAMInitOption = md.RAMInitOption;
info.RAMInitSeed = md.RAMInitSeed;
info.nosynchack = true; info.nosynchack = true;
info.num_frames = md.records.size(); info.num_frames = md.records.size();
info.md5_of_rom_used = md.romChecksum; info.md5_of_rom_used = md.romChecksum;

View File

@ -23,13 +23,15 @@ enum EMOVIE_FLAG
MOVIE_FLAG_PAL = (1<<2), MOVIE_FLAG_PAL = (1<<2),
//movie was recorded from poweron. the alternative is from a savestate (or from reset) //movie was recorded from poweron. the alternative is from a savestate (or from reset). OR from saveram.
MOVIE_FLAG_FROM_POWERON = (1<<3), MOVIE_FLAG_FROM_POWERON = (1<<3),
// set in newer version, used for old movie compatibility // set in newer version, used for old movie compatibility
//TODO - only use this flag to print a warning that the sync might be bad //TODO - only use this flag to print a warning that the sync might be bad
//so that we can get rid of the sync hack code //so that we can get rid of the sync hack code
MOVIE_FLAG_NOSYNCHACK = (1<<4) MOVIE_FLAG_NOSYNCHACK = (1<<4),
MOVIE_FLAG_FROM_SAVERAM = (1<<5)
}; };
typedef struct typedef struct
@ -42,6 +44,7 @@ typedef struct
uint32 emu_version_used; // 9813 = 0.98.13 uint32 emu_version_used; // 9813 = 0.98.13
MD5DATA md5_of_rom_used; MD5DATA md5_of_rom_used;
std::string name_of_rom_used; std::string name_of_rom_used;
int RAMInitOption, RAMInitSeed;
std::vector<std::wstring> comments; std::vector<std::wstring> comments;
std::vector<std::string> subtitles; std::vector<std::string> subtitles;
@ -177,6 +180,7 @@ public:
MD5DATA romChecksum; MD5DATA romChecksum;
std::string romFilename; std::string romFilename;
std::vector<uint8> savestate; std::vector<uint8> savestate;
std::vector<uint8> saveram;
std::vector<MovieRecord> records; std::vector<MovieRecord> records;
std::vector<std::wstring> comments; std::vector<std::wstring> comments;
std::vector<std::string> subtitles; std::vector<std::string> subtitles;
@ -198,6 +202,8 @@ public:
int getNumRecords() { return records.size(); } int getNumRecords() { return records.size(); }
int RAMInitOption, RAMInitSeed;
class TDictionary : public std::map<std::string,std::string> class TDictionary : public std::map<std::string,std::string>
{ {
public: public:
@ -238,6 +244,9 @@ public:
static bool loadSavestateFrom(std::vector<uint8>* buf); static bool loadSavestateFrom(std::vector<uint8>* buf);
static void dumpSavestateTo(std::vector<uint8>* buf, int compressionLevel); static void dumpSavestateTo(std::vector<uint8>* buf, int compressionLevel);
static bool loadSaveramFrom(std::vector<uint8>* buf);
static void dumpSaveramTo(std::vector<uint8>* buf, int compressionLevel);
private: private:
void installInt(std::string& val, int& var) void installInt(std::string& val, int& var)
{ {

View File

@ -119,7 +119,7 @@ int FCEUNET_SendFile(uint8 cmd, char *fn)
if(!(fp=FCEUD_UTF8fopen(fn,"rb"))) return(0); if(!(fp=FCEUD_UTF8fopen(fn,"rb"))) return(0);
fstat(fileno(fp),&sb); FCEUX_fstat(fileno(fp),&sb);
len = sb.st_size; len = sb.st_size;
buf = (char*)FCEU_dmalloc(len); //mbg merge 7/17/06 added cast buf = (char*)FCEU_dmalloc(len); //mbg merge 7/17/06 added cast
fread(buf, 1, len, fp); fread(buf, 1, len, fp);

View File

@ -482,6 +482,7 @@ void DrawNSF(uint8 *XBuf)
if(vismode==0) return; if(vismode==0) return;
memset(XBuf,0,256*240); memset(XBuf,0,256*240);
memset(XDBuf,0,256*240);
{ {
@ -567,13 +568,14 @@ void DrawNSF(uint8 *XBuf)
} }
} }
DrawTextTrans(ClipSidesOffset+XBuf+10*256+4+(((31-strlen((char*)NSFHeader.SongName))<<2)), 256, NSFHeader.SongName, 6); static const int kFgColor = 1;
DrawTextTrans(ClipSidesOffset+XBuf+26*256+4+(((31-strlen((char*)NSFHeader.Artist))<<2)), 256,NSFHeader.Artist, 6); DrawTextTrans(ClipSidesOffset+XBuf+10*256+4+(((31-strlen((char*)NSFHeader.SongName))<<2)), 256, NSFHeader.SongName, kFgColor);
DrawTextTrans(ClipSidesOffset+XBuf+42*256+4+(((31-strlen((char*)NSFHeader.Copyright))<<2)), 256,NSFHeader.Copyright, 6); DrawTextTrans(ClipSidesOffset+XBuf+26*256+4+(((31-strlen((char*)NSFHeader.Artist))<<2)), 256,NSFHeader.Artist, kFgColor);
DrawTextTrans(ClipSidesOffset+XBuf+42*256+4+(((31-strlen((char*)NSFHeader.Copyright))<<2)), 256,NSFHeader.Copyright, kFgColor);
DrawTextTrans(ClipSidesOffset+XBuf+70*256+4+(((31-strlen("Song:"))<<2)), 256, (uint8*)"Song:", 6); DrawTextTrans(ClipSidesOffset+XBuf+70*256+4+(((31-strlen("Song:"))<<2)), 256, (uint8*)"Song:", kFgColor);
sprintf(snbuf,"<%d/%d>",CurrentSong,NSFHeader.TotalSongs); sprintf(snbuf,"<%d/%d>",CurrentSong,NSFHeader.TotalSongs);
DrawTextTrans(XBuf+82*256+4+(((31-strlen(snbuf))<<2)), 256, (uint8*)snbuf, 6); DrawTextTrans(XBuf+82*256+4+(((31-strlen(snbuf))<<2)), 256, (uint8*)snbuf, kFgColor);
{ {
static uint8 last=0; static uint8 last=0;

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +1,59 @@
pal rp2c04001[64] = { #define EMPTY_PALETTE_1 {0,0,0},
#define EMPTY_PALETTE_4 EMPTY_PALETTE_1 EMPTY_PALETTE_1 EMPTY_PALETTE_1 EMPTY_PALETTE_1
#define EMPTY_PALETTE_16 EMPTY_PALETTE_4 EMPTY_PALETTE_4 EMPTY_PALETTE_4 EMPTY_PALETTE_4
#define EMPTY_PALETTE_64 EMPTY_PALETTE_16 EMPTY_PALETTE_16 EMPTY_PALETTE_16 EMPTY_PALETTE_16
#define EMPTY_PALETTE_DEEMPH_X_7 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64
pal rp2c04001[512] = {
#include "rp2c04001.h" #include "rp2c04001.h"
EMPTY_PALETTE_DEEMPH_X_7
}; };
pal rp2c04002[64] = { pal rp2c04002[512] = {
#include "rp2c04002.h" #include "rp2c04002.h"
EMPTY_PALETTE_DEEMPH_X_7
}; };
pal rp2c04003[64] = { pal rp2c04003[512] = {
#include "rp2c04003.h" #include "rp2c04003.h"
EMPTY_PALETTE_DEEMPH_X_7
}; };
pal rp2c05004[64] = { pal rp2c05004[512] = {
#include "rp2c05004.h" #include "rp2c05004.h"
EMPTY_PALETTE_DEEMPH_X_7
}; };
pal unvpalette[7] = { // Fixed palette entries used by the GUI
{ 0x00<<2,0x00<<2,0x00<<2}, // Black pal palette_unvarying[] = {
{ 0x3F<<2,0x3F<<2,0x34<<2}, // White { 0x00<<2,0x00<<2,0x00<<2}, // 0 = Black
{ 0x00<<2,0x00<<2,0x00<<2}, // Black { 0x3F<<2,0x3F<<2,0x34<<2}, // 1 = White
{ 0x1d<<2,0x1d<<2,0x24<<2}, // Greyish { 0x00<<2,0x00<<2,0x00<<2}, // 2 = Black
{ 190,0,0 }, // Redish { 0x1d<<2,0x1d<<2,0x24<<2}, // 3 = Greyish
{ 51,255,51}, // Bright green { 190, 0, 0}, // 4 = Reddish
{ 49,14,200}, { 51,255, 51}, // 5 = Bright green
{ 49, 14,200}, // 6 = Ultramarine Blue
// 16 saturated colors useful for Lua scripts
{ 0, 0, 0}, // 7 = Black
{ 0, 0,128}, // 8 = Dark Blue
{ 0,128, 0}, // 9 = Dark Green
{ 0,128,128}, // 10 = Dark Cyan
{ 128, 0, 0}, // 11 = Dark Red
{ 128, 0,128}, // 12 = Dark Magenta
{ 128,128, 0}, // 13 = Dark Yellow
{ 128,128,128}, // 14 = Light Grey
{ 64, 64, 64}, // 15 = Dark Grey
{ 0, 0,255}, // 16 = Bright Blue
{ 0,255, 0}, // 17 = Bright Green
{ 0,255,255}, // 18 = Bright Cyan
{ 255, 0, 0}, // 19 = Bright Red
{ 255, 0,255}, // 20 = Bright Magenta
{ 255,255, 0}, // 21 = Bright Yellow
{ 255,255,255}, // 22 = Bright White
}; };
// Default palette // Default palette
pal palette[64] = { pal palette[512] = {
{ 0x1D<<2, 0x1D<<2, 0x1D<<2 }, /* Value 0 */ { 0x1D<<2, 0x1D<<2, 0x1D<<2 }, /* Value 0 */
{ 0x09<<2, 0x06<<2, 0x23<<2 }, /* Value 1 */ { 0x09<<2, 0x06<<2, 0x23<<2 }, /* Value 1 */
@ -292,4 +320,6 @@ slightly better but too dark:
*/ */
EMPTY_PALETTE_DEEMPH_X_7
}; };

View File

@ -19,45 +19,46 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "types.h" #include "types.h"
#include "x6502.h" #include "x6502.h"
#include "fceu.h" #include "fceu.h"
#include "ppu.h" #include "ppu.h"
#include "nsf.h" #include "nsf.h"
#include "sound.h" #include "sound.h"
#include "file.h" #include "file.h"
#include "utils/endian.h" #include "utils/endian.h"
#include "utils/memory.h" #include "utils/memory.h"
#include "cart.h"
#include "palette.h"
#include "state.h"
#include "video.h"
#include "input.h"
#include "driver.h"
#include "debug.h"
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include "cart.h" #define VBlankON (PPU[0] & 0x80) //Generate VBlank NMI
#include "palette.h" #define Sprite16 (PPU[0] & 0x20) //Sprites 8x16/8x8
#include "state.h" #define BGAdrHI (PPU[0] & 0x10) //BG pattern adr $0000/$1000
#include "video.h" #define SpAdrHI (PPU[0] & 0x08) //Sprite pattern adr $0000/$1000
#include "input.h" #define INC32 (PPU[0] & 0x04) //auto increment 1/32
#include "driver.h"
#include "debug.h"
#include <cstring> #define SpriteON (PPU[1] & 0x10) //Show Sprite
#include <cstdio> #define ScreenON (PPU[1] & 0x08) //Show screen
#include <cstdlib> #define PPUON (PPU[1] & 0x18) //PPU should operate
#define GRAYSCALE (PPU[1] & 0x01) //Grayscale (AND palette entries with 0x30)
#define VBlankON (PPU[0] & 0x80) //Generate VBlank NMI #define SpriteLeft8 (PPU[1] & 0x04)
#define Sprite16 (PPU[0] & 0x20) //Sprites 8x16/8x8 #define BGLeft8 (PPU[1] & 0x02)
#define BGAdrHI (PPU[0] & 0x10) //BG pattern adr $0000/$1000
#define SpAdrHI (PPU[0] & 0x08) //Sprite pattern adr $0000/$1000
#define INC32 (PPU[0] & 0x04) //auto increment 1/32
#define SpriteON (PPU[1] & 0x10) //Show Sprite #define PPU_status (PPU[2])
#define ScreenON (PPU[1] & 0x08) //Show screen
#define PPUON (PPU[1] & 0x18) //PPU should operate
#define GRAYSCALE (PPU[1] & 0x01) //Grayscale (AND palette entries with 0x30)
#define SpriteLeft8 (PPU[1] & 0x04) #define READPAL(ofs) (PALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF))
#define BGLeft8 (PPU[1] & 0x02) #define READUPAL(ofs) (UPALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF))
#define PPU_status (PPU[2])
#define Pal (PALRAM)
static void FetchSpriteData(void); static void FetchSpriteData(void);
static void RefreshLine(int lastpixel); static void RefreshLine(int lastpixel);
@ -69,6 +70,8 @@ static uint32 ppulut1[256];
static uint32 ppulut2[256]; static uint32 ppulut2[256];
static uint32 ppulut3[128]; static uint32 ppulut3[128];
static bool new_ppu_reset = false;
int test = 0; int test = 0;
template<typename T, int BITS> template<typename T, int BITS>
@ -274,8 +277,24 @@ struct PPUREGS {
v &= 1; v &= 1;
fv &= 7; fv &= 7;
} }
void debug_log()
{
FCEU_printf("ppur: fv(%d), v(%d), h(%d), vt(%d), ht(%d)\n",fv,v,h,vt,ht);
FCEU_printf(" _fv(%d), _v(%d), _h(%d), _vt(%d), _ht(%d)\n",_fv,_v,_h,_vt,_ht);
FCEU_printf(" fh(%d), s(%d), par(%d)\n",fh,s,par);
FCEU_printf(" .status cycle(%d), end_cycle(%d), sl(%d)\n",status.cycle,status.end_cycle,status.sl);
}
} ppur; } ppur;
int newppu_get_scanline() { return ppur.status.sl; }
int newppu_get_dot() { return ppur.status.cycle; }
void newppu_hacky_emergency_reset()
{
if(ppur.status.end_cycle == 0)
ppur.reset();
}
static void makeppulut(void) { static void makeppulut(void) {
int x; int x;
int y; int y;
@ -337,7 +356,7 @@ uint8 vtoggle = 0;
uint8 XOffset = 0; uint8 XOffset = 0;
uint8 SpriteDMA = 0; // $4014 / Writing $xx copies 256 bytes by reading from $xx00-$xxFF and writing to $2004 (OAM data) uint8 SpriteDMA = 0; // $4014 / Writing $xx copies 256 bytes by reading from $xx00-$xxFF and writing to $2004 (OAM data)
uint32 TempAddr = 0, RefreshAddr = 0, DummyRead = 0; uint32 TempAddr = 0, RefreshAddr = 0, DummyRead = 0, NTRefreshAddr = 0;
static int maxsprites = 8; static int maxsprites = 8;
@ -355,18 +374,7 @@ uint8 UPALRAM[0x03];//for 0x4/0x8/0xC addresses in palette, the ones in
#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)] #define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)]
#define VRAMADR(V) &VPage[(V) >> 10][(V)] #define VRAMADR(V) &VPage[(V) >> 10][(V)]
//mbg 8/6/08 - fix a bug relating to uint8* MMC5BGVRAMADR(uint32 A);
//"When in 8x8 sprite mode, only one set is used for both BG and sprites."
//in mmc5 docs
uint8 * MMC5BGVRAMADR(uint32 V) {
if (!Sprite16) {
extern uint8 mmc5ABMode; /* A=0, B=1 */
if (mmc5ABMode == 0)
return MMC5SPRVRAMADR(V);
else
return &MMC5BGVPage[(V) >> 10][(V)];
} else return &MMC5BGVPage[(V) >> 10][(V)];
}
//this duplicates logic which is embedded in the ppu rendering code //this duplicates logic which is embedded in the ppu rendering code
//which figures out where to get CHR data from depending on various hack modes //which figures out where to get CHR data from depending on various hack modes
@ -420,7 +428,7 @@ inline void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) {
} }
volatile int rendercount, vromreadcount, undefinedvromcount, LogAddress = -1; volatile int rendercount, vromreadcount, undefinedvromcount, LogAddress = -1;
unsigned char *cdloggervdata; unsigned char *cdloggervdata = NULL;
unsigned int cdloggerVideoDataSize = 0; unsigned int cdloggerVideoDataSize = 0;
int GetCHRAddress(int A) { int GetCHRAddress(int A) {
@ -428,6 +436,19 @@ int GetCHRAddress(int A) {
int result = &VPage[A >> 10][A] - CHRptr[0]; int result = &VPage[A >> 10][A] - CHRptr[0];
if ((result >= 0) && (result < (int)cdloggerVideoDataSize)) if ((result >= 0) && (result < (int)cdloggerVideoDataSize))
return result; return result;
} else
if(A < 0x2000) return A;
return -1;
}
int GetCHROffset(uint8 *ptr) {
int result = ptr - CHRptr[0];
if (cdloggerVideoDataSize) {
if ((result >= 0) && (result < (int)cdloggerVideoDataSize))
return result;
} else {
if ((result >= 0) && (result < 0x2000))
return result;
} }
return -1; return -1;
} }
@ -441,8 +462,28 @@ int GetCHRAddress(int A) {
if (!(cdloggervdata[addr] & 1)) \ if (!(cdloggervdata[addr] & 1)) \
{ \ { \
cdloggervdata[addr] |= 1; \ cdloggervdata[addr] |= 1; \
if (!(cdloggervdata[addr] & 2)) undefinedvromcount--; \ if(cdloggerVideoDataSize) { \
rendercount++; \ if (!(cdloggervdata[addr] & 2)) undefinedvromcount--; \
rendercount++; \
} \
} \
} \
} \
}
#define RENDER_LOGP(tmp) { \
if (debug_loggingCD) \
{ \
int addr = GetCHROffset(tmp); \
if (addr != -1) \
{ \
if (!(cdloggervdata[addr] & 1)) \
{ \
cdloggervdata[addr] |= 1; \
if(cdloggerVideoDataSize) { \
if (!(cdloggervdata[addr] & 2)) undefinedvromcount--; \
rendercount++; \
} \
} \ } \
} \ } \
} \ } \
@ -461,14 +502,11 @@ uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A) {
uint8 ret; uint8 ret;
if (!(tmp & 3)) { if (!(tmp & 3)) {
if (!(tmp & 0xC)) if (!(tmp & 0xC))
ret = PALRAM[0x00]; ret = READPAL(0x00);
else else
ret = UPALRAM[((tmp & 0xC) >> 2) - 1]; ret = READUPAL(((tmp & 0xC) >> 2) - 1);
} else } else
ret = PALRAM[tmp & 0x1F]; ret = READPAL(tmp & 0x1F);
if (GRAYSCALE)
ret &= 0x30;
return ret; return ret;
} }
} }
@ -481,7 +519,7 @@ void (*FFCEUX_PPUWrite)(uint32 A, uint8 V) = 0;
#define CALL_PPUWRITE(A, V) (FFCEUX_PPUWrite ? FFCEUX_PPUWrite(A, V) : FFCEUX_PPUWrite_Default(A, V)) #define CALL_PPUWRITE(A, V) (FFCEUX_PPUWrite ? FFCEUX_PPUWrite(A, V) : FFCEUX_PPUWrite_Default(A, V))
//whether to use the new ppu (new PPU doesn't handle MMC5 extra nametables at all //whether to use the new ppu
int newppu = 0; int newppu = 0;
void ppu_getScroll(int &xpos, int &ypos) { void ppu_getScroll(int &xpos, int &ypos) {
@ -665,7 +703,7 @@ static DECLFR(A2007) {
if (!DummyRead && (LogAddress != -1)) { if (!DummyRead && (LogAddress != -1)) {
if (!(cdloggervdata[LogAddress] & 2)) { if (!(cdloggervdata[LogAddress] & 2)) {
cdloggervdata[LogAddress] |= 2; cdloggervdata[LogAddress] |= 2;
if (!(cdloggervdata[LogAddress] & 1)) undefinedvromcount--; if ((!(cdloggervdata[LogAddress] & 1)) && cdloggerVideoDataSize) undefinedvromcount--;
vromreadcount++; vromreadcount++;
} }
} else } else
@ -683,13 +721,11 @@ static DECLFR(A2007) {
//to get a gray color reading //to get a gray color reading
if (!(tmp & 3)) { if (!(tmp & 3)) {
if (!(tmp & 0xC)) if (!(tmp & 0xC))
ret = PALRAM[0x00]; ret = READPAL(0x00);
else else
ret = UPALRAM[((tmp & 0xC) >> 2) - 1]; ret = READUPAL(((tmp & 0xC) >> 2) - 1);
} else } else
ret = PALRAM[tmp & 0x1F]; ret = READPAL(tmp & 0x1F);
if (GRAYSCALE)
ret &= 0x30;
VRAMBuffer = CALL_PPUREAD(RefreshAddr - 0x1000); VRAMBuffer = CALL_PPUREAD(RefreshAddr - 0x1000);
} else { } else {
if (debug_loggingCD && (RefreshAddr < 0x2000)) if (debug_loggingCD && (RefreshAddr < 0x2000))
@ -700,18 +736,18 @@ static DECLFR(A2007) {
RefreshAddr = ppur.get_2007access(); RefreshAddr = ppur.get_2007access();
return ret; return ret;
} else { } else {
//OLDPPU
FCEUPPU_LineUpdate(); FCEUPPU_LineUpdate();
if (tmp >= 0x3F00) { // Palette RAM tied directly to the output data, without VRAM buffer if (tmp >= 0x3F00) { // Palette RAM tied directly to the output data, without VRAM buffer
if (!(tmp & 3)) { if (!(tmp & 3)) {
if (!(tmp & 0xC)) if (!(tmp & 0xC))
ret = PALRAM[0x00]; ret = READPAL(0x00);
else else
ret = UPALRAM[((tmp & 0xC) >> 2) - 1]; ret = READUPAL(((tmp & 0xC) >> 2) - 1);
} else } else
ret = PALRAM[tmp & 0x1F]; ret = READPAL(tmp & 0x1F);
if (GRAYSCALE)
ret &= 0x30;
#ifdef FCEUDEF_DEBUGGER #ifdef FCEUDEF_DEBUGGER
if (!fceuindbg) if (!fceuindbg)
#endif #endif
@ -731,9 +767,14 @@ static DECLFR(A2007) {
if (PPU_hook) PPU_hook(tmp); if (PPU_hook) PPU_hook(tmp);
PPUGenLatch = VRAMBuffer; PPUGenLatch = VRAMBuffer;
if (tmp < 0x2000) { if (tmp < 0x2000) {
if (debug_loggingCD) if (debug_loggingCD)
LogAddress = GetCHRAddress(tmp); LogAddress = GetCHRAddress(tmp);
VRAMBuffer = VPage[tmp >> 10][tmp]; if(MMC5Hack && newppu)
VRAMBuffer = *MMC5BGVRAMADR(tmp);
else
VRAMBuffer = VPage[tmp >> 10][tmp];
} else if (tmp < 0x3F00) } else if (tmp < 0x3F00)
VRAMBuffer = vnapage[(tmp >> 10) & 0x3][tmp & 0x3FF]; VRAMBuffer = vnapage[(tmp >> 10) & 0x3][tmp & 0x3FF];
} }
@ -786,6 +827,8 @@ static DECLFW(B2000) {
static DECLFW(B2001) { static DECLFW(B2001) {
FCEUPPU_LineUpdate(); FCEUPPU_LineUpdate();
if (paldeemphswap)
V = (V&0x9F)|((V&0x40)>>1)|((V&0x20)<<1);
PPUGenLatch = V; PPUGenLatch = V;
PPU[1] = V; PPU[1] = V;
if (V & 0xE0) if (V & 0xE0)
@ -881,6 +924,11 @@ static DECLFW(B2006) {
static DECLFW(B2007) { static DECLFW(B2007) {
uint32 tmp = RefreshAddr & 0x3FFF; uint32 tmp = RefreshAddr & 0x3FFF;
if (debug_loggingCD) {
if(!cdloggerVideoDataSize && (tmp < 0x2000))
cdloggervdata[tmp] = 0;
}
if (newppu) { if (newppu) {
PPUGenLatch = V; PPUGenLatch = V;
RefreshAddr = ppur.get_2007access() & 0x3FFF; RefreshAddr = ppur.get_2007access() & 0x3FFF;
@ -1043,7 +1091,7 @@ static void RefreshLine(int lastpixel) {
if (!ScreenON && !SpriteON) { if (!ScreenON && !SpriteON) {
uint32 tem; uint32 tem;
tem = Pal[0] | (Pal[0] << 8) | (Pal[0] << 16) | (Pal[0] << 24); tem = READPAL(0) | (READPAL(0) << 8) | (READPAL(0) << 16) | (READPAL(0) << 24);
tem |= 0x40404040; tem |= 0x40404040;
FCEU_dwmemset(Pline, tem, numtiles * 8); FCEU_dwmemset(Pline, tem, numtiles * 8);
P += numtiles * 8; P += numtiles * 8;
@ -1064,10 +1112,10 @@ static void RefreshLine(int lastpixel) {
} }
//Priority bits, needed for sprite emulation. //Priority bits, needed for sprite emulation.
Pal[0] |= 64; PALRAM[0] |= 64;
Pal[4] |= 64; PALRAM[4] |= 64;
Pal[8] |= 64; PALRAM[8] |= 64;
Pal[0xC] |= 64; PALRAM[0xC] |= 64;
//This high-level graphics MMC5 emulation code was written for MMC5 carts in "CL" mode. //This high-level graphics MMC5 emulation code was written for MMC5 carts in "CL" mode.
//It's probably not totally correct for carts in "SL" mode. //It's probably not totally correct for carts in "SL" mode.
@ -1145,15 +1193,15 @@ static void RefreshLine(int lastpixel) {
#undef RefreshAddr #undef RefreshAddr
//Reverse changes made before. //Reverse changes made before.
Pal[0] &= 63; PALRAM[0] &= 63;
Pal[4] &= 63; PALRAM[4] &= 63;
Pal[8] &= 63; PALRAM[8] &= 63;
Pal[0xC] &= 63; PALRAM[0xC] &= 63;
RefreshAddr = smorkus; RefreshAddr = smorkus;
if (firsttile <= 2 && 2 < lasttile && !(PPU[1] & 2)) { if (firsttile <= 2 && 2 < lasttile && !(PPU[1] & 2)) {
uint32 tem; uint32 tem;
tem = Pal[0] | (Pal[0] << 8) | (Pal[0] << 16) | (Pal[0] << 24); tem = READPAL(0) | (READPAL(0) << 8) | (READPAL(0) << 16) | (READPAL(0) << 24);
tem |= 0x40404040; tem |= 0x40404040;
*(uint32*)Plinef = *(uint32*)(Plinef + 4) = tem; *(uint32*)Plinef = *(uint32*)(Plinef + 4) = tem;
} }
@ -1161,7 +1209,7 @@ static void RefreshLine(int lastpixel) {
if (!ScreenON) { if (!ScreenON) {
uint32 tem; uint32 tem;
int tstart, tcount; int tstart, tcount;
tem = Pal[0] | (Pal[0] << 8) | (Pal[0] << 16) | (Pal[0] << 24); tem = READPAL(0) | (READPAL(0) << 8) | (READPAL(0) << 16) | (READPAL(0) << 24);
tem |= 0x40404040; tem |= 0x40404040;
tcount = lasttile - firsttile; tcount = lasttile - firsttile;
@ -1218,11 +1266,16 @@ static void Fixit1(void) {
void MMC5_hb(int); //Ugh ugh ugh. void MMC5_hb(int); //Ugh ugh ugh.
static void DoLine(void) { static void DoLine(void) {
if (scanline >= 240 && scanline != totalscanlines) {
X6502_Run(256 + 69);
scanline++;
X6502_Run(16);
return;
}
int x; int x;
// scanlines after 239 are dummy for dendy, and Xbuf is capped at 0xffff bytes, don't let it overflow
// send all future writes to the invisible sanline. the easiest way to "skip" them altogether in old ppu
// todo: figure out what exactly should be skipped. it's known that there's no activity on PPU bus
uint8 *target = XBuf + ((scanline < 240 ? scanline : 240) << 8); uint8 *target = XBuf + ((scanline < 240 ? scanline : 240) << 8);
u8* dtarget = XDBuf + ((scanline < 240 ? scanline : 240) << 8);
if (MMC5Hack) MMC5_hb(scanline); if (MMC5Hack) MMC5_hb(scanline);
@ -1233,22 +1286,26 @@ static void DoLine(void) {
uint32 tem; uint32 tem;
uint8 col; uint8 col;
if (gNoBGFillColor == 0xFF) if (gNoBGFillColor == 0xFF)
col = Pal[0]; col = READPAL(0);
else col = gNoBGFillColor; else col = gNoBGFillColor;
tem = col | (col << 8) | (col << 16) | (col << 24); tem = col | (col << 8) | (col << 16) | (col << 24);
tem |= 0x40404040; tem |= 0x40404040;
FCEU_dwmemset(target, tem, 256); FCEU_dwmemset(target, tem, 256);
} }
if (SpriteON) if (SpriteON)
CopySprites(target); CopySprites(target);
if (ScreenON || SpriteON) { // Yes, very el-cheapo. //greyscale handling (mask some bits off the color) ? ? ?
if (ScreenON || SpriteON)
{
if (PPU[1] & 0x01) { if (PPU[1] & 0x01) {
for (x = 63; x >= 0; x--) for (x = 63; x >= 0; x--)
*(uint32*)&target[x << 2] = (*(uint32*)&target[x << 2]) & 0x30303030; *(uint32*)&target[x << 2] = (*(uint32*)&target[x << 2]) & 0x30303030;
} }
} }
//some pathetic attempts at deemph
if ((PPU[1] >> 5) == 0x7) { if ((PPU[1] >> 5) == 0x7) {
for (x = 63; x >= 0; x--) for (x = 63; x >= 0; x--)
*(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0xc0c0c0c0; *(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0xc0c0c0c0;
@ -1259,6 +1316,10 @@ static void DoLine(void) {
for (x = 63; x >= 0; x--) for (x = 63; x >= 0; x--)
*(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0x80808080; *(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0x80808080;
//write the actual deemph
for (x = 63; x >= 0; x--)
*(uint32*)&dtarget[x << 2] = ((PPU[1]>>5)<<0)|((PPU[1]>>5)<<8)|((PPU[1]>>5)<<16)|((PPU[1]>>5)<<24);
sphitx = 0x100; sphitx = 0x100;
if (ScreenON || SpriteON) if (ScreenON || SpriteON)
@ -1362,10 +1423,10 @@ static void FetchSpriteData(void) {
C = VRAMADR(vadr); C = VRAMADR(vadr);
if (SpriteON) if (SpriteON)
RENDER_LOG(vadr); RENDER_LOGP(C);
dst.ca[0] = C[0]; dst.ca[0] = C[0];
if (SpriteON) if (SpriteON)
RENDER_LOG(vadr + 8); RENDER_LOGP(C + 8);
dst.ca[1] = C[8]; dst.ca[1] = C[8];
dst.x = spr->x; dst.x = spr->x;
dst.atr = spr->atr; dst.atr = spr->atr;
@ -1414,14 +1475,14 @@ static void FetchSpriteData(void) {
else else
C = VRAMADR(vadr); C = VRAMADR(vadr);
if (SpriteON) if (SpriteON)
RENDER_LOG(vadr); RENDER_LOGP(C);
dst.ca[0] = C[0]; dst.ca[0] = C[0];
if (ns < 8) { if (ns < 8) {
PPU_hook(0x2000); PPU_hook(0x2000);
PPU_hook(vadr); PPU_hook(vadr);
} }
if (SpriteON) if (SpriteON)
RENDER_LOG(vadr + 8); RENDER_LOGP(C + 8);
dst.ca[1] = C[8]; dst.ca[1] = C[8];
dst.x = spr->x; dst.x = spr->x;
dst.atr = spr->atr; dst.atr = spr->atr;
@ -1466,7 +1527,7 @@ static void RefreshSprites(void) {
int x = spr->x; int x = spr->x;
uint8 *C; uint8 *C;
uint8 *VB; int VB;
pixdata = ppulut1[spr->ca[0]] | ppulut2[spr->ca[1]]; pixdata = ppulut1[spr->ca[0]] | ppulut2[spr->ca[1]];
J = spr->ca[0] | spr->ca[1]; J = spr->ca[0] | spr->ca[1];
@ -1488,75 +1549,75 @@ static void RefreshSprites(void) {
} }
C = sprlinebuf + x; C = sprlinebuf + x;
VB = (PALRAM + 0x10) + ((atr & 3) << 2); VB = (0x10) + ((atr & 3) << 2);
if (atr & SP_BACK) { if (atr & SP_BACK) {
if (atr & H_FLIP) { if (atr & H_FLIP) {
if (J & 0x80) C[7] = VB[pixdata & 3] | 0x40; if (J & 0x80) C[7] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x40) C[6] = VB[pixdata & 3] | 0x40; if (J & 0x40) C[6] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x20) C[5] = VB[pixdata & 3] | 0x40; if (J & 0x20) C[5] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x10) C[4] = VB[pixdata & 3] | 0x40; if (J & 0x10) C[4] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x08) C[3] = VB[pixdata & 3] | 0x40; if (J & 0x08) C[3] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x04) C[2] = VB[pixdata & 3] | 0x40; if (J & 0x04) C[2] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x02) C[1] = VB[pixdata & 3] | 0x40; if (J & 0x02) C[1] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x01) C[0] = VB[pixdata] | 0x40; if (J & 0x01) C[0] = READPAL(VB | pixdata) | 0x40;
} else { } else {
if (J & 0x80) C[0] = VB[pixdata & 3] | 0x40; if (J & 0x80) C[0] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x40) C[1] = VB[pixdata & 3] | 0x40; if (J & 0x40) C[1] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x20) C[2] = VB[pixdata & 3] | 0x40; if (J & 0x20) C[2] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x10) C[3] = VB[pixdata & 3] | 0x40; if (J & 0x10) C[3] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x08) C[4] = VB[pixdata & 3] | 0x40; if (J & 0x08) C[4] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x04) C[5] = VB[pixdata & 3] | 0x40; if (J & 0x04) C[5] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x02) C[6] = VB[pixdata & 3] | 0x40; if (J & 0x02) C[6] = READPAL(VB | (pixdata & 3)) | 0x40;
pixdata >>= 4; pixdata >>= 4;
if (J & 0x01) C[7] = VB[pixdata] | 0x40; if (J & 0x01) C[7] = READPAL(VB | pixdata) | 0x40;
} }
} else { } else {
if (atr & H_FLIP) { if (atr & H_FLIP) {
if (J & 0x80) C[7] = VB[pixdata & 3]; if (J & 0x80) C[7] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x40) C[6] = VB[pixdata & 3]; if (J & 0x40) C[6] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x20) C[5] = VB[pixdata & 3]; if (J & 0x20) C[5] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x10) C[4] = VB[pixdata & 3]; if (J & 0x10) C[4] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x08) C[3] = VB[pixdata & 3]; if (J & 0x08) C[3] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x04) C[2] = VB[pixdata & 3]; if (J & 0x04) C[2] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x02) C[1] = VB[pixdata & 3]; if (J & 0x02) C[1] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x01) C[0] = VB[pixdata]; if (J & 0x01) C[0] = READPAL(VB | pixdata);
} else { } else {
if (J & 0x80) C[0] = VB[pixdata & 3]; if (J & 0x80) C[0] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x40) C[1] = VB[pixdata & 3]; if (J & 0x40) C[1] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x20) C[2] = VB[pixdata & 3]; if (J & 0x20) C[2] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x10) C[3] = VB[pixdata & 3]; if (J & 0x10) C[3] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x08) C[4] = VB[pixdata & 3]; if (J & 0x08) C[4] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x04) C[5] = VB[pixdata & 3]; if (J & 0x04) C[5] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x02) C[6] = VB[pixdata & 3]; if (J & 0x02) C[6] = READPAL(VB | (pixdata & 3));
pixdata >>= 4; pixdata >>= 4;
if (J & 0x01) C[7] = VB[pixdata]; if (J & 0x01) C[7] = READPAL(VB | pixdata);
} }
} }
} }
@ -1640,10 +1701,12 @@ void FCEUPPU_SetVideoSystem(int w) {
scanlines_per_frame = dendy ? 262: 312; scanlines_per_frame = dendy ? 262: 312;
FSettings.FirstSLine = FSettings.UsrFirstSLine[1]; FSettings.FirstSLine = FSettings.UsrFirstSLine[1];
FSettings.LastSLine = FSettings.UsrLastSLine[1]; FSettings.LastSLine = FSettings.UsrLastSLine[1];
//paldeemphswap = 1; // dendy has pal ppu, and pal ppu has these swapped
} else { } else {
scanlines_per_frame = 262; scanlines_per_frame = 262;
FSettings.FirstSLine = FSettings.UsrFirstSLine[0]; FSettings.FirstSLine = FSettings.UsrFirstSLine[0];
FSettings.LastSLine = FSettings.UsrLastSLine[0]; FSettings.LastSLine = FSettings.UsrLastSLine[0];
//paldeemphswap = 0;
} }
} }
@ -1666,8 +1729,7 @@ void FCEUPPU_Reset(void) {
kook = 0; kook = 0;
idleSynch = 1; idleSynch = 1;
ppur.reset(); new_ppu_reset = true; // delay reset of ppur/spr_read until it's ready to start a new frame
spr_read.reset();
} }
void FCEUPPU_Power(void) { void FCEUPPU_Power(void) {
@ -1729,6 +1791,13 @@ int FCEUPPU_Loop(int skip) {
TriggerNMI(); TriggerNMI();
} }
X6502_Run((scanlines_per_frame - 242) * (256 + 85) - 12); X6502_Run((scanlines_per_frame - 242) * (256 + 85) - 12);
if (overclock_enabled && vblankscanlines) {
if (!DMC_7bit || !skip_7bit_overclocking) {
overclocking = 1;
X6502_Run(vblankscanlines * (256 + 85) - 12);
overclocking = 0;
}
}
PPU_status &= 0x1f; PPU_status &= 0x1f;
X6502_Run(256); X6502_Run(256);
@ -1759,7 +1828,7 @@ int FCEUPPU_Loop(int skip) {
kook ^= 1; kook ^= 1;
} }
if (GameInfo->type == GIT_NSF) if (GameInfo->type == GIT_NSF)
X6502_Run((256 + 85) * (dendy ? 290 : 240)); X6502_Run((256 + 85) * normalscanlines);
#ifdef FRAMESKIP #ifdef FRAMESKIP
else if (skip) { else if (skip) {
int y; int y;
@ -1785,24 +1854,42 @@ int FCEUPPU_Loop(int skip) {
} }
#endif #endif
else { else {
int x, max, maxref;
deemp = PPU[1] >> 5; deemp = PPU[1] >> 5;
for (scanline = 0; scanline < (dendy ? 290 : 240); ) { //scanline is incremented in DoLine. Evil. :/
// manual samples can't play correctly with overclocking
if (DMC_7bit && skip_7bit_overclocking) // 7bit sample started before 240th line
totalscanlines = normalscanlines;
else
totalscanlines = normalscanlines + (overclock_enabled ? postrenderscanlines : 0);
for (scanline = 0; scanline < totalscanlines; ) { //scanline is incremented in DoLine. Evil. :/
deempcnt[deemp]++; deempcnt[deemp]++;
if (scanline < 240) if (scanline < 240)
DEBUG(FCEUD_UpdatePPUView(scanline, 1)); DEBUG(FCEUD_UpdatePPUView(scanline, 1));
DoLine(); DoLine();
if (scanline < normalscanlines || scanline == totalscanlines)
overclocking = 0;
else {
if (DMC_7bit && skip_7bit_overclocking) // 7bit sample started after 240th line
break;
overclocking = 1;
}
} }
DMC_7bit = 0;
if (MMC5Hack) MMC5_hb(scanline); if (MMC5Hack) MMC5_hb(scanline);
for (x = 1, max = 0, maxref = 0; x < 7; x++) {
//deemph nonsense, kept for complicated reasons (see SetNESDeemph_OldHacky implementation)
int maxref = 0;
for (int x = 1, max = 0; x < 7; x++) {
if (deempcnt[x] > max) { if (deempcnt[x] > max) {
max = deempcnt[x]; max = deempcnt[x];
maxref = x; maxref = x;
} }
deempcnt[x] = 0; deempcnt[x] = 0;
} }
SetNESDeemph(maxref, 0); SetNESDeemph_OldHacky(maxref, 0);
} }
} //else... to if(ppudead) } //else... to if(ppudead)
@ -1902,7 +1989,10 @@ const int kFetchTime = 2;
void runppu(int x) { void runppu(int x) {
ppur.status.cycle = (ppur.status.cycle + x) % ppur.status.end_cycle; ppur.status.cycle = (ppur.status.cycle + x) % ppur.status.end_cycle;
X6502_Run(x); if (!new_ppu_reset) // if resetting, suspend CPU until the first frame
{
X6502_Run(x);
}
} }
//todo - consider making this a 3 or 4 slot fifo to keep from touching so much memory //todo - consider making this a 3 or 4 slot fifo to keep from touching so much memory
@ -1911,7 +2001,7 @@ struct BGData {
uint8 nt, pecnt, at, pt[2]; uint8 nt, pecnt, at, pt[2];
INLINE void Read() { INLINE void Read() {
RefreshAddr = ppur.get_ntread(); NTRefreshAddr = RefreshAddr = ppur.get_ntread();
if (PEC586Hack) if (PEC586Hack)
ppur.s = (RefreshAddr & 0x200) >> 9; ppur.s = (RefreshAddr & 0x200) >> 9;
pecnt = (RefreshAddr & 1) << 3; pecnt = (RefreshAddr & 1) << 3;
@ -1973,6 +2063,14 @@ static inline int PaletteAdjustPixel(int pixel) {
int framectr = 0; int framectr = 0;
int FCEUX_PPU_Loop(int skip) { int FCEUX_PPU_Loop(int skip) {
if (new_ppu_reset) // first frame since reset, time to initialize
{
ppur.reset();
spr_read.reset();
new_ppu_reset = false;
}
//262 scanlines //262 scanlines
if (ppudead) { if (ppudead) {
// not quite emulating all the NES power up behavior // not quite emulating all the NES power up behavior
@ -2003,12 +2101,20 @@ int FCEUX_PPU_Loop(int skip) {
ppur.status.sl = 241; //for sprite reads ppur.status.sl = 241; //for sprite reads
runppu(delay); //X6502_Run(12); //formerly: runppu(delay);
for(int dot=0;dot<delay;dot++)
runppu(1);
if (VBlankON) TriggerNMI(); if (VBlankON) TriggerNMI();
if (PAL) int sltodo = PAL?70:20;
runppu(70 * (kLineTime) - delay);
else //formerly: runppu(20 * (kLineTime) - delay);
runppu(20 * (kLineTime) - delay); for(int S=0;S<sltodo;S++)
{
for(int dot=(S==0?delay:0);dot<kLineTime;dot++)
runppu(1);
ppur.status.sl++;
}
//this seems to run just before the dummy scanline begins //this seems to run just before the dummy scanline begins
PPU_status = 0; PPU_status = 0;
@ -2032,7 +2138,8 @@ int FCEUX_PPU_Loop(int skip) {
//capture the initial xscroll //capture the initial xscroll
//int xscroll = ppur.fh; //int xscroll = ppur.fh;
//render 241/291 scanlines (1 dummy at beginning, dendy's 50 at the end) //render 241/291 scanlines (1 dummy at beginning, dendy's 50 at the end)
for (int sl = 0; sl < (dendy ? 291 : 241); sl++) { //ignore overclocking!
for (int sl = 0; sl < normalscanlines; sl++) {
spr_read.start_scanline(); spr_read.start_scanline();
g_rasterpos = 0; g_rasterpos = 0;
@ -2048,7 +2155,10 @@ int FCEUX_PPU_Loop(int skip) {
DEBUG(FCEUD_UpdateNTView(scanline = yp, 1)); DEBUG(FCEUD_UpdateNTView(scanline = yp, 1));
} }
if (MMC5Hack) MMC5_hb(yp); //hack to fix SDF ship intro screen with split. is it right?
//well, if we didnt do this, we'd be passing in a negative scanline, so that's a sign something is fishy..
if(sl != 0)
if (MMC5Hack) MMC5_hb(yp);
//twiddle the oam buffers //twiddle the oam buffers
@ -2064,18 +2174,22 @@ int FCEUX_PPU_Loop(int skip) {
for (int xt = 0; xt < 32; xt++) { for (int xt = 0; xt < 32; xt++) {
bgdata.main[xt + 2].Read(); bgdata.main[xt + 2].Read();
const uint8 blank = (gNoBGFillColor == 0xFF) ? READPAL(0) : gNoBGFillColor;
//ok, we're also going to draw here. //ok, we're also going to draw here.
//unless we're on the first dummy scanline //unless we're on the first dummy scanline
if (sl != 0 && sl < 241) { // cape at 240 for dendy, its PPU does nothing afterwards if (sl != 0 && sl < 241) { // cape at 240 for dendy, its PPU does nothing afterwards
int xstart = xt << 3; int xstart = xt << 3;
oamcount = oamcounts[renderslot]; oamcount = oamcounts[renderslot];
uint8 * const target = XBuf + (yp << 8) + xstart; uint8 * const target = XBuf + (yp << 8) + xstart;
uint8 * const dtarget = XDBuf + (yp << 8) + xstart;
uint8 *ptr = target; uint8 *ptr = target;
uint8 *dptr = dtarget;
int rasterpos = xstart; int rasterpos = xstart;
//check all the conditions that can cause things to render in these 8px //check all the conditions that can cause things to render in these 8px
const bool renderspritenow = SpriteON && rendersprites && (xt > 0 || SpriteLeft8); const bool renderspritenow = SpriteON && (xt > 0 || SpriteLeft8);
const bool renderbgnow = ScreenON && renderbg && (xt > 0 || BGLeft8); const bool renderbgnow = ScreenON && (xt > 0 || BGLeft8);
for (int xp = 0; xp < 8; xp++, rasterpos++, g_rasterpos++) { for (int xp = 0; xp < 8; xp++, rasterpos++, g_rasterpos++) {
//bg pos is different from raster pos due to its offsetability. //bg pos is different from raster pos due to its offsetability.
//so adjust for that here //so adjust for that here
@ -2083,14 +2197,28 @@ int FCEUX_PPU_Loop(int skip) {
const int bgpx = bgpos & 7; const int bgpx = bgpos & 7;
const int bgtile = bgpos >> 3; const int bgtile = bgpos >> 3;
uint8 pixel = 0, pixelcolor; uint8 pixel = 0;
uint8 pixelcolor = blank;
//according to qeed's doc, use palette 0 or $2006's value if it is & 0x3Fxx
if (!ScreenON && !SpriteON)
{
// if there's anything wrong with how we're doing this, someone please chime in
int addr = ppur.get_2007access();
if ((addr & 0x3F00) == 0x3F00)
{
pixel = addr & 0x1F;
}
pixelcolor = PALRAM[pixel];
}
//generate the BG data //generate the BG data
if (renderbgnow) { if (renderbgnow) {
uint8* pt = bgdata.main[bgtile].pt; uint8* pt = bgdata.main[bgtile].pt;
pixel = ((pt[0] >> (7 - bgpx)) & 1) | (((pt[1] >> (7 - bgpx)) & 1) << 1) | bgdata.main[bgtile].at; pixel = ((pt[0] >> (7 - bgpx)) & 1) | (((pt[1] >> (7 - bgpx)) & 1) << 1) | bgdata.main[bgtile].at;
} }
pixelcolor = PALRAM[pixel]; if (renderbg)
pixelcolor = READPAL(pixel);
//look for a sprite to be drawn //look for a sprite to be drawn
bool havepixel = false; bool havepixel = false;
@ -2133,11 +2261,14 @@ int FCEUX_PPU_Loop(int skip) {
//bring in the palette bits and palettize //bring in the palette bits and palettize
spixel |= (oam[2] & 3) << 2; spixel |= (oam[2] & 3) << 2;
pixelcolor = PALRAM[0x10 + spixel];
if (rendersprites)
pixelcolor = READPAL(0x10 + spixel);
} }
} }
*ptr++ = PaletteAdjustPixel(pixelcolor); *ptr++ = PaletteAdjustPixel(pixelcolor);
*dptr++= PPU[1]>>5; //grab deemph
} }
} }
} }
@ -2264,6 +2395,14 @@ int FCEUX_PPU_Loop(int skip) {
} }
} }
//blind attempt to replicate old ppu functionality
if(s == 2 && PPUON)
{
if (GameHBIRQHook2) {
GameHBIRQHook2();
}
}
if (realSprite) runppu(kFetchTime); if (realSprite) runppu(kFetchTime);
@ -2318,6 +2457,8 @@ int FCEUX_PPU_Loop(int skip) {
runppu(1); runppu(1);
} //scanline loop } //scanline loop
DMC_7bit = 0;
if (MMC5Hack) MMC5_hb(240); if (MMC5Hack) MMC5_hb(240);
//idle for one line //idle for one line

View File

@ -9,6 +9,10 @@ void FCEUPPU_SetVideoSystem(int w);
extern void (*PPU_hook)(uint32 A); extern void (*PPU_hook)(uint32 A);
extern void (*GameHBIRQHook)(void), (*GameHBIRQHook2)(void); extern void (*GameHBIRQHook)(void), (*GameHBIRQHook2)(void);
int newppu_get_scanline();
int newppu_get_dot();
void newppu_hacky_emergency_reset();
/* For cart.c and banksw.h, mostly */ /* For cart.c and banksw.h, mostly */
extern uint8 NTARAM[0x800], *vnapage[4]; extern uint8 NTARAM[0x800], *vnapage[4];
extern uint8 PPUNTARAM; extern uint8 PPUNTARAM;
@ -18,10 +22,10 @@ void FCEUPPU_SaveState(void);
void FCEUPPU_LoadState(int version); void FCEUPPU_LoadState(int version);
uint32 FCEUPPU_PeekAddress(); uint32 FCEUPPU_PeekAddress();
uint8* FCEUPPU_GetCHR(uint32 vadr, uint32 refreshaddr); uint8* FCEUPPU_GetCHR(uint32 vadr, uint32 refreshaddr);
int FCEUPPU_GetAttr(int ntnum, int xt, int yt);
void ppu_getScroll(int &xpos, int &ypos); void ppu_getScroll(int &xpos, int &ypos);
#ifdef _MSC_VER #ifdef _MSC_VER
#define FASTCALL __fastcall #define FASTCALL __fastcall
#else #else
@ -34,9 +38,10 @@ extern void (*FFCEUX_PPUWrite)(uint32 A, uint8 V);
extern uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A); extern uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A);
void FFCEUX_PPUWrite_Default(uint32 A, uint8 V); void FFCEUX_PPUWrite_Default(uint32 A, uint8 V);
extern int scanline;
extern int g_rasterpos; extern int g_rasterpos;
extern uint8 PPU[4]; extern uint8 PPU[4];
extern bool DMC_7bit;
extern bool paldeemphswap;
enum PPUPHASE { enum PPUPHASE {
PPUPHASE_VBL, PPUPHASE_BG, PPUPHASE_OBJ PPUPHASE_VBL, PPUPHASE_BG, PPUPHASE_OBJ

View File

@ -89,21 +89,21 @@ pshift[1] <<= 8;
#ifdef PPU_BGFETCH #ifdef PPU_BGFETCH
if (RefreshAddr & 1) { if (RefreshAddr & 1) {
if(ScreenON) if(ScreenON)
RENDER_LOG(vadr + 8); RENDER_LOGP(C + 8);
pshift[0] |= C[8]; pshift[0] |= C[8];
pshift[1] |= C[8]; pshift[1] |= C[8];
} else { } else {
if(ScreenON) if(ScreenON)
RENDER_LOG(vadr); RENDER_LOGP(C);
pshift[0] |= C[0]; pshift[0] |= C[0];
pshift[1] |= C[0]; pshift[1] |= C[0];
} }
#else #else
if(ScreenON) if(ScreenON)
RENDER_LOG(vadr); RENDER_LOGP(C);
pshift[0] |= C[0]; pshift[0] |= C[0];
if(ScreenON) if(ScreenON)
RENDER_LOG(vadr + 8); RENDER_LOGP(C + 8);
pshift[1] |= C[8]; pshift[1] |= C[8];
#endif #endif

View File

@ -58,6 +58,7 @@ uint8 EnabledChannels=0; // $4015 / Sound channels enable and status
uint8 IRQFrameMode=0; // $4017 / Frame counter control / xx000000 uint8 IRQFrameMode=0; // $4017 / Frame counter control / xx000000
uint8 InitialRawDALatch=0; // used only for lua uint8 InitialRawDALatch=0; // used only for lua
bool DMC_7bit = 0; // used to skip overclocking
ENVUNIT EnvUnits[3]; ENVUNIT EnvUnits[3];
static const int RectDuties[4]={1,2,4,6}; static const int RectDuties[4]={1,2,4,6};
@ -90,19 +91,18 @@ static const uint8 lengthtable[0x20]=
}; };
static const uint32 NoiseFreqTableNTSC[0x10] = extern const uint32 NoiseFreqTableNTSC[0x10] =
{ {
4, 8, 16, 32, 64, 96, 128, 160, 202, 4, 8, 16, 32, 64, 96, 128, 160, 202,
254, 380, 508, 762, 1016, 2034, 4068 254, 380, 508, 762, 1016, 2034, 4068
}; };
static const uint32 NoiseFreqTablePAL[0x10] = extern const uint32 NoiseFreqTablePAL[0x10] =
{ {
4, 7, 14, 30, 60, 88, 118, 148, 188, 4, 7, 14, 30, 60, 88, 118, 148, 188,
236, 354, 472, 708, 944, 1890, 3778 236, 354, 472, 708, 944, 1890, 3778
}; };
const uint32 *NoiseFreqTable = NoiseFreqTableNTSC; // for lua only
static const uint32 NTSCDMCTable[0x10]= static const uint32 NTSCDMCTable[0x10]=
{ {
@ -233,10 +233,8 @@ static DECLFW(Write_PSG)
DoSQ1(); DoSQ1();
EnvUnits[0].Mode=(V&0x30)>>4; EnvUnits[0].Mode=(V&0x30)>>4;
EnvUnits[0].Speed=(V&0xF); EnvUnits[0].Speed=(V&0xF);
#ifdef WIN32
if (swapDuty) if (swapDuty)
V = (V&0x3F)|((V&0x80)>>1)|((V&0x40)<<1); V = (V&0x3F)|((V&0x80)>>1)|((V&0x40)<<1);
#endif
break; break;
case 0x1: case 0x1:
sweepon[0]=V&0x80; sweepon[0]=V&0x80;
@ -253,10 +251,8 @@ static DECLFW(Write_PSG)
DoSQ2(); DoSQ2();
EnvUnits[1].Mode=(V&0x30)>>4; EnvUnits[1].Mode=(V&0x30)>>4;
EnvUnits[1].Speed=(V&0xF); EnvUnits[1].Speed=(V&0xF);
#ifdef WIN32
if (swapDuty) if (swapDuty)
V = (V&0x3F)|((V&0x80)>>1)|((V&0x40)<<1); V = (V&0x3F)|((V&0x80)>>1)|((V&0x40)<<1);
#endif
break; break;
case 0x5: case 0x5:
sweepon[1]=V&0x80; sweepon[1]=V&0x80;
@ -311,58 +307,69 @@ static DECLFW(Write_PSG)
static DECLFW(Write_DMCRegs) static DECLFW(Write_DMCRegs)
{ {
A&=0xF; A&=0xF;
switch(A) switch(A)
{ {
case 0x00:DoPCM(); case 0x00:
LoadDMCPeriod(V&0xF); DoPCM();
LoadDMCPeriod(V&0xF);
if(SIRQStat&0x80)
{ if(SIRQStat&0x80)
if(!(V&0x80)) {
{ if(!(V&0x80))
X6502_IRQEnd(FCEU_IQDPCM); {
SIRQStat&=~0x80; X6502_IRQEnd(FCEU_IQDPCM);
} SIRQStat&=~0x80;
else X6502_IRQBegin(FCEU_IQDPCM); }
} else X6502_IRQBegin(FCEU_IQDPCM);
DMCFormat=V; }
break; DMCFormat=V;
case 0x01:DoPCM(); break;
InitialRawDALatch=V&0x7F; case 0x01:
RawDALatch=InitialRawDALatch; DoPCM();
break; InitialRawDALatch=V&0x7F;
case 0x02:DMCAddressLatch=V;break; RawDALatch=InitialRawDALatch;
case 0x03:DMCSizeLatch=V;break; if (RawDALatch)
} DMC_7bit = 1;
break;
case 0x02:
DMCAddressLatch=V;
if (V)
DMC_7bit = 0;
break;
case 0x03:
DMCSizeLatch=V;
if (V)
DMC_7bit = 0;
break;
}
} }
static DECLFW(StatusWrite) static DECLFW(StatusWrite)
{ {
int x; int x;
DoSQ1(); DoSQ1();
DoSQ2(); DoSQ2();
DoTriangle(); DoTriangle();
DoNoise(); DoNoise();
DoPCM(); DoPCM();
for(x=0;x<4;x++)
if(!(V&(1<<x))) lengthcount[x]=0; /* Force length counters to 0. */
if(V&0x10) for(x=0;x<4;x++)
{ if(!(V&(1<<x))) lengthcount[x]=0; /* Force length counters to 0. */
if(!DMCSize)
PrepDPCM(); if(V&0x10)
} {
if(!DMCSize)
PrepDPCM();
}
else else
{ {
DMCSize=0; DMCSize=0;
} }
SIRQStat&=~0x80; SIRQStat&=~0x80;
X6502_IRQEnd(FCEU_IQDPCM); X6502_IRQEnd(FCEU_IQDPCM);
EnabledChannels=V&0x1F; EnabledChannels=V&0x1F;
} }
@ -552,7 +559,7 @@ static INLINE void DMCDMA(void)
void FCEU_SoundCPUHook(int cycles) void FCEU_SoundCPUHook(int cycles)
{ {
fhcnt-=cycles*48; fhcnt-=cycles*48;
if(fhcnt<=0) if(fhcnt<=0)
{ {
FrameSoundUpdate(); FrameSoundUpdate();
@ -1045,7 +1052,7 @@ int FlushEmulateSound(void)
int x; int x;
int32 end,left; int32 end,left;
if(!timestamp) return(0); if(!soundtimestamp) return(0);
if(!FSettings.SndRate) if(!FSettings.SndRate)
{ {
@ -1066,7 +1073,7 @@ int FlushEmulateSound(void)
if(GameExpSound.HiFill) GameExpSound.HiFill(); if(GameExpSound.HiFill) GameExpSound.HiFill();
for(x=timestamp;x;x--) for(x=soundtimestamp;x;x--)
{ {
uint32 b=*tmpo; uint32 b=*tmpo;
*tmpo=(b&65535)+wlookup2[(b>>16)&255]+wlookup1[b>>24]; *tmpo=(b&65535)+wlookup2[(b>>16)&255]+wlookup1[b>>24];

View File

@ -59,7 +59,7 @@ extern unsigned char *cdloggerdata;
extern uint32 soundtsoffs; extern uint32 soundtsoffs;
extern bool swapDuty; extern bool swapDuty;
#define SOUNDTS (timestamp + soundtsoffs) #define SOUNDTS (soundtimestamp + soundtsoffs)
void SetNESSoundMap(void); void SetNESSoundMap(void);
void FrameSoundUpdate(void); void FrameSoundUpdate(void);

View File

@ -974,8 +974,12 @@ void FCEUI_LoadState(const char *fname, bool display_message)
loadStateFailed = 1; loadStateFailed = 1;
return; // state doesn't exist; exit cleanly return; // state doesn't exist; exit cleanly
} }
if (FCEUSS_Load(fname, display_message)) if (FCEUSS_Load(fname, display_message))
{ {
//in case we're loading a savestate made with old ppu, we need to make sure ppur's regs used for dividing are ready to go
newppu_hacky_emergency_reset();
//mbg todo netplay //mbg todo netplay
#if 0 #if 0
if(FCEUnetplay) if(FCEUnetplay)

View File

@ -1,458 +1,458 @@
/* Copyright (C) 2005 Guillaume Duhamel /* Copyright (C) 2005 Guillaume Duhamel
Copyright (C) 2008-2009 DeSmuME team Copyright (C) 2008-2009 DeSmuME team
This file is part of DeSmuME This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
DeSmuME is distributed in the hope that it will be useful, DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef TYPES_HPP #ifndef TYPES_HPP
#define TYPES_HPP #define TYPES_HPP
//analyze microsoft compilers //analyze microsoft compilers
#ifdef _MSC_VER #ifdef _MSC_VER
#ifdef _XBOX #ifdef _XBOX
//#define _XBOX //already defined //#define _XBOX //already defined
#else #else
#define _WINDOWS #define _WINDOWS
#ifdef _M_X64 #ifdef _M_X64
//#define _WIN64 //already defined in x64 compiler //#define _WIN64 //already defined in x64 compiler
#else #else
//#define _WIN32 //already defined //#define _WIN32 //already defined
#endif #endif
#endif #endif
#endif #endif
//todo - everyone will want to support this eventually, i suppose //todo - everyone will want to support this eventually, i suppose
#ifdef _WINDOWS #ifdef _WINDOWS
#include "config.h" #include "config.h"
#endif #endif
//xbox needs to include this to resemble windows //xbox needs to include this to resemble windows
#ifdef _XBOX #ifdef _XBOX
#include <xtl.h> #include <xtl.h>
#include <io.h> #include <io.h>
#endif #endif
#ifdef DEVELOPER #ifdef DEVELOPER
#define IF_DEVELOPER(X) X #define IF_DEVELOPER(X) X
#else #else
#define IF_DEVELOPER(X) #define IF_DEVELOPER(X)
#endif #endif
#ifdef _WINDOWS #ifdef _WINDOWS
//#define HAVE_WX //not useful yet.... //#define HAVE_WX //not useful yet....
#define HAVE_LIBAGG #define HAVE_LIBAGG
#define ENABLE_SSE #define ENABLE_SSE
#define ENABLE_SSE2 #define ENABLE_SSE2
#ifdef DEVELOPER #ifdef DEVELOPER
#define HAVE_LUA #define HAVE_LUA
#endif #endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
#ifdef __SSE__ #ifdef __SSE__
#define ENABLE_SSE #define ENABLE_SSE
#endif #endif
#ifdef __SSE2__ #ifdef __SSE2__
#define ENABLE_SSE2 #define ENABLE_SSE2
#endif #endif
#endif #endif
#ifdef NOSSE #ifdef NOSSE
#undef ENABLE_SSE #undef ENABLE_SSE
#endif #endif
#ifdef NOSSE2 #ifdef NOSSE2
#undef ENABLE_SSE2 #undef ENABLE_SSE2
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
#define strcasecmp(x,y) _stricmp(x,y) #define strcasecmp(x,y) _stricmp(x,y)
#define snprintf _snprintf #define snprintf _snprintf
#else #else
#define WINAPI #define WINAPI
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
#include <limits.h> #include <limits.h>
#ifndef PATH_MAX #ifndef PATH_MAX
#define MAX_PATH 1024 #define MAX_PATH 1024
#else #else
#define MAX_PATH PATH_MAX #define MAX_PATH PATH_MAX
#endif #endif
#endif #endif
#ifdef _XBOX #ifdef _XBOX
#define MAX_PATH 1024 #define MAX_PATH 1024
#define PATH_MAX 1024 #define PATH_MAX 1024
#endif #endif
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) #if defined(_MSC_VER) || defined(__INTEL_COMPILER)
#define ALIGN(X) __declspec(align(X)) #define ALIGN(X) __declspec(align(X))
#elif __GNUC__ #elif __GNUC__
#define ALIGN(X) __attribute__ ((aligned (X))) #define ALIGN(X) __attribute__ ((aligned (X)))
#else #else
#define ALIGN(X) #define ALIGN(X)
#endif #endif
#define CACHE_ALIGN ALIGN(32) #define CACHE_ALIGN ALIGN(32)
//use this for example when you want a byte value to be better-aligned //use this for example when you want a byte value to be better-aligned
#define FAST_ALIGN ALIGN(4) #define FAST_ALIGN ALIGN(4)
#ifndef FASTCALL #ifndef FASTCALL
#ifdef __MINGW32__ #ifdef __MINGW32__
#define FASTCALL __attribute__((fastcall)) #define FASTCALL __attribute__((fastcall))
#elif defined (__i386__) && !defined(__clang__) #elif defined (__i386__) && !defined(__clang__)
#define FASTCALL __attribute__((regparm(3))) #define FASTCALL __attribute__((regparm(3)))
#elif defined(_MSC_VER) || defined(__INTEL_COMPILER) #elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
#define FASTCALL #define FASTCALL
#else #else
#define FASTCALL #define FASTCALL
#endif #endif
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
#define _CDECL_ __cdecl #define _CDECL_ __cdecl
#else #else
#define _CDECL_ #define _CDECL_
#endif #endif
#ifndef INLINE #ifndef INLINE
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) #if defined(_MSC_VER) || defined(__INTEL_COMPILER)
#define INLINE _inline #define INLINE _inline
#else #else
#define INLINE inline #define INLINE inline
#endif #endif
#endif #endif
#ifndef FORCEINLINE #ifndef FORCEINLINE
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) #if defined(_MSC_VER) || defined(__INTEL_COMPILER)
#define FORCEINLINE __forceinline #define FORCEINLINE __forceinline
#define MSC_FORCEINLINE __forceinline #define MSC_FORCEINLINE __forceinline
#else #else
#define FORCEINLINE inline __attribute__((always_inline)) #define FORCEINLINE inline __attribute__((always_inline))
#define MSC_FORCEINLINE #define MSC_FORCEINLINE
#endif #endif
#endif #endif
#if defined(__LP64__) #if defined(__LP64__)
typedef unsigned char u8; typedef unsigned char u8;
typedef unsigned short u16; typedef unsigned short u16;
typedef unsigned int u32; typedef unsigned int u32;
typedef unsigned long long u64; typedef unsigned long long u64;
typedef signed char s8; typedef signed char s8;
typedef signed short s16; typedef signed short s16;
typedef signed int s32; typedef signed int s32;
typedef signed long long s64; typedef signed long long s64;
#else #else
typedef unsigned char u8; typedef unsigned char u8;
typedef unsigned short u16; typedef unsigned short u16;
typedef unsigned int u32; typedef unsigned int u32;
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) #if defined(_MSC_VER) || defined(__INTEL_COMPILER)
typedef unsigned __int64 u64; typedef unsigned __int64 u64;
#else #else
typedef unsigned long long u64; typedef unsigned long long u64;
#endif #endif
typedef signed char s8; typedef signed char s8;
typedef signed short s16; typedef signed short s16;
typedef signed int s32; typedef signed int s32;
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) #if defined(_MSC_VER) || defined(__INTEL_COMPILER)
typedef __int64 s64; typedef __int64 s64;
#else #else
typedef signed long long s64; typedef signed long long s64;
#endif #endif
#endif #endif
typedef u8 uint8; typedef u8 uint8;
typedef u16 uint16; typedef u16 uint16;
#ifndef OBJ_C #ifndef OBJ_C
typedef u32 uint32; typedef u32 uint32;
#else #else
#define uint32 u32 //uint32 is defined in Leopard somewhere, avoid conflicts #define uint32 u32 //uint32 is defined in Leopard somewhere, avoid conflicts
#endif #endif
/*---------- GPU3D fixed-points types -----------*/ /*---------- GPU3D fixed-points types -----------*/
typedef s32 f32; typedef s32 f32;
#define inttof32(n) ((n) << 12) #define inttof32(n) ((n) << 12)
#define f32toint(n) ((n) >> 12) #define f32toint(n) ((n) >> 12)
#define floattof32(n) ((int32)((n) * (1 << 12))) #define floattof32(n) ((int32)((n) * (1 << 12)))
#define f32tofloat(n) (((float)(n)) / (float)(1<<12)) #define f32tofloat(n) (((float)(n)) / (float)(1<<12))
typedef s16 t16; typedef s16 t16;
#define f32tot16(n) ((t16)(n >> 8)) #define f32tot16(n) ((t16)(n >> 8))
#define inttot16(n) ((n) << 4) #define inttot16(n) ((n) << 4)
#define t16toint(n) ((n) >> 4) #define t16toint(n) ((n) >> 4)
#define floattot16(n) ((t16)((n) * (1 << 4))) #define floattot16(n) ((t16)((n) * (1 << 4)))
#define t16ofloat(n) (((float)(n)) / (float)(1<<4)) #define t16ofloat(n) (((float)(n)) / (float)(1<<4))
typedef s16 v16; typedef s16 v16;
#define inttov16(n) ((n) << 12) #define inttov16(n) ((n) << 12)
#define f32tov16(n) (n) #define f32tov16(n) (n)
#define floattov16(n) ((v16)((n) * (1 << 12))) #define floattov16(n) ((v16)((n) * (1 << 12)))
#define v16toint(n) ((n) >> 12) #define v16toint(n) ((n) >> 12)
#define v16tofloat(n) (((float)(n)) / (float)(1<<12)) #define v16tofloat(n) (((float)(n)) / (float)(1<<12))
typedef s16 v10; typedef s16 v10;
#define inttov10(n) ((n) << 9) #define inttov10(n) ((n) << 9)
#define f32tov10(n) ((v10)(n >> 3)) #define f32tov10(n) ((v10)(n >> 3))
#define v10toint(n) ((n) >> 9) #define v10toint(n) ((n) >> 9)
#define floattov10(n) ((v10)((n) * (1 << 9))) #define floattov10(n) ((v10)((n) * (1 << 9)))
#define v10tofloat(n) (((float)(n)) / (float)(1<<9)) #define v10tofloat(n) (((float)(n)) / (float)(1<<9))
/*----------------------*/ /*----------------------*/
#ifndef OBJ_C #ifndef OBJ_C
typedef int BOOL; typedef int BOOL;
#else #else
//apple also defines BOOL //apple also defines BOOL
typedef int desmume_BOOL; typedef int desmume_BOOL;
#define BOOL desmume_BOOL #define BOOL desmume_BOOL
#endif #endif
#ifndef TRUE #ifndef TRUE
#define TRUE 1 #define TRUE 1
#endif #endif
#ifndef FALSE #ifndef FALSE
#define FALSE 0 #define FALSE 0
#endif #endif
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
#ifndef WORDS_BIGENDIAN #ifndef WORDS_BIGENDIAN
#define WORDS_BIGENDIAN #define WORDS_BIGENDIAN
#endif #endif
#endif #endif
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
# define LOCAL_BE # define LOCAL_BE
#else #else
# define LOCAL_LE # define LOCAL_LE
#endif #endif
/* little endian (ds' endianess) to local endianess convert macros */ /* little endian (ds' endianess) to local endianess convert macros */
#ifdef LOCAL_BE /* local arch is big endian */ #ifdef LOCAL_BE /* local arch is big endian */
# define LE_TO_LOCAL_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff)) # 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_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 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_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_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)) # 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 */ #else /* local arch is little endian */
# define LE_TO_LOCAL_16(x) (x) # define LE_TO_LOCAL_16(x) (x)
# define LE_TO_LOCAL_32(x) (x) # define LE_TO_LOCAL_32(x) (x)
# define LE_TO_LOCAL_64(x) (x) # define LE_TO_LOCAL_64(x) (x)
# define LOCAL_TO_LE_16(x) (x) # define LOCAL_TO_LE_16(x) (x)
# define LOCAL_TO_LE_32(x) (x) # define LOCAL_TO_LE_32(x) (x)
# define LOCAL_TO_LE_64(x) (x) # define LOCAL_TO_LE_64(x) (x)
#endif #endif
// kilobytes and megabytes macro // kilobytes and megabytes macro
#define MB(x) ((x)*1024*1024) #define MB(x) ((x)*1024*1024)
#define KB(x) ((x)*1024) #define KB(x) ((x)*1024)
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define CPU_STR(c) ((c==ARM9)?"ARM9":"ARM7") #define CPU_STR(c) ((c==ARM9)?"ARM9":"ARM7")
typedef enum typedef enum
{ {
ARM9 = 0, ARM9 = 0,
ARM7 = 1 ARM7 = 1
} cpu_id_t; } cpu_id_t;
///endian-flips count bytes. count should be even and nonzero. ///endian-flips count bytes. count should be even and nonzero.
inline void FlipByteOrder(u8 *src, u32 count) inline void FlipByteOrder(u8 *src, u32 count)
{ {
u8 *start=src; u8 *start=src;
u8 *end=src+count-1; u8 *end=src+count-1;
if((count&1) || !count) return; /* This shouldn't happen. */ if((count&1) || !count) return; /* This shouldn't happen. */
while(count--) while(count--)
{ {
u8 tmp; u8 tmp;
tmp=*end; tmp=*end;
*end=*start; *end=*start;
*start=tmp; *start=tmp;
end--; end--;
start++; start++;
} }
} }
inline u64 double_to_u64(double d) { inline u64 double_to_u64(double d) {
union { union {
u64 a; u64 a;
double b; double b;
} fuxor; } fuxor;
fuxor.b = d; fuxor.b = d;
return fuxor.a; return fuxor.a;
} }
inline double u64_to_double(u64 u) { inline double u64_to_double(u64 u) {
union { union {
u64 a; u64 a;
double b; double b;
} fuxor; } fuxor;
fuxor.a = u; fuxor.a = u;
return fuxor.b; return fuxor.b;
} }
inline u32 float_to_u32(float f) { inline u32 float_to_u32(float f) {
union { union {
u32 a; u32 a;
float b; float b;
} fuxor; } fuxor;
fuxor.b = f; fuxor.b = f;
return fuxor.a; return fuxor.a;
} }
inline float u32_to_float(u32 u) { inline float u32_to_float(u32 u) {
union { union {
u32 a; u32 a;
float b; float b;
} fuxor; } fuxor;
fuxor.a = u; fuxor.a = u;
return fuxor.b; return fuxor.b;
} }
///stores a 32bit value into the provided byte array in guaranteed little endian form ///stores a 32bit value into the provided byte array in guaranteed little endian form
inline void en32lsb(u8 *buf, u32 morp) inline void en32lsb(u8 *buf, u32 morp)
{ {
buf[0]=(u8)(morp); buf[0]=(u8)(morp);
buf[1]=(u8)(morp>>8); buf[1]=(u8)(morp>>8);
buf[2]=(u8)(morp>>16); buf[2]=(u8)(morp>>16);
buf[3]=(u8)(morp>>24); buf[3]=(u8)(morp>>24);
} }
inline void en16lsb(u8* buf, u16 morp) inline void en16lsb(u8* buf, u16 morp)
{ {
buf[0]=(u8)morp; buf[0]=(u8)morp;
buf[1]=(u8)(morp>>8); buf[1]=(u8)(morp>>8);
} }
///unpacks a 64bit little endian value from the provided byte array into host byte order ///unpacks a 64bit little endian value from the provided byte array into host byte order
inline u64 de64lsb(u8 *morp) inline u64 de64lsb(u8 *morp)
{ {
return morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24)|((u64)morp[4]<<32)|((u64)morp[5]<<40)|((u64)morp[6]<<48)|((u64)morp[7]<<56); return morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24)|((u64)morp[4]<<32)|((u64)morp[5]<<40)|((u64)morp[6]<<48)|((u64)morp[7]<<56);
} }
///unpacks a 32bit little endian value from the provided byte array into host byte order ///unpacks a 32bit little endian value from the provided byte array into host byte order
inline u32 de32lsb(u8 *morp) inline u32 de32lsb(u8 *morp)
{ {
return morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24); return morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24);
} }
///unpacks a 16bit little endian value from the provided byte array into host byte order ///unpacks a 16bit little endian value from the provided byte array into host byte order
inline u16 de16lsb(u8 *morp) inline u16 de16lsb(u8 *morp)
{ {
return morp[0]|(morp[1]<<8); return morp[0]|(morp[1]<<8);
} }
#ifndef ARRAY_SIZE #ifndef ARRAY_SIZE
//taken from winnt.h //taken from winnt.h
extern "C++" // templates cannot be declared to have 'C' linkage extern "C++" // templates cannot be declared to have 'C' linkage
template <typename T, size_t N> template <typename T, size_t N>
char (*BLAHBLAHBLAH( UNALIGNED T (&)[N] ))[N]; char (*BLAHBLAHBLAH( UNALIGNED T (&)[N] ))[N];
#define ARRAY_SIZE(A) (sizeof(*BLAHBLAHBLAH(A))) #define ARRAY_SIZE(A) (sizeof(*BLAHBLAHBLAH(A)))
#endif #endif
//fairly standard for loop macros //fairly standard for loop macros
#define MACRODO1(TRICK,TODO) { const int X = TRICK; TODO; } #define MACRODO1(TRICK,TODO) { const int X = TRICK; TODO; }
#define MACRODO2(X,TODO) { MACRODO1((X),TODO) MACRODO1(((X)+1),TODO) } #define MACRODO2(X,TODO) { MACRODO1((X),TODO) MACRODO1(((X)+1),TODO) }
#define MACRODO4(X,TODO) { MACRODO2((X),TODO) MACRODO2(((X)+2),TODO) } #define MACRODO4(X,TODO) { MACRODO2((X),TODO) MACRODO2(((X)+2),TODO) }
#define MACRODO8(X,TODO) { MACRODO4((X),TODO) MACRODO4(((X)+4),TODO) } #define MACRODO8(X,TODO) { MACRODO4((X),TODO) MACRODO4(((X)+4),TODO) }
#define MACRODO16(X,TODO) { MACRODO8((X),TODO) MACRODO8(((X)+8),TODO) } #define MACRODO16(X,TODO) { MACRODO8((X),TODO) MACRODO8(((X)+8),TODO) }
#define MACRODO32(X,TODO) { MACRODO16((X),TODO) MACRODO16(((X)+16),TODO) } #define MACRODO32(X,TODO) { MACRODO16((X),TODO) MACRODO16(((X)+16),TODO) }
#define MACRODO64(X,TODO) { MACRODO32((X),TODO) MACRODO32(((X)+32),TODO) } #define MACRODO64(X,TODO) { MACRODO32((X),TODO) MACRODO32(((X)+32),TODO) }
#define MACRODO128(X,TODO) { MACRODO64((X),TODO) MACRODO64(((X)+64),TODO) } #define MACRODO128(X,TODO) { MACRODO64((X),TODO) MACRODO64(((X)+64),TODO) }
#define MACRODO256(X,TODO) { MACRODO128((X),TODO) MACRODO128(((X)+128),TODO) } #define MACRODO256(X,TODO) { MACRODO128((X),TODO) MACRODO128(((X)+128),TODO) }
//this one lets you loop any number of times (as long as N<256) //this one lets you loop any number of times (as long as N<256)
#define MACRODO_N(N,TODO) {\ #define MACRODO_N(N,TODO) {\
if((N)&0x100) MACRODO256(0,TODO); \ if((N)&0x100) MACRODO256(0,TODO); \
if((N)&0x080) MACRODO128((N)&(0x100),TODO); \ if((N)&0x080) MACRODO128((N)&(0x100),TODO); \
if((N)&0x040) MACRODO64((N)&(0x100|0x080),TODO); \ if((N)&0x040) MACRODO64((N)&(0x100|0x080),TODO); \
if((N)&0x020) MACRODO32((N)&(0x100|0x080|0x040),TODO); \ if((N)&0x020) MACRODO32((N)&(0x100|0x080|0x040),TODO); \
if((N)&0x010) MACRODO16((N)&(0x100|0x080|0x040|0x020),TODO); \ if((N)&0x010) MACRODO16((N)&(0x100|0x080|0x040|0x020),TODO); \
if((N)&0x008) MACRODO8((N)&(0x100|0x080|0x040|0x020|0x010),TODO); \ if((N)&0x008) MACRODO8((N)&(0x100|0x080|0x040|0x020|0x010),TODO); \
if((N)&0x004) MACRODO4((N)&(0x100|0x080|0x040|0x020|0x010|0x008),TODO); \ if((N)&0x004) MACRODO4((N)&(0x100|0x080|0x040|0x020|0x010|0x008),TODO); \
if((N)&0x002) MACRODO2((N)&(0x100|0x080|0x040|0x020|0x010|0x008|0x004),TODO); \ if((N)&0x002) MACRODO2((N)&(0x100|0x080|0x040|0x020|0x010|0x008|0x004),TODO); \
if((N)&0x001) MACRODO1((N)&(0x100|0x080|0x040|0x020|0x010|0x008|0x004|0x002),TODO); \ if((N)&0x001) MACRODO1((N)&(0x100|0x080|0x040|0x020|0x010|0x008|0x004|0x002),TODO); \
} }
//--------------------------- //---------------------------
//Binary constant generator macro By Tom Torfs - donated to the public domain //Binary constant generator macro By Tom Torfs - donated to the public domain
//turn a numeric literal into a hex constant //turn a numeric literal into a hex constant
//(avoids problems with leading zeroes) //(avoids problems with leading zeroes)
//8-bit constants max value 0x11111111, always fits in unsigned long //8-bit constants max value 0x11111111, always fits in unsigned long
#define HEX__(n) 0x##n##LU #define HEX__(n) 0x##n##LU
//8-bit conversion function //8-bit conversion function
#define B8__(x) ((x&0x0000000FLU)?1:0) \ #define B8__(x) ((x&0x0000000FLU)?1:0) \
+((x&0x000000F0LU)?2:0) \ +((x&0x000000F0LU)?2:0) \
+((x&0x00000F00LU)?4:0) \ +((x&0x00000F00LU)?4:0) \
+((x&0x0000F000LU)?8:0) \ +((x&0x0000F000LU)?8:0) \
+((x&0x000F0000LU)?16:0) \ +((x&0x000F0000LU)?16:0) \
+((x&0x00F00000LU)?32:0) \ +((x&0x00F00000LU)?32:0) \
+((x&0x0F000000LU)?64:0) \ +((x&0x0F000000LU)?64:0) \
+((x&0xF0000000LU)?128:0) +((x&0xF0000000LU)?128:0)
//for upto 8-bit binary constants //for upto 8-bit binary constants
#define B8(d) ((unsigned char)B8__(HEX__(d))) #define B8(d) ((unsigned char)B8__(HEX__(d)))
// for upto 16-bit binary constants, MSB first // for upto 16-bit binary constants, MSB first
#define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8) \ #define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8) \
+ B8(dlsb)) + B8(dlsb))
// for upto 32-bit binary constants, MSB first */ // for upto 32-bit binary constants, MSB first */
#define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24) \ #define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24) \
+ ((unsigned long)B8(db2)<<16) \ + ((unsigned long)B8(db2)<<16) \
+ ((unsigned long)B8(db3)<<8) \ + ((unsigned long)B8(db3)<<8) \
+ B8(dlsb)) + B8(dlsb))
//Sample usage: //Sample usage:
//B8(01010101) = 85 //B8(01010101) = 85
//B16(10101010,01010101) = 43605 //B16(10101010,01010101) = 43605
//B32(10000000,11111111,10101010,01010101) = 2164238933 //B32(10000000,11111111,10101010,01010101) = 2164238933
//--------------------------- //---------------------------
#ifndef CTASSERT #ifndef CTASSERT
#define CTASSERT(x) typedef char __assert ## y[(x) ? 1 : -1] #define CTASSERT(x) typedef char __assert ## y[(x) ? 1 : -1]
#endif #endif
static const char hexValid[23] = {"0123456789ABCDEFabcdef"}; static const char hexValid[23] = {"0123456789ABCDEFabcdef"};
template<typename T> inline void reconstruct(T* t) { template<typename T> inline void reconstruct(T* t) {
t->~T(); t->~T();
new(t) T(); new(t) T();
} }
#endif #endif

View File

@ -44,10 +44,9 @@ typedef signed short int16;
typedef signed int int32; typedef signed int int32;
#define dup _dup #define dup _dup
#define stat _stat #define stat _stat
#define fstat _fstat
#define mkdir _mkdir #define mkdir _mkdir
#define alloca _alloca #define alloca _alloca
#define snprintf _snprintf #define FCEUX_fstat _fstat
#if _MSC_VER < 1500 #if _MSC_VER < 1500
#define vsnprintf _vsnprintf #define vsnprintf _vsnprintf
#endif #endif
@ -74,6 +73,8 @@ typedef int32_t int32;
typedef uint8_t uint8; typedef uint8_t uint8;
typedef uint16_t uint16; typedef uint16_t uint16;
typedef uint32_t uint32; typedef uint32_t uint32;
#define FCEUX_fstat fstat
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__

View File

@ -118,6 +118,7 @@ static void MooMirroring(void) {
if (mirrortodo < 0x4) if (mirrortodo < 0x4)
SetupCartMirroring(mirrortodo, 1, 0); SetupCartMirroring(mirrortodo, 1, 0);
else if (mirrortodo == 0x4) { else if (mirrortodo == 0x4) {
FCEU_MemoryRand(exntar, sizeof(exntar), true);
SetupCartMirroring(4, 1, exntar); SetupCartMirroring(4, 1, exntar);
AddExState(exntar, 2048, 0, "EXNR"); AddExState(exntar, 2048, 0, "EXNR");
} else } else
@ -348,6 +349,7 @@ static BMAPPING bmap[] = {
{ "BS-5", BMCBS5_Init, 0 }, { "BS-5", BMCBS5_Init, 0 },
{ "CC-21", UNLCC21_Init, 0 }, { "CC-21", UNLCC21_Init, 0 },
{ "CITYFIGHT", UNLCITYFIGHT_Init, 0 }, { "CITYFIGHT", UNLCITYFIGHT_Init, 0 },
{ "10-24-C-A1", BMC1024CA1_Init, 0 },
{ "CNROM", CNROM_Init, 0 }, { "CNROM", CNROM_Init, 0 },
{ "CPROM", CPROM_Init, BMCFLAG_16KCHRR }, { "CPROM", CPROM_Init, BMCFLAG_16KCHRR },
{ "D1038", BMCD1038_Init, 0 }, { "D1038", BMCD1038_Init, 0 },
@ -374,6 +376,7 @@ static BMAPPING bmap[] = {
{ "KS7010", UNLKS7010_Init, 0 }, { "KS7010", UNLKS7010_Init, 0 },
{ "KS7012", UNLKS7012_Init, 0 }, { "KS7012", UNLKS7012_Init, 0 },
{ "KS7013B", UNLKS7013B_Init, 0 }, { "KS7013B", UNLKS7013B_Init, 0 },
{ "KS7016", UNLKS7016_Init, 0 },
{ "KS7017", UNLKS7017_Init, 0 }, { "KS7017", UNLKS7017_Init, 0 },
{ "KS7030", UNLKS7030_Init, 0 }, { "KS7030", UNLKS7030_Init, 0 },
{ "KS7031", UNLKS7031_Init, 0 }, { "KS7031", UNLKS7031_Init, 0 },
@ -462,6 +465,16 @@ static BMAPPING bmap[] = {
{ "YOKO", UNLYOKO_Init, 0 }, { "YOKO", UNLYOKO_Init, 0 },
{ "SB-2000", UNLSB2000_Init, 0 }, { "SB-2000", UNLSB2000_Init, 0 },
{ "COOLBOY", COOLBOY_Init, BMCFLAG_256KCHRR }, { "COOLBOY", COOLBOY_Init, BMCFLAG_256KCHRR },
{ "158B", UNL158B_Init, 0 },
{ "DRAGONFIGHTER", UNLBMW8544_Init, 0 },
{ "EH8813A", UNLEH8813A_Init, 0 },
{ "HP898F", BMCHP898F_Init, 0 },
{ "F-15", BMCF15_Init, 0 },
{ "RT-01", UNLRT01_Init, 0 },
{ "81-01-31-C", BMC810131C_Init, 0 },
{ "8-IN-1", BMC8IN1_Init, 0 },
{ "80013-B", BMC80013B_Init, 0 },
{ "HPxx", BMCHPxx_Init, 0 },
{ 0, 0, 0 } { 0, 0, 0 }
}; };
@ -526,7 +539,7 @@ static int InitializeBoard(void) {
CHRRAMSize = 256; CHRRAMSize = 256;
else else
CHRRAMSize = 8; CHRRAMSize = 8;
CHRRAMSize <<= 10; CHRRAMSize <<= 10;
if ((UNIFchrrama = (uint8*)FCEU_malloc(CHRRAMSize))) { if ((UNIFchrrama = (uint8*)FCEU_malloc(CHRRAMSize))) {
SetupCartCHRMapping(0, UNIFchrrama, CHRRAMSize, 1); SetupCartCHRMapping(0, UNIFchrrama, CHRRAMSize, 1);
AddExState(UNIFchrrama, CHRRAMSize, 0, "CHRR"); AddExState(UNIFchrrama, CHRRAMSize, 0, "CHRR");
@ -614,6 +627,7 @@ int UNIFLoad(const char *name, FCEUFILE *fp) {
strcpy(LoadedRomFName, name); //For the debugger list strcpy(LoadedRomFName, name); //For the debugger list
GameInterface = UNIFGI; GameInterface = UNIFGI;
currCartInfo = &UNIFCart;
return 1; return 1;
aborto: aborto:

View File

@ -1,151 +1,163 @@
/* FCE Ultra - NES/Famicom Emulator /* FCE Ultra - NES/Famicom Emulator
* *
* Copyright notice for this file: * Copyright notice for this file:
* Copyright (C) 2002 Xodnizel * Copyright (C) 2002 Xodnizel
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
void AC08_Init(CartInfo *info); void AC08_Init(CartInfo *info);
void ANROM_Init(CartInfo *info); void ANROM_Init(CartInfo *info);
void BMC11160_Init(CartInfo *info); void BMC11160_Init(CartInfo *info);
void BMC12IN1_Init(CartInfo *info); void BMC12IN1_Init(CartInfo *info);
void BMC13in1JY110_Init(CartInfo *info); void BMC13in1JY110_Init(CartInfo *info);
void BMC190in1_Init(CartInfo *info); void BMC190in1_Init(CartInfo *info);
void BMC411120C_Init(CartInfo *info); void BMC411120C_Init(CartInfo *info);
void BMC64in1nr_Init(CartInfo *info); void BMC64in1nr_Init(CartInfo *info);
void BMC70in1B_Init(CartInfo *info); void BMC70in1B_Init(CartInfo *info);
void BMC70in1_Init(CartInfo *info); void BMC70in1_Init(CartInfo *info);
void BMC810544CA1_Init(CartInfo *info); void BMC810544CA1_Init(CartInfo *info);
void BMC830118C_Init(CartInfo *info); void BMC830118C_Init(CartInfo *info);
void BMCA65AS_Init(CartInfo *info); void BMCA65AS_Init(CartInfo *info);
void BMCBS5_Init(CartInfo *info); void BMCBS5_Init(CartInfo *info);
void BMCD1038_Init(CartInfo *info); void BMCD1038_Init(CartInfo *info);
void BMCFK23CA_Init(CartInfo *info); void BMCFK23CA_Init(CartInfo *info);
void BMCFK23C_Init(CartInfo *info); void BMCFK23C_Init(CartInfo *info);
void BMCG146_Init(CartInfo *info); void BMCG146_Init(CartInfo *info);
void BMCGK192_Init(CartInfo *info); void BMCGK192_Init(CartInfo *info);
void BMCGS2004_Init(CartInfo *info); void BMCGS2004_Init(CartInfo *info);
void BMCGS2013_Init(CartInfo *info); void BMCGS2013_Init(CartInfo *info);
void BMCGhostbusters63in1_Init(CartInfo *info); void BMCGhostbusters63in1_Init(CartInfo *info);
void BMCNTD03_Init(CartInfo *info); void BMCNTD03_Init(CartInfo *info);
void BMCT2271_Init(CartInfo *info); void BMCT2271_Init(CartInfo *info);
void BMCT262_Init(CartInfo *info); void BMCT262_Init(CartInfo *info);
void CNROM_Init(CartInfo *info); void BMC1024CA1_Init(CartInfo *info);
void CPROM_Init(CartInfo *info); void CNROM_Init(CartInfo *info);
void DreamTech01_Init(CartInfo *info); void CPROM_Init(CartInfo *info);
void EKROM_Init(CartInfo *info); void DreamTech01_Init(CartInfo *info);
void ELROM_Init(CartInfo *info); void EKROM_Init(CartInfo *info);
void ETROM_Init(CartInfo *info); void ELROM_Init(CartInfo *info);
void EWROM_Init(CartInfo *info); void ETROM_Init(CartInfo *info);
void GNROM_Init(CartInfo *info); void EWROM_Init(CartInfo *info);
void HKROM_Init(CartInfo *info); void GNROM_Init(CartInfo *info);
void LE05_Init(CartInfo *info); void HKROM_Init(CartInfo *info);
void LH10_Init(CartInfo *info); void LE05_Init(CartInfo *info);
void LH32_Init(CartInfo *info); void LH10_Init(CartInfo *info);
void LH53_Init(CartInfo *info); void LH32_Init(CartInfo *info);
void MALEE_Init(CartInfo *info); void LH53_Init(CartInfo *info);
void MHROM_Init(CartInfo *info); void MALEE_Init(CartInfo *info);
void Mapper190_Init(CartInfo *info); void MHROM_Init(CartInfo *info);
void NROM_Init(CartInfo *info); void Mapper190_Init(CartInfo *info);
void Novel_Init(CartInfo *info); void NROM_Init(CartInfo *info);
void S74LS374NA_Init(CartInfo *info); void Novel_Init(CartInfo *info);
void S74LS374N_Init(CartInfo *info); void S74LS374NA_Init(CartInfo *info);
void S8259A_Init(CartInfo *info); void S74LS374N_Init(CartInfo *info);
void S8259B_Init(CartInfo *info); void S8259A_Init(CartInfo *info);
void S8259C_Init(CartInfo *info); void S8259B_Init(CartInfo *info);
void S8259D_Init(CartInfo *info); void S8259C_Init(CartInfo *info);
void SA0036_Init(CartInfo *info); void S8259D_Init(CartInfo *info);
void SA0037_Init(CartInfo *info); void SA0036_Init(CartInfo *info);
void SA009_Init(CartInfo *info); void SA0037_Init(CartInfo *info);
void SA0161M_Init(CartInfo *info); void SA009_Init(CartInfo *info);
void SA72007_Init(CartInfo *info); void SA0161M_Init(CartInfo *info);
void SA72008_Init(CartInfo *info); void SA72007_Init(CartInfo *info);
void SA9602B_Init(CartInfo *info); void SA72008_Init(CartInfo *info);
void SAROM_Init(CartInfo *info); void SA9602B_Init(CartInfo *info);
void SBROM_Init(CartInfo *info); void SAROM_Init(CartInfo *info);
void SCROM_Init(CartInfo *info); void SBROM_Init(CartInfo *info);
void SEROM_Init(CartInfo *info); void SCROM_Init(CartInfo *info);
void SGROM_Init(CartInfo *info); void SEROM_Init(CartInfo *info);
void SKROM_Init(CartInfo *info); void SGROM_Init(CartInfo *info);
void SL1ROM_Init(CartInfo *info); void SKROM_Init(CartInfo *info);
void SLROM_Init(CartInfo *info); void SL1ROM_Init(CartInfo *info);
void SNROM_Init(CartInfo *info); void SLROM_Init(CartInfo *info);
void SOROM_Init(CartInfo *info); void SNROM_Init(CartInfo *info);
void SSSNROM_Init(CartInfo *info); void SOROM_Init(CartInfo *info);
void SUNSOFT_UNROM_Init(CartInfo *info); // "Shanghi" original version mapper void SSSNROM_Init(CartInfo *info);
void Super24_Init(CartInfo *info); void SUNSOFT_UNROM_Init(CartInfo *info); // "Shanghi" original version mapper
void Supervision16_Init(CartInfo *info); void Super24_Init(CartInfo *info);
void TBROM_Init(CartInfo *info); void Supervision16_Init(CartInfo *info);
void TCA01_Init(CartInfo *info); void TBROM_Init(CartInfo *info);
void TCU01_Init(CartInfo *info); void TCA01_Init(CartInfo *info);
void TCU02_Init(CartInfo *info); void TCU01_Init(CartInfo *info);
void TEROM_Init(CartInfo *info); void TCU02_Init(CartInfo *info);
void TFROM_Init(CartInfo *info); void TEROM_Init(CartInfo *info);
void TGROM_Init(CartInfo *info); void TFROM_Init(CartInfo *info);
void TKROM_Init(CartInfo *info); void TGROM_Init(CartInfo *info);
void TKSROM_Init(CartInfo *info); void TKROM_Init(CartInfo *info);
void TLROM_Init(CartInfo *info); void TKSROM_Init(CartInfo *info);
void TLSROM_Init(CartInfo *info); void TLROM_Init(CartInfo *info);
void TQROM_Init(CartInfo *info); void TLSROM_Init(CartInfo *info);
void TQROM_Init(CartInfo *info); void TQROM_Init(CartInfo *info);
void TSROM_Init(CartInfo *info); void TQROM_Init(CartInfo *info);
void Transformer_Init(CartInfo *info); void TSROM_Init(CartInfo *info);
void UNL22211_Init(CartInfo *info); void Transformer_Init(CartInfo *info);
void UNL3DBlock_Init(CartInfo *info); void UNL22211_Init(CartInfo *info);
void UNL43272_Init(CartInfo *info); void UNL3DBlock_Init(CartInfo *info);
void UNL6035052_Init(CartInfo *info); void UNL43272_Init(CartInfo *info);
void UNL8157_Init(CartInfo *info); void UNL6035052_Init(CartInfo *info);
void UNL8237A_Init(CartInfo *info); void UNL8157_Init(CartInfo *info);
void UNL8237_Init(CartInfo *info); void UNL8237A_Init(CartInfo *info);
void UNLA9746_Init(CartInfo *info); void UNL8237_Init(CartInfo *info);
void UNLAX5705_Init(CartInfo *info); void UNLA9746_Init(CartInfo *info);
void UNLBB_Init(CartInfo *info); void UNLAX5705_Init(CartInfo *info);
void UNLCC21_Init(CartInfo *info); void UNLBB_Init(CartInfo *info);
void UNLCITYFIGHT_Init(CartInfo *info); void UNLCC21_Init(CartInfo *info);
void UNLD2000_Init(CartInfo *info); void UNLCITYFIGHT_Init(CartInfo *info);
void UNLEDU2000_Init(CartInfo *info); void UNLD2000_Init(CartInfo *info);
void UNLFS304_Init(CartInfo *info); void UNLEDU2000_Init(CartInfo *info);
void UNLH2288_Init(CartInfo *info); void UNLFS304_Init(CartInfo *info);
void UNLKOF97_Init(CartInfo *info); void UNLH2288_Init(CartInfo *info);
void UNLKS7012_Init(CartInfo *info); void UNLKOF97_Init(CartInfo *info);
void UNLKS7013B_Init(CartInfo *info); void UNLKS7012_Init(CartInfo *info);
void UNLKS7017_Init(CartInfo *info); void UNLKS7013B_Init(CartInfo *info);
void UNLKS7030_Init(CartInfo *info); void UNLKS7016_Init(CartInfo *info);
void UNLKS7031_Init(CartInfo *info); void UNLKS7017_Init(CartInfo *info);
void UNLKS7032_Init(CartInfo *info); void UNLKS7030_Init(CartInfo *info);
void UNLKS7037_Init(CartInfo *info); void UNLKS7031_Init(CartInfo *info);
void UNLKS7057_Init(CartInfo *info); void UNLKS7032_Init(CartInfo *info);
void UNLN625092_Init(CartInfo *info); void UNLKS7037_Init(CartInfo *info);
void UNLMaliSB_Init(CartInfo *info); void UNLKS7057_Init(CartInfo *info);
void UNLOneBus_Init(CartInfo *info); void UNLN625092_Init(CartInfo *info);
void UNLPEC586Init(CartInfo *info); void UNLMaliSB_Init(CartInfo *info);
void UNLSC127_Init(CartInfo *info); void UNLOneBus_Init(CartInfo *info);
void UNLSHeroes_Init(CartInfo *info); void UNLPEC586Init(CartInfo *info);
void UNLSL12_Init(CartInfo *info); void UNLSC127_Init(CartInfo *info);
void UNLSL1632_Init(CartInfo *info); void UNLSHeroes_Init(CartInfo *info);
void UNLSMB2J_Init(CartInfo *info); void UNLSL12_Init(CartInfo *info);
void UNLT230_Init(CartInfo *info); void UNLSL1632_Init(CartInfo *info);
void UNLTF1201_Init(CartInfo *info); void UNLSMB2J_Init(CartInfo *info);
void UNLVRC7_Init(CartInfo *info); void UNLT230_Init(CartInfo *info);
void UNLYOKO_Init(CartInfo *info); void UNLTF1201_Init(CartInfo *info);
void UNROM_Init(CartInfo *info); void UNLVRC7_Init(CartInfo *info);
void UNROM512_Init(CartInfo *info); void UNLYOKO_Init(CartInfo *info);
void UNLSB2000_Init(CartInfo *info); void UNROM_Init(CartInfo *info);
void UNLKS7010_Init(CartInfo *info); void UNROM512_Init(CartInfo *info);
void COOLBOY_Init(CartInfo *info); void UNLSB2000_Init(CartInfo *info);
void UNLKS7010_Init(CartInfo *info);
extern uint8 *UNIFchrrama; // Meh. So I can stop CHR RAM void COOLBOY_Init(CartInfo *info);
// bank switcherooing with certain boards... void UNL158B_Init(CartInfo *info);
void UNLBMW8544_Init(CartInfo *info);
void UNLEH8813A_Init(CartInfo *info);
void BMCHP898F_Init(CartInfo *info);
void BMCF15_Init(CartInfo *info);
void UNLRT01_Init(CartInfo *info);
void BMC810131C_Init(CartInfo *info);
void BMC8IN1_Init(CartInfo *info);
void BMC80013B_Init(CartInfo *info);
void BMCHPxx_Init(CartInfo *info);
extern uint8 *UNIFchrrama; // Meh. So I can stop CHR RAM
// bank switcherooing with certain boards...

View File

@ -39,11 +39,7 @@ void *FCEU_gmalloc(uint32 size)
FCEU_PrintError("Error allocating memory! Doing a hard exit."); FCEU_PrintError("Error allocating memory! Doing a hard exit.");
exit(1); exit(1);
} }
//mbg 6/17/08 - sometimes this memory is used as RAM or somesuch without clearing first. FCEU_MemoryRand((uint8*)ret,size,true); // initialize according to RAMInitOption, default zero
//this yields different behavior in debug and release modes.
//specifically, saveram wasnt getting cleared so the games thought their savefiles were initialized
//so we are going to clear it here.
memset(ret,0,size);
return ret; return ret;
} }
@ -57,11 +53,7 @@ void *FCEU_malloc(uint32 size)
FCEU_PrintError("Error allocating memory!"); FCEU_PrintError("Error allocating memory!");
return(0); return(0);
} }
//mbg 6/17/08 - sometimes this memory is used as RAM or somesuch without clearing first. memset(ret,0,size); // initialize to 0
//this yields different behavior in debug and release modes.
//specifically, saveram wasnt getting cleared so the games thought their savefiles were initialized
//so we are going to clear it here.
memset(ret,0,size);
return ret; return ret;
} }

View File

@ -24,8 +24,8 @@
#define FCEU_dwmemset(d,c,n) {int _x; for(_x=n-4;_x>=0;_x-=4) *(uint32 *)&(d)[_x]=c;} #define FCEU_dwmemset(d,c,n) {int _x; for(_x=n-4;_x>=0;_x-=4) *(uint32 *)&(d)[_x]=c;}
void *FCEU_malloc(uint32 size); void *FCEU_malloc(uint32 size); // initialized to 0
void *FCEU_gmalloc(uint32 size); void *FCEU_gmalloc(uint32 size); // used by boards for WRAM etc, initialized to 0 (default) or other via RAMInitOption
void FCEU_gfree(void *ptr); void FCEU_gfree(void *ptr);
void FCEU_free(void *ptr); void FCEU_free(void *ptr);
void FCEU_memmove(void *d, void *s, uint32 l); void FCEU_memmove(void *d, void *s, uint32 l);

View File

@ -231,8 +231,8 @@ std::string BytesToString(const void* data, int len)
{ {
Base64Table[ input[0] >> 2 ], Base64Table[ input[0] >> 2 ],
Base64Table[ ((input[0] & 0x03) << 4) | (input[1] >> 4) ], Base64Table[ ((input[0] & 0x03) << 4) | (input[1] >> 4) ],
n<2 ? '=' : Base64Table[ ((input[1] & 0x0F) << 2) | (input[2] >> 6) ], static_cast<unsigned char> (n<2 ? '=' : Base64Table[ ((input[1] & 0x0F) << 2) | (input[2] >> 6) ]),
n<3 ? '=' : Base64Table[ input[2] & 0x3F ] static_cast<unsigned char> (n<3 ? '=' : Base64Table[ input[2] & 0x3F ])
}; };
ret.append(output, output+4); ret.append(output, output+4);
} }
@ -296,9 +296,9 @@ bool StringToBytes(const std::string& str, void* data, int len)
} }
unsigned char outpacket[3] = unsigned char outpacket[3] =
{ {
(converted[0] << 2) | (converted[1] >> 4), static_cast<unsigned char>((converted[0] << 2) | (converted[1] >> 4)),
(converted[1] << 4) | (converted[2] >> 2), static_cast<unsigned char>((converted[1] << 4) | (converted[2] >> 2)),
(converted[2] << 6) | (converted[3]) static_cast<unsigned char>((converted[2] << 6) | (converted[3]))
}; };
int outlen = (input[2] == '=') ? 1 : (input[3] == '=' ? 2 : 3); int outlen = (input[2] == '=') ? 1 : (input[3] == '=' ? 2 : 3);
if(outlen > len) outlen = len; if(outlen > len) outlen = len;

View File

@ -26,12 +26,12 @@
//todo - everyone will want to support this eventually, i suppose //todo - everyone will want to support this eventually, i suppose
#ifdef _MSC_VER #ifdef _MSC_VER
#include "svnrev.h" #include "scmrev.h"
#else #else
#ifdef SVN_REV #ifdef SVN_REV
#define SVN_REV_STR SVN_REV #define SCM_REV_STR SCM_REV
#else #else
#define SVN_REV_STR "" #define SCM_REV_STR ""
#endif #endif
#endif #endif
@ -44,7 +44,7 @@
#elif defined(PUBLIC_RELEASE) #elif defined(PUBLIC_RELEASE)
#define FCEU_SUBVERSION_STRING "" #define FCEU_SUBVERSION_STRING ""
#else #else
#define FCEU_SUBVERSION_STRING "-interim svn" SVN_REV_STR #define FCEU_SUBVERSION_STRING "-interim git" SCM_REV_STR
#endif #endif
#if defined(_MSC_VER) #if defined(_MSC_VER)

View File

@ -32,6 +32,7 @@
#include "vsuni.h" #include "vsuni.h"
#include "drawing.h" #include "drawing.h"
#include "driver.h" #include "driver.h"
#ifdef _S9XLUA_H #ifdef _S9XLUA_H
#include "fceulua.h" #include "fceulua.h"
#endif #endif
@ -56,10 +57,17 @@
#include <cstdarg> #include <cstdarg>
#include <zlib.h> #include <zlib.h>
uint8 *XBuf=NULL; //XBuf:
uint8 *XBackBuf=NULL; //0-63 is reserved for 7 special colours used by FCEUX (overlay, etc.)
//64-127 is the most-used emphasis setting per frame
//128-195 is the palette with no emphasis
//196-255 is the palette with all emphasis bits on
u8 *XBuf=NULL; //used for current display
u8 *XBackBuf=NULL; //ppu output is stashed here before drawing happens
u8 *XDBuf=NULL; //corresponding to XBuf but with deemph bits
u8 *XDBackBuf=NULL; //corresponding to XBackBuf but with deemph bits
int ClipSidesOffset=0; //Used to move displayed messages when Clips left and right sides is checked int ClipSidesOffset=0; //Used to move displayed messages when Clips left and right sides is checked
static uint8 *xbsave=NULL; static u8 *xbsave=NULL;
GUIMESSAGE guiMessage; GUIMESSAGE guiMessage;
GUIMESSAGE subtitleMessage; GUIMESSAGE subtitleMessage;
@ -105,29 +113,35 @@ void FCEU_KillVirtualVideo(void)
**/ **/
int FCEU_InitVirtualVideo(void) int FCEU_InitVirtualVideo(void)
{ {
if(!XBuf) /* Some driver code may allocate XBuf externally. */ //Some driver code may allocate XBuf externally.
/* 256 bytes per scanline, * 240 scanline maximum, +16 for alignment, //256 bytes per scanline, * 240 scanline maximum, +16 for alignment,
*/ if(XBuf)
if(!(XBuf= (uint8*) (FCEU_malloc(256 * 256 + 16))) ||
!(XBackBuf= (uint8*) (FCEU_malloc(256 * 256 + 16))))
{
return 0;
}
xbsave = XBuf;
if( sizeof(uint8*) == 4 )
{
uintptr_t m = (uintptr_t)XBuf;
m = ( 8 - m) & 7;
XBuf+=m;
}
memset(XBuf,128,256*256); //*240);
memset(XBackBuf,128,256*256);
return 1; return 1;
XBuf = (u8*)FCEU_malloc(256 * 256 + 16);
XBackBuf = (u8*)FCEU_malloc(256 * 256 + 16);
XDBuf = (u8*)FCEU_malloc(256 * 256 + 16);
XDBackBuf = (u8*)FCEU_malloc(256 * 256 + 16);
if(!XBuf || !XBackBuf || !XDBuf || !XDBackBuf)
{
return 0;
}
xbsave = XBuf;
if( sizeof(uint8*) == 4 )
{
uintptr_t m = (uintptr_t)XBuf;
m = ( 8 - m) & 7;
XBuf+=m;
}
memset(XBuf,128,256*256);
memset(XBackBuf,128,256*256);
memset(XBuf,128,256*256);
memset(XBackBuf,128,256*256);
return 1;
} }
#ifdef FRAMESKIP #ifdef FRAMESKIP
@ -551,11 +565,14 @@ int GetScreenPixelPalette(int x, int y, bool usebackup) {
int SaveSnapshot(void) int SaveSnapshot(void)
{ {
#ifdef GEKKO
return 0;
#else
int totallines=FSettings.LastSLine-FSettings.FirstSLine+1; int totallines=FSettings.LastSLine-FSettings.FirstSLine+1;
int x,u,y; int x,u,y;
FILE *pp=NULL; FILE *pp=NULL;
uint8 *compmem=NULL; uint8 *compmem=NULL;
uLongf compmemsize=totallines*263+12; uLongf compmemsize=(totallines*263+12)*3;
if(!(compmem=(uint8 *)FCEU_malloc(compmemsize))) if(!(compmem=(uint8 *)FCEU_malloc(compmemsize)))
return 0; return 0;
@ -575,7 +592,7 @@ int SaveSnapshot(void)
} }
{ {
static uint8 header[8]={137,80,78,71,13,10,26,10}; static const uint8 header[8]={137,80,78,71,13,10,26,10};
if(fwrite(header,8,1,pp)!=1) if(fwrite(header,8,1,pp)!=1)
goto PNGerr; goto PNGerr;
} }
@ -589,8 +606,8 @@ int SaveSnapshot(void)
chunko[4]=chunko[5]=chunko[6]=0; chunko[4]=chunko[5]=chunko[6]=0;
chunko[7]=totallines; // Height chunko[7]=totallines; // Height
chunko[8]=8; // bit depth chunko[8]=8; // 8 bits per sample(24 bits per pixel)
chunko[9]=3; // Color type; indexed 8-bit chunko[9]=2; // Color type; RGB triplet
chunko[10]=0; // compression: deflate chunko[10]=0; // compression: deflate
chunko[11]=0; // Basic adapative filter set(though none are used). chunko[11]=0; // Basic adapative filter set(though none are used).
chunko[12]=0; // No interlace. chunko[12]=0; // No interlace.
@ -599,19 +616,12 @@ int SaveSnapshot(void)
goto PNGerr; 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 *tmp=XBuf+FSettings.FirstSLine*256;
uint8 *dest,*mal,*mork; uint8 *dest,*mal,*mork;
if(!(mal=mork=dest=(uint8 *)FCEU_dmalloc((totallines<<8)+totallines))) int bufsize = (256*3+1)*totallines;
if(!(mal=mork=dest=(uint8 *)FCEU_dmalloc(bufsize)))
goto PNGerr; goto PNGerr;
// mork=dest=XBuf; // mork=dest=XBuf;
@ -619,11 +629,17 @@ int SaveSnapshot(void)
{ {
*dest=0; // No filter. *dest=0; // No filter.
dest++; dest++;
for(x=256;x;x--,tmp++,dest++) for(x=256;x;x--)
*dest=*tmp; {
u32 color = ModernDeemphColorMap(tmp,XBuf,1,1);
*dest++=(color>>0x10)&0xFF;
*dest++=(color>>0x08)&0xFF;
*dest++=(color>>0x00)&0xFF;
tmp++;
}
} }
if(compress(compmem,&compmemsize,mork,(totallines<<8)+totallines)!=Z_OK) if(compress(compmem,&compmemsize,mork,bufsize)!=Z_OK)
{ {
if(mal) free(mal); if(mal) free(mal);
goto PNGerr; goto PNGerr;
@ -647,6 +663,7 @@ PNGerr:
if(pp) if(pp)
fclose(pp); fclose(pp);
return(0); return(0);
#endif
} }
//overloaded SaveSnapshot for "Savesnapshot As" function //overloaded SaveSnapshot for "Savesnapshot As" function

View File

@ -9,6 +9,8 @@ uint32 GetScreenPixel(int x, int y, bool usebackup);
int GetScreenPixelPalette(int x, int y, bool usebackup); int GetScreenPixelPalette(int x, int y, bool usebackup);
extern uint8 *XBuf; extern uint8 *XBuf;
extern uint8 *XBackBuf; extern uint8 *XBackBuf;
extern uint8 *XDBuf;
extern uint8 *XDBackBuf;
extern int ClipSidesOffset; extern int ClipSidesOffset;
extern struct GUIMESSAGE extern struct GUIMESSAGE
{ {

View File

@ -301,7 +301,7 @@ void FCEU_VSUniCheck(uint64 md5partial, int *MapperNo, uint8 *Mirroring) {
while (vs->name) { while (vs->name) {
if (md5partial == vs->md5partial) { if (md5partial == vs->md5partial) {
if (vs->ppu < RCP2C03B) pale = vs->ppu; if (vs->ppu < RCP2C03B) default_palette_selection = vs->ppu;
*MapperNo = vs->mapper; *MapperNo = vs->mapper;
*Mirroring = vs->mirroring; *Mirroring = vs->mirroring;
GameInfo->type = GIT_VSUNI; GameInfo->type = GIT_VSUNI;

View File

@ -32,14 +32,16 @@
#include <cstring> #include <cstring>
X6502 X; X6502 X;
uint32 timestamp; uint32 timestamp;
uint32 soundtimestamp;
void (*MapIRQHook)(int a); void (*MapIRQHook)(int a);
#define ADDCYC(x) \ #define ADDCYC(x) \
{ \ { \
int __x=x; \ int __x=x; \
_tcount+=__x; \ _tcount+=__x; \
_count-=__x*48; \ _count-=__x*48; \
timestamp+=__x; \ timestamp+=__x; \
if(!overclocking) soundtimestamp+=__x; \
} }
//normal memory read //normal memory read
@ -404,12 +406,14 @@ void X6502_Init(void)
} }
} }
extern int StackAddrBackup;
void X6502_Power(void) void X6502_Power(void)
{ {
_count=_tcount=_IRQlow=_PC=_A=_X=_Y=_P=_PI=_DB=_jammed=0; _count=_tcount=_IRQlow=_PC=_A=_X=_Y=_P=_PI=_DB=_jammed=0;
_S=0xFD; _S=0xFD;
timestamp=0; timestamp=soundtimestamp=0;
X6502_Reset(); X6502_Reset();
StackAddrBackup = -1;
} }
void X6502_Run(int32 cycles) void X6502_Run(int32 cycles)
@ -493,7 +497,9 @@ extern int test; test++;
temp=_tcount; temp=_tcount;
_tcount=0; _tcount=0;
if(MapIRQHook) MapIRQHook(temp); if(MapIRQHook) MapIRQHook(temp);
FCEU_SoundCPUHook(temp);
if (!overclocking)
FCEU_SoundCPUHook(temp);
#ifdef _S9XLUA_H #ifdef _S9XLUA_H
CallRegisteredLuaMemHook(_PC, 1, 0, LUAMEMHOOK_EXEC); CallRegisteredLuaMemHook(_PC, 1, 0, LUAMEMHOOK_EXEC);
#endif #endif
@ -537,7 +543,7 @@ const uint8 opsize[256] = {
#else #else
/*0x00*/ 1, //BRK /*0x00*/ 1, //BRK
#endif #endif
/*0x01*/ 2,0,0,0,2,2,0,1,2,1,0,0,3,3,0, /*0x01*/ 2,0,0,0,2,2,0,1,2,1,0,0,3,3,0,
/*0x10*/ 2,2,0,0,0,2,2,0,1,3,0,0,0,3,3,0, /*0x10*/ 2,2,0,0,0,2,2,0,1,3,0,0,0,3,3,0,
/*0x20*/ 3,2,0,0,2,2,2,0,1,2,1,0,3,3,3,0, /*0x20*/ 3,2,0,0,2,2,2,0,1,2,1,0,3,3,3,0,
/*0x30*/ 2,2,0,0,0,2,2,0,1,3,0,0,0,3,3,0, /*0x30*/ 2,2,0,0,0,2,2,0,1,3,0,0,0,3,3,0,
@ -569,20 +575,58 @@ const uint8 opsize[256] = {
// 8 = Zero Page,Y // 8 = Zero Page,Y
// //
const uint8 optype[256] = { const uint8 optype[256] = {
/*0x00*/ 0,1,0,0,0,2,2,0,0,0,0,0,0,3,3,0, /*0x00*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
/*0x10*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0, /*0x10*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
/*0x20*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0, /*0x20*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
/*0x30*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0, /*0x30*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
/*0x40*/ 0,1,0,0,0,2,2,0,0,0,0,0,0,3,3,0, /*0x40*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
/*0x50*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0, /*0x50*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
/*0x60*/ 0,1,0,0,0,2,2,0,0,0,0,0,3,3,3,0, /*0x60*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
/*0x70*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0, /*0x70*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
/*0x80*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0, /*0x80*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
/*0x90*/ 0,4,0,0,5,5,8,0,0,6,0,0,0,7,0,0, /*0x90*/ 0,4,0,3,5,5,8,8,0,6,0,6,7,7,6,6,
/*0xA0*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0, /*0xA0*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
/*0xB0*/ 0,4,0,0,5,5,8,0,0,6,0,0,7,7,6,0, /*0xB0*/ 0,4,0,3,5,5,8,8,0,6,0,6,7,7,6,6,
/*0xC0*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0, /*0xC0*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
/*0xD0*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0, /*0xD0*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
/*0xE0*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0, /*0xE0*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
/*0xF0*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0 /*0xF0*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
}; };
// the opwrite table aids in predicting the value written for any 6502 opcode
//
// 0 = No value written
// 1 = Write from A
// 2 = Write from X
// 3 = Write from Y
// 4 = Write from P
// 5 = ASL (SLO)
// 6 = LSR (SRE)
// 7 = ROL (RLA)
// 8 = ROR (RRA)
// 9 = INC (ISC)
// 10 = DEC (DCP)
// 11 = (SAX)
// 12 = (AHX)
// 13 = (SHY)
// 14 = (SHX)
// 15 = (TAS)
const uint8 opwrite[256] = {
/*0x00*/ 0, 0, 0, 5, 0, 0, 5, 5, 4, 0, 0, 0, 0, 0, 5, 5,
/*0x10*/ 0, 0, 0, 5, 0, 0, 5, 5, 0, 0, 0, 5, 0, 0, 5, 5,
/*0x20*/ 0, 0, 0, 7, 0, 0, 7, 7, 0, 0, 7, 0, 0, 0, 7, 7,
/*0x30*/ 0, 0, 0, 7, 0, 0, 7, 7, 0, 0, 0, 7, 0, 0, 7, 7,
/*0x40*/ 0, 0, 0, 6, 0, 0, 6, 6, 1, 0, 6, 0, 0, 0, 6, 6,
/*0x50*/ 0, 0, 0, 6, 0, 0, 6, 6, 0, 0, 0, 6, 0, 0, 6, 6,
/*0x60*/ 0, 0, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 0, 0, 8, 8,
/*0x70*/ 0, 0, 0, 8, 0, 0, 8, 8, 0, 0, 0, 8, 0, 0, 8, 8,
/*0x80*/ 0, 1, 0,11, 3, 1, 2,11, 0, 0, 0, 0, 3, 1, 2,11,
/*0x90*/ 0, 1, 0,12, 3, 1, 2,11, 0, 1, 0,15,13, 1,14,12,
/*0xA0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*0xB0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*0xC0*/ 0, 0, 0,10, 0, 0,10,10, 0, 0, 0, 0, 0, 0,10,10,
/*0xD0*/ 0, 0, 0,10, 0, 0,10,10, 0, 0, 0,10, 0, 0,10,10,
/*0xE0*/ 0, 0, 0, 9, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9,
/*0xF0*/ 0, 0, 0, 9, 0, 0, 9, 9, 0, 0, 0, 9, 0, 0, 9, 9,
};

View File

@ -31,6 +31,9 @@ extern const uint8 opsize[256];
//the optype table is a quick way to grab the addressing mode for any 6502 opcode //the optype table is a quick way to grab the addressing mode for any 6502 opcode
extern const uint8 optype[256]; extern const uint8 optype[256];
// the opwrite table aids in predicting the value written for any 6502 opcode
extern const uint8 opwrite[256];
//----------- //-----------
//mbg 6/30/06 - some of this was removed to mimic XD //mbg 6/30/06 - some of this was removed to mimic XD
//#ifdef FCEUDEF_DEBUGGER //#ifdef FCEUDEF_DEBUGGER
@ -47,8 +50,8 @@ void X6502_RunDebug(int32 cycles);
//------------ //------------
extern uint32 timestamp; extern uint32 timestamp;
extern uint32 soundtimestamp;
extern int scanline;
#define N_FLAG 0x80 #define N_FLAG 0x80
#define V_FLAG 0x40 #define V_FLAG 0x40

View File

@ -18,6 +18,10 @@
#include "menu.h" #include "menu.h"
bool turbo = false; bool turbo = false;
bool paldeemphswap = 0;
int dendy;
bool swapDuty;
int KillFCEUXonFrame = 0;
/** /**
* Closes a game. Frees memory, and deinitializes the drivers. * Closes a game. Frees memory, and deinitializes the drivers.
@ -172,3 +176,4 @@ const char *FCEUD_GetCompilerString() { return NULL; }
void FCEUI_UseInputPreset(int preset) { } void FCEUI_UseInputPreset(int preset) { }
void FCEUD_SoundVolumeAdjust(int n) { } void FCEUD_SoundVolumeAdjust(int n) { }
void FCEUD_SetEmulationSpeed(int cmd) { } void FCEUD_SetEmulationSpeed(int cmd) { }
void GetMouseData(uint32 (&d)[3]) { }