Merge pull request #17 from TASVideos/master

Sync code to the newest
This commit is contained in:
owomomo 2020-01-31 19:46:54 +08:00 committed by GitHub
commit 935cdaf178
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 716 additions and 119 deletions

4
.gitignore vendored
View File

@ -34,3 +34,7 @@ fceux-net-server
.sconsign.dblite
.deps
.dirstamp
/output/movies
/output/cheats
/output/snaps
/output/sav

2
README
View File

@ -65,7 +65,7 @@ tweak some of these options.
4 - GUI
-------
You can enable the GTK GUI by setting GTK to 1 in the SConstruct build file.
GfceuX is deprecatiated in favor of the new GTK GUI. You can disable the GTK GUI at
GfceuX is deprecated in favor of the new GTK GUI. You can disable the GTK GUI at
run-time by passing the --nogui option, or disable it at build-time by setting
GTK to 0 in the SConstruct file. If you prefer GTK3 to GTK2, you can set the
GTK3 BoolVariable to 1 in the SConstruct.

View File

@ -237,13 +237,8 @@ void Mapper200_Init(CartInfo *info) {
//------------------ Map 201 ---------------------------
static void M201Sync(void) {
if (latche & 8) {
setprg32(0x8000, latche & 3);
setchr8(latche & 3);
} else {
setprg32(0x8000, 0);
setchr8(0);
}
setprg32(0x8000, latche & 3);
setchr8(latche & 3);
}
void Mapper201_Init(CartInfo *info) {

252
src/boards/fns.cpp Normal file
View File

@ -0,0 +1,252 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 1998 BERO
* Copyright (C) 2002 Xodnizel
* Copyright (C) 2020 CaH4e3
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Famicom Network System Base Unit + MMC1 cartridge board
*
*/
#include "mapinc.h"
static uint8 DRegs[4];
static uint8 Buffer, BufferShift;
static uint32 WRAMSIZE;
static uint8 *WRAM = NULL;
static int kanji_pos, kanji_page, r40C0;
static int IRQa, IRQCount;
static DECLFW(MBWRAM) {
if (!(DRegs[3] & 0x10))
Page[A >> 11][A] = V;
}
static DECLFR(MAWRAM) {
if (DRegs[3] & 0x10)
return X.DB;
return(Page[A >> 11][A]);
}
static void MMC1CHR(void) {
setchr8((r40C0 >> 3) & 1);
}
static void MMC1PRG(void) {
uint8 offs_16banks = DRegs[1] & 0x10;
uint8 prg_reg = DRegs[3] & 0xF;
setprg8r(0x10, 0x6000, DRegs[1] & 3);
switch (DRegs[0] & 0xC) {
case 0xC:
setprg16(0x8000, (prg_reg + offs_16banks));
setprg16(0xC000, 0xF + offs_16banks);
break;
case 0x8:
setprg16(0xC000, (prg_reg + offs_16banks));
setprg16(0x8000, offs_16banks);
break;
case 0x0:
case 0x4:
setprg16(0x8000, ((prg_reg & ~1) + offs_16banks));
setprg16(0xc000, ((prg_reg & ~1) + offs_16banks + 1));
break;
}
}
static void MMC1MIRROR(void) {
switch (DRegs[0] & 3) {
case 2: setmirror(MI_V); break;
case 3: setmirror(MI_H); break;
case 0: setmirror(MI_0); break;
case 1: setmirror(MI_1); break;
}
}
static uint64 lreset;
static DECLFW(MMC1_write) {
int n = (A >> 13) - 4;
if ((timestampbase + timestamp) < (lreset + 2))
return;
if (V & 0x80) {
DRegs[0] |= 0xC;
BufferShift = Buffer = 0;
MMC1PRG();
lreset = timestampbase + timestamp;
return;
}
Buffer |= (V & 1) << (BufferShift++);
if (BufferShift == 5) {
DRegs[n] = Buffer;
// FCEU_printf("MMC1 REG%d:%02x\n", n, Buffer);
BufferShift = Buffer = 0;
switch (n) {
case 0: MMC1MIRROR(); // break;
case 1: // break;
// case 2: MMC1CHR(); break;
case 3: MMC1PRG(); break;
}
}
}
static void MMC1_Restore(int version) {
MMC1MIRROR();
MMC1CHR();
MMC1PRG();
lreset = 0;
}
static void MMC1CMReset(void) {
int i;
for (i = 0; i < 4; i++)
DRegs[i] = 0;
Buffer = BufferShift = 0;
DRegs[0] = 0x1F;
DRegs[1] = 0;
DRegs[2] = 0;
DRegs[3] = 0;
MMC1MIRROR();
MMC1CHR();
MMC1PRG();
}
static DECLFW(FNC_cmd_write) {
switch (A) {
case 0x40A6: {
IRQCount = (IRQCount & 0xFF00) | V;
break;
}
case 0x40A7: {
IRQCount = (IRQCount & 0x00FF) | (V << 8);
break;
}
case 0x40A8: {
IRQa = V;
break;
}
case 0x40B0: {
kanji_page = V & 1;
break;
}
case 0x40C0: {
// FCEU_printf("FNS W %04x:%02x\n", A, V);
r40C0 = V;
MMC1CHR();
break;
}
// default:
// FCEU_printf("FNS W %04x:%02x\n", A, V);
}
}
static DECLFR(FNC_stat_read) {
switch (A) {
case 0x40A2: {
int ret = (IRQa >> 1);
X6502_IRQEnd(FCEU_IQEXT);
IRQa = 0;
return ret;
}
case 0x40B0: {
kanji_pos = 0;
return 0;
}
case 0x40C0: {
// FCEU_printf("FNS R %04x\n", A);
int ret = r40C0;
r40C0 &= 0;
return ret;
}
default: {
// FCEU_printf("FNS R %04x\n", A);
return 0xff;
}
}
}
static DECLFR(FNC_kanji_read) {
int32 ofs = ((A & 0xFFF) << 5) + kanji_pos;
kanji_pos++;
kanji_pos &= 0x1F;
// if (PRGptr[1] != NULL) // iNES debug
return PRGptr[1][ofs];
// else
// return CHRptr[0][ofs];
}
void NFC_IRQ(int a) {
if (IRQa) {
IRQCount -= a;
if (IRQCount <= 0)
X6502_IRQBegin(FCEU_IQEXT);
}
}
static void FNS_Power(void) {
lreset = 0;
SetWriteHandler(0x8000, 0xFFFF, MMC1_write);
SetReadHandler(0x8000, 0xFFFF, CartBR);
kanji_page = 0;
kanji_pos = 0;
r40C0 = 0xC0;
SetWriteHandler(0x4080, 0x40FF, FNC_cmd_write);
SetReadHandler(0x4080, 0x40FF, FNC_stat_read);
SetReadHandler(0x5000, 0x5FFF, FNC_kanji_read);
SetReadHandler(0x6000, 0x7FFF, MAWRAM);
SetWriteHandler(0x6000, 0x7FFF, MBWRAM);
FCEU_CheatAddRAM(8, 0x6000, WRAM);
MMC1CMReset();
}
static void FNS_Close(void) {
if (WRAM)
FCEU_gfree(WRAM);
WRAM = NULL;
}
void FNS_Init(CartInfo *info) {
info->Close = FNS_Close;
info->Power = FNS_Power;
GameStateRestore = MMC1_Restore;
MapIRQHook = NFC_IRQ;
WRAMSIZE = (8 + 32) * 1024;
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
AddExState(DRegs, 4, 0, "DREG");
AddExState(&lreset, 8, 1, "LRST");
AddExState(&Buffer, 1, 1, "BFFR");
AddExState(&BufferShift, 1, 1, "BFRS");
}

View File

@ -100,8 +100,9 @@ static uint8 *WRAM = NULL;
static uint8 *MMC5fill = NULL;
static uint8 *ExRAM = NULL;
const int MMC5WRAMMAX = 1<<7; // 7 bits in register interface (real MMC5 has only 4 pins, however)
static uint8 MMC5WRAMsize; //configuration, not state
static uint8 MMC5WRAMIndex[8]; //configuration, not state
static uint8 MMC5WRAMIndex[MMC5WRAMMAX]; //configuration, not state
static uint8 MMC5ROMWrProtect[4];
static uint8 MMC5MemIn[5];
@ -314,6 +315,8 @@ int DetectMMC5WRAMSize(uint32 crc32) {
}
static void BuildWRAMSizeTable(void) {
bool other = false; // non-standard configuration
// fill first 8 entries
int x;
for (x = 0; x < 8; x++) {
switch (MMC5WRAMsize) {
@ -321,9 +324,22 @@ static void BuildWRAMSizeTable(void) {
case 1: MMC5WRAMIndex[x] = (x > 3) ? 255 : 0; break; //0,0,0,0,X,X,X,X
case 2: MMC5WRAMIndex[x] = (x & 4) >> 2; break; //0,0,0,0,1,1,1,1
case 4: MMC5WRAMIndex[x] = (x > 3) ? 255 : (x & 3); break; //0,1,2,3,X,X,X,X
case 8: MMC5WRAMIndex[x] = x; break; //0,1,2,3,4,5,6,7
case 8: MMC5WRAMIndex[x] = x; break; //0,1,2,3,4,5,6,7
default: MMC5WRAMIndex[x] = x; other = true; break; //0,1,2...
}
}
// extend to fill complete table
if (other)
{
for (x = 0; x < MMC5WRAMMAX && x < MMC5WRAMsize; ++x) MMC5WRAMIndex[x] = x; // linear mapping
for (x = MMC5WRAMsize; x < MMC5WRAMMAX; ++x) MMC5WRAMIndex[x] = MMC5WRAMIndex[x-MMC5WRAMsize]; // repeat to fill table
// theoretically the table fill should decompose into powers of two for possible mismatched SRAM combos,
// but I don't want to complicate the code with unnecessary hypotheticals
}
else
{
for (x = 8; x < MMC5WRAMMAX; ++x) MMC5WRAMIndex[x] = MMC5WRAMIndex[x & 7]; // fill table, repeating groups of 8
}
}
static void MMC5CHRA(void) {
@ -391,7 +407,7 @@ static void MMC5CHRB(void) {
}
static void MMC5WRAM(uint32 A, uint32 V) {
V = MMC5WRAMIndex[V & 7];
V = MMC5WRAMIndex[V & (MMC5WRAMMAX-1)];
if (V != 255) {
setprg8r(0x10, A, V);
FCEU_CheatAddRAM(8, 0x6000, (WRAM + ((V * 8192) & (WRAMSIZE - 1))));
@ -416,8 +432,8 @@ static void MMC5PRG(void) {
MMC5MemIn[1] = MMC5MemIn[2] = 1;
} else {
MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0;
MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE);
MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1);
MMC5WRAM(0x8000, PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE);
MMC5WRAM(0xA000, (PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE) + 1);
}
MMC5MemIn[3] = MMC5MemIn[4] = 1;
MMC5ROMWrProtect[2] = MMC5ROMWrProtect[3] = 1;
@ -430,8 +446,8 @@ static void MMC5PRG(void) {
setprg16(0x8000, (PRGBanks[1] & 0x7F) >> 1);
} else {
MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0;
MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE);
MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1);
MMC5WRAM(0x8000, PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE);
MMC5WRAM(0xA000, (PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE) + 1);
}
if (PRGBanks[2] & 0x80) {
MMC5ROMWrProtect[2] = 1;
@ -439,7 +455,7 @@ static void MMC5PRG(void) {
setprg8(0xC000, PRGBanks[2] & 0x7F);
} else {
MMC5ROMWrProtect[2] = 0;
MMC5WRAM(0xC000, PRGBanks[2] & 7);
MMC5WRAM(0xC000, PRGBanks[2] & (MMC5WRAMMAX-1));
}
MMC5MemIn[4] = 1;
MMC5ROMWrProtect[3] = 1;
@ -453,7 +469,7 @@ static void MMC5PRG(void) {
MMC5MemIn[1 + x] = 1;
} else {
MMC5ROMWrProtect[x] = 0;
MMC5WRAM(0x8000 + (x << 13), PRGBanks[x] & 7);
MMC5WRAM(0x8000 + (x << 13), PRGBanks[x] & (MMC5WRAMMAX-1));
}
MMC5MemIn[4] = 1;
MMC5ROMWrProtect[3] = 1;
@ -516,7 +532,7 @@ static DECLFW(Mapper5_write) {
break;
case 0x5113:
WRAMPage = V;
MMC5WRAM(0x6000, V & 7);
MMC5WRAM(0x6000, V & (MMC5WRAMMAX-1));
break;
case 0x5114:
case 0x5115:
@ -612,7 +628,7 @@ void MMC5Synco(void) {
case 3: PPUNTARAM &= ~(1 << x); vnapage[x] = MMC5fill; break;
}
}
MMC5WRAM(0x6000, WRAMPage & 7);
MMC5WRAM(0x6000, WRAMPage & (MMC5WRAMMAX-1));
if (!mmc5ABMode) {
MMC5CHRB();
MMC5CHRA();
@ -984,15 +1000,21 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
if (battery) {
info->SaveGame[0] = WRAM;
//this is more complex than it looks because it MUST BE, I guess. is there an assumption that only 8KB of 16KB is battery backed? That's NES mappers for you
//I added 64KB for the new 64KB homebrews
if (wsize <= 16)
info->SaveGameLen[0] = 8192;
else if(wsize == 64)
info->SaveGameLen[0] = 64*1024;
if (info->ines2)
{
info->SaveGameLen[0] = info->battery_wram_size;
}
else
info->SaveGameLen[0] = 32768;
{
//this is more complex than it looks because it MUST BE, I guess. is there an assumption that only 8KB of 16KB is battery backed? That's NES mappers for you
//I added 64KB for the new 64KB homebrews
if (wsize <= 16)
info->SaveGameLen[0] = 8192;
else if(wsize == 64)
info->SaveGameLen[0] = 64*1024;
else
info->SaveGameLen[0] = 32768;
}
}
MMC5HackVROMMask = CHRmask4[0];
@ -1008,7 +1030,14 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
}
void Mapper5_Init(CartInfo *info) {
WRAMSIZE = DetectMMC5WRAMSize(info->CRC32);
if (info->ines2)
{
WRAMSIZE = (info->wram_size + info->battery_wram_size) / 1024;
}
else
{
WRAMSIZE = DetectMMC5WRAMSize(info->CRC32);
}
GenMMC5_Init(info, WRAMSIZE, info->battery);
}

View File

@ -47,31 +47,31 @@ static uint8 flash_save=0, flash_state=0, flash_mode=0, flash_bank;
static void (*WLSync)(void);
static void (*WHSync)(void);
static INLINE void setfpageptr(int s, uint32 A, uint8 *p) {
uint32 AB = A >> 11;
int x;
if (p)
for (x = (s >> 1) - 1; x >= 0; x--) {
FlashPage[AB + x] = p - A;
}
else
for (x = (s >> 1) - 1; x >= 0; x--) {
FlashPage[AB + x] = 0;
}
static INLINE void setfpageptr(int s, uint32 A, uint8 *p) {
uint32 AB = A >> 11;
int x;
if (p)
for (x = (s >> 1) - 1; x >= 0; x--) {
FlashPage[AB + x] = p - A;
}
else
for (x = (s >> 1) - 1; x >= 0; x--) {
FlashPage[AB + x] = 0;
}
}
void setfprg16(uint32 A, uint32 V) {
if (PRGsize[0] >= 16384) {
V &= PRGmask16[0];
setfpageptr(16, A, flashdata ? (&flashdata[V << 14]) : 0);
} else {
uint32 VA = V << 3;
int x;
for (x = 0; x < 8; x++)
setfpageptr(2, A + (x << 11), flashdata ? (&flashdata[((VA + x) & PRGmask2[0]) << 11]) : 0);
}
void setfprg16(uint32 A, uint32 V) {
if (PRGsize[0] >= 16384) {
V &= PRGmask16[0];
setfpageptr(16, A, flashdata ? (&flashdata[V << 14]) : 0);
} else {
uint32 VA = V << 3;
int x;
for (x = 0; x < 8; x++)
setfpageptr(2, A + (x << 11), flashdata ? (&flashdata[((VA + x) & PRGmask2[0]) << 11]) : 0);
}
}
void inc_flash_write_count(uint8 bank, uint32 A)

View File

@ -152,11 +152,11 @@ static void Sync(void) {
chrSync();
setprg4r(0x10, 0x6000, (regs[0] & 1) | (regs[0] >> 2)); // two 4K banks are identical, either internal or excernal
setprg4r(0x10, 0x7000, (regs[1] & 1) | (regs[1] >> 2)); // SRAMs may be mapped in any bank independently
if (PRGsize[0] == 1024 * 1024) {// hacky hacky way to run it as iNES rom for debugging purposes
setprg8(0x8000, regs[2]);
setprg8(0xA000, regs[3]);
setprg8(0xC000, regs[4]);
setprg8(0xE000, ~0);
if (PRGptr[1] == NULL) { // for iNES 2.0 version it even more hacky lol
setprg8(0x8000, (regs[2] & 0x3F) + ((regs[2] & 0x40) >> 2));
setprg8(0xA000, (regs[3] & 0x3F) + ((regs[3] & 0x40) >> 2));
setprg8(0xC000, (regs[4] & 0x3F) + ((regs[4] & 0x40) >> 2));
setprg8(0xE000, 0x10 + 0x3F);
} else {
setprg8r((regs[2] >> 6) & 1, 0x8000, (regs[2] & 0x3F));
setprg8r((regs[3] >> 6) & 1, 0xA000, (regs[3] & 0x3F));

View File

@ -533,35 +533,36 @@ void IncrementInstructionsCounters()
delta_instructions++;
}
void BreakHit(int bp_num, bool force)
{
if(!force)
bool CondForbidTest(int bp_num) {
if (bp_num >= 0 && !condition(&watchpoint[bp_num]))
{
if (bp_num >= 0 && !condition(&watchpoint[bp_num]))
{
return; // condition rejected
}
return false; // condition rejected
}
//check to see whether we fall in any forbid zone
for (int i = 0; i < numWPs; i++)
{
watchpointinfo& wp = watchpoint[i];
if(!(wp.flags & WP_F) || !(wp.flags & WP_E))
continue;
//check to see whether we fall in any forbid zone
for (int i = 0; i < numWPs; i++)
{
watchpointinfo& wp = watchpoint[i];
if (!(wp.flags & WP_F) || !(wp.flags & WP_E))
continue;
if (condition(&wp))
{
if (wp.endaddress) {
if( (wp.address <= _PC) && (wp.endaddress >= _PC) )
return; //forbid
} else {
if(wp.address == _PC)
return; //forbid
}
if (condition(&wp))
{
if (wp.endaddress) {
if ((wp.address <= _PC) && (wp.endaddress >= _PC))
return false; // forbid
}
else {
if (wp.address == _PC)
return false; // forbid
}
}
}
return true;
}
void BreakHit(int bp_num)
{
FCEUI_SetEmulationPaused(EMULATIONPAUSED_PAUSED); //mbg merge 7/19/06 changed to use EmulationPaused()
#ifdef WIN32
@ -585,17 +586,17 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
if (break_asap)
{
break_asap = false;
BreakHit(BREAK_TYPE_LUA, true);
BreakHit(BREAK_TYPE_LUA);
}
if (break_on_cycles && ((timestampbase + (uint64)timestamp - total_cycles_base) > break_cycles_limit))
BreakHit(BREAK_TYPE_CYCLES_EXCEED, true);
BreakHit(BREAK_TYPE_CYCLES_EXCEED);
if (break_on_instructions && (total_instructions > break_instructions_limit))
BreakHit(BREAK_TYPE_INSTRUCTIONS_EXCEED, true);
BreakHit(BREAK_TYPE_INSTRUCTIONS_EXCEED);
//if the current instruction is bad, and we are breaking on bad opcodes, then hit the breakpoint
if(dbgstate.badopbreak && (size == 0))
BreakHit(BREAK_TYPE_BADOP, true);
BreakHit(BREAK_TYPE_BADOP);
//if we're stepping out, track the nest level
if (dbgstate.stepout) {
@ -614,7 +615,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
//if we're stepping, then we'll always want to break
if (dbgstate.step) {
dbgstate.step = false;
BreakHit(BREAK_TYPE_STEP, true);
BreakHit(BREAK_TYPE_STEP);
return;
}
@ -626,7 +627,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
if (diff<=0)
{
dbgstate.runline=false;
BreakHit(BREAK_TYPE_STEP, true);
BreakHit(BREAK_TYPE_STEP);
return;
}
}
@ -635,7 +636,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
if ((watchpoint[64].address == _PC) && (watchpoint[64].flags)) {
watchpoint[64].address = 0;
watchpoint[64].flags = 0;
BreakHit(BREAK_TYPE_STEP, true);
BreakHit(BREAK_TYPE_STEP);
return;
}
@ -657,7 +658,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
default: break;
}
#define BREAKHIT(x) { breakHit = (x); goto STOPCHECKING; }
#define BREAKHIT(x) { if (CondForbidTest(x)) { breakHit = (x); goto STOPCHECKING; } }
int breakHit = -1;
for (i = 0; i < numWPs; i++)
{

View File

@ -93,7 +93,8 @@ static INLINE int FCEUI_GetLoggingCD() { return debug_loggingCD; }
extern int iaPC;
extern uint32 iapoffset; //mbg merge 7/18/06 changed from int
void DebugCycle();
void BreakHit(int bp_num, bool force = false);
bool CondForbidTest(int bp_num);
void BreakHit(int bp_num);
extern bool break_asap;
extern uint64 total_cycles_base;
@ -113,7 +114,7 @@ extern void IncrementInstructionsCounters();
//internal variables that debuggers will want access to
extern uint8 *vnapage[4],*VPage[8];
extern uint8 PPU[4],PALRAM[0x20],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset;
extern uint8 PPU[4],PALRAM[0x20],UPALRAM[3],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset;
extern uint32 FCEUPPU_PeekAddress();
extern uint8 READPAL_MOTHEROFALL(uint32 A);
extern int numWPs;

View File

@ -562,8 +562,10 @@ void InitCDLog()
cdloggerVideoDataSize = CHRsize[0];
cdloggervdata = (unsigned char*)malloc(cdloggerVideoDataSize);
} else {
cdloggerVideoDataSize = 0;
cdloggervdata = (unsigned char*)malloc(8192);
if (GameInfo->type != GIT_NSF) {
cdloggerVideoDataSize = 0;
cdloggervdata = (unsigned char*)malloc(8192);
}
}
}
@ -576,8 +578,10 @@ void ResetCDLog()
undefinedvromcount = cdloggerVideoDataSize;
ZeroMemory(cdloggervdata, cdloggerVideoDataSize);
} else {
undefinedvromcount = 8192;
ZeroMemory(cdloggervdata, 8192);
if (GameInfo->type != GIT_NSF) {
undefinedvromcount = 8192;
ZeroMemory(cdloggervdata, 8192);
}
}
}

View File

@ -279,8 +279,9 @@ INT_PTR CALLBACK AddbpCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
SendDlgItemMessage(hwndDlg, IDC_ADDBP_ADDR_START, EM_SETLIMITTEXT, 4, 0);
SendDlgItemMessage(hwndDlg, IDC_ADDBP_ADDR_END, EM_SETLIMITTEXT, 4, 0);
DefaultEditCtrlProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ADDBP_ADDR_START), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ADDBP_ADDR_END), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
// Don't limit address entry. See: debugcpp offsetStringToInt
//DefaultEditCtrlProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ADDBP_ADDR_START), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
//SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ADDBP_ADDR_END), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
if (WP_edit >= 0)
{
@ -1825,12 +1826,14 @@ INT_PTR CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_SPR,EM_SETLIMITTEXT,2,0);
// limit input
DefaultEditCtrlProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_VAL_PCSEEK), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
// Don't limit address entry. See: debugcpp offsetStringToInt
DefaultEditCtrlProc = (WNDPROC)
//DefaultEditCtrlProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_VAL_PCSEEK), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_VAL_PC), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_VAL_A), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_VAL_X), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_VAL_Y), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_BOOKMARK), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
//SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_BOOKMARK), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
//I'm lazy, disable the controls which I can't mess with right now
SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_PPU,EM_SETREADONLY,TRUE,0);

View File

@ -93,6 +93,7 @@ static uint8 HyperShotData=0;
static uint32 MahjongData=0;
static uint32 FTrainerData=0;
static uint8 TopRiderData=0;
static uint32 FamiNetSysData = 0;
static uint8 BWorldData[1+13+1];
@ -104,6 +105,7 @@ static void UpdateHyperShot(void);
static void UpdateMahjong(void);
static void UpdateFTrainer(void);
static void UpdateTopRider(void);
static void UpdateFamiNetSys(void);
static uint32 snespad_return[4];
static uint32 JSreturn=0;
@ -463,6 +465,7 @@ void FCEUD_UpdateInput()
case SIFC_FTRAINERB:
case SIFC_FTRAINERA: UpdateFTrainer();break;
case SIFC_TOPRIDER: UpdateTopRider();break;
case SIFC_FAMINETSYS: UpdateFamiNetSys(); break;
case SIFC_OEKAKIDS: mouse=true; break;
}
@ -566,6 +569,9 @@ void InitInputPorts(bool fourscore)
case SIFC_TOPRIDER:
InputDPtr=&TopRiderData;
break;
case SIFC_FAMINETSYS:
InputDPtr = &FamiNetSysData;
break;
case SIFC_BWORLD:
InputDPtr=BWorldData;
break;
@ -718,6 +724,27 @@ static void UpdateTopRider(void)
TopRiderData|=1<<x;
}
ButtConfig FamiNetSysButtons[24] =
{
MK(V),MK(C),MK(X),MK(Z),MK(BL_CURSORUP),MK(BL_CURSORDOWN),MK(BL_CURSORLEFT),MK(BL_CURSORRIGHT),
MK(0),MK(1),MK(2),MK(3),MK(4),MK(5),MK(6),MK(7),
MK(8),MK(9),MK(ASTERISK),MK(KP_PLUS),MK(KP_DELETE),MK(KP_MINUS),MK(ESCAPE),MK(BACKSPACE)
};
// A B SEL ST * # . C x EndComm
// V C X Z * + DEL - x BS
static void UpdateFamiNetSys(void)
{
int x;
FamiNetSysData = 0;
for (x = 0; x<24; x++) {
if (DTestButton(&FamiNetSysButtons[x]))
FamiNetSysData |= 1 << x;
}
FamiNetSysData &= 0x00BFFFFF; // bit22 must be zero
}
ButtConfig FTrainerButtons[12]=
{
MK(O),MK(P),MK(BRACKET_LEFT),

View File

@ -147,6 +147,7 @@ void FindNext();
void OpenFindDialog();
static int GetFileData(uint32 offset);
static int WriteFileData(uint32 offset,int data);
static void PalettePoke(uint32 addr, uint8 data);
HWND hMemView, hMemFind;
@ -1013,7 +1014,7 @@ void InputData(char *input){
if((addr >= 0x2000) && (addr < 0x3F00))
vnapage[(addr>>10)&0x3][addr&0x3FF] = data[i]; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct?
if((addr >= 0x3F00) && (addr < 0x3FFF))
PALRAM[addr&0x1F] = data[i];
PalettePoke(addr,data[i]);
} else if (EditingMode == MODE_NES_OAM)
{
addr &= 0xFF;
@ -1049,7 +1050,7 @@ if(EditingMode == MODE_NES_PPU){
addr &= 0x3FFF;
if(addr < 0x2000)VPage[addr>>10][addr] = data; //todo: detect if this is vrom and turn it red if so
if((addr > 0x2000) && (addr < 0x3F00))vnapage[(addr>>10)&0x3][addr&0x3FF] = data; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct?
if((addr > 0x3F00) && (addr < 0x3FFF))PALRAM[addr&0x1F] = data;
if((addr > 0x3F00) && (addr < 0x3FFF)) PalettePoke(addr,data);
}
if(EditingMode == MODE_NES_FILE)ApplyPatch(addr,1,(uint8 *)&data);
CursorStartAddy++;
@ -1915,7 +1916,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
i &= 0x3FFF;
if(i < 0x2000) bar[i] = VPage[(i)>>10][(i)];
else if(i < 0x3F00) bar[i] = vnapage[(i>>10)&0x3][i&0x3FF];
else bar[i] = PALRAM[i&0x1F];
else bar[i] = READPAL_MOTHEROFALL(i & 0x1F);
}
dumpToFile(bar, sizeof(bar));
return 0;
@ -1952,7 +1953,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
if((addr >= 0x2000) && (addr < 0x3F00))
vnapage[(addr>>10)&0x3][addr&0x3FF] = v; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct?
if((addr >= 0x3F00) && (addr < 0x3FFF))
PALRAM[addr&0x1F] = v;
PalettePoke(addr,v);
}
}
return 0;
@ -2394,3 +2395,25 @@ void OpenFindDialog()
hMemFind = CreateDialog(fceu_hInstance,"MEMVIEWFIND",hMemView,MemFindCallB);
return;
}
void PalettePoke(uint32 addr, uint8 data)
{
data = data & 0x3F;
addr = addr & 0x1F;
if ((addr & 3) == 0)
{
addr = (addr & 0xC) >> 2;
if (addr == 0)
{
PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = data;
}
else
{
UPALRAM[addr-1] = UPALRAM[0x10|(addr-1)] = data;
}
}
else
{
PALRAM[addr] = data;
}
}

