mirror of
https://github.com/dborth/fceugx.git
synced 2024-11-01 06:55:05 +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)
|
* Cheat support (.CHT files and Game Genie)
|
||||||
* Famicom 3D System support
|
* Famicom 3D System support
|
||||||
* IPS/UPS automatic patching support
|
* IPS/UPS automatic patching support
|
||||||
* NES Compatibility Based on FCEUX 2.2.0+ (r2951)
|
* NES Compatibility Based on FCEUX 2.2.3+ (git 21c0971)
|
||||||
* Open Source!
|
* Open Source!
|
||||||
|
|
||||||
×—–—–—–—– –—–—–—–—–—–—–—–—–—–— —–—–—–—–—–—–—–—-—–-–•¬
|
×—–—–—–—– –—–—–—–—–—–—–—–—–—–— —–—–—–—–—–—–—–—-—–-–•¬
|
||||||
@ -39,6 +39,7 @@ https://github.com/dborth/fceugx/releases
|
|||||||
|
|
||||||
[3.4.0]
|
[3.4.0]
|
||||||
|
|
||||||
|
* Update to the latest FCEUX core
|
||||||
* Allow loader to pass two arguments instead of three (libertyernie)
|
* Allow loader to pass two arguments instead of three (libertyernie)
|
||||||
* Add PocketNES interoperability (load ROMs and read/write SRAM)
|
* Add PocketNES interoperability (load ROMs and read/write SRAM)
|
||||||
* Add option to not append " Auto" on saves
|
* Add option to not append " Auto" on saves
|
||||||
|
@ -272,7 +272,7 @@ char *Disassemble(int addr, uint8 *opcode) {
|
|||||||
(a) = opcode[1] | opcode[2]<<8; \
|
(a) = opcode[1] | opcode[2]<<8; \
|
||||||
}
|
}
|
||||||
#define zpIndex(a,i) { \
|
#define zpIndex(a,i) { \
|
||||||
(a) = opcode[1]+(i); \
|
(a) = (opcode[1]+(i))&0xFF; \
|
||||||
}
|
}
|
||||||
#define indirectX(a) { \
|
#define indirectX(a) { \
|
||||||
(a) = (opcode[1]+RX)&0xFF; \
|
(a) = (opcode[1]+RX)&0xFF; \
|
||||||
@ -360,8 +360,8 @@ char *Disassemble(int addr, uint8 *opcode) {
|
|||||||
case 0xE6: strcpy(chr,"INC"); goto _zeropage;
|
case 0xE6: strcpy(chr,"INC"); goto _zeropage;
|
||||||
_zeropage:
|
_zeropage:
|
||||||
// ################################## Start of SP CODE ###########################
|
// ################################## Start of SP CODE ###########################
|
||||||
// Change width to %04X
|
// Change width to %04X // don't!
|
||||||
sprintf(str,"%s $%04X = #$%02X", chr,opcode[1],GetMem(opcode[1]));
|
sprintf(str,"%s $%02X = #$%02X", chr,opcode[1],GetMem(opcode[1]));
|
||||||
// ################################## End of SP CODE ###########################
|
// ################################## End of SP CODE ###########################
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -457,7 +457,7 @@ char *Disassemble(int addr, uint8 *opcode) {
|
|||||||
_zeropagex:
|
_zeropagex:
|
||||||
zpIndex(tmp,RX);
|
zpIndex(tmp,RX);
|
||||||
// ################################## Start of SP CODE ###########################
|
// ################################## Start of SP CODE ###########################
|
||||||
// Change width to %04X
|
// Change width to %04X // don't!
|
||||||
sprintf(str,"%s $%02X,X @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
sprintf(str,"%s $%02X,X @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
||||||
// ################################## End of SP CODE ###########################
|
// ################################## End of SP CODE ###########################
|
||||||
break;
|
break;
|
||||||
@ -515,8 +515,8 @@ char *Disassemble(int addr, uint8 *opcode) {
|
|||||||
_zeropagey:
|
_zeropagey:
|
||||||
zpIndex(tmp,RY);
|
zpIndex(tmp,RY);
|
||||||
// ################################## Start of SP CODE ###########################
|
// ################################## Start of SP CODE ###########################
|
||||||
// Change width to %04X
|
// Change width to %04X // don't!
|
||||||
sprintf(str,"%s $%04X,Y @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
sprintf(str,"%s $%02X,Y @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
||||||
// ################################## End of SP CODE ###########################
|
// ################################## End of SP CODE ###########################
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
*
|
*
|
||||||
* TXC mappers, originally much complex banksitching
|
* TXC mappers, originally much complex banksitching
|
||||||
*
|
*
|
||||||
|
* P/N PRG MAP, UNIF Name
|
||||||
* 01-22111-000 (05-00002-010) (132, 22211) - MGC-001 Qi Wang
|
* 01-22111-000 (05-00002-010) (132, 22211) - MGC-001 Qi Wang
|
||||||
* 01-22110-000 (52S ) - MGC-002 2-in-1 Gun
|
* 01-22110-000 (52S ) - MGC-002 2-in-1 Gun
|
||||||
* 01-22111-100 (02-00002-010) (173 ) - MGC-008 Mahjong Block
|
* 01-22111-100 (02-00002-010) (173 ) - MGC-008 Mahjong Block
|
||||||
@ -27,6 +28,7 @@
|
|||||||
* 01-22000-400 (05-00002-010) (036 ) - MGC-015 Policeman
|
* 01-22000-400 (05-00002-010) (036 ) - MGC-015 Policeman
|
||||||
* 01-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior
|
* 01-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior
|
||||||
* 01-11160-000 (04-02310-000) ( , 11160) - MGC-023 6-in-1
|
* 01-11160-000 (04-02310-000) ( , 11160) - MGC-023 6-in-1
|
||||||
|
* 01-22026-000 (05-04010-090) ( ) - MGC-026 4-in-1
|
||||||
* 01-22270-000 (05-00002-010) (132, 22211) - MGC-xxx Creatom
|
* 01-22270-000 (05-00002-010) (132, 22211) - MGC-xxx Creatom
|
||||||
* 01-22200-400 (------------) (079 ) - ET.03 F-15 City War
|
* 01-22200-400 (------------) (079 ) - ET.03 F-15 City War
|
||||||
* (172 ) - 1991 Du Ma Racing
|
* (172 ) - 1991 Du Ma Racing
|
||||||
|
@ -55,7 +55,7 @@ static void M168Power(void) {
|
|||||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MNNNClose(void) {
|
static void M168Close(void) {
|
||||||
if (CHRRAM)
|
if (CHRRAM)
|
||||||
FCEU_gfree(CHRRAM);
|
FCEU_gfree(CHRRAM);
|
||||||
CHRRAM = NULL;
|
CHRRAM = NULL;
|
||||||
@ -67,7 +67,7 @@ static void StateRestore(int version) {
|
|||||||
|
|
||||||
void Mapper168_Init(CartInfo *info) {
|
void Mapper168_Init(CartInfo *info) {
|
||||||
info->Power = M168Power;
|
info->Power = M168Power;
|
||||||
info->Close = MNNNClose;
|
info->Close = M168Close;
|
||||||
GameStateRestore = StateRestore;
|
GameStateRestore = StateRestore;
|
||||||
AddExState(&StateRegs, ~0, 0, 0);
|
AddExState(&StateRegs, ~0, 0, 0);
|
||||||
|
|
||||||
|
@ -29,6 +29,12 @@ static uint8 reg[4];
|
|||||||
static uint8 *WRAM = NULL;
|
static uint8 *WRAM = NULL;
|
||||||
static uint32 WRAMSIZE;
|
static uint32 WRAMSIZE;
|
||||||
|
|
||||||
|
// Tennis with VR sensor, very simple behaviour
|
||||||
|
extern void GetMouseData(uint32 (&md)[3]);
|
||||||
|
static uint32 MouseData[3], click, lastclick;
|
||||||
|
static int32 SensorDelay;
|
||||||
|
|
||||||
|
// highly experimental, not actually working, just curious if it hapen to work with some other decoder
|
||||||
// SND Registers
|
// SND Registers
|
||||||
static uint8 pcm_enable = 0;
|
static uint8 pcm_enable = 0;
|
||||||
static int16 pcm_latch = 0x3F6, pcm_clock = 0x3F6;
|
static int16 pcm_latch = 0x3F6, pcm_clock = 0x3F6;
|
||||||
@ -40,41 +46,41 @@ static SFORMAT StateRegs[] =
|
|||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int16 step_size[49] = {
|
//static int16 step_size[49] = {
|
||||||
16, 17, 19, 21, 23, 25, 28, 31, 34, 37,
|
// 16, 17, 19, 21, 23, 25, 28, 31, 34, 37,
|
||||||
41, 45, 50, 55, 60, 66, 73, 80, 88, 97,
|
// 41, 45, 50, 55, 60, 66, 73, 80, 88, 97,
|
||||||
107, 118, 130, 143, 157, 173, 190, 209, 230, 253,
|
// 107, 118, 130, 143, 157, 173, 190, 209, 230, 253,
|
||||||
279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
|
// 279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
|
||||||
724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
|
// 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
|
||||||
}; //49 items
|
//}; //49 items
|
||||||
static int32 step_adj[16] = { -1, -1, -1, -1, 2, 5, 7, 9, -1, -1, -1, -1, 2, 5, 7, 9 };
|
//static int32 step_adj[16] = { -1, -1, -1, -1, 2, 5, 7, 9, -1, -1, -1, -1, 2, 5, 7, 9 };
|
||||||
|
|
||||||
//decode stuff
|
//decode stuff
|
||||||
static int32 jedi_table[16 * 49];
|
//static int32 jedi_table[16 * 49];
|
||||||
static int32 acc = 0; //ADPCM accumulator, initial condition must be 0
|
//static int32 acc = 0; //ADPCM accumulator, initial condition must be 0
|
||||||
static int32 decstep = 0; //ADPCM decoding step, initial condition must be 0
|
//static int32 decstep = 0; //ADPCM decoding step, initial condition must be 0
|
||||||
|
|
||||||
static void jedi_table_init() {
|
//static void jedi_table_init() {
|
||||||
int step, nib;
|
// int step, nib;
|
||||||
|
//
|
||||||
|
// for (step = 0; step < 49; step++) {
|
||||||
|
// for (nib = 0; nib < 16; nib++) {
|
||||||
|
// int value = (2 * (nib & 0x07) + 1) * step_size[step] / 8;
|
||||||
|
// jedi_table[step * 16 + nib] = ((nib & 0x08) != 0) ? -value : value;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
for (step = 0; step < 49; step++) {
|
//static uint8 decode(uint8 code) {
|
||||||
for (nib = 0; nib < 16; nib++) {
|
// acc += jedi_table[decstep + code];
|
||||||
int value = (2 * (nib & 0x07) + 1) * step_size[step] / 8;
|
// if ((acc & ~0x7ff) != 0) // acc is > 2047
|
||||||
jedi_table[step * 16 + nib] = ((nib & 0x08) != 0) ? -value : value;
|
// acc |= ~0xfff;
|
||||||
}
|
// else acc &= 0xfff;
|
||||||
}
|
// decstep += step_adj[code & 7] * 16;
|
||||||
}
|
// if (decstep < 0) decstep = 0;
|
||||||
|
// if (decstep > 48 * 16) decstep = 48 * 16;
|
||||||
static uint8 decode(uint8 code) {
|
// return (acc >> 8) & 0xff;
|
||||||
acc += jedi_table[decstep + code];
|
//}
|
||||||
if ((acc & ~0x7ff) != 0) // acc is > 2047
|
|
||||||
acc |= ~0xfff;
|
|
||||||
else acc &= 0xfff;
|
|
||||||
decstep += step_adj[code & 7] * 16;
|
|
||||||
if (decstep < 0) decstep = 0;
|
|
||||||
if (decstep > 48 * 16) decstep = 48 * 16;
|
|
||||||
return (acc >> 8) & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Sync(void) {
|
static void Sync(void) {
|
||||||
uint32 sbank = reg[1] & 0x7;
|
uint32 sbank = reg[1] & 0x7;
|
||||||
@ -109,11 +115,11 @@ static DECLFW(M178WriteSnd) {
|
|||||||
if (V & 0xF0) {
|
if (V & 0xF0) {
|
||||||
pcm_enable = 1;
|
pcm_enable = 1;
|
||||||
// pcmwrite(0x4011, (V & 0xF) << 3);
|
// pcmwrite(0x4011, (V & 0xF) << 3);
|
||||||
pcmwrite(0x4011, decode(V & 0xf));
|
// pcmwrite(0x4011, decode(V & 0xf));
|
||||||
} else
|
} else
|
||||||
pcm_enable = 0;
|
pcm_enable = 0;
|
||||||
} else
|
}// else
|
||||||
FCEU_printf("misc %04x:%02x\n", A, V);
|
// FCEU_printf("misc %04x:%02x\n", A, V);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DECLFR(M178ReadSnd) {
|
static DECLFR(M178ReadSnd) {
|
||||||
@ -123,13 +129,19 @@ static DECLFR(M178ReadSnd) {
|
|||||||
return X.DB;
|
return X.DB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DECLFR(M178ReadSensor) {
|
||||||
|
X6502_IRQEnd(FCEU_IQEXT); // hacky-hacky, actual reg is 6000 and it clear IRQ while reading, but then I need another mapper lol
|
||||||
|
return 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
static void M178Power(void) {
|
static void M178Power(void) {
|
||||||
reg[0] = reg[1] = reg[2] = reg[3] = 0;
|
reg[0] = reg[1] = reg[2] = reg[3] = SensorDelay = 0;
|
||||||
Sync();
|
Sync();
|
||||||
pcmwrite = GetWriteHandler(0x4011);
|
// pcmwrite = GetWriteHandler(0x4011);
|
||||||
SetWriteHandler(0x4800, 0x4fff, M178Write);
|
SetWriteHandler(0x4800, 0x4fff, M178Write);
|
||||||
SetWriteHandler(0x5800, 0x5fff, M178WriteSnd);
|
SetWriteHandler(0x5800, 0x5fff, M178WriteSnd);
|
||||||
SetReadHandler(0x5800, 0x5fff, M178ReadSnd);
|
SetReadHandler(0x5800, 0x5fff, M178ReadSnd);
|
||||||
|
SetReadHandler(0x5000, 0x5000, M178ReadSensor);
|
||||||
SetReadHandler(0x6000, 0x7fff, CartBR);
|
SetReadHandler(0x6000, 0x7fff, CartBR);
|
||||||
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
||||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||||
@ -137,13 +149,25 @@ static void M178Power(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void M178SndClk(int a) {
|
static void M178SndClk(int a) {
|
||||||
if (pcm_enable) {
|
SensorDelay += a;
|
||||||
pcm_latch -= a;
|
if(SensorDelay > 0x32768) {
|
||||||
if (pcm_latch <= 0) {
|
SensorDelay -= 32768;
|
||||||
pcm_latch += pcm_clock;
|
GetMouseData (MouseData);
|
||||||
pcm_enable = 0;
|
lastclick = click;
|
||||||
}
|
click = MouseData[2] & 1; // to prevent from continuos IRQ trigger if button is held.
|
||||||
|
// actual circuit is just a D-C-R edge detector for IR-sensor
|
||||||
|
// triggered by the active IR bat.
|
||||||
|
if(lastclick && !click)
|
||||||
|
X6502_IRQBegin(FCEU_IQEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (pcm_enable) {
|
||||||
|
// pcm_latch -= a;
|
||||||
|
// if (pcm_latch <= 0) {
|
||||||
|
// pcm_latch += pcm_clock;
|
||||||
|
// pcm_enable = 0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
static void M178Close(void) {
|
static void M178Close(void) {
|
||||||
@ -162,7 +186,7 @@ void Mapper178_Init(CartInfo *info) {
|
|||||||
GameStateRestore = StateRestore;
|
GameStateRestore = StateRestore;
|
||||||
MapIRQHook = M178SndClk;
|
MapIRQHook = M178SndClk;
|
||||||
|
|
||||||
jedi_table_init();
|
// jedi_table_init();
|
||||||
|
|
||||||
WRAMSIZE = 32768;
|
WRAMSIZE = 32768;
|
||||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2012 FCEUX team
|
Copyright (C) 2012-2017 FCEUX team
|
||||||
|
|
||||||
This file is free software: you can redistribute it and/or modify
|
This file is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -141,6 +141,7 @@ static DECLFW(WritePRG)
|
|||||||
case 0x00:
|
case 0x00:
|
||||||
chr = value & 3;
|
chr = value & 3;
|
||||||
Mirror(value);
|
Mirror(value);
|
||||||
|
Sync();
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
prg = value & 15;
|
prg = value & 15;
|
||||||
|
@ -22,11 +22,12 @@
|
|||||||
|
|
||||||
#include "mapinc.h"
|
#include "mapinc.h"
|
||||||
|
|
||||||
static uint8 latche;
|
static uint8 latche, mirr;
|
||||||
|
|
||||||
static SFORMAT StateRegs[] =
|
static SFORMAT StateRegs[] =
|
||||||
{
|
{
|
||||||
{ &latche, 1, "LATC" },
|
{ &latche, 1, "LATC" },
|
||||||
|
{ &mirr, 1, "MIRR" },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -36,6 +37,11 @@ static void Sync(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static DECLFW(M36Write) {
|
static DECLFW(M36Write) {
|
||||||
|
|
||||||
|
switch((A>>12)&7) { // need to 4-in-1 MGC-26 BMC, doesnt break other games though
|
||||||
|
case 0: mirr = MI_V; setmirror(mirr); break;
|
||||||
|
case 4: mirr = MI_H; setmirror(mirr); break;
|
||||||
|
}
|
||||||
latche = V;
|
latche = V;
|
||||||
Sync();
|
Sync();
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ static SFORMAT StateRegs[] =
|
|||||||
static void Sync(void) {
|
static void Sync(void) {
|
||||||
uint8 i;
|
uint8 i;
|
||||||
if ((preg[3] & 0xC0) == 0xC0)
|
if ((preg[3] & 0xC0) == 0xC0)
|
||||||
setprg8r(0x10, 0x6000, 0);
|
setprg8r(0x10, 0x6000, preg[3] & 0x3F);
|
||||||
else
|
else
|
||||||
setprg8(0x6000, preg[3] & 0x3F);
|
setprg8(0x6000, preg[3] & 0x3F);
|
||||||
setprg8(0x8000, preg[0]);
|
setprg8(0x8000, preg[0]);
|
||||||
@ -258,6 +258,9 @@ void Mapper69_Init(CartInfo *info) {
|
|||||||
info->Power = M69Power;
|
info->Power = M69Power;
|
||||||
info->Close = M69Close;
|
info->Close = M69Close;
|
||||||
MapIRQHook = M69IRQHook;
|
MapIRQHook = M69IRQHook;
|
||||||
|
if(info->ines2)
|
||||||
|
WRAMSIZE = info->wram_size + info->battery_wram_size;
|
||||||
|
else
|
||||||
WRAMSIZE = 8192;
|
WRAMSIZE = 8192;
|
||||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||||
|
@ -303,14 +303,20 @@ static void M212Sync(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Mapper212_Init(CartInfo *info) {
|
void Mapper212_Init(CartInfo *info) {
|
||||||
Latch_Init(info, M212Sync, M212Read, 0xFFFF, 0x8000, 0xFFFF, 0);
|
Latch_Init(info, M212Sync, M212Read, 0x0000, 0x8000, 0xFFFF, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------ Map 213 ---------------------------
|
//------------------ Map 213 ---------------------------
|
||||||
|
|
||||||
static void M213Sync(void) {
|
static void M213Sync(void) {
|
||||||
|
if(latche & 0x40) {
|
||||||
|
setprg16(0x8000, (latche & 7));
|
||||||
|
setprg16(0xC000, (latche & 7));
|
||||||
|
} else {
|
||||||
setprg32(0x8000, (latche >> 1) & 3);
|
setprg32(0x8000, (latche >> 1) & 3);
|
||||||
|
}
|
||||||
setchr8((latche >> 3) & 7);
|
setchr8((latche >> 3) & 7);
|
||||||
|
setmirror(((latche & 1)^((latche >> 6) & 1)) ^ 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mapper213_Init(CartInfo *info) {
|
void Mapper213_Init(CartInfo *info) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* FCE Ultra - NES/Famicom Emulator
|
/* FCE Ultra - NES/Famicom Emulator
|
||||||
*
|
*
|
||||||
* Copyright notice for this file:
|
* Copyright notice for this file:
|
||||||
* Copyright (C) 2015 CaH4e3
|
* Copyright (C) 2015 CaH4e3, ClusteR
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -20,70 +20,105 @@
|
|||||||
* CoolBoy 400-in-1 FK23C-mimic mapper 16Mb/32Mb PROM + 128K/256K CHR RAM, optional SRAM, optional NTRAM
|
* CoolBoy 400-in-1 FK23C-mimic mapper 16Mb/32Mb PROM + 128K/256K CHR RAM, optional SRAM, optional NTRAM
|
||||||
* only MMC3 mode
|
* only MMC3 mode
|
||||||
*
|
*
|
||||||
* 6000 (õõ76x210) | 0õÑ0
|
* 6000 (xx76x210) | 0xC0
|
||||||
* 6001 (õõõ354õõ)
|
* 6001 (xxx354x)
|
||||||
* 6002 = 0
|
* 6002 = 0
|
||||||
* 6003 = 0
|
* 6003 = 0
|
||||||
*
|
*
|
||||||
|
* hardware tested logic, don't try to understand lol
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mapinc.h"
|
#include "mapinc.h"
|
||||||
#include "mmc3.h"
|
#include "mmc3.h"
|
||||||
|
|
||||||
static void COOLBOYCW(uint32 A, uint8 V) {
|
static void COOLBOYCW(uint32 A, uint8 V) {
|
||||||
if(EXPREGS[3] & 0x10)
|
uint32 mask = 0xFF ^ (EXPREGS[0] & 0x80);
|
||||||
setchr8(EXPREGS[2] & 0xF);
|
if (EXPREGS[3] & 0x10) {
|
||||||
else {
|
if (EXPREGS[3] & 0x40) { // Weird mode
|
||||||
uint32 mask = 0xFF;
|
int cbase = (MMC3_cmd & 0x80) << 5;
|
||||||
switch(EXPREGS[0] & 0xC0) {
|
switch (cbase ^ A) { // Don't even try do understand
|
||||||
case 0xC0:
|
case 0x0400:
|
||||||
mask = 0x7F;
|
case 0x0C00: V &= 0x7F; break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
setchr1(A, V & mask);
|
}
|
||||||
|
// Highest bit goes from MMC3 registers when EXPREGS[3]&0x80==0 or from EXPREGS[0]&0x08 otherwise
|
||||||
|
setchr1(A,
|
||||||
|
(V & 0x80 & mask) | ((((EXPREGS[0] & 0x08) << 4) & ~mask)) // 7th bit
|
||||||
|
| ((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) {
|
static void COOLBOYPW(uint32 A, uint8 V) {
|
||||||
uint32 mask, shift;
|
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);
|
uint32 base = ((EXPREGS[0] & 0x07) >> 0) | ((EXPREGS[1] & 0x10) >> 1) | ((EXPREGS[1] & 0x0C) << 2) | ((EXPREGS[0] & 0x30) << 2);
|
||||||
switch(EXPREGS[0] & 0xC0) {
|
|
||||||
case 0x00:
|
// Very weird mode
|
||||||
mask = 0x3F;
|
// 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;
|
break;
|
||||||
case 0x80:
|
case 0xC000:
|
||||||
mask = 0x1F;
|
if (!(MMC3_cmd & 0x40)) V = 0;
|
||||||
break;
|
break;
|
||||||
case 0xC0:
|
case 0xE000:
|
||||||
if(EXPREGS[3] & 0x10) {
|
V = 0;
|
||||||
mask = 0x01 | (EXPREGS[1] & 2);
|
|
||||||
} else {
|
|
||||||
mask = 0x0F;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(EXPREGS[3] & 0x10)
|
}
|
||||||
setprg8(A, (base << 4) | (V & mask) | ((EXPREGS[3] & (0x0E ^ (EXPREGS[1] & 2))) ));
|
|
||||||
else
|
// Regular MMC3 mode, internal ROM size can be up to 2048kb!
|
||||||
setprg8(A, (base << 4) | (V & mask));
|
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) {
|
static DECLFW(COOLBOYWrite) {
|
||||||
if(A001B & 0x80)
|
if(A001B & 0x80)
|
||||||
CartBW(A,V);
|
CartBW(A,V);
|
||||||
else
|
|
||||||
if((EXPREGS[3] & 0x80) == 0) {
|
// Deny any further writes when 7th bit is 1 AND 4th is 0
|
||||||
|
if ((EXPREGS[3] & 0x90) != 0x80) {
|
||||||
EXPREGS[A & 3] = V;
|
EXPREGS[A & 3] = V;
|
||||||
FixMMC3PRG(MMC3_cmd);
|
FixMMC3PRG(MMC3_cmd);
|
||||||
FixMMC3CHR(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) {
|
static void COOLBOYReset(void) {
|
||||||
MMC3RegReset();
|
MMC3RegReset();
|
||||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||||
|
// EXPREGS[0] = 0;
|
||||||
|
// EXPREGS[1] = 0x60;
|
||||||
|
// EXPREGS[2] = 0;
|
||||||
|
// EXPREGS[3] = 0;
|
||||||
FixMMC3PRG(MMC3_cmd);
|
FixMMC3PRG(MMC3_cmd);
|
||||||
FixMMC3CHR(MMC3_cmd);
|
FixMMC3CHR(MMC3_cmd);
|
||||||
}
|
}
|
||||||
@ -91,18 +126,21 @@ static void COOLBOYReset(void) {
|
|||||||
static void COOLBOYPower(void) {
|
static void COOLBOYPower(void) {
|
||||||
GenMMC3Power();
|
GenMMC3Power();
|
||||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||||
|
// EXPREGS[0] = 0;
|
||||||
|
// EXPREGS[1] = 0x60;
|
||||||
|
// EXPREGS[2] = 0;
|
||||||
|
// EXPREGS[3] = 0;
|
||||||
FixMMC3PRG(MMC3_cmd);
|
FixMMC3PRG(MMC3_cmd);
|
||||||
FixMMC3CHR(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(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);
|
SetWriteHandler(0x6000, 0x7fff, COOLBOYWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
void COOLBOY_Init(CartInfo *info) {
|
void COOLBOY_Init(CartInfo *info) {
|
||||||
GenMMC3_Init(info, 512, 128, 8, 0);
|
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||||
pwrap = COOLBOYPW;
|
pwrap = COOLBOYPW;
|
||||||
cwrap = COOLBOYCW;
|
cwrap = COOLBOYCW;
|
||||||
info->Power = COOLBOYPower;
|
info->Power = COOLBOYPower;
|
||||||
info->Reset = COOLBOYReset;
|
info->Reset = COOLBOYReset;
|
||||||
AddExState(EXPREGS, 4, 0, "EXPR");
|
AddExState(EXPREGS, 4, 0, "EXPR");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ static void (*WSync)(void);
|
|||||||
static DECLFW(LatchWrite) {
|
static DECLFW(LatchWrite) {
|
||||||
// FCEU_printf("bs %04x %02x\n",A,V);
|
// FCEU_printf("bs %04x %02x\n",A,V);
|
||||||
if (bus_conflict)
|
if (bus_conflict)
|
||||||
latche = (V == CartBR(A)) ? V : 0;
|
latche = V & CartBR(A);
|
||||||
else
|
else
|
||||||
latche = V;
|
latche = V;
|
||||||
WSync();
|
WSync();
|
||||||
@ -68,7 +68,48 @@ static void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 ad
|
|||||||
info->Power = LatchPower;
|
info->Power = LatchPower;
|
||||||
info->Close = LatchClose;
|
info->Close = LatchClose;
|
||||||
GameStateRestore = StateRestore;
|
GameStateRestore = StateRestore;
|
||||||
if (wram) {
|
if(info->ines2)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
WRAMSIZE = 8192;
|
WRAMSIZE = 8192;
|
||||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||||
@ -78,6 +119,8 @@ static void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 ad
|
|||||||
}
|
}
|
||||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
AddExState(&latche, 1, 0, "LATC");
|
AddExState(&latche, 1, 0, "LATC");
|
||||||
AddExState(&bus_conflict, 1, 0, "BUSC");
|
AddExState(&bus_conflict, 1, 0, "BUSC");
|
||||||
}
|
}
|
||||||
@ -93,7 +136,7 @@ static DECLFW(NROMWrite) {
|
|||||||
|
|
||||||
static void NROMPower(void) {
|
static void NROMPower(void) {
|
||||||
setprg8r(0x10, 0x6000, 0); // Famili BASIC (v3.0) need it (uses only 4KB), FP-BASIC uses 8KB
|
setprg8r(0x10, 0x6000, 0); // Famili BASIC (v3.0) need it (uses only 4KB), FP-BASIC uses 8KB
|
||||||
setprg16(0x8000, 0);
|
setprg16(0x8000, ~1);
|
||||||
setprg16(0xC000, ~0);
|
setprg16(0xC000, ~0);
|
||||||
setchr8(0);
|
setchr8(0);
|
||||||
|
|
||||||
|
@ -13,12 +13,11 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GEKKO
|
||||||
typedef uint8_t uint8 ;
|
typedef uint8_t uint8 ;
|
||||||
typedef int8_t int8 ;
|
typedef int8_t int8 ;
|
||||||
|
|
||||||
@ -27,6 +26,16 @@ typedef int16_t int16 ;
|
|||||||
|
|
||||||
typedef uint32_t uint32 ;
|
typedef uint32_t uint32 ;
|
||||||
typedef int32_t int32 ;
|
typedef int32_t int32 ;
|
||||||
|
#else
|
||||||
|
typedef unsigned char uint8 ;
|
||||||
|
typedef signed char int8 ;
|
||||||
|
|
||||||
|
typedef unsigned short uint16 ;
|
||||||
|
typedef signed short int16 ;
|
||||||
|
|
||||||
|
typedef unsigned int uint32 ;
|
||||||
|
typedef signed int int32 ;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PI 3.14159265358979323846
|
#define PI 3.14159265358979323846
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ static void SSSNROMPower(void) {
|
|||||||
regs[0] = regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0;
|
regs[0] = regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0;
|
||||||
regs[7] = 0xff;
|
regs[7] = 0xff;
|
||||||
Sync();
|
Sync();
|
||||||
memset(WRAM, 0x00, WRAMSIZE);
|
FCEU_MemoryRand(WRAM, WRAMSIZE, true);
|
||||||
// SetWriteHandler(0x0000,0x1FFF,SSSNROMRamWrite);
|
// SetWriteHandler(0x0000,0x1FFF,SSSNROMRamWrite);
|
||||||
SetReadHandler(0x0800, 0x1FFF, CartBR);
|
SetReadHandler(0x0800, 0x1FFF, CartBR);
|
||||||
SetWriteHandler(0x0800, 0x1FFF, CartBW);
|
SetWriteHandler(0x0800, 0x1FFF, CartBW);
|
||||||
|
@ -34,20 +34,16 @@ static void BMCFK23CCW(uint32 A, uint8 V)
|
|||||||
setchr8(EXPREGS[2]|unromchr);
|
setchr8(EXPREGS[2]|unromchr);
|
||||||
else if(EXPREGS[0]&0x20) {
|
else if(EXPREGS[0]&0x20) {
|
||||||
setchr1r(0x10, A, V);
|
setchr1r(0x10, A, V);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
uint16 base=(EXPREGS[2]&0x7F)<<3;
|
uint16 base=(EXPREGS[2]&0x7F)<<3;
|
||||||
if(EXPREGS[3]&2)
|
if(EXPREGS[3]&2) {
|
||||||
{
|
|
||||||
int cbase=(MMC3_cmd&0x80)<<5;
|
int cbase=(MMC3_cmd&0x80)<<5;
|
||||||
setchr1(A,V|base);
|
setchr1(A,V|base);
|
||||||
setchr1(0x0000^cbase,DRegBuf[0]|base);
|
setchr1(0x0000^cbase,DRegBuf[0]|base);
|
||||||
setchr1(0x0400^cbase,EXPREGS[6]|base);
|
setchr1(0x0400^cbase,EXPREGS[6]|base);
|
||||||
setchr1(0x0800^cbase,DRegBuf[1]|base);
|
setchr1(0x0800^cbase,DRegBuf[1]|base);
|
||||||
setchr1(0x0c00^cbase,EXPREGS[7]|base);
|
setchr1(0x0c00^cbase,EXPREGS[7]|base);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
setchr1(A,V|base);
|
setchr1(A,V|base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,30 +86,28 @@ static void BMCFK23CPW(uint32 A, uint8 V)
|
|||||||
uint32 hiblock = ((EXPREGS[0] & 8) << 4)|((EXPREGS[0] & 0x80) << 1)|(UNIFchrrama?((EXPREGS[2] & 0x40)<<3):0);
|
uint32 hiblock = ((EXPREGS[0] & 8) << 4)|((EXPREGS[0] & 0x80) << 1)|(UNIFchrrama?((EXPREGS[2] & 0x40)<<3):0);
|
||||||
uint32 block = (EXPREGS[1] & 0x60) | hiblock;
|
uint32 block = (EXPREGS[1] & 0x60) | hiblock;
|
||||||
uint32 extra = (EXPREGS[3] & 2);
|
uint32 extra = (EXPREGS[3] & 2);
|
||||||
|
// FCEU_printf("0:%04X:%02X\n",A,V);
|
||||||
|
|
||||||
if((EXPREGS[0]&7)==4)
|
if((EXPREGS[0]&7)==4)
|
||||||
setprg32(0x8000,EXPREGS[1]>>1);
|
setprg32(0x8000,EXPREGS[1]>>1);
|
||||||
else if ((EXPREGS[0]&7)==3)
|
else if ((EXPREGS[0]&7)==3) {
|
||||||
{
|
|
||||||
setprg16(0x8000,EXPREGS[1]);
|
setprg16(0x8000,EXPREGS[1]);
|
||||||
setprg16(0xC000,EXPREGS[1]);
|
setprg16(0xC000,EXPREGS[1]);
|
||||||
}
|
} else {
|
||||||
else
|
if(EXPREGS[0]&3) {
|
||||||
{
|
|
||||||
if(EXPREGS[0]&3)
|
|
||||||
{
|
|
||||||
uint32 blocksize = (6)-(EXPREGS[0]&3);
|
uint32 blocksize = (6)-(EXPREGS[0]&3);
|
||||||
uint32 mask = (1<<blocksize)-1;
|
uint32 mask = (1<<blocksize)-1;
|
||||||
V &= mask;
|
V &= mask;
|
||||||
//V &= 63; //? is this a good idea?
|
//V &= 63; //? is this a good idea?
|
||||||
V |= (EXPREGS[1]<<1);
|
V |= (EXPREGS[1]<<1);
|
||||||
|
// FCEU_printf("1:%04X:%02X\n",A,V);
|
||||||
setprg8(A,V);
|
setprg8(A,V);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
setprg8(A,V & prg_mask);
|
setprg8(A,V & prg_mask);
|
||||||
|
// FCEU_printf("2:%04X:%02X\n",A,V);
|
||||||
|
}
|
||||||
|
|
||||||
if(EXPREGS[3]&2)
|
if(EXPREGS[3]&2) {
|
||||||
{
|
|
||||||
setprg8(0xC000,EXPREGS[4]);
|
setprg8(0xC000,EXPREGS[4]);
|
||||||
setprg8(0xE000,EXPREGS[5]);
|
setprg8(0xE000,EXPREGS[5]);
|
||||||
}
|
}
|
||||||
@ -124,25 +118,23 @@ static void BMCFK23CPW(uint32 A, uint8 V)
|
|||||||
//PRG handler ($8000-$FFFF)
|
//PRG handler ($8000-$FFFF)
|
||||||
static DECLFW(BMCFK23CHiWrite)
|
static DECLFW(BMCFK23CHiWrite)
|
||||||
{
|
{
|
||||||
if(EXPREGS[0]&0x40)
|
// FCEU_printf("K4:(exp0=%02x)\n",EXPREGS[0]);
|
||||||
{
|
// FCEU_printf("W0:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||||
|
if((EXPREGS[0]&0x60)==0x40) {
|
||||||
|
// FCEU_printf("W2:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||||
if(EXPREGS[0]&0x30)
|
if(EXPREGS[0]&0x30)
|
||||||
unromchr=0;
|
unromchr=0;
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
unromchr=V&3;
|
unromchr=V&3;
|
||||||
FixMMC3CHR(MMC3_cmd);
|
FixMMC3CHR(MMC3_cmd);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
if((A==0x8001)&&(EXPREGS[3]&2)&&(MMC3_cmd&8)) {
|
||||||
{
|
// FCEU_printf("W3:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||||
if((A==0x8001)&&(EXPREGS[3]&2&&MMC3_cmd&8))
|
|
||||||
{
|
|
||||||
EXPREGS[4|(MMC3_cmd&3)]=V;
|
EXPREGS[4|(MMC3_cmd&3)]=V;
|
||||||
FixMMC3PRG(MMC3_cmd);
|
FixMMC3PRG(MMC3_cmd);
|
||||||
FixMMC3CHR(MMC3_cmd);
|
FixMMC3CHR(MMC3_cmd);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
if(A<0xC000) {
|
if(A<0xC000) {
|
||||||
if(UNIFchrrama) { // hacky... strange behaviour, must be bit scramble due to pcb layot restrictions
|
if(UNIFchrrama) { // hacky... strange behaviour, must be bit scramble due to pcb layot restrictions
|
||||||
// check if it not interfer with other dumps
|
// check if it not interfer with other dumps
|
||||||
@ -151,44 +143,48 @@ static DECLFW(BMCFK23CHiWrite)
|
|||||||
else if((A==0x8000)&&(V==0x47))
|
else if((A==0x8000)&&(V==0x47))
|
||||||
V=0x46;
|
V=0x46;
|
||||||
}
|
}
|
||||||
|
// FCEU_printf("W1:%04X:%02X\n",A,V);
|
||||||
MMC3_CMDWrite(A,V);
|
MMC3_CMDWrite(A,V);
|
||||||
FixMMC3PRG(MMC3_cmd);
|
FixMMC3PRG(MMC3_cmd);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
MMC3_IRQWrite(A,V);
|
MMC3_IRQWrite(A,V);
|
||||||
|
// FCEU_printf("W4:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//EXP handler ($5000-$5FFF)
|
//EXP handler ($5000-$5FFF)
|
||||||
static DECLFW(BMCFK23CWrite)
|
static DECLFW(BMCFK23CWrite)
|
||||||
{
|
{
|
||||||
if(A&(1<<(dipswitch+4)))
|
if(A&(1<<(dipswitch+4))) {
|
||||||
{
|
|
||||||
//printf("+ ");
|
//printf("+ ");
|
||||||
EXPREGS[A&3]=V;
|
EXPREGS[A&3]=V;
|
||||||
|
|
||||||
|
// BUT WHY is there any rom that need it actually?
|
||||||
bool remap = false;
|
bool remap = false;
|
||||||
|
// FCEU_printf("K3:(exp0=%02x)\n",EXPREGS[0]);
|
||||||
|
// FCEU_printf("WH0:%04X:%02X\n",A,V);
|
||||||
|
|
||||||
//sometimes writing to reg0 causes remappings to occur. we think the 2 signifies this.
|
//sometimes writing to reg0 causes remappings to occur. we think the 2 signifies this.
|
||||||
//if not, 0x24 is a value that is known to work
|
//if not, 0x24 is a value that is known to work
|
||||||
//however, the low 4 bits are known to control the mapping mode, so 0x20 is more likely to be the immediate remap flag
|
//however, the low 4 bits are known to control the mapping mode, so 0x20 is more likely to be the immediate remap flag
|
||||||
remap |= ((EXPREGS[0]&0xF0)==0x20);
|
// remap |= ((EXPREGS[0]&0xF0)==0x20);
|
||||||
|
|
||||||
//this is an actual mapping reg. i think reg0 controls what happens when reg1 is written. anyway, we have to immediately remap these
|
//this is an actual mapping reg. i think reg0 controls what happens when reg1 is written. anyway, we have to immediately remap these
|
||||||
remap |= (A&3)==1;
|
// remap |= (A&3)==1;
|
||||||
//this too.
|
//this too.
|
||||||
remap |= (A&3)==2;
|
// remap |= (A&3)==2;
|
||||||
|
|
||||||
if(remap)
|
// if(remap) {
|
||||||
{
|
// FCEU_printf("WH1:%04X:%02X\n",A,V);
|
||||||
FixMMC3PRG(MMC3_cmd);
|
FixMMC3PRG(MMC3_cmd);
|
||||||
FixMMC3CHR(MMC3_cmd);
|
FixMMC3CHR(MMC3_cmd);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_BMCFK23CA)
|
if(is_BMCFK23CA) {
|
||||||
{
|
|
||||||
if(EXPREGS[3]&2)
|
if(EXPREGS[3]&2)
|
||||||
|
// 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)
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,13 +195,15 @@ static DECLFW(BMCFK23CWrite)
|
|||||||
static void BMCFK23CReset(void)
|
static void BMCFK23CReset(void)
|
||||||
{
|
{
|
||||||
//NOT NECESSARY ANYMORE
|
//NOT NECESSARY ANYMORE
|
||||||
|
// BUT WHY?
|
||||||
//this little hack makes sure that we try all the dip switch settings eventually, if we reset enough
|
//this little hack makes sure that we try all the dip switch settings eventually, if we reset enough
|
||||||
// dipswitch++;
|
dipswitch++;
|
||||||
// dipswitch&=7;
|
dipswitch&=7;
|
||||||
//printf("BMCFK23C dipswitch set to %d\n",dipswitch);
|
printf("BMCFK23C dipswitch set to %d\n",dipswitch);
|
||||||
|
|
||||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||||
|
// FCEU_printf("K0:(exp0=%02x)\n",EXPREGS[0]);
|
||||||
MMC3RegReset();
|
MMC3RegReset();
|
||||||
FixMMC3PRG(MMC3_cmd);
|
FixMMC3PRG(MMC3_cmd);
|
||||||
FixMMC3CHR(MMC3_cmd);
|
FixMMC3CHR(MMC3_cmd);
|
||||||
@ -213,15 +211,15 @@ static void BMCFK23CReset(void)
|
|||||||
|
|
||||||
static void BMCFK23CPower(void)
|
static void BMCFK23CPower(void)
|
||||||
{
|
{
|
||||||
dipswitch = 0;
|
|
||||||
GenMMC3Power();
|
GenMMC3Power();
|
||||||
|
dipswitch = 0;
|
||||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||||
GenMMC3Power();
|
// FCEU_printf("K1:(exp0=%02x)\n",EXPREGS[0]);
|
||||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
|
||||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
|
||||||
FixMMC3PRG(MMC3_cmd);
|
FixMMC3PRG(MMC3_cmd);
|
||||||
FixMMC3CHR(MMC3_cmd);
|
FixMMC3CHR(MMC3_cmd);
|
||||||
|
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||||
|
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BMCFK23CAPower(void)
|
static void BMCFK23CAPower(void)
|
||||||
@ -230,10 +228,11 @@ static void BMCFK23CAPower(void)
|
|||||||
dipswitch = 0;
|
dipswitch = 0;
|
||||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
// FCEU_printf("K2:(exp0=%02x)\n",EXPREGS[0]);
|
||||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
|
||||||
FixMMC3PRG(MMC3_cmd);
|
FixMMC3PRG(MMC3_cmd);
|
||||||
FixMMC3CHR(MMC3_cmd);
|
FixMMC3CHR(MMC3_cmd);
|
||||||
|
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||||
|
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BMCFK23CAClose(void)
|
static void BMCFK23CAClose(void)
|
||||||
|
@ -35,6 +35,7 @@ static void MALEEPower(void) {
|
|||||||
|
|
||||||
void MALEE_Init(CartInfo *info) {
|
void MALEE_Init(CartInfo *info) {
|
||||||
info->Power = MALEEPower;
|
info->Power = MALEEPower;
|
||||||
|
FCEU_MemoryRand(WRAM,sizeof(WRAM),true);
|
||||||
SetupCartPRGMapping(0x10, WRAM, 2048, 1);
|
SetupCartPRGMapping(0x10, WRAM, 2048, 1);
|
||||||
AddExState(WRAM, 2048, 0, "WRAM");
|
AddExState(WRAM, 2048, 0, "WRAM");
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,13 @@
|
|||||||
#include "mapinc.h"
|
#include "mapinc.h"
|
||||||
|
|
||||||
static void GenMMC1Power(void);
|
static void GenMMC1Power(void);
|
||||||
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery);
|
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int bram);
|
||||||
|
|
||||||
static uint8 DRegs[4];
|
static uint8 DRegs[4];
|
||||||
static uint8 Buffer, BufferShift;
|
static uint8 Buffer, BufferShift;
|
||||||
|
|
||||||
static int mmc1opts;
|
static uint32 WRAMSIZE;
|
||||||
|
static uint32 NONBRAMSIZE; // size of non-battery-backed portion of WRAM
|
||||||
|
|
||||||
static void (*MMC1CHRHook4)(uint32 A, uint8 V);
|
static void (*MMC1CHRHook4)(uint32 A, uint8 V);
|
||||||
static void (*MMC1PRGHook16)(uint32 A, uint8 V);
|
static void (*MMC1PRGHook16)(uint32 A, uint8 V);
|
||||||
@ -48,9 +49,9 @@ static DECLFR(MAWRAM) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void MMC1CHR(void) {
|
static void MMC1CHR(void) {
|
||||||
if (mmc1opts & 4) {
|
if (WRAMSIZE > 0x2000) {
|
||||||
if (DRegs[0] & 0x10)
|
if (WRAMSIZE > 0x4000)
|
||||||
setprg8r(0x10, 0x6000, (DRegs[1] >> 4) & 1);
|
setprg8r(0x10, 0x6000, (DRegs[1] >> 2) & 3);
|
||||||
else
|
else
|
||||||
setprg8r(0x10, 0x6000, (DRegs[1] >> 3) & 1);
|
setprg8r(0x10, 0x6000, (DRegs[1] >> 3) & 1);
|
||||||
}
|
}
|
||||||
@ -73,37 +74,38 @@ static void MMC1CHR(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void MMC1PRG(void) {
|
static void MMC1PRG(void) {
|
||||||
uint8 offs = DRegs[1] & 0x10;
|
uint8 offs_16banks = DRegs[1] & 0x10;
|
||||||
|
uint8 prg_reg = DRegs[3] & 0xF; //homebrewers arent allowed to use more banks on MMC1. use another mapper.
|
||||||
if (MMC1PRGHook16) {
|
if (MMC1PRGHook16) {
|
||||||
switch (DRegs[0] & 0xC) {
|
switch (DRegs[0] & 0xC) {
|
||||||
case 0xC:
|
case 0xC:
|
||||||
MMC1PRGHook16(0x8000, (DRegs[3] + offs));
|
MMC1PRGHook16(0x8000, (prg_reg + offs_16banks));
|
||||||
MMC1PRGHook16(0xC000, 0xF + offs);
|
MMC1PRGHook16(0xC000, 0xF + offs_16banks);
|
||||||
break;
|
break;
|
||||||
case 0x8:
|
case 0x8:
|
||||||
MMC1PRGHook16(0xC000, (DRegs[3] + offs));
|
MMC1PRGHook16(0xC000, (prg_reg + offs_16banks));
|
||||||
MMC1PRGHook16(0x8000, offs);
|
MMC1PRGHook16(0x8000, offs_16banks);
|
||||||
break;
|
break;
|
||||||
case 0x0:
|
case 0x0:
|
||||||
case 0x4:
|
case 0x4:
|
||||||
MMC1PRGHook16(0x8000, ((DRegs[3] & ~1) + offs));
|
MMC1PRGHook16(0x8000, ((prg_reg & ~1) + offs_16banks));
|
||||||
MMC1PRGHook16(0xc000, ((DRegs[3] & ~1) + offs + 1));
|
MMC1PRGHook16(0xc000, ((prg_reg & ~1) + offs_16banks + 1));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (DRegs[0] & 0xC) {
|
switch (DRegs[0] & 0xC) {
|
||||||
case 0xC:
|
case 0xC:
|
||||||
setprg16(0x8000, (DRegs[3] + offs));
|
setprg16(0x8000, (prg_reg + offs_16banks));
|
||||||
setprg16(0xC000, 0xF + offs);
|
setprg16(0xC000, 0xF + offs_16banks);
|
||||||
break;
|
break;
|
||||||
case 0x8:
|
case 0x8:
|
||||||
setprg16(0xC000, (DRegs[3] + offs));
|
setprg16(0xC000, (prg_reg + offs_16banks));
|
||||||
setprg16(0x8000, offs);
|
setprg16(0x8000, offs_16banks);
|
||||||
break;
|
break;
|
||||||
case 0x0:
|
case 0x0:
|
||||||
case 0x4:
|
case 0x4:
|
||||||
setprg16(0x8000, ((DRegs[3] & ~1) + offs));
|
setprg16(0x8000, ((prg_reg & ~1) + offs_16banks));
|
||||||
setprg16(0xc000, ((DRegs[3] & ~1) + offs + 1));
|
setprg16(0xc000, ((prg_reg & ~1) + offs_16banks + 1));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,21 +180,40 @@ static void MMC1CMReset(void) {
|
|||||||
MMC1PRG();
|
MMC1PRG();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DetectMMC1WRAMSize(uint32 crc32) {
|
static int DetectMMC1WRAMSize(CartInfo *info, int *bs) {
|
||||||
switch (crc32) {
|
int ws = 8;
|
||||||
|
switch (info->CRC32) {
|
||||||
case 0xc6182024: // Romance of the 3 Kingdoms
|
case 0xc6182024: // Romance of the 3 Kingdoms
|
||||||
|
case 0xabbf7217: // "" "" (J) (PRG0)
|
||||||
|
case 0xccf35c02: // "" "" (J) (PRG1)
|
||||||
case 0x2225c20f: // Genghis Khan
|
case 0x2225c20f: // Genghis Khan
|
||||||
|
case 0xfb69743a: // "" "" (J)
|
||||||
case 0x4642dda6: // Nobunaga's Ambition
|
case 0x4642dda6: // Nobunaga's Ambition
|
||||||
case 0x29449ba9: // "" "" (J)
|
case 0x3f7ad415: // "" "" (J) (PRG0)
|
||||||
case 0x2b11e0b0: // "" "" (J)
|
case 0x2b11e0b0: // "" "" (J) (PRG1)
|
||||||
case 0xb8747abf: // Best Play Pro Yakyuu Special (J)
|
*bs = 8;
|
||||||
case 0xc9556b36: // Final Fantasy I & II (J) [!]
|
ws = 16;
|
||||||
FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n");
|
|
||||||
return(16);
|
|
||||||
break;
|
break;
|
||||||
default: return(8);
|
case 0xb8747abf: // Best Play Pro Yakyuu Special (J) (PRG0)
|
||||||
|
case 0xc3de7c69: // "" "" (J) (PRG1)
|
||||||
|
case 0xc9556b36: // Final Fantasy I & II (J) [!]
|
||||||
|
*bs = 32;
|
||||||
|
ws = 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if(info->ines2) {
|
||||||
|
ws = (info->wram_size + info->battery_wram_size) / 1024;
|
||||||
|
*bs = info->battery_wram_size / 1024;
|
||||||
|
// we only support sizes between 8K and 32K
|
||||||
|
if (ws > 0 && ws < 8) ws = 8;
|
||||||
|
if (ws > 32) ws = 32;
|
||||||
|
if (*bs > ws) *bs = ws;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ws > 8)
|
||||||
|
FCEU_printf(" >8KB external WRAM present. Use NES 2.0 if you hack the ROM image.\n");
|
||||||
|
return ws;
|
||||||
|
}
|
||||||
|
|
||||||
static uint32 NWCIRQCount;
|
static uint32 NWCIRQCount;
|
||||||
static uint8 NWCRec;
|
static uint8 NWCRec;
|
||||||
@ -243,17 +264,16 @@ void Mapper105_Init(CartInfo *info) {
|
|||||||
|
|
||||||
static void GenMMC1Power(void) {
|
static void GenMMC1Power(void) {
|
||||||
lreset = 0;
|
lreset = 0;
|
||||||
if (mmc1opts & 1) {
|
|
||||||
FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
|
||||||
if (mmc1opts & 4)
|
|
||||||
FCEU_dwmemset(WRAM, 0, 8192)
|
|
||||||
else if (!(mmc1opts & 2))
|
|
||||||
FCEU_dwmemset(WRAM, 0, 8192); // wtf?
|
|
||||||
}
|
|
||||||
SetWriteHandler(0x8000, 0xFFFF, MMC1_write);
|
SetWriteHandler(0x8000, 0xFFFF, MMC1_write);
|
||||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||||
|
|
||||||
if (mmc1opts & 1) {
|
if (WRAMSIZE) {
|
||||||
|
FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
||||||
|
|
||||||
|
// clear non-battery-backed portion of WRAM
|
||||||
|
if (NONBRAMSIZE)
|
||||||
|
FCEU_MemoryRand(WRAM, NONBRAMSIZE, true);
|
||||||
|
|
||||||
SetReadHandler(0x6000, 0x7FFF, MAWRAM);
|
SetReadHandler(0x6000, 0x7FFF, MAWRAM);
|
||||||
SetWriteHandler(0x6000, 0x7FFF, MBWRAM);
|
SetWriteHandler(0x6000, 0x7FFF, MBWRAM);
|
||||||
setprg8r(0x10, 0x6000, 0);
|
setprg8r(0x10, 0x6000, 0);
|
||||||
@ -270,31 +290,24 @@ static void GenMMC1Close(void) {
|
|||||||
CHRRAM = WRAM = NULL;
|
CHRRAM = WRAM = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery) {
|
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int bram) {
|
||||||
is155 = 0;
|
is155 = 0;
|
||||||
|
|
||||||
info->Close = GenMMC1Close;
|
info->Close = GenMMC1Close;
|
||||||
MMC1PRGHook16 = MMC1CHRHook4 = 0;
|
MMC1PRGHook16 = MMC1CHRHook4 = 0;
|
||||||
mmc1opts = 0;
|
WRAMSIZE = wram * 1024;
|
||||||
|
NONBRAMSIZE = (wram - bram) * 1024;
|
||||||
PRGmask16[0] &= (prg >> 14) - 1;
|
PRGmask16[0] &= (prg >> 14) - 1;
|
||||||
CHRmask4[0] &= (chr >> 12) - 1;
|
CHRmask4[0] &= (chr >> 12) - 1;
|
||||||
CHRmask8[0] &= (chr >> 13) - 1;
|
CHRmask8[0] &= (chr >> 13) - 1;
|
||||||
|
|
||||||
if (wram) {
|
if (WRAMSIZE) {
|
||||||
WRAM = (uint8*)FCEU_gmalloc(wram * 1024);
|
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||||
//mbg 17-jun-08 - this shouldve been cleared to re-initialize save ram
|
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||||
//ch4 10-dec-08 - nope, this souldn't
|
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||||
//mbg 29-mar-09 - no time to debate this, we need to keep from breaking some old stuff.
|
if (bram) {
|
||||||
//we really need to make up a policy for how compatibility and accuracy can be resolved.
|
info->SaveGame[0] = WRAM + NONBRAMSIZE;
|
||||||
memset(WRAM, 0, wram * 1024);
|
info->SaveGameLen[0] = bram * 1024;
|
||||||
mmc1opts |= 1;
|
|
||||||
if (wram > 8) mmc1opts |= 4;
|
|
||||||
SetupCartPRGMapping(0x10, WRAM, wram * 1024, 1);
|
|
||||||
AddExState(WRAM, wram * 1024, 0, "WRAM");
|
|
||||||
if (battery) {
|
|
||||||
mmc1opts |= 2;
|
|
||||||
info->SaveGame[0] = WRAM + ((mmc1opts & 4) ? 8192 : 0);
|
|
||||||
info->SaveGameLen[0] = 8192;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!chr) {
|
if (!chr) {
|
||||||
@ -312,13 +325,14 @@ static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Mapper1_Init(CartInfo *info) {
|
void Mapper1_Init(CartInfo *info) {
|
||||||
int ws = DetectMMC1WRAMSize(info->CRC32);
|
int bs = info->battery ? 8 : 0;
|
||||||
GenMMC1Init(info, 512, 256, ws, info->battery);
|
int ws = DetectMMC1WRAMSize(info, &bs);
|
||||||
|
GenMMC1Init(info, 512, 256, ws, bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Same as mapper 1, without respect for WRAM enable bit. */
|
/* Same as mapper 1, without respect for WRAM enable bit. */
|
||||||
void Mapper155_Init(CartInfo *info) {
|
void Mapper155_Init(CartInfo *info) {
|
||||||
GenMMC1Init(info, 512, 256, 8, info->battery);
|
GenMMC1Init(info, 512, 256, 8, info->battery ? 8 : 0);
|
||||||
is155 = 1;
|
is155 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,7 +344,7 @@ void Mapper171_Init(CartInfo *info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SAROM_Init(CartInfo *info) {
|
void SAROM_Init(CartInfo *info) {
|
||||||
GenMMC1Init(info, 128, 64, 8, info->battery);
|
GenMMC1Init(info, 128, 64, 8, info->battery ? 8 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SBROM_Init(CartInfo *info) {
|
void SBROM_Init(CartInfo *info) {
|
||||||
@ -350,7 +364,7 @@ void SGROM_Init(CartInfo *info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SKROM_Init(CartInfo *info) {
|
void SKROM_Init(CartInfo *info) {
|
||||||
GenMMC1Init(info, 256, 64, 8, info->battery);
|
GenMMC1Init(info, 256, 64, 8, info->battery ? 8 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SLROM_Init(CartInfo *info) {
|
void SLROM_Init(CartInfo *info) {
|
||||||
@ -382,11 +396,9 @@ void SHROM_Init(CartInfo *info) {
|
|||||||
/* */
|
/* */
|
||||||
|
|
||||||
void SNROM_Init(CartInfo *info) {
|
void SNROM_Init(CartInfo *info) {
|
||||||
GenMMC1Init(info, 256, 0, 8, info->battery);
|
GenMMC1Init(info, 256, 0, 8, info->battery ? 8 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SOROM_Init(CartInfo *info) {
|
void SOROM_Init(CartInfo *info) {
|
||||||
GenMMC1Init(info, 256, 0, 16, info->battery);
|
GenMMC1Init(info, 256, 0, 16, info->battery ? 8 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -279,11 +279,11 @@ void GenMMC3Power(void) {
|
|||||||
setprg8r(0x10, 0x6000, 0);
|
setprg8r(0x10, 0x6000, 0);
|
||||||
}
|
}
|
||||||
if (!(mmc3opts & 2))
|
if (!(mmc3opts & 2))
|
||||||
FCEU_dwmemset(WRAM, 0, WRAMSIZE);
|
FCEU_MemoryRand(WRAM, WRAMSIZE, true);
|
||||||
}
|
}
|
||||||
MMC3RegReset();
|
MMC3RegReset();
|
||||||
if (CHRRAM)
|
if (CHRRAM)
|
||||||
FCEU_dwmemset(CHRRAM, 0, CHRRAMSIZE);
|
FCEU_MemoryRand(CHRRAM, CHRRAMSIZE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GenMMC3Close(void) {
|
static void GenMMC3Close(void) {
|
||||||
@ -498,13 +498,18 @@ static void M45CW(uint32 A, uint8 V) {
|
|||||||
NV &= 0; // hack ;( don't know exactly how it should be
|
NV &= 0; // hack ;( don't know exactly how it should be
|
||||||
NV |= EXPREGS[0] | ((EXPREGS[2] & 0xF0) << 4);
|
NV |= EXPREGS[0] | ((EXPREGS[2] & 0xF0) << 4);
|
||||||
setchr1(A, NV);
|
setchr1(A, NV);
|
||||||
}
|
} else
|
||||||
|
// setchr8(0); // i don't know what cart need this, but a new one need other lol
|
||||||
|
setchr1(A, V);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void M45PW(uint32 A, uint8 V) {
|
static void M45PW(uint32 A, uint8 V) {
|
||||||
V &= (EXPREGS[3] & 0x3F) ^ 0x3F;
|
uint32 MV = V & ((EXPREGS[3] & 0x3F) ^ 0x3F);
|
||||||
V |= EXPREGS[1];
|
MV |= EXPREGS[1];
|
||||||
setprg8(A, V);
|
if(UNIFchrrama)
|
||||||
|
MV |= ((EXPREGS[2] & 0x40) << 2);
|
||||||
|
setprg8(A, MV);
|
||||||
|
// FCEU_printf("1:%02x 2:%02x 3:%02x A=%04x V=%03x\n",EXPREGS[1],EXPREGS[2],EXPREGS[3],A,MV);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DECLFW(M45Write) {
|
static DECLFW(M45Write) {
|
||||||
@ -534,7 +539,6 @@ static void M45Reset(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void M45Power(void) {
|
static void M45Power(void) {
|
||||||
setchr8(0);
|
|
||||||
GenMMC3Power();
|
GenMMC3Power();
|
||||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = EXPREGS[4] = EXPREGS[5] = 0;
|
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = EXPREGS[4] = EXPREGS[5] = 0;
|
||||||
SetWriteHandler(0x5000, 0x7FFF, M45Write);
|
SetWriteHandler(0x5000, 0x7FFF, M45Write);
|
||||||
@ -1039,8 +1043,8 @@ static DECLFW(Mapper196Write) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static DECLFW(Mapper196WriteLo) {
|
static DECLFW(Mapper196WriteLo) {
|
||||||
EXPREGS[0] = 1;
|
EXPREGS[0] = 1; // hacky
|
||||||
EXPREGS[1] = (V & 0xf) | (V >> 4);
|
EXPREGS[1] = (V & 0xf) | (V >> 4); // this is the same as 189 mapper, but with addr permutations
|
||||||
FixMMC3PRG(MMC3_cmd);
|
FixMMC3PRG(MMC3_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,13 @@
|
|||||||
|
|
||||||
#include "mapinc.h"
|
#include "mapinc.h"
|
||||||
|
|
||||||
|
#define ABANKS MMC5SPRVPage
|
||||||
|
#define BBANKS MMC5BGVPage
|
||||||
|
#define SpriteON (PPU[1] & 0x10) //Show Sprite
|
||||||
|
#define ScreenON (PPU[1] & 0x08) //Show screen
|
||||||
|
#define PPUON (PPU[1] & 0x18) //PPU should operate
|
||||||
|
#define Sprite16 (PPU[0] & 0x20) //Sprites 8x16/8x8
|
||||||
|
|
||||||
static void (*sfun)(int P);
|
static void (*sfun)(int P);
|
||||||
static void (*psfun)(void);
|
static void (*psfun)(void);
|
||||||
|
|
||||||
@ -107,15 +114,33 @@ typedef struct __cartdata {
|
|||||||
uint8 size;
|
uint8 size;
|
||||||
} cartdata;
|
} cartdata;
|
||||||
|
|
||||||
#define Sprite16 (PPU[0]& 0x20) //Sprites 8x16/8x8
|
#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)]
|
||||||
//#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V)>>10][(V)]
|
|
||||||
static inline uint8 * MMC5BGVRAMADR(uint32 A) {
|
uint8* MMC5BGVRAMADR(uint32 A)
|
||||||
|
{
|
||||||
|
if(newppu)
|
||||||
|
{
|
||||||
|
if(Sprite16)
|
||||||
|
{
|
||||||
|
bool isPattern = PPUON != 0;
|
||||||
|
if (ppuphase == PPUPHASE_OBJ && isPattern)
|
||||||
|
return &ABANKS[(A) >> 10][(A)];
|
||||||
|
if (ppuphase == PPUPHASE_BG && isPattern)
|
||||||
|
return &BBANKS[(A) >> 10][(A)];
|
||||||
|
else if(mmc5ABMode == 0)
|
||||||
|
return &ABANKS[(A) >> 10][(A)];
|
||||||
|
else
|
||||||
|
return &BBANKS[(A) >> 10][(A)];
|
||||||
|
}
|
||||||
|
else return &ABANKS[(A) >> 10][(A)];;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Sprite16) {
|
if (!Sprite16) {
|
||||||
if (mmc5ABMode == 0)
|
if (mmc5ABMode == 0)
|
||||||
return &MMC5SPRVPage[(A) >> 10][(A)];
|
return &ABANKS[(A) >> 10][(A)];
|
||||||
else
|
else
|
||||||
return &MMC5BGVPage[(A) >> 10][(A)];
|
return &BBANKS[(A) >> 10][(A)];
|
||||||
} else return &MMC5BGVPage[(A) >> 10][(A)];
|
} else return &BBANKS[(A) >> 10][(A)];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mmc5_PPUWrite(uint32 A, uint8 V) {
|
static void mmc5_PPUWrite(uint32 A, uint8 V) {
|
||||||
@ -136,16 +161,105 @@ static void mmc5_PPUWrite(uint32 A, uint8 V) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 FASTCALL mmc5_PPURead(uint32 A) {
|
extern uint32 NTRefreshAddr;
|
||||||
if (A < 0x2000) {
|
uint8 FASTCALL mmc5_PPURead(uint32 A)
|
||||||
if (ppuphase == PPUPHASE_BG
|
{
|
||||||
//zero 03-aug-2014 - added this to fix Uchuu Keibitai SDF. The game reads NT entries from CHR rom while PPU is disabled.
|
bool split = false;
|
||||||
//obviously we have enormous numbers of bugs springing from our terrible emulation of ppu-disabled states, but this does the job for fixing this one
|
if(newppu)
|
||||||
&& (PPU[1] & 0x10)
|
{
|
||||||
)
|
if((MMC5HackSPMode&0x80) && !(MMC5HackCHRMode&2))
|
||||||
return *MMC5BGVRAMADR(A);
|
{
|
||||||
else return MMC5SPRVPage[(A) >> 10][(A)];
|
int target = MMC5HackSPMode&0x1f;
|
||||||
} else {
|
int side = MMC5HackSPMode&0x40;
|
||||||
|
int ht = NTRefreshAddr&31;
|
||||||
|
|
||||||
|
if(side==0)
|
||||||
|
{
|
||||||
|
if(ht<target) split = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(ht>=target) split = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (A < 0x2000)
|
||||||
|
{
|
||||||
|
if(Sprite16)
|
||||||
|
{
|
||||||
|
bool isPattern = !!PPUON;
|
||||||
|
if (ppuphase == PPUPHASE_OBJ && isPattern)
|
||||||
|
return ABANKS[(A) >> 10][(A)];
|
||||||
|
if (ppuphase == PPUPHASE_BG && isPattern)
|
||||||
|
{
|
||||||
|
if(split)
|
||||||
|
return MMC5HackVROMPTR[MMC5HackSPPage*0x1000 + (A&0xFFF)];
|
||||||
|
|
||||||
|
//uhhh call through to this more sophisticated function, only if it's really needed?
|
||||||
|
//we should probably reuse it completely, if we can
|
||||||
|
if (MMC5HackCHRMode == 1)
|
||||||
|
return *FCEUPPU_GetCHR(A,NTRefreshAddr);
|
||||||
|
|
||||||
|
return BBANKS[(A) >> 10][(A)];
|
||||||
|
}
|
||||||
|
else if(mmc5ABMode == 0)
|
||||||
|
return ABANKS[(A) >> 10][(A)];
|
||||||
|
else
|
||||||
|
return BBANKS[(A) >> 10][(A)];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ppuphase == PPUPHASE_BG && ScreenON)
|
||||||
|
{
|
||||||
|
if(split)
|
||||||
|
return MMC5HackVROMPTR[MMC5HackSPPage*0x1000 + (A&0xFFF)];
|
||||||
|
|
||||||
|
//uhhh call through to this more sophisticated function, only if it's really needed?
|
||||||
|
//we should probably reuse it completely, if we can
|
||||||
|
if (MMC5HackCHRMode == 1)
|
||||||
|
return *FCEUPPU_GetCHR(A,NTRefreshAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ABANKS[(A) >> 10][(A)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(split)
|
||||||
|
{
|
||||||
|
static const int kHack = -1; //dunno if theres science to this or if it just fixes SDF (cant be bothered to think about it)
|
||||||
|
int linetile = (newppu_get_scanline()+kHack)/8 + MMC5HackSPScroll;
|
||||||
|
|
||||||
|
//REF NT: return 0x2000 | (v << 0xB) | (h << 0xA) | (vt << 5) | ht;
|
||||||
|
//REF AT: return 0x2000 | (v << 0xB) | (h << 0xA) | 0x3C0 | ((vt & 0x1C) << 1) | ((ht & 0x1C) >> 2);
|
||||||
|
|
||||||
|
if((A&0x3FF)>=0x3C0)
|
||||||
|
{
|
||||||
|
A &= ~(0x1C<<1); //mask off VT
|
||||||
|
A |= (linetile&0x1C)<<1; //mask on adjusted VT
|
||||||
|
return ExRAM[A & 0x3FF];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
A &= ~((0x1F<<5) | (1<<0xB)); //mask off VT and V
|
||||||
|
A |= (linetile&31)<<5; //mask on adjusted VT (V doesnt make any sense, I think)
|
||||||
|
return ExRAM[A & 0x3FF];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MMC5HackCHRMode == 1)
|
||||||
|
{
|
||||||
|
if((A&0x3FF)>=0x3C0)
|
||||||
|
{
|
||||||
|
uint8 byte = ExRAM[NTRefreshAddr & 0x3ff];
|
||||||
|
//get attribute part and paste it 4x across the byte
|
||||||
|
byte >>= 6;
|
||||||
|
byte *= 0x55;
|
||||||
|
return byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return vnapage[(A >> 10) & 0x3][A & 0x3FF];
|
return vnapage[(A >> 10) & 0x3][A & 0x3FF];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -844,6 +958,12 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
|
|||||||
MMC5fill = (uint8*)FCEU_gmalloc(1024);
|
MMC5fill = (uint8*)FCEU_gmalloc(1024);
|
||||||
ExRAM = (uint8*)FCEU_gmalloc(1024);
|
ExRAM = (uint8*)FCEU_gmalloc(1024);
|
||||||
|
|
||||||
|
// MMC5fill is and 8-bit tile index, and a 2-bit attribute implented as a mirrored nametable
|
||||||
|
u8 nval = MMC5fill[0x000];
|
||||||
|
u8 aval = MMC5fill[0x3C0] & 3; aval = aval | (aval << 2) | (aval << 4) | (aval << 6);
|
||||||
|
FCEU_dwmemset(MMC5fill + 0x000, nval | (nval<<8) | (nval<<16) | (nval<<24), 0x3C0);
|
||||||
|
FCEU_dwmemset(MMC5fill + 0x3C0, aval | (aval<<8) | (aval<<16) | (aval<<24), 0x040);
|
||||||
|
|
||||||
AddExState(ExRAM, 1024, 0, "ERAM");
|
AddExState(ExRAM, 1024, 0, "ERAM");
|
||||||
AddExState(&MMC5HackSPMode, 1, 0, "SPLM");
|
AddExState(&MMC5HackSPMode, 1, 0, "SPLM");
|
||||||
AddExState(&MMC5HackSPScroll, 1, 0, "SPLS");
|
AddExState(&MMC5HackSPScroll, 1, 0, "SPLS");
|
||||||
@ -858,8 +978,13 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
|
|||||||
|
|
||||||
if (battery) {
|
if (battery) {
|
||||||
info->SaveGame[0] = WRAM;
|
info->SaveGame[0] = WRAM;
|
||||||
|
|
||||||
|
//this is more complex than it looks because it MUST BE, I guess. is there an assumption that only 8KB of 16KB is battery backed? That's NES mappers for you
|
||||||
|
//I added 64KB for the new 64KB homebrews
|
||||||
if (wsize <= 16)
|
if (wsize <= 16)
|
||||||
info->SaveGameLen[0] = 8192;
|
info->SaveGameLen[0] = 8192;
|
||||||
|
else if(wsize == 64)
|
||||||
|
info->SaveGameLen[0] = 64*1024;
|
||||||
else
|
else
|
||||||
info->SaveGameLen[0] = 32768;
|
info->SaveGameLen[0] = 32768;
|
||||||
}
|
}
|
||||||
|
@ -57,9 +57,23 @@ static SFORMAT N106_StateRegs[] = {
|
|||||||
{ PRG, 3, "PRG" },
|
{ PRG, 3, "PRG" },
|
||||||
{ CHR, 8, "CHR" },
|
{ CHR, 8, "CHR" },
|
||||||
{ NTAPage, 4, "NTA" },
|
{ NTAPage, 4, "NTA" },
|
||||||
|
{ &gorfus, 1, "GORF" },
|
||||||
|
{ &dopol, 1, "DOPO" },
|
||||||
|
{ &gorko, 1, "GORK" },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void SyncMirror()
|
||||||
|
{
|
||||||
|
switch(gorko) {
|
||||||
|
case 0: setmirror(MI_0); break;
|
||||||
|
case 1: setmirror(MI_V); break;
|
||||||
|
case 2: setmirror(MI_H); break;
|
||||||
|
case 3: setmirror(MI_0); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void SyncPRG(void) {
|
static void SyncPRG(void) {
|
||||||
setprg8(0x8000, PRG[0]);
|
setprg8(0x8000, PRG[0]);
|
||||||
setprg8(0xa000, PRG[1]);
|
setprg8(0xa000, PRG[1]);
|
||||||
@ -179,8 +193,11 @@ static DECLFW(Mapper19_write) {
|
|||||||
X6502_IRQEnd(FCEU_IQEXT);
|
X6502_IRQEnd(FCEU_IQEXT);
|
||||||
break;
|
break;
|
||||||
case 0xE000:
|
case 0xE000:
|
||||||
gorko = V & 0xC0;
|
|
||||||
PRG[0] = V & 0x3F;
|
PRG[0] = V & 0x3F;
|
||||||
|
if(is210) {
|
||||||
|
gorko = V>>6;
|
||||||
|
SyncMirror();
|
||||||
|
}
|
||||||
SyncPRG();
|
SyncPRG();
|
||||||
break;
|
break;
|
||||||
case 0xE800:
|
case 0xE800:
|
||||||
@ -333,6 +350,7 @@ static void Mapper19_StateRestore(int version) {
|
|||||||
SyncPRG();
|
SyncPRG();
|
||||||
FixNTAR();
|
FixNTAR();
|
||||||
FixCRR();
|
FixCRR();
|
||||||
|
SyncMirror();
|
||||||
int x;
|
int x;
|
||||||
for (x = 0x40; x < 0x80; x++)
|
for (x = 0x40; x < 0x80; x++)
|
||||||
FixCache(x, IRAM[x]);
|
FixCache(x, IRAM[x]);
|
||||||
@ -382,8 +400,8 @@ static void N106_Power(void) {
|
|||||||
FixCRR();
|
FixCRR();
|
||||||
|
|
||||||
if (!battery) {
|
if (!battery) {
|
||||||
FCEU_dwmemset(WRAM, 0, 8192);
|
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
|
||||||
FCEU_dwmemset(IRAM, 0, 128);
|
FCEU_MemoryRand(IRAM, sizeof(IRAM), true);
|
||||||
}
|
}
|
||||||
for (x = 0x40; x < 0x80; x++)
|
for (x = 0x40; x < 0x80; x++)
|
||||||
FixCache(x, IRAM[x]);
|
FixCache(x, IRAM[x]);
|
||||||
@ -401,6 +419,8 @@ void Mapper19_Init(CartInfo *info) {
|
|||||||
if (FSettings.SndRate)
|
if (FSettings.SndRate)
|
||||||
Mapper19_ESI();
|
Mapper19_ESI();
|
||||||
|
|
||||||
|
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
|
||||||
|
FCEU_MemoryRand(IRAM, sizeof(IRAM), true);
|
||||||
AddExState(WRAM, 8192, 0, "WRAM");
|
AddExState(WRAM, 8192, 0, "WRAM");
|
||||||
AddExState(IRAM, 128, 0, "IRAM");
|
AddExState(IRAM, 128, 0, "IRAM");
|
||||||
AddExState(N106_StateRegs, ~0, 0, 0);
|
AddExState(N106_StateRegs, ~0, 0, 0);
|
||||||
@ -422,6 +442,7 @@ void Mapper210_Init(CartInfo *info) {
|
|||||||
is210 = 1;
|
is210 = 1;
|
||||||
GameStateRestore = Mapper210_StateRestore;
|
GameStateRestore = Mapper210_StateRestore;
|
||||||
info->Power = N106_Power;
|
info->Power = N106_Power;
|
||||||
|
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
|
||||||
AddExState(WRAM, 8192, 0, "WRAM");
|
AddExState(WRAM, 8192, 0, "WRAM");
|
||||||
AddExState(N106_StateRegs, ~0, 0, 0);
|
AddExState(N106_StateRegs, ~0, 0, 0);
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ static void CSync(void) {
|
|||||||
setchr1(0x1800 ^ cswap, block | (bank6 & mask));
|
setchr1(0x1800 ^ cswap, block | (bank6 & mask));
|
||||||
setchr1(0x1c00 ^ cswap, block | (bank7 & mask));
|
setchr1(0x1c00 ^ cswap, block | (bank7 & mask));
|
||||||
|
|
||||||
setmirror(mirror & 1);
|
setmirror((mirror ^ 1) & 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Sync(void) {
|
static void Sync(void) {
|
||||||
@ -158,7 +158,7 @@ static DECLFW(UNLOneBusWriteMMC3) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xa000: mirror = V ^ 1; CSync(); break;
|
case 0xa000: mirror = V; CSync(); break;
|
||||||
case 0xc000: IRQLatch = V & 0xfe; break;
|
case 0xc000: IRQLatch = V & 0xfe; break;
|
||||||
case 0xc001: IRQReload = 1; break;
|
case 0xc001: IRQReload = 1; break;
|
||||||
case 0xe000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break;
|
case 0xe000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break;
|
||||||
|
@ -197,7 +197,7 @@ static void UNROM512LSync() {
|
|||||||
}
|
}
|
||||||
else if (latche==0x10)
|
else if (latche==0x10)
|
||||||
{
|
{
|
||||||
for(int i=0;i<(ROM_size*4);i++)
|
for(uint32 i=0;i<(ROM_size*4);i++)
|
||||||
inc_flash_write_count(i>>2,i<<12);
|
inc_flash_write_count(i>>2,i<<12);
|
||||||
memset(flashdata,0xFF,ROM_size*0x4000); //Erasing the rom chip as instructed. Crash rate calulated to be 99.9% :)
|
memset(flashdata,0xFF,ROM_size*0x4000); //Erasing the rom chip as instructed. Crash rate calulated to be 99.9% :)
|
||||||
}
|
}
|
||||||
@ -241,7 +241,23 @@ void UNROM512_Init(CartInfo *info) {
|
|||||||
else
|
else
|
||||||
chrram_mask = 0x60;
|
chrram_mask = 0x60;
|
||||||
|
|
||||||
SetupCartMirroring(info->mirror,(info->mirror>=MI_0)?0:1,0);
|
int mirror = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2);
|
||||||
|
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;
|
bus_conflict = !info->battery;
|
||||||
latcheinit = 0;
|
latcheinit = 0;
|
||||||
WLSync = UNROM512LSync;
|
WLSync = UNROM512LSync;
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
|
|
||||||
#include "mapinc.h"
|
#include "mapinc.h"
|
||||||
|
|
||||||
static uint8 isPirate, is22;
|
static bool isPirate;
|
||||||
|
static uint8 is22, reg1mask, reg2mask;
|
||||||
static uint16 IRQCount;
|
static uint16 IRQCount;
|
||||||
static uint8 IRQLatch, IRQa;
|
static uint8 IRQLatch, IRQa;
|
||||||
static uint8 prgreg[2], chrreg[8];
|
static uint8 prgreg[2], chrreg[8];
|
||||||
@ -61,15 +62,15 @@ static void Sync(void) {
|
|||||||
setchr8(0);
|
setchr8(0);
|
||||||
else{
|
else{
|
||||||
uint8 i;
|
uint8 i;
|
||||||
if(!weirdo)
|
//if(!weirdo)
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
setchr1(i << 10, (chrhi[i] | chrreg[i]) >> is22);
|
setchr1(i << 10, (chrhi[i] | chrreg[i]) >> is22);
|
||||||
else {
|
//else {
|
||||||
setchr1(0x0000, 0xFC);
|
// setchr1(0x0000, 0xFC);
|
||||||
setchr1(0x0400, 0xFD);
|
// setchr1(0x0400, 0xFD);
|
||||||
setchr1(0x0800, 0xFF);
|
// setchr1(0x0800, 0xFF);
|
||||||
weirdo--;
|
// weirdo--;
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
switch (mirr & 0x3) {
|
switch (mirr & 0x3) {
|
||||||
case 0: setmirror(MI_V); break;
|
case 0: setmirror(MI_V); break;
|
||||||
@ -80,7 +81,7 @@ static void Sync(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static DECLFW(VRC24Write) {
|
static DECLFW(VRC24Write) {
|
||||||
A &= 0xF003;
|
A = A & 0xF000 | !!(A & reg2mask) << 1 | !!(A & reg1mask);
|
||||||
if ((A >= 0xB000) && (A <= 0xE003)) {
|
if ((A >= 0xB000) && (A <= 0xE003)) {
|
||||||
if (UNIFchrrama)
|
if (UNIFchrrama)
|
||||||
big_bank = (V & 8) << 2; // my personally many-in-one feature ;) just for support pirate cart 2-in-1
|
big_bank = (V & 8) << 2; // my personally many-in-one feature ;) just for support pirate cart 2-in-1
|
||||||
@ -126,62 +127,18 @@ static DECLFW(VRC24Write) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static DECLFW(M21Write) {
|
static void VRC24Power(void) {
|
||||||
A = (A & 0xF000) | ((A >> 1) & 0x3); // Ganbare Goemon Gaiden 2 - Tenka no Zaihou (J) [!] isn't mapper 21 actually,
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
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;
|
big_bank = 0x20;
|
||||||
Sync();
|
Sync();
|
||||||
|
if (WRAM) {
|
||||||
setprg8r(0x10, 0x6000, 0);
|
setprg8r(0x10, 0x6000, 0);
|
||||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
|
||||||
SetWriteHandler(0x8000, 0xFFFF, M22Write);
|
|
||||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||||
}
|
}
|
||||||
|
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||||
|
SetWriteHandler(0x8000, 0xFFFF, VRC24Write);
|
||||||
|
}
|
||||||
|
|
||||||
void VRC24IRQHook(int a) {
|
void VRC24IRQHook(int a) {
|
||||||
#define LCYCS 341
|
#define LCYCS 341
|
||||||
@ -210,26 +167,8 @@ static void VRC24Close(void) {
|
|||||||
WRAM = NULL;
|
WRAM = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mapper21_Init(CartInfo *info) {
|
static void VRC24_Init(CartInfo *info) {
|
||||||
isPirate = 0;
|
info->Power = VRC24Power;
|
||||||
is22 = 0;
|
|
||||||
info->Power = M21Power;
|
|
||||||
MapIRQHook = VRC24IRQHook;
|
|
||||||
GameStateRestore = StateRestore;
|
|
||||||
|
|
||||||
AddExState(&StateRegs, ~0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mapper22_Init(CartInfo *info) {
|
|
||||||
isPirate = 0;
|
|
||||||
is22 = 1;
|
|
||||||
info->Power = M22Power;
|
|
||||||
GameStateRestore = StateRestore;
|
|
||||||
|
|
||||||
AddExState(&StateRegs, ~0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VRC24_Init(CartInfo *info) {
|
|
||||||
info->Close = VRC24Close;
|
info->Close = VRC24Close;
|
||||||
MapIRQHook = VRC24IRQHook;
|
MapIRQHook = VRC24IRQHook;
|
||||||
GameStateRestore = StateRestore;
|
GameStateRestore = StateRestore;
|
||||||
@ -247,23 +186,48 @@ void VRC24_Init(CartInfo *info) {
|
|||||||
AddExState(&StateRegs, ~0, 0, 0);
|
AddExState(&StateRegs, ~0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mapper23_Init(CartInfo *info) {
|
void Mapper21_Init(CartInfo *info) {
|
||||||
isPirate = 0;
|
isPirate = false;
|
||||||
is22 = 0;
|
is22 = 0;
|
||||||
info->Power = M23Power;
|
reg1mask = 0x42;
|
||||||
|
reg2mask = 0x84;
|
||||||
|
VRC24_Init(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mapper22_Init(CartInfo *info) {
|
||||||
|
isPirate = false;
|
||||||
|
is22 = 1;
|
||||||
|
reg1mask = 2;
|
||||||
|
reg2mask = 1;
|
||||||
|
|
||||||
|
// no IRQ (all mapper 22 games are VRC2)
|
||||||
|
// no WRAM
|
||||||
|
info->Power = VRC24Power;
|
||||||
|
GameStateRestore = StateRestore;
|
||||||
|
|
||||||
|
AddExState(&StateRegs, ~0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mapper23_Init(CartInfo *info) {
|
||||||
|
isPirate = false;
|
||||||
|
is22 = 0;
|
||||||
|
reg1mask = 0x15;
|
||||||
|
reg2mask = 0x2a;
|
||||||
VRC24_Init(info);
|
VRC24_Init(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mapper25_Init(CartInfo *info) {
|
void Mapper25_Init(CartInfo *info) {
|
||||||
isPirate = 0;
|
isPirate = false;
|
||||||
is22 = 0;
|
is22 = 0;
|
||||||
info->Power = M25Power;
|
reg1mask = 0xa;
|
||||||
|
reg2mask = 0x5;
|
||||||
VRC24_Init(info);
|
VRC24_Init(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UNLT230_Init(CartInfo *info) {
|
void UNLT230_Init(CartInfo *info) {
|
||||||
isPirate = 1;
|
isPirate = true;
|
||||||
is22 = 0;
|
is22 = 0;
|
||||||
info->Power = M23Power;
|
reg1mask = 0x15;
|
||||||
|
reg2mask = 0x2a;
|
||||||
VRC24_Init(info);
|
VRC24_Init(info);
|
||||||
}
|
}
|
||||||
|
@ -200,27 +200,3 @@ static void M190Close(void) {
|
|||||||
static void StateRestore(int version) {
|
static void StateRestore(int version) {
|
||||||
Sync();
|
Sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mapper190_Init(CartInfo *info) {
|
|
||||||
info->Power = M190Power;
|
|
||||||
info->Close = M190Close;
|
|
||||||
GameStateRestore = StateRestore;
|
|
||||||
|
|
||||||
MapIRQHook = VRC5IRQ;
|
|
||||||
// PPU_hook=Mapper190_PPU;
|
|
||||||
|
|
||||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRSIZE);
|
|
||||||
SetupCartCHRMapping(0x10, CHRRAM, CHRSIZE, 1);
|
|
||||||
AddExState(CHRRAM, CHRSIZE, 0, "CRAM");
|
|
||||||
|
|
||||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
|
||||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
|
||||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
|
||||||
|
|
||||||
if (info->battery) {
|
|
||||||
info->SaveGame[0] = WRAM;
|
|
||||||
info->SaveGameLen[0] = WRAMSIZE - 4096;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddExState(&StateRegs, ~0, 0, 0);
|
|
||||||
}
|
|
||||||
|
@ -86,7 +86,7 @@ static void VRC7SKill(void) {
|
|||||||
static void VRC7_ESI(void) {
|
static void VRC7_ESI(void) {
|
||||||
GameExpSound.RChange = VRC7SC;
|
GameExpSound.RChange = VRC7SC;
|
||||||
GameExpSound.Kill = VRC7SKill;
|
GameExpSound.Kill = VRC7SKill;
|
||||||
VRC7Sound = OPLL_new(3579545, FSettings.SndRate ? FSettings.SndRate : 44100);
|
VRC7Sound = OPLL_new(3579545, FSettings.SndRate ? FSettings.SndRate : 48000);
|
||||||
OPLL_reset(VRC7Sound);
|
OPLL_reset(VRC7Sound);
|
||||||
OPLL_reset(VRC7Sound);
|
OPLL_reset(VRC7Sound);
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,8 @@ uint8 geniech[3];
|
|||||||
|
|
||||||
uint32 genieaddr[3];
|
uint32 genieaddr[3];
|
||||||
|
|
||||||
|
CartInfo *currCartInfo;
|
||||||
|
|
||||||
static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram) {
|
static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram) {
|
||||||
uint32 AB = A >> 11;
|
uint32 AB = A >> 11;
|
||||||
int x;
|
int x;
|
||||||
|
@ -25,6 +25,8 @@ typedef struct {
|
|||||||
// other code in the future.
|
// other code in the future.
|
||||||
} CartInfo;
|
} CartInfo;
|
||||||
|
|
||||||
|
extern CartInfo *currCartInfo;
|
||||||
|
|
||||||
void FCEU_SaveGameSave(CartInfo *LocalHWInfo);
|
void FCEU_SaveGameSave(CartInfo *LocalHWInfo);
|
||||||
void FCEU_LoadGameSave(CartInfo *LocalHWInfo);
|
void FCEU_LoadGameSave(CartInfo *LocalHWInfo);
|
||||||
void FCEU_ClearGameSave(CartInfo *LocalHWInfo);
|
void FCEU_ClearGameSave(CartInfo *LocalHWInfo);
|
||||||
|
@ -216,7 +216,7 @@ void FCEU_LoadGameCheats(FILE *override)
|
|||||||
}
|
}
|
||||||
|
|
||||||
FCEU_DispMessage("Cheats file loaded.",0); //Tells user a cheats file was loaded.
|
FCEU_DispMessage("Cheats file loaded.",0); //Tells user a cheats file was loaded.
|
||||||
while(fgets(linebuf,2048,fp)>0)
|
while(fgets(linebuf,2048,fp) != nullptr)
|
||||||
{
|
{
|
||||||
char *tbuf=linebuf;
|
char *tbuf=linebuf;
|
||||||
int doc=0;
|
int doc=0;
|
||||||
@ -931,11 +931,13 @@ void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2)
|
|||||||
|
|
||||||
int FCEU_CheatGetByte(uint32 A)
|
int FCEU_CheatGetByte(uint32 A)
|
||||||
{
|
{
|
||||||
// if(CheatRPtrs[A>>10])
|
if(A < 0x10000) {
|
||||||
// return CheatRPtrs[A>>10][A]; //adelikat-commenting this stuff out so that lua can see frozen addresses, I hope this doesn't bork stuff.
|
uint32 ret;
|
||||||
/*else*/ if(A < 0x10000)
|
fceuindbg=1;
|
||||||
return ARead[A](A);
|
ret = ARead[A](A);
|
||||||
else
|
fceuindbg=0;
|
||||||
|
return ret;
|
||||||
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,10 +34,11 @@
|
|||||||
* Primitive -> Number | Address | Register | Flag | PC Bank | '(' Connect ')'
|
* Primitive -> Number | Address | Register | Flag | PC Bank | '(' Connect ')'
|
||||||
* Number -> '#' [1-9A-F]*
|
* Number -> '#' [1-9A-F]*
|
||||||
* Address -> '$' [1-9A-F]* | '$' '[' Connect ']'
|
* Address -> '$' [1-9A-F]* | '$' '[' Connect ']'
|
||||||
* Register -> 'A' | 'X' | 'Y' | 'P'
|
* Register -> 'A' | 'X' | 'Y' | 'P' | 'S'
|
||||||
* Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V'
|
* Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V' | 'U' | 'D'
|
||||||
* PC Bank -> 'K'
|
* PC Bank -> 'K'
|
||||||
* Data Bank -> 'T'
|
* Data Bank -> 'T'
|
||||||
|
* Value -> 'R' | 'W'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
@ -50,8 +51,9 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
// hack: this address is used by 'T' condition
|
uint16 debugLastAddress = 0; // used by 'T' and 'R' conditions
|
||||||
uint16 addressOfTheLastAccessedData = 0;
|
uint8 debugLastOpcode; // used to evaluate 'W' condition
|
||||||
|
|
||||||
// Next non-whitespace character in string
|
// Next non-whitespace character in string
|
||||||
char next;
|
char next;
|
||||||
|
|
||||||
@ -137,7 +139,7 @@ int isFlag(char c)
|
|||||||
// Determines if a character is a register
|
// Determines if a character is a register
|
||||||
int isRegister(char c)
|
int isRegister(char c)
|
||||||
{
|
{
|
||||||
return c == 'A' || c == 'X' || c == 'Y' || c == 'P';
|
return c == 'A' || c == 'X' || c == 'Y' || c == 'P' || c == 'S';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determines if a character is for PC bank
|
// Determines if a character is for PC bank
|
||||||
@ -152,6 +154,18 @@ int isDataBank(char c)
|
|||||||
return c == 'T';
|
return c == 'T';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determines if a character is for value read
|
||||||
|
int isValueRead(char c)
|
||||||
|
{
|
||||||
|
return c == 'R';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determines if a character is for value write
|
||||||
|
int isValueWrite(char c)
|
||||||
|
{
|
||||||
|
return c == 'W';
|
||||||
|
}
|
||||||
|
|
||||||
// Reads a hexadecimal number from str
|
// Reads a hexadecimal number from str
|
||||||
int getNumber(unsigned int* number, const char** str)
|
int getNumber(unsigned int* number, const char** str)
|
||||||
{
|
{
|
||||||
@ -272,6 +286,40 @@ Condition* Primitive(const char** str, Condition* c)
|
|||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
else if (isValueRead(next))
|
||||||
|
{
|
||||||
|
if (c->type1 == TYPE_NO)
|
||||||
|
{
|
||||||
|
c->type1 = TYPE_VALUE_READ;
|
||||||
|
c->value1 = next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->type2 = TYPE_VALUE_READ;
|
||||||
|
c->value2 = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
scan(str);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
else if (isValueWrite(next))
|
||||||
|
{
|
||||||
|
if (c->type1 == TYPE_NO)
|
||||||
|
{
|
||||||
|
c->type1 = TYPE_VALUE_WRITE;
|
||||||
|
c->value1 = next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->type2 = TYPE_VALUE_WRITE;
|
||||||
|
c->value2 = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
scan(str);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
else if (next == '#') /* Numbers */
|
else if (next == '#') /* Numbers */
|
||||||
{
|
{
|
||||||
unsigned int number = 0;
|
unsigned int number = 0;
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
#define TYPE_ADDR 4
|
#define TYPE_ADDR 4
|
||||||
#define TYPE_PC_BANK 5
|
#define TYPE_PC_BANK 5
|
||||||
#define TYPE_DATA_BANK 6
|
#define TYPE_DATA_BANK 6
|
||||||
|
#define TYPE_VALUE_READ 7
|
||||||
|
#define TYPE_VALUE_WRITE 8
|
||||||
|
|
||||||
#define OP_NO 0
|
#define OP_NO 0
|
||||||
#define OP_EQ 1
|
#define OP_EQ 1
|
||||||
@ -43,7 +45,9 @@
|
|||||||
#define OP_OR 11
|
#define OP_OR 11
|
||||||
#define OP_AND 12
|
#define OP_AND 12
|
||||||
|
|
||||||
extern uint16 addressOfTheLastAccessedData;
|
extern uint16 debugLastAddress;
|
||||||
|
extern uint8 debugLastOpcode;
|
||||||
|
|
||||||
//mbg merge 7/18/06 turned into sane c++
|
//mbg merge 7/18/06 turned into sane c++
|
||||||
struct Condition
|
struct Condition
|
||||||
{
|
{
|
||||||
|
@ -18,10 +18,13 @@ char *FCEUI_GetAboutString() {
|
|||||||
const char *aboutTemplate =
|
const char *aboutTemplate =
|
||||||
FCEU_NAME_AND_VERSION "\n\n"
|
FCEU_NAME_AND_VERSION "\n\n"
|
||||||
"Administrators:\n"
|
"Administrators:\n"
|
||||||
"zeromus, adelikat, AnS\n\n"
|
"zeromus, punkrockguy318 (Lukas Sabota), feos\n"
|
||||||
|
"\n"
|
||||||
"Current Contributors:\n"
|
"Current Contributors:\n"
|
||||||
"punkrockguy318 (Lukas Sabota)\n"
|
"CaH4e3, rainwarrior\n"
|
||||||
"CaH4e3, gocha, xhainingx, feos\n"
|
"\n"
|
||||||
|
"Past Contributors:\n"
|
||||||
|
"xhainingx, gocha, AnS\n"
|
||||||
"\n"
|
"\n"
|
||||||
"FCEUX 2.0:\n"
|
"FCEUX 2.0:\n"
|
||||||
"mz, nitsujrehtona, SP, Ugly Joe,\n"
|
"mz, nitsujrehtona, SP, Ugly Joe,\n"
|
||||||
|
@ -77,6 +77,7 @@ int getValue(int type)
|
|||||||
case 'Z': return _P & Z_FLAG ? 1 : 0;
|
case 'Z': return _P & Z_FLAG ? 1 : 0;
|
||||||
case 'C': return _P & C_FLAG ? 1 : 0;
|
case 'C': return _P & C_FLAG ? 1 : 0;
|
||||||
case 'P': return _PC;
|
case 'P': return _PC;
|
||||||
|
case 'S': return _S;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -290,9 +291,13 @@ uint8 GetMem(uint16 A) {
|
|||||||
}
|
}
|
||||||
else if ((A >= 0x4018) && (A < 0x5000)) // AnS: changed the range, so MMC5 ExRAM can be watched in the Hexeditor
|
else if ((A >= 0x4018) && (A < 0x5000)) // AnS: changed the range, so MMC5 ExRAM can be watched in the Hexeditor
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
if (GameInfo) //adelikat: 11/17/09: Prevent crash if this is called with no game loaded.
|
if (GameInfo) { //adelikat: 11/17/09: Prevent crash if this is called with no game loaded.
|
||||||
return ARead[A](A);
|
uint32 ret;
|
||||||
else return 0;
|
fceuindbg=1;
|
||||||
|
ret = ARead[A](A);
|
||||||
|
fceuindbg=0;
|
||||||
|
return ret;
|
||||||
|
} else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 GetPPUMem(uint8 A) {
|
uint8 GetPPUMem(uint8 A) {
|
||||||
@ -305,6 +310,32 @@ uint8 GetPPUMem(uint8 A) {
|
|||||||
|
|
||||||
//---------------------
|
//---------------------
|
||||||
|
|
||||||
|
uint8 evaluateWrite(uint8 opcode, uint16 address)
|
||||||
|
{
|
||||||
|
// predicts value written by this opcode
|
||||||
|
switch (opwrite[opcode])
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case 0: return 0; // no write
|
||||||
|
case 1: return _A; // STA, PHA
|
||||||
|
case 2: return _X; // STX
|
||||||
|
case 3: return _Y; // STY
|
||||||
|
case 4: return _P; // PHP
|
||||||
|
case 5: return GetMem(address) << 1; // ASL (SLO)
|
||||||
|
case 6: return GetMem(address) >> 1; // LSR (SRE)
|
||||||
|
case 7: return (GetMem(address) << 1) | (_P & 1); // ROL (RLA)
|
||||||
|
case 8: return (GetMem(address) >> 1) | ((_P & 1) << 7); // ROL (RRA)
|
||||||
|
case 9: return GetMem(address) + 1; // INC (ISC)
|
||||||
|
case 10: return GetMem(address) - 1; // DEC (DCP)
|
||||||
|
case 11: return _A & _X; // (SAX)
|
||||||
|
case 12: return _A&_X&(((address-_Y)>>8)+1); // (AHX)
|
||||||
|
case 13: return _Y&(((address-_X)>>8)+1); // (SHY)
|
||||||
|
case 14: return _X&(((address-_Y)>>8)+1); // (SHX)
|
||||||
|
case 15: return _S& (((address-_Y)>>8)+1); // (TAS)
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Evaluates a condition
|
// Evaluates a condition
|
||||||
int evaluate(Condition* c)
|
int evaluate(Condition* c)
|
||||||
{
|
{
|
||||||
@ -330,7 +361,9 @@ int evaluate(Condition* c)
|
|||||||
{
|
{
|
||||||
case TYPE_ADDR: value1 = GetMem(value1); break;
|
case TYPE_ADDR: value1 = GetMem(value1); break;
|
||||||
case TYPE_PC_BANK: value1 = getBank(_PC); break;
|
case TYPE_PC_BANK: value1 = getBank(_PC); break;
|
||||||
case TYPE_DATA_BANK: value1 = getBank(addressOfTheLastAccessedData); break;
|
case TYPE_DATA_BANK: value1 = getBank(debugLastAddress); break;
|
||||||
|
case TYPE_VALUE_READ: value1 = GetMem(debugLastAddress); break;
|
||||||
|
case TYPE_VALUE_WRITE: value1 = evaluateWrite(debugLastOpcode, debugLastAddress); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = value1;
|
f = value1;
|
||||||
@ -355,7 +388,9 @@ int evaluate(Condition* c)
|
|||||||
{
|
{
|
||||||
case TYPE_ADDR: value2 = GetMem(value2); break;
|
case TYPE_ADDR: value2 = GetMem(value2); break;
|
||||||
case TYPE_PC_BANK: value2 = getBank(_PC); break;
|
case TYPE_PC_BANK: value2 = getBank(_PC); break;
|
||||||
case TYPE_DATA_BANK: value2 = getBank(addressOfTheLastAccessedData); break;
|
case TYPE_DATA_BANK: value2 = getBank(debugLastAddress); break;
|
||||||
|
case TYPE_VALUE_READ: value2 = GetMem(debugLastAddress); break;
|
||||||
|
case TYPE_VALUE_WRITE: value2 = evaluateWrite(debugLastOpcode, debugLastAddress); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (c->op)
|
switch (c->op)
|
||||||
@ -367,7 +402,7 @@ int evaluate(Condition* c)
|
|||||||
case OP_G: f = value1 > value2; break;
|
case OP_G: f = value1 > value2; break;
|
||||||
case OP_L: f = value1 < value2; break;
|
case OP_L: f = value1 < value2; break;
|
||||||
case OP_MULT: f = value1 * value2; break;
|
case OP_MULT: f = value1 * value2; break;
|
||||||
case OP_DIV: f = value1 / value2; break;
|
case OP_DIV: f = (value2==0) ? 0 : (value1 / value2); break;
|
||||||
case OP_PLUS: f = value1 + value2; break;
|
case OP_PLUS: f = value1 + value2; break;
|
||||||
case OP_MINUS: f = value1 - value2; break;
|
case OP_MINUS: f = value1 - value2; break;
|
||||||
case OP_OR: f = value1 || value2; break;
|
case OP_OR: f = value1 || value2; break;
|
||||||
@ -502,6 +537,11 @@ void BreakHit(int bp_num, bool force)
|
|||||||
{
|
{
|
||||||
if(!force)
|
if(!force)
|
||||||
{
|
{
|
||||||
|
if (bp_num >= 0 && !condition(&watchpoint[bp_num]))
|
||||||
|
{
|
||||||
|
return; // condition rejected
|
||||||
|
}
|
||||||
|
|
||||||
//check to see whether we fall in any forbid zone
|
//check to see whether we fall in any forbid zone
|
||||||
for (int i = 0; i < numWPs; i++)
|
for (int i = 0; i < numWPs; i++)
|
||||||
{
|
{
|
||||||
@ -529,7 +569,7 @@ void BreakHit(int bp_num, bool force)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 StackAddrBackup = X.S;
|
int StackAddrBackup;
|
||||||
uint16 StackNextIgnorePC = 0xFFFF;
|
uint16 StackNextIgnorePC = 0xFFFF;
|
||||||
|
|
||||||
///fires a breakpoint
|
///fires a breakpoint
|
||||||
@ -539,6 +579,9 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
|||||||
uint8 stackop=0;
|
uint8 stackop=0;
|
||||||
uint8 stackopstartaddr,stackopendaddr;
|
uint8 stackopstartaddr,stackopendaddr;
|
||||||
|
|
||||||
|
debugLastAddress = A;
|
||||||
|
debugLastOpcode = opcode[0];
|
||||||
|
|
||||||
if (break_asap)
|
if (break_asap)
|
||||||
{
|
{
|
||||||
break_asap = false;
|
break_asap = false;
|
||||||
@ -601,24 +644,25 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
|||||||
switch (opcode[0]) {
|
switch (opcode[0]) {
|
||||||
//Push Ops
|
//Push Ops
|
||||||
case 0x08: //Fall to next
|
case 0x08: //Fall to next
|
||||||
case 0x48: stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
case 0x48: debugLastAddress=stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||||
//Pull Ops
|
//Pull Ops
|
||||||
case 0x28: //Fall to next
|
case 0x28: //Fall to next
|
||||||
case 0x68: stackopstartaddr=stackopendaddr=X.S+1; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
case 0x68: debugLastAddress=stackopstartaddr=stackopendaddr=X.S+1; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||||
//JSR (Includes return address - 1)
|
//JSR (Includes return address - 1)
|
||||||
case 0x20: stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=(opcode[1]|opcode[2]<<8); break;
|
case 0x20: stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=(opcode[1]|opcode[2]<<8); break;
|
||||||
//RTI (Includes processor status, and exact return address)
|
//RTI (Includes processor status, and exact return address)
|
||||||
case 0x40: stackopstartaddr=X.S+1; stackopendaddr=X.S+3; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=(GetMem(X.S+2|0x0100)|GetMem(X.S+3|0x0100)<<8); break;
|
case 0x40: stackopstartaddr=X.S+1; stackopendaddr=X.S+3; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=(GetMem(X.S+2|0x0100)|GetMem(X.S+3|0x0100)<<8); break;
|
||||||
//RTS (Includes return address - 1)
|
//RTS (Includes return address - 1)
|
||||||
case 0x60: stackopstartaddr=X.S+1; stackopendaddr=X.S+2; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=(GetMem(stackopstartaddr|0x0100)|GetMem(stackopendaddr|0x0100)<<8)+1; break;
|
case 0x60: stackopstartaddr=X.S+1; stackopendaddr=X.S+2; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=(GetMem(stackopstartaddr|0x0100)|GetMem(stackopendaddr|0x0100)<<8)+1; break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BREAKHIT(x) { breakHit = (x); goto STOPCHECKING; }
|
||||||
|
int breakHit = -1;
|
||||||
for (i = 0; i < numWPs; i++)
|
for (i = 0; i < numWPs; i++)
|
||||||
{
|
{
|
||||||
// ################################## Start of SP CODE ###########################
|
if ((watchpoint[i].flags & WP_E))
|
||||||
if ((watchpoint[i].flags & WP_E) && condition(&watchpoint[i]))
|
|
||||||
{
|
{
|
||||||
// ################################## End of SP CODE ###########################
|
|
||||||
if (watchpoint[i].flags & BT_P)
|
if (watchpoint[i].flags & BT_P)
|
||||||
{
|
{
|
||||||
// PPU Mem breaks
|
// PPU Mem breaks
|
||||||
@ -628,11 +672,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
|||||||
if (watchpoint[i].endaddress)
|
if (watchpoint[i].endaddress)
|
||||||
{
|
{
|
||||||
if ((watchpoint[i].address <= PPUAddr) && (watchpoint[i].endaddress >= PPUAddr))
|
if ((watchpoint[i].address <= PPUAddr) && (watchpoint[i].endaddress >= PPUAddr))
|
||||||
BreakHit(i);
|
BREAKHIT(i);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
if (watchpoint[i].address == PPUAddr)
|
if (watchpoint[i].address == PPUAddr)
|
||||||
BreakHit(i);
|
BREAKHIT(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (watchpoint[i].flags & BT_S)
|
} else if (watchpoint[i].flags & BT_S)
|
||||||
@ -643,16 +687,16 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
|||||||
if (watchpoint[i].endaddress)
|
if (watchpoint[i].endaddress)
|
||||||
{
|
{
|
||||||
if ((watchpoint[i].address <= PPU[3]) && (watchpoint[i].endaddress >= PPU[3]))
|
if ((watchpoint[i].address <= PPU[3]) && (watchpoint[i].endaddress >= PPU[3]))
|
||||||
BreakHit(i);
|
BREAKHIT(i);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
if (watchpoint[i].address == PPU[3])
|
if (watchpoint[i].address == PPU[3])
|
||||||
BreakHit(i);
|
BREAKHIT(i);
|
||||||
}
|
}
|
||||||
} else if ((watchpoint[i].flags & WP_W) && (A == 0x4014))
|
} else if ((watchpoint[i].flags & WP_W) && (A == 0x4014))
|
||||||
{
|
{
|
||||||
// Sprite DMA! :P
|
// Sprite DMA! :P
|
||||||
BreakHit(i);
|
BREAKHIT(i);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
@ -663,12 +707,12 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
|||||||
{
|
{
|
||||||
if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address <= A) && (watchpoint[i].endaddress >= A)) ||
|
if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address <= A) && (watchpoint[i].endaddress >= A)) ||
|
||||||
((watchpoint[i].flags & WP_X) && (watchpoint[i].address <= _PC) && (watchpoint[i].endaddress >= _PC)))
|
((watchpoint[i].flags & WP_X) && (watchpoint[i].address <= _PC) && (watchpoint[i].endaddress >= _PC)))
|
||||||
BreakHit(i);
|
BREAKHIT(i);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address == A)) ||
|
if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address == A)) ||
|
||||||
((watchpoint[i].flags & WP_X) && (watchpoint[i].address == _PC)))
|
((watchpoint[i].flags & WP_X) && (watchpoint[i].address == _PC)))
|
||||||
BreakHit(i);
|
BREAKHIT(i);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
@ -685,11 +729,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
|||||||
if (watchpoint[i].endaddress)
|
if (watchpoint[i].endaddress)
|
||||||
{
|
{
|
||||||
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
||||||
BreakHit(i);
|
BREAKHIT(i);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
if (watchpoint[i].address == j)
|
if (watchpoint[i].address == j)
|
||||||
BreakHit(i);
|
BREAKHIT(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -700,7 +744,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
|||||||
StackNextIgnorePC = 0xFFFF;
|
StackNextIgnorePC = 0xFFFF;
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
if ((X.S < StackAddrBackup) && (stackop==0))
|
if (StackAddrBackup != -1 && (X.S < StackAddrBackup) && (stackop==0))
|
||||||
{
|
{
|
||||||
// Unannounced stack mem breaks
|
// Unannounced stack mem breaks
|
||||||
// Pushes to stack
|
// Pushes to stack
|
||||||
@ -711,15 +755,15 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
|||||||
if (watchpoint[i].endaddress)
|
if (watchpoint[i].endaddress)
|
||||||
{
|
{
|
||||||
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
||||||
BreakHit(i);
|
BREAKHIT(i);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
if (watchpoint[i].address == j)
|
if (watchpoint[i].address == j)
|
||||||
BreakHit(i);
|
BREAKHIT(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ((StackAddrBackup < X.S) && (stackop==0))
|
} else if (StackAddrBackup != -1 && (StackAddrBackup < X.S) && (stackop==0))
|
||||||
{
|
{
|
||||||
// Pulls from stack
|
// Pulls from stack
|
||||||
if (watchpoint[i].flags & WP_R)
|
if (watchpoint[i].flags & WP_R)
|
||||||
@ -729,11 +773,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
|||||||
if (watchpoint[i].endaddress)
|
if (watchpoint[i].endaddress)
|
||||||
{
|
{
|
||||||
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
||||||
BreakHit(i);
|
BREAKHIT(i);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
if (watchpoint[i].address == j)
|
if (watchpoint[i].address == j)
|
||||||
BreakHit(i);
|
BREAKHIT(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -742,13 +786,20 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ################################## Start of SP CODE ###########################
|
|
||||||
}
|
|
||||||
// ################################## End of SP CODE ###########################
|
|
||||||
}
|
}
|
||||||
|
} //loop across all breakpoints
|
||||||
|
|
||||||
|
STOPCHECKING:
|
||||||
|
|
||||||
//Update the stack address with the current one, now that changes have registered.
|
//Update the stack address with the current one, now that changes have registered.
|
||||||
|
//ZEROMUS THINKS IT MAKES MORE SENSE HERE
|
||||||
StackAddrBackup = X.S;
|
StackAddrBackup = X.S;
|
||||||
|
|
||||||
|
if(breakHit != -1)
|
||||||
|
BreakHit(i);
|
||||||
|
|
||||||
|
////Update the stack address with the current one, now that changes have registered.
|
||||||
|
//StackAddrBackup = X.S;
|
||||||
}
|
}
|
||||||
//bbit edited: this is the end of the inserted code
|
//bbit edited: this is the end of the inserted code
|
||||||
|
|
||||||
@ -777,9 +828,12 @@ void DebugCycle()
|
|||||||
size = opsize[opcode[0]];
|
size = opsize[opcode[0]];
|
||||||
switch (size)
|
switch (size)
|
||||||
{
|
{
|
||||||
|
default:
|
||||||
|
case 1: break;
|
||||||
case 2:
|
case 2:
|
||||||
opcode[1] = GetMem(_PC + 1);
|
opcode[1] = GetMem(_PC + 1);
|
||||||
break;
|
break;
|
||||||
|
case 0: // illegal instructions may have operands
|
||||||
case 3:
|
case 3:
|
||||||
opcode[1] = GetMem(_PC + 1);
|
opcode[1] = GetMem(_PC + 1);
|
||||||
opcode[2] = GetMem(_PC + 2);
|
opcode[2] = GetMem(_PC + 2);
|
||||||
@ -803,7 +857,6 @@ void DebugCycle()
|
|||||||
case 7: A = (opcode[1] | (opcode[2] << 8)) + _X; break;
|
case 7: A = (opcode[1] | (opcode[2] << 8)) + _X; break;
|
||||||
case 8: A = opcode[1] + _Y; break;
|
case 8: A = opcode[1] + _Y; break;
|
||||||
}
|
}
|
||||||
addressOfTheLastAccessedData = A;
|
|
||||||
|
|
||||||
if (numWPs || dbgstate.step || dbgstate.runline || dbgstate.stepout || watchpoint[64].flags || dbgstate.badopbreak || break_on_cycles || break_on_instructions || break_asap)
|
if (numWPs || dbgstate.step || dbgstate.runline || dbgstate.stepout || watchpoint[64].flags || dbgstate.badopbreak || break_on_cycles || break_on_instructions || break_asap)
|
||||||
breakpoint(opcode, A, size);
|
breakpoint(opcode, A, size);
|
||||||
|
@ -49,13 +49,11 @@ typedef struct {
|
|||||||
uint16 address;
|
uint16 address;
|
||||||
uint16 endaddress;
|
uint16 endaddress;
|
||||||
uint8 flags;
|
uint8 flags;
|
||||||
// ################################## Start of SP CODE ###########################
|
|
||||||
|
|
||||||
Condition* cond;
|
Condition* cond;
|
||||||
char* condText;
|
char* condText;
|
||||||
char* desc;
|
char* desc;
|
||||||
|
|
||||||
// ################################## End of SP CODE ###########################
|
|
||||||
} watchpointinfo;
|
} watchpointinfo;
|
||||||
|
|
||||||
//mbg merge 7/18/06 had to make this extern
|
//mbg merge 7/18/06 had to make this extern
|
||||||
@ -117,8 +115,6 @@ extern void IncrementInstructionsCounters();
|
|||||||
extern uint8 *vnapage[4],*VPage[8];
|
extern uint8 *vnapage[4],*VPage[8];
|
||||||
extern uint8 PPU[4],PALRAM[0x20],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset;
|
extern uint8 PPU[4],PALRAM[0x20],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset;
|
||||||
extern uint32 FCEUPPU_PeekAddress();
|
extern uint32 FCEUPPU_PeekAddress();
|
||||||
|
|
||||||
extern int debug_loggingCD;
|
|
||||||
extern int numWPs;
|
extern int numWPs;
|
||||||
|
|
||||||
///encapsulates the operational state of the debugger core
|
///encapsulates the operational state of the debugger core
|
||||||
|
@ -68,7 +68,7 @@ void FCEUI_NTSCSELTINT(void);
|
|||||||
void FCEUI_NTSCDEC(void);
|
void FCEUI_NTSCDEC(void);
|
||||||
void FCEUI_NTSCINC(void);
|
void FCEUI_NTSCINC(void);
|
||||||
void FCEUI_GetNTSCTH(int *tint, int *hue);
|
void FCEUI_GetNTSCTH(int *tint, int *hue);
|
||||||
void FCEUI_SetNTSCTH(int n, int tint, int hue);
|
void FCEUI_SetNTSCTH(bool en, int tint, int hue);
|
||||||
|
|
||||||
void FCEUI_SetInput(int port, ESI type, void *ptr, int attrib);
|
void FCEUI_SetInput(int port, ESI type, void *ptr, int attrib);
|
||||||
void FCEUI_SetInputFC(ESIFC type, void *ptr, int attrib);
|
void FCEUI_SetInputFC(ESIFC type, void *ptr, int attrib);
|
||||||
@ -122,7 +122,7 @@ void FCEUI_SetVidSystem(int a);
|
|||||||
|
|
||||||
//Set variables for NTSC(0) / PAL(1) / Dendy(2)
|
//Set variables for NTSC(0) / PAL(1) / Dendy(2)
|
||||||
//Dendy has PAL framerate and resolution, but ~NTSC timings, and has 50 dummy scanlines to force 50 fps
|
//Dendy has PAL framerate and resolution, but ~NTSC timings, and has 50 dummy scanlines to force 50 fps
|
||||||
void FCEUI_SetRegion(int region);
|
void FCEUI_SetRegion(int region, int notify = 1);
|
||||||
|
|
||||||
//Convenience function; returns currently emulated video system(0=NTSC, 1=PAL).
|
//Convenience function; returns currently emulated video system(0=NTSC, 1=PAL).
|
||||||
int FCEUI_GetCurrentVidSystem(int *slstart, int *slend);
|
int FCEUI_GetCurrentVidSystem(int *slstart, int *slend);
|
||||||
@ -141,9 +141,7 @@ void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall);
|
|||||||
//Sets the base directory(save states, snapshots, etc. are saved in directories below this directory.
|
//Sets the base directory(save states, snapshots, etc. are saved in directories below this directory.
|
||||||
void FCEUI_SetBaseDirectory(std::string const & dir);
|
void FCEUI_SetBaseDirectory(std::string const & dir);
|
||||||
|
|
||||||
//Tells FCE Ultra to copy the palette data pointed to by pal and use it.
|
void FCEUI_SetUserPalette(uint8 *pal, int nEntries);
|
||||||
//Data pointed to by pal needs to be 64*3 bytes in length.
|
|
||||||
void FCEUI_SetPaletteArray(uint8 *pal);
|
|
||||||
|
|
||||||
//Sets up sound code to render sound at the specified rate, in samples
|
//Sets up sound code to render sound at the specified rate, in samples
|
||||||
//per second. Only sample rates of 44100, 48000, and 96000 are currently supported.
|
//per second. Only sample rates of 44100, 48000, and 96000 are currently supported.
|
||||||
|
@ -56,9 +56,10 @@ extern bool isTaseditorRecording();
|
|||||||
extern int32 fps_scale;
|
extern int32 fps_scale;
|
||||||
extern int32 fps_scale_unpaused;
|
extern int32 fps_scale_unpaused;
|
||||||
extern int32 fps_scale_frameadvance;
|
extern int32 fps_scale_frameadvance;
|
||||||
extern void RefreshThrottleFPS();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern void RefreshThrottleFPS();
|
||||||
|
|
||||||
#ifdef _S9XLUA_H
|
#ifdef _S9XLUA_H
|
||||||
#include "fceulua.h"
|
#include "fceulua.h"
|
||||||
#endif
|
#endif
|
||||||
@ -93,6 +94,20 @@ extern void RefreshThrottleFPS();
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
//-----------
|
||||||
|
//overclocking-related
|
||||||
|
// overclock the console by adding dummy scanlines to PPU loop or to vblank
|
||||||
|
// disables DMC DMA, WaveHi filling and image rendering for these dummies
|
||||||
|
// doesn't work with new PPU
|
||||||
|
bool overclock_enabled = 0;
|
||||||
|
bool overclocking = 0;
|
||||||
|
bool skip_7bit_overclocking = 1; // 7-bit samples have priority over overclocking
|
||||||
|
int normalscanlines;
|
||||||
|
int totalscanlines;
|
||||||
|
int postrenderscanlines = 0;
|
||||||
|
int vblankscanlines = 0;
|
||||||
|
//------------
|
||||||
|
|
||||||
int AFon = 1, AFoff = 1, AutoFireOffset = 0; //For keeping track of autofire settings
|
int AFon = 1, AFoff = 1, AutoFireOffset = 0; //For keeping track of autofire settings
|
||||||
bool justLagged = false;
|
bool justLagged = false;
|
||||||
bool frameAdvanceLagSkip = false; //If this is true, frame advance will skip over lag frame (i.e. it will emulate 2 frames instead of 1)
|
bool frameAdvanceLagSkip = false; //If this is true, frame advance will skip over lag frame (i.e. it will emulate 2 frames instead of 1)
|
||||||
@ -101,7 +116,6 @@ bool movieSubtitles = true; //Toggle for displaying movie subtitles
|
|||||||
bool DebuggerWasUpdated = false; //To prevent the debugger from updating things without being updated.
|
bool DebuggerWasUpdated = false; //To prevent the debugger from updating things without being updated.
|
||||||
bool AutoResumePlay = false;
|
bool AutoResumePlay = false;
|
||||||
char romNameWhenClosingEmulator[2048] = {0};
|
char romNameWhenClosingEmulator[2048] = {0};
|
||||||
int dendy = 0;
|
|
||||||
|
|
||||||
FCEUGI::FCEUGI()
|
FCEUGI::FCEUGI()
|
||||||
: filename(0),
|
: filename(0),
|
||||||
@ -140,10 +154,12 @@ void FCEU_TogglePPU(void) {
|
|||||||
if (newppu) {
|
if (newppu) {
|
||||||
FCEU_DispMessage("New PPU loaded", 0);
|
FCEU_DispMessage("New PPU loaded", 0);
|
||||||
FCEUI_printf("New PPU loaded");
|
FCEUI_printf("New PPU loaded");
|
||||||
|
overclock_enabled = 0;
|
||||||
} else {
|
} else {
|
||||||
FCEU_DispMessage("Old PPU loaded", 0);
|
FCEU_DispMessage("Old PPU loaded", 0);
|
||||||
FCEUI_printf("Old PPU loaded");
|
FCEUI_printf("Old PPU loaded");
|
||||||
}
|
}
|
||||||
|
normalscanlines = (dendy ? 290 : 240)+newppu; // use flag as number!
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
SetMainWindowText();
|
SetMainWindowText();
|
||||||
#endif
|
#endif
|
||||||
@ -348,16 +364,10 @@ uint8 PAL = 0;
|
|||||||
|
|
||||||
static DECLFW(BRAML) {
|
static DECLFW(BRAML) {
|
||||||
RAM[A] = V;
|
RAM[A] = V;
|
||||||
#ifdef _S9XLUA_H
|
|
||||||
CallRegisteredLuaMemHook(A, 1, V, LUAMEMHOOK_WRITE);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static DECLFW(BRAMH) {
|
static DECLFW(BRAMH) {
|
||||||
RAM[A & 0x7FF] = V;
|
RAM[A & 0x7FF] = V;
|
||||||
#ifdef _S9XLUA_H
|
|
||||||
CallRegisteredLuaMemHook(A & 0x7FF, 1, V, LUAMEMHOOK_WRITE);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static DECLFR(ARAML) {
|
static DECLFR(ARAML) {
|
||||||
@ -384,7 +394,7 @@ void ResetGameLoaded(void) {
|
|||||||
MMC5Hack = 0;
|
MMC5Hack = 0;
|
||||||
PEC586Hack = 0;
|
PEC586Hack = 0;
|
||||||
PAL &= 1;
|
PAL &= 1;
|
||||||
pale = 0;
|
default_palette_selection = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int UNIFLoad(const char *name, FCEUFILE *fp);
|
int UNIFLoad(const char *name, FCEUFILE *fp);
|
||||||
@ -401,6 +411,8 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
|
|||||||
//attempt to open the files
|
//attempt to open the files
|
||||||
FCEUFILE *fp;
|
FCEUFILE *fp;
|
||||||
char fullname[2048]; // this name contains both archive name and ROM file name
|
char fullname[2048]; // this name contains both archive name and ROM file name
|
||||||
|
int lastpal = PAL;
|
||||||
|
int lastdendy = dendy;
|
||||||
|
|
||||||
const char* romextensions[] = { "nes", "fds", 0 };
|
const char* romextensions[] = { "nes", "fds", 0 };
|
||||||
fp = FCEU_fopen(name, 0, "rb", 0, -1, romextensions);
|
fp = FCEU_fopen(name, 0, "rb", 0, -1, romextensions);
|
||||||
@ -488,6 +500,7 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
|
|||||||
// ################################## End of SP CODE ###########################
|
// ################################## End of SP CODE ###########################
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (OverwriteVidMode)
|
||||||
FCEU_ResetVidSys();
|
FCEU_ResetVidSys();
|
||||||
|
|
||||||
if (GameInfo->type != GIT_NSF)
|
if (GameInfo->type != GIT_NSF)
|
||||||
@ -511,6 +524,18 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
|
|||||||
FCEU_ResetPalette();
|
FCEU_ResetPalette();
|
||||||
FCEU_ResetMessages(); // Save state, status messages, etc.
|
FCEU_ResetMessages(); // Save state, status messages, etc.
|
||||||
|
|
||||||
|
if (!lastpal && PAL) {
|
||||||
|
FCEU_DispMessage("PAL mode set", 0);
|
||||||
|
FCEUI_printf("PAL mode set");
|
||||||
|
} else if (!lastdendy && dendy) {
|
||||||
|
// this won't happen, since we don't autodetect dendy, but maybe someday we will?
|
||||||
|
FCEU_DispMessage("Dendy mode set", 0);
|
||||||
|
FCEUI_printf("Dendy mode set");
|
||||||
|
} else if ((lastpal || lastdendy) && !(PAL || dendy)) {
|
||||||
|
FCEU_DispMessage("NTSC mode set", 0);
|
||||||
|
FCEUI_printf("NTSC mode set");
|
||||||
|
}
|
||||||
|
|
||||||
if (GameInfo->type != GIT_NSF)
|
if (GameInfo->type != GIT_NSF)
|
||||||
FCEU_LoadGameCheats(0);
|
FCEU_LoadGameCheats(0);
|
||||||
|
|
||||||
@ -712,10 +737,15 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
|
|||||||
extern int KillFCEUXonFrame;
|
extern int KillFCEUXonFrame;
|
||||||
if (KillFCEUXonFrame && (FCEUMOV_GetFrame() >= KillFCEUXonFrame))
|
if (KillFCEUXonFrame && (FCEUMOV_GetFrame() >= KillFCEUXonFrame))
|
||||||
DoFCEUExit();
|
DoFCEUExit();
|
||||||
|
#else
|
||||||
|
extern int KillFCEUXonFrame;
|
||||||
|
if (KillFCEUXonFrame && (FCEUMOV_GetFrame() >= KillFCEUXonFrame))
|
||||||
|
exit(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
timestampbase += timestamp;
|
timestampbase += timestamp;
|
||||||
timestamp = 0;
|
timestamp = 0;
|
||||||
|
soundtimestamp = 0;
|
||||||
|
|
||||||
*pXBuf = skip ? 0 : XBuf;
|
*pXBuf = skip ? 0 : XBuf;
|
||||||
if (skip == 2) { //If skip = 2, then bypass sound
|
if (skip == 2) { //If skip = 2, then bypass sound
|
||||||
@ -769,17 +799,79 @@ void ResetNES(void) {
|
|||||||
//FCEU_DispMessage("Reset", 0);
|
//FCEU_DispMessage("Reset", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCEU_MemoryRand(uint8 *ptr, uint32 size) {
|
|
||||||
|
int RAMInitSeed = 0;
|
||||||
|
int RAMInitOption = 0;
|
||||||
|
|
||||||
|
u64 splitmix64(u32 input) {
|
||||||
|
u64 z = (input + 0x9e3779b97f4a7c15);
|
||||||
|
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
||||||
|
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
||||||
|
return z ^ (z >> 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u64 xoroshiro128plus_rotl(const u64 x, int k) {
|
||||||
|
return (x << k) | (x >> (64 - k));
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 xoroshiro128plus_s[2];
|
||||||
|
void xoroshiro128plus_seed(u32 input)
|
||||||
|
{
|
||||||
|
//http://xoroshiro.di.unimi.it/splitmix64.c
|
||||||
|
u64 x = input;
|
||||||
|
|
||||||
|
u64 z = (x += 0x9e3779b97f4a7c15);
|
||||||
|
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
||||||
|
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
||||||
|
xoroshiro128plus_s[0] = z ^ (z >> 31);
|
||||||
|
|
||||||
|
z = (x += 0x9e3779b97f4a7c15);
|
||||||
|
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
||||||
|
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
||||||
|
xoroshiro128plus_s[1] = z ^ (z >> 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
//http://vigna.di.unimi.it/xorshift/xoroshiro128plus.c
|
||||||
|
u64 xoroshiro128plus_next() {
|
||||||
|
const u64 s0 = xoroshiro128plus_s[0];
|
||||||
|
u64 s1 = xoroshiro128plus_s[1];
|
||||||
|
const u64 result = s0 + s1;
|
||||||
|
|
||||||
|
s1 ^= s0;
|
||||||
|
xoroshiro128plus_s[0] = xoroshiro128plus_rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b
|
||||||
|
xoroshiro128plus_s[1] = xoroshiro128plus_rotl(s1, 36); // c
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_MemoryRand(uint8 *ptr, uint32 size, bool default_zero) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
|
|
||||||
while (size) {
|
while (size) {
|
||||||
*ptr = (x & 4) ? 0xFF : 0x00; // Huang Di DEBUG MODE enabled by default
|
uint8 v = 0;
|
||||||
// Cybernoid NO MUSIC by default
|
switch (RAMInitOption)
|
||||||
// *ptr = (x & 4) ? 0x7F : 0x00; // Huang Di DEBUG MODE enabled by default
|
{
|
||||||
// Minna no Taabou no Nakayoshi Daisakusen DOESN'T BOOT
|
default:
|
||||||
// Cybernoid NO MUSIC by default
|
case 0:
|
||||||
// *ptr = (x & 1) ? 0x55 : 0xAA; // F-15 Sity War HISCORE is screwed...
|
if (!default_zero) v = (x & 4) ? 0xFF : 0x00;
|
||||||
// 1942 SCORE/HISCORE is screwed...
|
else v = 0x00;
|
||||||
// *ptr = 0xFF; // Work for all cases
|
break;
|
||||||
|
case 1: v = 0xFF; break;
|
||||||
|
case 2: v = 0x00; break;
|
||||||
|
case 3: v = (u8)(xoroshiro128plus_next()); break;
|
||||||
|
|
||||||
|
// the default is this 8 byte pattern: 00 00 00 00 FF FF FF FF
|
||||||
|
// it has been used in FCEUX since time immemorial
|
||||||
|
|
||||||
|
// Some games to examine uninitialied RAM problems with:
|
||||||
|
// * Cybernoid - music option starts turned off with default pattern
|
||||||
|
// * Huang Di - debug mode is enabled with default pattern
|
||||||
|
// * Minna no Taabou no Nakayoshi Daisakusen - fails to boot with some patterns
|
||||||
|
// * F-15 City War - high score table
|
||||||
|
// * 1942 - high score table
|
||||||
|
// * Cheetahmen II - may start in different levels with different RAM startup
|
||||||
|
}
|
||||||
|
*ptr = v;
|
||||||
x++;
|
x++;
|
||||||
size--;
|
size--;
|
||||||
ptr++;
|
ptr++;
|
||||||
@ -793,18 +885,21 @@ void PowerNES(void) {
|
|||||||
FCEUMOV_AddCommand(FCEUNPCMD_POWER);
|
FCEUMOV_AddCommand(FCEUNPCMD_POWER);
|
||||||
if (!GameInfo) return;
|
if (!GameInfo) return;
|
||||||
|
|
||||||
|
//reseed random, unless we're in a movie
|
||||||
|
extern int disableBatteryLoading;
|
||||||
|
if(FCEUMOV_Mode(MOVIEMODE_INACTIVE) && !disableBatteryLoading)
|
||||||
|
{
|
||||||
|
RAMInitSeed = rand() ^ (u32)xoroshiro128plus_next();
|
||||||
|
}
|
||||||
|
|
||||||
|
//always reseed the PRNG with the current seed, for deterministic results (for that seed)
|
||||||
|
xoroshiro128plus_seed(RAMInitSeed);
|
||||||
|
|
||||||
FCEU_CheatResetRAM();
|
FCEU_CheatResetRAM();
|
||||||
FCEU_CheatAddRAM(2, 0, RAM);
|
FCEU_CheatAddRAM(2, 0, RAM);
|
||||||
|
|
||||||
FCEU_GeniePower();
|
FCEU_GeniePower();
|
||||||
|
|
||||||
//dont do this, it breaks some games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; and maybe mechanized attack
|
|
||||||
//memset(RAM,0xFF,0x800);
|
|
||||||
//this fixes the above, but breaks Huang Di, which expects $100 to be non-zero or else it believes it has debug cheats enabled, giving you moon jump and other great but likely unwanted things
|
|
||||||
//FCEU_MemoryRand(RAM,0x800);
|
|
||||||
//this should work better, based on observational evidence. fixes all of the above:
|
|
||||||
//for(int i=0;i<0x800;i++) if(i&1) RAM[i] = 0xAA; else RAM[i] = 0x55;
|
|
||||||
//but we're leaving this for now until we collect some more data
|
|
||||||
FCEU_MemoryRand(RAM, 0x800);
|
FCEU_MemoryRand(RAM, 0x800);
|
||||||
|
|
||||||
SetReadHandler(0x0000, 0xFFFF, ANull);
|
SetReadHandler(0x0000, 0xFFFF, ANull);
|
||||||
@ -845,7 +940,7 @@ void PowerNES(void) {
|
|||||||
Update_RAM_Search(); // Update_RAM_Watch() is also called.
|
Update_RAM_Search(); // Update_RAM_Watch() is also called.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//FCEU_DispMessage("Power on", 0);
|
FCEU_DispMessage("Power on", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCEU_ResetVidSys(void) {
|
void FCEU_ResetVidSys(void) {
|
||||||
@ -861,6 +956,14 @@ void FCEU_ResetVidSys(void) {
|
|||||||
|
|
||||||
PAL = w ? 1 : 0;
|
PAL = w ? 1 : 0;
|
||||||
|
|
||||||
|
if (PAL)
|
||||||
|
dendy = 0;
|
||||||
|
|
||||||
|
if (newppu)
|
||||||
|
overclock_enabled = 0;
|
||||||
|
|
||||||
|
normalscanlines = (dendy ? 290 : 240)+newppu; // use flag as number!
|
||||||
|
totalscanlines = normalscanlines + (overclock_enabled ? postrenderscanlines : 0);
|
||||||
FCEUPPU_SetVideoSystem(w || dendy);
|
FCEUPPU_SetVideoSystem(w || dendy);
|
||||||
SetSoundVariables();
|
SetSoundVariables();
|
||||||
}
|
}
|
||||||
@ -877,6 +980,13 @@ void FCEU_printf(char *format, ...) {
|
|||||||
vsnprintf(temp, sizeof(temp), format, ap);
|
vsnprintf(temp, sizeof(temp), format, ap);
|
||||||
FCEUD_Message(temp);
|
FCEUD_Message(temp);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
FILE *ofile;
|
||||||
|
ofile = fopen("stdout.txt", "ab");
|
||||||
|
fwrite(temp, 1, strlen(temp), ofile);
|
||||||
|
fclose(ofile);
|
||||||
|
#endif
|
||||||
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -925,30 +1035,58 @@ int FCEUI_GetCurrentVidSystem(int *slstart, int *slend) {
|
|||||||
*slend = FSettings.LastSLine;
|
*slend = FSettings.LastSLine;
|
||||||
return(PAL);
|
return(PAL);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
// TODO: make use on SDL
|
#ifndef GEKKO
|
||||||
void FCEUI_SetRegion(int region) {
|
void FCEUI_SetRegion(int region, int notify) {
|
||||||
switch (region) {
|
switch (region) {
|
||||||
case 0: // NTSC
|
case 0: // NTSC
|
||||||
|
normalscanlines = 240;
|
||||||
pal_emulation = 0;
|
pal_emulation = 0;
|
||||||
dendy = 0;
|
dendy = 0;
|
||||||
|
// until it's fixed on sdl. see issue #740
|
||||||
|
#ifdef WIN32
|
||||||
|
if (notify)
|
||||||
|
{
|
||||||
|
FCEU_DispMessage("NTSC mode set", 0);
|
||||||
|
FCEUI_printf("NTSC mode set");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case 1: // PAL
|
case 1: // PAL
|
||||||
|
normalscanlines = 240;
|
||||||
pal_emulation = 1;
|
pal_emulation = 1;
|
||||||
dendy = 0;
|
dendy = 0;
|
||||||
|
#ifdef WIN32
|
||||||
|
if (notify)
|
||||||
|
{
|
||||||
|
FCEU_DispMessage("PAL mode set", 0);
|
||||||
|
FCEUI_printf("PAL mode set");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case 2: // Dendy
|
case 2: // Dendy
|
||||||
|
normalscanlines = 290;
|
||||||
pal_emulation = 0;
|
pal_emulation = 0;
|
||||||
dendy = 1;
|
dendy = 1;
|
||||||
|
#ifdef WIN32
|
||||||
|
if (notify)
|
||||||
|
{
|
||||||
|
FCEU_DispMessage("Dendy mode set", 0);
|
||||||
|
FCEUI_printf("Dendy mode set");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
normalscanlines += newppu;
|
||||||
|
totalscanlines = normalscanlines + (overclock_enabled ? postrenderscanlines : 0);
|
||||||
FCEUI_SetVidSystem(pal_emulation);
|
FCEUI_SetVidSystem(pal_emulation);
|
||||||
RefreshThrottleFPS();
|
RefreshThrottleFPS();
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
UpdateCheckedMenuItems();
|
UpdateCheckedMenuItems();
|
||||||
PushCurrentVideoSettings();
|
PushCurrentVideoSettings();
|
||||||
#endif
|
#endif
|
||||||
}*/
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//Enable or disable Game Genie option.
|
//Enable or disable Game Genie option.
|
||||||
void FCEUI_SetGameGenie(bool a) {
|
void FCEUI_SetGameGenie(bool a) {
|
||||||
@ -1052,9 +1190,7 @@ int FCEU_TextScanlineOffsetFromBottom(int y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool FCEU_IsValidUI(EFCEUI ui) {
|
bool FCEU_IsValidUI(EFCEUI ui) {
|
||||||
#ifdef GEKKO
|
#ifndef GEKKO
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
switch (ui) {
|
switch (ui) {
|
||||||
case FCEUI_OPENGAME:
|
case FCEUI_OPENGAME:
|
||||||
case FCEUI_CLOSEGAME:
|
case FCEUI_CLOSEGAME:
|
||||||
@ -1099,6 +1235,7 @@ bool FCEU_IsValidUI(EFCEUI ui) {
|
|||||||
if (!FCEUMOV_Mode(MOVIEMODE_INACTIVE)) return false;
|
if (!FCEUMOV_Mode(MOVIEMODE_INACTIVE)) return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1165,8 +1302,6 @@ void FCEUXGameInterface(GI command) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool FCEUXLoad(const char *name, FCEUFILE *fp) {
|
bool FCEUXLoad(const char *name, FCEUFILE *fp) {
|
||||||
//read ines header
|
//read ines header
|
||||||
iNES_HEADER head;
|
iNES_HEADER head;
|
||||||
@ -1218,11 +1353,26 @@ bool FCEUXLoad(const char *name, FCEUFILE *fp) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8 FCEU_ReadRomByte(uint32 i) {
|
uint8 FCEU_ReadRomByte(uint32 i) {
|
||||||
extern iNES_HEADER head;
|
extern iNES_HEADER head;
|
||||||
if (i < 16) return *((unsigned char*)&head + i);
|
if (i < 16)
|
||||||
if (i < 16 + PRGsize[0]) return PRGptr[0][i - 16];
|
return *((unsigned char*)&head + i);
|
||||||
if (i < 16 + PRGsize[0] + CHRsize[0]) return CHRptr[0][i - 16 - PRGsize[0]];
|
if (i < 16 + PRGsize[0])
|
||||||
|
return PRGptr[0][i - 16];
|
||||||
|
if (i < 16 + PRGsize[0] + CHRsize[0])
|
||||||
|
return CHRptr[0][i - 16 - PRGsize[0]];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FCEU_WriteRomByte(uint32 i, uint8 value) {
|
||||||
|
if (i < 16)
|
||||||
|
#ifdef WIN32
|
||||||
|
MessageBox(hMemView,"Sorry", "You can't edit the ROM header.", MB_OK);
|
||||||
|
#else
|
||||||
|
printf("Sorry, you can't edit the ROM header.\n");
|
||||||
|
#endif
|
||||||
|
if (i < 16 + PRGsize[0])
|
||||||
|
PRGptr[0][i - 16] = value;
|
||||||
|
else if (i < 16 + PRGsize[0] + CHRsize[0])
|
||||||
|
CHRptr[0][i - 16 - PRGsize[0]] = value;
|
||||||
|
}
|
||||||
|
@ -7,13 +7,22 @@ extern int fceuindbg;
|
|||||||
extern int newppu;
|
extern int newppu;
|
||||||
void ResetGameLoaded(void);
|
void ResetGameLoaded(void);
|
||||||
|
|
||||||
|
//overclocking-related
|
||||||
|
extern bool overclock_enabled;
|
||||||
|
extern bool overclocking;
|
||||||
|
extern bool skip_7bit_overclocking;
|
||||||
|
extern int normalscanlines;
|
||||||
|
extern int totalscanlines;
|
||||||
|
extern int postrenderscanlines;
|
||||||
|
extern int vblankscanlines;
|
||||||
|
|
||||||
extern bool AutoResumePlay;
|
extern bool AutoResumePlay;
|
||||||
extern char romNameWhenClosingEmulator[];
|
extern char romNameWhenClosingEmulator[];
|
||||||
|
|
||||||
#define DECLFR(x) uint8 x (uint32 A)
|
#define DECLFR(x) uint8 x (uint32 A)
|
||||||
#define DECLFW(x) void x (uint32 A, uint8 V)
|
#define DECLFW(x) void x (uint32 A, uint8 V)
|
||||||
|
|
||||||
void FCEU_MemoryRand(uint8 *ptr, uint32 size);
|
void FCEU_MemoryRand(uint8 *ptr, uint32 size, bool default_zero=false);
|
||||||
void SetReadHandler(int32 start, int32 end, readfunc func);
|
void SetReadHandler(int32 start, int32 end, readfunc func);
|
||||||
void SetWriteHandler(int32 start, int32 end, writefunc func);
|
void SetWriteHandler(int32 start, int32 end, writefunc func);
|
||||||
writefunc GetWriteHandler(int32 a);
|
writefunc GetWriteHandler(int32 a);
|
||||||
@ -54,6 +63,7 @@ extern uint8 *RAM; //shared memory modifications
|
|||||||
extern int EmulationPaused;
|
extern int EmulationPaused;
|
||||||
|
|
||||||
uint8 FCEU_ReadRomByte(uint32 i);
|
uint8 FCEU_ReadRomByte(uint32 i);
|
||||||
|
void FCEU_WriteRomByte(uint32 i, uint8 value);
|
||||||
|
|
||||||
extern readfunc ARead[0x10000];
|
extern readfunc ARead[0x10000];
|
||||||
extern writefunc BWrite[0x10000];
|
extern writefunc BWrite[0x10000];
|
||||||
@ -121,7 +131,7 @@ void FCEU_DispMessage(char *format, int disppos, ...);
|
|||||||
void FCEU_DispMessageOnMovie(char *format, ...);
|
void FCEU_DispMessageOnMovie(char *format, ...);
|
||||||
void FCEU_TogglePPU();
|
void FCEU_TogglePPU();
|
||||||
|
|
||||||
void SetNESDeemph(uint8 d, int force);
|
void SetNESDeemph_OldHacky(uint8 d, int force);
|
||||||
void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor);
|
void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor);
|
||||||
void FCEU_PutImage(void);
|
void FCEU_PutImage(void);
|
||||||
#ifdef FRAMESKIP
|
#ifdef FRAMESKIP
|
||||||
@ -134,7 +144,7 @@ extern void PushCurrentVideoSettings();
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern uint8 Exit;
|
extern uint8 Exit;
|
||||||
extern uint8 pale;
|
extern int default_palette_selection;
|
||||||
extern uint8 vsdip;
|
extern uint8 vsdip;
|
||||||
|
|
||||||
//#define FCEUDEF_DEBUGGER //mbg merge 7/17/06 - cleaning out conditional compiles
|
//#define FCEUDEF_DEBUGGER //mbg merge 7/17/06 - cleaning out conditional compiles
|
||||||
|
@ -18,10 +18,6 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "x6502.h"
|
#include "x6502.h"
|
||||||
#include "fceu.h"
|
#include "fceu.h"
|
||||||
@ -37,6 +33,10 @@
|
|||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
#include "movie.h"
|
#include "movie.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
// TODO: Add code to put a delay in between the time a disk is inserted
|
// TODO: Add code to put a delay in between the time a disk is inserted
|
||||||
// and the when it can be successfully read/written to. This should
|
// and the when it can be successfully read/written to. This should
|
||||||
// prevent writes to wrong places OR add code to prevent disk ejects
|
// prevent writes to wrong places OR add code to prevent disk ejects
|
||||||
@ -147,20 +147,26 @@ static void FDSInit(void) {
|
|||||||
SelectDisk = 0;
|
SelectDisk = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCEU_FDSInsert(void) {
|
void FCEU_FDSInsert(void)
|
||||||
if (FCEUI_EmulationPaused()) EmulationPaused |= 2;
|
{
|
||||||
|
if (TotalSides == 0)
|
||||||
|
{
|
||||||
|
FCEU_DispMessage("", 0);//FCEU_DispMessage("Not FDS; can't eject disk.", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FCEUI_EmulationPaused())
|
||||||
|
EmulationPaused |= EMULATIONPAUSED_FA;
|
||||||
|
|
||||||
if (FCEUMOV_Mode(MOVIEMODE_RECORD))
|
if (FCEUMOV_Mode(MOVIEMODE_RECORD))
|
||||||
FCEUMOV_AddCommand(FCEUNPCMD_FDSINSERT);
|
FCEUMOV_AddCommand(FCEUNPCMD_FDSINSERT);
|
||||||
|
|
||||||
if (TotalSides == 0) {
|
if (InDisk == 255)
|
||||||
FCEU_DispMessage("", 0);// remove text "Not FDS; can't eject disk."
|
{
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (InDisk == 255) {
|
|
||||||
//FCEU_DispMessage("Disk %d Side %s Inserted", 0, SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
|
//FCEU_DispMessage("Disk %d Side %s Inserted", 0, SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
|
||||||
InDisk = SelectDisk;
|
InDisk = SelectDisk;
|
||||||
} else {
|
} else
|
||||||
|
{
|
||||||
//FCEU_DispMessage("Disk %d Side %s Ejected", 0, SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
|
//FCEU_DispMessage("Disk %d Side %s Ejected", 0, SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
|
||||||
InDisk = 255;
|
InDisk = 255;
|
||||||
}
|
}
|
||||||
@ -171,22 +177,27 @@ void FCEU_FDSEject(void)
|
|||||||
InDisk=255;
|
InDisk=255;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
void FCEU_FDSSelect(void) {
|
void FCEU_FDSSelect(void)
|
||||||
if (FCEUI_EmulationPaused()) EmulationPaused |= 2;
|
{
|
||||||
|
if (TotalSides == 0)
|
||||||
|
{
|
||||||
|
FCEU_DispMessage("", 0); //FCEU_DispMessage("Not FDS; can't select disk.", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (InDisk != 255)
|
||||||
|
{
|
||||||
|
FCEU_DispMessage("", 0); //FCEU_DispMessage("Eject disk before selecting.", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FCEUI_EmulationPaused())
|
||||||
|
EmulationPaused |= EMULATIONPAUSED_FA;
|
||||||
|
|
||||||
if (FCEUMOV_Mode(MOVIEMODE_RECORD))
|
if (FCEUMOV_Mode(MOVIEMODE_RECORD))
|
||||||
FCEUMOV_AddCommand(FCEUNPCMD_FDSSELECT);
|
FCEUMOV_AddCommand(FCEUNPCMD_FDSSELECT);
|
||||||
|
|
||||||
if (TotalSides == 0) {
|
|
||||||
FCEU_DispMessage("", 0);//remove text "Not FDS; can't select disk."
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (InDisk != 255) {
|
|
||||||
FCEU_DispMessage("", 0); //remove text "Eject disk before selecting"
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SelectDisk = ((SelectDisk + 1) % TotalSides) & 3;
|
SelectDisk = ((SelectDisk + 1) % TotalSides) & 3;
|
||||||
FCEU_DispMessage("", 0); //("Disk %d Side %c Selected", 0, SelectDisk >> 1, (SelectDisk & 1) ? 'B' : 'A');
|
FCEU_DispMessage("", 0); //FCEU_DispMessage("Disk %d Side %c Selected", 0, SelectDisk >> 1, (SelectDisk & 1) ? 'B' : 'A');
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FDSFix(int a) {
|
static void FDSFix(int a) {
|
||||||
@ -753,13 +764,11 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
|
|||||||
|
|
||||||
CHRRAMSize = 8192;
|
CHRRAMSize = 8192;
|
||||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
|
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
|
||||||
memset(CHRRAM, 0, CHRRAMSize);
|
|
||||||
SetupCartCHRMapping(0, CHRRAM, CHRRAMSize, 1);
|
SetupCartCHRMapping(0, CHRRAM, CHRRAMSize, 1);
|
||||||
AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
|
AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
|
||||||
|
|
||||||
FDSRAMSize = 32768;
|
FDSRAMSize = 32768;
|
||||||
FDSRAM = (uint8*)FCEU_gmalloc(FDSRAMSize);
|
FDSRAM = (uint8*)FCEU_gmalloc(FDSRAMSize);
|
||||||
memset(FDSRAM, 0, FDSRAMSize);
|
|
||||||
SetupCartPRGMapping(1, FDSRAM, FDSRAMSize, 1);
|
SetupCartPRGMapping(1, FDSRAM, FDSRAMSize, 1);
|
||||||
AddExState(FDSRAM, FDSRAMSize, 0, "FDSR");
|
AddExState(FDSRAM, FDSRAMSize, 0, "FDSR");
|
||||||
|
|
||||||
|
@ -27,10 +27,6 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <zlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "utils/endian.h"
|
#include "utils/endian.h"
|
||||||
@ -49,6 +45,10 @@
|
|||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
#include "utils/xstring.h"
|
#include "utils/xstring.h"
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <zlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
bool bindSavestate = true; //Toggle that determines if a savestate filename will include the movie filename
|
bool bindSavestate = true; //Toggle that determines if a savestate filename will include the movie filename
|
||||||
|
@ -36,8 +36,10 @@ enum ESI
|
|||||||
SI_POWERPADB = 4,
|
SI_POWERPADB = 4,
|
||||||
SI_ARKANOID = 5,
|
SI_ARKANOID = 5,
|
||||||
SI_MOUSE = 6,
|
SI_MOUSE = 6,
|
||||||
|
SI_SNES = 7,
|
||||||
|
SI_SNES_MOUSE = 8,
|
||||||
|
|
||||||
SI_COUNT = SI_MOUSE
|
SI_COUNT = SI_SNES_MOUSE
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const char* ESI_Name(ESI esi)
|
inline const char* ESI_Name(ESI esi)
|
||||||
@ -50,7 +52,9 @@ inline const char* ESI_Name(ESI esi)
|
|||||||
"Power Pad A",
|
"Power Pad A",
|
||||||
"Power Pad B",
|
"Power Pad B",
|
||||||
"Arkanoid Paddle",
|
"Arkanoid Paddle",
|
||||||
"Mouse"
|
"Subor Mouse",
|
||||||
|
"SNES Pad",
|
||||||
|
"SNES Mouse"
|
||||||
};
|
};
|
||||||
|
|
||||||
if(esi >= SI_NONE && esi <= SI_COUNT)
|
if(esi >= SI_NONE && esi <= SI_COUNT)
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
{ 0x9b4bad37b5498992LL, "Gradius 2", INESB_HACKED },
|
{ 0x9b4bad37b5498992LL, "Gradius 2", INESB_HACKED },
|
||||||
{ 0xb068d4ac10ef848eLL, "Highway Star", INESB_HACKED },
|
{ 0xb068d4ac10ef848eLL, "Highway Star", INESB_HACKED },
|
||||||
{ 0xbf5175271e5019c3LL, "Kaiketsu Yanchamaru 3", INESB_HACKED },
|
{ 0xbf5175271e5019c3LL, "Kaiketsu Yanchamaru 3", INESB_HACKED },
|
||||||
|
{ 0x81c1de64550a1531LL, "Nobunaga no Yabou Zenkokuban", INESB_HACKED },
|
||||||
{ 0xfb4b508a236bbba3LL, "Salamander", INESB_HACKED },
|
{ 0xfb4b508a236bbba3LL, "Salamander", INESB_HACKED },
|
||||||
{ 0x1895afc6eef26c7dLL, "Super Mario Bros.", INESB_HACKED },
|
{ 0x1895afc6eef26c7dLL, "Super Mario Bros.", INESB_HACKED },
|
||||||
{ 0x3716c4bebf885344LL, "Super Mario Bros.", INESB_HACKED },
|
{ 0x3716c4bebf885344LL, "Super Mario Bros.", INESB_HACKED },
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
{0x02cc3973, 3, 1}, /* Ninja Kid */
|
{0x02cc3973, 3, 1}, /* Ninja Kid */
|
||||||
{0xbc065fc3, 3, 1}, /* Pipe Dream */
|
{0xbc065fc3, 3, 1}, /* Pipe Dream */
|
||||||
{0xc9ee15a7, 3, -1}, /* 3 is probably best. 41 WILL NOT WORK. */
|
{0xc9ee15a7, 3, -1}, /* 3 is probably best. 41 WILL NOT WORK. */
|
||||||
|
{0x13e09d7a, 4, 0}, /*Dragon Wars (U) (proto) - comes with erroneous 4-screen mirroring set*/
|
||||||
{0x22d6d5bd, 4, 1},
|
{0x22d6d5bd, 4, 1},
|
||||||
{0xd97c31b0, 4, 1}, //Rasaaru Ishii no Childs Quest (J)
|
{0xd97c31b0, 4, 1}, //Rasaaru Ishii no Childs Quest (J)
|
||||||
{0x404b2e8b, 4, 2}, /* Rad Racer 2 */
|
{0x404b2e8b, 4, 2}, /* Rad Racer 2 */
|
||||||
@ -83,7 +84,6 @@
|
|||||||
{0x6e68e31a, 16, 8}, /* Dragon Ball 3*/
|
{0x6e68e31a, 16, 8}, /* Dragon Ball 3*/
|
||||||
{0x33b899c9, 16, -1}, /* Dragon Ball - Dai Maou Fukkatsu (J) [!] */
|
{0x33b899c9, 16, -1}, /* Dragon Ball - Dai Maou Fukkatsu (J) [!] */
|
||||||
{0xa262a81f, 16, -1}, /* Rokudenashi Blues (J) */
|
{0xa262a81f, 16, -1}, /* Rokudenashi Blues (J) */
|
||||||
{0x286fcd20, 23, -1}, /* Ganbare Goemon Gaiden 2 - Tenka no Zaihou (J) [!] */
|
|
||||||
{0xe4a291ce, 23, -1}, /* World Hero (Unl) [!] */
|
{0xe4a291ce, 23, -1}, /* World Hero (Unl) [!] */
|
||||||
{0x51e9cd33, 23, -1}, /* World Hero (Unl) [b1] */
|
{0x51e9cd33, 23, -1}, /* World Hero (Unl) [b1] */
|
||||||
{0x105dd586, 27, -1}, /* Mi Hun Che variations... */
|
{0x105dd586, 27, -1}, /* Mi Hun Che variations... */
|
||||||
@ -257,10 +257,28 @@
|
|||||||
{0x345ee51a, 245, -1}, /* DQ4c */
|
{0x345ee51a, 245, -1}, /* DQ4c */
|
||||||
{0x57514c6c, 245, -1}, /* Yong Zhe Dou E Long - Dragon Quest VI (Ch) */
|
{0x57514c6c, 245, -1}, /* Yong Zhe Dou E Long - Dragon Quest VI (Ch) */
|
||||||
|
|
||||||
|
// added a new mask bit to define these mappers as a dupes of the UNIF format boards
|
||||||
|
|
||||||
{0x1d75fd35, 256|0x1000,-1}, /* 2-in-1 - Street Dance + Hit Mouse (Unl) [!] */
|
{0x1d75fd35, 256|0x1000,-1}, /* 2-in-1 - Street Dance + Hit Mouse (Unl) [!] */
|
||||||
{0x6eef8bb7, 257|0x1000,-1}, /* PEC-586 Chinese */
|
{0x6eef8bb7, 257|0x1000,-1}, /* PEC-586 Chinese */
|
||||||
{0xac7e98fb, 257|0x1000,-1}, /* PEC-586 Chinese No Tape Out */
|
{0xac7e98fb, 257|0x1000,-1}, /* PEC-586 Chinese No Tape Out */
|
||||||
{0x8d51a23b, 257|0x1000,-1}, /* [KeWang] Chao Ji Wu Bi Han Ka (C) V1 */
|
{0x8d51a23b, 257|0x1000,-1}, /* [KeWang] Chao Ji Wu Bi Han Ka (C) V1 */
|
||||||
{0x25c76773, 257|0x1000,-1}, /* [KeWang] Chao Ji Wu Bi Han Ka (C) V2 */
|
{0x25c76773, 257|0x1000,-1}, /* [KeWang] Chao Ji Wu Bi Han Ka (C) V2 */
|
||||||
|
{0x1ca9c322, 258|0x1000,-1}, /* Blood Of Jurassic (GD-98)(Unl) */
|
||||||
|
{0x2469c1ae, 259|0x1000,-1}, /* 150-in-1 Unchained FIGHT version */
|
||||||
|
|
||||||
|
{0x99d4464f, 260|0x1000,-1}, /* HP10xx/HP20xx board dumps */
|
||||||
|
{0xb72b2cf4, 260|0x1000,-1},
|
||||||
|
{0x4dc6107d, 260|0x1000,-1},
|
||||||
|
{0x0073dbd8, 260|0x1000,-1},
|
||||||
|
{0x3b098344, 260|0x1000,-1},
|
||||||
|
{0x1fc640c0, 260|0x1000,-1},
|
||||||
|
{0x2f1ad1fc, 260|0x1000,-1},
|
||||||
|
{0xa22214bb, 260|0x1000,-1},
|
||||||
|
{0x5dd9073b, 260|0x1000,-1},
|
||||||
|
{0x26a36cc2, 260|0x1000,-1},
|
||||||
|
{0xd1e52b37, 260|0x1000,-1},
|
||||||
|
{0x4d4a0e1b, 260|0x1000,-1},
|
||||||
|
{0xb6dd2c9d, 260|0x1000,-1},
|
||||||
|
|
||||||
{0x00000000, -1, -1}
|
{0x00000000, -1, -1}
|
||||||
|
@ -327,7 +327,7 @@ static void CheckHInfo(void) {
|
|||||||
{
|
{
|
||||||
#include "ines-correct.h"
|
#include "ines-correct.h"
|
||||||
};
|
};
|
||||||
int32 tofix = 0, x;
|
int32 tofix = 0, x, mask;
|
||||||
uint64 partialmd5 = 0;
|
uint64 partialmd5 = 0;
|
||||||
|
|
||||||
for (x = 0; x < 8; x++)
|
for (x = 0; x < 8; x++)
|
||||||
@ -361,9 +361,13 @@ static void CheckHInfo(void) {
|
|||||||
VROM = NULL;
|
VROM = NULL;
|
||||||
tofix |= 8;
|
tofix |= 8;
|
||||||
}
|
}
|
||||||
if (MapperNo != (moo[x].mapper & 0xFF)) {
|
if (moo[x].mapper & 0x1000)
|
||||||
|
mask = 0xFFF;
|
||||||
|
else
|
||||||
|
mask = 0xFF;
|
||||||
|
if (MapperNo != (moo[x].mapper & mask)) {
|
||||||
tofix |= 1;
|
tofix |= 1;
|
||||||
MapperNo = moo[x].mapper & 0xFF;
|
MapperNo = moo[x].mapper & mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (moo[x].mirror >= 0) {
|
if (moo[x].mirror >= 0) {
|
||||||
@ -561,7 +565,7 @@ static BMAPPINGLocal bmap[] = {
|
|||||||
{"FDS UNROM BOARD", 108, Mapper108_Init},
|
{"FDS UNROM BOARD", 108, Mapper108_Init},
|
||||||
// {"", 109, Mapper109_Init},
|
// {"", 109, Mapper109_Init},
|
||||||
// {"", 110, Mapper110_Init},
|
// {"", 110, Mapper110_Init},
|
||||||
// {"", 111, Mapper111_Init},
|
{"Cheapocabra", 111, Mapper111_Init},
|
||||||
{"ASDER/NTDEC BOARD", 112, Mapper112_Init},
|
{"ASDER/NTDEC BOARD", 112, Mapper112_Init},
|
||||||
{"HACKER/SACHEN BOARD", 113, Mapper113_Init},
|
{"HACKER/SACHEN BOARD", 113, Mapper113_Init},
|
||||||
{"MMC3 SG PROT. A", 114, Mapper114_Init},
|
{"MMC3 SG PROT. A", 114, Mapper114_Init},
|
||||||
@ -640,7 +644,7 @@ static BMAPPINGLocal bmap[] = {
|
|||||||
{"", 187, Mapper187_Init},
|
{"", 187, Mapper187_Init},
|
||||||
{"", 188, Mapper188_Init},
|
{"", 188, Mapper188_Init},
|
||||||
{"", 189, Mapper189_Init},
|
{"", 189, Mapper189_Init},
|
||||||
// {"", 190, Mapper190_Init},
|
{"", 190, Mapper190_Init},
|
||||||
{"", 191, Mapper191_Init},
|
{"", 191, Mapper191_Init},
|
||||||
{"TW MMC3+VRAM Rev. B", 192, Mapper192_Init},
|
{"TW MMC3+VRAM Rev. B", 192, Mapper192_Init},
|
||||||
{"NTDEC TC-112", 193, Mapper193_Init}, // War in the Gulf
|
{"NTDEC TC-112", 193, Mapper193_Init}, // War in the Gulf
|
||||||
@ -711,6 +715,18 @@ static BMAPPINGLocal bmap[] = {
|
|||||||
//-------- Mappers 512-767 is the Supplementary Ideographic Plane -----------
|
//-------- Mappers 512-767 is the Supplementary Ideographic Plane -----------
|
||||||
//-------- Mappers 3840-4095 are for rom dumps not publicly released --------
|
//-------- Mappers 3840-4095 are for rom dumps not publicly released --------
|
||||||
|
|
||||||
|
// An attempt to make working the UNIF BOARD ROMs in INES FORMAT
|
||||||
|
// I don't know if there a complete ines 2.0 mapper list exist, so if it does,
|
||||||
|
// just redefine these numbers to any others which isn't used before
|
||||||
|
// see the ines-correct.h files for the ROMs CHR list
|
||||||
|
|
||||||
|
{"ONE-BUS Systems", 256, UNLOneBus_Init},
|
||||||
|
{"PEC-586 Computer", 257, UNLPEC586Init},
|
||||||
|
{"158B Prot Board", 258, UNL158B_Init},
|
||||||
|
{"F-15 MMC3 Based", 259, BMCF15_Init},
|
||||||
|
{"HP10xx/H20xx Boards", 260, BMCHPxx_Init},
|
||||||
|
{"810544-CA-1", 261, BMC810544CA1_Init},
|
||||||
|
|
||||||
{"", 0, NULL}
|
{"", 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -845,7 +861,7 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
|
|||||||
FCEU_printf(" Total VRAM size: %d\n", iNESCart.vram_size + iNESCart.battery_vram_size);
|
FCEU_printf(" Total VRAM size: %d\n", iNESCart.vram_size + iNESCart.battery_vram_size);
|
||||||
if(head.ROM_type & 2)
|
if(head.ROM_type & 2)
|
||||||
{
|
{
|
||||||
FCEU_printf(" WRAM backked by battery: %d\n", iNESCart.battery_wram_size);
|
FCEU_printf(" WRAM backed by battery: %d\n", iNESCart.battery_wram_size);
|
||||||
FCEU_printf(" VRAM backed by battery: %d\n", iNESCart.battery_vram_size);
|
FCEU_printf(" VRAM backed by battery: %d\n", iNESCart.battery_vram_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -895,12 +911,15 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GameInterface = iNESGI;
|
GameInterface = iNESGI;
|
||||||
|
currCartInfo = &iNESCart;
|
||||||
FCEU_printf("\n");
|
FCEU_printf("\n");
|
||||||
|
|
||||||
// since apparently the iNES format doesn't store this information,
|
// since apparently the iNES format doesn't store this information,
|
||||||
// guess if the settings should be PAL or NTSC from the ROM name
|
// guess if the settings should be PAL or NTSC from the ROM name
|
||||||
// TODO: MD5 check against a list of all known PAL games instead?
|
// TODO: MD5 check against a list of all known PAL games instead?
|
||||||
if (OverwriteVidMode) {
|
if (iNES2) {
|
||||||
|
FCEUI_SetVidSystem(((head.TV_system & 3) == 1) ? 1 : 0);
|
||||||
|
} else if (OverwriteVidMode) {
|
||||||
if (strstr(name, "(E)") || strstr(name, "(e)")
|
if (strstr(name, "(E)") || strstr(name, "(e)")
|
||||||
|| strstr(name, "(Europe)") || strstr(name, "(PAL)")
|
|| strstr(name, "(Europe)") || strstr(name, "(PAL)")
|
||||||
|| strstr(name, "(F)") || strstr(name, "(f)")
|
|| strstr(name, "(F)") || strstr(name, "(f)")
|
||||||
@ -990,6 +1009,7 @@ static int iNES_Init(int num) {
|
|||||||
case 6:
|
case 6:
|
||||||
case 29:
|
case 29:
|
||||||
case 30:
|
case 30:
|
||||||
|
case 45:
|
||||||
case 96: CHRRAMSize = 32 * 1024; break;
|
case 96: CHRRAMSize = 32 * 1024; break;
|
||||||
case 176: CHRRAMSize = 128 * 1024; break;
|
case 176: CHRRAMSize = 128 * 1024; break;
|
||||||
default: CHRRAMSize = 8 * 1024; break;
|
default: CHRRAMSize = 8 * 1024; break;
|
||||||
@ -1004,9 +1024,19 @@ static int iNES_Init(int num) {
|
|||||||
FCEU_MemoryRand(VROM, CHRRAMSize);
|
FCEU_MemoryRand(VROM, CHRRAMSize);
|
||||||
|
|
||||||
UNIFchrrama = VROM;
|
UNIFchrrama = VROM;
|
||||||
|
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);
|
SetupCartCHRMapping(0, VROM, CHRRAMSize, 1);
|
||||||
AddExState(VROM, CHRRAMSize, 0, "CHRR");
|
AddExState(VROM, CHRRAMSize, 0, "CHRR");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (head.ROM_type & 8)
|
if (head.ROM_type & 8)
|
||||||
AddExState(ExtraNTARAM, 2048, 0, "EXNR");
|
AddExState(ExtraNTARAM, 2048, 0, "EXNR");
|
||||||
tmp->init(&iNESCart);
|
tmp->init(&iNESCart);
|
||||||
|
@ -177,6 +177,7 @@ void Mapper105_Init(CartInfo *);
|
|||||||
void Mapper106_Init(CartInfo *);
|
void Mapper106_Init(CartInfo *);
|
||||||
void Mapper107_Init(CartInfo *);
|
void Mapper107_Init(CartInfo *);
|
||||||
void Mapper108_Init(CartInfo *);
|
void Mapper108_Init(CartInfo *);
|
||||||
|
void Mapper111_Init(CartInfo *);
|
||||||
void Mapper112_Init(CartInfo *);
|
void Mapper112_Init(CartInfo *);
|
||||||
void Mapper113_Init(CartInfo *);
|
void Mapper113_Init(CartInfo *);
|
||||||
void Mapper114_Init(CartInfo *);
|
void Mapper114_Init(CartInfo *);
|
||||||
|
@ -62,6 +62,8 @@ extern INPUTC *FCEU_InitZapper(int w);
|
|||||||
extern INPUTC *FCEU_InitPowerpadA(int w);
|
extern INPUTC *FCEU_InitPowerpadA(int w);
|
||||||
extern INPUTC *FCEU_InitPowerpadB(int w);
|
extern INPUTC *FCEU_InitPowerpadB(int w);
|
||||||
extern INPUTC *FCEU_InitArkanoid(int w);
|
extern INPUTC *FCEU_InitArkanoid(int w);
|
||||||
|
extern INPUTC *FCEU_InitMouse(int w);
|
||||||
|
extern INPUTC *FCEU_InitSNESMouse(int w);
|
||||||
|
|
||||||
extern INPUTCFC *FCEU_InitArkanoidFC(void);
|
extern INPUTCFC *FCEU_InitArkanoidFC(void);
|
||||||
extern INPUTCFC *FCEU_InitSpaceShadow(void);
|
extern INPUTCFC *FCEU_InitSpaceShadow(void);
|
||||||
@ -88,6 +90,7 @@ extern bool movieSubtitles;
|
|||||||
|
|
||||||
static uint8 joy_readbit[2];
|
static uint8 joy_readbit[2];
|
||||||
uint8 joy[4]={0,0,0,0}; //HACK - should be static but movie needs it
|
uint8 joy[4]={0,0,0,0}; //HACK - should be static but movie needs it
|
||||||
|
uint16 snesjoy[4]={0,0,0,0}; //HACK - should be static but movie needs it
|
||||||
static uint8 LastStrobe;
|
static uint8 LastStrobe;
|
||||||
uint8 RawReg4016 = 0; // Joystick strobe (W)
|
uint8 RawReg4016 = 0; // Joystick strobe (W)
|
||||||
|
|
||||||
@ -107,6 +110,9 @@ static bool FSAttached = false;
|
|||||||
JOYPORT joyports[2] = { JOYPORT(0), JOYPORT(1) };
|
JOYPORT joyports[2] = { JOYPORT(0), JOYPORT(1) };
|
||||||
FCPORT portFC;
|
FCPORT portFC;
|
||||||
|
|
||||||
|
FILE* DumpInputFile;
|
||||||
|
FILE* PlayInputFile;
|
||||||
|
|
||||||
static DECLFR(JPRead)
|
static DECLFR(JPRead)
|
||||||
{
|
{
|
||||||
lagFlag = 0;
|
lagFlag = 0;
|
||||||
@ -139,6 +145,12 @@ static DECLFR(JPRead)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(PlayInputFile)
|
||||||
|
ret = fgetc(PlayInputFile);
|
||||||
|
|
||||||
|
if(DumpInputFile)
|
||||||
|
fputc(ret,DumpInputFile);
|
||||||
|
|
||||||
ret|=X.DB&0xC0;
|
ret|=X.DB&0xC0;
|
||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
@ -305,9 +317,64 @@ static void StrobeGP(int w)
|
|||||||
|
|
||||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
//SNES pad
|
||||||
|
|
||||||
|
static void UpdateSNES(int w, void *data, int arg)
|
||||||
|
{
|
||||||
|
//LUA NOT SUPPORTED YET
|
||||||
|
if(w==0)
|
||||||
|
{
|
||||||
|
snesjoy[0]= ((uint32 *)joyports[0].ptr)[0];
|
||||||
|
snesjoy[2]= ((uint32 *)joyports[0].ptr)[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snesjoy[1] = ((uint32 *)joyports[0].ptr)[1];
|
||||||
|
snesjoy[3] = ((uint32 *)joyports[0].ptr)[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LogSNES(int w, MovieRecord* mr)
|
||||||
|
{
|
||||||
|
//not supported for SNES pad right noe
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LoadSNES(int w, MovieRecord* mr)
|
||||||
|
{
|
||||||
|
//not supported for SNES pad right now
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint8 ReadSNES(int w)
|
||||||
|
{
|
||||||
|
//no fourscore support on snes (not clear how it would work)
|
||||||
|
|
||||||
|
uint8 ret;
|
||||||
|
|
||||||
|
if(joy_readbit[w]>=16)
|
||||||
|
ret = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = ((snesjoy[w]>>(joy_readbit[w]))&1);
|
||||||
|
}
|
||||||
|
if(!fceuindbg)
|
||||||
|
joy_readbit[w]++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void StrobeSNES(int w)
|
||||||
|
{
|
||||||
|
joy_readbit[w]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static INPUTC GPC={ReadGP,0,StrobeGP,UpdateGP,0,0,LogGP,LoadGP};
|
static INPUTC GPC={ReadGP,0,StrobeGP,UpdateGP,0,0,LogGP,LoadGP};
|
||||||
static INPUTC GPCVS={ReadGPVS,0,StrobeGP,UpdateGP,0,0,LogGP,LoadGP};
|
static INPUTC GPCVS={ReadGPVS,0,StrobeGP,UpdateGP,0,0,LogGP,LoadGP};
|
||||||
|
static INPUTC GPSNES={ReadSNES,0,StrobeSNES,UpdateSNES,0,0,LogSNES,LoadSNES};
|
||||||
|
|
||||||
void FCEU_DrawInput(uint8 *buf)
|
void FCEU_DrawInput(uint8 *buf)
|
||||||
{
|
{
|
||||||
@ -390,6 +457,9 @@ static void SetInputStuff(int port)
|
|||||||
joyports[port].driver= &GPC;
|
joyports[port].driver= &GPC;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SI_SNES:
|
||||||
|
joyports[port].driver= &GPSNES;
|
||||||
|
break;
|
||||||
case SI_ARKANOID:
|
case SI_ARKANOID:
|
||||||
joyports[port].driver=FCEU_InitArkanoid(port);
|
joyports[port].driver=FCEU_InitArkanoid(port);
|
||||||
break;
|
break;
|
||||||
@ -402,6 +472,12 @@ static void SetInputStuff(int port)
|
|||||||
case SI_POWERPADB:
|
case SI_POWERPADB:
|
||||||
joyports[port].driver=FCEU_InitPowerpadB(port);
|
joyports[port].driver=FCEU_InitPowerpadB(port);
|
||||||
break;
|
break;
|
||||||
|
case SI_MOUSE:
|
||||||
|
joyports[port].driver=FCEU_InitMouse(port);
|
||||||
|
break;
|
||||||
|
case SI_SNES_MOUSE:
|
||||||
|
joyports[port].driver=FCEU_InitSNESMouse(port);
|
||||||
|
break;
|
||||||
case SI_NONE:
|
case SI_NONE:
|
||||||
joyports[port].driver=&DummyJPort;
|
joyports[port].driver=&DummyJPort;
|
||||||
break;
|
break;
|
||||||
@ -665,10 +741,11 @@ static void RamSearchOpLTE(void);
|
|||||||
static void RamSearchOpGTE(void);
|
static void RamSearchOpGTE(void);
|
||||||
static void RamSearchOpEQ(void);
|
static void RamSearchOpEQ(void);
|
||||||
static void RamSearchOpNE(void);
|
static void RamSearchOpNE(void);
|
||||||
|
static void DebuggerStepInto(void);
|
||||||
static void FA_SkipLag(void);
|
static void FA_SkipLag(void);
|
||||||
static void OpenRom(void);
|
static void OpenRom(void);
|
||||||
static void CloseRom(void);
|
static void CloseRom(void);
|
||||||
static void ReloadRom(void);
|
void ReloadRom(void);
|
||||||
static void MovieSubtitleToggle(void);
|
static void MovieSubtitleToggle(void);
|
||||||
static void UndoRedoSavestate(void);
|
static void UndoRedoSavestate(void);
|
||||||
static void FCEUI_DoExit(void);
|
static void FCEUI_DoExit(void);
|
||||||
@ -687,6 +764,7 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
|
|||||||
{ EMUCMD_SCREENSHOT, EMUCMDTYPE_MISC, FCEUI_SaveSnapshot, 0, 0, "Screenshot", EMUCMDFLAG_TASEDITOR },
|
{ EMUCMD_SCREENSHOT, EMUCMDTYPE_MISC, FCEUI_SaveSnapshot, 0, 0, "Screenshot", EMUCMDFLAG_TASEDITOR },
|
||||||
{ EMUCMD_HIDE_MENU_TOGGLE, EMUCMDTYPE_MISC, FCEUD_HideMenuToggle, 0, 0, "Hide Menu Toggle", 0 },
|
{ EMUCMD_HIDE_MENU_TOGGLE, EMUCMDTYPE_MISC, FCEUD_HideMenuToggle, 0, 0, "Hide Menu Toggle", 0 },
|
||||||
{ EMUCMD_EXIT, EMUCMDTYPE_MISC, FCEUI_DoExit, 0, 0, "Exit", EMUCMDFLAG_TASEDITOR },
|
{ EMUCMD_EXIT, EMUCMDTYPE_MISC, FCEUI_DoExit, 0, 0, "Exit", EMUCMDFLAG_TASEDITOR },
|
||||||
|
|
||||||
{ EMUCMD_SPEED_SLOWEST, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Slowest Speed", EMUCMDFLAG_TASEDITOR },
|
{ EMUCMD_SPEED_SLOWEST, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Slowest Speed", EMUCMDFLAG_TASEDITOR },
|
||||||
{ EMUCMD_SPEED_SLOWER, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Speed Down", 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_NORMAL, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Normal Speed", EMUCMDFLAG_TASEDITOR },
|
||||||
@ -738,7 +816,6 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
|
|||||||
{ EMUCMD_MOVIE_STOP, EMUCMDTYPE_MOVIE, FCEUI_StopMovie, 0, 0, "Stop Movie", 0 },
|
{ 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_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_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_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_ICON_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUD_ToggleStatusIcon, 0, 0, "Toggle Status Icon", EMUCMDFLAG_TASEDITOR },
|
||||||
|
|
||||||
@ -768,6 +845,7 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
|
|||||||
{ EMUCMD_VSUNI_TOGGLE_DIP_7, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 7", 0 },
|
{ EMUCMD_VSUNI_TOGGLE_DIP_7, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 7", 0 },
|
||||||
{ EMUCMD_VSUNI_TOGGLE_DIP_8, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 8", 0 },
|
{ EMUCMD_VSUNI_TOGGLE_DIP_8, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 8", 0 },
|
||||||
{ EMUCMD_VSUNI_TOGGLE_DIP_9, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 9", 0 },
|
{ EMUCMD_VSUNI_TOGGLE_DIP_9, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 9", 0 },
|
||||||
|
|
||||||
{ EMUCMD_MISC_AUTOSAVE, EMUCMDTYPE_MISC, FCEUI_RewindToLastAutosave, 0, 0, "Load Last Auto-save", 0},
|
{ EMUCMD_MISC_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_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_1, EMUCMDTYPE_MISC, CommandUsePreset, 0, 0, "Use Input Preset 1", EMUCMDFLAG_TASEDITOR },
|
||||||
@ -776,6 +854,7 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
|
|||||||
{ EMUCMD_MISC_DISPLAY_BG_TOGGLE, EMUCMDTYPE_MISC, BackgroundDisplayToggle, 0, 0, "Toggle Background Display", 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_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_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_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_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_OPENCHEATS, EMUCMDTYPE_TOOL, LaunchCheats, 0, 0, "Open Cheats", EMUCMDFLAG_TASEDITOR },
|
||||||
@ -801,13 +880,16 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
|
|||||||
{ EMUCMD_TOOL_RAMSEARCHEQ, EMUCMDTYPE_TOOL, RamSearchOpEQ, 0, 0, "Ram Search - Equal", 0},
|
{ EMUCMD_TOOL_RAMSEARCHEQ, EMUCMDTYPE_TOOL, RamSearchOpEQ, 0, 0, "Ram Search - Equal", 0},
|
||||||
{ EMUCMD_TOOL_RAMSEARCHNE, EMUCMDTYPE_TOOL, RamSearchOpNE, 0, 0, "Ram Search - Not Equal", 0},
|
{ EMUCMD_TOOL_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_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_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_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_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_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_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_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_FPS_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_ToggleShowFPS, 0, 0, "Toggle FPS Display", EMUCMDFLAG_TASEDITOR },
|
||||||
|
{ EMUCMD_TOOL_DEBUGSTEPINTO, EMUCMDTYPE_TOOL, DebuggerStepInto, 0, 0, "Debugger - Step Into", EMUCMDFLAG_TASEDITOR },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_EMU_CMDS (sizeof(FCEUI_CommandTable)/sizeof(FCEUI_CommandTable[0]))
|
#define NUM_EMU_CMDS (sizeof(FCEUI_CommandTable)/sizeof(FCEUI_CommandTable[0]))
|
||||||
@ -1119,6 +1201,17 @@ static void RamSearchOpNE(void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DebuggerStepInto()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
if (GameInfo)
|
||||||
|
{
|
||||||
|
extern void DoDebuggerStepInto();
|
||||||
|
DoDebuggerStepInto();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void FA_SkipLag(void)
|
static void FA_SkipLag(void)
|
||||||
{
|
{
|
||||||
frameAdvanceLagSkip ^= 1;
|
frameAdvanceLagSkip ^= 1;
|
||||||
@ -1139,7 +1232,7 @@ static void CloseRom(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ReloadRom(void)
|
void ReloadRom(void)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
|
|
||||||
void LagCounterToggle(void);
|
void LagCounterToggle(void);
|
||||||
|
|
||||||
|
extern FILE* PlayInputFile;
|
||||||
|
extern FILE* DumpInputFile;
|
||||||
|
|
||||||
|
|
||||||
class MovieRecord;
|
class MovieRecord;
|
||||||
|
|
||||||
//MBG TODO - COMBINE THESE INPUTC AND INPUTCFC
|
//MBG TODO - COMBINE THESE INPUTC AND INPUTCFC
|
||||||
@ -242,6 +246,7 @@ enum EMUCMD
|
|||||||
//-----------------------------
|
//-----------------------------
|
||||||
//keep adding these in order of newness or else the hotkey binding configs will get messed up...
|
//keep adding these in order of newness or else the hotkey binding configs will get messed up...
|
||||||
EMUCMD_FPS_DISPLAY_TOGGLE,
|
EMUCMD_FPS_DISPLAY_TOGGLE,
|
||||||
|
EMUCMD_TOOL_DEBUGSTEPINTO,
|
||||||
|
|
||||||
EMUCMD_MAX
|
EMUCMD_MAX
|
||||||
};
|
};
|
||||||
|
@ -18,64 +18,66 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// implementation of Subor Mouse
|
||||||
|
// used in Educational Computer 2000
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "share.h"
|
#include "share.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32 mzx, mzy, mzxold, mzyold;
|
uint8 latch;
|
||||||
uint32 readbit;
|
int32 dx,dy;
|
||||||
uint32 data;
|
uint32 mb;
|
||||||
} MOUSE;
|
} MOUSE;
|
||||||
|
|
||||||
static MOUSE Mouse;
|
static MOUSE Mouse;
|
||||||
|
|
||||||
|
// since this game only picks up 1 mickey per frame,
|
||||||
|
// allow a single delta to spread out over a few frames
|
||||||
|
// to make it easier to move.
|
||||||
|
const int INERTIA = 32;
|
||||||
|
|
||||||
static void StrobeMOUSE(int w)
|
static void StrobeMOUSE(int w)
|
||||||
{
|
{
|
||||||
Mouse.readbit=0;
|
Mouse.latch = Mouse.mb & 0x03;
|
||||||
|
|
||||||
|
int32 dx = Mouse.dx;
|
||||||
|
int32 dy = Mouse.dy;
|
||||||
|
|
||||||
|
if (dx > 0) { Mouse.latch |= (0x2 << 2); --Mouse.dx; }
|
||||||
|
else if (dx < 0) { Mouse.latch |= (0x3 << 2); ++Mouse.dx; }
|
||||||
|
if (dy > 0) { Mouse.latch |= (0x2 << 4); --Mouse.dy; }
|
||||||
|
else if (dy < 0) { Mouse.latch |= (0x3 << 4); ++Mouse.dy; }
|
||||||
|
|
||||||
|
//FCEU_printf("Subor Mouse: %02X\n",Mouse.latch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8 ReadMOUSE(int w)
|
static uint8 ReadMOUSE(int w)
|
||||||
{
|
{
|
||||||
uint8 ret=0;
|
uint8 result = Mouse.latch & 0x01;
|
||||||
if(Mouse.readbit>=8)
|
Mouse.latch = (Mouse.latch >> 1) | 0x80;
|
||||||
ret|=1;
|
return result;
|
||||||
else
|
|
||||||
{
|
|
||||||
ret|=(Mouse.data>>Mouse.readbit)&1;
|
|
||||||
if(!fceuindbg)
|
|
||||||
Mouse.readbit++;
|
|
||||||
}
|
|
||||||
return(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UpdateMOUSE(int w, void *data, int arg)
|
static void UpdateMOUSE(int w, void *data, int arg)
|
||||||
{
|
{
|
||||||
uint32 *ptr=(uint32*)data;
|
uint32 *ptr=(uint32*)data;
|
||||||
Mouse.data=0;
|
Mouse.dx += ptr[0]; ptr[0] = 0;
|
||||||
Mouse.mzxold=Mouse.mzx;
|
Mouse.dy += ptr[1]; ptr[1] = 0;
|
||||||
Mouse.mzyold=Mouse.mzy;
|
Mouse.mb = ptr[2];
|
||||||
Mouse.mzx=ptr[0];
|
|
||||||
Mouse.mzy=ptr[1];
|
if (Mouse.dx > INERTIA) Mouse.dx = INERTIA;
|
||||||
Mouse.data|=ptr[2];
|
else if (Mouse.dx < -INERTIA) Mouse.dx = -INERTIA;
|
||||||
if((Mouse.mzxold-Mouse.mzx)>0)
|
|
||||||
Mouse.data|=0x0C;
|
if (Mouse.dy > INERTIA) Mouse.dy = INERTIA;
|
||||||
else if((Mouse.mzxold-Mouse.mzx)<0)
|
else if (Mouse.dy < -INERTIA) Mouse.dy = -INERTIA;
|
||||||
Mouse.data|=0x04;
|
|
||||||
if((Mouse.mzyold-Mouse.mzy)>0)
|
|
||||||
Mouse.data|=0x30;
|
|
||||||
else if((Mouse.mzyold-Mouse.mzy)<0)
|
|
||||||
Mouse.data|=0x10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static INPUTC MOUSEC={ReadMOUSE,0,StrobeMOUSE,UpdateMOUSE,0,0};
|
static INPUTC MOUSEC={ReadMOUSE,0,StrobeMOUSE,UpdateMOUSE,0,0};
|
||||||
|
|
||||||
INPUTC *FCEU_InitMouse(int w)
|
INPUTC *FCEU_InitMouse(int w)
|
||||||
{
|
{
|
||||||
Mouse.mzx=0;
|
memset(&Mouse,0,sizeof(Mouse));
|
||||||
Mouse.mzy=0;
|
|
||||||
Mouse.mzxold=0;
|
|
||||||
Mouse.mzyold=0;
|
|
||||||
Mouse.data=0;
|
|
||||||
return(&MOUSEC);
|
return(&MOUSEC);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "video.h"
|
#include "video.h"
|
||||||
#include "movie.h"
|
#include "movie.h"
|
||||||
|
#include "cart.h"
|
||||||
#include "fds.h"
|
#include "fds.h"
|
||||||
#include "vsuni.h"
|
#include "vsuni.h"
|
||||||
#ifdef _S9XLUA_H
|
#ifdef _S9XLUA_H
|
||||||
@ -34,6 +35,9 @@ extern void AddRecentMovieFile(const char *filename);
|
|||||||
extern bool mustEngageTaseditor;
|
extern bool mustEngageTaseditor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern int RAMInitOption;
|
||||||
|
extern int RAMInitSeed;
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -107,7 +111,6 @@ int currRerecordCount; // Keep the global value
|
|||||||
|
|
||||||
char lagcounterbuf[32] = {0};
|
char lagcounterbuf[32] = {0};
|
||||||
|
|
||||||
|
|
||||||
#ifdef GEKKO
|
#ifdef GEKKO
|
||||||
void MovieData::clearRecordRange(int start, int len) { }
|
void MovieData::clearRecordRange(int start, int len) { }
|
||||||
void MovieData::eraseRecords(int at, int frames) { }
|
void MovieData::eraseRecords(int at, int frames) { }
|
||||||
@ -454,8 +457,11 @@ void MovieRecord::dump(MovieData* md, EMUFILE* os, int index)
|
|||||||
MovieData::MovieData()
|
MovieData::MovieData()
|
||||||
: version(MOVIE_VERSION)
|
: version(MOVIE_VERSION)
|
||||||
, emuVersion(FCEU_VERSION_NUMERIC)
|
, emuVersion(FCEU_VERSION_NUMERIC)
|
||||||
|
, fds(false)
|
||||||
, palFlag(false)
|
, palFlag(false)
|
||||||
, PPUflag(false)
|
, PPUflag(false)
|
||||||
|
, RAMInitOption(0)
|
||||||
|
, RAMInitSeed(0)
|
||||||
, rerecordCount(0)
|
, rerecordCount(0)
|
||||||
, binaryFlag(false)
|
, binaryFlag(false)
|
||||||
, loadFrameCount(-1)
|
, loadFrameCount(-1)
|
||||||
@ -476,6 +482,10 @@ void MovieData::installValue(std::string& key, std::string& val)
|
|||||||
installInt(val,fds);
|
installInt(val,fds);
|
||||||
else if(key == "NewPPU")
|
else if(key == "NewPPU")
|
||||||
installBool(val,PPUflag);
|
installBool(val,PPUflag);
|
||||||
|
else if(key == "RAMInitOption")
|
||||||
|
installInt(val,RAMInitOption);
|
||||||
|
else if(key == "RAMInitSeed")
|
||||||
|
installInt(val,RAMInitSeed);
|
||||||
else if(key == "version")
|
else if(key == "version")
|
||||||
installInt(val,version);
|
installInt(val,version);
|
||||||
else if(key == "emuVersion")
|
else if(key == "emuVersion")
|
||||||
@ -516,6 +526,16 @@ void MovieData::installValue(std::string& key, std::string& val)
|
|||||||
StringToBytes(val,&savestate[0],len); // decodes either base64 or hex
|
StringToBytes(val,&savestate[0],len); // decodes either base64 or hex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(key == "saveram")
|
||||||
|
{
|
||||||
|
int len = Base64StringToBytesLength(val);
|
||||||
|
if(len == -1) len = HexStringToBytesLength(val); // wasn't base64, try hex
|
||||||
|
if(len >= 1)
|
||||||
|
{
|
||||||
|
saveram.resize(len);
|
||||||
|
StringToBytes(val,&saveram[0],len); // decodes either base64 or hex
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (key == "length")
|
else if (key == "length")
|
||||||
{
|
{
|
||||||
installInt(val, loadFrameCount);
|
installInt(val, loadFrameCount);
|
||||||
@ -539,6 +559,8 @@ int MovieData::dump(EMUFILE *os, bool binary)
|
|||||||
os->fprintf("port2 %d\n" , ports[2] );
|
os->fprintf("port2 %d\n" , ports[2] );
|
||||||
os->fprintf("FDS %d\n" , fds?1:0 );
|
os->fprintf("FDS %d\n" , fds?1:0 );
|
||||||
os->fprintf("NewPPU %d\n" , PPUflag?1:0 );
|
os->fprintf("NewPPU %d\n" , PPUflag?1:0 );
|
||||||
|
os->fprintf("RAMInitOption %d\n", RAMInitOption);
|
||||||
|
os->fprintf("RAMInitSeed %d\n", RAMInitSeed);
|
||||||
|
|
||||||
for(uint32 i=0;i<comments.size();i++)
|
for(uint32 i=0;i<comments.size();i++)
|
||||||
os->fprintf("comment %s\n" , wcstombs(comments[i]).c_str() );
|
os->fprintf("comment %s\n" , wcstombs(comments[i]).c_str() );
|
||||||
@ -552,6 +574,9 @@ int MovieData::dump(EMUFILE *os, bool binary)
|
|||||||
if(savestate.size())
|
if(savestate.size())
|
||||||
os->fprintf("savestate %s\n" , BytesToString(&savestate[0],savestate.size()).c_str() );
|
os->fprintf("savestate %s\n" , BytesToString(&savestate[0],savestate.size()).c_str() );
|
||||||
|
|
||||||
|
if(saveram.size())
|
||||||
|
os->fprintf("saveram %s\n" , BytesToString(&saveram[0],saveram.size()).c_str() );
|
||||||
|
|
||||||
if (this->loadFrameCount >= 0)
|
if (this->loadFrameCount >= 0)
|
||||||
os->fprintf("length %d\n" , this->loadFrameCount);
|
os->fprintf("length %d\n" , this->loadFrameCount);
|
||||||
|
|
||||||
@ -831,6 +856,8 @@ void FCEUI_StopMovie()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool bogorf;
|
||||||
|
|
||||||
void poweron(bool shouldDisableBatteryLoading)
|
void poweron(bool shouldDisableBatteryLoading)
|
||||||
{
|
{
|
||||||
//// make a for-movie-recording power-on clear the game's save data, too
|
//// make a for-movie-recording power-on clear the game's save data, too
|
||||||
@ -855,9 +882,9 @@ void poweron(bool shouldDisableBatteryLoading)
|
|||||||
//suppressAddPowerCommand=0;
|
//suppressAddPowerCommand=0;
|
||||||
|
|
||||||
extern int disableBatteryLoading;
|
extern int disableBatteryLoading;
|
||||||
disableBatteryLoading = 1;
|
if(!bogorf) disableBatteryLoading = 1;
|
||||||
PowerNES();
|
PowerNES();
|
||||||
disableBatteryLoading = 0;
|
if(!bogorf) disableBatteryLoading = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCEUMOV_CreateCleanMovie()
|
void FCEUMOV_CreateCleanMovie()
|
||||||
@ -874,6 +901,8 @@ void FCEUMOV_CreateCleanMovie()
|
|||||||
currMovieData.ports[2] = portFC.type;
|
currMovieData.ports[2] = portFC.type;
|
||||||
currMovieData.fds = isFDS;
|
currMovieData.fds = isFDS;
|
||||||
currMovieData.PPUflag = (newppu != 0);
|
currMovieData.PPUflag = (newppu != 0);
|
||||||
|
currMovieData.RAMInitOption = RAMInitOption;
|
||||||
|
currMovieData.RAMInitSeed = RAMInitSeed;
|
||||||
}
|
}
|
||||||
void FCEUMOV_ClearCommands()
|
void FCEUMOV_ClearCommands()
|
||||||
{
|
{
|
||||||
@ -897,6 +926,59 @@ void MovieData::dumpSavestateTo(std::vector<uint8>* buf, int compressionLevel)
|
|||||||
ms.trim();
|
ms.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MovieData::loadSaveramFrom(std::vector<uint8>* buf)
|
||||||
|
{
|
||||||
|
EMUFILE_MEMORY ms(buf);
|
||||||
|
|
||||||
|
bool hasBattery = !!ms.read32le();
|
||||||
|
if(hasBattery != !!currCartInfo->battery)
|
||||||
|
{
|
||||||
|
FCEU_PrintError("movie battery load mismatch 1");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0;i<4;i++)
|
||||||
|
{
|
||||||
|
int len = ms.read32le();
|
||||||
|
|
||||||
|
if(!currCartInfo->SaveGame[i] && len!=0)
|
||||||
|
{
|
||||||
|
FCEU_PrintError("movie battery load mismatch 2");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(currCartInfo->SaveGameLen[i] != len)
|
||||||
|
{
|
||||||
|
FCEU_PrintError("movie battery load mismatch 3");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ms.fread(currCartInfo->SaveGame[i], len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovieData::dumpSaveramTo(std::vector<uint8>* buf, int compressionLevel)
|
||||||
|
{
|
||||||
|
EMUFILE_MEMORY ms(buf);
|
||||||
|
|
||||||
|
ms.write32le(currCartInfo->battery?1:0);
|
||||||
|
for(int i=0;i<4;i++)
|
||||||
|
{
|
||||||
|
if(!currCartInfo->SaveGame[i])
|
||||||
|
{
|
||||||
|
ms.write32le((u32)0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ms.write32le(currCartInfo->SaveGameLen[i]);
|
||||||
|
ms.fwrite(currCartInfo->SaveGame[i], currCartInfo->SaveGameLen[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//begin playing an existing movie
|
//begin playing an existing movie
|
||||||
bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
|
bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
|
||||||
{
|
{
|
||||||
@ -938,6 +1020,9 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
|
|||||||
LoadSubtitles(currMovieData);
|
LoadSubtitles(currMovieData);
|
||||||
delete fp;
|
delete fp;
|
||||||
|
|
||||||
|
RAMInitOption = currMovieData.RAMInitOption;
|
||||||
|
RAMInitSeed = currMovieData.RAMInitSeed;
|
||||||
|
|
||||||
freshMovie = true; //Movie has been loaded, so it must be unaltered
|
freshMovie = true; //Movie has been loaded, so it must be unaltered
|
||||||
if (bindSavestate) AutoSS = false; //If bind savestate to movie is true, then their isn't a valid auto-save to load, so flag it
|
if (bindSavestate) AutoSS = false; //If bind savestate to movie is true, then their isn't a valid auto-save to load, so flag it
|
||||||
//fully reload the game to reinitialize everything before playing any movie
|
//fully reload the game to reinitialize everything before playing any movie
|
||||||
@ -949,7 +1034,14 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
|
|||||||
movieFromPoweron = false;
|
movieFromPoweron = false;
|
||||||
bool success = MovieData::loadSavestateFrom(&currMovieData.savestate);
|
bool success = MovieData::loadSavestateFrom(&currMovieData.savestate);
|
||||||
if(!success) return true; //adelikat: I guess return true here? False is only for a bad movie filename, if it got this far the file was good?
|
if(!success) return true; //adelikat: I guess return true here? False is only for a bad movie filename, if it got this far the file was good?
|
||||||
} else {
|
}
|
||||||
|
else if(currMovieData.saveram.size())
|
||||||
|
{
|
||||||
|
movieFromPoweron = true;
|
||||||
|
bool success = MovieData::loadSaveramFrom(&currMovieData.saveram);
|
||||||
|
if(!success) return true; //adelikat: I guess return true here? False is only for a bad movie filename, if it got this far the file was good?
|
||||||
|
}
|
||||||
|
else {
|
||||||
movieFromPoweron = true;
|
movieFromPoweron = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -960,6 +1052,8 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
|
|||||||
else
|
else
|
||||||
FCEUI_SetVidSystem(0);
|
FCEUI_SetVidSystem(0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//force the input configuration stored in the movie to apply
|
//force the input configuration stored in the movie to apply
|
||||||
FCEUD_SetInput(currMovieData.fourscore, currMovieData.microphone, (ESI)currMovieData.ports[0], (ESI)currMovieData.ports[1], (ESIFC)currMovieData.ports[2]);
|
FCEUD_SetInput(currMovieData.fourscore, currMovieData.microphone, (ESI)currMovieData.ports[0], (ESI)currMovieData.ports[1], (ESIFC)currMovieData.ports[2]);
|
||||||
|
|
||||||
@ -1027,7 +1121,15 @@ void FCEUI_SaveMovie(const char *fname, EMOVIE_FLAG flags, std::wstring author)
|
|||||||
movieFromPoweron = true;
|
movieFromPoweron = true;
|
||||||
poweron(true);
|
poweron(true);
|
||||||
}
|
}
|
||||||
else
|
else if(flags & MOVIE_FLAG_FROM_SAVERAM)
|
||||||
|
{
|
||||||
|
movieFromPoweron = true;
|
||||||
|
MovieData::dumpSaveramTo(&currMovieData.saveram,Z_NO_COMPRESSION); //i guess with this there's a chance someone could hack the file, at least, so maybe it's helpfu
|
||||||
|
bogorf = true;
|
||||||
|
poweron(false);
|
||||||
|
bogorf = false;
|
||||||
|
}
|
||||||
|
else //from savestate
|
||||||
{
|
{
|
||||||
movieFromPoweron = false;
|
movieFromPoweron = false;
|
||||||
MovieData::dumpSavestateTo(&currMovieData.savestate,Z_BEST_COMPRESSION);
|
MovieData::dumpSavestateTo(&currMovieData.savestate,Z_BEST_COMPRESSION);
|
||||||
@ -1481,7 +1583,7 @@ void FCEUMOV_IncrementRerecordCount()
|
|||||||
else
|
else
|
||||||
currMovieData.rerecordCount++;
|
currMovieData.rerecordCount++;
|
||||||
#else
|
#else
|
||||||
if (movieMode != MOVIEMODE_TASEDITOR)currRerecordCount++;
|
if (movieMode != MOVIEMODE_TASEDITOR)
|
||||||
currRerecordCount++;
|
currRerecordCount++;
|
||||||
else
|
else
|
||||||
currMovieData.rerecordCount++;
|
currMovieData.rerecordCount++;
|
||||||
@ -1627,6 +1729,8 @@ bool FCEUI_MovieGetInfo(FCEUFILE* fp, MOVIE_INFO& info, bool skipFrameCount)
|
|||||||
info.reset = false; //Soft-reset isn't used from starting movies anymore, so this will be false, better for FCEUFILE to have that info (as |1| on the first frame indicates it
|
info.reset = false; //Soft-reset isn't used from starting movies anymore, so this will be false, better for FCEUFILE to have that info (as |1| on the first frame indicates it
|
||||||
info.pal = md.palFlag;
|
info.pal = md.palFlag;
|
||||||
info.ppuflag = md.PPUflag;
|
info.ppuflag = md.PPUflag;
|
||||||
|
info.RAMInitOption = md.RAMInitOption;
|
||||||
|
info.RAMInitSeed = md.RAMInitSeed;
|
||||||
info.nosynchack = true;
|
info.nosynchack = true;
|
||||||
info.num_frames = md.records.size();
|
info.num_frames = md.records.size();
|
||||||
info.md5_of_rom_used = md.romChecksum;
|
info.md5_of_rom_used = md.romChecksum;
|
||||||
|
@ -23,13 +23,15 @@ enum EMOVIE_FLAG
|
|||||||
|
|
||||||
MOVIE_FLAG_PAL = (1<<2),
|
MOVIE_FLAG_PAL = (1<<2),
|
||||||
|
|
||||||
//movie was recorded from poweron. the alternative is from a savestate (or from reset)
|
//movie was recorded from poweron. the alternative is from a savestate (or from reset). OR from saveram.
|
||||||
MOVIE_FLAG_FROM_POWERON = (1<<3),
|
MOVIE_FLAG_FROM_POWERON = (1<<3),
|
||||||
|
|
||||||
// set in newer version, used for old movie compatibility
|
// set in newer version, used for old movie compatibility
|
||||||
//TODO - only use this flag to print a warning that the sync might be bad
|
//TODO - only use this flag to print a warning that the sync might be bad
|
||||||
//so that we can get rid of the sync hack code
|
//so that we can get rid of the sync hack code
|
||||||
MOVIE_FLAG_NOSYNCHACK = (1<<4)
|
MOVIE_FLAG_NOSYNCHACK = (1<<4),
|
||||||
|
|
||||||
|
MOVIE_FLAG_FROM_SAVERAM = (1<<5)
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -42,6 +44,7 @@ typedef struct
|
|||||||
uint32 emu_version_used; // 9813 = 0.98.13
|
uint32 emu_version_used; // 9813 = 0.98.13
|
||||||
MD5DATA md5_of_rom_used;
|
MD5DATA md5_of_rom_used;
|
||||||
std::string name_of_rom_used;
|
std::string name_of_rom_used;
|
||||||
|
int RAMInitOption, RAMInitSeed;
|
||||||
|
|
||||||
std::vector<std::wstring> comments;
|
std::vector<std::wstring> comments;
|
||||||
std::vector<std::string> subtitles;
|
std::vector<std::string> subtitles;
|
||||||
@ -177,6 +180,7 @@ public:
|
|||||||
MD5DATA romChecksum;
|
MD5DATA romChecksum;
|
||||||
std::string romFilename;
|
std::string romFilename;
|
||||||
std::vector<uint8> savestate;
|
std::vector<uint8> savestate;
|
||||||
|
std::vector<uint8> saveram;
|
||||||
std::vector<MovieRecord> records;
|
std::vector<MovieRecord> records;
|
||||||
std::vector<std::wstring> comments;
|
std::vector<std::wstring> comments;
|
||||||
std::vector<std::string> subtitles;
|
std::vector<std::string> subtitles;
|
||||||
@ -198,6 +202,8 @@ public:
|
|||||||
|
|
||||||
int getNumRecords() { return records.size(); }
|
int getNumRecords() { return records.size(); }
|
||||||
|
|
||||||
|
int RAMInitOption, RAMInitSeed;
|
||||||
|
|
||||||
class TDictionary : public std::map<std::string,std::string>
|
class TDictionary : public std::map<std::string,std::string>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -238,6 +244,9 @@ public:
|
|||||||
static bool loadSavestateFrom(std::vector<uint8>* buf);
|
static bool loadSavestateFrom(std::vector<uint8>* buf);
|
||||||
static void dumpSavestateTo(std::vector<uint8>* buf, int compressionLevel);
|
static void dumpSavestateTo(std::vector<uint8>* buf, int compressionLevel);
|
||||||
|
|
||||||
|
static bool loadSaveramFrom(std::vector<uint8>* buf);
|
||||||
|
static void dumpSaveramTo(std::vector<uint8>* buf, int compressionLevel);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void installInt(std::string& val, int& var)
|
void installInt(std::string& val, int& var)
|
||||||
{
|
{
|
||||||
|
@ -119,7 +119,7 @@ int FCEUNET_SendFile(uint8 cmd, char *fn)
|
|||||||
|
|
||||||
if(!(fp=FCEUD_UTF8fopen(fn,"rb"))) return(0);
|
if(!(fp=FCEUD_UTF8fopen(fn,"rb"))) return(0);
|
||||||
|
|
||||||
fstat(fileno(fp),&sb);
|
FCEUX_fstat(fileno(fp),&sb);
|
||||||
len = sb.st_size;
|
len = sb.st_size;
|
||||||
buf = (char*)FCEU_dmalloc(len); //mbg merge 7/17/06 added cast
|
buf = (char*)FCEU_dmalloc(len); //mbg merge 7/17/06 added cast
|
||||||
fread(buf, 1, len, fp);
|
fread(buf, 1, len, fp);
|
||||||
|
@ -482,6 +482,7 @@ void DrawNSF(uint8 *XBuf)
|
|||||||
if(vismode==0) return;
|
if(vismode==0) return;
|
||||||
|
|
||||||
memset(XBuf,0,256*240);
|
memset(XBuf,0,256*240);
|
||||||
|
memset(XDBuf,0,256*240);
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -567,13 +568,14 @@ void DrawNSF(uint8 *XBuf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawTextTrans(ClipSidesOffset+XBuf+10*256+4+(((31-strlen((char*)NSFHeader.SongName))<<2)), 256, NSFHeader.SongName, 6);
|
static const int kFgColor = 1;
|
||||||
DrawTextTrans(ClipSidesOffset+XBuf+26*256+4+(((31-strlen((char*)NSFHeader.Artist))<<2)), 256,NSFHeader.Artist, 6);
|
DrawTextTrans(ClipSidesOffset+XBuf+10*256+4+(((31-strlen((char*)NSFHeader.SongName))<<2)), 256, NSFHeader.SongName, kFgColor);
|
||||||
DrawTextTrans(ClipSidesOffset+XBuf+42*256+4+(((31-strlen((char*)NSFHeader.Copyright))<<2)), 256,NSFHeader.Copyright, 6);
|
DrawTextTrans(ClipSidesOffset+XBuf+26*256+4+(((31-strlen((char*)NSFHeader.Artist))<<2)), 256,NSFHeader.Artist, kFgColor);
|
||||||
|
DrawTextTrans(ClipSidesOffset+XBuf+42*256+4+(((31-strlen((char*)NSFHeader.Copyright))<<2)), 256,NSFHeader.Copyright, kFgColor);
|
||||||
|
|
||||||
DrawTextTrans(ClipSidesOffset+XBuf+70*256+4+(((31-strlen("Song:"))<<2)), 256, (uint8*)"Song:", 6);
|
DrawTextTrans(ClipSidesOffset+XBuf+70*256+4+(((31-strlen("Song:"))<<2)), 256, (uint8*)"Song:", kFgColor);
|
||||||
sprintf(snbuf,"<%d/%d>",CurrentSong,NSFHeader.TotalSongs);
|
sprintf(snbuf,"<%d/%d>",CurrentSong,NSFHeader.TotalSongs);
|
||||||
DrawTextTrans(XBuf+82*256+4+(((31-strlen(snbuf))<<2)), 256, (uint8*)snbuf, 6);
|
DrawTextTrans(XBuf+82*256+4+(((31-strlen(snbuf))<<2)), 256, (uint8*)snbuf, kFgColor);
|
||||||
|
|
||||||
{
|
{
|
||||||
static uint8 last=0;
|
static uint8 last=0;
|
||||||
|
@ -31,8 +31,6 @@
|
|||||||
#include "palette.h"
|
#include "palette.h"
|
||||||
#include "palettes/palettes.h"
|
#include "palettes/palettes.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
#define M_PI 3.14159265358979323846
|
#define M_PI 3.14159265358979323846
|
||||||
#endif
|
#endif
|
||||||
@ -42,24 +40,25 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
static int ntsccol=0;
|
bool force_grayscale = false;
|
||||||
|
|
||||||
|
pal palette_game[64*8]; //custom palette for an individual game. (formerly palettei)
|
||||||
|
pal palette_user[64*8]; //user's overridden palette (formerly palettec)
|
||||||
|
pal palette_ntsc[64*8]; //mathematically generated NTSC palette (formerly paletten)
|
||||||
|
|
||||||
|
static bool palette_game_available; //whether palette_game is available
|
||||||
|
static bool palette_user_available; //whether palette_user is available
|
||||||
|
|
||||||
|
//ntsc parameters:
|
||||||
|
bool ntsccol_enable = false; //whether NTSC palette is selected
|
||||||
static int ntsctint = 46+10;
|
static int ntsctint = 46+10;
|
||||||
static int ntschue = 72;
|
static int ntschue = 72;
|
||||||
|
|
||||||
bool force_grayscale = false;
|
//the default basic palette
|
||||||
|
int default_palette_selection = 0;
|
||||||
|
|
||||||
/* These are dynamically filled/generated palettes: */
|
//library of default palettes
|
||||||
pal palettei[64]; // Custom palette for an individual game.
|
static pal *default_palette[8]=
|
||||||
pal palettec[64]; // Custom "global" palette.
|
|
||||||
pal paletten[64]; // Mathematically generated palette.
|
|
||||||
|
|
||||||
static void CalculatePalette(void);
|
|
||||||
static void ChoosePalette(void);
|
|
||||||
static void WritePalette(void);
|
|
||||||
uint8 pale=0;
|
|
||||||
|
|
||||||
pal *palo;
|
|
||||||
static pal *palpoint[8]=
|
|
||||||
{
|
{
|
||||||
palette,
|
palette,
|
||||||
rp2c04001,
|
rp2c04001,
|
||||||
@ -68,35 +67,280 @@ static pal *palpoint[8]=
|
|||||||
rp2c05004,
|
rp2c05004,
|
||||||
};
|
};
|
||||||
|
|
||||||
void FCEUI_SetPaletteArray(uint8 *pal)
|
static void CalculatePalette(void);
|
||||||
|
static void ChoosePalette(void);
|
||||||
|
static void WritePalette(void);
|
||||||
|
|
||||||
|
//points to the actually selected current palette
|
||||||
|
pal *palo;
|
||||||
|
|
||||||
|
#define RGB_TO_YIQ( r, g, b, y, i ) (\
|
||||||
|
(y = (r) * 0.299f + (g) * 0.587f + (b) * 0.114f),\
|
||||||
|
(i = (r) * 0.596f - (g) * 0.275f - (b) * 0.321f),\
|
||||||
|
((r) * 0.212f - (g) * 0.523f + (b) * 0.311f)\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define YIQ_TO_RGB( y, i, q, to_rgb, type, r, g ) (\
|
||||||
|
r = (type) (y + to_rgb [0] * i + to_rgb [1] * q),\
|
||||||
|
g = (type) (y + to_rgb [2] * i + to_rgb [3] * q),\
|
||||||
|
(type) (y + to_rgb [4] * i + to_rgb [5] * q)\
|
||||||
|
)
|
||||||
|
|
||||||
|
static void ApplyDeemphasisNTSC(int entry, u8& r, u8& g, u8& b)
|
||||||
{
|
{
|
||||||
if(!pal)
|
static float const to_float = 1.0f / 0xFF;
|
||||||
palpoint[0]=palette;
|
float fr = to_float * r;
|
||||||
|
float fg = to_float * g;
|
||||||
|
float fb = to_float * b;
|
||||||
|
float y, i, q = RGB_TO_YIQ( fr, fg, fb, y, i );
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------
|
||||||
|
//it seems a bit bogus here to use this segment which is essentially part of the base palette generation,
|
||||||
|
//but it's needed for 'hi'
|
||||||
|
static float const lo_levels [4] = { -0.12f, 0.00f, 0.31f, 0.72f };
|
||||||
|
static float const hi_levels [4] = { 0.40f, 0.68f, 1.00f, 1.00f };
|
||||||
|
int level = entry >> 4 & 0x03;
|
||||||
|
float lo = lo_levels [level];
|
||||||
|
float hi = hi_levels [level];
|
||||||
|
|
||||||
|
int color = entry & 0x0F;
|
||||||
|
if ( color == 0 )
|
||||||
|
lo = hi;
|
||||||
|
if ( color == 0x0D )
|
||||||
|
hi = lo;
|
||||||
|
if ( color > 0x0D )
|
||||||
|
hi = lo = 0.0f;
|
||||||
|
//---------------------------------
|
||||||
|
|
||||||
|
int tint = (entry >> 6) & 7;
|
||||||
|
if ( tint && color <= 0x0D )
|
||||||
|
{
|
||||||
|
static float const phases [0x10 + 3] = {
|
||||||
|
-1.0f, -0.866025f, -0.5f, 0.0f, 0.5f, 0.866025f,
|
||||||
|
1.0f, 0.866025f, 0.5f, 0.0f, -0.5f, -0.866025f,
|
||||||
|
-1.0f, -0.866025f, -0.5f, 0.0f, 0.5f, 0.866025f,
|
||||||
|
1.0f
|
||||||
|
};
|
||||||
|
#define TO_ANGLE_SIN( color ) phases [color]
|
||||||
|
#define TO_ANGLE_COS( color ) phases [(color) + 3]
|
||||||
|
|
||||||
|
static float const atten_mul = 0.79399f;
|
||||||
|
static float const atten_sub = 0.0782838f;
|
||||||
|
|
||||||
|
if ( tint == 7 )
|
||||||
|
{
|
||||||
|
y = y * (atten_mul * 1.13f) - (atten_sub * 1.13f);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int x;
|
static unsigned char const tints [8] = { 0, 6, 10, 8, 2, 4, 0, 0 };
|
||||||
palpoint[0]=palettec;
|
int const tint_color = tints [tint];
|
||||||
for(x=0;x<64;x++)
|
float sat = hi * (0.5f - atten_mul * 0.5f) + atten_sub * 0.5f;
|
||||||
|
y -= sat * 0.5f;
|
||||||
|
if ( tint >= 3 && tint != 4 )
|
||||||
{
|
{
|
||||||
palpoint[0][x].r=*((uint8 *)pal+x+x+x);
|
//combined tint bits
|
||||||
palpoint[0][x].g=*((uint8 *)pal+x+x+x+1);
|
sat *= 0.6f;
|
||||||
palpoint[0][x].b=*((uint8 *)pal+x+x+x+2);
|
y -= sat;
|
||||||
}
|
}
|
||||||
|
i += TO_ANGLE_SIN( tint_color ) * sat;
|
||||||
|
q += TO_ANGLE_COS( tint_color ) * sat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static float const default_decoder [6] =
|
||||||
|
{ 0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f };
|
||||||
|
fb = YIQ_TO_RGB( y, i, q, default_decoder, float, fr, fg );
|
||||||
|
|
||||||
|
#define CLAMP(x) ((x)<0?0:((x)>1.0f?1.0f:(x)))
|
||||||
|
r = (u8)(CLAMP(fr)*255);
|
||||||
|
g = (u8)(CLAMP(fg)*255);
|
||||||
|
b = (u8)(CLAMP(fb)*255);
|
||||||
|
|
||||||
|
//doesnt help
|
||||||
|
//float gamma=1.8f;
|
||||||
|
// auto gammafix = [=](float f) { return f < 0.f ? 0.f : std::pow(f, 2.2f / gamma); };
|
||||||
|
// auto clamp = [](int v) { return v<0 ? 0 : v>255 ? 255 : v; };
|
||||||
|
// r = clamp(255 * gammafix(y + 0.946882f*i + 0.623557f*q));
|
||||||
|
// g = clamp(255 * gammafix(y + -0.274788f*i + -0.635691f*q));
|
||||||
|
// b = clamp(255 * gammafix(y + -1.108545f*i + 1.709007f*q));
|
||||||
|
}
|
||||||
|
|
||||||
|
float bisqwit_gammafix(float f, float gamma) { return f < 0.f ? 0.f : std::pow(f, 2.2f / gamma); }
|
||||||
|
int bisqwit_clamp(int v) { return v<0 ? 0 : v>255 ? 255 : v; }
|
||||||
|
|
||||||
|
// Calculate the luma and chroma by emulating the relevant circuits:
|
||||||
|
int bisqwit_wave(int p, int color) { return (color+p+8)%12 < 6; }
|
||||||
|
|
||||||
|
static void ApplyDeemphasisBisqwit(int entry, u8& r, u8& g, u8& b)
|
||||||
|
{
|
||||||
|
if(entry<64) return;
|
||||||
|
int myr, myg, myb;
|
||||||
|
// The input value is a NES color index (with de-emphasis bits).
|
||||||
|
// We need RGB values. Convert the index into RGB.
|
||||||
|
// For most part, this process is described at:
|
||||||
|
// http://wiki.nesdev.com/w/index.php/NTSC_video
|
||||||
|
|
||||||
|
// Decode the color index
|
||||||
|
int color = (entry & 0x0F), level = color<0xE ? (entry>>4) & 3 : 1;
|
||||||
|
|
||||||
|
// Voltage levels, relative to synch voltage
|
||||||
|
static const float black=.518f, white=1.962f, attenuation=.746f,
|
||||||
|
levels[8] = {.350f, .518f, .962f,1.550f, // Signal low
|
||||||
|
1.094f,1.506f,1.962f,1.962f}; // Signal high
|
||||||
|
|
||||||
|
float lo_and_hi[2] = { levels[level + 4 * (color == 0x0)],
|
||||||
|
levels[level + 4 * (color < 0xD)] };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//fceux alteration: two passes
|
||||||
|
//1st pass calculates bisqwit's base color
|
||||||
|
//2nd pass calculates it with deemph
|
||||||
|
//finally, we'll do something dumb: find a 'scale factor' between them and apply it to the input palette. (later, we could pregenerate the scale factors)
|
||||||
|
//whatever, it gets the job done.
|
||||||
|
for(int pass=0;pass<2;pass++)
|
||||||
|
{
|
||||||
|
float y=0.f, i=0.f, q=0.f, gamma=1.8f;
|
||||||
|
for(int p=0; p<12; ++p) // 12 clock cycles per pixel.
|
||||||
|
{
|
||||||
|
// NES NTSC modulator (square wave between two voltage levels):
|
||||||
|
float spot = lo_and_hi[bisqwit_wave(p,color)];
|
||||||
|
|
||||||
|
// De-emphasis bits attenuate a part of the signal:
|
||||||
|
if(pass==1)
|
||||||
|
{
|
||||||
|
if(((entry & 0x40) && bisqwit_wave(p,12))
|
||||||
|
|| ((entry & 0x80) && bisqwit_wave(p, 4))
|
||||||
|
|| ((entry &0x100) && bisqwit_wave(p, 8))) spot *= attenuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize:
|
||||||
|
float v = (spot - black) / (white-black) / 12.f;
|
||||||
|
|
||||||
|
// Ideal TV NTSC demodulator:
|
||||||
|
y += v;
|
||||||
|
i += v * std::cos(3.141592653 * p / 6);
|
||||||
|
q += v * std::sin(3.141592653 * p / 6); // Or cos(... p-3 ... )
|
||||||
|
// Note: Integrating cos() and sin() for p-0.5 .. p+0.5 range gives
|
||||||
|
// the exactly same result, scaled by a factor of 2*cos(pi/12).
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert YIQ into RGB according to FCC-sanctioned conversion matrix.
|
||||||
|
|
||||||
|
int rt = bisqwit_clamp(255 * bisqwit_gammafix(y + 0.946882f*i + 0.623557f*q,gamma));
|
||||||
|
int gt = bisqwit_clamp(255 * bisqwit_gammafix(y + -0.274788f*i + -0.635691f*q,gamma));
|
||||||
|
int bt = bisqwit_clamp(255 * bisqwit_gammafix(y + -1.108545f*i + 1.709007f*q,gamma));
|
||||||
|
|
||||||
|
if(pass==0) myr = rt, myg = gt, myb = bt;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float rscale = (float)rt / myr;
|
||||||
|
float gscale = (float)gt / myg;
|
||||||
|
float bscale = (float)bt / myb;
|
||||||
|
#define BCLAMP(x) ((x)<0?0:((x)>255?255:(x)))
|
||||||
|
if(myr!=0) r = (u8)(BCLAMP(r*rscale));
|
||||||
|
if(myg!=0) g = (u8)(BCLAMP(g*gscale));
|
||||||
|
if(myb!=0) b = (u8)(BCLAMP(b*bscale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//classic algorithm
|
||||||
|
static void ApplyDeemphasisClassic(int entry, u8& r, u8& g, u8& b)
|
||||||
|
{
|
||||||
|
//DEEMPH BITS MAY BE ORDERED WRONG. PLEASE CHECK
|
||||||
|
|
||||||
|
static const float rtmul[] = { 1.239f, 0.794f, 1.019f, 0.905f, 1.023f, 0.741f, 0.75f };
|
||||||
|
static const float gtmul[] = { 0.915f, 1.086f, 0.98f, 1.026f, 0.908f, 0.987f, 0.75f };
|
||||||
|
static const float btmul[] = { 0.743f, 0.882f, 0.653f, 1.277f, 0.979f, 0.101f, 0.75f };
|
||||||
|
|
||||||
|
int deemph_bits = entry >> 6;
|
||||||
|
|
||||||
|
if (deemph_bits == 0) return;
|
||||||
|
|
||||||
|
int d = deemph_bits - 1;
|
||||||
|
int nr = (int)(r * rtmul[d]);
|
||||||
|
int ng = (int)(g * gtmul[d]);
|
||||||
|
int nb = (int)(b * btmul[d]);
|
||||||
|
if (nr > 0xFF) nr = 0xFF;
|
||||||
|
if (ng > 0xFF) ng = 0xFF;
|
||||||
|
if (nb > 0xFF) nb = 0xFF;
|
||||||
|
r = (u8)nr;
|
||||||
|
g = (u8)ng;
|
||||||
|
b = (u8)nb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ApplyDeemphasisComplete(pal* pal512)
|
||||||
|
{
|
||||||
|
//for each deemph level beyond 0
|
||||||
|
for(int i=0,idx=0;i<8;i++)
|
||||||
|
{
|
||||||
|
//for each palette entry
|
||||||
|
for(int p=0;p<64;p++,idx++)
|
||||||
|
{
|
||||||
|
pal512[idx] = pal512[p];
|
||||||
|
ApplyDeemphasisBisqwit(idx,pal512[idx].r,pal512[idx].g,pal512[idx].b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_SetUserPalette(uint8 *pal, int nEntries)
|
||||||
|
{
|
||||||
|
if(!pal)
|
||||||
|
{
|
||||||
|
palette_user_available = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
palette_user_available = true;
|
||||||
|
memcpy(palette_user,pal,nEntries*3);
|
||||||
|
|
||||||
|
//if palette is incomplete, generate deemph entries
|
||||||
|
if(nEntries != 512)
|
||||||
|
ApplyDeemphasisComplete(palette_user);
|
||||||
}
|
}
|
||||||
FCEU_ResetPalette();
|
FCEU_ResetPalette();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FCEU_LoadGamePalette(void)
|
||||||
|
{
|
||||||
|
palette_game_available = false;
|
||||||
|
std::string path = FCEU_MakeFName(FCEUMKF_PALETTE,0,0);
|
||||||
|
FILE* fp = FCEUD_UTF8fopen(path,"rb");
|
||||||
|
if(fp)
|
||||||
|
{
|
||||||
|
int readed = fread(palette_game,1,64*8*3,fp);
|
||||||
|
int nEntries = readed/3;
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
void FCEUI_SetNTSCTH(int n, int tint, int hue)
|
//if palette is incomplete, generate deemph entries
|
||||||
|
if(nEntries != 512)
|
||||||
|
ApplyDeemphasisComplete(palette_game);
|
||||||
|
|
||||||
|
palette_game_available = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//not sure whether this is needed
|
||||||
|
FCEU_ResetPalette();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_SetNTSCTH(bool en, int tint, int hue)
|
||||||
{
|
{
|
||||||
ntsctint=tint;
|
ntsctint=tint;
|
||||||
ntschue=hue;
|
ntschue=hue;
|
||||||
ntsccol=n;
|
ntsccol_enable = en;
|
||||||
FCEU_ResetPalette();
|
FCEU_ResetPalette();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//this prepares the 'deemph' palette which was a horrible idea to jam a single deemph palette into 0xC0-0xFF of the 8bpp palette.
|
||||||
|
//its needed for GUI and lua and stuff, so we're leaving it, despite having a newer codepath for applying deemph
|
||||||
static uint8 lastd=0;
|
static uint8 lastd=0;
|
||||||
void SetNESDeemph(uint8 d, int force)
|
void SetNESDeemph_OldHacky(uint8 d, int force)
|
||||||
{
|
{
|
||||||
static uint16 rtmul[]={
|
static uint16 rtmul[]={
|
||||||
static_cast<uint16>(32768*1.239),
|
static_cast<uint16>(32768*1.239),
|
||||||
@ -194,6 +438,10 @@ void SetNESDeemph(uint8 d, int force)
|
|||||||
// Converted from Kevin Horton's qbasic palette generator.
|
// Converted from Kevin Horton's qbasic palette generator.
|
||||||
static void CalculatePalette(void)
|
static void CalculatePalette(void)
|
||||||
{
|
{
|
||||||
|
//PRECONDITION: ntsc palette is enabled
|
||||||
|
if(!ntsccol_enable)
|
||||||
|
return;
|
||||||
|
|
||||||
int x,z;
|
int x,z;
|
||||||
int r,g,b;
|
int r,g,b;
|
||||||
double s,luma,theta;
|
double s,luma,theta;
|
||||||
@ -229,41 +477,16 @@ static void CalculatePalette(void)
|
|||||||
if(g<0) g=0;
|
if(g<0) g=0;
|
||||||
if(b<0) b=0;
|
if(b<0) b=0;
|
||||||
|
|
||||||
paletten[(x<<4)+z].r=r;
|
palette_ntsc[(x<<4)+z].r=r;
|
||||||
paletten[(x<<4)+z].g=g;
|
palette_ntsc[(x<<4)+z].g=g;
|
||||||
paletten[(x<<4)+z].b=b;
|
palette_ntsc[(x<<4)+z].b=b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//can't call FCEU_ResetPalette(), it would be re-entrant
|
||||||
|
//see precondition for this function
|
||||||
WritePalette();
|
WritePalette();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ipalette=0;
|
|
||||||
|
|
||||||
void FCEU_LoadGamePalette(void)
|
|
||||||
{
|
|
||||||
uint8 ptmp[192];
|
|
||||||
FILE *fp;
|
|
||||||
char *fn;
|
|
||||||
|
|
||||||
ipalette=0;
|
|
||||||
|
|
||||||
fn=strdup(FCEU_MakeFName(FCEUMKF_PALETTE,0,0).c_str());
|
|
||||||
|
|
||||||
if((fp=FCEUD_UTF8fopen(fn,"rb")))
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
fread(ptmp,1,192,fp);
|
|
||||||
fclose(fp);
|
|
||||||
for(x=0;x<64;x++)
|
|
||||||
{
|
|
||||||
palettei[x].r=ptmp[x+x+x];
|
|
||||||
palettei[x].g=ptmp[x+x+x+1];
|
|
||||||
palettei[x].b=ptmp[x+x+x+2];
|
|
||||||
}
|
|
||||||
ipalette=1;
|
|
||||||
}
|
|
||||||
free(fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCEU_ResetPalette(void)
|
void FCEU_ResetPalette(void)
|
||||||
{
|
{
|
||||||
if(GameInfo)
|
if(GameInfo)
|
||||||
@ -275,39 +498,53 @@ void FCEU_ResetPalette(void)
|
|||||||
|
|
||||||
static void ChoosePalette(void)
|
static void ChoosePalette(void)
|
||||||
{
|
{
|
||||||
|
//NSF uses a fixed palette always:
|
||||||
if(GameInfo->type==GIT_NSF)
|
if(GameInfo->type==GIT_NSF)
|
||||||
palo=0;
|
palo = default_palette[0];
|
||||||
else if(ipalette)
|
//user palette takes priority over others
|
||||||
palo=palettei;
|
else if(palette_user_available)
|
||||||
else if(ntsccol && !PAL && GameInfo->type!=GIT_VSUNI)
|
palo = palette_user;
|
||||||
|
//NTSC takes priority next, if it's appropriate
|
||||||
|
else if(ntsccol_enable && !PAL && GameInfo->type!=GIT_VSUNI)
|
||||||
{
|
{
|
||||||
palo=paletten;
|
//for NTSC games, we can actually use the NTSC palette
|
||||||
|
palo = palette_ntsc;
|
||||||
CalculatePalette();
|
CalculatePalette();
|
||||||
}
|
}
|
||||||
|
//select the game's overridden palette if available
|
||||||
|
else if(palette_game_available)
|
||||||
|
palo = palette_game;
|
||||||
|
//finally, use a default built-in palette
|
||||||
else
|
else
|
||||||
palo=palpoint[pale];
|
{
|
||||||
|
palo = default_palette[default_palette_selection];
|
||||||
|
//need to calcualte a deemph on the fly.. sorry. maybe support otherwise later
|
||||||
|
ApplyDeemphasisComplete(palo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WritePalette(void)
|
void WritePalette(void)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
for(x=0;x<7;x++)
|
//set the 'unvarying' palettes to low < 64 palette entries
|
||||||
FCEUD_SetPalette(x,unvpalette[x].r,unvpalette[x].g,unvpalette[x].b);
|
const int unvaried = sizeof(palette_unvarying)/sizeof(palette_unvarying[0]);
|
||||||
if(GameInfo->type==GIT_NSF)
|
for(x=0;x<unvaried;x++)
|
||||||
{
|
FCEUD_SetPalette(x,palette_unvarying[x].r,palette_unvarying[x].g,palette_unvarying[x].b);
|
||||||
|
|
||||||
|
//clear everything else to a deterministic state.
|
||||||
|
//it seems likely that the text rendering on NSF has been broken since the beginning of fceux, depending on palette entries 205,205,205 everywhere
|
||||||
|
//this was just whatever msvc filled malloc with. on non-msvc platforms, there was no backdrop on the rendering.
|
||||||
|
for(x=unvaried;x<256;x++)
|
||||||
|
FCEUD_SetPalette(x,205,205,205);
|
||||||
|
|
||||||
|
//sets palette entries >= 128 with the 64 selected main colors
|
||||||
|
for(x=0;x<64;x++)
|
||||||
|
FCEUD_SetPalette(128+x,palo[x].r,palo[x].g,palo[x].b);
|
||||||
|
SetNESDeemph_OldHacky(lastd,1);
|
||||||
#ifdef _S9XLUA_H
|
#ifdef _S9XLUA_H
|
||||||
FCEU_LuaUpdatePalette();
|
FCEU_LuaUpdatePalette();
|
||||||
#endif
|
#endif
|
||||||
//for(x=0;x<128;x++)
|
|
||||||
// FCEUD_SetPalette(x,x,0,x);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(x=0;x<64;x++)
|
|
||||||
FCEUD_SetPalette(128+x,palo[x].r,palo[x].g,palo[x].b);
|
|
||||||
SetNESDeemph(lastd,1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCEUI_GetNTSCTH(int *tint, int *hue)
|
void FCEUI_GetNTSCTH(int *tint, int *hue)
|
||||||
@ -321,7 +558,7 @@ static int controllength=0;
|
|||||||
|
|
||||||
void FCEUI_NTSCDEC(void)
|
void FCEUI_NTSCDEC(void)
|
||||||
{
|
{
|
||||||
if(ntsccol && GameInfo->type!=GIT_VSUNI &&!PAL && GameInfo->type!=GIT_NSF)
|
if(ntsccol_enable && GameInfo->type!=GIT_VSUNI &&!PAL && GameInfo->type!=GIT_NSF)
|
||||||
{
|
{
|
||||||
int which;
|
int which;
|
||||||
if(controlselect)
|
if(controlselect)
|
||||||
@ -343,7 +580,7 @@ void FCEUI_NTSCDEC(void)
|
|||||||
|
|
||||||
void FCEUI_NTSCINC(void)
|
void FCEUI_NTSCINC(void)
|
||||||
{
|
{
|
||||||
if(ntsccol && GameInfo->type!=GIT_VSUNI && !PAL && GameInfo->type!=GIT_NSF)
|
if(ntsccol_enable && GameInfo->type!=GIT_VSUNI && !PAL && GameInfo->type!=GIT_NSF)
|
||||||
if(controlselect)
|
if(controlselect)
|
||||||
{
|
{
|
||||||
if(controllength)
|
if(controllength)
|
||||||
@ -366,12 +603,12 @@ void FCEUI_NTSCINC(void)
|
|||||||
|
|
||||||
void FCEUI_NTSCSELHUE(void)
|
void FCEUI_NTSCSELHUE(void)
|
||||||
{
|
{
|
||||||
if(ntsccol && GameInfo->type!=GIT_VSUNI && !PAL && GameInfo->type!=GIT_NSF){controlselect=1;controllength=360;}
|
if(ntsccol_enable && GameInfo->type!=GIT_VSUNI && !PAL && GameInfo->type!=GIT_NSF){controlselect=1;controllength=360;}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCEUI_NTSCSELTINT(void)
|
void FCEUI_NTSCSELTINT(void)
|
||||||
{
|
{
|
||||||
if(ntsccol && GameInfo->type!=GIT_VSUNI && !PAL && GameInfo->type!=GIT_NSF){controlselect=2;controllength=360;}
|
if(ntsccol_enable && GameInfo->type!=GIT_VSUNI && !PAL && GameInfo->type!=GIT_NSF){controlselect=2;controllength=360;}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCEU_DrawNTSCControlBars(uint8 *XBuf)
|
void FCEU_DrawNTSCControlBars(uint8 *XBuf)
|
||||||
|
@ -1,31 +1,59 @@
|
|||||||
pal rp2c04001[64] = {
|
#define EMPTY_PALETTE_1 {0,0,0},
|
||||||
|
#define EMPTY_PALETTE_4 EMPTY_PALETTE_1 EMPTY_PALETTE_1 EMPTY_PALETTE_1 EMPTY_PALETTE_1
|
||||||
|
#define EMPTY_PALETTE_16 EMPTY_PALETTE_4 EMPTY_PALETTE_4 EMPTY_PALETTE_4 EMPTY_PALETTE_4
|
||||||
|
#define EMPTY_PALETTE_64 EMPTY_PALETTE_16 EMPTY_PALETTE_16 EMPTY_PALETTE_16 EMPTY_PALETTE_16
|
||||||
|
#define EMPTY_PALETTE_DEEMPH_X_7 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64
|
||||||
|
|
||||||
|
pal rp2c04001[512] = {
|
||||||
#include "rp2c04001.h"
|
#include "rp2c04001.h"
|
||||||
|
EMPTY_PALETTE_DEEMPH_X_7
|
||||||
};
|
};
|
||||||
|
|
||||||
pal rp2c04002[64] = {
|
pal rp2c04002[512] = {
|
||||||
#include "rp2c04002.h"
|
#include "rp2c04002.h"
|
||||||
|
EMPTY_PALETTE_DEEMPH_X_7
|
||||||
};
|
};
|
||||||
|
|
||||||
pal rp2c04003[64] = {
|
pal rp2c04003[512] = {
|
||||||
#include "rp2c04003.h"
|
#include "rp2c04003.h"
|
||||||
|
EMPTY_PALETTE_DEEMPH_X_7
|
||||||
};
|
};
|
||||||
pal rp2c05004[64] = {
|
pal rp2c05004[512] = {
|
||||||
#include "rp2c05004.h"
|
#include "rp2c05004.h"
|
||||||
|
EMPTY_PALETTE_DEEMPH_X_7
|
||||||
};
|
};
|
||||||
|
|
||||||
pal unvpalette[7] = {
|
// Fixed palette entries used by the GUI
|
||||||
{ 0x00<<2,0x00<<2,0x00<<2}, // Black
|
pal palette_unvarying[] = {
|
||||||
{ 0x3F<<2,0x3F<<2,0x34<<2}, // White
|
{ 0x00<<2,0x00<<2,0x00<<2}, // 0 = Black
|
||||||
{ 0x00<<2,0x00<<2,0x00<<2}, // Black
|
{ 0x3F<<2,0x3F<<2,0x34<<2}, // 1 = White
|
||||||
{ 0x1d<<2,0x1d<<2,0x24<<2}, // Greyish
|
{ 0x00<<2,0x00<<2,0x00<<2}, // 2 = Black
|
||||||
{ 190,0,0 }, // Redish
|
{ 0x1d<<2,0x1d<<2,0x24<<2}, // 3 = Greyish
|
||||||
{ 51,255,51}, // Bright green
|
{ 190, 0, 0}, // 4 = Reddish
|
||||||
{ 49,14,200},
|
{ 51,255, 51}, // 5 = Bright green
|
||||||
|
{ 49, 14,200}, // 6 = Ultramarine Blue
|
||||||
|
// 16 saturated colors useful for Lua scripts
|
||||||
|
{ 0, 0, 0}, // 7 = Black
|
||||||
|
{ 0, 0,128}, // 8 = Dark Blue
|
||||||
|
{ 0,128, 0}, // 9 = Dark Green
|
||||||
|
{ 0,128,128}, // 10 = Dark Cyan
|
||||||
|
{ 128, 0, 0}, // 11 = Dark Red
|
||||||
|
{ 128, 0,128}, // 12 = Dark Magenta
|
||||||
|
{ 128,128, 0}, // 13 = Dark Yellow
|
||||||
|
{ 128,128,128}, // 14 = Light Grey
|
||||||
|
{ 64, 64, 64}, // 15 = Dark Grey
|
||||||
|
{ 0, 0,255}, // 16 = Bright Blue
|
||||||
|
{ 0,255, 0}, // 17 = Bright Green
|
||||||
|
{ 0,255,255}, // 18 = Bright Cyan
|
||||||
|
{ 255, 0, 0}, // 19 = Bright Red
|
||||||
|
{ 255, 0,255}, // 20 = Bright Magenta
|
||||||
|
{ 255,255, 0}, // 21 = Bright Yellow
|
||||||
|
{ 255,255,255}, // 22 = Bright White
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Default palette
|
// Default palette
|
||||||
pal palette[64] = {
|
pal palette[512] = {
|
||||||
|
|
||||||
{ 0x1D<<2, 0x1D<<2, 0x1D<<2 }, /* Value 0 */
|
{ 0x1D<<2, 0x1D<<2, 0x1D<<2 }, /* Value 0 */
|
||||||
{ 0x09<<2, 0x06<<2, 0x23<<2 }, /* Value 1 */
|
{ 0x09<<2, 0x06<<2, 0x23<<2 }, /* Value 1 */
|
||||||
@ -292,4 +320,6 @@ slightly better but too dark:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
EMPTY_PALETTE_DEEMPH_X_7
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -57,7 +57,8 @@
|
|||||||
|
|
||||||
#define PPU_status (PPU[2])
|
#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 FetchSpriteData(void);
|
||||||
static void RefreshLine(int lastpixel);
|
static void RefreshLine(int lastpixel);
|
||||||
@ -69,6 +70,8 @@ static uint32 ppulut1[256];
|
|||||||
static uint32 ppulut2[256];
|
static uint32 ppulut2[256];
|
||||||
static uint32 ppulut3[128];
|
static uint32 ppulut3[128];
|
||||||
|
|
||||||
|
static bool new_ppu_reset = false;
|
||||||
|
|
||||||
int test = 0;
|
int test = 0;
|
||||||
|
|
||||||
template<typename T, int BITS>
|
template<typename T, int BITS>
|
||||||
@ -274,8 +277,24 @@ struct PPUREGS {
|
|||||||
v &= 1;
|
v &= 1;
|
||||||
fv &= 7;
|
fv &= 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void debug_log()
|
||||||
|
{
|
||||||
|
FCEU_printf("ppur: fv(%d), v(%d), h(%d), vt(%d), ht(%d)\n",fv,v,h,vt,ht);
|
||||||
|
FCEU_printf(" _fv(%d), _v(%d), _h(%d), _vt(%d), _ht(%d)\n",_fv,_v,_h,_vt,_ht);
|
||||||
|
FCEU_printf(" fh(%d), s(%d), par(%d)\n",fh,s,par);
|
||||||
|
FCEU_printf(" .status cycle(%d), end_cycle(%d), sl(%d)\n",status.cycle,status.end_cycle,status.sl);
|
||||||
|
}
|
||||||
} ppur;
|
} ppur;
|
||||||
|
|
||||||
|
int newppu_get_scanline() { return ppur.status.sl; }
|
||||||
|
int newppu_get_dot() { return ppur.status.cycle; }
|
||||||
|
void newppu_hacky_emergency_reset()
|
||||||
|
{
|
||||||
|
if(ppur.status.end_cycle == 0)
|
||||||
|
ppur.reset();
|
||||||
|
}
|
||||||
|
|
||||||
static void makeppulut(void) {
|
static void makeppulut(void) {
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
@ -337,7 +356,7 @@ uint8 vtoggle = 0;
|
|||||||
uint8 XOffset = 0;
|
uint8 XOffset = 0;
|
||||||
uint8 SpriteDMA = 0; // $4014 / Writing $xx copies 256 bytes by reading from $xx00-$xxFF and writing to $2004 (OAM data)
|
uint8 SpriteDMA = 0; // $4014 / Writing $xx copies 256 bytes by reading from $xx00-$xxFF and writing to $2004 (OAM data)
|
||||||
|
|
||||||
uint32 TempAddr = 0, RefreshAddr = 0, DummyRead = 0;
|
uint32 TempAddr = 0, RefreshAddr = 0, DummyRead = 0, NTRefreshAddr = 0;
|
||||||
|
|
||||||
static int maxsprites = 8;
|
static int maxsprites = 8;
|
||||||
|
|
||||||
@ -355,18 +374,7 @@ uint8 UPALRAM[0x03];//for 0x4/0x8/0xC addresses in palette, the ones in
|
|||||||
#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)]
|
#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)]
|
||||||
#define VRAMADR(V) &VPage[(V) >> 10][(V)]
|
#define VRAMADR(V) &VPage[(V) >> 10][(V)]
|
||||||
|
|
||||||
//mbg 8/6/08 - fix a bug relating to
|
uint8* MMC5BGVRAMADR(uint32 A);
|
||||||
//"When in 8x8 sprite mode, only one set is used for both BG and sprites."
|
|
||||||
//in mmc5 docs
|
|
||||||
uint8 * MMC5BGVRAMADR(uint32 V) {
|
|
||||||
if (!Sprite16) {
|
|
||||||
extern uint8 mmc5ABMode; /* A=0, B=1 */
|
|
||||||
if (mmc5ABMode == 0)
|
|
||||||
return MMC5SPRVRAMADR(V);
|
|
||||||
else
|
|
||||||
return &MMC5BGVPage[(V) >> 10][(V)];
|
|
||||||
} else return &MMC5BGVPage[(V) >> 10][(V)];
|
|
||||||
}
|
|
||||||
|
|
||||||
//this duplicates logic which is embedded in the ppu rendering code
|
//this duplicates logic which is embedded in the ppu rendering code
|
||||||
//which figures out where to get CHR data from depending on various hack modes
|
//which figures out where to get CHR data from depending on various hack modes
|
||||||
@ -420,7 +428,7 @@ inline void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
volatile int rendercount, vromreadcount, undefinedvromcount, LogAddress = -1;
|
volatile int rendercount, vromreadcount, undefinedvromcount, LogAddress = -1;
|
||||||
unsigned char *cdloggervdata;
|
unsigned char *cdloggervdata = NULL;
|
||||||
unsigned int cdloggerVideoDataSize = 0;
|
unsigned int cdloggerVideoDataSize = 0;
|
||||||
|
|
||||||
int GetCHRAddress(int A) {
|
int GetCHRAddress(int A) {
|
||||||
@ -428,6 +436,19 @@ int GetCHRAddress(int A) {
|
|||||||
int result = &VPage[A >> 10][A] - CHRptr[0];
|
int result = &VPage[A >> 10][A] - CHRptr[0];
|
||||||
if ((result >= 0) && (result < (int)cdloggerVideoDataSize))
|
if ((result >= 0) && (result < (int)cdloggerVideoDataSize))
|
||||||
return result;
|
return result;
|
||||||
|
} else
|
||||||
|
if(A < 0x2000) return A;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetCHROffset(uint8 *ptr) {
|
||||||
|
int result = ptr - CHRptr[0];
|
||||||
|
if (cdloggerVideoDataSize) {
|
||||||
|
if ((result >= 0) && (result < (int)cdloggerVideoDataSize))
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
if ((result >= 0) && (result < 0x2000))
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -441,11 +462,31 @@ int GetCHRAddress(int A) {
|
|||||||
if (!(cdloggervdata[addr] & 1)) \
|
if (!(cdloggervdata[addr] & 1)) \
|
||||||
{ \
|
{ \
|
||||||
cdloggervdata[addr] |= 1; \
|
cdloggervdata[addr] |= 1; \
|
||||||
|
if(cdloggerVideoDataSize) { \
|
||||||
if (!(cdloggervdata[addr] & 2)) undefinedvromcount--; \
|
if (!(cdloggervdata[addr] & 2)) undefinedvromcount--; \
|
||||||
rendercount++; \
|
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++; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A) {
|
uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A) {
|
||||||
@ -461,14 +502,11 @@ uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A) {
|
|||||||
uint8 ret;
|
uint8 ret;
|
||||||
if (!(tmp & 3)) {
|
if (!(tmp & 3)) {
|
||||||
if (!(tmp & 0xC))
|
if (!(tmp & 0xC))
|
||||||
ret = PALRAM[0x00];
|
ret = READPAL(0x00);
|
||||||
else
|
else
|
||||||
ret = UPALRAM[((tmp & 0xC) >> 2) - 1];
|
ret = READUPAL(((tmp & 0xC) >> 2) - 1);
|
||||||
} else
|
} else
|
||||||
ret = PALRAM[tmp & 0x1F];
|
ret = READPAL(tmp & 0x1F);
|
||||||
|
|
||||||
if (GRAYSCALE)
|
|
||||||
ret &= 0x30;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -481,7 +519,7 @@ void (*FFCEUX_PPUWrite)(uint32 A, uint8 V) = 0;
|
|||||||
|
|
||||||
#define CALL_PPUWRITE(A, V) (FFCEUX_PPUWrite ? FFCEUX_PPUWrite(A, V) : FFCEUX_PPUWrite_Default(A, V))
|
#define CALL_PPUWRITE(A, V) (FFCEUX_PPUWrite ? FFCEUX_PPUWrite(A, V) : FFCEUX_PPUWrite_Default(A, V))
|
||||||
|
|
||||||
//whether to use the new ppu (new PPU doesn't handle MMC5 extra nametables at all
|
//whether to use the new ppu
|
||||||
int newppu = 0;
|
int newppu = 0;
|
||||||
|
|
||||||
void ppu_getScroll(int &xpos, int &ypos) {
|
void ppu_getScroll(int &xpos, int &ypos) {
|
||||||
@ -665,7 +703,7 @@ static DECLFR(A2007) {
|
|||||||
if (!DummyRead && (LogAddress != -1)) {
|
if (!DummyRead && (LogAddress != -1)) {
|
||||||
if (!(cdloggervdata[LogAddress] & 2)) {
|
if (!(cdloggervdata[LogAddress] & 2)) {
|
||||||
cdloggervdata[LogAddress] |= 2;
|
cdloggervdata[LogAddress] |= 2;
|
||||||
if (!(cdloggervdata[LogAddress] & 1)) undefinedvromcount--;
|
if ((!(cdloggervdata[LogAddress] & 1)) && cdloggerVideoDataSize) undefinedvromcount--;
|
||||||
vromreadcount++;
|
vromreadcount++;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -683,13 +721,11 @@ static DECLFR(A2007) {
|
|||||||
//to get a gray color reading
|
//to get a gray color reading
|
||||||
if (!(tmp & 3)) {
|
if (!(tmp & 3)) {
|
||||||
if (!(tmp & 0xC))
|
if (!(tmp & 0xC))
|
||||||
ret = PALRAM[0x00];
|
ret = READPAL(0x00);
|
||||||
else
|
else
|
||||||
ret = UPALRAM[((tmp & 0xC) >> 2) - 1];
|
ret = READUPAL(((tmp & 0xC) >> 2) - 1);
|
||||||
} else
|
} else
|
||||||
ret = PALRAM[tmp & 0x1F];
|
ret = READPAL(tmp & 0x1F);
|
||||||
if (GRAYSCALE)
|
|
||||||
ret &= 0x30;
|
|
||||||
VRAMBuffer = CALL_PPUREAD(RefreshAddr - 0x1000);
|
VRAMBuffer = CALL_PPUREAD(RefreshAddr - 0x1000);
|
||||||
} else {
|
} else {
|
||||||
if (debug_loggingCD && (RefreshAddr < 0x2000))
|
if (debug_loggingCD && (RefreshAddr < 0x2000))
|
||||||
@ -700,18 +736,18 @@ static DECLFR(A2007) {
|
|||||||
RefreshAddr = ppur.get_2007access();
|
RefreshAddr = ppur.get_2007access();
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
//OLDPPU
|
||||||
FCEUPPU_LineUpdate();
|
FCEUPPU_LineUpdate();
|
||||||
|
|
||||||
if (tmp >= 0x3F00) { // Palette RAM tied directly to the output data, without VRAM buffer
|
if (tmp >= 0x3F00) { // Palette RAM tied directly to the output data, without VRAM buffer
|
||||||
if (!(tmp & 3)) {
|
if (!(tmp & 3)) {
|
||||||
if (!(tmp & 0xC))
|
if (!(tmp & 0xC))
|
||||||
ret = PALRAM[0x00];
|
ret = READPAL(0x00);
|
||||||
else
|
else
|
||||||
ret = UPALRAM[((tmp & 0xC) >> 2) - 1];
|
ret = READUPAL(((tmp & 0xC) >> 2) - 1);
|
||||||
} else
|
} else
|
||||||
ret = PALRAM[tmp & 0x1F];
|
ret = READPAL(tmp & 0x1F);
|
||||||
if (GRAYSCALE)
|
|
||||||
ret &= 0x30;
|
|
||||||
#ifdef FCEUDEF_DEBUGGER
|
#ifdef FCEUDEF_DEBUGGER
|
||||||
if (!fceuindbg)
|
if (!fceuindbg)
|
||||||
#endif
|
#endif
|
||||||
@ -731,9 +767,14 @@ static DECLFR(A2007) {
|
|||||||
if (PPU_hook) PPU_hook(tmp);
|
if (PPU_hook) PPU_hook(tmp);
|
||||||
PPUGenLatch = VRAMBuffer;
|
PPUGenLatch = VRAMBuffer;
|
||||||
if (tmp < 0x2000) {
|
if (tmp < 0x2000) {
|
||||||
|
|
||||||
if (debug_loggingCD)
|
if (debug_loggingCD)
|
||||||
LogAddress = GetCHRAddress(tmp);
|
LogAddress = GetCHRAddress(tmp);
|
||||||
|
if(MMC5Hack && newppu)
|
||||||
|
VRAMBuffer = *MMC5BGVRAMADR(tmp);
|
||||||
|
else
|
||||||
VRAMBuffer = VPage[tmp >> 10][tmp];
|
VRAMBuffer = VPage[tmp >> 10][tmp];
|
||||||
|
|
||||||
} else if (tmp < 0x3F00)
|
} else if (tmp < 0x3F00)
|
||||||
VRAMBuffer = vnapage[(tmp >> 10) & 0x3][tmp & 0x3FF];
|
VRAMBuffer = vnapage[(tmp >> 10) & 0x3][tmp & 0x3FF];
|
||||||
}
|
}
|
||||||
@ -786,6 +827,8 @@ static DECLFW(B2000) {
|
|||||||
|
|
||||||
static DECLFW(B2001) {
|
static DECLFW(B2001) {
|
||||||
FCEUPPU_LineUpdate();
|
FCEUPPU_LineUpdate();
|
||||||
|
if (paldeemphswap)
|
||||||
|
V = (V&0x9F)|((V&0x40)>>1)|((V&0x20)<<1);
|
||||||
PPUGenLatch = V;
|
PPUGenLatch = V;
|
||||||
PPU[1] = V;
|
PPU[1] = V;
|
||||||
if (V & 0xE0)
|
if (V & 0xE0)
|
||||||
@ -881,6 +924,11 @@ static DECLFW(B2006) {
|
|||||||
static DECLFW(B2007) {
|
static DECLFW(B2007) {
|
||||||
uint32 tmp = RefreshAddr & 0x3FFF;
|
uint32 tmp = RefreshAddr & 0x3FFF;
|
||||||
|
|
||||||
|
if (debug_loggingCD) {
|
||||||
|
if(!cdloggerVideoDataSize && (tmp < 0x2000))
|
||||||
|
cdloggervdata[tmp] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (newppu) {
|
if (newppu) {
|
||||||
PPUGenLatch = V;
|
PPUGenLatch = V;
|
||||||
RefreshAddr = ppur.get_2007access() & 0x3FFF;
|
RefreshAddr = ppur.get_2007access() & 0x3FFF;
|
||||||
@ -1043,7 +1091,7 @@ static void RefreshLine(int lastpixel) {
|
|||||||
|
|
||||||
if (!ScreenON && !SpriteON) {
|
if (!ScreenON && !SpriteON) {
|
||||||
uint32 tem;
|
uint32 tem;
|
||||||
tem = Pal[0] | (Pal[0] << 8) | (Pal[0] << 16) | (Pal[0] << 24);
|
tem = READPAL(0) | (READPAL(0) << 8) | (READPAL(0) << 16) | (READPAL(0) << 24);
|
||||||
tem |= 0x40404040;
|
tem |= 0x40404040;
|
||||||
FCEU_dwmemset(Pline, tem, numtiles * 8);
|
FCEU_dwmemset(Pline, tem, numtiles * 8);
|
||||||
P += numtiles * 8;
|
P += numtiles * 8;
|
||||||
@ -1064,10 +1112,10 @@ static void RefreshLine(int lastpixel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Priority bits, needed for sprite emulation.
|
//Priority bits, needed for sprite emulation.
|
||||||
Pal[0] |= 64;
|
PALRAM[0] |= 64;
|
||||||
Pal[4] |= 64;
|
PALRAM[4] |= 64;
|
||||||
Pal[8] |= 64;
|
PALRAM[8] |= 64;
|
||||||
Pal[0xC] |= 64;
|
PALRAM[0xC] |= 64;
|
||||||
|
|
||||||
//This high-level graphics MMC5 emulation code was written for MMC5 carts in "CL" mode.
|
//This high-level graphics MMC5 emulation code was written for MMC5 carts in "CL" mode.
|
||||||
//It's probably not totally correct for carts in "SL" mode.
|
//It's probably not totally correct for carts in "SL" mode.
|
||||||
@ -1145,15 +1193,15 @@ static void RefreshLine(int lastpixel) {
|
|||||||
#undef RefreshAddr
|
#undef RefreshAddr
|
||||||
|
|
||||||
//Reverse changes made before.
|
//Reverse changes made before.
|
||||||
Pal[0] &= 63;
|
PALRAM[0] &= 63;
|
||||||
Pal[4] &= 63;
|
PALRAM[4] &= 63;
|
||||||
Pal[8] &= 63;
|
PALRAM[8] &= 63;
|
||||||
Pal[0xC] &= 63;
|
PALRAM[0xC] &= 63;
|
||||||
|
|
||||||
RefreshAddr = smorkus;
|
RefreshAddr = smorkus;
|
||||||
if (firsttile <= 2 && 2 < lasttile && !(PPU[1] & 2)) {
|
if (firsttile <= 2 && 2 < lasttile && !(PPU[1] & 2)) {
|
||||||
uint32 tem;
|
uint32 tem;
|
||||||
tem = Pal[0] | (Pal[0] << 8) | (Pal[0] << 16) | (Pal[0] << 24);
|
tem = READPAL(0) | (READPAL(0) << 8) | (READPAL(0) << 16) | (READPAL(0) << 24);
|
||||||
tem |= 0x40404040;
|
tem |= 0x40404040;
|
||||||
*(uint32*)Plinef = *(uint32*)(Plinef + 4) = tem;
|
*(uint32*)Plinef = *(uint32*)(Plinef + 4) = tem;
|
||||||
}
|
}
|
||||||
@ -1161,7 +1209,7 @@ static void RefreshLine(int lastpixel) {
|
|||||||
if (!ScreenON) {
|
if (!ScreenON) {
|
||||||
uint32 tem;
|
uint32 tem;
|
||||||
int tstart, tcount;
|
int tstart, tcount;
|
||||||
tem = Pal[0] | (Pal[0] << 8) | (Pal[0] << 16) | (Pal[0] << 24);
|
tem = READPAL(0) | (READPAL(0) << 8) | (READPAL(0) << 16) | (READPAL(0) << 24);
|
||||||
tem |= 0x40404040;
|
tem |= 0x40404040;
|
||||||
|
|
||||||
tcount = lasttile - firsttile;
|
tcount = lasttile - firsttile;
|
||||||
@ -1218,11 +1266,16 @@ static void Fixit1(void) {
|
|||||||
|
|
||||||
void MMC5_hb(int); //Ugh ugh ugh.
|
void MMC5_hb(int); //Ugh ugh ugh.
|
||||||
static void DoLine(void) {
|
static void DoLine(void) {
|
||||||
|
if (scanline >= 240 && scanline != totalscanlines) {
|
||||||
|
X6502_Run(256 + 69);
|
||||||
|
scanline++;
|
||||||
|
X6502_Run(16);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int x;
|
int x;
|
||||||
// scanlines after 239 are dummy for dendy, and Xbuf is capped at 0xffff bytes, don't let it overflow
|
|
||||||
// send all future writes to the invisible sanline. the easiest way to "skip" them altogether in old ppu
|
|
||||||
// todo: figure out what exactly should be skipped. it's known that there's no activity on PPU bus
|
|
||||||
uint8 *target = XBuf + ((scanline < 240 ? scanline : 240) << 8);
|
uint8 *target = XBuf + ((scanline < 240 ? scanline : 240) << 8);
|
||||||
|
u8* dtarget = XDBuf + ((scanline < 240 ? scanline : 240) << 8);
|
||||||
|
|
||||||
if (MMC5Hack) MMC5_hb(scanline);
|
if (MMC5Hack) MMC5_hb(scanline);
|
||||||
|
|
||||||
@ -1233,7 +1286,7 @@ static void DoLine(void) {
|
|||||||
uint32 tem;
|
uint32 tem;
|
||||||
uint8 col;
|
uint8 col;
|
||||||
if (gNoBGFillColor == 0xFF)
|
if (gNoBGFillColor == 0xFF)
|
||||||
col = Pal[0];
|
col = READPAL(0);
|
||||||
else col = gNoBGFillColor;
|
else col = gNoBGFillColor;
|
||||||
tem = col | (col << 8) | (col << 16) | (col << 24);
|
tem = col | (col << 8) | (col << 16) | (col << 24);
|
||||||
tem |= 0x40404040;
|
tem |= 0x40404040;
|
||||||
@ -1243,12 +1296,16 @@ static void DoLine(void) {
|
|||||||
if (SpriteON)
|
if (SpriteON)
|
||||||
CopySprites(target);
|
CopySprites(target);
|
||||||
|
|
||||||
if (ScreenON || SpriteON) { // Yes, very el-cheapo.
|
//greyscale handling (mask some bits off the color) ? ? ?
|
||||||
|
if (ScreenON || SpriteON)
|
||||||
|
{
|
||||||
if (PPU[1] & 0x01) {
|
if (PPU[1] & 0x01) {
|
||||||
for (x = 63; x >= 0; x--)
|
for (x = 63; x >= 0; x--)
|
||||||
*(uint32*)&target[x << 2] = (*(uint32*)&target[x << 2]) & 0x30303030;
|
*(uint32*)&target[x << 2] = (*(uint32*)&target[x << 2]) & 0x30303030;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//some pathetic attempts at deemph
|
||||||
if ((PPU[1] >> 5) == 0x7) {
|
if ((PPU[1] >> 5) == 0x7) {
|
||||||
for (x = 63; x >= 0; x--)
|
for (x = 63; x >= 0; x--)
|
||||||
*(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0xc0c0c0c0;
|
*(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0xc0c0c0c0;
|
||||||
@ -1259,6 +1316,10 @@ static void DoLine(void) {
|
|||||||
for (x = 63; x >= 0; x--)
|
for (x = 63; x >= 0; x--)
|
||||||
*(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0x80808080;
|
*(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0x80808080;
|
||||||
|
|
||||||
|
//write the actual deemph
|
||||||
|
for (x = 63; x >= 0; x--)
|
||||||
|
*(uint32*)&dtarget[x << 2] = ((PPU[1]>>5)<<0)|((PPU[1]>>5)<<8)|((PPU[1]>>5)<<16)|((PPU[1]>>5)<<24);
|
||||||
|
|
||||||
sphitx = 0x100;
|
sphitx = 0x100;
|
||||||
|
|
||||||
if (ScreenON || SpriteON)
|
if (ScreenON || SpriteON)
|
||||||
@ -1362,10 +1423,10 @@ static void FetchSpriteData(void) {
|
|||||||
C = VRAMADR(vadr);
|
C = VRAMADR(vadr);
|
||||||
|
|
||||||
if (SpriteON)
|
if (SpriteON)
|
||||||
RENDER_LOG(vadr);
|
RENDER_LOGP(C);
|
||||||
dst.ca[0] = C[0];
|
dst.ca[0] = C[0];
|
||||||
if (SpriteON)
|
if (SpriteON)
|
||||||
RENDER_LOG(vadr + 8);
|
RENDER_LOGP(C + 8);
|
||||||
dst.ca[1] = C[8];
|
dst.ca[1] = C[8];
|
||||||
dst.x = spr->x;
|
dst.x = spr->x;
|
||||||
dst.atr = spr->atr;
|
dst.atr = spr->atr;
|
||||||
@ -1414,14 +1475,14 @@ static void FetchSpriteData(void) {
|
|||||||
else
|
else
|
||||||
C = VRAMADR(vadr);
|
C = VRAMADR(vadr);
|
||||||
if (SpriteON)
|
if (SpriteON)
|
||||||
RENDER_LOG(vadr);
|
RENDER_LOGP(C);
|
||||||
dst.ca[0] = C[0];
|
dst.ca[0] = C[0];
|
||||||
if (ns < 8) {
|
if (ns < 8) {
|
||||||
PPU_hook(0x2000);
|
PPU_hook(0x2000);
|
||||||
PPU_hook(vadr);
|
PPU_hook(vadr);
|
||||||
}
|
}
|
||||||
if (SpriteON)
|
if (SpriteON)
|
||||||
RENDER_LOG(vadr + 8);
|
RENDER_LOGP(C + 8);
|
||||||
dst.ca[1] = C[8];
|
dst.ca[1] = C[8];
|
||||||
dst.x = spr->x;
|
dst.x = spr->x;
|
||||||
dst.atr = spr->atr;
|
dst.atr = spr->atr;
|
||||||
@ -1466,7 +1527,7 @@ static void RefreshSprites(void) {
|
|||||||
|
|
||||||
int x = spr->x;
|
int x = spr->x;
|
||||||
uint8 *C;
|
uint8 *C;
|
||||||
uint8 *VB;
|
int VB;
|
||||||
|
|
||||||
pixdata = ppulut1[spr->ca[0]] | ppulut2[spr->ca[1]];
|
pixdata = ppulut1[spr->ca[0]] | ppulut2[spr->ca[1]];
|
||||||
J = spr->ca[0] | spr->ca[1];
|
J = spr->ca[0] | spr->ca[1];
|
||||||
@ -1488,75 +1549,75 @@ static void RefreshSprites(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
C = sprlinebuf + x;
|
C = sprlinebuf + x;
|
||||||
VB = (PALRAM + 0x10) + ((atr & 3) << 2);
|
VB = (0x10) + ((atr & 3) << 2);
|
||||||
|
|
||||||
if (atr & SP_BACK) {
|
if (atr & SP_BACK) {
|
||||||
if (atr & H_FLIP) {
|
if (atr & H_FLIP) {
|
||||||
if (J & 0x80) C[7] = VB[pixdata & 3] | 0x40;
|
if (J & 0x80) C[7] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x40) C[6] = VB[pixdata & 3] | 0x40;
|
if (J & 0x40) C[6] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x20) C[5] = VB[pixdata & 3] | 0x40;
|
if (J & 0x20) C[5] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x10) C[4] = VB[pixdata & 3] | 0x40;
|
if (J & 0x10) C[4] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x08) C[3] = VB[pixdata & 3] | 0x40;
|
if (J & 0x08) C[3] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x04) C[2] = VB[pixdata & 3] | 0x40;
|
if (J & 0x04) C[2] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x02) C[1] = VB[pixdata & 3] | 0x40;
|
if (J & 0x02) C[1] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x01) C[0] = VB[pixdata] | 0x40;
|
if (J & 0x01) C[0] = READPAL(VB | pixdata) | 0x40;
|
||||||
} else {
|
} else {
|
||||||
if (J & 0x80) C[0] = VB[pixdata & 3] | 0x40;
|
if (J & 0x80) C[0] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x40) C[1] = VB[pixdata & 3] | 0x40;
|
if (J & 0x40) C[1] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x20) C[2] = VB[pixdata & 3] | 0x40;
|
if (J & 0x20) C[2] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x10) C[3] = VB[pixdata & 3] | 0x40;
|
if (J & 0x10) C[3] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x08) C[4] = VB[pixdata & 3] | 0x40;
|
if (J & 0x08) C[4] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x04) C[5] = VB[pixdata & 3] | 0x40;
|
if (J & 0x04) C[5] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x02) C[6] = VB[pixdata & 3] | 0x40;
|
if (J & 0x02) C[6] = READPAL(VB | (pixdata & 3)) | 0x40;
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x01) C[7] = VB[pixdata] | 0x40;
|
if (J & 0x01) C[7] = READPAL(VB | pixdata) | 0x40;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (atr & H_FLIP) {
|
if (atr & H_FLIP) {
|
||||||
if (J & 0x80) C[7] = VB[pixdata & 3];
|
if (J & 0x80) C[7] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x40) C[6] = VB[pixdata & 3];
|
if (J & 0x40) C[6] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x20) C[5] = VB[pixdata & 3];
|
if (J & 0x20) C[5] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x10) C[4] = VB[pixdata & 3];
|
if (J & 0x10) C[4] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x08) C[3] = VB[pixdata & 3];
|
if (J & 0x08) C[3] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x04) C[2] = VB[pixdata & 3];
|
if (J & 0x04) C[2] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x02) C[1] = VB[pixdata & 3];
|
if (J & 0x02) C[1] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x01) C[0] = VB[pixdata];
|
if (J & 0x01) C[0] = READPAL(VB | pixdata);
|
||||||
} else {
|
} else {
|
||||||
if (J & 0x80) C[0] = VB[pixdata & 3];
|
if (J & 0x80) C[0] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x40) C[1] = VB[pixdata & 3];
|
if (J & 0x40) C[1] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x20) C[2] = VB[pixdata & 3];
|
if (J & 0x20) C[2] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x10) C[3] = VB[pixdata & 3];
|
if (J & 0x10) C[3] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x08) C[4] = VB[pixdata & 3];
|
if (J & 0x08) C[4] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x04) C[5] = VB[pixdata & 3];
|
if (J & 0x04) C[5] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x02) C[6] = VB[pixdata & 3];
|
if (J & 0x02) C[6] = READPAL(VB | (pixdata & 3));
|
||||||
pixdata >>= 4;
|
pixdata >>= 4;
|
||||||
if (J & 0x01) C[7] = VB[pixdata];
|
if (J & 0x01) C[7] = READPAL(VB | pixdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1640,10 +1701,12 @@ void FCEUPPU_SetVideoSystem(int w) {
|
|||||||
scanlines_per_frame = dendy ? 262: 312;
|
scanlines_per_frame = dendy ? 262: 312;
|
||||||
FSettings.FirstSLine = FSettings.UsrFirstSLine[1];
|
FSettings.FirstSLine = FSettings.UsrFirstSLine[1];
|
||||||
FSettings.LastSLine = FSettings.UsrLastSLine[1];
|
FSettings.LastSLine = FSettings.UsrLastSLine[1];
|
||||||
|
//paldeemphswap = 1; // dendy has pal ppu, and pal ppu has these swapped
|
||||||
} else {
|
} else {
|
||||||
scanlines_per_frame = 262;
|
scanlines_per_frame = 262;
|
||||||
FSettings.FirstSLine = FSettings.UsrFirstSLine[0];
|
FSettings.FirstSLine = FSettings.UsrFirstSLine[0];
|
||||||
FSettings.LastSLine = FSettings.UsrLastSLine[0];
|
FSettings.LastSLine = FSettings.UsrLastSLine[0];
|
||||||
|
//paldeemphswap = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1666,8 +1729,7 @@ void FCEUPPU_Reset(void) {
|
|||||||
kook = 0;
|
kook = 0;
|
||||||
idleSynch = 1;
|
idleSynch = 1;
|
||||||
|
|
||||||
ppur.reset();
|
new_ppu_reset = true; // delay reset of ppur/spr_read until it's ready to start a new frame
|
||||||
spr_read.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCEUPPU_Power(void) {
|
void FCEUPPU_Power(void) {
|
||||||
@ -1729,6 +1791,13 @@ int FCEUPPU_Loop(int skip) {
|
|||||||
TriggerNMI();
|
TriggerNMI();
|
||||||
}
|
}
|
||||||
X6502_Run((scanlines_per_frame - 242) * (256 + 85) - 12);
|
X6502_Run((scanlines_per_frame - 242) * (256 + 85) - 12);
|
||||||
|
if (overclock_enabled && vblankscanlines) {
|
||||||
|
if (!DMC_7bit || !skip_7bit_overclocking) {
|
||||||
|
overclocking = 1;
|
||||||
|
X6502_Run(vblankscanlines * (256 + 85) - 12);
|
||||||
|
overclocking = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
PPU_status &= 0x1f;
|
PPU_status &= 0x1f;
|
||||||
X6502_Run(256);
|
X6502_Run(256);
|
||||||
|
|
||||||
@ -1759,7 +1828,7 @@ int FCEUPPU_Loop(int skip) {
|
|||||||
kook ^= 1;
|
kook ^= 1;
|
||||||
}
|
}
|
||||||
if (GameInfo->type == GIT_NSF)
|
if (GameInfo->type == GIT_NSF)
|
||||||
X6502_Run((256 + 85) * (dendy ? 290 : 240));
|
X6502_Run((256 + 85) * normalscanlines);
|
||||||
#ifdef FRAMESKIP
|
#ifdef FRAMESKIP
|
||||||
else if (skip) {
|
else if (skip) {
|
||||||
int y;
|
int y;
|
||||||
@ -1785,24 +1854,42 @@ int FCEUPPU_Loop(int skip) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else {
|
else {
|
||||||
int x, max, maxref;
|
|
||||||
|
|
||||||
deemp = PPU[1] >> 5;
|
deemp = PPU[1] >> 5;
|
||||||
for (scanline = 0; scanline < (dendy ? 290 : 240); ) { //scanline is incremented in DoLine. Evil. :/
|
|
||||||
|
// manual samples can't play correctly with overclocking
|
||||||
|
if (DMC_7bit && skip_7bit_overclocking) // 7bit sample started before 240th line
|
||||||
|
totalscanlines = normalscanlines;
|
||||||
|
else
|
||||||
|
totalscanlines = normalscanlines + (overclock_enabled ? postrenderscanlines : 0);
|
||||||
|
|
||||||
|
for (scanline = 0; scanline < totalscanlines; ) { //scanline is incremented in DoLine. Evil. :/
|
||||||
deempcnt[deemp]++;
|
deempcnt[deemp]++;
|
||||||
if (scanline < 240)
|
if (scanline < 240)
|
||||||
DEBUG(FCEUD_UpdatePPUView(scanline, 1));
|
DEBUG(FCEUD_UpdatePPUView(scanline, 1));
|
||||||
DoLine();
|
DoLine();
|
||||||
|
|
||||||
|
if (scanline < normalscanlines || scanline == totalscanlines)
|
||||||
|
overclocking = 0;
|
||||||
|
else {
|
||||||
|
if (DMC_7bit && skip_7bit_overclocking) // 7bit sample started after 240th line
|
||||||
|
break;
|
||||||
|
overclocking = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
DMC_7bit = 0;
|
||||||
|
|
||||||
if (MMC5Hack) MMC5_hb(scanline);
|
if (MMC5Hack) MMC5_hb(scanline);
|
||||||
for (x = 1, max = 0, maxref = 0; x < 7; x++) {
|
|
||||||
|
//deemph nonsense, kept for complicated reasons (see SetNESDeemph_OldHacky implementation)
|
||||||
|
int maxref = 0;
|
||||||
|
for (int x = 1, max = 0; x < 7; x++) {
|
||||||
if (deempcnt[x] > max) {
|
if (deempcnt[x] > max) {
|
||||||
max = deempcnt[x];
|
max = deempcnt[x];
|
||||||
maxref = x;
|
maxref = x;
|
||||||
}
|
}
|
||||||
deempcnt[x] = 0;
|
deempcnt[x] = 0;
|
||||||
}
|
}
|
||||||
SetNESDeemph(maxref, 0);
|
SetNESDeemph_OldHacky(maxref, 0);
|
||||||
}
|
}
|
||||||
} //else... to if(ppudead)
|
} //else... to if(ppudead)
|
||||||
|
|
||||||
@ -1902,8 +1989,11 @@ const int kFetchTime = 2;
|
|||||||
|
|
||||||
void runppu(int x) {
|
void runppu(int x) {
|
||||||
ppur.status.cycle = (ppur.status.cycle + x) % ppur.status.end_cycle;
|
ppur.status.cycle = (ppur.status.cycle + x) % ppur.status.end_cycle;
|
||||||
|
if (!new_ppu_reset) // if resetting, suspend CPU until the first frame
|
||||||
|
{
|
||||||
X6502_Run(x);
|
X6502_Run(x);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//todo - consider making this a 3 or 4 slot fifo to keep from touching so much memory
|
//todo - consider making this a 3 or 4 slot fifo to keep from touching so much memory
|
||||||
struct BGData {
|
struct BGData {
|
||||||
@ -1911,7 +2001,7 @@ struct BGData {
|
|||||||
uint8 nt, pecnt, at, pt[2];
|
uint8 nt, pecnt, at, pt[2];
|
||||||
|
|
||||||
INLINE void Read() {
|
INLINE void Read() {
|
||||||
RefreshAddr = ppur.get_ntread();
|
NTRefreshAddr = RefreshAddr = ppur.get_ntread();
|
||||||
if (PEC586Hack)
|
if (PEC586Hack)
|
||||||
ppur.s = (RefreshAddr & 0x200) >> 9;
|
ppur.s = (RefreshAddr & 0x200) >> 9;
|
||||||
pecnt = (RefreshAddr & 1) << 3;
|
pecnt = (RefreshAddr & 1) << 3;
|
||||||
@ -1973,6 +2063,14 @@ static inline int PaletteAdjustPixel(int pixel) {
|
|||||||
|
|
||||||
int framectr = 0;
|
int framectr = 0;
|
||||||
int FCEUX_PPU_Loop(int skip) {
|
int FCEUX_PPU_Loop(int skip) {
|
||||||
|
|
||||||
|
if (new_ppu_reset) // first frame since reset, time to initialize
|
||||||
|
{
|
||||||
|
ppur.reset();
|
||||||
|
spr_read.reset();
|
||||||
|
new_ppu_reset = false;
|
||||||
|
}
|
||||||
|
|
||||||
//262 scanlines
|
//262 scanlines
|
||||||
if (ppudead) {
|
if (ppudead) {
|
||||||
// not quite emulating all the NES power up behavior
|
// not quite emulating all the NES power up behavior
|
||||||
@ -2003,12 +2101,20 @@ int FCEUX_PPU_Loop(int skip) {
|
|||||||
|
|
||||||
ppur.status.sl = 241; //for sprite reads
|
ppur.status.sl = 241; //for sprite reads
|
||||||
|
|
||||||
runppu(delay); //X6502_Run(12);
|
//formerly: runppu(delay);
|
||||||
|
for(int dot=0;dot<delay;dot++)
|
||||||
|
runppu(1);
|
||||||
|
|
||||||
if (VBlankON) TriggerNMI();
|
if (VBlankON) TriggerNMI();
|
||||||
if (PAL)
|
int sltodo = PAL?70:20;
|
||||||
runppu(70 * (kLineTime) - delay);
|
|
||||||
else
|
//formerly: runppu(20 * (kLineTime) - delay);
|
||||||
runppu(20 * (kLineTime) - delay);
|
for(int S=0;S<sltodo;S++)
|
||||||
|
{
|
||||||
|
for(int dot=(S==0?delay:0);dot<kLineTime;dot++)
|
||||||
|
runppu(1);
|
||||||
|
ppur.status.sl++;
|
||||||
|
}
|
||||||
|
|
||||||
//this seems to run just before the dummy scanline begins
|
//this seems to run just before the dummy scanline begins
|
||||||
PPU_status = 0;
|
PPU_status = 0;
|
||||||
@ -2032,7 +2138,8 @@ int FCEUX_PPU_Loop(int skip) {
|
|||||||
//capture the initial xscroll
|
//capture the initial xscroll
|
||||||
//int xscroll = ppur.fh;
|
//int xscroll = ppur.fh;
|
||||||
//render 241/291 scanlines (1 dummy at beginning, dendy's 50 at the end)
|
//render 241/291 scanlines (1 dummy at beginning, dendy's 50 at the end)
|
||||||
for (int sl = 0; sl < (dendy ? 291 : 241); sl++) {
|
//ignore overclocking!
|
||||||
|
for (int sl = 0; sl < normalscanlines; sl++) {
|
||||||
spr_read.start_scanline();
|
spr_read.start_scanline();
|
||||||
|
|
||||||
g_rasterpos = 0;
|
g_rasterpos = 0;
|
||||||
@ -2048,6 +2155,9 @@ int FCEUX_PPU_Loop(int skip) {
|
|||||||
DEBUG(FCEUD_UpdateNTView(scanline = yp, 1));
|
DEBUG(FCEUD_UpdateNTView(scanline = yp, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//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);
|
if (MMC5Hack) MMC5_hb(yp);
|
||||||
|
|
||||||
|
|
||||||
@ -2064,18 +2174,22 @@ int FCEUX_PPU_Loop(int skip) {
|
|||||||
for (int xt = 0; xt < 32; xt++) {
|
for (int xt = 0; xt < 32; xt++) {
|
||||||
bgdata.main[xt + 2].Read();
|
bgdata.main[xt + 2].Read();
|
||||||
|
|
||||||
|
const uint8 blank = (gNoBGFillColor == 0xFF) ? READPAL(0) : gNoBGFillColor;
|
||||||
|
|
||||||
//ok, we're also going to draw here.
|
//ok, we're also going to draw here.
|
||||||
//unless we're on the first dummy scanline
|
//unless we're on the first dummy scanline
|
||||||
if (sl != 0 && sl < 241) { // cape at 240 for dendy, its PPU does nothing afterwards
|
if (sl != 0 && sl < 241) { // cape at 240 for dendy, its PPU does nothing afterwards
|
||||||
int xstart = xt << 3;
|
int xstart = xt << 3;
|
||||||
oamcount = oamcounts[renderslot];
|
oamcount = oamcounts[renderslot];
|
||||||
uint8 * const target = XBuf + (yp << 8) + xstart;
|
uint8 * const target = XBuf + (yp << 8) + xstart;
|
||||||
|
uint8 * const dtarget = XDBuf + (yp << 8) + xstart;
|
||||||
uint8 *ptr = target;
|
uint8 *ptr = target;
|
||||||
|
uint8 *dptr = dtarget;
|
||||||
int rasterpos = xstart;
|
int rasterpos = xstart;
|
||||||
|
|
||||||
//check all the conditions that can cause things to render in these 8px
|
//check all the conditions that can cause things to render in these 8px
|
||||||
const bool renderspritenow = SpriteON && rendersprites && (xt > 0 || SpriteLeft8);
|
const bool renderspritenow = SpriteON && (xt > 0 || SpriteLeft8);
|
||||||
const bool renderbgnow = ScreenON && renderbg && (xt > 0 || BGLeft8);
|
const bool renderbgnow = ScreenON && (xt > 0 || BGLeft8);
|
||||||
for (int xp = 0; xp < 8; xp++, rasterpos++, g_rasterpos++) {
|
for (int xp = 0; xp < 8; xp++, rasterpos++, g_rasterpos++) {
|
||||||
//bg pos is different from raster pos due to its offsetability.
|
//bg pos is different from raster pos due to its offsetability.
|
||||||
//so adjust for that here
|
//so adjust for that here
|
||||||
@ -2083,14 +2197,28 @@ int FCEUX_PPU_Loop(int skip) {
|
|||||||
const int bgpx = bgpos & 7;
|
const int bgpx = bgpos & 7;
|
||||||
const int bgtile = bgpos >> 3;
|
const int bgtile = bgpos >> 3;
|
||||||
|
|
||||||
uint8 pixel = 0, pixelcolor;
|
uint8 pixel = 0;
|
||||||
|
uint8 pixelcolor = blank;
|
||||||
|
|
||||||
|
//according to qeed's doc, use palette 0 or $2006's value if it is & 0x3Fxx
|
||||||
|
if (!ScreenON && !SpriteON)
|
||||||
|
{
|
||||||
|
// if there's anything wrong with how we're doing this, someone please chime in
|
||||||
|
int addr = ppur.get_2007access();
|
||||||
|
if ((addr & 0x3F00) == 0x3F00)
|
||||||
|
{
|
||||||
|
pixel = addr & 0x1F;
|
||||||
|
}
|
||||||
|
pixelcolor = PALRAM[pixel];
|
||||||
|
}
|
||||||
|
|
||||||
//generate the BG data
|
//generate the BG data
|
||||||
if (renderbgnow) {
|
if (renderbgnow) {
|
||||||
uint8* pt = bgdata.main[bgtile].pt;
|
uint8* pt = bgdata.main[bgtile].pt;
|
||||||
pixel = ((pt[0] >> (7 - bgpx)) & 1) | (((pt[1] >> (7 - bgpx)) & 1) << 1) | bgdata.main[bgtile].at;
|
pixel = ((pt[0] >> (7 - bgpx)) & 1) | (((pt[1] >> (7 - bgpx)) & 1) << 1) | bgdata.main[bgtile].at;
|
||||||
}
|
}
|
||||||
pixelcolor = PALRAM[pixel];
|
if (renderbg)
|
||||||
|
pixelcolor = READPAL(pixel);
|
||||||
|
|
||||||
//look for a sprite to be drawn
|
//look for a sprite to be drawn
|
||||||
bool havepixel = false;
|
bool havepixel = false;
|
||||||
@ -2133,11 +2261,14 @@ int FCEUX_PPU_Loop(int skip) {
|
|||||||
|
|
||||||
//bring in the palette bits and palettize
|
//bring in the palette bits and palettize
|
||||||
spixel |= (oam[2] & 3) << 2;
|
spixel |= (oam[2] & 3) << 2;
|
||||||
pixelcolor = PALRAM[0x10 + spixel];
|
|
||||||
|
if (rendersprites)
|
||||||
|
pixelcolor = READPAL(0x10 + spixel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*ptr++ = PaletteAdjustPixel(pixelcolor);
|
*ptr++ = PaletteAdjustPixel(pixelcolor);
|
||||||
|
*dptr++= PPU[1]>>5; //grab deemph
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2264,6 +2395,14 @@ int FCEUX_PPU_Loop(int skip) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//blind attempt to replicate old ppu functionality
|
||||||
|
if(s == 2 && PPUON)
|
||||||
|
{
|
||||||
|
if (GameHBIRQHook2) {
|
||||||
|
GameHBIRQHook2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (realSprite) runppu(kFetchTime);
|
if (realSprite) runppu(kFetchTime);
|
||||||
|
|
||||||
|
|
||||||
@ -2318,6 +2457,8 @@ int FCEUX_PPU_Loop(int skip) {
|
|||||||
runppu(1);
|
runppu(1);
|
||||||
} //scanline loop
|
} //scanline loop
|
||||||
|
|
||||||
|
DMC_7bit = 0;
|
||||||
|
|
||||||
if (MMC5Hack) MMC5_hb(240);
|
if (MMC5Hack) MMC5_hb(240);
|
||||||
|
|
||||||
//idle for one line
|
//idle for one line
|
||||||
|
@ -9,6 +9,10 @@ void FCEUPPU_SetVideoSystem(int w);
|
|||||||
extern void (*PPU_hook)(uint32 A);
|
extern void (*PPU_hook)(uint32 A);
|
||||||
extern void (*GameHBIRQHook)(void), (*GameHBIRQHook2)(void);
|
extern void (*GameHBIRQHook)(void), (*GameHBIRQHook2)(void);
|
||||||
|
|
||||||
|
int newppu_get_scanline();
|
||||||
|
int newppu_get_dot();
|
||||||
|
void newppu_hacky_emergency_reset();
|
||||||
|
|
||||||
/* For cart.c and banksw.h, mostly */
|
/* For cart.c and banksw.h, mostly */
|
||||||
extern uint8 NTARAM[0x800], *vnapage[4];
|
extern uint8 NTARAM[0x800], *vnapage[4];
|
||||||
extern uint8 PPUNTARAM;
|
extern uint8 PPUNTARAM;
|
||||||
@ -18,10 +22,10 @@ void FCEUPPU_SaveState(void);
|
|||||||
void FCEUPPU_LoadState(int version);
|
void FCEUPPU_LoadState(int version);
|
||||||
uint32 FCEUPPU_PeekAddress();
|
uint32 FCEUPPU_PeekAddress();
|
||||||
uint8* FCEUPPU_GetCHR(uint32 vadr, uint32 refreshaddr);
|
uint8* FCEUPPU_GetCHR(uint32 vadr, uint32 refreshaddr);
|
||||||
|
int FCEUPPU_GetAttr(int ntnum, int xt, int yt);
|
||||||
void ppu_getScroll(int &xpos, int &ypos);
|
void ppu_getScroll(int &xpos, int &ypos);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define FASTCALL __fastcall
|
#define FASTCALL __fastcall
|
||||||
#else
|
#else
|
||||||
@ -34,9 +38,10 @@ extern void (*FFCEUX_PPUWrite)(uint32 A, uint8 V);
|
|||||||
extern uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A);
|
extern uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A);
|
||||||
void FFCEUX_PPUWrite_Default(uint32 A, uint8 V);
|
void FFCEUX_PPUWrite_Default(uint32 A, uint8 V);
|
||||||
|
|
||||||
extern int scanline;
|
|
||||||
extern int g_rasterpos;
|
extern int g_rasterpos;
|
||||||
extern uint8 PPU[4];
|
extern uint8 PPU[4];
|
||||||
|
extern bool DMC_7bit;
|
||||||
|
extern bool paldeemphswap;
|
||||||
|
|
||||||
enum PPUPHASE {
|
enum PPUPHASE {
|
||||||
PPUPHASE_VBL, PPUPHASE_BG, PPUPHASE_OBJ
|
PPUPHASE_VBL, PPUPHASE_BG, PPUPHASE_OBJ
|
||||||
|
@ -89,21 +89,21 @@ pshift[1] <<= 8;
|
|||||||
#ifdef PPU_BGFETCH
|
#ifdef PPU_BGFETCH
|
||||||
if (RefreshAddr & 1) {
|
if (RefreshAddr & 1) {
|
||||||
if(ScreenON)
|
if(ScreenON)
|
||||||
RENDER_LOG(vadr + 8);
|
RENDER_LOGP(C + 8);
|
||||||
pshift[0] |= C[8];
|
pshift[0] |= C[8];
|
||||||
pshift[1] |= C[8];
|
pshift[1] |= C[8];
|
||||||
} else {
|
} else {
|
||||||
if(ScreenON)
|
if(ScreenON)
|
||||||
RENDER_LOG(vadr);
|
RENDER_LOGP(C);
|
||||||
pshift[0] |= C[0];
|
pshift[0] |= C[0];
|
||||||
pshift[1] |= C[0];
|
pshift[1] |= C[0];
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if(ScreenON)
|
if(ScreenON)
|
||||||
RENDER_LOG(vadr);
|
RENDER_LOGP(C);
|
||||||
pshift[0] |= C[0];
|
pshift[0] |= C[0];
|
||||||
if(ScreenON)
|
if(ScreenON)
|
||||||
RENDER_LOG(vadr + 8);
|
RENDER_LOGP(C + 8);
|
||||||
pshift[1] |= C[8];
|
pshift[1] |= C[8];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ uint8 EnabledChannels=0; // $4015 / Sound channels enable and status
|
|||||||
uint8 IRQFrameMode=0; // $4017 / Frame counter control / xx000000
|
uint8 IRQFrameMode=0; // $4017 / Frame counter control / xx000000
|
||||||
|
|
||||||
uint8 InitialRawDALatch=0; // used only for lua
|
uint8 InitialRawDALatch=0; // used only for lua
|
||||||
|
bool DMC_7bit = 0; // used to skip overclocking
|
||||||
ENVUNIT EnvUnits[3];
|
ENVUNIT EnvUnits[3];
|
||||||
|
|
||||||
static const int RectDuties[4]={1,2,4,6};
|
static const int RectDuties[4]={1,2,4,6};
|
||||||
@ -90,19 +91,18 @@ static const uint8 lengthtable[0x20]=
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static const uint32 NoiseFreqTableNTSC[0x10] =
|
extern const uint32 NoiseFreqTableNTSC[0x10] =
|
||||||
{
|
{
|
||||||
4, 8, 16, 32, 64, 96, 128, 160, 202,
|
4, 8, 16, 32, 64, 96, 128, 160, 202,
|
||||||
254, 380, 508, 762, 1016, 2034, 4068
|
254, 380, 508, 762, 1016, 2034, 4068
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32 NoiseFreqTablePAL[0x10] =
|
extern const uint32 NoiseFreqTablePAL[0x10] =
|
||||||
{
|
{
|
||||||
4, 7, 14, 30, 60, 88, 118, 148, 188,
|
4, 7, 14, 30, 60, 88, 118, 148, 188,
|
||||||
236, 354, 472, 708, 944, 1890, 3778
|
236, 354, 472, 708, 944, 1890, 3778
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint32 *NoiseFreqTable = NoiseFreqTableNTSC; // for lua only
|
|
||||||
|
|
||||||
static const uint32 NTSCDMCTable[0x10]=
|
static const uint32 NTSCDMCTable[0x10]=
|
||||||
{
|
{
|
||||||
@ -233,10 +233,8 @@ static DECLFW(Write_PSG)
|
|||||||
DoSQ1();
|
DoSQ1();
|
||||||
EnvUnits[0].Mode=(V&0x30)>>4;
|
EnvUnits[0].Mode=(V&0x30)>>4;
|
||||||
EnvUnits[0].Speed=(V&0xF);
|
EnvUnits[0].Speed=(V&0xF);
|
||||||
#ifdef WIN32
|
|
||||||
if (swapDuty)
|
if (swapDuty)
|
||||||
V = (V&0x3F)|((V&0x80)>>1)|((V&0x40)<<1);
|
V = (V&0x3F)|((V&0x80)>>1)|((V&0x40)<<1);
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case 0x1:
|
case 0x1:
|
||||||
sweepon[0]=V&0x80;
|
sweepon[0]=V&0x80;
|
||||||
@ -253,10 +251,8 @@ static DECLFW(Write_PSG)
|
|||||||
DoSQ2();
|
DoSQ2();
|
||||||
EnvUnits[1].Mode=(V&0x30)>>4;
|
EnvUnits[1].Mode=(V&0x30)>>4;
|
||||||
EnvUnits[1].Speed=(V&0xF);
|
EnvUnits[1].Speed=(V&0xF);
|
||||||
#ifdef WIN32
|
|
||||||
if (swapDuty)
|
if (swapDuty)
|
||||||
V = (V&0x3F)|((V&0x80)>>1)|((V&0x40)<<1);
|
V = (V&0x3F)|((V&0x80)>>1)|((V&0x40)<<1);
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case 0x5:
|
case 0x5:
|
||||||
sweepon[1]=V&0x80;
|
sweepon[1]=V&0x80;
|
||||||
@ -315,7 +311,8 @@ static DECLFW(Write_DMCRegs)
|
|||||||
|
|
||||||
switch(A)
|
switch(A)
|
||||||
{
|
{
|
||||||
case 0x00:DoPCM();
|
case 0x00:
|
||||||
|
DoPCM();
|
||||||
LoadDMCPeriod(V&0xF);
|
LoadDMCPeriod(V&0xF);
|
||||||
|
|
||||||
if(SIRQStat&0x80)
|
if(SIRQStat&0x80)
|
||||||
@ -329,15 +326,24 @@ static DECLFW(Write_DMCRegs)
|
|||||||
}
|
}
|
||||||
DMCFormat=V;
|
DMCFormat=V;
|
||||||
break;
|
break;
|
||||||
case 0x01:DoPCM();
|
case 0x01:
|
||||||
|
DoPCM();
|
||||||
InitialRawDALatch=V&0x7F;
|
InitialRawDALatch=V&0x7F;
|
||||||
RawDALatch=InitialRawDALatch;
|
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;
|
break;
|
||||||
case 0x02:DMCAddressLatch=V;break;
|
|
||||||
case 0x03:DMCSizeLatch=V;break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static DECLFW(StatusWrite)
|
static DECLFW(StatusWrite)
|
||||||
@ -349,6 +355,7 @@ static DECLFW(StatusWrite)
|
|||||||
DoTriangle();
|
DoTriangle();
|
||||||
DoNoise();
|
DoNoise();
|
||||||
DoPCM();
|
DoPCM();
|
||||||
|
|
||||||
for(x=0;x<4;x++)
|
for(x=0;x<4;x++)
|
||||||
if(!(V&(1<<x))) lengthcount[x]=0; /* Force length counters to 0. */
|
if(!(V&(1<<x))) lengthcount[x]=0; /* Force length counters to 0. */
|
||||||
|
|
||||||
@ -1045,7 +1052,7 @@ int FlushEmulateSound(void)
|
|||||||
int x;
|
int x;
|
||||||
int32 end,left;
|
int32 end,left;
|
||||||
|
|
||||||
if(!timestamp) return(0);
|
if(!soundtimestamp) return(0);
|
||||||
|
|
||||||
if(!FSettings.SndRate)
|
if(!FSettings.SndRate)
|
||||||
{
|
{
|
||||||
@ -1066,7 +1073,7 @@ int FlushEmulateSound(void)
|
|||||||
|
|
||||||
if(GameExpSound.HiFill) GameExpSound.HiFill();
|
if(GameExpSound.HiFill) GameExpSound.HiFill();
|
||||||
|
|
||||||
for(x=timestamp;x;x--)
|
for(x=soundtimestamp;x;x--)
|
||||||
{
|
{
|
||||||
uint32 b=*tmpo;
|
uint32 b=*tmpo;
|
||||||
*tmpo=(b&65535)+wlookup2[(b>>16)&255]+wlookup1[b>>24];
|
*tmpo=(b&65535)+wlookup2[(b>>16)&255]+wlookup1[b>>24];
|
||||||
|
@ -59,7 +59,7 @@ extern unsigned char *cdloggerdata;
|
|||||||
|
|
||||||
extern uint32 soundtsoffs;
|
extern uint32 soundtsoffs;
|
||||||
extern bool swapDuty;
|
extern bool swapDuty;
|
||||||
#define SOUNDTS (timestamp + soundtsoffs)
|
#define SOUNDTS (soundtimestamp + soundtsoffs)
|
||||||
|
|
||||||
void SetNESSoundMap(void);
|
void SetNESSoundMap(void);
|
||||||
void FrameSoundUpdate(void);
|
void FrameSoundUpdate(void);
|
||||||
|
@ -974,8 +974,12 @@ void FCEUI_LoadState(const char *fname, bool display_message)
|
|||||||
loadStateFailed = 1;
|
loadStateFailed = 1;
|
||||||
return; // state doesn't exist; exit cleanly
|
return; // state doesn't exist; exit cleanly
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FCEUSS_Load(fname, display_message))
|
if (FCEUSS_Load(fname, display_message))
|
||||||
{
|
{
|
||||||
|
//in case we're loading a savestate made with old ppu, we need to make sure ppur's regs used for dividing are ready to go
|
||||||
|
newppu_hacky_emergency_reset();
|
||||||
|
|
||||||
//mbg todo netplay
|
//mbg todo netplay
|
||||||
#if 0
|
#if 0
|
||||||
if(FCEUnetplay)
|
if(FCEUnetplay)
|
||||||
|
@ -44,10 +44,9 @@ typedef signed short int16;
|
|||||||
typedef signed int int32;
|
typedef signed int int32;
|
||||||
#define dup _dup
|
#define dup _dup
|
||||||
#define stat _stat
|
#define stat _stat
|
||||||
#define fstat _fstat
|
|
||||||
#define mkdir _mkdir
|
#define mkdir _mkdir
|
||||||
#define alloca _alloca
|
#define alloca _alloca
|
||||||
#define snprintf _snprintf
|
#define FCEUX_fstat _fstat
|
||||||
#if _MSC_VER < 1500
|
#if _MSC_VER < 1500
|
||||||
#define vsnprintf _vsnprintf
|
#define vsnprintf _vsnprintf
|
||||||
#endif
|
#endif
|
||||||
@ -74,6 +73,8 @@ typedef int32_t int32;
|
|||||||
typedef uint8_t uint8;
|
typedef uint8_t uint8;
|
||||||
typedef uint16_t uint16;
|
typedef uint16_t uint16;
|
||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
|
|
||||||
|
#define FCEUX_fstat fstat
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
@ -118,6 +118,7 @@ static void MooMirroring(void) {
|
|||||||
if (mirrortodo < 0x4)
|
if (mirrortodo < 0x4)
|
||||||
SetupCartMirroring(mirrortodo, 1, 0);
|
SetupCartMirroring(mirrortodo, 1, 0);
|
||||||
else if (mirrortodo == 0x4) {
|
else if (mirrortodo == 0x4) {
|
||||||
|
FCEU_MemoryRand(exntar, sizeof(exntar), true);
|
||||||
SetupCartMirroring(4, 1, exntar);
|
SetupCartMirroring(4, 1, exntar);
|
||||||
AddExState(exntar, 2048, 0, "EXNR");
|
AddExState(exntar, 2048, 0, "EXNR");
|
||||||
} else
|
} else
|
||||||
@ -348,6 +349,7 @@ static BMAPPING bmap[] = {
|
|||||||
{ "BS-5", BMCBS5_Init, 0 },
|
{ "BS-5", BMCBS5_Init, 0 },
|
||||||
{ "CC-21", UNLCC21_Init, 0 },
|
{ "CC-21", UNLCC21_Init, 0 },
|
||||||
{ "CITYFIGHT", UNLCITYFIGHT_Init, 0 },
|
{ "CITYFIGHT", UNLCITYFIGHT_Init, 0 },
|
||||||
|
{ "10-24-C-A1", BMC1024CA1_Init, 0 },
|
||||||
{ "CNROM", CNROM_Init, 0 },
|
{ "CNROM", CNROM_Init, 0 },
|
||||||
{ "CPROM", CPROM_Init, BMCFLAG_16KCHRR },
|
{ "CPROM", CPROM_Init, BMCFLAG_16KCHRR },
|
||||||
{ "D1038", BMCD1038_Init, 0 },
|
{ "D1038", BMCD1038_Init, 0 },
|
||||||
@ -374,6 +376,7 @@ static BMAPPING bmap[] = {
|
|||||||
{ "KS7010", UNLKS7010_Init, 0 },
|
{ "KS7010", UNLKS7010_Init, 0 },
|
||||||
{ "KS7012", UNLKS7012_Init, 0 },
|
{ "KS7012", UNLKS7012_Init, 0 },
|
||||||
{ "KS7013B", UNLKS7013B_Init, 0 },
|
{ "KS7013B", UNLKS7013B_Init, 0 },
|
||||||
|
{ "KS7016", UNLKS7016_Init, 0 },
|
||||||
{ "KS7017", UNLKS7017_Init, 0 },
|
{ "KS7017", UNLKS7017_Init, 0 },
|
||||||
{ "KS7030", UNLKS7030_Init, 0 },
|
{ "KS7030", UNLKS7030_Init, 0 },
|
||||||
{ "KS7031", UNLKS7031_Init, 0 },
|
{ "KS7031", UNLKS7031_Init, 0 },
|
||||||
@ -462,6 +465,16 @@ static BMAPPING bmap[] = {
|
|||||||
{ "YOKO", UNLYOKO_Init, 0 },
|
{ "YOKO", UNLYOKO_Init, 0 },
|
||||||
{ "SB-2000", UNLSB2000_Init, 0 },
|
{ "SB-2000", UNLSB2000_Init, 0 },
|
||||||
{ "COOLBOY", COOLBOY_Init, BMCFLAG_256KCHRR },
|
{ "COOLBOY", COOLBOY_Init, BMCFLAG_256KCHRR },
|
||||||
|
{ "158B", UNL158B_Init, 0 },
|
||||||
|
{ "DRAGONFIGHTER", UNLBMW8544_Init, 0 },
|
||||||
|
{ "EH8813A", UNLEH8813A_Init, 0 },
|
||||||
|
{ "HP898F", BMCHP898F_Init, 0 },
|
||||||
|
{ "F-15", BMCF15_Init, 0 },
|
||||||
|
{ "RT-01", UNLRT01_Init, 0 },
|
||||||
|
{ "81-01-31-C", BMC810131C_Init, 0 },
|
||||||
|
{ "8-IN-1", BMC8IN1_Init, 0 },
|
||||||
|
{ "80013-B", BMC80013B_Init, 0 },
|
||||||
|
{ "HPxx", BMCHPxx_Init, 0 },
|
||||||
|
|
||||||
{ 0, 0, 0 }
|
{ 0, 0, 0 }
|
||||||
};
|
};
|
||||||
@ -614,6 +627,7 @@ int UNIFLoad(const char *name, FCEUFILE *fp) {
|
|||||||
|
|
||||||
strcpy(LoadedRomFName, name); //For the debugger list
|
strcpy(LoadedRomFName, name); //For the debugger list
|
||||||
GameInterface = UNIFGI;
|
GameInterface = UNIFGI;
|
||||||
|
currCartInfo = &UNIFCart;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
aborto:
|
aborto:
|
||||||
|
@ -43,6 +43,7 @@ void BMCGhostbusters63in1_Init(CartInfo *info);
|
|||||||
void BMCNTD03_Init(CartInfo *info);
|
void BMCNTD03_Init(CartInfo *info);
|
||||||
void BMCT2271_Init(CartInfo *info);
|
void BMCT2271_Init(CartInfo *info);
|
||||||
void BMCT262_Init(CartInfo *info);
|
void BMCT262_Init(CartInfo *info);
|
||||||
|
void BMC1024CA1_Init(CartInfo *info);
|
||||||
void CNROM_Init(CartInfo *info);
|
void CNROM_Init(CartInfo *info);
|
||||||
void CPROM_Init(CartInfo *info);
|
void CPROM_Init(CartInfo *info);
|
||||||
void DreamTech01_Init(CartInfo *info);
|
void DreamTech01_Init(CartInfo *info);
|
||||||
@ -122,6 +123,7 @@ void UNLH2288_Init(CartInfo *info);
|
|||||||
void UNLKOF97_Init(CartInfo *info);
|
void UNLKOF97_Init(CartInfo *info);
|
||||||
void UNLKS7012_Init(CartInfo *info);
|
void UNLKS7012_Init(CartInfo *info);
|
||||||
void UNLKS7013B_Init(CartInfo *info);
|
void UNLKS7013B_Init(CartInfo *info);
|
||||||
|
void UNLKS7016_Init(CartInfo *info);
|
||||||
void UNLKS7017_Init(CartInfo *info);
|
void UNLKS7017_Init(CartInfo *info);
|
||||||
void UNLKS7030_Init(CartInfo *info);
|
void UNLKS7030_Init(CartInfo *info);
|
||||||
void UNLKS7031_Init(CartInfo *info);
|
void UNLKS7031_Init(CartInfo *info);
|
||||||
@ -146,6 +148,16 @@ void UNROM512_Init(CartInfo *info);
|
|||||||
void UNLSB2000_Init(CartInfo *info);
|
void UNLSB2000_Init(CartInfo *info);
|
||||||
void UNLKS7010_Init(CartInfo *info);
|
void UNLKS7010_Init(CartInfo *info);
|
||||||
void COOLBOY_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
|
extern uint8 *UNIFchrrama; // Meh. So I can stop CHR RAM
|
||||||
// bank switcherooing with certain boards...
|
// bank switcherooing with certain boards...
|
||||||
|
@ -39,11 +39,7 @@ void *FCEU_gmalloc(uint32 size)
|
|||||||
FCEU_PrintError("Error allocating memory! Doing a hard exit.");
|
FCEU_PrintError("Error allocating memory! Doing a hard exit.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
//mbg 6/17/08 - sometimes this memory is used as RAM or somesuch without clearing first.
|
FCEU_MemoryRand((uint8*)ret,size,true); // initialize according to RAMInitOption, default zero
|
||||||
//this yields different behavior in debug and release modes.
|
|
||||||
//specifically, saveram wasnt getting cleared so the games thought their savefiles were initialized
|
|
||||||
//so we are going to clear it here.
|
|
||||||
memset(ret,0,size);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,11 +53,7 @@ void *FCEU_malloc(uint32 size)
|
|||||||
FCEU_PrintError("Error allocating memory!");
|
FCEU_PrintError("Error allocating memory!");
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
//mbg 6/17/08 - sometimes this memory is used as RAM or somesuch without clearing first.
|
memset(ret,0,size); // initialize to 0
|
||||||
//this yields different behavior in debug and release modes.
|
|
||||||
//specifically, saveram wasnt getting cleared so the games thought their savefiles were initialized
|
|
||||||
//so we are going to clear it here.
|
|
||||||
memset(ret,0,size);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
|
|
||||||
#define FCEU_dwmemset(d,c,n) {int _x; for(_x=n-4;_x>=0;_x-=4) *(uint32 *)&(d)[_x]=c;}
|
#define FCEU_dwmemset(d,c,n) {int _x; for(_x=n-4;_x>=0;_x-=4) *(uint32 *)&(d)[_x]=c;}
|
||||||
|
|
||||||
void *FCEU_malloc(uint32 size);
|
void *FCEU_malloc(uint32 size); // initialized to 0
|
||||||
void *FCEU_gmalloc(uint32 size);
|
void *FCEU_gmalloc(uint32 size); // used by boards for WRAM etc, initialized to 0 (default) or other via RAMInitOption
|
||||||
void FCEU_gfree(void *ptr);
|
void FCEU_gfree(void *ptr);
|
||||||
void FCEU_free(void *ptr);
|
void FCEU_free(void *ptr);
|
||||||
void FCEU_memmove(void *d, void *s, uint32 l);
|
void FCEU_memmove(void *d, void *s, uint32 l);
|
||||||
|
@ -231,8 +231,8 @@ std::string BytesToString(const void* data, int len)
|
|||||||
{
|
{
|
||||||
Base64Table[ input[0] >> 2 ],
|
Base64Table[ input[0] >> 2 ],
|
||||||
Base64Table[ ((input[0] & 0x03) << 4) | (input[1] >> 4) ],
|
Base64Table[ ((input[0] & 0x03) << 4) | (input[1] >> 4) ],
|
||||||
n<2 ? '=' : Base64Table[ ((input[1] & 0x0F) << 2) | (input[2] >> 6) ],
|
static_cast<unsigned char> (n<2 ? '=' : Base64Table[ ((input[1] & 0x0F) << 2) | (input[2] >> 6) ]),
|
||||||
n<3 ? '=' : Base64Table[ input[2] & 0x3F ]
|
static_cast<unsigned char> (n<3 ? '=' : Base64Table[ input[2] & 0x3F ])
|
||||||
};
|
};
|
||||||
ret.append(output, output+4);
|
ret.append(output, output+4);
|
||||||
}
|
}
|
||||||
@ -296,9 +296,9 @@ bool StringToBytes(const std::string& str, void* data, int len)
|
|||||||
}
|
}
|
||||||
unsigned char outpacket[3] =
|
unsigned char outpacket[3] =
|
||||||
{
|
{
|
||||||
(converted[0] << 2) | (converted[1] >> 4),
|
static_cast<unsigned char>((converted[0] << 2) | (converted[1] >> 4)),
|
||||||
(converted[1] << 4) | (converted[2] >> 2),
|
static_cast<unsigned char>((converted[1] << 4) | (converted[2] >> 2)),
|
||||||
(converted[2] << 6) | (converted[3])
|
static_cast<unsigned char>((converted[2] << 6) | (converted[3]))
|
||||||
};
|
};
|
||||||
int outlen = (input[2] == '=') ? 1 : (input[3] == '=' ? 2 : 3);
|
int outlen = (input[2] == '=') ? 1 : (input[3] == '=' ? 2 : 3);
|
||||||
if(outlen > len) outlen = len;
|
if(outlen > len) outlen = len;
|
||||||
|
@ -26,12 +26,12 @@
|
|||||||
|
|
||||||
//todo - everyone will want to support this eventually, i suppose
|
//todo - everyone will want to support this eventually, i suppose
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include "svnrev.h"
|
#include "scmrev.h"
|
||||||
#else
|
#else
|
||||||
#ifdef SVN_REV
|
#ifdef SVN_REV
|
||||||
#define SVN_REV_STR SVN_REV
|
#define SCM_REV_STR SCM_REV
|
||||||
#else
|
#else
|
||||||
#define SVN_REV_STR ""
|
#define SCM_REV_STR ""
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -44,7 +44,7 @@
|
|||||||
#elif defined(PUBLIC_RELEASE)
|
#elif defined(PUBLIC_RELEASE)
|
||||||
#define FCEU_SUBVERSION_STRING ""
|
#define FCEU_SUBVERSION_STRING ""
|
||||||
#else
|
#else
|
||||||
#define FCEU_SUBVERSION_STRING "-interim svn" SVN_REV_STR
|
#define FCEU_SUBVERSION_STRING "-interim git" SCM_REV_STR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "vsuni.h"
|
#include "vsuni.h"
|
||||||
#include "drawing.h"
|
#include "drawing.h"
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
|
||||||
#ifdef _S9XLUA_H
|
#ifdef _S9XLUA_H
|
||||||
#include "fceulua.h"
|
#include "fceulua.h"
|
||||||
#endif
|
#endif
|
||||||
@ -56,10 +57,17 @@
|
|||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
uint8 *XBuf=NULL;
|
//XBuf:
|
||||||
uint8 *XBackBuf=NULL;
|
//0-63 is reserved for 7 special colours used by FCEUX (overlay, etc.)
|
||||||
|
//64-127 is the most-used emphasis setting per frame
|
||||||
|
//128-195 is the palette with no emphasis
|
||||||
|
//196-255 is the palette with all emphasis bits on
|
||||||
|
u8 *XBuf=NULL; //used for current display
|
||||||
|
u8 *XBackBuf=NULL; //ppu output is stashed here before drawing happens
|
||||||
|
u8 *XDBuf=NULL; //corresponding to XBuf but with deemph bits
|
||||||
|
u8 *XDBackBuf=NULL; //corresponding to XBackBuf but with deemph bits
|
||||||
int ClipSidesOffset=0; //Used to move displayed messages when Clips left and right sides is checked
|
int ClipSidesOffset=0; //Used to move displayed messages when Clips left and right sides is checked
|
||||||
static uint8 *xbsave=NULL;
|
static u8 *xbsave=NULL;
|
||||||
|
|
||||||
GUIMESSAGE guiMessage;
|
GUIMESSAGE guiMessage;
|
||||||
GUIMESSAGE subtitleMessage;
|
GUIMESSAGE subtitleMessage;
|
||||||
@ -105,12 +113,16 @@ void FCEU_KillVirtualVideo(void)
|
|||||||
**/
|
**/
|
||||||
int FCEU_InitVirtualVideo(void)
|
int FCEU_InitVirtualVideo(void)
|
||||||
{
|
{
|
||||||
if(!XBuf) /* Some driver code may allocate XBuf externally. */
|
//Some driver code may allocate XBuf externally.
|
||||||
/* 256 bytes per scanline, * 240 scanline maximum, +16 for alignment,
|
//256 bytes per scanline, * 240 scanline maximum, +16 for alignment,
|
||||||
*/
|
if(XBuf)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if(!(XBuf= (uint8*) (FCEU_malloc(256 * 256 + 16))) ||
|
XBuf = (u8*)FCEU_malloc(256 * 256 + 16);
|
||||||
!(XBackBuf= (uint8*) (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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -124,7 +136,9 @@ int FCEU_InitVirtualVideo(void)
|
|||||||
XBuf+=m;
|
XBuf+=m;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(XBuf,128,256*256); //*240);
|
memset(XBuf,128,256*256);
|
||||||
|
memset(XBackBuf,128,256*256);
|
||||||
|
memset(XBuf,128,256*256);
|
||||||
memset(XBackBuf,128,256*256);
|
memset(XBackBuf,128,256*256);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -551,11 +565,14 @@ int GetScreenPixelPalette(int x, int y, bool usebackup) {
|
|||||||
|
|
||||||
int SaveSnapshot(void)
|
int SaveSnapshot(void)
|
||||||
{
|
{
|
||||||
|
#ifdef GEKKO
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
int totallines=FSettings.LastSLine-FSettings.FirstSLine+1;
|
int totallines=FSettings.LastSLine-FSettings.FirstSLine+1;
|
||||||
int x,u,y;
|
int x,u,y;
|
||||||
FILE *pp=NULL;
|
FILE *pp=NULL;
|
||||||
uint8 *compmem=NULL;
|
uint8 *compmem=NULL;
|
||||||
uLongf compmemsize=totallines*263+12;
|
uLongf compmemsize=(totallines*263+12)*3;
|
||||||
|
|
||||||
if(!(compmem=(uint8 *)FCEU_malloc(compmemsize)))
|
if(!(compmem=(uint8 *)FCEU_malloc(compmemsize)))
|
||||||
return 0;
|
return 0;
|
||||||
@ -575,7 +592,7 @@ int SaveSnapshot(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
static uint8 header[8]={137,80,78,71,13,10,26,10};
|
static const uint8 header[8]={137,80,78,71,13,10,26,10};
|
||||||
if(fwrite(header,8,1,pp)!=1)
|
if(fwrite(header,8,1,pp)!=1)
|
||||||
goto PNGerr;
|
goto PNGerr;
|
||||||
}
|
}
|
||||||
@ -589,8 +606,8 @@ int SaveSnapshot(void)
|
|||||||
chunko[4]=chunko[5]=chunko[6]=0;
|
chunko[4]=chunko[5]=chunko[6]=0;
|
||||||
chunko[7]=totallines; // Height
|
chunko[7]=totallines; // Height
|
||||||
|
|
||||||
chunko[8]=8; // bit depth
|
chunko[8]=8; // 8 bits per sample(24 bits per pixel)
|
||||||
chunko[9]=3; // Color type; indexed 8-bit
|
chunko[9]=2; // Color type; RGB triplet
|
||||||
chunko[10]=0; // compression: deflate
|
chunko[10]=0; // compression: deflate
|
||||||
chunko[11]=0; // Basic adapative filter set(though none are used).
|
chunko[11]=0; // Basic adapative filter set(though none are used).
|
||||||
chunko[12]=0; // No interlace.
|
chunko[12]=0; // No interlace.
|
||||||
@ -599,19 +616,12 @@ int SaveSnapshot(void)
|
|||||||
goto PNGerr;
|
goto PNGerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
uint8 pdata[256*3];
|
|
||||||
for(x=0;x<256;x++)
|
|
||||||
FCEUD_GetPalette(x,pdata+x*3,pdata+x*3+1,pdata+x*3+2);
|
|
||||||
if(!WritePNGChunk(pp,256*3,"PLTE",pdata))
|
|
||||||
goto PNGerr;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
uint8 *tmp=XBuf+FSettings.FirstSLine*256;
|
uint8 *tmp=XBuf+FSettings.FirstSLine*256;
|
||||||
uint8 *dest,*mal,*mork;
|
uint8 *dest,*mal,*mork;
|
||||||
|
|
||||||
if(!(mal=mork=dest=(uint8 *)FCEU_dmalloc((totallines<<8)+totallines)))
|
int bufsize = (256*3+1)*totallines;
|
||||||
|
if(!(mal=mork=dest=(uint8 *)FCEU_dmalloc(bufsize)))
|
||||||
goto PNGerr;
|
goto PNGerr;
|
||||||
// mork=dest=XBuf;
|
// mork=dest=XBuf;
|
||||||
|
|
||||||
@ -619,11 +629,17 @@ int SaveSnapshot(void)
|
|||||||
{
|
{
|
||||||
*dest=0; // No filter.
|
*dest=0; // No filter.
|
||||||
dest++;
|
dest++;
|
||||||
for(x=256;x;x--,tmp++,dest++)
|
for(x=256;x;x--)
|
||||||
*dest=*tmp;
|
{
|
||||||
|
u32 color = ModernDeemphColorMap(tmp,XBuf,1,1);
|
||||||
|
*dest++=(color>>0x10)&0xFF;
|
||||||
|
*dest++=(color>>0x08)&0xFF;
|
||||||
|
*dest++=(color>>0x00)&0xFF;
|
||||||
|
tmp++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(compress(compmem,&compmemsize,mork,(totallines<<8)+totallines)!=Z_OK)
|
if(compress(compmem,&compmemsize,mork,bufsize)!=Z_OK)
|
||||||
{
|
{
|
||||||
if(mal) free(mal);
|
if(mal) free(mal);
|
||||||
goto PNGerr;
|
goto PNGerr;
|
||||||
@ -647,6 +663,7 @@ PNGerr:
|
|||||||
if(pp)
|
if(pp)
|
||||||
fclose(pp);
|
fclose(pp);
|
||||||
return(0);
|
return(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//overloaded SaveSnapshot for "Savesnapshot As" function
|
//overloaded SaveSnapshot for "Savesnapshot As" function
|
||||||
|
@ -9,6 +9,8 @@ uint32 GetScreenPixel(int x, int y, bool usebackup);
|
|||||||
int GetScreenPixelPalette(int x, int y, bool usebackup);
|
int GetScreenPixelPalette(int x, int y, bool usebackup);
|
||||||
extern uint8 *XBuf;
|
extern uint8 *XBuf;
|
||||||
extern uint8 *XBackBuf;
|
extern uint8 *XBackBuf;
|
||||||
|
extern uint8 *XDBuf;
|
||||||
|
extern uint8 *XDBackBuf;
|
||||||
extern int ClipSidesOffset;
|
extern int ClipSidesOffset;
|
||||||
extern struct GUIMESSAGE
|
extern struct GUIMESSAGE
|
||||||
{
|
{
|
||||||
|
@ -301,7 +301,7 @@ void FCEU_VSUniCheck(uint64 md5partial, int *MapperNo, uint8 *Mirroring) {
|
|||||||
|
|
||||||
while (vs->name) {
|
while (vs->name) {
|
||||||
if (md5partial == vs->md5partial) {
|
if (md5partial == vs->md5partial) {
|
||||||
if (vs->ppu < RCP2C03B) pale = vs->ppu;
|
if (vs->ppu < RCP2C03B) default_palette_selection = vs->ppu;
|
||||||
*MapperNo = vs->mapper;
|
*MapperNo = vs->mapper;
|
||||||
*Mirroring = vs->mirroring;
|
*Mirroring = vs->mirroring;
|
||||||
GameInfo->type = GIT_VSUNI;
|
GameInfo->type = GIT_VSUNI;
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
X6502 X;
|
X6502 X;
|
||||||
uint32 timestamp;
|
uint32 timestamp;
|
||||||
|
uint32 soundtimestamp;
|
||||||
void (*MapIRQHook)(int a);
|
void (*MapIRQHook)(int a);
|
||||||
|
|
||||||
#define ADDCYC(x) \
|
#define ADDCYC(x) \
|
||||||
@ -40,6 +41,7 @@ void (*MapIRQHook)(int a);
|
|||||||
_tcount+=__x; \
|
_tcount+=__x; \
|
||||||
_count-=__x*48; \
|
_count-=__x*48; \
|
||||||
timestamp+=__x; \
|
timestamp+=__x; \
|
||||||
|
if(!overclocking) soundtimestamp+=__x; \
|
||||||
}
|
}
|
||||||
|
|
||||||
//normal memory read
|
//normal memory read
|
||||||
@ -404,12 +406,14 @@ void X6502_Init(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int StackAddrBackup;
|
||||||
void X6502_Power(void)
|
void X6502_Power(void)
|
||||||
{
|
{
|
||||||
_count=_tcount=_IRQlow=_PC=_A=_X=_Y=_P=_PI=_DB=_jammed=0;
|
_count=_tcount=_IRQlow=_PC=_A=_X=_Y=_P=_PI=_DB=_jammed=0;
|
||||||
_S=0xFD;
|
_S=0xFD;
|
||||||
timestamp=0;
|
timestamp=soundtimestamp=0;
|
||||||
X6502_Reset();
|
X6502_Reset();
|
||||||
|
StackAddrBackup = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void X6502_Run(int32 cycles)
|
void X6502_Run(int32 cycles)
|
||||||
@ -493,6 +497,8 @@ extern int test; test++;
|
|||||||
temp=_tcount;
|
temp=_tcount;
|
||||||
_tcount=0;
|
_tcount=0;
|
||||||
if(MapIRQHook) MapIRQHook(temp);
|
if(MapIRQHook) MapIRQHook(temp);
|
||||||
|
|
||||||
|
if (!overclocking)
|
||||||
FCEU_SoundCPUHook(temp);
|
FCEU_SoundCPUHook(temp);
|
||||||
#ifdef _S9XLUA_H
|
#ifdef _S9XLUA_H
|
||||||
CallRegisteredLuaMemHook(_PC, 1, 0, LUAMEMHOOK_EXEC);
|
CallRegisteredLuaMemHook(_PC, 1, 0, LUAMEMHOOK_EXEC);
|
||||||
@ -569,20 +575,58 @@ const uint8 opsize[256] = {
|
|||||||
// 8 = Zero Page,Y
|
// 8 = Zero Page,Y
|
||||||
//
|
//
|
||||||
const uint8 optype[256] = {
|
const uint8 optype[256] = {
|
||||||
/*0x00*/ 0,1,0,0,0,2,2,0,0,0,0,0,0,3,3,0,
|
/*0x00*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||||
/*0x10*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0,
|
/*0x10*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
|
||||||
/*0x20*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0,
|
/*0x20*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||||
/*0x30*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0,
|
/*0x30*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
|
||||||
/*0x40*/ 0,1,0,0,0,2,2,0,0,0,0,0,0,3,3,0,
|
/*0x40*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||||
/*0x50*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0,
|
/*0x50*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
|
||||||
/*0x60*/ 0,1,0,0,0,2,2,0,0,0,0,0,3,3,3,0,
|
/*0x60*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||||
/*0x70*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0,
|
/*0x70*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
|
||||||
/*0x80*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0,
|
/*0x80*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||||
/*0x90*/ 0,4,0,0,5,5,8,0,0,6,0,0,0,7,0,0,
|
/*0x90*/ 0,4,0,3,5,5,8,8,0,6,0,6,7,7,6,6,
|
||||||
/*0xA0*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0,
|
/*0xA0*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||||
/*0xB0*/ 0,4,0,0,5,5,8,0,0,6,0,0,7,7,6,0,
|
/*0xB0*/ 0,4,0,3,5,5,8,8,0,6,0,6,7,7,6,6,
|
||||||
/*0xC0*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0,
|
/*0xC0*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||||
/*0xD0*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0,
|
/*0xD0*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
|
||||||
/*0xE0*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0,
|
/*0xE0*/ 0,1,0,1,2,2,2,2,0,0,0,0,3,3,3,3,
|
||||||
/*0xF0*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0
|
/*0xF0*/ 0,4,0,3,5,5,5,5,0,6,0,6,7,7,7,7,
|
||||||
|
};
|
||||||
|
|
||||||
|
// the opwrite table aids in predicting the value written for any 6502 opcode
|
||||||
|
//
|
||||||
|
// 0 = No value written
|
||||||
|
// 1 = Write from A
|
||||||
|
// 2 = Write from X
|
||||||
|
// 3 = Write from Y
|
||||||
|
// 4 = Write from P
|
||||||
|
// 5 = ASL (SLO)
|
||||||
|
// 6 = LSR (SRE)
|
||||||
|
// 7 = ROL (RLA)
|
||||||
|
// 8 = ROR (RRA)
|
||||||
|
// 9 = INC (ISC)
|
||||||
|
// 10 = DEC (DCP)
|
||||||
|
// 11 = (SAX)
|
||||||
|
// 12 = (AHX)
|
||||||
|
// 13 = (SHY)
|
||||||
|
// 14 = (SHX)
|
||||||
|
// 15 = (TAS)
|
||||||
|
|
||||||
|
const uint8 opwrite[256] = {
|
||||||
|
/*0x00*/ 0, 0, 0, 5, 0, 0, 5, 5, 4, 0, 0, 0, 0, 0, 5, 5,
|
||||||
|
/*0x10*/ 0, 0, 0, 5, 0, 0, 5, 5, 0, 0, 0, 5, 0, 0, 5, 5,
|
||||||
|
/*0x20*/ 0, 0, 0, 7, 0, 0, 7, 7, 0, 0, 7, 0, 0, 0, 7, 7,
|
||||||
|
/*0x30*/ 0, 0, 0, 7, 0, 0, 7, 7, 0, 0, 0, 7, 0, 0, 7, 7,
|
||||||
|
/*0x40*/ 0, 0, 0, 6, 0, 0, 6, 6, 1, 0, 6, 0, 0, 0, 6, 6,
|
||||||
|
/*0x50*/ 0, 0, 0, 6, 0, 0, 6, 6, 0, 0, 0, 6, 0, 0, 6, 6,
|
||||||
|
/*0x60*/ 0, 0, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 0, 0, 8, 8,
|
||||||
|
/*0x70*/ 0, 0, 0, 8, 0, 0, 8, 8, 0, 0, 0, 8, 0, 0, 8, 8,
|
||||||
|
/*0x80*/ 0, 1, 0,11, 3, 1, 2,11, 0, 0, 0, 0, 3, 1, 2,11,
|
||||||
|
/*0x90*/ 0, 1, 0,12, 3, 1, 2,11, 0, 1, 0,15,13, 1,14,12,
|
||||||
|
/*0xA0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/*0xB0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/*0xC0*/ 0, 0, 0,10, 0, 0,10,10, 0, 0, 0, 0, 0, 0,10,10,
|
||||||
|
/*0xD0*/ 0, 0, 0,10, 0, 0,10,10, 0, 0, 0,10, 0, 0,10,10,
|
||||||
|
/*0xE0*/ 0, 0, 0, 9, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9,
|
||||||
|
/*0xF0*/ 0, 0, 0, 9, 0, 0, 9, 9, 0, 0, 0, 9, 0, 0, 9, 9,
|
||||||
};
|
};
|
@ -31,6 +31,9 @@ extern const uint8 opsize[256];
|
|||||||
//the optype table is a quick way to grab the addressing mode for any 6502 opcode
|
//the optype table is a quick way to grab the addressing mode for any 6502 opcode
|
||||||
extern const uint8 optype[256];
|
extern const uint8 optype[256];
|
||||||
|
|
||||||
|
// the opwrite table aids in predicting the value written for any 6502 opcode
|
||||||
|
extern const uint8 opwrite[256];
|
||||||
|
|
||||||
//-----------
|
//-----------
|
||||||
//mbg 6/30/06 - some of this was removed to mimic XD
|
//mbg 6/30/06 - some of this was removed to mimic XD
|
||||||
//#ifdef FCEUDEF_DEBUGGER
|
//#ifdef FCEUDEF_DEBUGGER
|
||||||
@ -47,8 +50,8 @@ void X6502_RunDebug(int32 cycles);
|
|||||||
//------------
|
//------------
|
||||||
|
|
||||||
extern uint32 timestamp;
|
extern uint32 timestamp;
|
||||||
|
extern uint32 soundtimestamp;
|
||||||
|
extern int scanline;
|
||||||
|
|
||||||
#define N_FLAG 0x80
|
#define N_FLAG 0x80
|
||||||
#define V_FLAG 0x40
|
#define V_FLAG 0x40
|
||||||
|
@ -18,6 +18,10 @@
|
|||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
|
|
||||||
bool turbo = false;
|
bool turbo = false;
|
||||||
|
bool paldeemphswap = 0;
|
||||||
|
int dendy;
|
||||||
|
bool swapDuty;
|
||||||
|
int KillFCEUXonFrame = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes a game. Frees memory, and deinitializes the drivers.
|
* Closes a game. Frees memory, and deinitializes the drivers.
|
||||||
@ -172,3 +176,4 @@ const char *FCEUD_GetCompilerString() { return NULL; }
|
|||||||
void FCEUI_UseInputPreset(int preset) { }
|
void FCEUI_UseInputPreset(int preset) { }
|
||||||
void FCEUD_SoundVolumeAdjust(int n) { }
|
void FCEUD_SoundVolumeAdjust(int n) { }
|
||||||
void FCEUD_SetEmulationSpeed(int cmd) { }
|
void FCEUD_SetEmulationSpeed(int cmd) { }
|
||||||
|
void GetMouseData(uint32 (&d)[3]) { }
|
||||||
|
Loading…
Reference in New Issue
Block a user