mirror of
https://github.com/dborth/fceugx.git
synced 2024-12-04 22:34:14 +01:00
update to the latest FCEUX core from git head.
This commit is contained in:
parent
a9c3f8c631
commit
50b3150515
@ -30,7 +30,7 @@ https://github.com/dborth/fceugx/releases
|
||||
* Cheat support (.CHT files and Game Genie)
|
||||
* Famicom 3D System 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!
|
||||
|
||||
×—–—–—–—– –—–—–—–—–—–—–—–—–—–— —–—–—–—–—–—–—–—-—–-–•¬
|
||||
@ -39,6 +39,7 @@ https://github.com/dborth/fceugx/releases
|
||||
|
||||
[3.4.0]
|
||||
|
||||
* Update to the latest FCEUX core
|
||||
* Allow loader to pass two arguments instead of three (libertyernie)
|
||||
* Add PocketNES interoperability (load ROMs and read/write SRAM)
|
||||
* Add option to not append " Auto" on saves
|
||||
|
@ -272,7 +272,7 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||
(a) = opcode[1] | opcode[2]<<8; \
|
||||
}
|
||||
#define zpIndex(a,i) { \
|
||||
(a) = opcode[1]+(i); \
|
||||
(a) = (opcode[1]+(i))&0xFF; \
|
||||
}
|
||||
#define indirectX(a) { \
|
||||
(a) = (opcode[1]+RX)&0xFF; \
|
||||
@ -360,8 +360,8 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||
case 0xE6: strcpy(chr,"INC"); goto _zeropage;
|
||||
_zeropage:
|
||||
// ################################## Start of SP CODE ###########################
|
||||
// Change width to %04X
|
||||
sprintf(str,"%s $%04X = #$%02X", chr,opcode[1],GetMem(opcode[1]));
|
||||
// Change width to %04X // don't!
|
||||
sprintf(str,"%s $%02X = #$%02X", chr,opcode[1],GetMem(opcode[1]));
|
||||
// ################################## End of SP CODE ###########################
|
||||
break;
|
||||
|
||||
@ -457,7 +457,7 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||
_zeropagex:
|
||||
zpIndex(tmp,RX);
|
||||
// ################################## 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));
|
||||
// ################################## End of SP CODE ###########################
|
||||
break;
|
||||
@ -515,8 +515,8 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||
_zeropagey:
|
||||
zpIndex(tmp,RY);
|
||||
// ################################## Start of SP CODE ###########################
|
||||
// Change width to %04X
|
||||
sprintf(str,"%s $%04X,Y @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
||||
// Change width to %04X // don't!
|
||||
sprintf(str,"%s $%02X,Y @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
||||
// ################################## End of SP CODE ###########################
|
||||
break;
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
*
|
||||
* 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-22110-000 (52S ) - MGC-002 2-in-1 Gun
|
||||
* 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-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior
|
||||
* 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-22200-400 (------------) (079 ) - ET.03 F-15 City War
|
||||
* (172 ) - 1991 Du Ma Racing
|
||||
|
@ -72,7 +72,7 @@ static void M112Power(void) {
|
||||
SetWriteHandler(0x4020, 0x5FFF, M112Write);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
||||
FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
|
@ -102,7 +102,7 @@ static void Power(void) {
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
WSync();
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ static void Power2(void) {
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write2);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
WSync();
|
||||
}
|
||||
|
||||
@ -208,7 +208,7 @@ static void Power3(void) {
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write3);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
WSync();
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ static void M168Power(void) {
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
}
|
||||
|
||||
static void MNNNClose(void) {
|
||||
static void M168Close(void) {
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
@ -67,7 +67,7 @@ static void StateRestore(int version) {
|
||||
|
||||
void Mapper168_Init(CartInfo *info) {
|
||||
info->Power = M168Power;
|
||||
info->Close = MNNNClose;
|
||||
info->Close = M168Close;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
|
||||
|
@ -29,6 +29,12 @@ static uint8 reg[4];
|
||||
static uint8 *WRAM = NULL;
|
||||
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
|
||||
static uint8 pcm_enable = 0;
|
||||
static int16 pcm_latch = 0x3F6, pcm_clock = 0x3F6;
|
||||
@ -40,41 +46,41 @@ static SFORMAT StateRegs[] =
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static int16 step_size[49] = {
|
||||
16, 17, 19, 21, 23, 25, 28, 31, 34, 37,
|
||||
41, 45, 50, 55, 60, 66, 73, 80, 88, 97,
|
||||
107, 118, 130, 143, 157, 173, 190, 209, 230, 253,
|
||||
279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
|
||||
724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
|
||||
}; //49 items
|
||||
static int32 step_adj[16] = { -1, -1, -1, -1, 2, 5, 7, 9, -1, -1, -1, -1, 2, 5, 7, 9 };
|
||||
//static int16 step_size[49] = {
|
||||
// 16, 17, 19, 21, 23, 25, 28, 31, 34, 37,
|
||||
// 41, 45, 50, 55, 60, 66, 73, 80, 88, 97,
|
||||
// 107, 118, 130, 143, 157, 173, 190, 209, 230, 253,
|
||||
// 279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
|
||||
// 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
|
||||
//}; //49 items
|
||||
//static int32 step_adj[16] = { -1, -1, -1, -1, 2, 5, 7, 9, -1, -1, -1, -1, 2, 5, 7, 9 };
|
||||
|
||||
//decode stuff
|
||||
static int32 jedi_table[16 * 49];
|
||||
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 jedi_table[16 * 49];
|
||||
//static int32 acc = 0; //ADPCM accumulator, initial condition must be 0
|
||||
//static int32 decstep = 0; //ADPCM decoding step, initial condition must be 0
|
||||
|
||||
static void jedi_table_init() {
|
||||
int step, nib;
|
||||
//static void jedi_table_init() {
|
||||
// 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++) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8 decode(uint8 code) {
|
||||
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 uint8 decode(uint8 code) {
|
||||
// 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) {
|
||||
uint32 sbank = reg[1] & 0x7;
|
||||
@ -109,11 +115,11 @@ static DECLFW(M178WriteSnd) {
|
||||
if (V & 0xF0) {
|
||||
pcm_enable = 1;
|
||||
// pcmwrite(0x4011, (V & 0xF) << 3);
|
||||
pcmwrite(0x4011, decode(V & 0xf));
|
||||
// pcmwrite(0x4011, decode(V & 0xf));
|
||||
} else
|
||||
pcm_enable = 0;
|
||||
} else
|
||||
FCEU_printf("misc %04x:%02x\n", A, V);
|
||||
}// else
|
||||
// FCEU_printf("misc %04x:%02x\n", A, V);
|
||||
}
|
||||
|
||||
static DECLFR(M178ReadSnd) {
|
||||
@ -123,13 +129,19 @@ static DECLFR(M178ReadSnd) {
|
||||
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) {
|
||||
reg[0] = reg[1] = reg[2] = reg[3] = 0;
|
||||
reg[0] = reg[1] = reg[2] = reg[3] = SensorDelay = 0;
|
||||
Sync();
|
||||
pcmwrite = GetWriteHandler(0x4011);
|
||||
// pcmwrite = GetWriteHandler(0x4011);
|
||||
SetWriteHandler(0x4800, 0x4fff, M178Write);
|
||||
SetWriteHandler(0x5800, 0x5fff, M178WriteSnd);
|
||||
SetReadHandler(0x5800, 0x5fff, M178ReadSnd);
|
||||
SetReadHandler(0x5000, 0x5000, M178ReadSensor);
|
||||
SetReadHandler(0x6000, 0x7fff, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
@ -137,13 +149,25 @@ static void M178Power(void) {
|
||||
}
|
||||
|
||||
static void M178SndClk(int a) {
|
||||
if (pcm_enable) {
|
||||
pcm_latch -= a;
|
||||
if (pcm_latch <= 0) {
|
||||
pcm_latch += pcm_clock;
|
||||
pcm_enable = 0;
|
||||
}
|
||||
SensorDelay += a;
|
||||
if(SensorDelay > 0x32768) {
|
||||
SensorDelay -= 32768;
|
||||
GetMouseData (MouseData);
|
||||
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) {
|
||||
@ -162,7 +186,7 @@ void Mapper178_Init(CartInfo *info) {
|
||||
GameStateRestore = StateRestore;
|
||||
MapIRQHook = M178SndClk;
|
||||
|
||||
jedi_table_init();
|
||||
// jedi_table_init();
|
||||
|
||||
WRAMSIZE = 32768;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
|
@ -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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -141,6 +141,7 @@ static DECLFW(WritePRG)
|
||||
case 0x00:
|
||||
chr = value & 3;
|
||||
Mirror(value);
|
||||
Sync();
|
||||
break;
|
||||
case 0x01:
|
||||
prg = value & 15;
|
||||
|
@ -22,11 +22,12 @@
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 latche;
|
||||
static uint8 latche, mirr;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &latche, 1, "LATC" },
|
||||
{ &mirr, 1, "MIRR" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@ -36,6 +37,11 @@ static void Sync(void) {
|
||||
}
|
||||
|
||||
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;
|
||||
Sync();
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ static SFORMAT StateRegs[] =
|
||||
static void Sync(void) {
|
||||
uint8 i;
|
||||
if ((preg[3] & 0xC0) == 0xC0)
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
setprg8r(0x10, 0x6000, preg[3] & 0x3F);
|
||||
else
|
||||
setprg8(0x6000, preg[3] & 0x3F);
|
||||
setprg8(0x8000, preg[0]);
|
||||
@ -258,7 +258,10 @@ void Mapper69_Init(CartInfo *info) {
|
||||
info->Power = M69Power;
|
||||
info->Close = M69Close;
|
||||
MapIRQHook = M69IRQHook;
|
||||
WRAMSIZE = 8192;
|
||||
if(info->ines2)
|
||||
WRAMSIZE = info->wram_size + info->battery_wram_size;
|
||||
else
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
@ -303,14 +303,20 @@ static void M212Sync(void) {
|
||||
}
|
||||
|
||||
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 ---------------------------
|
||||
|
||||
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);
|
||||
setmirror(((latche & 1)^((latche >> 6) & 1)) ^ 1);
|
||||
}
|
||||
|
||||
void Mapper213_Init(CartInfo *info) {
|
||||
|
@ -1,108 +1,146 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2015 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* CoolBoy 400-in-1 FK23C-mimic mapper 16Mb/32Mb PROM + 128K/256K CHR RAM, optional SRAM, optional NTRAM
|
||||
* only MMC3 mode
|
||||
*
|
||||
* 6000 (õõ76x210) | 0õÑ0
|
||||
* 6001 (õõõ354õõ)
|
||||
* 6002 = 0
|
||||
* 6003 = 0
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void COOLBOYCW(uint32 A, uint8 V) {
|
||||
if(EXPREGS[3] & 0x10)
|
||||
setchr8(EXPREGS[2] & 0xF);
|
||||
else {
|
||||
uint32 mask = 0xFF;
|
||||
switch(EXPREGS[0] & 0xC0) {
|
||||
case 0xC0:
|
||||
mask = 0x7F;
|
||||
break;
|
||||
}
|
||||
setchr1(A, V & mask);
|
||||
}
|
||||
}
|
||||
|
||||
static void COOLBOYPW(uint32 A, uint8 V) {
|
||||
uint32 mask, shift;
|
||||
uint32 base = ((EXPREGS[0] & 0x07) >> 0) | ((EXPREGS[1] & 0x10) >> 1) | ((EXPREGS[1] & 0x0C) << 2) | ((EXPREGS[0] & 0x30) << 2);
|
||||
switch(EXPREGS[0] & 0xC0) {
|
||||
case 0x00:
|
||||
mask = 0x3F;
|
||||
break;
|
||||
case 0x80:
|
||||
mask = 0x1F;
|
||||
break;
|
||||
case 0xC0:
|
||||
if(EXPREGS[3] & 0x10) {
|
||||
mask = 0x01 | (EXPREGS[1] & 2);
|
||||
} else {
|
||||
mask = 0x0F;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(EXPREGS[3] & 0x10)
|
||||
setprg8(A, (base << 4) | (V & mask) | ((EXPREGS[3] & (0x0E ^ (EXPREGS[1] & 2))) ));
|
||||
else
|
||||
setprg8(A, (base << 4) | (V & mask));
|
||||
}
|
||||
|
||||
static DECLFW(COOLBOYWrite) {
|
||||
if(A001B & 0x80)
|
||||
CartBW(A,V);
|
||||
else
|
||||
if((EXPREGS[3] & 0x80) == 0) {
|
||||
EXPREGS[A & 3] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
uint32 base = ((EXPREGS[0] & 0x07) >> 0) | ((EXPREGS[1] & 0x10) >> 1) | ((EXPREGS[1] & 0x0C) << 2) | ((EXPREGS[0] & 0x30) << 2);
|
||||
FCEU_printf("exp %02x %02x (base %03d)\n",A,V,base);
|
||||
}
|
||||
}
|
||||
|
||||
static void COOLBOYReset(void) {
|
||||
MMC3RegReset();
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void COOLBOYPower(void) {
|
||||
GenMMC3Power();
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
SetWriteHandler(0x5000, 0x5fff, CartBW); // some games access random unmapped areas and crashes because of KT-008 PCB hack in MMC3 source lol
|
||||
SetWriteHandler(0x6000, 0x6fff, COOLBOYWrite);
|
||||
}
|
||||
|
||||
void COOLBOY_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 128, 8, 0);
|
||||
pwrap = COOLBOYPW;
|
||||
cwrap = COOLBOYCW;
|
||||
info->Power = COOLBOYPower;
|
||||
info->Reset = COOLBOYReset;
|
||||
AddExState(EXPREGS, 4, 0, "EXPR");
|
||||
}
|
||||
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2015 CaH4e3, ClusteR
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* CoolBoy 400-in-1 FK23C-mimic mapper 16Mb/32Mb PROM + 128K/256K CHR RAM, optional SRAM, optional NTRAM
|
||||
* only MMC3 mode
|
||||
*
|
||||
* 6000 (xx76x210) | 0xC0
|
||||
* 6001 (xxx354x)
|
||||
* 6002 = 0
|
||||
* 6003 = 0
|
||||
*
|
||||
* hardware tested logic, don't try to understand lol
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void COOLBOYCW(uint32 A, uint8 V) {
|
||||
uint32 mask = 0xFF ^ (EXPREGS[0] & 0x80);
|
||||
if (EXPREGS[3] & 0x10) {
|
||||
if (EXPREGS[3] & 0x40) { // Weird mode
|
||||
int cbase = (MMC3_cmd & 0x80) << 5;
|
||||
switch (cbase ^ A) { // Don't even try do understand
|
||||
case 0x0400:
|
||||
case 0x0C00: V &= 0x7F; break;
|
||||
}
|
||||
}
|
||||
// Highest bit goes from MMC3 registers when EXPREGS[3]&0x80==0 or from EXPREGS[0]&0x08 otherwise
|
||||
setchr1(A,
|
||||
(V & 0x80 & mask) | ((((EXPREGS[0] & 0x08) << 4) & ~mask)) // 7th bit
|
||||
| ((EXPREGS[2] & 0x0F) << 3) // 6-3 bits
|
||||
| ((A >> 10) & 7) // 2-0 bits
|
||||
);
|
||||
} else {
|
||||
if (EXPREGS[3] & 0x40) { // Weird mode, again
|
||||
int cbase = (MMC3_cmd & 0x80) << 5;
|
||||
switch (cbase ^ A) { // Don't even try do understand
|
||||
case 0x0000: V = DRegBuf[0]; break;
|
||||
case 0x0800: V = DRegBuf[1]; break;
|
||||
case 0x0400:
|
||||
case 0x0C00: V = 0; break;
|
||||
}
|
||||
}
|
||||
// Simple MMC3 mode
|
||||
// Highest bit goes from MMC3 registers when EXPREGS[3]&0x80==0 or from EXPREGS[0]&0x08 otherwise
|
||||
setchr1(A, (V & mask) | (((EXPREGS[0] & 0x08) << 4) & ~mask));
|
||||
}
|
||||
}
|
||||
|
||||
static void COOLBOYPW(uint32 A, uint8 V) {
|
||||
uint32 mask = ((0x3F | (EXPREGS[1] & 0x40) | ((EXPREGS[1] & 0x20) << 2)) ^ ((EXPREGS[0] & 0x40) >> 2)) ^ ((EXPREGS[1] & 0x80) >> 2);
|
||||
uint32 base = ((EXPREGS[0] & 0x07) >> 0) | ((EXPREGS[1] & 0x10) >> 1) | ((EXPREGS[1] & 0x0C) << 2) | ((EXPREGS[0] & 0x30) << 2);
|
||||
|
||||
// Very weird mode
|
||||
// Last banks are first in this mode, ignored when MMC3_cmd&0x40
|
||||
if ((EXPREGS[3] & 0x40) && (V >= 0xFE) && !((MMC3_cmd & 0x40) != 0)) {
|
||||
switch (A & 0xE000) {
|
||||
case 0xA000:
|
||||
if ((MMC3_cmd & 0x40)) V = 0;
|
||||
break;
|
||||
case 0xC000:
|
||||
if (!(MMC3_cmd & 0x40)) V = 0;
|
||||
break;
|
||||
case 0xE000:
|
||||
V = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Regular MMC3 mode, internal ROM size can be up to 2048kb!
|
||||
if (!(EXPREGS[3] & 0x10))
|
||||
setprg8(A, (((base << 4) & ~mask)) | (V & mask));
|
||||
else { // NROM mode
|
||||
mask &= 0xF0;
|
||||
uint8 emask;
|
||||
if ((((EXPREGS[1] & 2) != 0))) // 32kb mode
|
||||
emask = (EXPREGS[3] & 0x0C) | ((A & 0x4000) >> 13);
|
||||
else // 16kb mode
|
||||
emask = EXPREGS[3] & 0x0E;
|
||||
setprg8(A, ((base << 4) & ~mask) // 7-4 bits are from base (see below)
|
||||
| (V & mask) // ... or from MM3 internal regs, depends on mask
|
||||
| emask // 3-1 (or 3-2 when (EXPREGS[3]&0x0C is set) from EXPREGS[3]
|
||||
| ((A & 0x2000) >> 13)); // 0th just as is
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(COOLBOYWrite) {
|
||||
if(A001B & 0x80)
|
||||
CartBW(A,V);
|
||||
|
||||
// Deny any further writes when 7th bit is 1 AND 4th is 0
|
||||
if ((EXPREGS[3] & 0x90) != 0x80) {
|
||||
EXPREGS[A & 3] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
@ -30,7 +30,7 @@ static void (*WSync)(void);
|
||||
static DECLFW(LatchWrite) {
|
||||
// FCEU_printf("bs %04x %02x\n",A,V);
|
||||
if (bus_conflict)
|
||||
latche = (V == CartBR(A)) ? V : 0;
|
||||
latche = V & CartBR(A);
|
||||
else
|
||||
latche = V;
|
||||
WSync();
|
||||
@ -68,15 +68,58 @@ static void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 ad
|
||||
info->Power = LatchPower;
|
||||
info->Close = LatchClose;
|
||||
GameStateRestore = StateRestore;
|
||||
if (wram) {
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
if(info->ines2)
|
||||
if(info->battery_wram_size + info->wram_size > 0)
|
||||
wram = 1;
|
||||
if (wram)
|
||||
{
|
||||
if(info->ines2)
|
||||
{
|
||||
//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(&bus_conflict, 1, 0, "BUSC");
|
||||
@ -93,7 +136,7 @@ static DECLFW(NROMWrite) {
|
||||
|
||||
static void NROMPower(void) {
|
||||
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);
|
||||
setchr8(0);
|
||||
|
||||
@ -101,7 +144,7 @@ static void NROMPower(void) {
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
|
||||
#ifdef DEBUG_MAPPER
|
||||
SetWriteHandler(0x4020, 0xFFFF, NROMWrite);
|
||||
|
@ -1,24 +1,23 @@
|
||||
#ifndef _EMU2413_H_
|
||||
#define _EMU2413_H_
|
||||
|
||||
#ifndef INLINE
|
||||
#if defined(_MSC_VER)
|
||||
#define INLINE __forceinline
|
||||
#elif defined(__GNUC__)
|
||||
#define INLINE __inline__
|
||||
#elif defined(_MWERKS_)
|
||||
#define INLINE inline
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef INLINE
|
||||
#if defined(_MSC_VER)
|
||||
#define INLINE __forceinline
|
||||
#elif defined(__GNUC__)
|
||||
#define INLINE __inline__
|
||||
#elif defined(_MWERKS_)
|
||||
#define INLINE inline
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef GEKKO
|
||||
typedef uint8_t uint8 ;
|
||||
typedef int8_t int8 ;
|
||||
|
||||
@ -27,6 +26,16 @@ typedef int16_t int16 ;
|
||||
|
||||
typedef uint32_t uint32 ;
|
||||
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
|
||||
|
||||
|
@ -70,7 +70,7 @@ static void SSSNROMPower(void) {
|
||||
regs[0] = regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0;
|
||||
regs[7] = 0xff;
|
||||
Sync();
|
||||
memset(WRAM, 0x00, WRAMSIZE);
|
||||
FCEU_MemoryRand(WRAM, WRAMSIZE, true);
|
||||
// SetWriteHandler(0x0000,0x1FFF,SSSNROMRamWrite);
|
||||
SetReadHandler(0x0800, 0x1FFF, CartBR);
|
||||
SetWriteHandler(0x0800, 0x1FFF, CartBW);
|
||||
|
@ -30,26 +30,22 @@ static uint32 CHRRAMSize;
|
||||
|
||||
static void BMCFK23CCW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&0x40)
|
||||
setchr8(EXPREGS[2]|unromchr);
|
||||
else if(EXPREGS[0]&0x20) {
|
||||
setchr1r(0x10, A, V);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16 base=(EXPREGS[2]&0x7F)<<3;
|
||||
if(EXPREGS[3]&2)
|
||||
{
|
||||
int cbase=(MMC3_cmd&0x80)<<5;
|
||||
setchr1(A,V|base);
|
||||
setchr1(0x0000^cbase,DRegBuf[0]|base);
|
||||
setchr1(0x0400^cbase,EXPREGS[6]|base);
|
||||
setchr1(0x0800^cbase,DRegBuf[1]|base);
|
||||
setchr1(0x0c00^cbase,EXPREGS[7]|base);
|
||||
}
|
||||
else
|
||||
setchr1(A,V|base);
|
||||
}
|
||||
if(EXPREGS[0]&0x40)
|
||||
setchr8(EXPREGS[2]|unromchr);
|
||||
else if(EXPREGS[0]&0x20) {
|
||||
setchr1r(0x10, A, V);
|
||||
} else {
|
||||
uint16 base=(EXPREGS[2]&0x7F)<<3;
|
||||
if(EXPREGS[3]&2) {
|
||||
int cbase=(MMC3_cmd&0x80)<<5;
|
||||
setchr1(A,V|base);
|
||||
setchr1(0x0000^cbase,DRegBuf[0]|base);
|
||||
setchr1(0x0400^cbase,EXPREGS[6]|base);
|
||||
setchr1(0x0800^cbase,DRegBuf[1]|base);
|
||||
setchr1(0x0c00^cbase,EXPREGS[7]|base);
|
||||
} else
|
||||
setchr1(A,V|base);
|
||||
}
|
||||
}
|
||||
|
||||
//some games are wired differently, and this will need to be changed.
|
||||
@ -86,110 +82,110 @@ static int prg_mask;
|
||||
//PRG wrapper
|
||||
static void BMCFK23CPW(uint32 A, uint8 V)
|
||||
{
|
||||
uint32 bank = (EXPREGS[1] & 0x1F);
|
||||
uint32 hiblock = ((EXPREGS[0] & 8) << 4)|((EXPREGS[0] & 0x80) << 1)|(UNIFchrrama?((EXPREGS[2] & 0x40)<<3):0);
|
||||
uint32 block = (EXPREGS[1] & 0x60) | hiblock;
|
||||
uint32 extra = (EXPREGS[3] & 2);
|
||||
uint32 bank = (EXPREGS[1] & 0x1F);
|
||||
uint32 hiblock = ((EXPREGS[0] & 8) << 4)|((EXPREGS[0] & 0x80) << 1)|(UNIFchrrama?((EXPREGS[2] & 0x40)<<3):0);
|
||||
uint32 block = (EXPREGS[1] & 0x60) | hiblock;
|
||||
uint32 extra = (EXPREGS[3] & 2);
|
||||
// FCEU_printf("0:%04X:%02X\n",A,V);
|
||||
|
||||
if((EXPREGS[0]&7)==4)
|
||||
setprg32(0x8000,EXPREGS[1]>>1);
|
||||
else if ((EXPREGS[0]&7)==3)
|
||||
{
|
||||
setprg16(0x8000,EXPREGS[1]);
|
||||
setprg16(0xC000,EXPREGS[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(EXPREGS[0]&3)
|
||||
{
|
||||
if((EXPREGS[0]&7)==4)
|
||||
setprg32(0x8000,EXPREGS[1]>>1);
|
||||
else if ((EXPREGS[0]&7)==3) {
|
||||
setprg16(0x8000,EXPREGS[1]);
|
||||
setprg16(0xC000,EXPREGS[1]);
|
||||
} else {
|
||||
if(EXPREGS[0]&3) {
|
||||
uint32 blocksize = (6)-(EXPREGS[0]&3);
|
||||
uint32 mask = (1<<blocksize)-1;
|
||||
V &= mask;
|
||||
//V &= 63; //? is this a good idea?
|
||||
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)
|
||||
{
|
||||
setprg8(0xC000,EXPREGS[4]);
|
||||
setprg8(0xE000,EXPREGS[5]);
|
||||
}
|
||||
}
|
||||
if(EXPREGS[3]&2) {
|
||||
setprg8(0xC000,EXPREGS[4]);
|
||||
setprg8(0xE000,EXPREGS[5]);
|
||||
}
|
||||
}
|
||||
setprg8r(0x10,0x6000,A001B&3);
|
||||
}
|
||||
|
||||
//PRG handler ($8000-$FFFF)
|
||||
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)
|
||||
unromchr=0;
|
||||
else
|
||||
{
|
||||
else {
|
||||
unromchr=V&3;
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((A==0x8001)&&(EXPREGS[3]&2&&MMC3_cmd&8))
|
||||
{
|
||||
} else {
|
||||
if((A==0x8001)&&(EXPREGS[3]&2)&&(MMC3_cmd&8)) {
|
||||
// FCEU_printf("W3:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||
EXPREGS[4|(MMC3_cmd&3)]=V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
else
|
||||
if(A<0xC000) {
|
||||
if(UNIFchrrama) { // hacky... strange behaviour, must be bit scramble due to pcb layot restrictions
|
||||
// check if it not interfer with other dumps
|
||||
if((A==0x8000)&&(V==0x46))
|
||||
V=0x47;
|
||||
else if((A==0x8000)&&(V==0x47))
|
||||
V=0x46;
|
||||
}
|
||||
MMC3_CMDWrite(A,V);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
else
|
||||
MMC3_IRQWrite(A,V);
|
||||
}
|
||||
} else
|
||||
if(A<0xC000) {
|
||||
if(UNIFchrrama) { // hacky... strange behaviour, must be bit scramble due to pcb layot restrictions
|
||||
// check if it not interfer with other dumps
|
||||
if((A==0x8000)&&(V==0x46))
|
||||
V=0x47;
|
||||
else if((A==0x8000)&&(V==0x47))
|
||||
V=0x46;
|
||||
}
|
||||
// FCEU_printf("W1:%04X:%02X\n",A,V);
|
||||
MMC3_CMDWrite(A,V);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
} else {
|
||||
MMC3_IRQWrite(A,V);
|
||||
// FCEU_printf("W4:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//EXP handler ($5000-$5FFF)
|
||||
static DECLFW(BMCFK23CWrite)
|
||||
{
|
||||
if(A&(1<<(dipswitch+4)))
|
||||
{
|
||||
if(A&(1<<(dipswitch+4))) {
|
||||
//printf("+ ");
|
||||
EXPREGS[A&3]=V;
|
||||
EXPREGS[A&3]=V;
|
||||
|
||||
// BUT WHY is there any rom that need it actually?
|
||||
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
|
||||
//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
|
||||
remap |= (A&3)==1;
|
||||
// remap |= (A&3)==1;
|
||||
//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);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
if(is_BMCFK23CA)
|
||||
{
|
||||
if(is_BMCFK23CA) {
|
||||
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);
|
||||
@ -199,62 +195,65 @@ static DECLFW(BMCFK23CWrite)
|
||||
static void BMCFK23CReset(void)
|
||||
{
|
||||
//NOT NECESSARY ANYMORE
|
||||
// BUT WHY?
|
||||
//this little hack makes sure that we try all the dip switch settings eventually, if we reset enough
|
||||
// dipswitch++;
|
||||
// dipswitch&=7;
|
||||
//printf("BMCFK23C dipswitch set to %d\n",dipswitch);
|
||||
dipswitch++;
|
||||
dipswitch&=7;
|
||||
printf("BMCFK23C dipswitch set to %d\n",dipswitch);
|
||||
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
MMC3RegReset();
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
// FCEU_printf("K0:(exp0=%02x)\n",EXPREGS[0]);
|
||||
MMC3RegReset();
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void BMCFK23CPower(void)
|
||||
{
|
||||
GenMMC3Power();
|
||||
dipswitch = 0;
|
||||
GenMMC3Power();
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
// FCEU_printf("K1:(exp0=%02x)\n",EXPREGS[0]);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||
}
|
||||
|
||||
static void BMCFK23CAPower(void)
|
||||
{
|
||||
GenMMC3Power();
|
||||
dipswitch = 0;
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
GenMMC3Power();
|
||||
dipswitch = 0;
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
// FCEU_printf("K2:(exp0=%02x)\n",EXPREGS[0]);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||
}
|
||||
|
||||
static void BMCFK23CAClose(void)
|
||||
{
|
||||
if(CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM=NULL;
|
||||
if(CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM=NULL;
|
||||
}
|
||||
|
||||
void BMCFK23C_Init(CartInfo *info)
|
||||
{
|
||||
is_BMCFK23CA = false;
|
||||
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap=BMCFK23CCW;
|
||||
pwrap=BMCFK23CPW;
|
||||
info->Power=BMCFK23CPower;
|
||||
info->Reset=BMCFK23CReset;
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap=BMCFK23CCW;
|
||||
pwrap=BMCFK23CPW;
|
||||
info->Power=BMCFK23CPower;
|
||||
info->Reset=BMCFK23CReset;
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
|
||||
prg_bonus = 1;
|
||||
if(MasterRomInfoParams.find("bonus") != MasterRomInfoParams.end())
|
||||
@ -267,21 +266,21 @@ void BMCFK23CA_Init(CartInfo *info)
|
||||
{
|
||||
is_BMCFK23CA = true;
|
||||
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap=BMCFK23CCW;
|
||||
pwrap=BMCFK23CPW;
|
||||
info->Power=BMCFK23CAPower;
|
||||
info->Reset=BMCFK23CReset;
|
||||
info->Close=BMCFK23CAClose;
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap=BMCFK23CCW;
|
||||
pwrap=BMCFK23CPW;
|
||||
info->Power=BMCFK23CAPower;
|
||||
info->Reset=BMCFK23CReset;
|
||||
info->Close=BMCFK23CAClose;
|
||||
|
||||
CHRRAMSize=8192;
|
||||
CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
|
||||
AddExState(CHRRAM, CHRRAMSize, 0, "CRAM");
|
||||
CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
|
||||
AddExState(CHRRAM, CHRRAMSize, 0, "CRAM");
|
||||
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
|
||||
prg_bonus = 1;
|
||||
if(MasterRomInfoParams.find("bonus") != MasterRomInfoParams.end())
|
||||
|
@ -18,45 +18,45 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 regs[8];
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ regs, 8, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
for (int i=0; i < 8; ++i)
|
||||
{
|
||||
setprg4(0x8000 + (0x1000 * i), regs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(M31Write) {
|
||||
if (A >= 0x5000 && A <= 0x5FFF)
|
||||
{
|
||||
regs[A&7] = V;
|
||||
Sync();
|
||||
}
|
||||
}
|
||||
|
||||
static void M31Power(void) {
|
||||
setchr8(0);
|
||||
regs[7] = 0xFF;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x5000, 0x5fff, M31Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper31_Init(CartInfo *info) {
|
||||
info->Power = M31Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 regs[8];
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ regs, 8, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
for (int i=0; i < 8; ++i)
|
||||
{
|
||||
setprg4(0x8000 + (0x1000 * i), regs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(M31Write) {
|
||||
if (A >= 0x5000 && A <= 0x5FFF)
|
||||
{
|
||||
regs[A&7] = V;
|
||||
Sync();
|
||||
}
|
||||
}
|
||||
|
||||
static void M31Power(void) {
|
||||
setchr8(0);
|
||||
regs[7] = 0xFF;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x5000, 0x5fff, M31Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper31_Init(CartInfo *info) {
|
||||
info->Power = M31Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
@ -1,85 +1,85 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2007 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 preg[4], creg, mirr;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ preg, 4, "PREG" },
|
||||
{ &creg, 1, "CREG" },
|
||||
{ &mirr, 1, "MIRR" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg8(0x6000, preg[0]);
|
||||
setprg8(0x8000, 0xa);
|
||||
setprg8(0xa000, 0xb);
|
||||
setprg8(0xc000, 0x6);
|
||||
setprg8(0xe000, 0x7);
|
||||
setchr8(0x0c);
|
||||
setmirror(mirr);
|
||||
}
|
||||
|
||||
static DECLFW(UNLKS7010Write) {
|
||||
switch (A) {
|
||||
case 0x4025: mirr = (((V >> 3) & 1) ^ 1); Sync(); break;
|
||||
default:
|
||||
FCEU_printf("bs %04x %02x\n",A,V);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void UNLKS7010Reset(void) {
|
||||
preg[0]++;
|
||||
if(preg[0] == 0x10) {
|
||||
preg[0] = 0;
|
||||
preg[1]++;
|
||||
if(preg[1] == 0x10) {
|
||||
preg[1] = 0;
|
||||
preg[2]++;
|
||||
}
|
||||
}
|
||||
FCEU_printf("preg %02x %02x %02x\n",preg[0], preg[1], preg[2]);
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void UNLKS7010Power(void) {
|
||||
preg[0] = preg[1] = preg[2] = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0x7fff, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x4020, 0xffff, UNLKS7010Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void UNLKS7010_Init(CartInfo *info) {
|
||||
info->Power = UNLKS7010Power;
|
||||
info->Reset = UNLKS7010Reset;
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2007 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 preg[4], creg, mirr;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ preg, 4, "PREG" },
|
||||
{ &creg, 1, "CREG" },
|
||||
{ &mirr, 1, "MIRR" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg8(0x6000, preg[0]);
|
||||
setprg8(0x8000, 0xa);
|
||||
setprg8(0xa000, 0xb);
|
||||
setprg8(0xc000, 0x6);
|
||||
setprg8(0xe000, 0x7);
|
||||
setchr8(0x0c);
|
||||
setmirror(mirr);
|
||||
}
|
||||
|
||||
static DECLFW(UNLKS7010Write) {
|
||||
switch (A) {
|
||||
case 0x4025: mirr = (((V >> 3) & 1) ^ 1); Sync(); break;
|
||||
default:
|
||||
FCEU_printf("bs %04x %02x\n",A,V);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void UNLKS7010Reset(void) {
|
||||
preg[0]++;
|
||||
if(preg[0] == 0x10) {
|
||||
preg[0] = 0;
|
||||
preg[1]++;
|
||||
if(preg[1] == 0x10) {
|
||||
preg[1] = 0;
|
||||
preg[2]++;
|
||||
}
|
||||
}
|
||||
FCEU_printf("preg %02x %02x %02x\n",preg[0], preg[1], preg[2]);
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void UNLKS7010Power(void) {
|
||||
preg[0] = preg[1] = preg[2] = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0x7fff, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x4020, 0xffff, UNLKS7010Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void UNLKS7010_Init(CartInfo *info) {
|
||||
info->Power = UNLKS7010Power;
|
||||
info->Reset = UNLKS7010Reset;
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ static void MALEEPower(void) {
|
||||
|
||||
void MALEE_Init(CartInfo *info) {
|
||||
info->Power = MALEEPower;
|
||||
FCEU_MemoryRand(WRAM,sizeof(WRAM),true);
|
||||
SetupCartPRGMapping(0x10, WRAM, 2048, 1);
|
||||
AddExState(WRAM, 2048, 0, "WRAM");
|
||||
}
|
||||
|
@ -1,68 +1,68 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2013 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint16 latche;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &latche, 2, "LATC" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg32(0x8000, 0);
|
||||
if(CHRsize[0] == 8192) {
|
||||
setchr4(0x0000, latche & 1);
|
||||
setchr4(0x1000, latche & 1);
|
||||
} else {
|
||||
setchr8(latche & 1); // actually, my bad, overdumped roms, the real CHR size if 8K
|
||||
}
|
||||
setmirror(MI_0 + (latche & 1));
|
||||
}
|
||||
|
||||
static DECLFW(UNLCC21Write1) {
|
||||
latche = A;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFW(UNLCC21Write2) {
|
||||
latche = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void UNLCC21Power(void) {
|
||||
latche = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
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
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void UNLCC21_Init(CartInfo *info) {
|
||||
info->Power = UNLCC21Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2013 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint16 latche;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &latche, 2, "LATC" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg32(0x8000, 0);
|
||||
if(CHRsize[0] == 8192) {
|
||||
setchr4(0x0000, latche & 1);
|
||||
setchr4(0x1000, latche & 1);
|
||||
} else {
|
||||
setchr8(latche & 1); // actually, my bad, overdumped roms, the real CHR size if 8K
|
||||
}
|
||||
setmirror(MI_0 + (latche & 1));
|
||||
}
|
||||
|
||||
static DECLFW(UNLCC21Write1) {
|
||||
latche = A;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFW(UNLCC21Write2) {
|
||||
latche = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void UNLCC21Power(void) {
|
||||
latche = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
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
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void UNLCC21_Init(CartInfo *info) {
|
||||
info->Power = UNLCC21Power;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
@ -22,12 +22,13 @@
|
||||
#include "mapinc.h"
|
||||
|
||||
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 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 (*MMC1PRGHook16)(uint32 A, uint8 V);
|
||||
@ -48,9 +49,9 @@ static DECLFR(MAWRAM) {
|
||||
}
|
||||
|
||||
static void MMC1CHR(void) {
|
||||
if (mmc1opts & 4) {
|
||||
if (DRegs[0] & 0x10)
|
||||
setprg8r(0x10, 0x6000, (DRegs[1] >> 4) & 1);
|
||||
if (WRAMSIZE > 0x2000) {
|
||||
if (WRAMSIZE > 0x4000)
|
||||
setprg8r(0x10, 0x6000, (DRegs[1] >> 2) & 3);
|
||||
else
|
||||
setprg8r(0x10, 0x6000, (DRegs[1] >> 3) & 1);
|
||||
}
|
||||
@ -73,37 +74,38 @@ static void MMC1CHR(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) {
|
||||
switch (DRegs[0] & 0xC) {
|
||||
case 0xC:
|
||||
MMC1PRGHook16(0x8000, (DRegs[3] + offs));
|
||||
MMC1PRGHook16(0xC000, 0xF + offs);
|
||||
MMC1PRGHook16(0x8000, (prg_reg + offs_16banks));
|
||||
MMC1PRGHook16(0xC000, 0xF + offs_16banks);
|
||||
break;
|
||||
case 0x8:
|
||||
MMC1PRGHook16(0xC000, (DRegs[3] + offs));
|
||||
MMC1PRGHook16(0x8000, offs);
|
||||
MMC1PRGHook16(0xC000, (prg_reg + offs_16banks));
|
||||
MMC1PRGHook16(0x8000, offs_16banks);
|
||||
break;
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
MMC1PRGHook16(0x8000, ((DRegs[3] & ~1) + offs));
|
||||
MMC1PRGHook16(0xc000, ((DRegs[3] & ~1) + offs + 1));
|
||||
MMC1PRGHook16(0x8000, ((prg_reg & ~1) + offs_16banks));
|
||||
MMC1PRGHook16(0xc000, ((prg_reg & ~1) + offs_16banks + 1));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (DRegs[0] & 0xC) {
|
||||
case 0xC:
|
||||
setprg16(0x8000, (DRegs[3] + offs));
|
||||
setprg16(0xC000, 0xF + offs);
|
||||
setprg16(0x8000, (prg_reg + offs_16banks));
|
||||
setprg16(0xC000, 0xF + offs_16banks);
|
||||
break;
|
||||
case 0x8:
|
||||
setprg16(0xC000, (DRegs[3] + offs));
|
||||
setprg16(0x8000, offs);
|
||||
setprg16(0xC000, (prg_reg + offs_16banks));
|
||||
setprg16(0x8000, offs_16banks);
|
||||
break;
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
setprg16(0x8000, ((DRegs[3] & ~1) + offs));
|
||||
setprg16(0xc000, ((DRegs[3] & ~1) + offs + 1));
|
||||
setprg16(0x8000, ((prg_reg & ~1) + offs_16banks));
|
||||
setprg16(0xc000, ((prg_reg & ~1) + offs_16banks + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -178,20 +180,39 @@ static void MMC1CMReset(void) {
|
||||
MMC1PRG();
|
||||
}
|
||||
|
||||
static int DetectMMC1WRAMSize(uint32 crc32) {
|
||||
switch (crc32) {
|
||||
static int DetectMMC1WRAMSize(CartInfo *info, int *bs) {
|
||||
int ws = 8;
|
||||
switch (info->CRC32) {
|
||||
case 0xc6182024: // Romance of the 3 Kingdoms
|
||||
case 0xabbf7217: // "" "" (J) (PRG0)
|
||||
case 0xccf35c02: // "" "" (J) (PRG1)
|
||||
case 0x2225c20f: // Genghis Khan
|
||||
case 0xfb69743a: // "" "" (J)
|
||||
case 0x4642dda6: // Nobunaga's Ambition
|
||||
case 0x29449ba9: // "" "" (J)
|
||||
case 0x2b11e0b0: // "" "" (J)
|
||||
case 0xb8747abf: // Best Play Pro Yakyuu Special (J)
|
||||
case 0xc9556b36: // Final Fantasy I & II (J) [!]
|
||||
FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n");
|
||||
return(16);
|
||||
case 0x3f7ad415: // "" "" (J) (PRG0)
|
||||
case 0x2b11e0b0: // "" "" (J) (PRG1)
|
||||
*bs = 8;
|
||||
ws = 16;
|
||||
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;
|
||||
@ -243,17 +264,16 @@ void Mapper105_Init(CartInfo *info) {
|
||||
|
||||
static void GenMMC1Power(void) {
|
||||
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);
|
||||
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);
|
||||
SetWriteHandler(0x6000, 0x7FFF, MBWRAM);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
@ -270,31 +290,24 @@ static void GenMMC1Close(void) {
|
||||
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;
|
||||
|
||||
info->Close = GenMMC1Close;
|
||||
MMC1PRGHook16 = MMC1CHRHook4 = 0;
|
||||
mmc1opts = 0;
|
||||
WRAMSIZE = wram * 1024;
|
||||
NONBRAMSIZE = (wram - bram) * 1024;
|
||||
PRGmask16[0] &= (prg >> 14) - 1;
|
||||
CHRmask4[0] &= (chr >> 12) - 1;
|
||||
CHRmask8[0] &= (chr >> 13) - 1;
|
||||
|
||||
if (wram) {
|
||||
WRAM = (uint8*)FCEU_gmalloc(wram * 1024);
|
||||
//mbg 17-jun-08 - this shouldve been cleared to re-initialize save ram
|
||||
//ch4 10-dec-08 - nope, this souldn't
|
||||
//mbg 29-mar-09 - no time to debate this, we need to keep from breaking some old stuff.
|
||||
//we really need to make up a policy for how compatibility and accuracy can be resolved.
|
||||
memset(WRAM, 0, wram * 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 (WRAMSIZE) {
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
if (bram) {
|
||||
info->SaveGame[0] = WRAM + NONBRAMSIZE;
|
||||
info->SaveGameLen[0] = bram * 1024;
|
||||
}
|
||||
}
|
||||
if (!chr) {
|
||||
@ -312,13 +325,14 @@ static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery)
|
||||
}
|
||||
|
||||
void Mapper1_Init(CartInfo *info) {
|
||||
int ws = DetectMMC1WRAMSize(info->CRC32);
|
||||
GenMMC1Init(info, 512, 256, ws, info->battery);
|
||||
int bs = info->battery ? 8 : 0;
|
||||
int ws = DetectMMC1WRAMSize(info, &bs);
|
||||
GenMMC1Init(info, 512, 256, ws, bs);
|
||||
}
|
||||
|
||||
/* Same as mapper 1, without respect for WRAM enable bit. */
|
||||
void Mapper155_Init(CartInfo *info) {
|
||||
GenMMC1Init(info, 512, 256, 8, info->battery);
|
||||
GenMMC1Init(info, 512, 256, 8, info->battery ? 8 : 0);
|
||||
is155 = 1;
|
||||
}
|
||||
|
||||
@ -330,7 +344,7 @@ void Mapper171_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) {
|
||||
@ -350,7 +364,7 @@ void SGROM_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) {
|
||||
@ -382,11 +396,9 @@ void SHROM_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) {
|
||||
GenMMC1Init(info, 256, 0, 16, info->battery);
|
||||
GenMMC1Init(info, 256, 0, 16, info->battery ? 8 : 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -279,11 +279,11 @@ void GenMMC3Power(void) {
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
}
|
||||
if (!(mmc3opts & 2))
|
||||
FCEU_dwmemset(WRAM, 0, WRAMSIZE);
|
||||
FCEU_MemoryRand(WRAM, WRAMSIZE, true);
|
||||
}
|
||||
MMC3RegReset();
|
||||
if (CHRRAM)
|
||||
FCEU_dwmemset(CHRRAM, 0, CHRRAMSIZE);
|
||||
FCEU_MemoryRand(CHRRAM, CHRRAMSIZE, true);
|
||||
}
|
||||
|
||||
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 |= EXPREGS[0] | ((EXPREGS[2] & 0xF0) << 4);
|
||||
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) {
|
||||
V &= (EXPREGS[3] & 0x3F) ^ 0x3F;
|
||||
V |= EXPREGS[1];
|
||||
setprg8(A, V);
|
||||
uint32 MV = V & ((EXPREGS[3] & 0x3F) ^ 0x3F);
|
||||
MV |= EXPREGS[1];
|
||||
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) {
|
||||
@ -534,7 +539,6 @@ static void M45Reset(void) {
|
||||
}
|
||||
|
||||
static void M45Power(void) {
|
||||
setchr8(0);
|
||||
GenMMC3Power();
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = EXPREGS[4] = EXPREGS[5] = 0;
|
||||
SetWriteHandler(0x5000, 0x7FFF, M45Write);
|
||||
@ -1039,8 +1043,8 @@ static DECLFW(Mapper196Write) {
|
||||
}
|
||||
|
||||
static DECLFW(Mapper196WriteLo) {
|
||||
EXPREGS[0] = 1;
|
||||
EXPREGS[1] = (V & 0xf) | (V >> 4);
|
||||
EXPREGS[0] = 1; // hacky
|
||||
EXPREGS[1] = (V & 0xf) | (V >> 4); // this is the same as 189 mapper, but with addr permutations
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,13 @@
|
||||
|
||||
#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 (*psfun)(void);
|
||||
|
||||
@ -107,15 +114,33 @@ typedef struct __cartdata {
|
||||
uint8 size;
|
||||
} cartdata;
|
||||
|
||||
#define Sprite16 (PPU[0]& 0x20) //Sprites 8x16/8x8
|
||||
//#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V)>>10][(V)]
|
||||
static inline uint8 * MMC5BGVRAMADR(uint32 A) {
|
||||
#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)]
|
||||
|
||||
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 (mmc5ABMode == 0)
|
||||
return &MMC5SPRVPage[(A) >> 10][(A)];
|
||||
return &ABANKS[(A) >> 10][(A)];
|
||||
else
|
||||
return &MMC5BGVPage[(A) >> 10][(A)];
|
||||
} else return &MMC5BGVPage[(A) >> 10][(A)];
|
||||
return &BBANKS[(A) >> 10][(A)];
|
||||
} else return &BBANKS[(A) >> 10][(A)];
|
||||
}
|
||||
|
||||
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) {
|
||||
if (A < 0x2000) {
|
||||
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.
|
||||
//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
|
||||
&& (PPU[1] & 0x10)
|
||||
)
|
||||
return *MMC5BGVRAMADR(A);
|
||||
else return MMC5SPRVPage[(A) >> 10][(A)];
|
||||
} else {
|
||||
extern uint32 NTRefreshAddr;
|
||||
uint8 FASTCALL mmc5_PPURead(uint32 A)
|
||||
{
|
||||
bool split = false;
|
||||
if(newppu)
|
||||
{
|
||||
if((MMC5HackSPMode&0x80) && !(MMC5HackCHRMode&2))
|
||||
{
|
||||
int target = MMC5HackSPMode&0x1f;
|
||||
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];
|
||||
}
|
||||
}
|
||||
@ -844,6 +958,12 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
|
||||
MMC5fill = (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(&MMC5HackSPMode, 1, 0, "SPLM");
|
||||
AddExState(&MMC5HackSPScroll, 1, 0, "SPLS");
|
||||
@ -858,8 +978,13 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
|
||||
|
||||
if (battery) {
|
||||
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)
|
||||
info->SaveGameLen[0] = 8192;
|
||||
else if(wsize == 64)
|
||||
info->SaveGameLen[0] = 64*1024;
|
||||
else
|
||||
info->SaveGameLen[0] = 32768;
|
||||
}
|
||||
|
@ -57,9 +57,23 @@ static SFORMAT N106_StateRegs[] = {
|
||||
{ PRG, 3, "PRG" },
|
||||
{ CHR, 8, "CHR" },
|
||||
{ NTAPage, 4, "NTA" },
|
||||
{ &gorfus, 1, "GORF" },
|
||||
{ &dopol, 1, "DOPO" },
|
||||
{ &gorko, 1, "GORK" },
|
||||
{ 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) {
|
||||
setprg8(0x8000, PRG[0]);
|
||||
setprg8(0xa000, PRG[1]);
|
||||
@ -179,8 +193,11 @@ static DECLFW(Mapper19_write) {
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 0xE000:
|
||||
gorko = V & 0xC0;
|
||||
PRG[0] = V & 0x3F;
|
||||
if(is210) {
|
||||
gorko = V>>6;
|
||||
SyncMirror();
|
||||
}
|
||||
SyncPRG();
|
||||
break;
|
||||
case 0xE800:
|
||||
@ -333,6 +350,7 @@ static void Mapper19_StateRestore(int version) {
|
||||
SyncPRG();
|
||||
FixNTAR();
|
||||
FixCRR();
|
||||
SyncMirror();
|
||||
int x;
|
||||
for (x = 0x40; x < 0x80; x++)
|
||||
FixCache(x, IRAM[x]);
|
||||
@ -382,8 +400,8 @@ static void N106_Power(void) {
|
||||
FixCRR();
|
||||
|
||||
if (!battery) {
|
||||
FCEU_dwmemset(WRAM, 0, 8192);
|
||||
FCEU_dwmemset(IRAM, 0, 128);
|
||||
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
|
||||
FCEU_MemoryRand(IRAM, sizeof(IRAM), true);
|
||||
}
|
||||
for (x = 0x40; x < 0x80; x++)
|
||||
FixCache(x, IRAM[x]);
|
||||
@ -401,6 +419,8 @@ void Mapper19_Init(CartInfo *info) {
|
||||
if (FSettings.SndRate)
|
||||
Mapper19_ESI();
|
||||
|
||||
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
|
||||
FCEU_MemoryRand(IRAM, sizeof(IRAM), true);
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(IRAM, 128, 0, "IRAM");
|
||||
AddExState(N106_StateRegs, ~0, 0, 0);
|
||||
@ -422,6 +442,7 @@ void Mapper210_Init(CartInfo *info) {
|
||||
is210 = 1;
|
||||
GameStateRestore = Mapper210_StateRestore;
|
||||
info->Power = N106_Power;
|
||||
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(N106_StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ static void CSync(void) {
|
||||
setchr1(0x1800 ^ cswap, block | (bank6 & mask));
|
||||
setchr1(0x1c00 ^ cswap, block | (bank7 & mask));
|
||||
|
||||
setmirror(mirror & 1);
|
||||
setmirror((mirror ^ 1) & 1);
|
||||
}
|
||||
|
||||
static void Sync(void) {
|
||||
@ -158,7 +158,7 @@ static DECLFW(UNLOneBusWriteMMC3) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0xa000: mirror = V ^ 1; CSync(); break;
|
||||
case 0xa000: mirror = V; CSync(); break;
|
||||
case 0xc000: IRQLatch = V & 0xfe; break;
|
||||
case 0xc001: IRQReload = 1; break;
|
||||
case 0xe000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break;
|
||||
|
@ -1,195 +1,195 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2014 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 preg[8];
|
||||
static uint8 IRQa;
|
||||
static int16 IRQCount, IRQLatch;
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
/*
|
||||
static uint8 *CHRRAM = NULL;
|
||||
static uint32 CHRRAMSIZE;
|
||||
*/
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ preg, 8, "PREG" },
|
||||
{ &IRQa, 1, "IRQA" },
|
||||
{ &IRQCount, 2, "IRQC" },
|
||||
{ &IRQLatch, 2, "IRQL" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setchr8(0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
if(preg[0] & 0x80)
|
||||
setprg4r(0x10,0x8000,preg[0] & 0x7f);
|
||||
else
|
||||
setprg4(0x8000,preg[0] & 0x7f);
|
||||
if(preg[1] & 0x80)
|
||||
setprg4r(0x10,0x9000,preg[1] & 0x7f);
|
||||
else
|
||||
setprg4(0x9000,preg[1] & 0x7f);
|
||||
if(preg[2] & 0x80)
|
||||
setprg4r(0x10,0xa000,preg[2] & 0x7f);
|
||||
else
|
||||
setprg4(0xa000,preg[2] & 0x7f);
|
||||
if(preg[3] & 0x80)
|
||||
setprg4r(0x10,0xb000,preg[3] & 0x7f);
|
||||
else
|
||||
setprg4(0xb000,preg[3] & 0x7f);
|
||||
/*
|
||||
if(preg[4] & 0x80)
|
||||
setprg4r(0x10,0xc000,preg[4] & 0x7f);
|
||||
else
|
||||
setprg4(0xc000,preg[4] & 0x7f);
|
||||
if(preg[5] & 0x80)
|
||||
setprg4r(0x10,0xd000,preg[5] & 0x7f);
|
||||
else
|
||||
setprg4(0xd000,preg[5] & 0x7f);
|
||||
if(preg[6] & 0x80)
|
||||
setprg4r(0x10,0xe000,preg[6] & 0x7f);
|
||||
else
|
||||
setprg4(0xe000,preg[6] & 0x7f);
|
||||
if(preg[7] & 0x80)
|
||||
setprg4r(0x10,0xf000,preg[7] & 0x7f);
|
||||
else
|
||||
setprg4(0xf000,preg[7] & 0x7f);
|
||||
*/
|
||||
setprg16(0xC000,1);
|
||||
}
|
||||
|
||||
static DECLFR(UNLSB2000Read) {
|
||||
switch(A) {
|
||||
case 0x4033: // IRQ flags
|
||||
X6502_IRQEnd(FCEU_IQFCOUNT);
|
||||
return 0xff;
|
||||
// case 0x4204: // unk
|
||||
// return 0xff;
|
||||
// case 0x4205: // unk
|
||||
// return 0xff;
|
||||
default:
|
||||
FCEU_printf("unk read: %04x\n",A);
|
||||
// break;
|
||||
return 0xff; // needed to prevent C4715 warning?
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(UNLSB2000Write) {
|
||||
switch(A) {
|
||||
case 0x4027: // PCM output
|
||||
BWrite[0x4015](0x4015, 0x10);
|
||||
BWrite[0x4011](0x4011, V >> 1);
|
||||
break;
|
||||
case 0x4032: // IRQ mask
|
||||
IRQa &= ~V;
|
||||
// X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 0x4040:
|
||||
case 0x4041:
|
||||
case 0x4042:
|
||||
case 0x4043:
|
||||
case 0x4044:
|
||||
case 0x4045:
|
||||
case 0x4046:
|
||||
case 0x4047:
|
||||
// FCEU_printf("bank write: %04x:%02x\n",A,V);
|
||||
preg[A&7] = V;
|
||||
Sync();
|
||||
break;
|
||||
default:
|
||||
// FCEU_printf("unk write: %04x:%02x\n",A,V);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void UNLSB2000Reset(void) {
|
||||
preg[0] = 0;
|
||||
preg[1] = 1;
|
||||
preg[2] = 2;
|
||||
preg[3] = 3;
|
||||
preg[4] = 4;
|
||||
preg[5] = 5;
|
||||
preg[6] = 6;
|
||||
preg[7] = 7;
|
||||
IRQa = 0;
|
||||
// BWrite[0x4017](0x4017,0xC0);
|
||||
// BWrite[0x4015](0x4015,0x1F);
|
||||
}
|
||||
|
||||
static void UNLSB2000Power(void) {
|
||||
UNLSB2000Reset();
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0x7fff, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x8000, 0xbfff, CartBW);
|
||||
SetWriteHandler(0x4020, 0x5fff, UNLSB2000Write);
|
||||
SetReadHandler(0x4020, 0x5fff, UNLSB2000Read);
|
||||
}
|
||||
|
||||
static void UNLSB2000Close(void)
|
||||
{
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
/*
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
*/
|
||||
WRAM = /*CHRRAM = */NULL;
|
||||
}
|
||||
/*
|
||||
static void UNLSB2000IRQHook() {
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
*/
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void UNLSB2000_Init(CartInfo *info) {
|
||||
info->Reset = UNLSB2000Reset;
|
||||
info->Power = UNLSB2000Power;
|
||||
info->Close = UNLSB2000Close;
|
||||
// GameHBIRQHook = UNLSB2000IRQHook;
|
||||
GameStateRestore = StateRestore;
|
||||
/*
|
||||
CHRRAMSIZE = 8192;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM");
|
||||
*/
|
||||
|
||||
// SetupCartCHRMapping(0, PRGptr[0], PRGsize[0], 0);
|
||||
|
||||
WRAMSIZE = 512 * 1024;
|
||||
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;
|
||||
}
|
||||
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2014 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 preg[8];
|
||||
static uint8 IRQa;
|
||||
static int16 IRQCount, IRQLatch;
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
/*
|
||||
static uint8 *CHRRAM = NULL;
|
||||
static uint32 CHRRAMSIZE;
|
||||
*/
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ preg, 8, "PREG" },
|
||||
{ &IRQa, 1, "IRQA" },
|
||||
{ &IRQCount, 2, "IRQC" },
|
||||
{ &IRQLatch, 2, "IRQL" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setchr8(0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
if(preg[0] & 0x80)
|
||||
setprg4r(0x10,0x8000,preg[0] & 0x7f);
|
||||
else
|
||||
setprg4(0x8000,preg[0] & 0x7f);
|
||||
if(preg[1] & 0x80)
|
||||
setprg4r(0x10,0x9000,preg[1] & 0x7f);
|
||||
else
|
||||
setprg4(0x9000,preg[1] & 0x7f);
|
||||
if(preg[2] & 0x80)
|
||||
setprg4r(0x10,0xa000,preg[2] & 0x7f);
|
||||
else
|
||||
setprg4(0xa000,preg[2] & 0x7f);
|
||||
if(preg[3] & 0x80)
|
||||
setprg4r(0x10,0xb000,preg[3] & 0x7f);
|
||||
else
|
||||
setprg4(0xb000,preg[3] & 0x7f);
|
||||
/*
|
||||
if(preg[4] & 0x80)
|
||||
setprg4r(0x10,0xc000,preg[4] & 0x7f);
|
||||
else
|
||||
setprg4(0xc000,preg[4] & 0x7f);
|
||||
if(preg[5] & 0x80)
|
||||
setprg4r(0x10,0xd000,preg[5] & 0x7f);
|
||||
else
|
||||
setprg4(0xd000,preg[5] & 0x7f);
|
||||
if(preg[6] & 0x80)
|
||||
setprg4r(0x10,0xe000,preg[6] & 0x7f);
|
||||
else
|
||||
setprg4(0xe000,preg[6] & 0x7f);
|
||||
if(preg[7] & 0x80)
|
||||
setprg4r(0x10,0xf000,preg[7] & 0x7f);
|
||||
else
|
||||
setprg4(0xf000,preg[7] & 0x7f);
|
||||
*/
|
||||
setprg16(0xC000,1);
|
||||
}
|
||||
|
||||
static DECLFR(UNLSB2000Read) {
|
||||
switch(A) {
|
||||
case 0x4033: // IRQ flags
|
||||
X6502_IRQEnd(FCEU_IQFCOUNT);
|
||||
return 0xff;
|
||||
// case 0x4204: // unk
|
||||
// return 0xff;
|
||||
// case 0x4205: // unk
|
||||
// return 0xff;
|
||||
default:
|
||||
FCEU_printf("unk read: %04x\n",A);
|
||||
// break;
|
||||
return 0xff; // needed to prevent C4715 warning?
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(UNLSB2000Write) {
|
||||
switch(A) {
|
||||
case 0x4027: // PCM output
|
||||
BWrite[0x4015](0x4015, 0x10);
|
||||
BWrite[0x4011](0x4011, V >> 1);
|
||||
break;
|
||||
case 0x4032: // IRQ mask
|
||||
IRQa &= ~V;
|
||||
// X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 0x4040:
|
||||
case 0x4041:
|
||||
case 0x4042:
|
||||
case 0x4043:
|
||||
case 0x4044:
|
||||
case 0x4045:
|
||||
case 0x4046:
|
||||
case 0x4047:
|
||||
// FCEU_printf("bank write: %04x:%02x\n",A,V);
|
||||
preg[A&7] = V;
|
||||
Sync();
|
||||
break;
|
||||
default:
|
||||
// FCEU_printf("unk write: %04x:%02x\n",A,V);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void UNLSB2000Reset(void) {
|
||||
preg[0] = 0;
|
||||
preg[1] = 1;
|
||||
preg[2] = 2;
|
||||
preg[3] = 3;
|
||||
preg[4] = 4;
|
||||
preg[5] = 5;
|
||||
preg[6] = 6;
|
||||
preg[7] = 7;
|
||||
IRQa = 0;
|
||||
// BWrite[0x4017](0x4017,0xC0);
|
||||
// BWrite[0x4015](0x4015,0x1F);
|
||||
}
|
||||
|
||||
static void UNLSB2000Power(void) {
|
||||
UNLSB2000Reset();
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0x7fff, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x8000, 0xbfff, CartBW);
|
||||
SetWriteHandler(0x4020, 0x5fff, UNLSB2000Write);
|
||||
SetReadHandler(0x4020, 0x5fff, UNLSB2000Read);
|
||||
}
|
||||
|
||||
static void UNLSB2000Close(void)
|
||||
{
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
/*
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
*/
|
||||
WRAM = /*CHRRAM = */NULL;
|
||||
}
|
||||
/*
|
||||
static void UNLSB2000IRQHook() {
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
*/
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void UNLSB2000_Init(CartInfo *info) {
|
||||
info->Reset = UNLSB2000Reset;
|
||||
info->Power = UNLSB2000Power;
|
||||
info->Close = UNLSB2000Close;
|
||||
// GameHBIRQHook = UNLSB2000IRQHook;
|
||||
GameStateRestore = StateRestore;
|
||||
/*
|
||||
CHRRAMSIZE = 8192;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM");
|
||||
*/
|
||||
|
||||
// SetupCartCHRMapping(0, PRGptr[0], PRGsize[0], 0);
|
||||
|
||||
WRAMSIZE = 512 * 1024;
|
||||
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;
|
||||
}
|
||||
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
@ -1,52 +1,52 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2014 CaitSith2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 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 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:
|
||||
* 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)
|
||||
* Although Xmas 2013 uses a different board, where LEDs can be controlled (with writes to the $8000-BFFF space),
|
||||
* it otherwise functions identically.
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "../ines.h"
|
||||
|
||||
static uint8 latche, latcheinit, bus_conflict, chrram_mask, software_id=false;
|
||||
static uint16 latcha;
|
||||
static uint8 *flashdata;
|
||||
static uint32 *flash_write_count;
|
||||
static uint8 *FlashPage[32];
|
||||
static uint32 *FlashWriteCountPage[32];
|
||||
static uint8 flashloaded = false;
|
||||
|
||||
static uint8 flash_save=0, flash_state=0, flash_mode=0, flash_bank;
|
||||
static void (*WLSync)(void);
|
||||
static void (*WHSync)(void);
|
||||
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2014 CaitSith2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 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 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:
|
||||
* 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)
|
||||
* Although Xmas 2013 uses a different board, where LEDs can be controlled (with writes to the $8000-BFFF space),
|
||||
* it otherwise functions identically.
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "../ines.h"
|
||||
|
||||
static uint8 latche, latcheinit, bus_conflict, chrram_mask, software_id=false;
|
||||
static uint16 latcha;
|
||||
static uint8 *flashdata;
|
||||
static uint32 *flash_write_count;
|
||||
static uint8 *FlashPage[32];
|
||||
static uint32 *FlashWriteCountPage[32];
|
||||
static uint8 flashloaded = false;
|
||||
|
||||
static uint8 flash_save=0, flash_state=0, flash_mode=0, flash_bank;
|
||||
static void (*WLSync)(void);
|
||||
static void (*WHSync)(void);
|
||||
|
||||
static INLINE void setfpageptr(int s, uint32 A, uint8 *p) {
|
||||
uint32 AB = A >> 11;
|
||||
int x;
|
||||
@ -59,8 +59,8 @@ static INLINE void setfpageptr(int s, uint32 A, uint8 *p) {
|
||||
for (x = (s >> 1) - 1; x >= 0; x--) {
|
||||
FlashPage[AB + x] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void setfprg16(uint32 A, uint32 V) {
|
||||
if (PRGsize[0] >= 16384) {
|
||||
V &= PRGmask16[0];
|
||||
@ -72,198 +72,214 @@ void setfprg16(uint32 A, uint32 V) {
|
||||
for (x = 0; x < 8; x++)
|
||||
setfpageptr(2, A + (x << 11), flashdata ? (&flashdata[((VA + x) & PRGmask2[0]) << 11]) : 0);
|
||||
}
|
||||
}
|
||||
|
||||
void inc_flash_write_count(uint8 bank, uint32 A)
|
||||
{
|
||||
flash_write_count[(bank*4) + ((A&0x3000)>>12)]++;
|
||||
if(!flash_write_count[(bank*4) + ((A&0x3000)>>12)])
|
||||
flash_write_count[(bank*4) + ((A&0x3000)>>12)]++;
|
||||
}
|
||||
|
||||
uint32 GetFlashWriteCount(uint8 bank, uint32 A)
|
||||
{
|
||||
return flash_write_count[(bank*4) + ((A&0x3000)>>12)];
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
WHSync();
|
||||
}
|
||||
|
||||
static DECLFW(UNROM512LLatchWrite)
|
||||
{
|
||||
latche = V;
|
||||
latcha = A;
|
||||
WLSync();
|
||||
}
|
||||
|
||||
static DECLFW(UNROM512HLatchWrite)
|
||||
{
|
||||
if (bus_conflict)
|
||||
latche = (V == CartBR(A)) ? V : 0;
|
||||
else
|
||||
latche = V;
|
||||
latcha = A;
|
||||
WHSync();
|
||||
}
|
||||
|
||||
static DECLFR(UNROM512LatchRead)
|
||||
{
|
||||
uint8 flash_id[3]={0xB5,0xB6,0xB7};
|
||||
if(software_id)
|
||||
{
|
||||
if(A&1)
|
||||
return flash_id[ROM_size>>4];
|
||||
else
|
||||
return 0xBF;
|
||||
}
|
||||
if(flash_save)
|
||||
{
|
||||
if(A < 0xC000)
|
||||
{
|
||||
if(GetFlashWriteCount(flash_bank,A))
|
||||
return FlashPage[A >> 11][A];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(GetFlashWriteCount(ROM_size-1,A))
|
||||
return FlashPage[A >> 11][A];
|
||||
}
|
||||
}
|
||||
return Page[A >> 11][A];
|
||||
}
|
||||
|
||||
static void UNROM512LatchPower(void) {
|
||||
latche = latcheinit;
|
||||
WHSync();
|
||||
SetReadHandler(0x8000, 0xFFFF, UNROM512LatchRead);
|
||||
if(!flash_save)
|
||||
SetWriteHandler(0x8000, 0xFFFF, UNROM512HLatchWrite);
|
||||
else
|
||||
{
|
||||
SetWriteHandler(0x8000,0xBFFF,UNROM512LLatchWrite);
|
||||
SetWriteHandler(0xC000,0xFFFF,UNROM512HLatchWrite);
|
||||
}
|
||||
}
|
||||
|
||||
static void UNROM512LatchClose(void) {
|
||||
if(flash_write_count)
|
||||
FCEU_gfree(flash_write_count);
|
||||
if(flashdata)
|
||||
FCEU_gfree(flashdata);
|
||||
flash_write_count = NULL;
|
||||
flashdata = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void UNROM512LSync() {
|
||||
int erase_a[5]={0x9555,0xAAAA,0x9555,0x9555,0xAAAA};
|
||||
int erase_d[5]={0xAA,0x55,0x80,0xAA,0x55};
|
||||
int erase_b[5]={1,0,1,1,0};
|
||||
|
||||
if(flash_mode==0)
|
||||
{
|
||||
if((latcha == erase_a[flash_state]) && (latche == erase_d[flash_state]) && (flash_bank == erase_b[flash_state]))
|
||||
{
|
||||
flash_state++;
|
||||
if(flash_state == 5)
|
||||
{
|
||||
flash_mode=1;
|
||||
}
|
||||
}
|
||||
else if ((flash_state==2)&&(latcha==0x9555)&&(latche==0xA0)&&(flash_bank==1))
|
||||
{
|
||||
flash_state++;
|
||||
flash_mode=2;
|
||||
}
|
||||
else if ((flash_state==2)&&(latcha==0x9555)&&(latche==0x90)&&(flash_bank==1))
|
||||
{
|
||||
flash_state=0;
|
||||
software_id=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(latche==0xF0)
|
||||
software_id=false;
|
||||
flash_state=0;
|
||||
}
|
||||
}
|
||||
else if(flash_mode==1) //Chip Erase or Sector Erase
|
||||
{
|
||||
if(latche==0x30)
|
||||
{
|
||||
inc_flash_write_count(flash_bank,latcha);
|
||||
memset(&FlashPage[(latcha & 0xF000) >> 11][latcha & 0xF000],0xFF,0x1000);
|
||||
}
|
||||
else if (latche==0x10)
|
||||
{
|
||||
for(int i=0;i<(ROM_size*4);i++)
|
||||
inc_flash_write_count(i>>2,i<<12);
|
||||
memset(flashdata,0xFF,ROM_size*0x4000); //Erasing the rom chip as instructed. Crash rate calulated to be 99.9% :)
|
||||
}
|
||||
flash_state=0;
|
||||
flash_mode=0;
|
||||
}
|
||||
else if(flash_mode==2) //Byte Program
|
||||
{
|
||||
if(!GetFlashWriteCount(flash_bank,latcha))
|
||||
{
|
||||
inc_flash_write_count(flash_bank,latcha);
|
||||
memcpy(&FlashPage[(latcha & 0xF000) >> 11][latcha & 0xF000],&Page[(latcha & 0xF000)>>11][latcha & 0xF000],0x1000);
|
||||
}
|
||||
FlashPage[latcha>>11][latcha]&=latche;
|
||||
flash_state=0;
|
||||
flash_mode=0;
|
||||
}
|
||||
}
|
||||
|
||||
static void UNROM512HSync()
|
||||
{
|
||||
flash_bank=latche&(ROM_size-1);
|
||||
|
||||
setprg16(0x8000, flash_bank);
|
||||
setprg16(0xc000, ~0);
|
||||
setfprg16(0x8000, flash_bank);
|
||||
setfprg16(0xC000, ~0);
|
||||
setchr8r(0, (latche & chrram_mask) >> 5);
|
||||
setmirror(MI_0+(latche>>7));
|
||||
}
|
||||
|
||||
void UNROM512_Init(CartInfo *info) {
|
||||
flash_state=0;
|
||||
flash_bank=0;
|
||||
flash_save=info->battery;
|
||||
|
||||
if(info->vram_size == 8192)
|
||||
chrram_mask = 0;
|
||||
else if (info->vram_size == 16384)
|
||||
chrram_mask = 0x20;
|
||||
else
|
||||
chrram_mask = 0x60;
|
||||
|
||||
SetupCartMirroring(info->mirror,(info->mirror>=MI_0)?0:1,0);
|
||||
bus_conflict = !info->battery;
|
||||
latcheinit = 0;
|
||||
WLSync = UNROM512LSync;
|
||||
WHSync = UNROM512HSync;
|
||||
info->Power = UNROM512LatchPower;
|
||||
info->Close = UNROM512LatchClose;
|
||||
GameStateRestore = StateRestore;
|
||||
if(flash_save)
|
||||
{
|
||||
flashdata = (uint8*)FCEU_gmalloc(ROM_size*0x4000);
|
||||
flash_write_count = (uint32*)FCEU_gmalloc(ROM_size*4*sizeof(uint32));
|
||||
info->SaveGame[0] = (uint8*)flash_write_count;
|
||||
info->SaveGame[1] = flashdata;
|
||||
info->SaveGameLen[0] = ROM_size*4*sizeof(uint32);
|
||||
info->SaveGameLen[1] = ROM_size*0x4000;
|
||||
AddExState(flash_write_count,ROM_size*4*sizeof(uint32),0,"FLASH_WRITE_COUNT");
|
||||
AddExState(flashdata,ROM_size*0x4000,0,"FLASH_DATA");
|
||||
AddExState(&flash_state,1,0,"FLASH_STATE");
|
||||
AddExState(&flash_mode,1,0,"FLASH_MODE");
|
||||
AddExState(&flash_bank,1,0,"FLASH_BANK");
|
||||
AddExState(&latcha,2,0,"LATA");
|
||||
}
|
||||
AddExState(&latche, 1, 0, "LATC");
|
||||
AddExState(&bus_conflict, 1, 0, "BUSC");
|
||||
}
|
||||
|
||||
void inc_flash_write_count(uint8 bank, uint32 A)
|
||||
{
|
||||
flash_write_count[(bank*4) + ((A&0x3000)>>12)]++;
|
||||
if(!flash_write_count[(bank*4) + ((A&0x3000)>>12)])
|
||||
flash_write_count[(bank*4) + ((A&0x3000)>>12)]++;
|
||||
}
|
||||
|
||||
uint32 GetFlashWriteCount(uint8 bank, uint32 A)
|
||||
{
|
||||
return flash_write_count[(bank*4) + ((A&0x3000)>>12)];
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
WHSync();
|
||||
}
|
||||
|
||||
static DECLFW(UNROM512LLatchWrite)
|
||||
{
|
||||
latche = V;
|
||||
latcha = A;
|
||||
WLSync();
|
||||
}
|
||||
|
||||
static DECLFW(UNROM512HLatchWrite)
|
||||
{
|
||||
if (bus_conflict)
|
||||
latche = (V == CartBR(A)) ? V : 0;
|
||||
else
|
||||
latche = V;
|
||||
latcha = A;
|
||||
WHSync();
|
||||
}
|
||||
|
||||
static DECLFR(UNROM512LatchRead)
|
||||
{
|
||||
uint8 flash_id[3]={0xB5,0xB6,0xB7};
|
||||
if(software_id)
|
||||
{
|
||||
if(A&1)
|
||||
return flash_id[ROM_size>>4];
|
||||
else
|
||||
return 0xBF;
|
||||
}
|
||||
if(flash_save)
|
||||
{
|
||||
if(A < 0xC000)
|
||||
{
|
||||
if(GetFlashWriteCount(flash_bank,A))
|
||||
return FlashPage[A >> 11][A];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(GetFlashWriteCount(ROM_size-1,A))
|
||||
return FlashPage[A >> 11][A];
|
||||
}
|
||||
}
|
||||
return Page[A >> 11][A];
|
||||
}
|
||||
|
||||
static void UNROM512LatchPower(void) {
|
||||
latche = latcheinit;
|
||||
WHSync();
|
||||
SetReadHandler(0x8000, 0xFFFF, UNROM512LatchRead);
|
||||
if(!flash_save)
|
||||
SetWriteHandler(0x8000, 0xFFFF, UNROM512HLatchWrite);
|
||||
else
|
||||
{
|
||||
SetWriteHandler(0x8000,0xBFFF,UNROM512LLatchWrite);
|
||||
SetWriteHandler(0xC000,0xFFFF,UNROM512HLatchWrite);
|
||||
}
|
||||
}
|
||||
|
||||
static void UNROM512LatchClose(void) {
|
||||
if(flash_write_count)
|
||||
FCEU_gfree(flash_write_count);
|
||||
if(flashdata)
|
||||
FCEU_gfree(flashdata);
|
||||
flash_write_count = NULL;
|
||||
flashdata = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void UNROM512LSync() {
|
||||
int erase_a[5]={0x9555,0xAAAA,0x9555,0x9555,0xAAAA};
|
||||
int erase_d[5]={0xAA,0x55,0x80,0xAA,0x55};
|
||||
int erase_b[5]={1,0,1,1,0};
|
||||
|
||||
if(flash_mode==0)
|
||||
{
|
||||
if((latcha == erase_a[flash_state]) && (latche == erase_d[flash_state]) && (flash_bank == erase_b[flash_state]))
|
||||
{
|
||||
flash_state++;
|
||||
if(flash_state == 5)
|
||||
{
|
||||
flash_mode=1;
|
||||
}
|
||||
}
|
||||
else if ((flash_state==2)&&(latcha==0x9555)&&(latche==0xA0)&&(flash_bank==1))
|
||||
{
|
||||
flash_state++;
|
||||
flash_mode=2;
|
||||
}
|
||||
else if ((flash_state==2)&&(latcha==0x9555)&&(latche==0x90)&&(flash_bank==1))
|
||||
{
|
||||
flash_state=0;
|
||||
software_id=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(latche==0xF0)
|
||||
software_id=false;
|
||||
flash_state=0;
|
||||
}
|
||||
}
|
||||
else if(flash_mode==1) //Chip Erase or Sector Erase
|
||||
{
|
||||
if(latche==0x30)
|
||||
{
|
||||
inc_flash_write_count(flash_bank,latcha);
|
||||
memset(&FlashPage[(latcha & 0xF000) >> 11][latcha & 0xF000],0xFF,0x1000);
|
||||
}
|
||||
else if (latche==0x10)
|
||||
{
|
||||
for(uint32 i=0;i<(ROM_size*4);i++)
|
||||
inc_flash_write_count(i>>2,i<<12);
|
||||
memset(flashdata,0xFF,ROM_size*0x4000); //Erasing the rom chip as instructed. Crash rate calulated to be 99.9% :)
|
||||
}
|
||||
flash_state=0;
|
||||
flash_mode=0;
|
||||
}
|
||||
else if(flash_mode==2) //Byte Program
|
||||
{
|
||||
if(!GetFlashWriteCount(flash_bank,latcha))
|
||||
{
|
||||
inc_flash_write_count(flash_bank,latcha);
|
||||
memcpy(&FlashPage[(latcha & 0xF000) >> 11][latcha & 0xF000],&Page[(latcha & 0xF000)>>11][latcha & 0xF000],0x1000);
|
||||
}
|
||||
FlashPage[latcha>>11][latcha]&=latche;
|
||||
flash_state=0;
|
||||
flash_mode=0;
|
||||
}
|
||||
}
|
||||
|
||||
static void UNROM512HSync()
|
||||
{
|
||||
flash_bank=latche&(ROM_size-1);
|
||||
|
||||
setprg16(0x8000, flash_bank);
|
||||
setprg16(0xc000, ~0);
|
||||
setfprg16(0x8000, flash_bank);
|
||||
setfprg16(0xC000, ~0);
|
||||
setchr8r(0, (latche & chrram_mask) >> 5);
|
||||
setmirror(MI_0+(latche>>7));
|
||||
}
|
||||
|
||||
void UNROM512_Init(CartInfo *info) {
|
||||
flash_state=0;
|
||||
flash_bank=0;
|
||||
flash_save=info->battery;
|
||||
|
||||
if(info->vram_size == 8192)
|
||||
chrram_mask = 0;
|
||||
else if (info->vram_size == 16384)
|
||||
chrram_mask = 0x20;
|
||||
else
|
||||
chrram_mask = 0x60;
|
||||
|
||||
int mirror = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2);
|
||||
switch (mirror)
|
||||
{
|
||||
case 0: // hard horizontal, internal
|
||||
SetupCartMirroring(MI_H, 1, NULL);
|
||||
break;
|
||||
case 1: // hard vertical, internal
|
||||
SetupCartMirroring(MI_V, 1, NULL);
|
||||
break;
|
||||
case 2: // switchable 1-screen, internal (flags: 4-screen + horizontal)
|
||||
SetupCartMirroring(MI_0, 0, NULL);
|
||||
break;
|
||||
case 3: // hard four screen, last 8k of 32k RAM (flags: 4-screen + vertical)
|
||||
SetupCartMirroring( 4, 1, VROM + (info->vram_size - 8192));
|
||||
break;
|
||||
}
|
||||
|
||||
bus_conflict = !info->battery;
|
||||
latcheinit = 0;
|
||||
WLSync = UNROM512LSync;
|
||||
WHSync = UNROM512HSync;
|
||||
info->Power = UNROM512LatchPower;
|
||||
info->Close = UNROM512LatchClose;
|
||||
GameStateRestore = StateRestore;
|
||||
if(flash_save)
|
||||
{
|
||||
flashdata = (uint8*)FCEU_gmalloc(ROM_size*0x4000);
|
||||
flash_write_count = (uint32*)FCEU_gmalloc(ROM_size*4*sizeof(uint32));
|
||||
info->SaveGame[0] = (uint8*)flash_write_count;
|
||||
info->SaveGame[1] = flashdata;
|
||||
info->SaveGameLen[0] = ROM_size*4*sizeof(uint32);
|
||||
info->SaveGameLen[1] = ROM_size*0x4000;
|
||||
AddExState(flash_write_count,ROM_size*4*sizeof(uint32),0,"FLASH_WRITE_COUNT");
|
||||
AddExState(flashdata,ROM_size*0x4000,0,"FLASH_DATA");
|
||||
AddExState(&flash_state,1,0,"FLASH_STATE");
|
||||
AddExState(&flash_mode,1,0,"FLASH_MODE");
|
||||
AddExState(&flash_bank,1,0,"FLASH_BANK");
|
||||
AddExState(&latcha,2,0,"LATA");
|
||||
}
|
||||
AddExState(&latche, 1, 0, "LATC");
|
||||
AddExState(&bus_conflict, 1, 0, "BUSC");
|
||||
}
|
@ -20,7 +20,8 @@
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 isPirate, is22;
|
||||
static bool isPirate;
|
||||
static uint8 is22, reg1mask, reg2mask;
|
||||
static uint16 IRQCount;
|
||||
static uint8 IRQLatch, IRQa;
|
||||
static uint8 prgreg[2], chrreg[8];
|
||||
@ -61,15 +62,15 @@ static void Sync(void) {
|
||||
setchr8(0);
|
||||
else{
|
||||
uint8 i;
|
||||
if(!weirdo)
|
||||
//if(!weirdo)
|
||||
for (i = 0; i < 8; i++)
|
||||
setchr1(i << 10, (chrhi[i] | chrreg[i]) >> is22);
|
||||
else {
|
||||
setchr1(0x0000, 0xFC);
|
||||
setchr1(0x0400, 0xFD);
|
||||
setchr1(0x0800, 0xFF);
|
||||
weirdo--;
|
||||
}
|
||||
//else {
|
||||
// setchr1(0x0000, 0xFC);
|
||||
// setchr1(0x0400, 0xFD);
|
||||
// setchr1(0x0800, 0xFF);
|
||||
// weirdo--;
|
||||
//}
|
||||
}
|
||||
switch (mirr & 0x3) {
|
||||
case 0: setmirror(MI_V); break;
|
||||
@ -80,7 +81,7 @@ static void Sync(void) {
|
||||
}
|
||||
|
||||
static DECLFW(VRC24Write) {
|
||||
A &= 0xF003;
|
||||
A = A & 0xF000 | !!(A & reg2mask) << 1 | !!(A & reg1mask);
|
||||
if ((A >= 0xB000) && (A <= 0xE003)) {
|
||||
if (UNIFchrrama)
|
||||
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) {
|
||||
A = (A & 0xF000) | ((A >> 1) & 0x3); // Ganbare Goemon Gaiden 2 - Tenka no Zaihou (J) [!] isn't mapper 21 actually,
|
||||
// it's mapper 23 by wirings
|
||||
VRC24Write(A, V);
|
||||
}
|
||||
|
||||
static DECLFW(M22Write) {
|
||||
if (A == 0xC007) { // Ganbare Goemon Gaiden does strange things!!! at the end credits
|
||||
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
|
||||
static void VRC24Power(void) {
|
||||
big_bank = 0x20;
|
||||
Sync();
|
||||
if (WRAM) {
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
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);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M21Write);
|
||||
}
|
||||
|
||||
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);
|
||||
SetWriteHandler(0x8000, 0xFFFF, VRC24Write);
|
||||
}
|
||||
|
||||
void VRC24IRQHook(int a) {
|
||||
@ -210,26 +167,8 @@ static void VRC24Close(void) {
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
void Mapper21_Init(CartInfo *info) {
|
||||
isPirate = 0;
|
||||
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) {
|
||||
static void VRC24_Init(CartInfo *info) {
|
||||
info->Power = VRC24Power;
|
||||
info->Close = VRC24Close;
|
||||
MapIRQHook = VRC24IRQHook;
|
||||
GameStateRestore = StateRestore;
|
||||
@ -247,23 +186,48 @@ void VRC24_Init(CartInfo *info) {
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Mapper23_Init(CartInfo *info) {
|
||||
isPirate = 0;
|
||||
void Mapper21_Init(CartInfo *info) {
|
||||
isPirate = false;
|
||||
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);
|
||||
}
|
||||
|
||||
void Mapper25_Init(CartInfo *info) {
|
||||
isPirate = 0;
|
||||
isPirate = false;
|
||||
is22 = 0;
|
||||
info->Power = M25Power;
|
||||
reg1mask = 0xa;
|
||||
reg2mask = 0x5;
|
||||
VRC24_Init(info);
|
||||
}
|
||||
|
||||
void UNLT230_Init(CartInfo *info) {
|
||||
isPirate = 1;
|
||||
isPirate = true;
|
||||
is22 = 0;
|
||||
info->Power = M23Power;
|
||||
reg1mask = 0x15;
|
||||
reg2mask = 0x2a;
|
||||
VRC24_Init(info);
|
||||
}
|
||||
|
@ -1,226 +1,202 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* VRC-5 (CAI Shogakko no Sansu)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 QTAINTRAM[2048];
|
||||
static writefunc old2007wrap;
|
||||
|
||||
static uint16 CHRSIZE = 8192;
|
||||
static uint16 WRAMSIZE = 8192 + 4096;
|
||||
static uint8 *CHRRAM = NULL;
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
static uint8 IRQa, K4IRQ;
|
||||
static uint32 IRQLatch, IRQCount;
|
||||
|
||||
static uint8 regs[16];
|
||||
//static uint8 test[8];
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &IRQCount, 1, "IRQC" },
|
||||
{ &IRQLatch, 1, "IRQL" },
|
||||
{ &IRQa, 1, "IRQA" },
|
||||
{ &K4IRQ, 1, "KIRQ" },
|
||||
{ regs, 16, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void chrSync(void) {
|
||||
setchr4r(0x10, 0x0000, regs[5] & 1);
|
||||
setchr4r(0x10, 0x1000, 0);
|
||||
}
|
||||
|
||||
static void Sync(void) {
|
||||
chrSync();
|
||||
// if(regs[0xA]&0x10)
|
||||
// {
|
||||
/* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0);
|
||||
setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1);
|
||||
setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2);
|
||||
setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3);
|
||||
setchr1r(0x10,0x1000,0);
|
||||
setchr1r(0x10,0x1400,1);
|
||||
setchr1r(0x10,0x1800,2);
|
||||
setchr1r(0x10,0x1c00,3);*/
|
||||
/* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0);
|
||||
setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1);
|
||||
setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2);
|
||||
setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3);
|
||||
setchr1r(0x10,0x1000,(((regs[5]&1)^1)<<2)+4);
|
||||
setchr1r(0x10,0x1400,(((regs[5]&1)^1)<<2)+5);
|
||||
setchr1r(0x10,0x1800,(((regs[5]&1)^1)<<2)+6);
|
||||
setchr1r(0x10,0x1c00,(((regs[5]&1)^1)<<2)+7);
|
||||
*/
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
/*
|
||||
setchr1r(0x10,0x0000,(((regs[5]&1)^1)<<2)+0);
|
||||
setchr1r(0x10,0x0400,(((regs[5]&1)^1)<<2)+1);
|
||||
setchr1r(0x10,0x0800,(((regs[5]&1)^1)<<2)+2);
|
||||
setchr1r(0x10,0x0c00,(((regs[5]&1)^1)<<2)+3);
|
||||
setchr1r(0x10,0x1000,(((regs[5]&1))<<2)+4);
|
||||
setchr1r(0x10,0x1400,(((regs[5]&1))<<2)+5);
|
||||
setchr1r(0x10,0x1800,(((regs[5]&1))<<2)+6);
|
||||
setchr1r(0x10,0x1c00,(((regs[5]&1))<<2)+7);
|
||||
// }
|
||||
//*/
|
||||
/* setchr1r(1,0x0000,test[0]);
|
||||
setchr1r(1,0x0400,test[1]);
|
||||
setchr1r(1,0x0800,test[2]);
|
||||
setchr1r(1,0x0c00,test[3]);
|
||||
setchr1r(1,0x1000,test[4]);
|
||||
setchr1r(1,0x1400,test[5]);
|
||||
setchr1r(1,0x1800,test[6]);
|
||||
setchr1r(1,0x1c00,test[7]);
|
||||
*/
|
||||
setprg4r(0x10, 0x6000, regs[0] & 1);
|
||||
if (regs[2] >= 0x40)
|
||||
setprg8r(1, 0x8000, (regs[2] - 0x40));
|
||||
else
|
||||
setprg8r(0, 0x8000, (regs[2] & 0x3F));
|
||||
if (regs[3] >= 0x40)
|
||||
setprg8r(1, 0xA000, (regs[3] - 0x40));
|
||||
else
|
||||
setprg8r(0, 0xA000, (regs[3] & 0x3F));
|
||||
if (regs[4] >= 0x40)
|
||||
setprg8r(1, 0xC000, (regs[4] - 0x40));
|
||||
else
|
||||
setprg8r(0, 0xC000, (regs[4] & 0x3F));
|
||||
|
||||
setprg8r(1, 0xE000, ~0);
|
||||
setmirror(MI_V);
|
||||
}
|
||||
|
||||
/*static DECLFW(TestWrite)
|
||||
{
|
||||
test[A&7] = V;
|
||||
Sync();
|
||||
}*/
|
||||
|
||||
static DECLFW(M190Write) {
|
||||
// FCEU_printf("write %04x:%04x %d, %d\n",A,V,scanline,timestamp);
|
||||
regs[(A & 0x0F00) >> 8] = V;
|
||||
switch (A) {
|
||||
case 0xd600: IRQLatch &= 0xFF00; IRQLatch |= V; 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 0xd800: IRQa = K4IRQ; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFR(M190Read) {
|
||||
// FCEU_printf("read %04x:%04x %d, %d\n",A,regs[(A&0x0F00)>>8],scanline,timestamp);
|
||||
return regs[(A & 0x0F00) >> 8] + regs[0x0B];
|
||||
}
|
||||
static void VRC5IRQ(int a) {
|
||||
if (IRQa) {
|
||||
IRQCount += a;
|
||||
if (IRQCount & 0x10000) {
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
IRQCount = IRQLatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//static void Mapper190_PPU(uint32 A)
|
||||
//{
|
||||
// if(A<0x2000)
|
||||
// setchr4r(0x10,0x1000,QTAINTRAM[A&0x1FFF]&1);
|
||||
// else
|
||||
// chrSync();
|
||||
//}
|
||||
|
||||
static DECLFW(M1902007Wrap) {
|
||||
if (A >= 0x2000) {
|
||||
if (regs[0xA] & 1)
|
||||
QTAINTRAM[A & 0x1FFF] = V;
|
||||
else
|
||||
old2007wrap(A, V);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void M190Power(void) {
|
||||
/* test[0]=0;
|
||||
test[1]=1;
|
||||
test[2]=2;
|
||||
test[3]=3;
|
||||
test[4]=4;
|
||||
test[5]=5;
|
||||
test[6]=6;
|
||||
test[7]=7;
|
||||
*/
|
||||
setprg4r(0x10, 0x7000, 2);
|
||||
|
||||
old2007wrap = GetWriteHandler(0x2007);
|
||||
SetWriteHandler(0x2007, 0x2007, M1902007Wrap);
|
||||
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
// SetWriteHandler(0x5000,0x5007,TestWrite);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M190Write);
|
||||
SetReadHandler(0xDC00, 0xDC00, M190Read);
|
||||
SetReadHandler(0xDD00, 0xDD00, M190Read);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M190Close(void) {
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
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);
|
||||
}
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* VRC-5 (CAI Shogakko no Sansu)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 QTAINTRAM[2048];
|
||||
static writefunc old2007wrap;
|
||||
|
||||
static uint16 CHRSIZE = 8192;
|
||||
static uint16 WRAMSIZE = 8192 + 4096;
|
||||
static uint8 *CHRRAM = NULL;
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
static uint8 IRQa, K4IRQ;
|
||||
static uint32 IRQLatch, IRQCount;
|
||||
|
||||
static uint8 regs[16];
|
||||
//static uint8 test[8];
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &IRQCount, 1, "IRQC" },
|
||||
{ &IRQLatch, 1, "IRQL" },
|
||||
{ &IRQa, 1, "IRQA" },
|
||||
{ &K4IRQ, 1, "KIRQ" },
|
||||
{ regs, 16, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void chrSync(void) {
|
||||
setchr4r(0x10, 0x0000, regs[5] & 1);
|
||||
setchr4r(0x10, 0x1000, 0);
|
||||
}
|
||||
|
||||
static void Sync(void) {
|
||||
chrSync();
|
||||
// if(regs[0xA]&0x10)
|
||||
// {
|
||||
/* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0);
|
||||
setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1);
|
||||
setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2);
|
||||
setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3);
|
||||
setchr1r(0x10,0x1000,0);
|
||||
setchr1r(0x10,0x1400,1);
|
||||
setchr1r(0x10,0x1800,2);
|
||||
setchr1r(0x10,0x1c00,3);*/
|
||||
/* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0);
|
||||
setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1);
|
||||
setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2);
|
||||
setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3);
|
||||
setchr1r(0x10,0x1000,(((regs[5]&1)^1)<<2)+4);
|
||||
setchr1r(0x10,0x1400,(((regs[5]&1)^1)<<2)+5);
|
||||
setchr1r(0x10,0x1800,(((regs[5]&1)^1)<<2)+6);
|
||||
setchr1r(0x10,0x1c00,(((regs[5]&1)^1)<<2)+7);
|
||||
*/
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
/*
|
||||
setchr1r(0x10,0x0000,(((regs[5]&1)^1)<<2)+0);
|
||||
setchr1r(0x10,0x0400,(((regs[5]&1)^1)<<2)+1);
|
||||
setchr1r(0x10,0x0800,(((regs[5]&1)^1)<<2)+2);
|
||||
setchr1r(0x10,0x0c00,(((regs[5]&1)^1)<<2)+3);
|
||||
setchr1r(0x10,0x1000,(((regs[5]&1))<<2)+4);
|
||||
setchr1r(0x10,0x1400,(((regs[5]&1))<<2)+5);
|
||||
setchr1r(0x10,0x1800,(((regs[5]&1))<<2)+6);
|
||||
setchr1r(0x10,0x1c00,(((regs[5]&1))<<2)+7);
|
||||
// }
|
||||
//*/
|
||||
/* setchr1r(1,0x0000,test[0]);
|
||||
setchr1r(1,0x0400,test[1]);
|
||||
setchr1r(1,0x0800,test[2]);
|
||||
setchr1r(1,0x0c00,test[3]);
|
||||
setchr1r(1,0x1000,test[4]);
|
||||
setchr1r(1,0x1400,test[5]);
|
||||
setchr1r(1,0x1800,test[6]);
|
||||
setchr1r(1,0x1c00,test[7]);
|
||||
*/
|
||||
setprg4r(0x10, 0x6000, regs[0] & 1);
|
||||
if (regs[2] >= 0x40)
|
||||
setprg8r(1, 0x8000, (regs[2] - 0x40));
|
||||
else
|
||||
setprg8r(0, 0x8000, (regs[2] & 0x3F));
|
||||
if (regs[3] >= 0x40)
|
||||
setprg8r(1, 0xA000, (regs[3] - 0x40));
|
||||
else
|
||||
setprg8r(0, 0xA000, (regs[3] & 0x3F));
|
||||
if (regs[4] >= 0x40)
|
||||
setprg8r(1, 0xC000, (regs[4] - 0x40));
|
||||
else
|
||||
setprg8r(0, 0xC000, (regs[4] & 0x3F));
|
||||
|
||||
setprg8r(1, 0xE000, ~0);
|
||||
setmirror(MI_V);
|
||||
}
|
||||
|
||||
/*static DECLFW(TestWrite)
|
||||
{
|
||||
test[A&7] = V;
|
||||
Sync();
|
||||
}*/
|
||||
|
||||
static DECLFW(M190Write) {
|
||||
// FCEU_printf("write %04x:%04x %d, %d\n",A,V,scanline,timestamp);
|
||||
regs[(A & 0x0F00) >> 8] = V;
|
||||
switch (A) {
|
||||
case 0xd600: IRQLatch &= 0xFF00; IRQLatch |= V; 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 0xd800: IRQa = K4IRQ; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFR(M190Read) {
|
||||
// FCEU_printf("read %04x:%04x %d, %d\n",A,regs[(A&0x0F00)>>8],scanline,timestamp);
|
||||
return regs[(A & 0x0F00) >> 8] + regs[0x0B];
|
||||
}
|
||||
static void VRC5IRQ(int a) {
|
||||
if (IRQa) {
|
||||
IRQCount += a;
|
||||
if (IRQCount & 0x10000) {
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
IRQCount = IRQLatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//static void Mapper190_PPU(uint32 A)
|
||||
//{
|
||||
// if(A<0x2000)
|
||||
// setchr4r(0x10,0x1000,QTAINTRAM[A&0x1FFF]&1);
|
||||
// else
|
||||
// chrSync();
|
||||
//}
|
||||
|
||||
static DECLFW(M1902007Wrap) {
|
||||
if (A >= 0x2000) {
|
||||
if (regs[0xA] & 1)
|
||||
QTAINTRAM[A & 0x1FFF] = V;
|
||||
else
|
||||
old2007wrap(A, V);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void M190Power(void) {
|
||||
/* test[0]=0;
|
||||
test[1]=1;
|
||||
test[2]=2;
|
||||
test[3]=3;
|
||||
test[4]=4;
|
||||
test[5]=5;
|
||||
test[6]=6;
|
||||
test[7]=7;
|
||||
*/
|
||||
setprg4r(0x10, 0x7000, 2);
|
||||
|
||||
old2007wrap = GetWriteHandler(0x2007);
|
||||
SetWriteHandler(0x2007, 0x2007, M1902007Wrap);
|
||||
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
// SetWriteHandler(0x5000,0x5007,TestWrite);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M190Write);
|
||||
SetReadHandler(0xDC00, 0xDC00, M190Read);
|
||||
SetReadHandler(0xDD00, 0xDD00, M190Read);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M190Close(void) {
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ static void VRC7SKill(void) {
|
||||
static void VRC7_ESI(void) {
|
||||
GameExpSound.RChange = VRC7SC;
|
||||
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);
|
||||
}
|
||||
|
@ -76,6 +76,8 @@ uint8 geniech[3];
|
||||
|
||||
uint32 genieaddr[3];
|
||||
|
||||
CartInfo *currCartInfo;
|
||||
|
||||
static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram) {
|
||||
uint32 AB = A >> 11;
|
||||
int x;
|
||||
|
@ -25,6 +25,8 @@ typedef struct {
|
||||
// other code in the future.
|
||||
} CartInfo;
|
||||
|
||||
extern CartInfo *currCartInfo;
|
||||
|
||||
void FCEU_SaveGameSave(CartInfo *LocalHWInfo);
|
||||
void FCEU_LoadGameSave(CartInfo *LocalHWInfo);
|
||||
void FCEU_ClearGameSave(CartInfo *LocalHWInfo);
|
||||
|
@ -216,7 +216,7 @@ void FCEU_LoadGameCheats(FILE *override)
|
||||
}
|
||||
|
||||
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;
|
||||
int doc=0;
|
||||
@ -931,12 +931,14 @@ void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2)
|
||||
|
||||
int FCEU_CheatGetByte(uint32 A)
|
||||
{
|
||||
// if(CheatRPtrs[A>>10])
|
||||
// return CheatRPtrs[A>>10][A]; //adelikat-commenting this stuff out so that lua can see frozen addresses, I hope this doesn't bork stuff.
|
||||
/*else*/ if(A < 0x10000)
|
||||
return ARead[A](A);
|
||||
else
|
||||
return 0;
|
||||
if(A < 0x10000) {
|
||||
uint32 ret;
|
||||
fceuindbg=1;
|
||||
ret = ARead[A](A);
|
||||
fceuindbg=0;
|
||||
return ret;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FCEU_CheatSetByte(uint32 A, uint8 V)
|
||||
|
@ -34,10 +34,11 @@
|
||||
* Primitive -> Number | Address | Register | Flag | PC Bank | '(' Connect ')'
|
||||
* Number -> '#' [1-9A-F]*
|
||||
* Address -> '$' [1-9A-F]* | '$' '[' Connect ']'
|
||||
* Register -> 'A' | 'X' | 'Y' | 'P'
|
||||
* Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V'
|
||||
* Register -> 'A' | 'X' | 'Y' | 'P' | 'S'
|
||||
* Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V' | 'U' | 'D'
|
||||
* PC Bank -> 'K'
|
||||
* Data Bank -> 'T'
|
||||
* Data Bank -> 'T'
|
||||
* Value -> 'R' | 'W'
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
@ -50,8 +51,9 @@
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
|
||||
// hack: this address is used by 'T' condition
|
||||
uint16 addressOfTheLastAccessedData = 0;
|
||||
uint16 debugLastAddress = 0; // used by 'T' and 'R' conditions
|
||||
uint8 debugLastOpcode; // used to evaluate 'W' condition
|
||||
|
||||
// Next non-whitespace character in string
|
||||
char next;
|
||||
|
||||
@ -137,7 +139,7 @@ int isFlag(char c)
|
||||
// Determines if a character is a register
|
||||
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
|
||||
@ -152,6 +154,18 @@ int isDataBank(char c)
|
||||
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
|
||||
int getNumber(unsigned int* number, const char** str)
|
||||
{
|
||||
@ -272,6 +286,40 @@ Condition* Primitive(const char** str, Condition* 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 */
|
||||
{
|
||||
unsigned int number = 0;
|
||||
|
@ -28,6 +28,8 @@
|
||||
#define TYPE_ADDR 4
|
||||
#define TYPE_PC_BANK 5
|
||||
#define TYPE_DATA_BANK 6
|
||||
#define TYPE_VALUE_READ 7
|
||||
#define TYPE_VALUE_WRITE 8
|
||||
|
||||
#define OP_NO 0
|
||||
#define OP_EQ 1
|
||||
@ -43,7 +45,9 @@
|
||||
#define OP_OR 11
|
||||
#define OP_AND 12
|
||||
|
||||
extern uint16 addressOfTheLastAccessedData;
|
||||
extern uint16 debugLastAddress;
|
||||
extern uint8 debugLastOpcode;
|
||||
|
||||
//mbg merge 7/18/06 turned into sane c++
|
||||
struct Condition
|
||||
{
|
||||
|
@ -18,10 +18,13 @@ char *FCEUI_GetAboutString() {
|
||||
const char *aboutTemplate =
|
||||
FCEU_NAME_AND_VERSION "\n\n"
|
||||
"Administrators:\n"
|
||||
"zeromus, adelikat, AnS\n\n"
|
||||
"zeromus, punkrockguy318 (Lukas Sabota), feos\n"
|
||||
"\n"
|
||||
"Current Contributors:\n"
|
||||
"punkrockguy318 (Lukas Sabota)\n"
|
||||
"CaH4e3, gocha, xhainingx, feos\n"
|
||||
"CaH4e3, rainwarrior\n"
|
||||
"\n"
|
||||
"Past Contributors:\n"
|
||||
"xhainingx, gocha, AnS\n"
|
||||
"\n"
|
||||
"FCEUX 2.0:\n"
|
||||
"mz, nitsujrehtona, SP, Ugly Joe,\n"
|
||||
|
@ -77,6 +77,7 @@ int getValue(int type)
|
||||
case 'Z': return _P & Z_FLAG ? 1 : 0;
|
||||
case 'C': return _P & C_FLAG ? 1 : 0;
|
||||
case 'P': return _PC;
|
||||
case 'S': return _S;
|
||||
}
|
||||
|
||||
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
|
||||
return 0xFF;
|
||||
if (GameInfo) //adelikat: 11/17/09: Prevent crash if this is called with no game loaded.
|
||||
return ARead[A](A);
|
||||
else return 0;
|
||||
if (GameInfo) { //adelikat: 11/17/09: Prevent crash if this is called with no game loaded.
|
||||
uint32 ret;
|
||||
fceuindbg=1;
|
||||
ret = ARead[A](A);
|
||||
fceuindbg=0;
|
||||
return ret;
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
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
|
||||
int evaluate(Condition* c)
|
||||
{
|
||||
@ -330,7 +361,9 @@ int evaluate(Condition* c)
|
||||
{
|
||||
case TYPE_ADDR: value1 = GetMem(value1); 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;
|
||||
@ -355,7 +388,9 @@ int evaluate(Condition* c)
|
||||
{
|
||||
case TYPE_ADDR: value2 = GetMem(value2); 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)
|
||||
@ -367,7 +402,7 @@ int evaluate(Condition* c)
|
||||
case OP_G: f = value1 > value2; break;
|
||||
case OP_L: 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_MINUS: 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 (bp_num >= 0 && !condition(&watchpoint[bp_num]))
|
||||
{
|
||||
return; // condition rejected
|
||||
}
|
||||
|
||||
//check to see whether we fall in any forbid zone
|
||||
for (int i = 0; i < numWPs; i++)
|
||||
{
|
||||
@ -529,7 +569,7 @@ void BreakHit(int bp_num, bool force)
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8 StackAddrBackup = X.S;
|
||||
int StackAddrBackup;
|
||||
uint16 StackNextIgnorePC = 0xFFFF;
|
||||
|
||||
///fires a breakpoint
|
||||
@ -539,6 +579,9 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
uint8 stackop=0;
|
||||
uint8 stackopstartaddr,stackopendaddr;
|
||||
|
||||
debugLastAddress = A;
|
||||
debugLastOpcode = opcode[0];
|
||||
|
||||
if (break_asap)
|
||||
{
|
||||
break_asap = false;
|
||||
@ -601,24 +644,25 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
switch (opcode[0]) {
|
||||
//Push Ops
|
||||
case 0x08: //Fall to next
|
||||
case 0x48: stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||
case 0x48: debugLastAddress=stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||
//Pull Ops
|
||||
case 0x28: //Fall to next
|
||||
case 0x68: stackopstartaddr=stackopendaddr=X.S+1; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||
case 0x68: debugLastAddress=stackopstartaddr=stackopendaddr=X.S+1; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||
//JSR (Includes return address - 1)
|
||||
case 0x20: stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=(opcode[1]|opcode[2]<<8); break;
|
||||
//RTI (Includes processor status, and exact return address)
|
||||
case 0x40: stackopstartaddr=X.S+1; stackopendaddr=X.S+3; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=(GetMem(X.S+2|0x0100)|GetMem(X.S+3|0x0100)<<8); break;
|
||||
//RTS (Includes return address - 1)
|
||||
case 0x60: stackopstartaddr=X.S+1; stackopendaddr=X.S+2; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=(GetMem(stackopstartaddr|0x0100)|GetMem(stackopendaddr|0x0100)<<8)+1; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
#define BREAKHIT(x) { breakHit = (x); goto STOPCHECKING; }
|
||||
int breakHit = -1;
|
||||
for (i = 0; i < numWPs; i++)
|
||||
{
|
||||
// ################################## Start of SP CODE ###########################
|
||||
if ((watchpoint[i].flags & WP_E) && condition(&watchpoint[i]))
|
||||
if ((watchpoint[i].flags & WP_E))
|
||||
{
|
||||
// ################################## End of SP CODE ###########################
|
||||
if (watchpoint[i].flags & BT_P)
|
||||
{
|
||||
// PPU Mem breaks
|
||||
@ -628,11 +672,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if (watchpoint[i].endaddress)
|
||||
{
|
||||
if ((watchpoint[i].address <= PPUAddr) && (watchpoint[i].endaddress >= PPUAddr))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == PPUAddr)
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
}
|
||||
} 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].address <= PPU[3]) && (watchpoint[i].endaddress >= PPU[3]))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == PPU[3])
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
} else if ((watchpoint[i].flags & WP_W) && (A == 0x4014))
|
||||
{
|
||||
// Sprite DMA! :P
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
} 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)) ||
|
||||
((watchpoint[i].flags & WP_X) && (watchpoint[i].address <= _PC) && (watchpoint[i].endaddress >= _PC)))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address == A)) ||
|
||||
((watchpoint[i].flags & WP_X) && (watchpoint[i].address == _PC)))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
} else
|
||||
{
|
||||
@ -685,11 +729,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if (watchpoint[i].endaddress)
|
||||
{
|
||||
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == j)
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -700,7 +744,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
StackNextIgnorePC = 0xFFFF;
|
||||
} else
|
||||
{
|
||||
if ((X.S < StackAddrBackup) && (stackop==0))
|
||||
if (StackAddrBackup != -1 && (X.S < StackAddrBackup) && (stackop==0))
|
||||
{
|
||||
// Unannounced stack mem breaks
|
||||
// Pushes to stack
|
||||
@ -711,15 +755,15 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if (watchpoint[i].endaddress)
|
||||
{
|
||||
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
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
|
||||
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].address <= j) && (watchpoint[i].endaddress >= j))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
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.
|
||||
//ZEROMUS THINKS IT MAKES MORE SENSE HERE
|
||||
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
|
||||
|
||||
@ -777,9 +828,12 @@ void DebugCycle()
|
||||
size = opsize[opcode[0]];
|
||||
switch (size)
|
||||
{
|
||||
default:
|
||||
case 1: break;
|
||||
case 2:
|
||||
opcode[1] = GetMem(_PC + 1);
|
||||
break;
|
||||
case 0: // illegal instructions may have operands
|
||||
case 3:
|
||||
opcode[1] = GetMem(_PC + 1);
|
||||
opcode[2] = GetMem(_PC + 2);
|
||||
@ -803,7 +857,6 @@ void DebugCycle()
|
||||
case 7: A = (opcode[1] | (opcode[2] << 8)) + _X; 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)
|
||||
breakpoint(opcode, A, size);
|
||||
|
@ -49,13 +49,11 @@ typedef struct {
|
||||
uint16 address;
|
||||
uint16 endaddress;
|
||||
uint8 flags;
|
||||
// ################################## Start of SP CODE ###########################
|
||||
|
||||
Condition* cond;
|
||||
char* condText;
|
||||
char* desc;
|
||||
|
||||
// ################################## End of SP CODE ###########################
|
||||
} watchpointinfo;
|
||||
|
||||
//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 PPU[4],PALRAM[0x20],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset;
|
||||
extern uint32 FCEUPPU_PeekAddress();
|
||||
|
||||
extern int debug_loggingCD;
|
||||
extern int numWPs;
|
||||
|
||||
///encapsulates the operational state of the debugger core
|
||||
|
@ -68,7 +68,7 @@ void FCEUI_NTSCSELTINT(void);
|
||||
void FCEUI_NTSCDEC(void);
|
||||
void FCEUI_NTSCINC(void);
|
||||
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_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)
|
||||
//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).
|
||||
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.
|
||||
void FCEUI_SetBaseDirectory(std::string const & dir);
|
||||
|
||||
//Tells FCE Ultra to copy the palette data pointed to by pal and use it.
|
||||
//Data pointed to by pal needs to be 64*3 bytes in length.
|
||||
void FCEUI_SetPaletteArray(uint8 *pal);
|
||||
void FCEUI_SetUserPalette(uint8 *pal, int nEntries);
|
||||
|
||||
//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.
|
||||
|
@ -56,9 +56,10 @@ extern bool isTaseditorRecording();
|
||||
extern int32 fps_scale;
|
||||
extern int32 fps_scale_unpaused;
|
||||
extern int32 fps_scale_frameadvance;
|
||||
extern void RefreshThrottleFPS();
|
||||
#endif
|
||||
|
||||
extern void RefreshThrottleFPS();
|
||||
|
||||
#ifdef _S9XLUA_H
|
||||
#include "fceulua.h"
|
||||
#endif
|
||||
@ -93,6 +94,20 @@ extern void RefreshThrottleFPS();
|
||||
|
||||
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
|
||||
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)
|
||||
@ -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 AutoResumePlay = false;
|
||||
char romNameWhenClosingEmulator[2048] = {0};
|
||||
int dendy = 0;
|
||||
|
||||
FCEUGI::FCEUGI()
|
||||
: filename(0),
|
||||
@ -140,10 +154,12 @@ void FCEU_TogglePPU(void) {
|
||||
if (newppu) {
|
||||
FCEU_DispMessage("New PPU loaded", 0);
|
||||
FCEUI_printf("New PPU loaded");
|
||||
overclock_enabled = 0;
|
||||
} else {
|
||||
FCEU_DispMessage("Old PPU loaded", 0);
|
||||
FCEUI_printf("Old PPU loaded");
|
||||
}
|
||||
normalscanlines = (dendy ? 290 : 240)+newppu; // use flag as number!
|
||||
#ifdef WIN32
|
||||
SetMainWindowText();
|
||||
#endif
|
||||
@ -348,16 +364,10 @@ uint8 PAL = 0;
|
||||
|
||||
static DECLFW(BRAML) {
|
||||
RAM[A] = V;
|
||||
#ifdef _S9XLUA_H
|
||||
CallRegisteredLuaMemHook(A, 1, V, LUAMEMHOOK_WRITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static DECLFW(BRAMH) {
|
||||
RAM[A & 0x7FF] = V;
|
||||
#ifdef _S9XLUA_H
|
||||
CallRegisteredLuaMemHook(A & 0x7FF, 1, V, LUAMEMHOOK_WRITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static DECLFR(ARAML) {
|
||||
@ -384,7 +394,7 @@ void ResetGameLoaded(void) {
|
||||
MMC5Hack = 0;
|
||||
PEC586Hack = 0;
|
||||
PAL &= 1;
|
||||
pale = 0;
|
||||
default_palette_selection = 0;
|
||||
}
|
||||
|
||||
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
|
||||
FCEUFILE *fp;
|
||||
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 };
|
||||
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 ###########################
|
||||
#endif
|
||||
|
||||
FCEU_ResetVidSys();
|
||||
if (OverwriteVidMode)
|
||||
FCEU_ResetVidSys();
|
||||
|
||||
if (GameInfo->type != GIT_NSF)
|
||||
{
|
||||
@ -511,6 +524,18 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
|
||||
FCEU_ResetPalette();
|
||||
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)
|
||||
FCEU_LoadGameCheats(0);
|
||||
|
||||
@ -712,10 +737,15 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
|
||||
extern int KillFCEUXonFrame;
|
||||
if (KillFCEUXonFrame && (FCEUMOV_GetFrame() >= KillFCEUXonFrame))
|
||||
DoFCEUExit();
|
||||
#else
|
||||
extern int KillFCEUXonFrame;
|
||||
if (KillFCEUXonFrame && (FCEUMOV_GetFrame() >= KillFCEUXonFrame))
|
||||
exit(0);
|
||||
#endif
|
||||
|
||||
timestampbase += timestamp;
|
||||
timestamp = 0;
|
||||
soundtimestamp = 0;
|
||||
|
||||
*pXBuf = skip ? 0 : XBuf;
|
||||
if (skip == 2) { //If skip = 2, then bypass sound
|
||||
@ -769,17 +799,79 @@ void ResetNES(void) {
|
||||
//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;
|
||||
|
||||
while (size) {
|
||||
*ptr = (x & 4) ? 0xFF : 0x00; // Huang Di DEBUG MODE enabled by default
|
||||
// Cybernoid NO MUSIC by default
|
||||
// *ptr = (x & 4) ? 0x7F : 0x00; // Huang Di DEBUG MODE enabled by default
|
||||
// Minna no Taabou no Nakayoshi Daisakusen DOESN'T BOOT
|
||||
// Cybernoid NO MUSIC by default
|
||||
// *ptr = (x & 1) ? 0x55 : 0xAA; // F-15 Sity War HISCORE is screwed...
|
||||
// 1942 SCORE/HISCORE is screwed...
|
||||
// *ptr = 0xFF; // Work for all cases
|
||||
uint8 v = 0;
|
||||
switch (RAMInitOption)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
if (!default_zero) v = (x & 4) ? 0xFF : 0x00;
|
||||
else v = 0x00;
|
||||
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++;
|
||||
size--;
|
||||
ptr++;
|
||||
@ -793,18 +885,21 @@ void PowerNES(void) {
|
||||
FCEUMOV_AddCommand(FCEUNPCMD_POWER);
|
||||
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_CheatAddRAM(2, 0, RAM);
|
||||
|
||||
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);
|
||||
|
||||
SetReadHandler(0x0000, 0xFFFF, ANull);
|
||||
@ -845,7 +940,7 @@ void PowerNES(void) {
|
||||
Update_RAM_Search(); // Update_RAM_Watch() is also called.
|
||||
#endif
|
||||
|
||||
//FCEU_DispMessage("Power on", 0);
|
||||
FCEU_DispMessage("Power on", 0);
|
||||
}
|
||||
|
||||
void FCEU_ResetVidSys(void) {
|
||||
@ -861,6 +956,14 @@ void FCEU_ResetVidSys(void) {
|
||||
|
||||
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);
|
||||
SetSoundVariables();
|
||||
}
|
||||
@ -877,6 +980,13 @@ void FCEU_printf(char *format, ...) {
|
||||
vsnprintf(temp, sizeof(temp), format, ap);
|
||||
FCEUD_Message(temp);
|
||||
|
||||
#if 0
|
||||
FILE *ofile;
|
||||
ofile = fopen("stdout.txt", "ab");
|
||||
fwrite(temp, 1, strlen(temp), ofile);
|
||||
fclose(ofile);
|
||||
#endif
|
||||
|
||||
va_end(ap);
|
||||
#endif
|
||||
}
|
||||
@ -925,30 +1035,58 @@ int FCEUI_GetCurrentVidSystem(int *slstart, int *slend) {
|
||||
*slend = FSettings.LastSLine;
|
||||
return(PAL);
|
||||
}
|
||||
/*
|
||||
// TODO: make use on SDL
|
||||
void FCEUI_SetRegion(int region) {
|
||||
|
||||
#ifndef GEKKO
|
||||
void FCEUI_SetRegion(int region, int notify) {
|
||||
switch (region) {
|
||||
case 0: // NTSC
|
||||
normalscanlines = 240;
|
||||
pal_emulation = 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;
|
||||
case 1: // PAL
|
||||
normalscanlines = 240;
|
||||
pal_emulation = 1;
|
||||
dendy = 0;
|
||||
#ifdef WIN32
|
||||
if (notify)
|
||||
{
|
||||
FCEU_DispMessage("PAL mode set", 0);
|
||||
FCEUI_printf("PAL mode set");
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 2: // Dendy
|
||||
normalscanlines = 290;
|
||||
pal_emulation = 0;
|
||||
dendy = 1;
|
||||
#ifdef WIN32
|
||||
if (notify)
|
||||
{
|
||||
FCEU_DispMessage("Dendy mode set", 0);
|
||||
FCEUI_printf("Dendy mode set");
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
normalscanlines += newppu;
|
||||
totalscanlines = normalscanlines + (overclock_enabled ? postrenderscanlines : 0);
|
||||
FCEUI_SetVidSystem(pal_emulation);
|
||||
RefreshThrottleFPS();
|
||||
#ifdef WIN32
|
||||
UpdateCheckedMenuItems();
|
||||
PushCurrentVideoSettings();
|
||||
#endif
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
|
||||
//Enable or disable Game Genie option.
|
||||
void FCEUI_SetGameGenie(bool a) {
|
||||
@ -1052,9 +1190,7 @@ int FCEU_TextScanlineOffsetFromBottom(int y) {
|
||||
}
|
||||
|
||||
bool FCEU_IsValidUI(EFCEUI ui) {
|
||||
#ifdef GEKKO
|
||||
return true;
|
||||
#endif
|
||||
#ifndef GEKKO
|
||||
switch (ui) {
|
||||
case FCEUI_OPENGAME:
|
||||
case FCEUI_CLOSEGAME:
|
||||
@ -1099,6 +1235,7 @@ bool FCEU_IsValidUI(EFCEUI ui) {
|
||||
if (!FCEUMOV_Mode(MOVIEMODE_INACTIVE)) return false;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1165,8 +1302,6 @@ void FCEUXGameInterface(GI command) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool FCEUXLoad(const char *name, FCEUFILE *fp) {
|
||||
//read ines header
|
||||
iNES_HEADER head;
|
||||
@ -1218,11 +1353,26 @@ bool FCEUXLoad(const char *name, FCEUFILE *fp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8 FCEU_ReadRomByte(uint32 i) {
|
||||
extern iNES_HEADER head;
|
||||
if (i < 16) return *((unsigned char*)&head + i);
|
||||
if (i < 16 + PRGsize[0]) return PRGptr[0][i - 16];
|
||||
if (i < 16 + PRGsize[0] + CHRsize[0]) return CHRptr[0][i - 16 - PRGsize[0]];
|
||||
if (i < 16)
|
||||
return *((unsigned char*)&head + i);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -7,13 +7,22 @@ extern int fceuindbg;
|
||||
extern int newppu;
|
||||
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 char romNameWhenClosingEmulator[];
|
||||
|
||||
#define DECLFR(x) uint8 x (uint32 A)
|
||||
#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 SetWriteHandler(int32 start, int32 end, writefunc func);
|
||||
writefunc GetWriteHandler(int32 a);
|
||||
@ -54,6 +63,7 @@ extern uint8 *RAM; //shared memory modifications
|
||||
extern int EmulationPaused;
|
||||
|
||||
uint8 FCEU_ReadRomByte(uint32 i);
|
||||
void FCEU_WriteRomByte(uint32 i, uint8 value);
|
||||
|
||||
extern readfunc ARead[0x10000];
|
||||
extern writefunc BWrite[0x10000];
|
||||
@ -121,7 +131,7 @@ void FCEU_DispMessage(char *format, int disppos, ...);
|
||||
void FCEU_DispMessageOnMovie(char *format, ...);
|
||||
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 FCEU_PutImage(void);
|
||||
#ifdef FRAMESKIP
|
||||
@ -134,7 +144,7 @@ extern void PushCurrentVideoSettings();
|
||||
#endif
|
||||
|
||||
extern uint8 Exit;
|
||||
extern uint8 pale;
|
||||
extern int default_palette_selection;
|
||||
extern uint8 vsdip;
|
||||
|
||||
//#define FCEUDEF_DEBUGGER //mbg merge 7/17/06 - cleaning out conditional compiles
|
||||
|
@ -18,10 +18,6 @@
|
||||
* 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 "x6502.h"
|
||||
#include "fceu.h"
|
||||
@ -37,10 +33,14 @@
|
||||
#include "driver.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
|
||||
// and the when it can be successfully read/written to. This should
|
||||
// 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void FCEU_FDSInsert(void) {
|
||||
if (FCEUI_EmulationPaused()) EmulationPaused |= 2;
|
||||
void FCEU_FDSInsert(void)
|
||||
{
|
||||
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))
|
||||
FCEUMOV_AddCommand(FCEUNPCMD_FDSINSERT);
|
||||
|
||||
if (TotalSides == 0) {
|
||||
FCEU_DispMessage("", 0);// remove text "Not FDS; can't eject disk."
|
||||
return;
|
||||
}
|
||||
if (InDisk == 255) {
|
||||
if (InDisk == 255)
|
||||
{
|
||||
//FCEU_DispMessage("Disk %d Side %s Inserted", 0, SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
|
||||
InDisk = SelectDisk;
|
||||
} else {
|
||||
} else
|
||||
{
|
||||
//FCEU_DispMessage("Disk %d Side %s Ejected", 0, SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
|
||||
InDisk = 255;
|
||||
}
|
||||
@ -171,22 +177,27 @@ void FCEU_FDSEject(void)
|
||||
InDisk=255;
|
||||
}
|
||||
*/
|
||||
void FCEU_FDSSelect(void) {
|
||||
if (FCEUI_EmulationPaused()) EmulationPaused |= 2;
|
||||
void FCEU_FDSSelect(void)
|
||||
{
|
||||
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))
|
||||
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;
|
||||
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) {
|
||||
@ -753,13 +764,11 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
|
||||
|
||||
CHRRAMSize = 8192;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
|
||||
memset(CHRRAM, 0, CHRRAMSize);
|
||||
SetupCartCHRMapping(0, CHRRAM, CHRRAMSize, 1);
|
||||
AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
|
||||
|
||||
FDSRAMSize = 32768;
|
||||
FDSRAM = (uint8*)FCEU_gmalloc(FDSRAMSize);
|
||||
memset(FDSRAM, 0, FDSRAMSize);
|
||||
SetupCartPRGMapping(1, FDSRAM, FDSRAMSize, 1);
|
||||
AddExState(FDSRAM, FDSRAMSize, 0, "FDSR");
|
||||
|
||||
|
@ -27,10 +27,6 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fstream>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#include "types.h"
|
||||
#include "file.h"
|
||||
#include "utils/endian.h"
|
||||
@ -49,6 +45,10 @@
|
||||
#include "driver.h"
|
||||
#include "utils/xstring.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool bindSavestate = true; //Toggle that determines if a savestate filename will include the movie filename
|
||||
|
@ -36,8 +36,10 @@ enum ESI
|
||||
SI_POWERPADB = 4,
|
||||
SI_ARKANOID = 5,
|
||||
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)
|
||||
@ -50,7 +52,9 @@ inline const char* ESI_Name(ESI esi)
|
||||
"Power Pad A",
|
||||
"Power Pad B",
|
||||
"Arkanoid Paddle",
|
||||
"Mouse"
|
||||
"Subor Mouse",
|
||||
"SNES Pad",
|
||||
"SNES Mouse"
|
||||
};
|
||||
|
||||
if(esi >= SI_NONE && esi <= SI_COUNT)
|
||||
|
@ -30,6 +30,7 @@
|
||||
{ 0x9b4bad37b5498992LL, "Gradius 2", INESB_HACKED },
|
||||
{ 0xb068d4ac10ef848eLL, "Highway Star", INESB_HACKED },
|
||||
{ 0xbf5175271e5019c3LL, "Kaiketsu Yanchamaru 3", INESB_HACKED },
|
||||
{ 0x81c1de64550a1531LL, "Nobunaga no Yabou Zenkokuban", INESB_HACKED },
|
||||
{ 0xfb4b508a236bbba3LL, "Salamander", INESB_HACKED },
|
||||
{ 0x1895afc6eef26c7dLL, "Super Mario Bros.", INESB_HACKED },
|
||||
{ 0x3716c4bebf885344LL, "Super Mario Bros.", INESB_HACKED },
|
||||
|
@ -62,6 +62,7 @@
|
||||
{0x02cc3973, 3, 1}, /* Ninja Kid */
|
||||
{0xbc065fc3, 3, 1}, /* Pipe Dream */
|
||||
{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},
|
||||
{0xd97c31b0, 4, 1}, //Rasaaru Ishii no Childs Quest (J)
|
||||
{0x404b2e8b, 4, 2}, /* Rad Racer 2 */
|
||||
@ -83,7 +84,6 @@
|
||||
{0x6e68e31a, 16, 8}, /* Dragon Ball 3*/
|
||||
{0x33b899c9, 16, -1}, /* Dragon Ball - Dai Maou Fukkatsu (J) [!] */
|
||||
{0xa262a81f, 16, -1}, /* Rokudenashi Blues (J) */
|
||||
{0x286fcd20, 23, -1}, /* Ganbare Goemon Gaiden 2 - Tenka no Zaihou (J) [!] */
|
||||
{0xe4a291ce, 23, -1}, /* World Hero (Unl) [!] */
|
||||
{0x51e9cd33, 23, -1}, /* World Hero (Unl) [b1] */
|
||||
{0x105dd586, 27, -1}, /* Mi Hun Che variations... */
|
||||
@ -257,10 +257,28 @@
|
||||
{0x345ee51a, 245, -1}, /* DQ4c */
|
||||
{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) [!] */
|
||||
{0x6eef8bb7, 257|0x1000,-1}, /* PEC-586 Chinese */
|
||||
{0xac7e98fb, 257|0x1000,-1}, /* PEC-586 Chinese No Tape Out */
|
||||
{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 */
|
||||
{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}
|
||||
|
@ -327,7 +327,7 @@ static void CheckHInfo(void) {
|
||||
{
|
||||
#include "ines-correct.h"
|
||||
};
|
||||
int32 tofix = 0, x;
|
||||
int32 tofix = 0, x, mask;
|
||||
uint64 partialmd5 = 0;
|
||||
|
||||
for (x = 0; x < 8; x++)
|
||||
@ -361,9 +361,13 @@ static void CheckHInfo(void) {
|
||||
VROM = NULL;
|
||||
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;
|
||||
MapperNo = moo[x].mapper & 0xFF;
|
||||
MapperNo = moo[x].mapper & mask;
|
||||
}
|
||||
}
|
||||
if (moo[x].mirror >= 0) {
|
||||
@ -561,7 +565,7 @@ static BMAPPINGLocal bmap[] = {
|
||||
{"FDS UNROM BOARD", 108, Mapper108_Init},
|
||||
// {"", 109, Mapper109_Init},
|
||||
// {"", 110, Mapper110_Init},
|
||||
// {"", 111, Mapper111_Init},
|
||||
{"Cheapocabra", 111, Mapper111_Init},
|
||||
{"ASDER/NTDEC BOARD", 112, Mapper112_Init},
|
||||
{"HACKER/SACHEN BOARD", 113, Mapper113_Init},
|
||||
{"MMC3 SG PROT. A", 114, Mapper114_Init},
|
||||
@ -640,7 +644,7 @@ static BMAPPINGLocal bmap[] = {
|
||||
{"", 187, Mapper187_Init},
|
||||
{"", 188, Mapper188_Init},
|
||||
{"", 189, Mapper189_Init},
|
||||
// {"", 190, Mapper190_Init},
|
||||
{"", 190, Mapper190_Init},
|
||||
{"", 191, Mapper191_Init},
|
||||
{"TW MMC3+VRAM Rev. B", 192, Mapper192_Init},
|
||||
{"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 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}
|
||||
};
|
||||
|
||||
@ -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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -895,12 +911,15 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
|
||||
}
|
||||
|
||||
GameInterface = iNESGI;
|
||||
currCartInfo = &iNESCart;
|
||||
FCEU_printf("\n");
|
||||
|
||||
// since apparently the iNES format doesn't store this information,
|
||||
// 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?
|
||||
if (OverwriteVidMode) {
|
||||
if (iNES2) {
|
||||
FCEUI_SetVidSystem(((head.TV_system & 3) == 1) ? 1 : 0);
|
||||
} else if (OverwriteVidMode) {
|
||||
if (strstr(name, "(E)") || strstr(name, "(e)")
|
||||
|| strstr(name, "(Europe)") || strstr(name, "(PAL)")
|
||||
|| strstr(name, "(F)") || strstr(name, "(f)")
|
||||
@ -990,6 +1009,7 @@ static int iNES_Init(int num) {
|
||||
case 6:
|
||||
case 29:
|
||||
case 30:
|
||||
case 45:
|
||||
case 96: CHRRAMSize = 32 * 1024; break;
|
||||
case 176: CHRRAMSize = 128 * 1024; break;
|
||||
default: CHRRAMSize = 8 * 1024; break;
|
||||
@ -1004,8 +1024,18 @@ static int iNES_Init(int num) {
|
||||
FCEU_MemoryRand(VROM, CHRRAMSize);
|
||||
|
||||
UNIFchrrama = VROM;
|
||||
SetupCartCHRMapping(0, VROM, CHRRAMSize, 1);
|
||||
AddExState(VROM, CHRRAMSize, 0, "CHRR");
|
||||
if(CHRRAMSize == 0)
|
||||
{
|
||||
//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)
|
||||
AddExState(ExtraNTARAM, 2048, 0, "EXNR");
|
||||
|
@ -177,6 +177,7 @@ void Mapper105_Init(CartInfo *);
|
||||
void Mapper106_Init(CartInfo *);
|
||||
void Mapper107_Init(CartInfo *);
|
||||
void Mapper108_Init(CartInfo *);
|
||||
void Mapper111_Init(CartInfo *);
|
||||
void Mapper112_Init(CartInfo *);
|
||||
void Mapper113_Init(CartInfo *);
|
||||
void Mapper114_Init(CartInfo *);
|
||||
|
@ -62,6 +62,8 @@ extern INPUTC *FCEU_InitZapper(int w);
|
||||
extern INPUTC *FCEU_InitPowerpadA(int w);
|
||||
extern INPUTC *FCEU_InitPowerpadB(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_InitSpaceShadow(void);
|
||||
@ -88,6 +90,7 @@ extern bool movieSubtitles;
|
||||
|
||||
static uint8 joy_readbit[2];
|
||||
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;
|
||||
uint8 RawReg4016 = 0; // Joystick strobe (W)
|
||||
|
||||
@ -107,6 +110,9 @@ static bool FSAttached = false;
|
||||
JOYPORT joyports[2] = { JOYPORT(0), JOYPORT(1) };
|
||||
FCPORT portFC;
|
||||
|
||||
FILE* DumpInputFile;
|
||||
FILE* PlayInputFile;
|
||||
|
||||
static DECLFR(JPRead)
|
||||
{
|
||||
lagFlag = 0;
|
||||
@ -139,6 +145,12 @@ static DECLFR(JPRead)
|
||||
}
|
||||
}
|
||||
|
||||
if(PlayInputFile)
|
||||
ret = fgetc(PlayInputFile);
|
||||
|
||||
if(DumpInputFile)
|
||||
fputc(ret,DumpInputFile);
|
||||
|
||||
ret|=X.DB&0xC0;
|
||||
|
||||
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 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)
|
||||
{
|
||||
@ -325,7 +392,7 @@ void FCEU_UpdateInput(void)
|
||||
{
|
||||
for(int port=0;port<2;port++){
|
||||
joyports[port].driver->Update(port,joyports[port].ptr,joyports[port].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?
|
||||
if(GameInfo->type==GIT_VSUNI){
|
||||
FCEU_VSUniSwap(&joy[0],&joy[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(VSUNIRead0)
|
||||
@ -386,9 +453,12 @@ static void SetInputStuff(int port)
|
||||
case SI_GAMEPAD:
|
||||
if(GameInfo->type==GIT_VSUNI){
|
||||
joyports[port].driver = &GPCVS;
|
||||
} else {
|
||||
} else {
|
||||
joyports[port].driver= &GPC;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SI_SNES:
|
||||
joyports[port].driver= &GPSNES;
|
||||
break;
|
||||
case SI_ARKANOID:
|
||||
joyports[port].driver=FCEU_InitArkanoid(port);
|
||||
@ -402,6 +472,12 @@ static void SetInputStuff(int port)
|
||||
case SI_POWERPADB:
|
||||
joyports[port].driver=FCEU_InitPowerpadB(port);
|
||||
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:
|
||||
joyports[port].driver=&DummyJPort;
|
||||
break;
|
||||
@ -665,10 +741,11 @@ static void RamSearchOpLTE(void);
|
||||
static void RamSearchOpGTE(void);
|
||||
static void RamSearchOpEQ(void);
|
||||
static void RamSearchOpNE(void);
|
||||
static void DebuggerStepInto(void);
|
||||
static void FA_SkipLag(void);
|
||||
static void OpenRom(void);
|
||||
static void CloseRom(void);
|
||||
static void ReloadRom(void);
|
||||
void ReloadRom(void);
|
||||
static void MovieSubtitleToggle(void);
|
||||
static void UndoRedoSavestate(void);
|
||||
static void FCEUI_DoExit(void);
|
||||
@ -680,134 +757,139 @@ extern void FCEUI_ToggleShowFPS();
|
||||
|
||||
struct EMUCMDTABLE FCEUI_CommandTable[]=
|
||||
{
|
||||
{ EMUCMD_POWER, EMUCMDTYPE_MISC, FCEUI_PowerNES, 0, 0, "Power", 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_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_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_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_POWER, EMUCMDTYPE_MISC, FCEUI_PowerNES, 0, 0, "Power", 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_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_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_SAVE_SLOT_0, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 0", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_SAVE_SLOT_1, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 1", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_SAVE_SLOT_2, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 2", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_SAVE_SLOT_3, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 3", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_SAVE_SLOT_4, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 4", 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_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_MOVIE_RECORD_TO, EMUCMDTYPE_MOVIE, FCEUD_MovieRecordTo, 0, 0, "Record Movie To...", 0 },
|
||||
{ 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_SAVE_SLOT_0, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 0", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_SAVE_SLOT_1, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 1", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_SAVE_SLOT_2, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 2", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_SAVE_SLOT_3, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 3", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_SAVE_SLOT_4, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 4", 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_ICON_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUD_ToggleStatusIcon, 0, 0, "Toggle Status Icon", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MOVIE_RECORD_TO, EMUCMDTYPE_MOVIE, FCEUD_MovieRecordTo, 0, 0, "Record Movie To...", 0 },
|
||||
{ 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
|
||||
{ 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
|
||||
|
||||
{ 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_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_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_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_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_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_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_EJECT_INSERT, EMUCMDTYPE_FDS, FCEUI_FDSInsert, 0, 0, "Eject or Insert FDS Disk", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_FDS_SIDE_SELECT, EMUCMDTYPE_FDS, FCEUI_FDSSelect, 0, 0, "Switch FDS Disk Side", EMUCMDFLAG_TASEDITOR },
|
||||
|
||||
{ EMUCMD_VSUNI_COIN, EMUCMDTYPE_VSUNI, FCEUI_VSUniCoin, 0, 0, "Insert Coin", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_0, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 0", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_1, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 1", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_2, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 2", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_3, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 3", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_4, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 4", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_5, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 5", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_6, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 6", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_7, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 7", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_8, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 8", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_9, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 9", 0 },
|
||||
{ EMUCMD_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_USE_INPUT_PRESET_1, EMUCMDTYPE_MISC, CommandUsePreset, 0, 0, "Use Input Preset 1", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_USE_INPUT_PRESET_2, EMUCMDTYPE_MISC, CommandUsePreset, 0, 0, "Use Input Preset 2", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_USE_INPUT_PRESET_3, EMUCMDTYPE_MISC, CommandUsePreset, 0, 0, "Use Input Preset 3", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_DISPLAY_BG_TOGGLE, EMUCMDTYPE_MISC, BackgroundDisplayToggle, 0, 0, "Toggle Background Display", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_DISPLAY_OBJ_TOGGLE, EMUCMDTYPE_MISC, ObjectDisplayToggle, 0, 0, "Toggle Object Display", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_DISPLAY_LAGCOUNTER_TOGGLE,EMUCMDTYPE_MISC, LagCounterToggle, 0, 0, "Lag Counter Toggle", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_OPENTASEDITOR, EMUCMDTYPE_TOOL, LaunchTasEditor, 0, 0, "Open TAS Editor", 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_TOOL_OPENDEBUGGER, EMUCMDTYPE_TOOL, LaunchDebugger, 0, 0, "Open Debugger", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_OPENHEX, EMUCMDTYPE_TOOL, LaunchHex, 0, 0, "Open Hex Editor", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_OPENPPU, EMUCMDTYPE_TOOL, LaunchPPU, 0, 0, "Open PPU Viewer", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_OPENNTVIEW, EMUCMDTYPE_TOOL, LaunchNTView, 0, 0, "Open Name Table Viewer", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_OPENTRACELOGGER, EMUCMDTYPE_TOOL, LaunchTraceLogger, 0, 0, "Open Trace Logger", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_OPENCDLOGGER, EMUCMDTYPE_TOOL, LaunchCodeDataLogger, 0, 0, "Open Code/Data Logger", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_FRAMEADV_SKIPLAG, EMUCMDTYPE_MISC, FA_SkipLag, 0, 0, "Frame Adv.-Skip Lag", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_OPENROM, EMUCMDTYPE_TOOL, OpenRom, 0, 0, "Open ROM", 0},
|
||||
{ EMUCMD_CLOSEROM, EMUCMDTYPE_TOOL, CloseRom, 0, 0, "Close ROM", 0},
|
||||
{ EMUCMD_RELOAD, EMUCMDTYPE_TOOL, ReloadRom, 0, 0, "Reload ROM or TAS Editor Project", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_DISPLAY_MOVIESUBTITLES, EMUCMDTYPE_MISC, MovieSubtitleToggle,0,0,"Toggle Movie Subtitles", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_UNDOREDOSAVESTATE, EMUCMDTYPE_MISC, UndoRedoSavestate, 0,0,"Undo/Redo Savestate", 0},
|
||||
{ EMUCMD_MISC_TOGGLEFULLSCREEN, EMUCMDTYPE_MISC, ToggleFullscreen, 0, 0, "Toggle Fullscreen", 0},
|
||||
{ EMUCMD_TOOL_OPENRAMWATCH, EMUCMDTYPE_TOOL, LaunchRamWatch, 0, 0, "Open Ram Watch", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_OPENRAMSEARCH, EMUCMDTYPE_TOOL, LaunchRamSearch, 0, 0, "Open Ram Search", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_RAMSEARCHLT, EMUCMDTYPE_TOOL, RamSearchOpLT, 0, 0, "Ram Search - Less Than", 0},
|
||||
{ EMUCMD_TOOL_RAMSEARCHGT, EMUCMDTYPE_TOOL, RamSearchOpGT, 0, 0, "Ram Search - Greater Than", 0},
|
||||
{ EMUCMD_TOOL_RAMSEARCHLTE, EMUCMDTYPE_TOOL, RamSearchOpLTE, 0, 0, "Ram Search - Less Than or Equal", 0},
|
||||
{ EMUCMD_TOOL_RAMSEARCHGTE, EMUCMDTYPE_TOOL, RamSearchOpGTE, 0, 0, "Ram Search - Greater Than or Equal", 0},
|
||||
{ EMUCMD_TOOL_RAMSEARCHEQ, EMUCMDTYPE_TOOL, RamSearchOpEQ, 0, 0, "Ram Search - Equal", 0},
|
||||
{ EMUCMD_TOOL_RAMSEARCHNE, EMUCMDTYPE_TOOL, RamSearchOpNE, 0, 0, "Ram Search - Not Equal", 0},
|
||||
{ EMUCMD_RERECORD_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_MovieToggleRerecordDisplay, 0, 0, "Toggle Rerecord Display", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TASEDITOR_REWIND, EMUCMDTYPE_TASEDITOR, TaseditorRewindOn, TaseditorRewindOff, 0, "Frame Rewind", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TASEDITOR_RESTORE_PLAYBACK, EMUCMDTYPE_TASEDITOR, TaseditorCommand, 0, 0, "Restore Playback", 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_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_VSUNI_COIN, EMUCMDTYPE_VSUNI, FCEUI_VSUniCoin, 0, 0, "Insert Coin", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_0, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 0", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_1, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 1", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_2, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 2", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_3, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 3", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_4, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 4", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_5, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 5", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_6, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 6", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_7, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 7", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_8, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 8", 0 },
|
||||
{ EMUCMD_VSUNI_TOGGLE_DIP_9, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 9", 0 },
|
||||
|
||||
{ EMUCMD_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_USE_INPUT_PRESET_1, EMUCMDTYPE_MISC, CommandUsePreset, 0, 0, "Use Input Preset 1", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_USE_INPUT_PRESET_2, EMUCMDTYPE_MISC, CommandUsePreset, 0, 0, "Use Input Preset 2", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_USE_INPUT_PRESET_3, EMUCMDTYPE_MISC, CommandUsePreset, 0, 0, "Use Input Preset 3", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_DISPLAY_BG_TOGGLE, EMUCMDTYPE_MISC, BackgroundDisplayToggle, 0, 0, "Toggle Background Display", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_DISPLAY_OBJ_TOGGLE, EMUCMDTYPE_MISC, ObjectDisplayToggle, 0, 0, "Toggle Object Display", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_DISPLAY_LAGCOUNTER_TOGGLE,EMUCMDTYPE_MISC, LagCounterToggle, 0, 0, "Lag Counter Toggle", EMUCMDFLAG_TASEDITOR },
|
||||
|
||||
{ EMUCMD_MISC_OPENTASEDITOR, EMUCMDTYPE_TOOL, LaunchTasEditor, 0, 0, "Open TAS Editor", 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_TOOL_OPENDEBUGGER, EMUCMDTYPE_TOOL, LaunchDebugger, 0, 0, "Open Debugger", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_OPENHEX, EMUCMDTYPE_TOOL, LaunchHex, 0, 0, "Open Hex Editor", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_OPENPPU, EMUCMDTYPE_TOOL, LaunchPPU, 0, 0, "Open PPU Viewer", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_OPENNTVIEW, EMUCMDTYPE_TOOL, LaunchNTView, 0, 0, "Open Name Table Viewer", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_OPENTRACELOGGER, EMUCMDTYPE_TOOL, LaunchTraceLogger, 0, 0, "Open Trace Logger", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_OPENCDLOGGER, EMUCMDTYPE_TOOL, LaunchCodeDataLogger, 0, 0, "Open Code/Data Logger", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_FRAMEADV_SKIPLAG, EMUCMDTYPE_MISC, FA_SkipLag, 0, 0, "Frame Adv.-Skip Lag", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_OPENROM, EMUCMDTYPE_TOOL, OpenRom, 0, 0, "Open ROM", 0},
|
||||
{ EMUCMD_CLOSEROM, EMUCMDTYPE_TOOL, CloseRom, 0, 0, "Close ROM", 0},
|
||||
{ EMUCMD_RELOAD, EMUCMDTYPE_TOOL, ReloadRom, 0, 0, "Reload ROM or TAS Editor Project", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_DISPLAY_MOVIESUBTITLES, EMUCMDTYPE_MISC, MovieSubtitleToggle, 0, 0, "Toggle Movie Subtitles", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_MISC_UNDOREDOSAVESTATE, EMUCMDTYPE_MISC, UndoRedoSavestate, 0, 0, "Undo/Redo Savestate", 0},
|
||||
{ EMUCMD_MISC_TOGGLEFULLSCREEN, EMUCMDTYPE_MISC, ToggleFullscreen, 0, 0, "Toggle Fullscreen", 0},
|
||||
{ EMUCMD_TOOL_OPENRAMWATCH, EMUCMDTYPE_TOOL, LaunchRamWatch, 0, 0, "Open Ram Watch", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_OPENRAMSEARCH, EMUCMDTYPE_TOOL, LaunchRamSearch, 0, 0, "Open Ram Search", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TOOL_RAMSEARCHLT, EMUCMDTYPE_TOOL, RamSearchOpLT, 0, 0, "Ram Search - Less Than", 0},
|
||||
{ EMUCMD_TOOL_RAMSEARCHGT, EMUCMDTYPE_TOOL, RamSearchOpGT, 0, 0, "Ram Search - Greater Than", 0},
|
||||
{ EMUCMD_TOOL_RAMSEARCHLTE, EMUCMDTYPE_TOOL, RamSearchOpLTE, 0, 0, "Ram Search - Less Than or Equal", 0},
|
||||
{ EMUCMD_TOOL_RAMSEARCHGTE, EMUCMDTYPE_TOOL, RamSearchOpGTE, 0, 0, "Ram Search - Greater Than or Equal", 0},
|
||||
{ EMUCMD_TOOL_RAMSEARCHEQ, EMUCMDTYPE_TOOL, RamSearchOpEQ, 0, 0, "Ram Search - Equal", 0},
|
||||
{ EMUCMD_TOOL_RAMSEARCHNE, EMUCMDTYPE_TOOL, RamSearchOpNE, 0, 0, "Ram Search - Not Equal", 0},
|
||||
{ EMUCMD_RERECORD_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_MovieToggleRerecordDisplay,0, 0, "Toggle Rerecord Display", EMUCMDFLAG_TASEDITOR },
|
||||
|
||||
{ EMUCMD_TASEDITOR_REWIND, EMUCMDTYPE_TASEDITOR, TaseditorRewindOn, TaseditorRewindOff, 0, "Frame Rewind", EMUCMDFLAG_TASEDITOR },
|
||||
{ EMUCMD_TASEDITOR_RESTORE_PLAYBACK, EMUCMDTYPE_TASEDITOR, TaseditorCommand, 0, 0, "Restore Playback", 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_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]))
|
||||
@ -1119,6 +1201,17 @@ static void RamSearchOpNE(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void DebuggerStepInto()
|
||||
{
|
||||
#ifdef WIN32
|
||||
if (GameInfo)
|
||||
{
|
||||
extern void DoDebuggerStepInto();
|
||||
DoDebuggerStepInto();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void FA_SkipLag(void)
|
||||
{
|
||||
frameAdvanceLagSkip ^= 1;
|
||||
@ -1139,7 +1232,7 @@ static void CloseRom(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ReloadRom(void)
|
||||
void ReloadRom(void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||
|
@ -8,6 +8,10 @@
|
||||
|
||||
void LagCounterToggle(void);
|
||||
|
||||
extern FILE* PlayInputFile;
|
||||
extern FILE* DumpInputFile;
|
||||
|
||||
|
||||
class MovieRecord;
|
||||
|
||||
//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...
|
||||
EMUCMD_FPS_DISPLAY_TOGGLE,
|
||||
EMUCMD_TOOL_DEBUGSTEPINTO,
|
||||
|
||||
EMUCMD_MAX
|
||||
};
|
||||
|
@ -18,64 +18,66 @@
|
||||
* 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 <stdlib.h>
|
||||
#include "share.h"
|
||||
|
||||
typedef struct {
|
||||
int32 mzx, mzy, mzxold, mzyold;
|
||||
uint32 readbit;
|
||||
uint32 data;
|
||||
uint8 latch;
|
||||
int32 dx,dy;
|
||||
uint32 mb;
|
||||
} 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
uint8 ret=0;
|
||||
if(Mouse.readbit>=8)
|
||||
ret|=1;
|
||||
else
|
||||
{
|
||||
ret|=(Mouse.data>>Mouse.readbit)&1;
|
||||
if(!fceuindbg)
|
||||
Mouse.readbit++;
|
||||
}
|
||||
return(ret);
|
||||
uint8 result = Mouse.latch & 0x01;
|
||||
Mouse.latch = (Mouse.latch >> 1) | 0x80;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void UpdateMOUSE(int w, void *data, int arg)
|
||||
{
|
||||
uint32 *ptr=(uint32*)data;
|
||||
Mouse.data=0;
|
||||
Mouse.mzxold=Mouse.mzx;
|
||||
Mouse.mzyold=Mouse.mzy;
|
||||
Mouse.mzx=ptr[0];
|
||||
Mouse.mzy=ptr[1];
|
||||
Mouse.data|=ptr[2];
|
||||
if((Mouse.mzxold-Mouse.mzx)>0)
|
||||
Mouse.data|=0x0C;
|
||||
else if((Mouse.mzxold-Mouse.mzx)<0)
|
||||
Mouse.data|=0x04;
|
||||
if((Mouse.mzyold-Mouse.mzy)>0)
|
||||
Mouse.data|=0x30;
|
||||
else if((Mouse.mzyold-Mouse.mzy)<0)
|
||||
Mouse.data|=0x10;
|
||||
uint32 *ptr=(uint32*)data;
|
||||
Mouse.dx += ptr[0]; ptr[0] = 0;
|
||||
Mouse.dy += ptr[1]; ptr[1] = 0;
|
||||
Mouse.mb = ptr[2];
|
||||
|
||||
if (Mouse.dx > INERTIA) Mouse.dx = INERTIA;
|
||||
else if (Mouse.dx < -INERTIA) Mouse.dx = -INERTIA;
|
||||
|
||||
if (Mouse.dy > INERTIA) Mouse.dy = INERTIA;
|
||||
else if (Mouse.dy < -INERTIA) Mouse.dy = -INERTIA;
|
||||
}
|
||||
|
||||
static INPUTC MOUSEC={ReadMOUSE,0,StrobeMOUSE,UpdateMOUSE,0,0};
|
||||
|
||||
INPUTC *FCEU_InitMouse(int w)
|
||||
{
|
||||
Mouse.mzx=0;
|
||||
Mouse.mzy=0;
|
||||
Mouse.mzxold=0;
|
||||
Mouse.mzyold=0;
|
||||
Mouse.data=0;
|
||||
return(&MOUSEC);
|
||||
memset(&Mouse,0,sizeof(Mouse));
|
||||
return(&MOUSEC);
|
||||
}
|
||||
|
@ -1,96 +1,96 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "share.h"
|
||||
#include "suborkb.h"
|
||||
|
||||
#define AK(x) FKB_ ## x
|
||||
|
||||
static uint8 bufit[0x66];
|
||||
static uint8 kspos, kstrobe;
|
||||
static uint8 ksindex;
|
||||
|
||||
//TODO: check all keys, some of the are wrong
|
||||
|
||||
static uint16 matrix[13][8] =
|
||||
{
|
||||
{ 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(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) },
|
||||
{ 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(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(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(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(INSERT),AK(NUMPAD1),AK(HOME),AK(PRIOR),AK(DELETE),AK(END),AK(NEXT),AK(NUMLOCK) },
|
||||
};
|
||||
|
||||
static void PEC586KB_Write(uint8 v) {
|
||||
if (!(kstrobe & 2) && (v & 2)) {
|
||||
kspos = 0;
|
||||
}
|
||||
if ((kstrobe & 1) && !(v & 1)) {
|
||||
ksindex = 0;
|
||||
}
|
||||
if ((kstrobe & 4) && !(v & 4)) {
|
||||
kspos++;
|
||||
kspos %= 13;
|
||||
}
|
||||
kstrobe = v;
|
||||
}
|
||||
|
||||
static uint8 PEC586KB_Read(int w, uint8 ret) {
|
||||
#ifdef FCEUDEF_DEBUGGER
|
||||
if (!fceuindbg) {
|
||||
#endif
|
||||
if (w) {
|
||||
ret &= ~2;
|
||||
if(bufit[matrix[kspos][7-ksindex]])
|
||||
ret |= 2;
|
||||
ksindex++;
|
||||
ksindex&=7;
|
||||
}
|
||||
#ifdef FCEUDEF_DEBUGGER
|
||||
}
|
||||
#endif
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void PEC586KB_Strobe(void) {
|
||||
// kstrobe = 0;
|
||||
// ksindex = 0;
|
||||
}
|
||||
|
||||
static void PEC586KB_Update(void *data, int arg) {
|
||||
memcpy(bufit + 1, data, sizeof(bufit) - 1);
|
||||
}
|
||||
|
||||
static INPUTCFC PEC586KB = { PEC586KB_Read, PEC586KB_Write, PEC586KB_Strobe, PEC586KB_Update, 0, 0 };
|
||||
|
||||
INPUTCFC *FCEU_InitPEC586KB(void) {
|
||||
memset(bufit, 0, sizeof(bufit));
|
||||
kspos = ksindex = kstrobe = 0;
|
||||
return(&PEC586KB);
|
||||
}
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "share.h"
|
||||
#include "suborkb.h"
|
||||
|
||||
#define AK(x) FKB_ ## x
|
||||
|
||||
static uint8 bufit[0x66];
|
||||
static uint8 kspos, kstrobe;
|
||||
static uint8 ksindex;
|
||||
|
||||
//TODO: check all keys, some of the are wrong
|
||||
|
||||
static uint16 matrix[13][8] =
|
||||
{
|
||||
{ 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(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) },
|
||||
{ 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(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(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(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(INSERT),AK(NUMPAD1),AK(HOME),AK(PRIOR),AK(DELETE),AK(END),AK(NEXT),AK(NUMLOCK) },
|
||||
};
|
||||
|
||||
static void PEC586KB_Write(uint8 v) {
|
||||
if (!(kstrobe & 2) && (v & 2)) {
|
||||
kspos = 0;
|
||||
}
|
||||
if ((kstrobe & 1) && !(v & 1)) {
|
||||
ksindex = 0;
|
||||
}
|
||||
if ((kstrobe & 4) && !(v & 4)) {
|
||||
kspos++;
|
||||
kspos %= 13;
|
||||
}
|
||||
kstrobe = v;
|
||||
}
|
||||
|
||||
static uint8 PEC586KB_Read(int w, uint8 ret) {
|
||||
#ifdef FCEUDEF_DEBUGGER
|
||||
if (!fceuindbg) {
|
||||
#endif
|
||||
if (w) {
|
||||
ret &= ~2;
|
||||
if(bufit[matrix[kspos][7-ksindex]])
|
||||
ret |= 2;
|
||||
ksindex++;
|
||||
ksindex&=7;
|
||||
}
|
||||
#ifdef FCEUDEF_DEBUGGER
|
||||
}
|
||||
#endif
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void PEC586KB_Strobe(void) {
|
||||
// kstrobe = 0;
|
||||
// ksindex = 0;
|
||||
}
|
||||
|
||||
static void PEC586KB_Update(void *data, int arg) {
|
||||
memcpy(bufit + 1, data, sizeof(bufit) - 1);
|
||||
}
|
||||
|
||||
static INPUTCFC PEC586KB = { PEC586KB_Read, PEC586KB_Write, PEC586KB_Strobe, PEC586KB_Update, 0, 0 };
|
||||
|
||||
INPUTCFC *FCEU_InitPEC586KB(void) {
|
||||
memset(bufit, 0, sizeof(bufit));
|
||||
kspos = ksindex = kstrobe = 0;
|
||||
return(&PEC586KB);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "file.h"
|
||||
#include "video.h"
|
||||
#include "movie.h"
|
||||
#include "cart.h"
|
||||
#include "fds.h"
|
||||
#include "vsuni.h"
|
||||
#ifdef _S9XLUA_H
|
||||
@ -34,6 +35,9 @@ extern void AddRecentMovieFile(const char *filename);
|
||||
extern bool mustEngageTaseditor;
|
||||
#endif
|
||||
|
||||
extern int RAMInitOption;
|
||||
extern int RAMInitSeed;
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
@ -107,7 +111,6 @@ int currRerecordCount; // Keep the global value
|
||||
|
||||
char lagcounterbuf[32] = {0};
|
||||
|
||||
|
||||
#ifdef GEKKO
|
||||
void MovieData::clearRecordRange(int start, int len) { }
|
||||
void MovieData::eraseRecords(int at, int frames) { }
|
||||
@ -454,8 +457,11 @@ void MovieRecord::dump(MovieData* md, EMUFILE* os, int index)
|
||||
MovieData::MovieData()
|
||||
: version(MOVIE_VERSION)
|
||||
, emuVersion(FCEU_VERSION_NUMERIC)
|
||||
, fds(false)
|
||||
, palFlag(false)
|
||||
, PPUflag(false)
|
||||
, RAMInitOption(0)
|
||||
, RAMInitSeed(0)
|
||||
, rerecordCount(0)
|
||||
, binaryFlag(false)
|
||||
, loadFrameCount(-1)
|
||||
@ -476,6 +482,10 @@ void MovieData::installValue(std::string& key, std::string& val)
|
||||
installInt(val,fds);
|
||||
else if(key == "NewPPU")
|
||||
installBool(val,PPUflag);
|
||||
else if(key == "RAMInitOption")
|
||||
installInt(val,RAMInitOption);
|
||||
else if(key == "RAMInitSeed")
|
||||
installInt(val,RAMInitSeed);
|
||||
else if(key == "version")
|
||||
installInt(val,version);
|
||||
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
|
||||
}
|
||||
}
|
||||
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")
|
||||
{
|
||||
installInt(val, loadFrameCount);
|
||||
@ -539,6 +559,8 @@ int MovieData::dump(EMUFILE *os, bool binary)
|
||||
os->fprintf("port2 %d\n" , ports[2] );
|
||||
os->fprintf("FDS %d\n" , fds?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++)
|
||||
os->fprintf("comment %s\n" , wcstombs(comments[i]).c_str() );
|
||||
@ -552,6 +574,9 @@ int MovieData::dump(EMUFILE *os, bool binary)
|
||||
if(savestate.size())
|
||||
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)
|
||||
os->fprintf("length %d\n" , this->loadFrameCount);
|
||||
|
||||
@ -831,6 +856,8 @@ void FCEUI_StopMovie()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool bogorf;
|
||||
|
||||
void poweron(bool shouldDisableBatteryLoading)
|
||||
{
|
||||
//// make a for-movie-recording power-on clear the game's save data, too
|
||||
@ -855,9 +882,9 @@ void poweron(bool shouldDisableBatteryLoading)
|
||||
//suppressAddPowerCommand=0;
|
||||
|
||||
extern int disableBatteryLoading;
|
||||
disableBatteryLoading = 1;
|
||||
if(!bogorf) disableBatteryLoading = 1;
|
||||
PowerNES();
|
||||
disableBatteryLoading = 0;
|
||||
if(!bogorf) disableBatteryLoading = 0;
|
||||
}
|
||||
|
||||
void FCEUMOV_CreateCleanMovie()
|
||||
@ -874,6 +901,8 @@ void FCEUMOV_CreateCleanMovie()
|
||||
currMovieData.ports[2] = portFC.type;
|
||||
currMovieData.fds = isFDS;
|
||||
currMovieData.PPUflag = (newppu != 0);
|
||||
currMovieData.RAMInitOption = RAMInitOption;
|
||||
currMovieData.RAMInitSeed = RAMInitSeed;
|
||||
}
|
||||
void FCEUMOV_ClearCommands()
|
||||
{
|
||||
@ -897,6 +926,59 @@ void MovieData::dumpSavestateTo(std::vector<uint8>* buf, int compressionLevel)
|
||||
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
|
||||
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);
|
||||
delete fp;
|
||||
|
||||
RAMInitOption = currMovieData.RAMInitOption;
|
||||
RAMInitSeed = currMovieData.RAMInitSeed;
|
||||
|
||||
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
|
||||
//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;
|
||||
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?
|
||||
} 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;
|
||||
}
|
||||
|
||||
@ -960,6 +1052,8 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
|
||||
else
|
||||
FCEUI_SetVidSystem(0);
|
||||
|
||||
|
||||
|
||||
//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]);
|
||||
|
||||
@ -1027,7 +1121,15 @@ void FCEUI_SaveMovie(const char *fname, EMOVIE_FLAG flags, std::wstring author)
|
||||
movieFromPoweron = 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;
|
||||
MovieData::dumpSavestateTo(&currMovieData.savestate,Z_BEST_COMPRESSION);
|
||||
@ -1481,7 +1583,7 @@ void FCEUMOV_IncrementRerecordCount()
|
||||
else
|
||||
currMovieData.rerecordCount++;
|
||||
#else
|
||||
if (movieMode != MOVIEMODE_TASEDITOR)currRerecordCount++;
|
||||
if (movieMode != MOVIEMODE_TASEDITOR)
|
||||
currRerecordCount++;
|
||||
else
|
||||
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.pal = md.palFlag;
|
||||
info.ppuflag = md.PPUflag;
|
||||
info.RAMInitOption = md.RAMInitOption;
|
||||
info.RAMInitSeed = md.RAMInitSeed;
|
||||
info.nosynchack = true;
|
||||
info.num_frames = md.records.size();
|
||||
info.md5_of_rom_used = md.romChecksum;
|
||||
|
@ -23,13 +23,15 @@ enum EMOVIE_FLAG
|
||||
|
||||
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),
|
||||
|
||||
// set in newer version, used for old movie compatibility
|
||||
//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
|
||||
MOVIE_FLAG_NOSYNCHACK = (1<<4)
|
||||
MOVIE_FLAG_NOSYNCHACK = (1<<4),
|
||||
|
||||
MOVIE_FLAG_FROM_SAVERAM = (1<<5)
|
||||
};
|
||||
|
||||
typedef struct
|
||||
@ -42,6 +44,7 @@ typedef struct
|
||||
uint32 emu_version_used; // 9813 = 0.98.13
|
||||
MD5DATA md5_of_rom_used;
|
||||
std::string name_of_rom_used;
|
||||
int RAMInitOption, RAMInitSeed;
|
||||
|
||||
std::vector<std::wstring> comments;
|
||||
std::vector<std::string> subtitles;
|
||||
@ -177,6 +180,7 @@ public:
|
||||
MD5DATA romChecksum;
|
||||
std::string romFilename;
|
||||
std::vector<uint8> savestate;
|
||||
std::vector<uint8> saveram;
|
||||
std::vector<MovieRecord> records;
|
||||
std::vector<std::wstring> comments;
|
||||
std::vector<std::string> subtitles;
|
||||
@ -198,6 +202,8 @@ public:
|
||||
|
||||
int getNumRecords() { return records.size(); }
|
||||
|
||||
int RAMInitOption, RAMInitSeed;
|
||||
|
||||
class TDictionary : public std::map<std::string,std::string>
|
||||
{
|
||||
public:
|
||||
@ -238,6 +244,9 @@ public:
|
||||
static bool loadSavestateFrom(std::vector<uint8>* buf);
|
||||
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:
|
||||
void installInt(std::string& val, int& var)
|
||||
{
|
||||
|
@ -119,7 +119,7 @@ int FCEUNET_SendFile(uint8 cmd, char *fn)
|
||||
|
||||
if(!(fp=FCEUD_UTF8fopen(fn,"rb"))) return(0);
|
||||
|
||||
fstat(fileno(fp),&sb);
|
||||
FCEUX_fstat(fileno(fp),&sb);
|
||||
len = sb.st_size;
|
||||
buf = (char*)FCEU_dmalloc(len); //mbg merge 7/17/06 added cast
|
||||
fread(buf, 1, len, fp);
|
||||
|
@ -482,6 +482,7 @@ void DrawNSF(uint8 *XBuf)
|
||||
if(vismode==0) return;
|
||||
|
||||
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);
|
||||
DrawTextTrans(ClipSidesOffset+XBuf+26*256+4+(((31-strlen((char*)NSFHeader.Artist))<<2)), 256,NSFHeader.Artist, 6);
|
||||
DrawTextTrans(ClipSidesOffset+XBuf+42*256+4+(((31-strlen((char*)NSFHeader.Copyright))<<2)), 256,NSFHeader.Copyright, 6);
|
||||
static const int kFgColor = 1;
|
||||
DrawTextTrans(ClipSidesOffset+XBuf+10*256+4+(((31-strlen((char*)NSFHeader.SongName))<<2)), 256, NSFHeader.SongName, kFgColor);
|
||||
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);
|
||||
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;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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"
|
||||
EMPTY_PALETTE_DEEMPH_X_7
|
||||
};
|
||||
|
||||
pal rp2c04002[64] = {
|
||||
pal rp2c04002[512] = {
|
||||
#include "rp2c04002.h"
|
||||
EMPTY_PALETTE_DEEMPH_X_7
|
||||
};
|
||||
|
||||
pal rp2c04003[64] = {
|
||||
pal rp2c04003[512] = {
|
||||
#include "rp2c04003.h"
|
||||
EMPTY_PALETTE_DEEMPH_X_7
|
||||
};
|
||||
pal rp2c05004[64] = {
|
||||
pal rp2c05004[512] = {
|
||||
#include "rp2c05004.h"
|
||||
EMPTY_PALETTE_DEEMPH_X_7
|
||||
};
|
||||
|
||||
pal unvpalette[7] = {
|
||||
{ 0x00<<2,0x00<<2,0x00<<2}, // Black
|
||||
{ 0x3F<<2,0x3F<<2,0x34<<2}, // White
|
||||
{ 0x00<<2,0x00<<2,0x00<<2}, // Black
|
||||
{ 0x1d<<2,0x1d<<2,0x24<<2}, // Greyish
|
||||
{ 190,0,0 }, // Redish
|
||||
{ 51,255,51}, // Bright green
|
||||
{ 49,14,200},
|
||||
// Fixed palette entries used by the GUI
|
||||
pal palette_unvarying[] = {
|
||||
{ 0x00<<2,0x00<<2,0x00<<2}, // 0 = Black
|
||||
{ 0x3F<<2,0x3F<<2,0x34<<2}, // 1 = White
|
||||
{ 0x00<<2,0x00<<2,0x00<<2}, // 2 = Black
|
||||
{ 0x1d<<2,0x1d<<2,0x24<<2}, // 3 = Greyish
|
||||
{ 190, 0, 0}, // 4 = Reddish
|
||||
{ 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
|
||||
pal palette[64] = {
|
||||
pal palette[512] = {
|
||||
|
||||
{ 0x1D<<2, 0x1D<<2, 0x1D<<2 }, /* Value 0 */
|
||||
{ 0x09<<2, 0x06<<2, 0x23<<2 }, /* Value 1 */
|
||||
@ -292,4 +320,6 @@ slightly better but too dark:
|
||||
|
||||
*/
|
||||
|
||||
EMPTY_PALETTE_DEEMPH_X_7
|
||||
|
||||
};
|
||||
|
@ -19,45 +19,46 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "x6502.h"
|
||||
#include "fceu.h"
|
||||
#include "ppu.h"
|
||||
#include "nsf.h"
|
||||
#include "sound.h"
|
||||
#include "file.h"
|
||||
#include "utils/endian.h"
|
||||
#include "utils/memory.h"
|
||||
#include "types.h"
|
||||
#include "x6502.h"
|
||||
#include "fceu.h"
|
||||
#include "ppu.h"
|
||||
#include "nsf.h"
|
||||
#include "sound.h"
|
||||
#include "file.h"
|
||||
#include "utils/endian.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"
|
||||
#include "palette.h"
|
||||
#include "state.h"
|
||||
#include "video.h"
|
||||
#include "input.h"
|
||||
#include "driver.h"
|
||||
#include "debug.h"
|
||||
#define VBlankON (PPU[0] & 0x80) //Generate VBlank NMI
|
||||
#define Sprite16 (PPU[0] & 0x20) //Sprites 8x16/8x8
|
||||
#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
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#define SpriteON (PPU[1] & 0x10) //Show Sprite
|
||||
#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 VBlankON (PPU[0] & 0x80) //Generate VBlank NMI
|
||||
#define Sprite16 (PPU[0] & 0x20) //Sprites 8x16/8x8
|
||||
#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 SpriteLeft8 (PPU[1] & 0x04)
|
||||
#define BGLeft8 (PPU[1] & 0x02)
|
||||
|
||||
#define SpriteON (PPU[1] & 0x10) //Show Sprite
|
||||
#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 PPU_status (PPU[2])
|
||||
|
||||
#define SpriteLeft8 (PPU[1] & 0x04)
|
||||
#define BGLeft8 (PPU[1] & 0x02)
|
||||
|
||||
#define PPU_status (PPU[2])
|
||||
|
||||
#define Pal (PALRAM)
|
||||
#define READPAL(ofs) (PALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF))
|
||||
#define READUPAL(ofs) (UPALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF))
|
||||
|
||||
static void FetchSpriteData(void);
|
||||
static void RefreshLine(int lastpixel);
|
||||
@ -69,6 +70,8 @@ static uint32 ppulut1[256];
|
||||
static uint32 ppulut2[256];
|
||||
static uint32 ppulut3[128];
|
||||
|
||||
static bool new_ppu_reset = false;
|
||||
|
||||
int test = 0;
|
||||
|
||||
template<typename T, int BITS>
|
||||
@ -274,8 +277,24 @@ struct PPUREGS {
|
||||
v &= 1;
|
||||
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;
|
||||
|
||||
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) {
|
||||
int x;
|
||||
int y;
|
||||
@ -337,7 +356,7 @@ uint8 vtoggle = 0;
|
||||
uint8 XOffset = 0;
|
||||
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;
|
||||
|
||||
@ -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 VRAMADR(V) &VPage[(V) >> 10][(V)]
|
||||
|
||||
//mbg 8/6/08 - fix a bug relating to
|
||||
//"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)];
|
||||
}
|
||||
uint8* MMC5BGVRAMADR(uint32 A);
|
||||
|
||||
//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
|
||||
@ -420,7 +428,7 @@ inline void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) {
|
||||
}
|
||||
|
||||
volatile int rendercount, vromreadcount, undefinedvromcount, LogAddress = -1;
|
||||
unsigned char *cdloggervdata;
|
||||
unsigned char *cdloggervdata = NULL;
|
||||
unsigned int cdloggerVideoDataSize = 0;
|
||||
|
||||
int GetCHRAddress(int A) {
|
||||
@ -428,6 +436,19 @@ int GetCHRAddress(int A) {
|
||||
int result = &VPage[A >> 10][A] - CHRptr[0];
|
||||
if ((result >= 0) && (result < (int)cdloggerVideoDataSize))
|
||||
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;
|
||||
}
|
||||
@ -441,8 +462,28 @@ int GetCHRAddress(int A) {
|
||||
if (!(cdloggervdata[addr] & 1)) \
|
||||
{ \
|
||||
cdloggervdata[addr] |= 1; \
|
||||
if (!(cdloggervdata[addr] & 2)) undefinedvromcount--; \
|
||||
rendercount++; \
|
||||
if(cdloggerVideoDataSize) { \
|
||||
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;
|
||||
if (!(tmp & 3)) {
|
||||
if (!(tmp & 0xC))
|
||||
ret = PALRAM[0x00];
|
||||
ret = READPAL(0x00);
|
||||
else
|
||||
ret = UPALRAM[((tmp & 0xC) >> 2) - 1];
|
||||
ret = READUPAL(((tmp & 0xC) >> 2) - 1);
|
||||
} else
|
||||
ret = PALRAM[tmp & 0x1F];
|
||||
|
||||
if (GRAYSCALE)
|
||||
ret &= 0x30;
|
||||
ret = READPAL(tmp & 0x1F);
|
||||
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))
|
||||
|
||||
//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;
|
||||
|
||||
void ppu_getScroll(int &xpos, int &ypos) {
|
||||
@ -665,7 +703,7 @@ static DECLFR(A2007) {
|
||||
if (!DummyRead && (LogAddress != -1)) {
|
||||
if (!(cdloggervdata[LogAddress] & 2)) {
|
||||
cdloggervdata[LogAddress] |= 2;
|
||||
if (!(cdloggervdata[LogAddress] & 1)) undefinedvromcount--;
|
||||
if ((!(cdloggervdata[LogAddress] & 1)) && cdloggerVideoDataSize) undefinedvromcount--;
|
||||
vromreadcount++;
|
||||
}
|
||||
} else
|
||||
@ -683,13 +721,11 @@ static DECLFR(A2007) {
|
||||
//to get a gray color reading
|
||||
if (!(tmp & 3)) {
|
||||
if (!(tmp & 0xC))
|
||||
ret = PALRAM[0x00];
|
||||
ret = READPAL(0x00);
|
||||
else
|
||||
ret = UPALRAM[((tmp & 0xC) >> 2) - 1];
|
||||
ret = READUPAL(((tmp & 0xC) >> 2) - 1);
|
||||
} else
|
||||
ret = PALRAM[tmp & 0x1F];
|
||||
if (GRAYSCALE)
|
||||
ret &= 0x30;
|
||||
ret = READPAL(tmp & 0x1F);
|
||||
VRAMBuffer = CALL_PPUREAD(RefreshAddr - 0x1000);
|
||||
} else {
|
||||
if (debug_loggingCD && (RefreshAddr < 0x2000))
|
||||
@ -700,18 +736,18 @@ static DECLFR(A2007) {
|
||||
RefreshAddr = ppur.get_2007access();
|
||||
return ret;
|
||||
} else {
|
||||
|
||||
//OLDPPU
|
||||
FCEUPPU_LineUpdate();
|
||||
|
||||
if (tmp >= 0x3F00) { // Palette RAM tied directly to the output data, without VRAM buffer
|
||||
if (!(tmp & 3)) {
|
||||
if (!(tmp & 0xC))
|
||||
ret = PALRAM[0x00];
|
||||
ret = READPAL(0x00);
|
||||
else
|
||||
ret = UPALRAM[((tmp & 0xC) >> 2) - 1];
|
||||
ret = READUPAL(((tmp & 0xC) >> 2) - 1);
|
||||
} else
|
||||
ret = PALRAM[tmp & 0x1F];
|
||||
if (GRAYSCALE)
|
||||
ret &= 0x30;
|
||||
ret = READPAL(tmp & 0x1F);
|
||||
#ifdef FCEUDEF_DEBUGGER
|
||||
if (!fceuindbg)
|
||||
#endif
|
||||
@ -731,9 +767,14 @@ static DECLFR(A2007) {
|
||||
if (PPU_hook) PPU_hook(tmp);
|
||||
PPUGenLatch = VRAMBuffer;
|
||||
if (tmp < 0x2000) {
|
||||
|
||||
if (debug_loggingCD)
|
||||
LogAddress = GetCHRAddress(tmp);
|
||||
VRAMBuffer = VPage[tmp >> 10][tmp];
|
||||
if(MMC5Hack && newppu)
|
||||
VRAMBuffer = *MMC5BGVRAMADR(tmp);
|
||||
else
|
||||
VRAMBuffer = VPage[tmp >> 10][tmp];
|
||||
|
||||
} else if (tmp < 0x3F00)
|
||||
VRAMBuffer = vnapage[(tmp >> 10) & 0x3][tmp & 0x3FF];
|
||||
}
|
||||
@ -786,6 +827,8 @@ static DECLFW(B2000) {
|
||||
|
||||
static DECLFW(B2001) {
|
||||
FCEUPPU_LineUpdate();
|
||||
if (paldeemphswap)
|
||||
V = (V&0x9F)|((V&0x40)>>1)|((V&0x20)<<1);
|
||||
PPUGenLatch = V;
|
||||
PPU[1] = V;
|
||||
if (V & 0xE0)
|
||||
@ -881,6 +924,11 @@ static DECLFW(B2006) {
|
||||
static DECLFW(B2007) {
|
||||
uint32 tmp = RefreshAddr & 0x3FFF;
|
||||
|
||||
if (debug_loggingCD) {
|
||||
if(!cdloggerVideoDataSize && (tmp < 0x2000))
|
||||
cdloggervdata[tmp] = 0;
|
||||
}
|
||||
|
||||
if (newppu) {
|
||||
PPUGenLatch = V;
|
||||
RefreshAddr = ppur.get_2007access() & 0x3FFF;
|
||||
@ -1043,7 +1091,7 @@ static void RefreshLine(int lastpixel) {
|
||||
|
||||
if (!ScreenON && !SpriteON) {
|
||||
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;
|
||||
FCEU_dwmemset(Pline, tem, numtiles * 8);
|
||||
P += numtiles * 8;
|
||||
@ -1064,10 +1112,10 @@ static void RefreshLine(int lastpixel) {
|
||||
}
|
||||
|
||||
//Priority bits, needed for sprite emulation.
|
||||
Pal[0] |= 64;
|
||||
Pal[4] |= 64;
|
||||
Pal[8] |= 64;
|
||||
Pal[0xC] |= 64;
|
||||
PALRAM[0] |= 64;
|
||||
PALRAM[4] |= 64;
|
||||
PALRAM[8] |= 64;
|
||||
PALRAM[0xC] |= 64;
|
||||
|
||||
//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.
|
||||
@ -1145,15 +1193,15 @@ static void RefreshLine(int lastpixel) {
|
||||
#undef RefreshAddr
|
||||
|
||||
//Reverse changes made before.
|
||||
Pal[0] &= 63;
|
||||
Pal[4] &= 63;
|
||||
Pal[8] &= 63;
|
||||
Pal[0xC] &= 63;
|
||||
PALRAM[0] &= 63;
|
||||
PALRAM[4] &= 63;
|
||||
PALRAM[8] &= 63;
|
||||
PALRAM[0xC] &= 63;
|
||||
|
||||
RefreshAddr = smorkus;
|
||||
if (firsttile <= 2 && 2 < lasttile && !(PPU[1] & 2)) {
|
||||
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;
|
||||
*(uint32*)Plinef = *(uint32*)(Plinef + 4) = tem;
|
||||
}
|
||||
@ -1161,7 +1209,7 @@ static void RefreshLine(int lastpixel) {
|
||||
if (!ScreenON) {
|
||||
uint32 tem;
|
||||
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;
|
||||
|
||||
tcount = lasttile - firsttile;
|
||||
@ -1218,11 +1266,16 @@ static void Fixit1(void) {
|
||||
|
||||
void MMC5_hb(int); //Ugh ugh ugh.
|
||||
static void DoLine(void) {
|
||||
if (scanline >= 240 && scanline != totalscanlines) {
|
||||
X6502_Run(256 + 69);
|
||||
scanline++;
|
||||
X6502_Run(16);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
u8* dtarget = XDBuf + ((scanline < 240 ? scanline : 240) << 8);
|
||||
|
||||
if (MMC5Hack) MMC5_hb(scanline);
|
||||
|
||||
@ -1233,22 +1286,26 @@ static void DoLine(void) {
|
||||
uint32 tem;
|
||||
uint8 col;
|
||||
if (gNoBGFillColor == 0xFF)
|
||||
col = Pal[0];
|
||||
col = READPAL(0);
|
||||
else col = gNoBGFillColor;
|
||||
tem = col | (col << 8) | (col << 16) | (col << 24);
|
||||
tem |= 0x40404040;
|
||||
tem |= 0x40404040;
|
||||
FCEU_dwmemset(target, tem, 256);
|
||||
}
|
||||
|
||||
if (SpriteON)
|
||||
CopySprites(target);
|
||||
|
||||
if (ScreenON || SpriteON) { // Yes, very el-cheapo.
|
||||
//greyscale handling (mask some bits off the color) ? ? ?
|
||||
if (ScreenON || SpriteON)
|
||||
{
|
||||
if (PPU[1] & 0x01) {
|
||||
for (x = 63; x >= 0; x--)
|
||||
*(uint32*)&target[x << 2] = (*(uint32*)&target[x << 2]) & 0x30303030;
|
||||
}
|
||||
}
|
||||
|
||||
//some pathetic attempts at deemph
|
||||
if ((PPU[1] >> 5) == 0x7) {
|
||||
for (x = 63; x >= 0; x--)
|
||||
*(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0xc0c0c0c0;
|
||||
@ -1259,6 +1316,10 @@ static void DoLine(void) {
|
||||
for (x = 63; x >= 0; x--)
|
||||
*(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;
|
||||
|
||||
if (ScreenON || SpriteON)
|
||||
@ -1362,10 +1423,10 @@ static void FetchSpriteData(void) {
|
||||
C = VRAMADR(vadr);
|
||||
|
||||
if (SpriteON)
|
||||
RENDER_LOG(vadr);
|
||||
RENDER_LOGP(C);
|
||||
dst.ca[0] = C[0];
|
||||
if (SpriteON)
|
||||
RENDER_LOG(vadr + 8);
|
||||
RENDER_LOGP(C + 8);
|
||||
dst.ca[1] = C[8];
|
||||
dst.x = spr->x;
|
||||
dst.atr = spr->atr;
|
||||
@ -1414,14 +1475,14 @@ static void FetchSpriteData(void) {
|
||||
else
|
||||
C = VRAMADR(vadr);
|
||||
if (SpriteON)
|
||||
RENDER_LOG(vadr);
|
||||
RENDER_LOGP(C);
|
||||
dst.ca[0] = C[0];
|
||||
if (ns < 8) {
|
||||
PPU_hook(0x2000);
|
||||
PPU_hook(vadr);
|
||||
}
|
||||
if (SpriteON)
|
||||
RENDER_LOG(vadr + 8);
|
||||
RENDER_LOGP(C + 8);
|
||||
dst.ca[1] = C[8];
|
||||
dst.x = spr->x;
|
||||
dst.atr = spr->atr;
|
||||
@ -1466,7 +1527,7 @@ static void RefreshSprites(void) {
|
||||
|
||||
int x = spr->x;
|
||||
uint8 *C;
|
||||
uint8 *VB;
|
||||
int VB;
|
||||
|
||||
pixdata = ppulut1[spr->ca[0]] | ppulut2[spr->ca[1]];
|
||||
J = spr->ca[0] | spr->ca[1];
|
||||
@ -1488,75 +1549,75 @@ static void RefreshSprites(void) {
|
||||
}
|
||||
|
||||
C = sprlinebuf + x;
|
||||
VB = (PALRAM + 0x10) + ((atr & 3) << 2);
|
||||
VB = (0x10) + ((atr & 3) << 2);
|
||||
|
||||
if (atr & SP_BACK) {
|
||||
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;
|
||||
if (J & 0x40) C[6] = VB[pixdata & 3] | 0x40;
|
||||
if (J & 0x40) C[6] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||
pixdata >>= 4;
|
||||
if (J & 0x20) C[5] = VB[pixdata & 3] | 0x40;
|
||||
if (J & 0x20) C[5] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||
pixdata >>= 4;
|
||||
if (J & 0x10) C[4] = VB[pixdata & 3] | 0x40;
|
||||
if (J & 0x10) C[4] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||
pixdata >>= 4;
|
||||
if (J & 0x08) C[3] = VB[pixdata & 3] | 0x40;
|
||||
if (J & 0x08) C[3] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||
pixdata >>= 4;
|
||||
if (J & 0x04) C[2] = VB[pixdata & 3] | 0x40;
|
||||
if (J & 0x04) C[2] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||
pixdata >>= 4;
|
||||
if (J & 0x02) C[1] = VB[pixdata & 3] | 0x40;
|
||||
if (J & 0x02) C[1] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||
pixdata >>= 4;
|
||||
if (J & 0x01) C[0] = VB[pixdata] | 0x40;
|
||||
if (J & 0x01) C[0] = READPAL(VB | pixdata) | 0x40;
|
||||
} else {
|
||||
if (J & 0x80) C[0] = VB[pixdata & 3] | 0x40;
|
||||
if (J & 0x80) C[0] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||
pixdata >>= 4;
|
||||
if (J & 0x40) C[1] = VB[pixdata & 3] | 0x40;
|
||||
if (J & 0x40) C[1] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||
pixdata >>= 4;
|
||||
if (J & 0x20) C[2] = VB[pixdata & 3] | 0x40;
|
||||
if (J & 0x20) C[2] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||
pixdata >>= 4;
|
||||
if (J & 0x10) C[3] = VB[pixdata & 3] | 0x40;
|
||||
if (J & 0x10) C[3] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||
pixdata >>= 4;
|
||||
if (J & 0x08) C[4] = VB[pixdata & 3] | 0x40;
|
||||
if (J & 0x08) C[4] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||
pixdata >>= 4;
|
||||
if (J & 0x04) C[5] = VB[pixdata & 3] | 0x40;
|
||||
if (J & 0x04) C[5] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||
pixdata >>= 4;
|
||||
if (J & 0x02) C[6] = VB[pixdata & 3] | 0x40;
|
||||
if (J & 0x02) C[6] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||
pixdata >>= 4;
|
||||
if (J & 0x01) C[7] = VB[pixdata] | 0x40;
|
||||
if (J & 0x01) C[7] = READPAL(VB | pixdata) | 0x40;
|
||||
}
|
||||
} else {
|
||||
if (atr & H_FLIP) {
|
||||
if (J & 0x80) C[7] = VB[pixdata & 3];
|
||||
if (J & 0x80) C[7] = READPAL(VB | (pixdata & 3));
|
||||
pixdata >>= 4;
|
||||
if (J & 0x40) C[6] = VB[pixdata & 3];
|
||||
if (J & 0x40) C[6] = READPAL(VB | (pixdata & 3));
|
||||
pixdata >>= 4;
|
||||
if (J & 0x20) C[5] = VB[pixdata & 3];
|
||||
if (J & 0x20) C[5] = READPAL(VB | (pixdata & 3));
|
||||
pixdata >>= 4;
|
||||
if (J & 0x10) C[4] = VB[pixdata & 3];
|
||||
if (J & 0x10) C[4] = READPAL(VB | (pixdata & 3));
|
||||
pixdata >>= 4;
|
||||
if (J & 0x08) C[3] = VB[pixdata & 3];
|
||||
if (J & 0x08) C[3] = READPAL(VB | (pixdata & 3));
|
||||
pixdata >>= 4;
|
||||
if (J & 0x04) C[2] = VB[pixdata & 3];
|
||||
if (J & 0x04) C[2] = READPAL(VB | (pixdata & 3));
|
||||
pixdata >>= 4;
|
||||
if (J & 0x02) C[1] = VB[pixdata & 3];
|
||||
if (J & 0x02) C[1] = READPAL(VB | (pixdata & 3));
|
||||
pixdata >>= 4;
|
||||
if (J & 0x01) C[0] = VB[pixdata];
|
||||
if (J & 0x01) C[0] = READPAL(VB | pixdata);
|
||||
} else {
|
||||
if (J & 0x80) C[0] = VB[pixdata & 3];
|
||||
if (J & 0x80) C[0] = READPAL(VB | (pixdata & 3));
|
||||
pixdata >>= 4;
|
||||
if (J & 0x40) C[1] = VB[pixdata & 3];
|
||||
if (J & 0x40) C[1] = READPAL(VB | (pixdata & 3));
|
||||
pixdata >>= 4;
|
||||
if (J & 0x20) C[2] = VB[pixdata & 3];
|
||||
if (J & 0x20) C[2] = READPAL(VB | (pixdata & 3));
|
||||
pixdata >>= 4;
|
||||
if (J & 0x10) C[3] = VB[pixdata & 3];
|
||||
if (J & 0x10) C[3] = READPAL(VB | (pixdata & 3));
|
||||
pixdata >>= 4;
|
||||
if (J & 0x08) C[4] = VB[pixdata & 3];
|
||||
if (J & 0x08) C[4] = READPAL(VB | (pixdata & 3));
|
||||
pixdata >>= 4;
|
||||
if (J & 0x04) C[5] = VB[pixdata & 3];
|
||||
if (J & 0x04) C[5] = READPAL(VB | (pixdata & 3));
|
||||
pixdata >>= 4;
|
||||
if (J & 0x02) C[6] = VB[pixdata & 3];
|
||||
if (J & 0x02) C[6] = READPAL(VB | (pixdata & 3));
|
||||
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;
|
||||
FSettings.FirstSLine = FSettings.UsrFirstSLine[1];
|
||||
FSettings.LastSLine = FSettings.UsrLastSLine[1];
|
||||
//paldeemphswap = 1; // dendy has pal ppu, and pal ppu has these swapped
|
||||
} else {
|
||||
scanlines_per_frame = 262;
|
||||
FSettings.FirstSLine = FSettings.UsrFirstSLine[0];
|
||||
FSettings.LastSLine = FSettings.UsrLastSLine[0];
|
||||
//paldeemphswap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1666,8 +1729,7 @@ void FCEUPPU_Reset(void) {
|
||||
kook = 0;
|
||||
idleSynch = 1;
|
||||
|
||||
ppur.reset();
|
||||
spr_read.reset();
|
||||
new_ppu_reset = true; // delay reset of ppur/spr_read until it's ready to start a new frame
|
||||
}
|
||||
|
||||
void FCEUPPU_Power(void) {
|
||||
@ -1729,6 +1791,13 @@ int FCEUPPU_Loop(int skip) {
|
||||
TriggerNMI();
|
||||
}
|
||||
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;
|
||||
X6502_Run(256);
|
||||
|
||||
@ -1759,7 +1828,7 @@ int FCEUPPU_Loop(int skip) {
|
||||
kook ^= 1;
|
||||
}
|
||||
if (GameInfo->type == GIT_NSF)
|
||||
X6502_Run((256 + 85) * (dendy ? 290 : 240));
|
||||
X6502_Run((256 + 85) * normalscanlines);
|
||||
#ifdef FRAMESKIP
|
||||
else if (skip) {
|
||||
int y;
|
||||
@ -1785,24 +1854,42 @@ int FCEUPPU_Loop(int skip) {
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
int x, max, maxref;
|
||||
|
||||
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]++;
|
||||
if (scanline < 240)
|
||||
DEBUG(FCEUD_UpdatePPUView(scanline, 1));
|
||||
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);
|
||||
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) {
|
||||
max = deempcnt[x];
|
||||
maxref = x;
|
||||
}
|
||||
deempcnt[x] = 0;
|
||||
}
|
||||
SetNESDeemph(maxref, 0);
|
||||
SetNESDeemph_OldHacky(maxref, 0);
|
||||
}
|
||||
} //else... to if(ppudead)
|
||||
|
||||
@ -1902,7 +1989,10 @@ const int kFetchTime = 2;
|
||||
|
||||
void runppu(int x) {
|
||||
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
|
||||
@ -1911,7 +2001,7 @@ struct BGData {
|
||||
uint8 nt, pecnt, at, pt[2];
|
||||
|
||||
INLINE void Read() {
|
||||
RefreshAddr = ppur.get_ntread();
|
||||
NTRefreshAddr = RefreshAddr = ppur.get_ntread();
|
||||
if (PEC586Hack)
|
||||
ppur.s = (RefreshAddr & 0x200) >> 9;
|
||||
pecnt = (RefreshAddr & 1) << 3;
|
||||
@ -1973,6 +2063,14 @@ static inline int PaletteAdjustPixel(int pixel) {
|
||||
|
||||
int framectr = 0;
|
||||
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
|
||||
if (ppudead) {
|
||||
// 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
|
||||
|
||||
runppu(delay); //X6502_Run(12);
|
||||
//formerly: runppu(delay);
|
||||
for(int dot=0;dot<delay;dot++)
|
||||
runppu(1);
|
||||
|
||||
if (VBlankON) TriggerNMI();
|
||||
if (PAL)
|
||||
runppu(70 * (kLineTime) - delay);
|
||||
else
|
||||
runppu(20 * (kLineTime) - delay);
|
||||
int sltodo = PAL?70:20;
|
||||
|
||||
//formerly: 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
|
||||
PPU_status = 0;
|
||||
@ -2032,7 +2138,8 @@ int FCEUX_PPU_Loop(int skip) {
|
||||
//capture the initial xscroll
|
||||
//int xscroll = ppur.fh;
|
||||
//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();
|
||||
|
||||
g_rasterpos = 0;
|
||||
@ -2048,7 +2155,10 @@ int FCEUX_PPU_Loop(int skip) {
|
||||
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
|
||||
@ -2064,18 +2174,22 @@ int FCEUX_PPU_Loop(int skip) {
|
||||
for (int xt = 0; xt < 32; xt++) {
|
||||
bgdata.main[xt + 2].Read();
|
||||
|
||||
const uint8 blank = (gNoBGFillColor == 0xFF) ? READPAL(0) : gNoBGFillColor;
|
||||
|
||||
//ok, we're also going to draw here.
|
||||
//unless we're on the first dummy scanline
|
||||
if (sl != 0 && sl < 241) { // cape at 240 for dendy, its PPU does nothing afterwards
|
||||
int xstart = xt << 3;
|
||||
oamcount = oamcounts[renderslot];
|
||||
uint8 * const target = XBuf + (yp << 8) + xstart;
|
||||
uint8 * const dtarget = XDBuf + (yp << 8) + xstart;
|
||||
uint8 *ptr = target;
|
||||
uint8 *dptr = dtarget;
|
||||
int rasterpos = xstart;
|
||||
|
||||
//check all the conditions that can cause things to render in these 8px
|
||||
const bool renderspritenow = SpriteON && rendersprites && (xt > 0 || SpriteLeft8);
|
||||
const bool renderbgnow = ScreenON && renderbg && (xt > 0 || BGLeft8);
|
||||
const bool renderspritenow = SpriteON && (xt > 0 || SpriteLeft8);
|
||||
const bool renderbgnow = ScreenON && (xt > 0 || BGLeft8);
|
||||
for (int xp = 0; xp < 8; xp++, rasterpos++, g_rasterpos++) {
|
||||
//bg pos is different from raster pos due to its offsetability.
|
||||
//so adjust for that here
|
||||
@ -2083,14 +2197,28 @@ int FCEUX_PPU_Loop(int skip) {
|
||||
const int bgpx = bgpos & 7;
|
||||
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
|
||||
if (renderbgnow) {
|
||||
uint8* pt = bgdata.main[bgtile].pt;
|
||||
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
|
||||
bool havepixel = false;
|
||||
@ -2133,11 +2261,14 @@ int FCEUX_PPU_Loop(int skip) {
|
||||
|
||||
//bring in the palette bits and palettize
|
||||
spixel |= (oam[2] & 3) << 2;
|
||||
pixelcolor = PALRAM[0x10 + spixel];
|
||||
|
||||
if (rendersprites)
|
||||
pixelcolor = READPAL(0x10 + spixel);
|
||||
}
|
||||
}
|
||||
|
||||
*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);
|
||||
|
||||
|
||||
@ -2318,6 +2457,8 @@ int FCEUX_PPU_Loop(int skip) {
|
||||
runppu(1);
|
||||
} //scanline loop
|
||||
|
||||
DMC_7bit = 0;
|
||||
|
||||
if (MMC5Hack) MMC5_hb(240);
|
||||
|
||||
//idle for one line
|
||||
|
@ -9,6 +9,10 @@ void FCEUPPU_SetVideoSystem(int w);
|
||||
extern void (*PPU_hook)(uint32 A);
|
||||
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 */
|
||||
extern uint8 NTARAM[0x800], *vnapage[4];
|
||||
extern uint8 PPUNTARAM;
|
||||
@ -18,10 +22,10 @@ void FCEUPPU_SaveState(void);
|
||||
void FCEUPPU_LoadState(int version);
|
||||
uint32 FCEUPPU_PeekAddress();
|
||||
uint8* FCEUPPU_GetCHR(uint32 vadr, uint32 refreshaddr);
|
||||
int FCEUPPU_GetAttr(int ntnum, int xt, int yt);
|
||||
void ppu_getScroll(int &xpos, int &ypos);
|
||||
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FASTCALL __fastcall
|
||||
#else
|
||||
@ -34,9 +38,10 @@ extern void (*FFCEUX_PPUWrite)(uint32 A, uint8 V);
|
||||
extern uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A);
|
||||
void FFCEUX_PPUWrite_Default(uint32 A, uint8 V);
|
||||
|
||||
extern int scanline;
|
||||
extern int g_rasterpos;
|
||||
extern uint8 PPU[4];
|
||||
extern bool DMC_7bit;
|
||||
extern bool paldeemphswap;
|
||||
|
||||
enum PPUPHASE {
|
||||
PPUPHASE_VBL, PPUPHASE_BG, PPUPHASE_OBJ
|
||||
|
@ -89,21 +89,21 @@ pshift[1] <<= 8;
|
||||
#ifdef PPU_BGFETCH
|
||||
if (RefreshAddr & 1) {
|
||||
if(ScreenON)
|
||||
RENDER_LOG(vadr + 8);
|
||||
RENDER_LOGP(C + 8);
|
||||
pshift[0] |= C[8];
|
||||
pshift[1] |= C[8];
|
||||
} else {
|
||||
if(ScreenON)
|
||||
RENDER_LOG(vadr);
|
||||
RENDER_LOGP(C);
|
||||
pshift[0] |= C[0];
|
||||
pshift[1] |= C[0];
|
||||
}
|
||||
#else
|
||||
if(ScreenON)
|
||||
RENDER_LOG(vadr);
|
||||
RENDER_LOGP(C);
|
||||
pshift[0] |= C[0];
|
||||
if(ScreenON)
|
||||
RENDER_LOG(vadr + 8);
|
||||
RENDER_LOGP(C + 8);
|
||||
pshift[1] |= C[8];
|
||||
#endif
|
||||
|
||||
|
@ -58,6 +58,7 @@ uint8 EnabledChannels=0; // $4015 / Sound channels enable and status
|
||||
uint8 IRQFrameMode=0; // $4017 / Frame counter control / xx000000
|
||||
|
||||
uint8 InitialRawDALatch=0; // used only for lua
|
||||
bool DMC_7bit = 0; // used to skip overclocking
|
||||
ENVUNIT EnvUnits[3];
|
||||
|
||||
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,
|
||||
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,
|
||||
236, 354, 472, 708, 944, 1890, 3778
|
||||
};
|
||||
|
||||
const uint32 *NoiseFreqTable = NoiseFreqTableNTSC; // for lua only
|
||||
|
||||
static const uint32 NTSCDMCTable[0x10]=
|
||||
{
|
||||
@ -233,10 +233,8 @@ static DECLFW(Write_PSG)
|
||||
DoSQ1();
|
||||
EnvUnits[0].Mode=(V&0x30)>>4;
|
||||
EnvUnits[0].Speed=(V&0xF);
|
||||
#ifdef WIN32
|
||||
if (swapDuty)
|
||||
V = (V&0x3F)|((V&0x80)>>1)|((V&0x40)<<1);
|
||||
#endif
|
||||
break;
|
||||
case 0x1:
|
||||
sweepon[0]=V&0x80;
|
||||
@ -253,10 +251,8 @@ static DECLFW(Write_PSG)
|
||||
DoSQ2();
|
||||
EnvUnits[1].Mode=(V&0x30)>>4;
|
||||
EnvUnits[1].Speed=(V&0xF);
|
||||
#ifdef WIN32
|
||||
if (swapDuty)
|
||||
V = (V&0x3F)|((V&0x80)>>1)|((V&0x40)<<1);
|
||||
#endif
|
||||
break;
|
||||
case 0x5:
|
||||
sweepon[1]=V&0x80;
|
||||
@ -311,58 +307,69 @@ static DECLFW(Write_PSG)
|
||||
|
||||
static DECLFW(Write_DMCRegs)
|
||||
{
|
||||
A&=0xF;
|
||||
|
||||
switch(A)
|
||||
{
|
||||
case 0x00:DoPCM();
|
||||
LoadDMCPeriod(V&0xF);
|
||||
|
||||
if(SIRQStat&0x80)
|
||||
{
|
||||
if(!(V&0x80))
|
||||
{
|
||||
X6502_IRQEnd(FCEU_IQDPCM);
|
||||
SIRQStat&=~0x80;
|
||||
}
|
||||
else X6502_IRQBegin(FCEU_IQDPCM);
|
||||
}
|
||||
DMCFormat=V;
|
||||
break;
|
||||
case 0x01:DoPCM();
|
||||
InitialRawDALatch=V&0x7F;
|
||||
RawDALatch=InitialRawDALatch;
|
||||
break;
|
||||
case 0x02:DMCAddressLatch=V;break;
|
||||
case 0x03:DMCSizeLatch=V;break;
|
||||
}
|
||||
|
||||
|
||||
A&=0xF;
|
||||
|
||||
switch(A)
|
||||
{
|
||||
case 0x00:
|
||||
DoPCM();
|
||||
LoadDMCPeriod(V&0xF);
|
||||
|
||||
if(SIRQStat&0x80)
|
||||
{
|
||||
if(!(V&0x80))
|
||||
{
|
||||
X6502_IRQEnd(FCEU_IQDPCM);
|
||||
SIRQStat&=~0x80;
|
||||
}
|
||||
else X6502_IRQBegin(FCEU_IQDPCM);
|
||||
}
|
||||
DMCFormat=V;
|
||||
break;
|
||||
case 0x01:
|
||||
DoPCM();
|
||||
InitialRawDALatch=V&0x7F;
|
||||
RawDALatch=InitialRawDALatch;
|
||||
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)
|
||||
{
|
||||
int x;
|
||||
|
||||
DoSQ1();
|
||||
DoSQ2();
|
||||
DoTriangle();
|
||||
DoNoise();
|
||||
DoPCM();
|
||||
for(x=0;x<4;x++)
|
||||
if(!(V&(1<<x))) lengthcount[x]=0; /* Force length counters to 0. */
|
||||
DoSQ1();
|
||||
DoSQ2();
|
||||
DoTriangle();
|
||||
DoNoise();
|
||||
DoPCM();
|
||||
|
||||
if(V&0x10)
|
||||
{
|
||||
if(!DMCSize)
|
||||
PrepDPCM();
|
||||
}
|
||||
for(x=0;x<4;x++)
|
||||
if(!(V&(1<<x))) lengthcount[x]=0; /* Force length counters to 0. */
|
||||
|
||||
if(V&0x10)
|
||||
{
|
||||
if(!DMCSize)
|
||||
PrepDPCM();
|
||||
}
|
||||
else
|
||||
{
|
||||
DMCSize=0;
|
||||
DMCSize=0;
|
||||
}
|
||||
SIRQStat&=~0x80;
|
||||
X6502_IRQEnd(FCEU_IQDPCM);
|
||||
X6502_IRQEnd(FCEU_IQDPCM);
|
||||
EnabledChannels=V&0x1F;
|
||||
}
|
||||
|
||||
@ -552,7 +559,7 @@ static INLINE void DMCDMA(void)
|
||||
|
||||
void FCEU_SoundCPUHook(int cycles)
|
||||
{
|
||||
fhcnt-=cycles*48;
|
||||
fhcnt-=cycles*48;
|
||||
if(fhcnt<=0)
|
||||
{
|
||||
FrameSoundUpdate();
|
||||
@ -1045,7 +1052,7 @@ int FlushEmulateSound(void)
|
||||
int x;
|
||||
int32 end,left;
|
||||
|
||||
if(!timestamp) return(0);
|
||||
if(!soundtimestamp) return(0);
|
||||
|
||||
if(!FSettings.SndRate)
|
||||
{
|
||||
@ -1066,7 +1073,7 @@ int FlushEmulateSound(void)
|
||||
|
||||
if(GameExpSound.HiFill) GameExpSound.HiFill();
|
||||
|
||||
for(x=timestamp;x;x--)
|
||||
for(x=soundtimestamp;x;x--)
|
||||
{
|
||||
uint32 b=*tmpo;
|
||||
*tmpo=(b&65535)+wlookup2[(b>>16)&255]+wlookup1[b>>24];
|
||||
|
@ -59,7 +59,7 @@ extern unsigned char *cdloggerdata;
|
||||
|
||||
extern uint32 soundtsoffs;
|
||||
extern bool swapDuty;
|
||||
#define SOUNDTS (timestamp + soundtsoffs)
|
||||
#define SOUNDTS (soundtimestamp + soundtsoffs)
|
||||
|
||||
void SetNESSoundMap(void);
|
||||
void FrameSoundUpdate(void);
|
||||
|
@ -974,8 +974,12 @@ void FCEUI_LoadState(const char *fname, bool display_message)
|
||||
loadStateFailed = 1;
|
||||
return; // state doesn't exist; exit cleanly
|
||||
}
|
||||
|
||||
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
|
||||
#if 0
|
||||
if(FCEUnetplay)
|
||||
|
@ -1,458 +1,458 @@
|
||||
/* Copyright (C) 2005 Guillaume Duhamel
|
||||
Copyright (C) 2008-2009 DeSmuME team
|
||||
|
||||
This file is part of DeSmuME
|
||||
|
||||
DeSmuME is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DeSmuME is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DeSmuME; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef TYPES_HPP
|
||||
#define TYPES_HPP
|
||||
|
||||
//analyze microsoft compilers
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _XBOX
|
||||
//#define _XBOX //already defined
|
||||
#else
|
||||
#define _WINDOWS
|
||||
#ifdef _M_X64
|
||||
//#define _WIN64 //already defined in x64 compiler
|
||||
#else
|
||||
//#define _WIN32 //already defined
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//todo - everyone will want to support this eventually, i suppose
|
||||
#ifdef _WINDOWS
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
//xbox needs to include this to resemble windows
|
||||
#ifdef _XBOX
|
||||
#include <xtl.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef DEVELOPER
|
||||
#define IF_DEVELOPER(X) X
|
||||
#else
|
||||
#define IF_DEVELOPER(X)
|
||||
#endif
|
||||
|
||||
#ifdef _WINDOWS
|
||||
//#define HAVE_WX //not useful yet....
|
||||
#define HAVE_LIBAGG
|
||||
#define ENABLE_SSE
|
||||
#define ENABLE_SSE2
|
||||
#ifdef DEVELOPER
|
||||
#define HAVE_LUA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef __SSE__
|
||||
#define ENABLE_SSE
|
||||
#endif
|
||||
#ifdef __SSE2__
|
||||
#define ENABLE_SSE2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef NOSSE
|
||||
#undef ENABLE_SSE
|
||||
#endif
|
||||
|
||||
#ifdef NOSSE2
|
||||
#undef ENABLE_SSE2
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strcasecmp(x,y) _stricmp(x,y)
|
||||
#define snprintf _snprintf
|
||||
#else
|
||||
#define WINAPI
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include <limits.h>
|
||||
#ifndef PATH_MAX
|
||||
#define MAX_PATH 1024
|
||||
#else
|
||||
#define MAX_PATH PATH_MAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _XBOX
|
||||
#define MAX_PATH 1024
|
||||
#define PATH_MAX 1024
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
#define ALIGN(X) __declspec(align(X))
|
||||
#elif __GNUC__
|
||||
#define ALIGN(X) __attribute__ ((aligned (X)))
|
||||
#else
|
||||
#define ALIGN(X)
|
||||
#endif
|
||||
|
||||
#define CACHE_ALIGN ALIGN(32)
|
||||
|
||||
//use this for example when you want a byte value to be better-aligned
|
||||
#define FAST_ALIGN ALIGN(4)
|
||||
|
||||
#ifndef FASTCALL
|
||||
#ifdef __MINGW32__
|
||||
#define FASTCALL __attribute__((fastcall))
|
||||
#elif defined (__i386__) && !defined(__clang__)
|
||||
#define FASTCALL __attribute__((regparm(3)))
|
||||
#elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
#define FASTCALL
|
||||
#else
|
||||
#define FASTCALL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CDECL_ __cdecl
|
||||
#else
|
||||
#define _CDECL_
|
||||
#endif
|
||||
|
||||
#ifndef INLINE
|
||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
#define INLINE _inline
|
||||
#else
|
||||
#define INLINE inline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef FORCEINLINE
|
||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
#define FORCEINLINE __forceinline
|
||||
#define MSC_FORCEINLINE __forceinline
|
||||
#else
|
||||
#define FORCEINLINE inline __attribute__((always_inline))
|
||||
#define MSC_FORCEINLINE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__LP64__)
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64;
|
||||
|
||||
typedef signed char s8;
|
||||
typedef signed short s16;
|
||||
typedef signed int s32;
|
||||
typedef signed long long s64;
|
||||
#else
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
typedef unsigned __int64 u64;
|
||||
#else
|
||||
typedef unsigned long long u64;
|
||||
#endif
|
||||
|
||||
typedef signed char s8;
|
||||
typedef signed short s16;
|
||||
typedef signed int s32;
|
||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
typedef __int64 s64;
|
||||
#else
|
||||
typedef signed long long s64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef u8 uint8;
|
||||
typedef u16 uint16;
|
||||
|
||||
#ifndef OBJ_C
|
||||
typedef u32 uint32;
|
||||
#else
|
||||
#define uint32 u32 //uint32 is defined in Leopard somewhere, avoid conflicts
|
||||
#endif
|
||||
|
||||
/*---------- GPU3D fixed-points types -----------*/
|
||||
|
||||
typedef s32 f32;
|
||||
#define inttof32(n) ((n) << 12)
|
||||
#define f32toint(n) ((n) >> 12)
|
||||
#define floattof32(n) ((int32)((n) * (1 << 12)))
|
||||
#define f32tofloat(n) (((float)(n)) / (float)(1<<12))
|
||||
|
||||
typedef s16 t16;
|
||||
#define f32tot16(n) ((t16)(n >> 8))
|
||||
#define inttot16(n) ((n) << 4)
|
||||
#define t16toint(n) ((n) >> 4)
|
||||
#define floattot16(n) ((t16)((n) * (1 << 4)))
|
||||
#define t16ofloat(n) (((float)(n)) / (float)(1<<4))
|
||||
|
||||
typedef s16 v16;
|
||||
#define inttov16(n) ((n) << 12)
|
||||
#define f32tov16(n) (n)
|
||||
#define floattov16(n) ((v16)((n) * (1 << 12)))
|
||||
#define v16toint(n) ((n) >> 12)
|
||||
#define v16tofloat(n) (((float)(n)) / (float)(1<<12))
|
||||
|
||||
typedef s16 v10;
|
||||
#define inttov10(n) ((n) << 9)
|
||||
#define f32tov10(n) ((v10)(n >> 3))
|
||||
#define v10toint(n) ((n) >> 9)
|
||||
#define floattov10(n) ((v10)((n) * (1 << 9)))
|
||||
#define v10tofloat(n) (((float)(n)) / (float)(1<<9))
|
||||
|
||||
/*----------------------*/
|
||||
|
||||
#ifndef OBJ_C
|
||||
typedef int BOOL;
|
||||
#else
|
||||
//apple also defines BOOL
|
||||
typedef int desmume_BOOL;
|
||||
#define BOOL desmume_BOOL
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
#define WORDS_BIGENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# define LOCAL_BE
|
||||
#else
|
||||
# define LOCAL_LE
|
||||
#endif
|
||||
|
||||
/* little endian (ds' endianess) to local endianess convert macros */
|
||||
#ifdef LOCAL_BE /* local arch is big endian */
|
||||
# define LE_TO_LOCAL_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
|
||||
# define LE_TO_LOCAL_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
|
||||
# define LE_TO_LOCAL_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00)|(((x)>>40)&0xff00)|(((x)>>56)&0xff))
|
||||
# define LOCAL_TO_LE_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
|
||||
# define LOCAL_TO_LE_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
|
||||
# define LOCAL_TO_LE_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00)|(((x)>>40)&0xff00)|(((x)>>56)&0xff))
|
||||
#else /* local arch is little endian */
|
||||
# define LE_TO_LOCAL_16(x) (x)
|
||||
# define LE_TO_LOCAL_32(x) (x)
|
||||
# define LE_TO_LOCAL_64(x) (x)
|
||||
# define LOCAL_TO_LE_16(x) (x)
|
||||
# define LOCAL_TO_LE_32(x) (x)
|
||||
# define LOCAL_TO_LE_64(x) (x)
|
||||
#endif
|
||||
|
||||
// kilobytes and megabytes macro
|
||||
#define MB(x) ((x)*1024*1024)
|
||||
#define KB(x) ((x)*1024)
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
#define CPU_STR(c) ((c==ARM9)?"ARM9":"ARM7")
|
||||
typedef enum
|
||||
{
|
||||
ARM9 = 0,
|
||||
ARM7 = 1
|
||||
} cpu_id_t;
|
||||
|
||||
///endian-flips count bytes. count should be even and nonzero.
|
||||
inline void FlipByteOrder(u8 *src, u32 count)
|
||||
{
|
||||
u8 *start=src;
|
||||
u8 *end=src+count-1;
|
||||
|
||||
if((count&1) || !count) return; /* This shouldn't happen. */
|
||||
|
||||
while(count--)
|
||||
{
|
||||
u8 tmp;
|
||||
|
||||
tmp=*end;
|
||||
*end=*start;
|
||||
*start=tmp;
|
||||
end--;
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline u64 double_to_u64(double d) {
|
||||
union {
|
||||
u64 a;
|
||||
double b;
|
||||
} fuxor;
|
||||
fuxor.b = d;
|
||||
return fuxor.a;
|
||||
}
|
||||
|
||||
inline double u64_to_double(u64 u) {
|
||||
union {
|
||||
u64 a;
|
||||
double b;
|
||||
} fuxor;
|
||||
fuxor.a = u;
|
||||
return fuxor.b;
|
||||
}
|
||||
|
||||
inline u32 float_to_u32(float f) {
|
||||
union {
|
||||
u32 a;
|
||||
float b;
|
||||
} fuxor;
|
||||
fuxor.b = f;
|
||||
return fuxor.a;
|
||||
}
|
||||
|
||||
inline float u32_to_float(u32 u) {
|
||||
union {
|
||||
u32 a;
|
||||
float b;
|
||||
} fuxor;
|
||||
fuxor.a = u;
|
||||
return fuxor.b;
|
||||
}
|
||||
|
||||
|
||||
///stores a 32bit value into the provided byte array in guaranteed little endian form
|
||||
inline void en32lsb(u8 *buf, u32 morp)
|
||||
{
|
||||
buf[0]=(u8)(morp);
|
||||
buf[1]=(u8)(morp>>8);
|
||||
buf[2]=(u8)(morp>>16);
|
||||
buf[3]=(u8)(morp>>24);
|
||||
}
|
||||
|
||||
inline void en16lsb(u8* buf, u16 morp)
|
||||
{
|
||||
buf[0]=(u8)morp;
|
||||
buf[1]=(u8)(morp>>8);
|
||||
}
|
||||
|
||||
///unpacks a 64bit little endian value from the provided byte array into host byte order
|
||||
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);
|
||||
}
|
||||
|
||||
///unpacks a 32bit little endian value from the provided byte array into host byte order
|
||||
inline u32 de32lsb(u8 *morp)
|
||||
{
|
||||
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
|
||||
inline u16 de16lsb(u8 *morp)
|
||||
{
|
||||
return morp[0]|(morp[1]<<8);
|
||||
}
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
//taken from winnt.h
|
||||
extern "C++" // templates cannot be declared to have 'C' linkage
|
||||
template <typename T, size_t N>
|
||||
char (*BLAHBLAHBLAH( UNALIGNED T (&)[N] ))[N];
|
||||
|
||||
#define ARRAY_SIZE(A) (sizeof(*BLAHBLAHBLAH(A)))
|
||||
#endif
|
||||
|
||||
|
||||
//fairly standard for loop macros
|
||||
#define MACRODO1(TRICK,TODO) { const int X = TRICK; TODO; }
|
||||
#define MACRODO2(X,TODO) { MACRODO1((X),TODO) MACRODO1(((X)+1),TODO) }
|
||||
#define MACRODO4(X,TODO) { MACRODO2((X),TODO) MACRODO2(((X)+2),TODO) }
|
||||
#define MACRODO8(X,TODO) { MACRODO4((X),TODO) MACRODO4(((X)+4),TODO) }
|
||||
#define MACRODO16(X,TODO) { MACRODO8((X),TODO) MACRODO8(((X)+8),TODO) }
|
||||
#define MACRODO32(X,TODO) { MACRODO16((X),TODO) MACRODO16(((X)+16),TODO) }
|
||||
#define MACRODO64(X,TODO) { MACRODO32((X),TODO) MACRODO32(((X)+32),TODO) }
|
||||
#define MACRODO128(X,TODO) { MACRODO64((X),TODO) MACRODO64(((X)+64),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)
|
||||
#define MACRODO_N(N,TODO) {\
|
||||
if((N)&0x100) MACRODO256(0,TODO); \
|
||||
if((N)&0x080) MACRODO128((N)&(0x100),TODO); \
|
||||
if((N)&0x040) MACRODO64((N)&(0x100|0x080),TODO); \
|
||||
if((N)&0x020) MACRODO32((N)&(0x100|0x080|0x040),TODO); \
|
||||
if((N)&0x010) MACRODO16((N)&(0x100|0x080|0x040|0x020),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)&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); \
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
//Binary constant generator macro By Tom Torfs - donated to the public domain
|
||||
|
||||
//turn a numeric literal into a hex constant
|
||||
//(avoids problems with leading zeroes)
|
||||
//8-bit constants max value 0x11111111, always fits in unsigned long
|
||||
#define HEX__(n) 0x##n##LU
|
||||
|
||||
//8-bit conversion function
|
||||
#define B8__(x) ((x&0x0000000FLU)?1:0) \
|
||||
+((x&0x000000F0LU)?2:0) \
|
||||
+((x&0x00000F00LU)?4:0) \
|
||||
+((x&0x0000F000LU)?8:0) \
|
||||
+((x&0x000F0000LU)?16:0) \
|
||||
+((x&0x00F00000LU)?32:0) \
|
||||
+((x&0x0F000000LU)?64:0) \
|
||||
+((x&0xF0000000LU)?128:0)
|
||||
|
||||
//for upto 8-bit binary constants
|
||||
#define B8(d) ((unsigned char)B8__(HEX__(d)))
|
||||
|
||||
// for upto 16-bit binary constants, MSB first
|
||||
#define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8) \
|
||||
+ B8(dlsb))
|
||||
|
||||
// for upto 32-bit binary constants, MSB first */
|
||||
#define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24) \
|
||||
+ ((unsigned long)B8(db2)<<16) \
|
||||
+ ((unsigned long)B8(db3)<<8) \
|
||||
+ B8(dlsb))
|
||||
|
||||
//Sample usage:
|
||||
//B8(01010101) = 85
|
||||
//B16(10101010,01010101) = 43605
|
||||
//B32(10000000,11111111,10101010,01010101) = 2164238933
|
||||
//---------------------------
|
||||
|
||||
#ifndef CTASSERT
|
||||
#define CTASSERT(x) typedef char __assert ## y[(x) ? 1 : -1]
|
||||
#endif
|
||||
|
||||
static const char hexValid[23] = {"0123456789ABCDEFabcdef"};
|
||||
|
||||
|
||||
template<typename T> inline void reconstruct(T* t) {
|
||||
t->~T();
|
||||
new(t) T();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
/* Copyright (C) 2005 Guillaume Duhamel
|
||||
Copyright (C) 2008-2009 DeSmuME team
|
||||
|
||||
This file is part of DeSmuME
|
||||
|
||||
DeSmuME is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DeSmuME is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DeSmuME; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef TYPES_HPP
|
||||
#define TYPES_HPP
|
||||
|
||||
//analyze microsoft compilers
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _XBOX
|
||||
//#define _XBOX //already defined
|
||||
#else
|
||||
#define _WINDOWS
|
||||
#ifdef _M_X64
|
||||
//#define _WIN64 //already defined in x64 compiler
|
||||
#else
|
||||
//#define _WIN32 //already defined
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//todo - everyone will want to support this eventually, i suppose
|
||||
#ifdef _WINDOWS
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
//xbox needs to include this to resemble windows
|
||||
#ifdef _XBOX
|
||||
#include <xtl.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef DEVELOPER
|
||||
#define IF_DEVELOPER(X) X
|
||||
#else
|
||||
#define IF_DEVELOPER(X)
|
||||
#endif
|
||||
|
||||
#ifdef _WINDOWS
|
||||
//#define HAVE_WX //not useful yet....
|
||||
#define HAVE_LIBAGG
|
||||
#define ENABLE_SSE
|
||||
#define ENABLE_SSE2
|
||||
#ifdef DEVELOPER
|
||||
#define HAVE_LUA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef __SSE__
|
||||
#define ENABLE_SSE
|
||||
#endif
|
||||
#ifdef __SSE2__
|
||||
#define ENABLE_SSE2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef NOSSE
|
||||
#undef ENABLE_SSE
|
||||
#endif
|
||||
|
||||
#ifdef NOSSE2
|
||||
#undef ENABLE_SSE2
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strcasecmp(x,y) _stricmp(x,y)
|
||||
#define snprintf _snprintf
|
||||
#else
|
||||
#define WINAPI
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include <limits.h>
|
||||
#ifndef PATH_MAX
|
||||
#define MAX_PATH 1024
|
||||
#else
|
||||
#define MAX_PATH PATH_MAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _XBOX
|
||||
#define MAX_PATH 1024
|
||||
#define PATH_MAX 1024
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
#define ALIGN(X) __declspec(align(X))
|
||||
#elif __GNUC__
|
||||
#define ALIGN(X) __attribute__ ((aligned (X)))
|
||||
#else
|
||||
#define ALIGN(X)
|
||||
#endif
|
||||
|
||||
#define CACHE_ALIGN ALIGN(32)
|
||||
|
||||
//use this for example when you want a byte value to be better-aligned
|
||||
#define FAST_ALIGN ALIGN(4)
|
||||
|
||||
#ifndef FASTCALL
|
||||
#ifdef __MINGW32__
|
||||
#define FASTCALL __attribute__((fastcall))
|
||||
#elif defined (__i386__) && !defined(__clang__)
|
||||
#define FASTCALL __attribute__((regparm(3)))
|
||||
#elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
#define FASTCALL
|
||||
#else
|
||||
#define FASTCALL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CDECL_ __cdecl
|
||||
#else
|
||||
#define _CDECL_
|
||||
#endif
|
||||
|
||||
#ifndef INLINE
|
||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
#define INLINE _inline
|
||||
#else
|
||||
#define INLINE inline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef FORCEINLINE
|
||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
#define FORCEINLINE __forceinline
|
||||
#define MSC_FORCEINLINE __forceinline
|
||||
#else
|
||||
#define FORCEINLINE inline __attribute__((always_inline))
|
||||
#define MSC_FORCEINLINE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__LP64__)
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64;
|
||||
|
||||
typedef signed char s8;
|
||||
typedef signed short s16;
|
||||
typedef signed int s32;
|
||||
typedef signed long long s64;
|
||||
#else
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
typedef unsigned __int64 u64;
|
||||
#else
|
||||
typedef unsigned long long u64;
|
||||
#endif
|
||||
|
||||
typedef signed char s8;
|
||||
typedef signed short s16;
|
||||
typedef signed int s32;
|
||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
typedef __int64 s64;
|
||||
#else
|
||||
typedef signed long long s64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef u8 uint8;
|
||||
typedef u16 uint16;
|
||||
|
||||
#ifndef OBJ_C
|
||||
typedef u32 uint32;
|
||||
#else
|
||||
#define uint32 u32 //uint32 is defined in Leopard somewhere, avoid conflicts
|
||||
#endif
|
||||
|
||||
/*---------- GPU3D fixed-points types -----------*/
|
||||
|
||||
typedef s32 f32;
|
||||
#define inttof32(n) ((n) << 12)
|
||||
#define f32toint(n) ((n) >> 12)
|
||||
#define floattof32(n) ((int32)((n) * (1 << 12)))
|
||||
#define f32tofloat(n) (((float)(n)) / (float)(1<<12))
|
||||
|
||||
typedef s16 t16;
|
||||
#define f32tot16(n) ((t16)(n >> 8))
|
||||
#define inttot16(n) ((n) << 4)
|
||||
#define t16toint(n) ((n) >> 4)
|
||||
#define floattot16(n) ((t16)((n) * (1 << 4)))
|
||||
#define t16ofloat(n) (((float)(n)) / (float)(1<<4))
|
||||
|
||||
typedef s16 v16;
|
||||
#define inttov16(n) ((n) << 12)
|
||||
#define f32tov16(n) (n)
|
||||
#define floattov16(n) ((v16)((n) * (1 << 12)))
|
||||
#define v16toint(n) ((n) >> 12)
|
||||
#define v16tofloat(n) (((float)(n)) / (float)(1<<12))
|
||||
|
||||
typedef s16 v10;
|
||||
#define inttov10(n) ((n) << 9)
|
||||
#define f32tov10(n) ((v10)(n >> 3))
|
||||
#define v10toint(n) ((n) >> 9)
|
||||
#define floattov10(n) ((v10)((n) * (1 << 9)))
|
||||
#define v10tofloat(n) (((float)(n)) / (float)(1<<9))
|
||||
|
||||
/*----------------------*/
|
||||
|
||||
#ifndef OBJ_C
|
||||
typedef int BOOL;
|
||||
#else
|
||||
//apple also defines BOOL
|
||||
typedef int desmume_BOOL;
|
||||
#define BOOL desmume_BOOL
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
#define WORDS_BIGENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# define LOCAL_BE
|
||||
#else
|
||||
# define LOCAL_LE
|
||||
#endif
|
||||
|
||||
/* little endian (ds' endianess) to local endianess convert macros */
|
||||
#ifdef LOCAL_BE /* local arch is big endian */
|
||||
# define LE_TO_LOCAL_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
|
||||
# define LE_TO_LOCAL_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
|
||||
# define LE_TO_LOCAL_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00)|(((x)>>40)&0xff00)|(((x)>>56)&0xff))
|
||||
# define LOCAL_TO_LE_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
|
||||
# define LOCAL_TO_LE_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
|
||||
# define LOCAL_TO_LE_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00)|(((x)>>40)&0xff00)|(((x)>>56)&0xff))
|
||||
#else /* local arch is little endian */
|
||||
# define LE_TO_LOCAL_16(x) (x)
|
||||
# define LE_TO_LOCAL_32(x) (x)
|
||||
# define LE_TO_LOCAL_64(x) (x)
|
||||
# define LOCAL_TO_LE_16(x) (x)
|
||||
# define LOCAL_TO_LE_32(x) (x)
|
||||
# define LOCAL_TO_LE_64(x) (x)
|
||||
#endif
|
||||
|
||||
// kilobytes and megabytes macro
|
||||
#define MB(x) ((x)*1024*1024)
|
||||
#define KB(x) ((x)*1024)
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
#define CPU_STR(c) ((c==ARM9)?"ARM9":"ARM7")
|
||||
typedef enum
|
||||
{
|
||||
ARM9 = 0,
|
||||
ARM7 = 1
|
||||
} cpu_id_t;
|
||||
|
||||
///endian-flips count bytes. count should be even and nonzero.
|
||||
inline void FlipByteOrder(u8 *src, u32 count)
|
||||
{
|
||||
u8 *start=src;
|
||||
u8 *end=src+count-1;
|
||||
|
||||
if((count&1) || !count) return; /* This shouldn't happen. */
|
||||
|
||||
while(count--)
|
||||
{
|
||||
u8 tmp;
|
||||
|
||||
tmp=*end;
|
||||
*end=*start;
|
||||
*start=tmp;
|
||||
end--;
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline u64 double_to_u64(double d) {
|
||||
union {
|
||||
u64 a;
|
||||
double b;
|
||||
} fuxor;
|
||||
fuxor.b = d;
|
||||
return fuxor.a;
|
||||
}
|
||||
|
||||
inline double u64_to_double(u64 u) {
|
||||
union {
|
||||
u64 a;
|
||||
double b;
|
||||
} fuxor;
|
||||
fuxor.a = u;
|
||||
return fuxor.b;
|
||||
}
|
||||
|
||||
inline u32 float_to_u32(float f) {
|
||||
union {
|
||||
u32 a;
|
||||
float b;
|
||||
} fuxor;
|
||||
fuxor.b = f;
|
||||
return fuxor.a;
|
||||
}
|
||||
|
||||
inline float u32_to_float(u32 u) {
|
||||
union {
|
||||
u32 a;
|
||||
float b;
|
||||
} fuxor;
|
||||
fuxor.a = u;
|
||||
return fuxor.b;
|
||||
}
|
||||
|
||||
|
||||
///stores a 32bit value into the provided byte array in guaranteed little endian form
|
||||
inline void en32lsb(u8 *buf, u32 morp)
|
||||
{
|
||||
buf[0]=(u8)(morp);
|
||||
buf[1]=(u8)(morp>>8);
|
||||
buf[2]=(u8)(morp>>16);
|
||||
buf[3]=(u8)(morp>>24);
|
||||
}
|
||||
|
||||
inline void en16lsb(u8* buf, u16 morp)
|
||||
{
|
||||
buf[0]=(u8)morp;
|
||||
buf[1]=(u8)(morp>>8);
|
||||
}
|
||||
|
||||
///unpacks a 64bit little endian value from the provided byte array into host byte order
|
||||
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);
|
||||
}
|
||||
|
||||
///unpacks a 32bit little endian value from the provided byte array into host byte order
|
||||
inline u32 de32lsb(u8 *morp)
|
||||
{
|
||||
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
|
||||
inline u16 de16lsb(u8 *morp)
|
||||
{
|
||||
return morp[0]|(morp[1]<<8);
|
||||
}
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
//taken from winnt.h
|
||||
extern "C++" // templates cannot be declared to have 'C' linkage
|
||||
template <typename T, size_t N>
|
||||
char (*BLAHBLAHBLAH( UNALIGNED T (&)[N] ))[N];
|
||||
|
||||
#define ARRAY_SIZE(A) (sizeof(*BLAHBLAHBLAH(A)))
|
||||
#endif
|
||||
|
||||
|
||||
//fairly standard for loop macros
|
||||
#define MACRODO1(TRICK,TODO) { const int X = TRICK; TODO; }
|
||||
#define MACRODO2(X,TODO) { MACRODO1((X),TODO) MACRODO1(((X)+1),TODO) }
|
||||
#define MACRODO4(X,TODO) { MACRODO2((X),TODO) MACRODO2(((X)+2),TODO) }
|
||||
#define MACRODO8(X,TODO) { MACRODO4((X),TODO) MACRODO4(((X)+4),TODO) }
|
||||
#define MACRODO16(X,TODO) { MACRODO8((X),TODO) MACRODO8(((X)+8),TODO) }
|
||||
#define MACRODO32(X,TODO) { MACRODO16((X),TODO) MACRODO16(((X)+16),TODO) }
|
||||
#define MACRODO64(X,TODO) { MACRODO32((X),TODO) MACRODO32(((X)+32),TODO) }
|
||||
#define MACRODO128(X,TODO) { MACRODO64((X),TODO) MACRODO64(((X)+64),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)
|
||||
#define MACRODO_N(N,TODO) {\
|
||||
if((N)&0x100) MACRODO256(0,TODO); \
|
||||
if((N)&0x080) MACRODO128((N)&(0x100),TODO); \
|
||||
if((N)&0x040) MACRODO64((N)&(0x100|0x080),TODO); \
|
||||
if((N)&0x020) MACRODO32((N)&(0x100|0x080|0x040),TODO); \
|
||||
if((N)&0x010) MACRODO16((N)&(0x100|0x080|0x040|0x020),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)&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); \
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
//Binary constant generator macro By Tom Torfs - donated to the public domain
|
||||
|
||||
//turn a numeric literal into a hex constant
|
||||
//(avoids problems with leading zeroes)
|
||||
//8-bit constants max value 0x11111111, always fits in unsigned long
|
||||
#define HEX__(n) 0x##n##LU
|
||||
|
||||
//8-bit conversion function
|
||||
#define B8__(x) ((x&0x0000000FLU)?1:0) \
|
||||
+((x&0x000000F0LU)?2:0) \
|
||||
+((x&0x00000F00LU)?4:0) \
|
||||
+((x&0x0000F000LU)?8:0) \
|
||||
+((x&0x000F0000LU)?16:0) \
|
||||
+((x&0x00F00000LU)?32:0) \
|
||||
+((x&0x0F000000LU)?64:0) \
|
||||
+((x&0xF0000000LU)?128:0)
|
||||
|
||||
//for upto 8-bit binary constants
|
||||
#define B8(d) ((unsigned char)B8__(HEX__(d)))
|
||||
|
||||
// for upto 16-bit binary constants, MSB first
|
||||
#define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8) \
|
||||
+ B8(dlsb))
|
||||
|
||||
// for upto 32-bit binary constants, MSB first */
|
||||
#define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24) \
|
||||
+ ((unsigned long)B8(db2)<<16) \
|
||||
+ ((unsigned long)B8(db3)<<8) \
|
||||
+ B8(dlsb))
|
||||
|
||||
//Sample usage:
|
||||
//B8(01010101) = 85
|
||||
//B16(10101010,01010101) = 43605
|
||||
//B32(10000000,11111111,10101010,01010101) = 2164238933
|
||||
//---------------------------
|
||||
|
||||
#ifndef CTASSERT
|
||||
#define CTASSERT(x) typedef char __assert ## y[(x) ? 1 : -1]
|
||||
#endif
|
||||
|
||||
static const char hexValid[23] = {"0123456789ABCDEFabcdef"};
|
||||
|
||||
|
||||
template<typename T> inline void reconstruct(T* t) {
|
||||
t->~T();
|
||||
new(t) T();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -44,10 +44,9 @@ typedef signed short int16;
|
||||
typedef signed int int32;
|
||||
#define dup _dup
|
||||
#define stat _stat
|
||||
#define fstat _fstat
|
||||
#define mkdir _mkdir
|
||||
#define alloca _alloca
|
||||
#define snprintf _snprintf
|
||||
#define FCEUX_fstat _fstat
|
||||
#if _MSC_VER < 1500
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
@ -74,6 +73,8 @@ typedef int32_t int32;
|
||||
typedef uint8_t uint8;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint32_t uint32;
|
||||
|
||||
#define FCEUX_fstat fstat
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
@ -118,6 +118,7 @@ static void MooMirroring(void) {
|
||||
if (mirrortodo < 0x4)
|
||||
SetupCartMirroring(mirrortodo, 1, 0);
|
||||
else if (mirrortodo == 0x4) {
|
||||
FCEU_MemoryRand(exntar, sizeof(exntar), true);
|
||||
SetupCartMirroring(4, 1, exntar);
|
||||
AddExState(exntar, 2048, 0, "EXNR");
|
||||
} else
|
||||
@ -348,6 +349,7 @@ static BMAPPING bmap[] = {
|
||||
{ "BS-5", BMCBS5_Init, 0 },
|
||||
{ "CC-21", UNLCC21_Init, 0 },
|
||||
{ "CITYFIGHT", UNLCITYFIGHT_Init, 0 },
|
||||
{ "10-24-C-A1", BMC1024CA1_Init, 0 },
|
||||
{ "CNROM", CNROM_Init, 0 },
|
||||
{ "CPROM", CPROM_Init, BMCFLAG_16KCHRR },
|
||||
{ "D1038", BMCD1038_Init, 0 },
|
||||
@ -374,6 +376,7 @@ static BMAPPING bmap[] = {
|
||||
{ "KS7010", UNLKS7010_Init, 0 },
|
||||
{ "KS7012", UNLKS7012_Init, 0 },
|
||||
{ "KS7013B", UNLKS7013B_Init, 0 },
|
||||
{ "KS7016", UNLKS7016_Init, 0 },
|
||||
{ "KS7017", UNLKS7017_Init, 0 },
|
||||
{ "KS7030", UNLKS7030_Init, 0 },
|
||||
{ "KS7031", UNLKS7031_Init, 0 },
|
||||
@ -462,6 +465,16 @@ static BMAPPING bmap[] = {
|
||||
{ "YOKO", UNLYOKO_Init, 0 },
|
||||
{ "SB-2000", UNLSB2000_Init, 0 },
|
||||
{ "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 }
|
||||
};
|
||||
@ -526,7 +539,7 @@ static int InitializeBoard(void) {
|
||||
CHRRAMSize = 256;
|
||||
else
|
||||
CHRRAMSize = 8;
|
||||
CHRRAMSize <<= 10;
|
||||
CHRRAMSize <<= 10;
|
||||
if ((UNIFchrrama = (uint8*)FCEU_malloc(CHRRAMSize))) {
|
||||
SetupCartCHRMapping(0, UNIFchrrama, CHRRAMSize, 1);
|
||||
AddExState(UNIFchrrama, CHRRAMSize, 0, "CHRR");
|
||||
@ -614,6 +627,7 @@ int UNIFLoad(const char *name, FCEUFILE *fp) {
|
||||
|
||||
strcpy(LoadedRomFName, name); //For the debugger list
|
||||
GameInterface = UNIFGI;
|
||||
currCartInfo = &UNIFCart;
|
||||
return 1;
|
||||
|
||||
aborto:
|
||||
|
@ -1,151 +1,163 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
void AC08_Init(CartInfo *info);
|
||||
void ANROM_Init(CartInfo *info);
|
||||
void BMC11160_Init(CartInfo *info);
|
||||
void BMC12IN1_Init(CartInfo *info);
|
||||
void BMC13in1JY110_Init(CartInfo *info);
|
||||
void BMC190in1_Init(CartInfo *info);
|
||||
void BMC411120C_Init(CartInfo *info);
|
||||
void BMC64in1nr_Init(CartInfo *info);
|
||||
void BMC70in1B_Init(CartInfo *info);
|
||||
void BMC70in1_Init(CartInfo *info);
|
||||
void BMC810544CA1_Init(CartInfo *info);
|
||||
void BMC830118C_Init(CartInfo *info);
|
||||
void BMCA65AS_Init(CartInfo *info);
|
||||
void BMCBS5_Init(CartInfo *info);
|
||||
void BMCD1038_Init(CartInfo *info);
|
||||
void BMCFK23CA_Init(CartInfo *info);
|
||||
void BMCFK23C_Init(CartInfo *info);
|
||||
void BMCG146_Init(CartInfo *info);
|
||||
void BMCGK192_Init(CartInfo *info);
|
||||
void BMCGS2004_Init(CartInfo *info);
|
||||
void BMCGS2013_Init(CartInfo *info);
|
||||
void BMCGhostbusters63in1_Init(CartInfo *info);
|
||||
void BMCNTD03_Init(CartInfo *info);
|
||||
void BMCT2271_Init(CartInfo *info);
|
||||
void BMCT262_Init(CartInfo *info);
|
||||
void CNROM_Init(CartInfo *info);
|
||||
void CPROM_Init(CartInfo *info);
|
||||
void DreamTech01_Init(CartInfo *info);
|
||||
void EKROM_Init(CartInfo *info);
|
||||
void ELROM_Init(CartInfo *info);
|
||||
void ETROM_Init(CartInfo *info);
|
||||
void EWROM_Init(CartInfo *info);
|
||||
void GNROM_Init(CartInfo *info);
|
||||
void HKROM_Init(CartInfo *info);
|
||||
void LE05_Init(CartInfo *info);
|
||||
void LH10_Init(CartInfo *info);
|
||||
void LH32_Init(CartInfo *info);
|
||||
void LH53_Init(CartInfo *info);
|
||||
void MALEE_Init(CartInfo *info);
|
||||
void MHROM_Init(CartInfo *info);
|
||||
void Mapper190_Init(CartInfo *info);
|
||||
void NROM_Init(CartInfo *info);
|
||||
void Novel_Init(CartInfo *info);
|
||||
void S74LS374NA_Init(CartInfo *info);
|
||||
void S74LS374N_Init(CartInfo *info);
|
||||
void S8259A_Init(CartInfo *info);
|
||||
void S8259B_Init(CartInfo *info);
|
||||
void S8259C_Init(CartInfo *info);
|
||||
void S8259D_Init(CartInfo *info);
|
||||
void SA0036_Init(CartInfo *info);
|
||||
void SA0037_Init(CartInfo *info);
|
||||
void SA009_Init(CartInfo *info);
|
||||
void SA0161M_Init(CartInfo *info);
|
||||
void SA72007_Init(CartInfo *info);
|
||||
void SA72008_Init(CartInfo *info);
|
||||
void SA9602B_Init(CartInfo *info);
|
||||
void SAROM_Init(CartInfo *info);
|
||||
void SBROM_Init(CartInfo *info);
|
||||
void SCROM_Init(CartInfo *info);
|
||||
void SEROM_Init(CartInfo *info);
|
||||
void SGROM_Init(CartInfo *info);
|
||||
void SKROM_Init(CartInfo *info);
|
||||
void SL1ROM_Init(CartInfo *info);
|
||||
void SLROM_Init(CartInfo *info);
|
||||
void SNROM_Init(CartInfo *info);
|
||||
void SOROM_Init(CartInfo *info);
|
||||
void SSSNROM_Init(CartInfo *info);
|
||||
void SUNSOFT_UNROM_Init(CartInfo *info); // "Shanghi" original version mapper
|
||||
void Super24_Init(CartInfo *info);
|
||||
void Supervision16_Init(CartInfo *info);
|
||||
void TBROM_Init(CartInfo *info);
|
||||
void TCA01_Init(CartInfo *info);
|
||||
void TCU01_Init(CartInfo *info);
|
||||
void TCU02_Init(CartInfo *info);
|
||||
void TEROM_Init(CartInfo *info);
|
||||
void TFROM_Init(CartInfo *info);
|
||||
void TGROM_Init(CartInfo *info);
|
||||
void TKROM_Init(CartInfo *info);
|
||||
void TKSROM_Init(CartInfo *info);
|
||||
void TLROM_Init(CartInfo *info);
|
||||
void TLSROM_Init(CartInfo *info);
|
||||
void TQROM_Init(CartInfo *info);
|
||||
void TQROM_Init(CartInfo *info);
|
||||
void TSROM_Init(CartInfo *info);
|
||||
void Transformer_Init(CartInfo *info);
|
||||
void UNL22211_Init(CartInfo *info);
|
||||
void UNL3DBlock_Init(CartInfo *info);
|
||||
void UNL43272_Init(CartInfo *info);
|
||||
void UNL6035052_Init(CartInfo *info);
|
||||
void UNL8157_Init(CartInfo *info);
|
||||
void UNL8237A_Init(CartInfo *info);
|
||||
void UNL8237_Init(CartInfo *info);
|
||||
void UNLA9746_Init(CartInfo *info);
|
||||
void UNLAX5705_Init(CartInfo *info);
|
||||
void UNLBB_Init(CartInfo *info);
|
||||
void UNLCC21_Init(CartInfo *info);
|
||||
void UNLCITYFIGHT_Init(CartInfo *info);
|
||||
void UNLD2000_Init(CartInfo *info);
|
||||
void UNLEDU2000_Init(CartInfo *info);
|
||||
void UNLFS304_Init(CartInfo *info);
|
||||
void UNLH2288_Init(CartInfo *info);
|
||||
void UNLKOF97_Init(CartInfo *info);
|
||||
void UNLKS7012_Init(CartInfo *info);
|
||||
void UNLKS7013B_Init(CartInfo *info);
|
||||
void UNLKS7017_Init(CartInfo *info);
|
||||
void UNLKS7030_Init(CartInfo *info);
|
||||
void UNLKS7031_Init(CartInfo *info);
|
||||
void UNLKS7032_Init(CartInfo *info);
|
||||
void UNLKS7037_Init(CartInfo *info);
|
||||
void UNLKS7057_Init(CartInfo *info);
|
||||
void UNLN625092_Init(CartInfo *info);
|
||||
void UNLMaliSB_Init(CartInfo *info);
|
||||
void UNLOneBus_Init(CartInfo *info);
|
||||
void UNLPEC586Init(CartInfo *info);
|
||||
void UNLSC127_Init(CartInfo *info);
|
||||
void UNLSHeroes_Init(CartInfo *info);
|
||||
void UNLSL12_Init(CartInfo *info);
|
||||
void UNLSL1632_Init(CartInfo *info);
|
||||
void UNLSMB2J_Init(CartInfo *info);
|
||||
void UNLT230_Init(CartInfo *info);
|
||||
void UNLTF1201_Init(CartInfo *info);
|
||||
void UNLVRC7_Init(CartInfo *info);
|
||||
void UNLYOKO_Init(CartInfo *info);
|
||||
void UNROM_Init(CartInfo *info);
|
||||
void UNROM512_Init(CartInfo *info);
|
||||
void UNLSB2000_Init(CartInfo *info);
|
||||
void UNLKS7010_Init(CartInfo *info);
|
||||
void COOLBOY_Init(CartInfo *info);
|
||||
|
||||
extern uint8 *UNIFchrrama; // Meh. So I can stop CHR RAM
|
||||
// bank switcherooing with certain boards...
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
void AC08_Init(CartInfo *info);
|
||||
void ANROM_Init(CartInfo *info);
|
||||
void BMC11160_Init(CartInfo *info);
|
||||
void BMC12IN1_Init(CartInfo *info);
|
||||
void BMC13in1JY110_Init(CartInfo *info);
|
||||
void BMC190in1_Init(CartInfo *info);
|
||||
void BMC411120C_Init(CartInfo *info);
|
||||
void BMC64in1nr_Init(CartInfo *info);
|
||||
void BMC70in1B_Init(CartInfo *info);
|
||||
void BMC70in1_Init(CartInfo *info);
|
||||
void BMC810544CA1_Init(CartInfo *info);
|
||||
void BMC830118C_Init(CartInfo *info);
|
||||
void BMCA65AS_Init(CartInfo *info);
|
||||
void BMCBS5_Init(CartInfo *info);
|
||||
void BMCD1038_Init(CartInfo *info);
|
||||
void BMCFK23CA_Init(CartInfo *info);
|
||||
void BMCFK23C_Init(CartInfo *info);
|
||||
void BMCG146_Init(CartInfo *info);
|
||||
void BMCGK192_Init(CartInfo *info);
|
||||
void BMCGS2004_Init(CartInfo *info);
|
||||
void BMCGS2013_Init(CartInfo *info);
|
||||
void BMCGhostbusters63in1_Init(CartInfo *info);
|
||||
void BMCNTD03_Init(CartInfo *info);
|
||||
void BMCT2271_Init(CartInfo *info);
|
||||
void BMCT262_Init(CartInfo *info);
|
||||
void BMC1024CA1_Init(CartInfo *info);
|
||||
void CNROM_Init(CartInfo *info);
|
||||
void CPROM_Init(CartInfo *info);
|
||||
void DreamTech01_Init(CartInfo *info);
|
||||
void EKROM_Init(CartInfo *info);
|
||||
void ELROM_Init(CartInfo *info);
|
||||
void ETROM_Init(CartInfo *info);
|
||||
void EWROM_Init(CartInfo *info);
|
||||
void GNROM_Init(CartInfo *info);
|
||||
void HKROM_Init(CartInfo *info);
|
||||
void LE05_Init(CartInfo *info);
|
||||
void LH10_Init(CartInfo *info);
|
||||
void LH32_Init(CartInfo *info);
|
||||
void LH53_Init(CartInfo *info);
|
||||
void MALEE_Init(CartInfo *info);
|
||||
void MHROM_Init(CartInfo *info);
|
||||
void Mapper190_Init(CartInfo *info);
|
||||
void NROM_Init(CartInfo *info);
|
||||
void Novel_Init(CartInfo *info);
|
||||
void S74LS374NA_Init(CartInfo *info);
|
||||
void S74LS374N_Init(CartInfo *info);
|
||||
void S8259A_Init(CartInfo *info);
|
||||
void S8259B_Init(CartInfo *info);
|
||||
void S8259C_Init(CartInfo *info);
|
||||
void S8259D_Init(CartInfo *info);
|
||||
void SA0036_Init(CartInfo *info);
|
||||
void SA0037_Init(CartInfo *info);
|
||||
void SA009_Init(CartInfo *info);
|
||||
void SA0161M_Init(CartInfo *info);
|
||||
void SA72007_Init(CartInfo *info);
|
||||
void SA72008_Init(CartInfo *info);
|
||||
void SA9602B_Init(CartInfo *info);
|
||||
void SAROM_Init(CartInfo *info);
|
||||
void SBROM_Init(CartInfo *info);
|
||||
void SCROM_Init(CartInfo *info);
|
||||
void SEROM_Init(CartInfo *info);
|
||||
void SGROM_Init(CartInfo *info);
|
||||
void SKROM_Init(CartInfo *info);
|
||||
void SL1ROM_Init(CartInfo *info);
|
||||
void SLROM_Init(CartInfo *info);
|
||||
void SNROM_Init(CartInfo *info);
|
||||
void SOROM_Init(CartInfo *info);
|
||||
void SSSNROM_Init(CartInfo *info);
|
||||
void SUNSOFT_UNROM_Init(CartInfo *info); // "Shanghi" original version mapper
|
||||
void Super24_Init(CartInfo *info);
|
||||
void Supervision16_Init(CartInfo *info);
|
||||
void TBROM_Init(CartInfo *info);
|
||||
void TCA01_Init(CartInfo *info);
|
||||
void TCU01_Init(CartInfo *info);
|
||||
void TCU02_Init(CartInfo *info);
|
||||
void TEROM_Init(CartInfo *info);
|
||||
void TFROM_Init(CartInfo *info);
|
||||
void TGROM_Init(CartInfo *info);
|
||||
void TKROM_Init(CartInfo *info);
|
||||
void TKSROM_Init(CartInfo *info);
|
||||
void TLROM_Init(CartInfo *info);
|
||||
void TLSROM_Init(CartInfo *info);
|
||||
void TQROM_Init(CartInfo *info);
|
||||
void TQROM_Init(CartInfo *info);
|
||||
void TSROM_Init(CartInfo *info);
|
||||
void Transformer_Init(CartInfo *info);
|
||||
void UNL22211_Init(CartInfo *info);
|
||||
void UNL3DBlock_Init(CartInfo *info);
|
||||
void UNL43272_Init(CartInfo *info);
|
||||
void UNL6035052_Init(CartInfo *info);
|
||||
void UNL8157_Init(CartInfo *info);
|
||||
void UNL8237A_Init(CartInfo *info);
|
||||
void UNL8237_Init(CartInfo *info);
|
||||
void UNLA9746_Init(CartInfo *info);
|
||||
void UNLAX5705_Init(CartInfo *info);
|
||||
void UNLBB_Init(CartInfo *info);
|
||||
void UNLCC21_Init(CartInfo *info);
|
||||
void UNLCITYFIGHT_Init(CartInfo *info);
|
||||
void UNLD2000_Init(CartInfo *info);
|
||||
void UNLEDU2000_Init(CartInfo *info);
|
||||
void UNLFS304_Init(CartInfo *info);
|
||||
void UNLH2288_Init(CartInfo *info);
|
||||
void UNLKOF97_Init(CartInfo *info);
|
||||
void UNLKS7012_Init(CartInfo *info);
|
||||
void UNLKS7013B_Init(CartInfo *info);
|
||||
void UNLKS7016_Init(CartInfo *info);
|
||||
void UNLKS7017_Init(CartInfo *info);
|
||||
void UNLKS7030_Init(CartInfo *info);
|
||||
void UNLKS7031_Init(CartInfo *info);
|
||||
void UNLKS7032_Init(CartInfo *info);
|
||||
void UNLKS7037_Init(CartInfo *info);
|
||||
void UNLKS7057_Init(CartInfo *info);
|
||||
void UNLN625092_Init(CartInfo *info);
|
||||
void UNLMaliSB_Init(CartInfo *info);
|
||||
void UNLOneBus_Init(CartInfo *info);
|
||||
void UNLPEC586Init(CartInfo *info);
|
||||
void UNLSC127_Init(CartInfo *info);
|
||||
void UNLSHeroes_Init(CartInfo *info);
|
||||
void UNLSL12_Init(CartInfo *info);
|
||||
void UNLSL1632_Init(CartInfo *info);
|
||||
void UNLSMB2J_Init(CartInfo *info);
|
||||
void UNLT230_Init(CartInfo *info);
|
||||
void UNLTF1201_Init(CartInfo *info);
|
||||
void UNLVRC7_Init(CartInfo *info);
|
||||
void UNLYOKO_Init(CartInfo *info);
|
||||
void UNROM_Init(CartInfo *info);
|
||||
void UNROM512_Init(CartInfo *info);
|
||||
void UNLSB2000_Init(CartInfo *info);
|
||||
void UNLKS7010_Init(CartInfo *info);
|
||||
void COOLBOY_Init(CartInfo *info);
|
||||
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...
|
||||
|
@ -39,11 +39,7 @@ void *FCEU_gmalloc(uint32 size)
|
||||
FCEU_PrintError("Error allocating memory! Doing a hard exit.");
|
||||
exit(1);
|
||||
}
|
||||
//mbg 6/17/08 - sometimes this memory is used as RAM or somesuch without clearing first.
|
||||
//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);
|
||||
FCEU_MemoryRand((uint8*)ret,size,true); // initialize according to RAMInitOption, default zero
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -57,11 +53,7 @@ void *FCEU_malloc(uint32 size)
|
||||
FCEU_PrintError("Error allocating memory!");
|
||||
return(0);
|
||||
}
|
||||
//mbg 6/17/08 - sometimes this memory is used as RAM or somesuch without clearing first.
|
||||
//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);
|
||||
memset(ret,0,size); // initialize to 0
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,8 @@
|
||||
|
||||
#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_gmalloc(uint32 size);
|
||||
void *FCEU_malloc(uint32 size); // initialized to 0
|
||||
void *FCEU_gmalloc(uint32 size); // used by boards for WRAM etc, initialized to 0 (default) or other via RAMInitOption
|
||||
void FCEU_gfree(void *ptr);
|
||||
void FCEU_free(void *ptr);
|
||||
void FCEU_memmove(void *d, void *s, uint32 l);
|
||||
|
@ -231,8 +231,8 @@ std::string BytesToString(const void* data, int len)
|
||||
{
|
||||
Base64Table[ input[0] >> 2 ],
|
||||
Base64Table[ ((input[0] & 0x03) << 4) | (input[1] >> 4) ],
|
||||
n<2 ? '=' : Base64Table[ ((input[1] & 0x0F) << 2) | (input[2] >> 6) ],
|
||||
n<3 ? '=' : Base64Table[ input[2] & 0x3F ]
|
||||
static_cast<unsigned char> (n<2 ? '=' : Base64Table[ ((input[1] & 0x0F) << 2) | (input[2] >> 6) ]),
|
||||
static_cast<unsigned char> (n<3 ? '=' : Base64Table[ input[2] & 0x3F ])
|
||||
};
|
||||
ret.append(output, output+4);
|
||||
}
|
||||
@ -296,9 +296,9 @@ bool StringToBytes(const std::string& str, void* data, int len)
|
||||
}
|
||||
unsigned char outpacket[3] =
|
||||
{
|
||||
(converted[0] << 2) | (converted[1] >> 4),
|
||||
(converted[1] << 4) | (converted[2] >> 2),
|
||||
(converted[2] << 6) | (converted[3])
|
||||
static_cast<unsigned char>((converted[0] << 2) | (converted[1] >> 4)),
|
||||
static_cast<unsigned char>((converted[1] << 4) | (converted[2] >> 2)),
|
||||
static_cast<unsigned char>((converted[2] << 6) | (converted[3]))
|
||||
};
|
||||
int outlen = (input[2] == '=') ? 1 : (input[3] == '=' ? 2 : 3);
|
||||
if(outlen > len) outlen = len;
|
||||
|
@ -26,12 +26,12 @@
|
||||
|
||||
//todo - everyone will want to support this eventually, i suppose
|
||||
#ifdef _MSC_VER
|
||||
#include "svnrev.h"
|
||||
#include "scmrev.h"
|
||||
#else
|
||||
#ifdef SVN_REV
|
||||
#define SVN_REV_STR SVN_REV
|
||||
#define SCM_REV_STR SCM_REV
|
||||
#else
|
||||
#define SVN_REV_STR ""
|
||||
#define SCM_REV_STR ""
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
#elif defined(PUBLIC_RELEASE)
|
||||
#define FCEU_SUBVERSION_STRING ""
|
||||
#else
|
||||
#define FCEU_SUBVERSION_STRING "-interim svn" SVN_REV_STR
|
||||
#define FCEU_SUBVERSION_STRING "-interim git" SCM_REV_STR
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "vsuni.h"
|
||||
#include "drawing.h"
|
||||
#include "driver.h"
|
||||
|
||||
#ifdef _S9XLUA_H
|
||||
#include "fceulua.h"
|
||||
#endif
|
||||
@ -56,10 +57,17 @@
|
||||
#include <cstdarg>
|
||||
#include <zlib.h>
|
||||
|
||||
uint8 *XBuf=NULL;
|
||||
uint8 *XBackBuf=NULL;
|
||||
//XBuf:
|
||||
//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
|
||||
static uint8 *xbsave=NULL;
|
||||
static u8 *xbsave=NULL;
|
||||
|
||||
GUIMESSAGE guiMessage;
|
||||
GUIMESSAGE subtitleMessage;
|
||||
@ -105,29 +113,35 @@ void FCEU_KillVirtualVideo(void)
|
||||
**/
|
||||
int FCEU_InitVirtualVideo(void)
|
||||
{
|
||||
if(!XBuf) /* Some driver code may allocate XBuf externally. */
|
||||
/* 256 bytes per scanline, * 240 scanline maximum, +16 for alignment,
|
||||
*/
|
||||
|
||||
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);
|
||||
|
||||
//Some driver code may allocate XBuf externally.
|
||||
//256 bytes per scanline, * 240 scanline maximum, +16 for alignment,
|
||||
if(XBuf)
|
||||
return 1;
|
||||
|
||||
XBuf = (u8*)FCEU_malloc(256 * 256 + 16);
|
||||
XBackBuf = (u8*)FCEU_malloc(256 * 256 + 16);
|
||||
XDBuf = (u8*)FCEU_malloc(256 * 256 + 16);
|
||||
XDBackBuf = (u8*)FCEU_malloc(256 * 256 + 16);
|
||||
if(!XBuf || !XBackBuf || !XDBuf || !XDBackBuf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
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
|
||||
@ -551,11 +565,14 @@ int GetScreenPixelPalette(int x, int y, bool usebackup) {
|
||||
|
||||
int SaveSnapshot(void)
|
||||
{
|
||||
#ifdef GEKKO
|
||||
return 0;
|
||||
#else
|
||||
int totallines=FSettings.LastSLine-FSettings.FirstSLine+1;
|
||||
int x,u,y;
|
||||
FILE *pp=NULL;
|
||||
uint8 *compmem=NULL;
|
||||
uLongf compmemsize=totallines*263+12;
|
||||
uLongf compmemsize=(totallines*263+12)*3;
|
||||
|
||||
if(!(compmem=(uint8 *)FCEU_malloc(compmemsize)))
|
||||
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)
|
||||
goto PNGerr;
|
||||
}
|
||||
@ -589,8 +606,8 @@ int SaveSnapshot(void)
|
||||
chunko[4]=chunko[5]=chunko[6]=0;
|
||||
chunko[7]=totallines; // Height
|
||||
|
||||
chunko[8]=8; // bit depth
|
||||
chunko[9]=3; // Color type; indexed 8-bit
|
||||
chunko[8]=8; // 8 bits per sample(24 bits per pixel)
|
||||
chunko[9]=2; // Color type; RGB triplet
|
||||
chunko[10]=0; // compression: deflate
|
||||
chunko[11]=0; // Basic adapative filter set(though none are used).
|
||||
chunko[12]=0; // No interlace.
|
||||
@ -599,19 +616,12 @@ int SaveSnapshot(void)
|
||||
goto PNGerr;
|
||||
}
|
||||
|
||||
{
|
||||
uint8 pdata[256*3];
|
||||
for(x=0;x<256;x++)
|
||||
FCEUD_GetPalette(x,pdata+x*3,pdata+x*3+1,pdata+x*3+2);
|
||||
if(!WritePNGChunk(pp,256*3,"PLTE",pdata))
|
||||
goto PNGerr;
|
||||
}
|
||||
|
||||
{
|
||||
uint8 *tmp=XBuf+FSettings.FirstSLine*256;
|
||||
uint8 *dest,*mal,*mork;
|
||||
|
||||
if(!(mal=mork=dest=(uint8 *)FCEU_dmalloc((totallines<<8)+totallines)))
|
||||
int bufsize = (256*3+1)*totallines;
|
||||
if(!(mal=mork=dest=(uint8 *)FCEU_dmalloc(bufsize)))
|
||||
goto PNGerr;
|
||||
// mork=dest=XBuf;
|
||||
|
||||
@ -619,11 +629,17 @@ int SaveSnapshot(void)
|
||||
{
|
||||
*dest=0; // No filter.
|
||||
dest++;
|
||||
for(x=256;x;x--,tmp++,dest++)
|
||||
*dest=*tmp;
|
||||
for(x=256;x;x--)
|
||||
{
|
||||
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);
|
||||
goto PNGerr;
|
||||
@ -647,6 +663,7 @@ PNGerr:
|
||||
if(pp)
|
||||
fclose(pp);
|
||||
return(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
//overloaded SaveSnapshot for "Savesnapshot As" function
|
||||
|
@ -9,6 +9,8 @@ uint32 GetScreenPixel(int x, int y, bool usebackup);
|
||||
int GetScreenPixelPalette(int x, int y, bool usebackup);
|
||||
extern uint8 *XBuf;
|
||||
extern uint8 *XBackBuf;
|
||||
extern uint8 *XDBuf;
|
||||
extern uint8 *XDBackBuf;
|
||||
extern int ClipSidesOffset;
|
||||
extern struct GUIMESSAGE
|
||||
{
|
||||
|
@ -301,7 +301,7 @@ void FCEU_VSUniCheck(uint64 md5partial, int *MapperNo, uint8 *Mirroring) {
|
||||
|
||||
while (vs->name) {
|
||||
if (md5partial == vs->md5partial) {
|
||||
if (vs->ppu < RCP2C03B) pale = vs->ppu;
|
||||
if (vs->ppu < RCP2C03B) default_palette_selection = vs->ppu;
|
||||
*MapperNo = vs->mapper;
|
||||
*Mirroring = vs->mirroring;
|
||||
GameInfo->type = GIT_VSUNI;
|
||||
|
@ -32,14 +32,16 @@
|
||||
#include <cstring>
|
||||
X6502 X;
|
||||
uint32 timestamp;
|
||||
uint32 soundtimestamp;
|
||||
void (*MapIRQHook)(int a);
|
||||
|
||||
#define ADDCYC(x) \
|
||||
{ \
|
||||
{ \
|
||||
int __x=x; \
|
||||
_tcount+=__x; \
|
||||
_count-=__x*48; \
|
||||
timestamp+=__x; \
|
||||
if(!overclocking) soundtimestamp+=__x; \
|
||||
}
|
||||
|
||||
//normal memory read
|
||||
@ -404,12 +406,14 @@ void X6502_Init(void)
|
||||
}
|
||||
}
|
||||
|
||||
extern int StackAddrBackup;
|
||||
void X6502_Power(void)
|
||||
{
|
||||
_count=_tcount=_IRQlow=_PC=_A=_X=_Y=_P=_PI=_DB=_jammed=0;
|
||||
_S=0xFD;
|
||||
timestamp=0;
|
||||
timestamp=soundtimestamp=0;
|
||||
X6502_Reset();
|
||||
StackAddrBackup = -1;
|
||||
}
|
||||
|
||||
void X6502_Run(int32 cycles)
|
||||
@ -493,7 +497,9 @@ extern int test; test++;
|
||||
temp=_tcount;
|
||||
_tcount=0;
|
||||
if(MapIRQHook) MapIRQHook(temp);
|
||||
FCEU_SoundCPUHook(temp);
|
||||
|
||||
if (!overclocking)
|
||||
FCEU_SoundCPUHook(temp);
|
||||
#ifdef _S9XLUA_H
|
||||
CallRegisteredLuaMemHook(_PC, 1, 0, LUAMEMHOOK_EXEC);
|
||||
#endif
|
||||
@ -537,7 +543,7 @@ const uint8 opsize[256] = {
|
||||
#else
|
||||
/*0x00*/ 1, //BRK
|
||||
#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,
|
||||
/*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,
|
||||
@ -569,20 +575,58 @@ const uint8 opsize[256] = {
|
||||
// 8 = Zero Page,Y
|
||||
//
|
||||
const uint8 optype[256] = {
|
||||
/*0x00*/ 0,1,0,0,0,2,2,0,0,0,0,0,0,3,3,0,
|
||||
/*0x10*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0,
|
||||
/*0x20*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0,
|
||||
/*0x30*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0,
|
||||
/*0x40*/ 0,1,0,0,0,2,2,0,0,0,0,0,0,3,3,0,
|
||||
/*0x50*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0,
|
||||
/*0x60*/ 0,1,0,0,0,2,2,0,0,0,0,0,3,3,3,0,
|
||||
/*0x70*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0,
|
||||
/*0x80*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0,
|
||||
/*0x90*/ 0,4,0,0,5,5,8,0,0,6,0,0,0,7,0,0,
|
||||
/*0xA0*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0,
|
||||
/*0xB0*/ 0,4,0,0,5,5,8,0,0,6,0,0,7,7,6,0,
|
||||
/*0xC0*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0,
|
||||
/*0xD0*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0,
|
||||
/*0xE0*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0,
|
||||
/*0xF0*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0
|
||||
/*0x00*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||
/*0x10*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
|
||||
/*0x20*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||
/*0x30*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
|
||||
/*0x40*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||
/*0x50*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
|
||||
/*0x60*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||
/*0x70*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
|
||||
/*0x80*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||
/*0x90*/ 0,4,0,3,5,5,8,8,0,6,0,6,7,7,6,6,
|
||||
/*0xA0*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||
/*0xB0*/ 0,4,0,3,5,5,8,8,0,6,0,6,7,7,6,6,
|
||||
/*0xC0*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||
/*0xD0*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
|
||||
/*0xE0*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||
/*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,
|
||||
};
|
@ -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
|
||||
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
|
||||
//#ifdef FCEUDEF_DEBUGGER
|
||||
@ -47,8 +50,8 @@ void X6502_RunDebug(int32 cycles);
|
||||
//------------
|
||||
|
||||
extern uint32 timestamp;
|
||||
|
||||
|
||||
extern uint32 soundtimestamp;
|
||||
extern int scanline;
|
||||
|
||||
#define N_FLAG 0x80
|
||||
#define V_FLAG 0x40
|
||||
|
@ -18,6 +18,10 @@
|
||||
#include "menu.h"
|
||||
|
||||
bool turbo = false;
|
||||
bool paldeemphswap = 0;
|
||||
int dendy;
|
||||
bool swapDuty;
|
||||
int KillFCEUXonFrame = 0;
|
||||
|
||||
/**
|
||||
* 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 FCEUD_SoundVolumeAdjust(int n) { }
|
||||
void FCEUD_SetEmulationSpeed(int cmd) { }
|
||||
void GetMouseData(uint32 (&d)[3]) { }
|
||||
|
Loading…
Reference in New Issue
Block a user