View File

@ -29,13 +29,15 @@ HWND hPPUView;
extern uint8 *VPage[8];
extern uint8 PALRAM[0x20];
extern uint8 UPALRAM[3];
int PPUViewPosX, PPUViewPosY;
bool PPUView_maskUnusedGraphics = true;
bool PPUView_invertTheMask = false;
int PPUView_sprite16Mode = 0;
static uint8 palcache[36] = { 0xFF }; //palette cache
static uint8 pallast[32+3] = { 0 }; // palette cache for change comparison
static uint8 palcache[36] = { 0 }; //palette cache for drawing
uint8 chrcache0[0x1000], chrcache1[0x1000], logcache0[0x1000], logcache1[0x1000]; //cache CHR, fixes a refresh problem when right-clicking
uint8 *pattern0, *pattern1; //pattern table bitmap arrays
uint8 *ppuv_palette;
@ -177,18 +179,17 @@ void FCEUD_UpdatePPUView(int scanline, int refreshchr)
}
// update palette only if required
if (memcmp(palcache, PALRAM, 32) != 0)
if ((memcmp(pallast, PALRAM, 32) != 0) || (memcmp(pallast+32, UPALRAM, 3) != 0))
{
// bbit note: let para know that this if is useless and
// will not work because of the lines below that change
// palcache which will make it not equal next time
memcpy(pallast, PALRAM, 32);
memcpy(pallast+32, UPALRAM, 3);
// cache palette content
memcpy(palcache,PALRAM,32);
palcache[0x10] = palcache[0x00];
palcache[0x14] = palcache[0x00];
palcache[0x18] = palcache[0x00];
palcache[0x1C] = palcache[0x00];
palcache[0x04] = palcache[0x14] = UPALRAM[0];
palcache[0x08] = palcache[0x18] = UPALRAM[1];
palcache[0x0C] = palcache[0x1C] = UPALRAM[2];
//draw palettes
for (y = 0; y < PALETTEHEIGHT; y++)
@ -220,7 +221,6 @@ void FCEUD_UpdatePPUView(int scanline, int refreshchr)
}
pbitmap += ((32*4*3)-6);
}
memcpy(palcache,PALRAM,32); //palcache which will make it not equal next time
}
DrawPatternTable(pattern0,chrcache0,logcache0,pindex0);
@ -428,7 +428,8 @@ INT_PTR CALLBACK PPUViewCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
PPUViewSkip=100;
//clear cache
memset(palcache,0,32);
memset(pallast,0,32+3);
memset(palcache,0,36);
memset(chrcache0,0,0x1000);
memset(chrcache1,0,0x1000);
memset(logcache0,0,0x1000);
@ -537,7 +538,6 @@ INT_PTR CALLBACK PPUViewCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
mouse_x = (mouse_x - paletteDestX) / 32;
mouse_y = (mouse_y - paletteDestY) / 32;
int ix = (mouse_y<<4)|mouse_x;
if ((ix & 0x10) && !(ix & 0x03)) ix = 0; // palcache 0x10/14/18/1C is bogus $00 values
sprintf(str,"Palette: $%02X",palcache[ix]);
SetDlgItemText(hwndDlg,LBL_PPUVIEW_TILE1,"Tile:");
SetDlgItemText(hwndDlg,LBL_PPUVIEW_TILE2,"Tile:");

View File

@ -86,6 +86,20 @@ static int32 DiskPtr;
static int32 DiskSeekIRQ;
static uint8 SelectDisk, InDisk;
/* 4024(w), 4025(w), 4031(r) by dink(fbneo) */
#define USE_DINK // remove this and old code after testing phase
enum FDS_DiskBlockIDs { DSK_INIT = 0, DSK_VOLUME, DSK_FILECNT, DSK_FILEHDR, DSK_FILEDATA };
static uint8 mapperFDS_control; // 4025(w) control register
static uint16 mapperFDS_filesize; // size of file being read/written
static uint8 mapperFDS_block; // block-id of current block
static uint16 mapperFDS_blockstart; // start-address of current block
static uint16 mapperFDS_blocklen; // length of current block
static uint16 mapperFDS_diskaddr; // current address relative to blockstart
static uint8 mapperFDS_diskaccess; // disk needs to be accessed at least once before writing
#define fds_disk() (diskdata[InDisk][mapperFDS_blockstart + mapperFDS_diskaddr])
#define mapperFDS_diskinsert (InDisk != 255)
#define DC_INC 1
void FDSGI(GI h) {
@ -141,6 +155,16 @@ static void FDSInit(void) {
FDSSoundReset();
InDisk = 0;
SelectDisk = 0;
#ifdef USE_DINK
mapperFDS_control = 0;
mapperFDS_filesize = 0;
mapperFDS_block = 0;
mapperFDS_blockstart = 0;
mapperFDS_blocklen = 0;
mapperFDS_diskaddr = 0;
mapperFDS_diskaccess = 0;
#endif
}
void FCEU_FDSInsert(void)
@ -232,6 +256,7 @@ static DECLFR(FDSRead4030) {
return ret;
}
#ifndef USE_DINK
static DECLFR(FDSRead4031) {
static uint8 z = 0;
if (InDisk != 255) {
@ -244,6 +269,51 @@ static DECLFR(FDSRead4031) {
}
return z;
}
#else
static DECLFR(FDSRead4031) {
static uint8 ret = 0;
ret = 0xff;
if (mapperFDS_diskinsert && mapperFDS_control & 0x04) {
mapperFDS_diskaccess = 1;
ret = 0;
switch (mapperFDS_block) {
case DSK_FILEHDR:
if (mapperFDS_diskaddr < mapperFDS_blocklen) {
ret = fds_disk();
switch (mapperFDS_diskaddr) {
case 13: mapperFDS_filesize = ret; break;
case 14:
mapperFDS_filesize |= ret << 8;
//char fdsfile[10];
//strncpy(fdsfile, (char*)&diskdata[InDisk][mapperFDS_blockstart + 3], 8);
//printf("Read file: %s (size: %d)\n"), fdsfile, mapperFDS_filesize);
break;
}
mapperFDS_diskaddr++;
}
break;
default:
if (mapperFDS_diskaddr < mapperFDS_blocklen) {
ret = fds_disk();
mapperFDS_diskaddr++;
}
break;
}
DiskSeekIRQ = 150;
X6502_IRQEnd(FCEU_IQEXT2);
}
return ret;
}
#endif
static DECLFR(FDSRead4032) {
uint8 ret;
@ -533,6 +603,7 @@ static DECLFW(FDSWrite) {
break;
case 0x4023: break;
case 0x4024:
#ifndef USE_DINK
if ((InDisk != 255) && !(FDSRegs[5] & 0x4) && (FDSRegs[3] & 0x1)) {
if (DiskPtr >= 0 && DiskPtr < 65500) {
if (writeskip)
@ -543,8 +614,43 @@ static DECLFW(FDSWrite) {
}
}
}
#else
if (mapperFDS_diskinsert && ~mapperFDS_control & 0x04) {
if (mapperFDS_diskaccess == 0) {
mapperFDS_diskaccess = 1;
break;
}
switch (mapperFDS_block) {
case DSK_FILEHDR:
if (mapperFDS_diskaddr < mapperFDS_blocklen) {
fds_disk() = V;
switch (mapperFDS_diskaddr) {
case 13: mapperFDS_filesize = V; break;
case 14:
mapperFDS_filesize |= V << 8;
//char fdsfile[10];
//strncpy(fdsfile, (char*)&diskdata[InDisk][mapperFDS_blockstart + 3], 8);
//printf("Write file: %s (size: %d)\n"), fdsfile, mapperFDS_filesize);
break;
}
mapperFDS_diskaddr++;
}
break;
default:
if (mapperFDS_diskaddr < mapperFDS_blocklen) {
fds_disk() = V;
mapperFDS_diskaddr++;
}
break;
}
}
#endif
break;
case 0x4025:
#ifndef USE_DINK
X6502_IRQEnd(FCEU_IQEXT2);
if (InDisk != 255) {
if (!(V & 0x40)) {
@ -561,6 +667,54 @@ static DECLFW(FDSWrite) {
if (V & 0x40) DiskSeekIRQ = 200;
}
setmirror(((V >> 3) & 1) ^ 1);
#else
X6502_IRQEnd(FCEU_IQEXT2);
if (mapperFDS_diskinsert) {
if (V & 0x40 && ~mapperFDS_control & 0x40) {
mapperFDS_diskaccess = 0;
DiskSeekIRQ = 150;
// blockstart - address of block on disk
// diskaddr - address relative to blockstart
// _block -> _blockID ?
mapperFDS_blockstart += mapperFDS_diskaddr;
mapperFDS_diskaddr = 0;
mapperFDS_block++;
if (mapperFDS_block > DSK_FILEDATA)
mapperFDS_block = DSK_FILEHDR;
switch (mapperFDS_block) {
case DSK_VOLUME:
mapperFDS_blocklen = 0x38;
break;
case DSK_FILECNT:
mapperFDS_blocklen = 0x02;
break;
case DSK_FILEHDR:
mapperFDS_blocklen = 0x10;
break;
case DSK_FILEDATA: // <blockid><filedata>
mapperFDS_blocklen = 0x01 + mapperFDS_filesize;
break;
}
}
if (V & 0x02) { // transfer reset
mapperFDS_block = DSK_INIT;
mapperFDS_blockstart = 0;
mapperFDS_blocklen = 0;
mapperFDS_diskaddr = 0;
DiskSeekIRQ = 150;
}
if (V & 0x40) { // turn on motor
DiskSeekIRQ = 150;
}
}
mapperFDS_control = V;
setmirror(((V >> 3) & 1) ^ 1);
#endif
break;
}
FDSRegs[A & 7] = V;
@ -749,6 +903,15 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
AddExState(&SelectDisk, 1, 0, "SELD");
AddExState(&InDisk, 1, 0, "INDI");
AddExState(&DiskWritten, 1, 0, "DSKW");
#ifdef USE_DINK
AddExState(&mapperFDS_control, 1, 0, "CTRG");
AddExState(&mapperFDS_filesize, 2, 1, "FLSZ");
AddExState(&mapperFDS_block, 1, 0, "BLCK");
AddExState(&mapperFDS_blockstart, 2, 1, "BLKS");
AddExState(&mapperFDS_blocklen, 2, 1, "BLKL");
AddExState(&mapperFDS_diskaddr, 2, 1, "DADR");
AddExState(&mapperFDS_diskaccess, 1, 0, "DACC");
#endif
CHRRAMSize = 8192;
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);

View File

@ -82,8 +82,9 @@ enum ESIFC
SIFC_OEKAKIDS = 12,
SIFC_BWORLD = 13,
SIFC_TOPRIDER = 14,
SIFC_FAMINETSYS = 15,
SIFC_COUNT = SIFC_TOPRIDER
SIFC_COUNT = SIFC_FAMINETSYS
};
@ -105,7 +106,8 @@ inline const char* ESIFC_Name(ESIFC esifc)
"Family Trainer B",
"Oeka Kids Tablet",
"Barcode World",
"Top Rider"
"Top Rider",
"Famicom Network Controller"
};
if(esifc >= SIFC_NONE && esifc <= SIFC_COUNT)

View File

@ -211,6 +211,7 @@ static void SetInput(void) {
{0xb8b9aca3, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Wild Gunman
{0x5112dc21, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Wild Gunman
{0xaf4010ea, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // World Class Track Meet
{0x67b126b9, SI_GAMEPAD, SI_GAMEPAD, SIFC_FAMINETSYS }, // Famicom Network System
{0x00000000, SI_UNSET, SI_UNSET, SIFC_UNSET }
};
int x = 0;
@ -439,9 +440,16 @@ typedef struct {
//that are not in the power of 2 tends to come
//in obscure mappers themselves which supports such
//size
//Cah4e3 25.10.19: iNES 2.0 attempts to cover all
// boards including UNIF boards with non power 2
// total rom size (a lot of them with a couple of
// roms different sizes (may vary a lot)
// so we need either add here ALL ines 2.0 mappers
// with not power2 roms or change logic here
// to something more unified for ines 2.0 specific
static int not_power2[] =
{
53, 198, 228
53, 198, 228, 547
};
BMAPPINGLocal bmap[] = {
@ -716,7 +724,8 @@ BMAPPINGLocal bmap[] = {
{"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},
{"810544-CA-1", 261, BMC810544CA1_Init},
{"KONAMI QTAi Board", 547, QTAi_Init },
{"", 0, NULL}
};

View File

@ -77,6 +77,7 @@ extern INPUTCFC *FCEU_InitFamilyTrainerA(void);
extern INPUTCFC *FCEU_InitFamilyTrainerB(void);
extern INPUTCFC *FCEU_InitOekaKids(void);
extern INPUTCFC *FCEU_InitTopRider(void);
extern INPUTCFC *FCEU_InitFamiNetSys(void);
extern INPUTCFC *FCEU_InitBarcodeWorld(void);
//---------------
@ -534,6 +535,9 @@ static void SetInputStuffFC()
case SIFC_TOPRIDER:
portFC.driver=FCEU_InitTopRider();
break;
case SIFC_FAMINETSYS:
portFC.driver = FCEU_InitFamiNetSys();
break;
}
}

59
src/input/fns.cpp Normal file
View File

@ -0,0 +1,59 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2019 CaH4e3
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Family Network System controller
*
*/
#include <string.h>
#include "share.h"
static int readbit;
static int32 readdata;
static uint8 Read(int w, uint8 ret)
{
if (!w)
{
if (readbit < 24) {
ret |= ((readdata >> readbit) & 1) << 1;
readbit++;
} else
ret |= 2; // sense!
}
return ret;
}
static void Strobe(void)
{
readbit = 0;
}
static void Update(void *data, int arg)
{
readdata = *(uint32*)data;
}
static INPUTCFC FamiNetSys = { Read, 0, Strobe, Update, 0, 0 };
INPUTCFC *FCEU_InitFamiNetSys(void)
{
return(&FamiNetSys);
}

View File

@ -515,7 +515,7 @@ extern void ReloadRom(void);
// emu.loadrom(string filename)
//
// Loads the rom from the directory relative to the lua script or from the absolute path.
// If the rom can't e loaded, loads the most recent one.
// If the rom can't be loaded, loads the most recent one.
static int emu_loadrom(lua_State *L) {
#ifdef WIN32
const char* str = lua_tostring(L,1);
@ -1416,6 +1416,16 @@ static int memory_readwordsigned(lua_State *L) {
}
static int memory_writebyte(lua_State *L) {
uint32 A = luaL_checkinteger(L, 1);
uint8 V = luaL_checkinteger(L, 2);
if(A < 0x10000)
BWrite[A](A, V);
return 0;
}
static int legacymemory_writebyte(lua_State *L) {
FCEU_CheatSetByte(luaL_checkinteger(L,1), luaL_checkinteger(L,2));
return 0;
}
@ -5764,6 +5774,7 @@ static const struct luaL_reg memorylib [] = {
{"readwordsigned", memory_readwordsigned},
{"readwordunsigned", memory_readword}, // alternate naming scheme for unsigned
{"writebyte", memory_writebyte},
{"legacywritebyte", legacymemory_writebyte},
{"getregister", memory_getregister},
{"setregister", memory_setregister},

View File

@ -2198,7 +2198,7 @@ int FCEUX_PPU_Loop(int skip) {
{
pixel = addr & 0x1F;
}
pixelcolor = PALRAM[pixel];
pixelcolor = READPAL_MOTHEROFALL(pixel);
}
//generate the BG data

View File

@ -472,6 +472,7 @@ static BMAPPING bmap[] = {
{ "80013-B", BMC80013B_Init, 0 },
{ "HPxx", BMCHPxx_Init, 0 },
{ "MINDKIDS", MINDKIDS_Init, BMCFLAG_256KCHRR },
{ "FNS", FNS_Init, BMCFLAG_16KCHRR },
{ 0, 0, 0 }
};

View File

@ -51,7 +51,7 @@ void EKROM_Init(CartInfo *info);
void ELROM_Init(CartInfo *info);
void ETROM_Init(CartInfo *info);
void EWROM_Init(CartInfo *info);
void GNROM_Init(CartInfo *info);
//void GNROM_Init(CartInfo *info);
void HKROM_Init(CartInfo *info);
void LE05_Init(CartInfo *info);
void LH10_Init(CartInfo *info);
@ -159,6 +159,7 @@ void BMC8IN1_Init(CartInfo *info);
void BMC80013B_Init(CartInfo *info);
void BMCHPxx_Init(CartInfo *info);
void MINDKIDS_Init(CartInfo *info);
void FNS_Init(CartInfo *info);
extern uint8 *UNIFchrrama; // Meh. So I can stop CHR RAM
// bank switcherooing with certain boards...

View File

@ -458,6 +458,7 @@
<ClCompile Include="..\src\boards\F-15.cpp" />
<ClCompile Include="..\src\boards\famicombox.cpp" />
<ClCompile Include="..\src\boards\ffe.cpp" />
<ClCompile Include="..\src\boards\fns.cpp" />
<ClCompile Include="..\src\boards\hp10xx_hp20xx.cpp" />
<ClCompile Include="..\src\boards\hp898f.cpp" />
<ClCompile Include="..\src\boards\ks7010.cpp" />
@ -688,6 +689,7 @@
</ClCompile>
<ClCompile Include="..\src\input\cursor.cpp" />
<ClCompile Include="..\src\input\fkb.cpp" />
<ClCompile Include="..\src\input\fns.cpp" />
<ClCompile Include="..\src\input\ftrainer.cpp" />
<ClCompile Include="..\src\input\hypershot.cpp" />
<ClCompile Include="..\src\input\mahjong.cpp" />

View File

@ -1096,6 +1096,12 @@
<ClCompile Include="..\src\drivers\win\header_editor.cpp">
<Filter>drivers\win</Filter>
</ClCompile>
<ClCompile Include="..\src\input\fns.cpp">
<Filter>input</Filter>
</ClCompile>
<ClCompile Include="..\src\boards\fns.cpp">
<Filter>boards</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\drivers\common\args.h">

View File

@ -158,7 +158,7 @@
<p><span class="rvts78"><br/></span></p>
<p><span class="rvts78">Loads the ROM from the directory relative to the lua script or from the absolute path. Hence, the filename parameter can be absolute or relative path.</span></p>
<p><span class="rvts78"><br/></span></p>
<p><span class="rvts78">If the ROM can't e loaded, loads the most recent one.</span></p>
<p><span class="rvts78">If the ROM can't be loaded, loads the most recent one.</span></p>
<p><span class="rvts37"><br/></span></p>
<p><span class="rvts63">emu.registerbefore(function func)</span></p>
<p><span class="rvts37"><br/></span></p>