mirror of
https://github.com/libretro/libretro-fceumm.git
synced 2024-12-29 12:23:18 +00:00
commit
c17f39167c
@ -1,355 +0,0 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2011 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
|
||||
*/
|
||||
|
||||
#ifdef COPYFAMI
|
||||
|
||||
#include "__serial.h"
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
/* #define DEBUG_SERIAL */
|
||||
|
||||
/* *** COPY FAMICOM EMULATION *** */
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* $0000-$1FFF
|
||||
* $2000-$200F PPU
|
||||
* $2010-$3FFB
|
||||
* $3FFC-$3FFF
|
||||
* $4000-$7FFF APU /
|
||||
* $8000-$FFF9 CART/ROM
|
||||
* $FFFA-$FFFB CART/ NMI
|
||||
* $FFFE-$FFFF CART/ IRQ
|
||||
*
|
||||
*
|
||||
*
|
||||
* CTRL R/W $3FFC ---aenic ($00 at reset)
|
||||
*
|
||||
* c -
|
||||
* 0 -
|
||||
* 1 -
|
||||
* i - IRQ
|
||||
* 0 -
|
||||
* 1 -
|
||||
* n - NMI
|
||||
* 0 -
|
||||
* 1 -
|
||||
* e - NMI
|
||||
* 0 -
|
||||
* 1 -
|
||||
* a - AROM
|
||||
* 0 -
|
||||
* 1 -
|
||||
*
|
||||
* BANK R/W $3FFD ---mbbbb
|
||||
*
|
||||
* b -
|
||||
* m - ROM
|
||||
*
|
||||
* USBDATA R/W $3FFE dddddddd
|
||||
*
|
||||
* d - /
|
||||
*
|
||||
* STATUS R $3FFF vmnicptr
|
||||
*
|
||||
* r - USB
|
||||
* 0 -
|
||||
* 1 -
|
||||
* t - USB
|
||||
* 0 -
|
||||
* 1 -
|
||||
* p - USB
|
||||
* 0 -
|
||||
* 1 -
|
||||
* c -
|
||||
* 0 -
|
||||
* 1 -
|
||||
* i - IRQ
|
||||
* 0 -
|
||||
* 1 -
|
||||
* n - NMI
|
||||
* 0 -
|
||||
* 1 -
|
||||
* m - 10 VRAM ()
|
||||
* v - VRAM
|
||||
* 0 -
|
||||
* 1 -
|
||||
*
|
||||
* AROM
|
||||
*
|
||||
* VRAM
|
||||
* 8000-FFFF
|
||||
*/
|
||||
|
||||
#define CTRL 0x00
|
||||
#define CCART 0x01
|
||||
#define CVIRQ 0x02
|
||||
#define CVNMI 0x04
|
||||
#define CDNMI 0x08
|
||||
#define CAROM 0x10
|
||||
#define BANK 0x01
|
||||
#define BMIRR 0x10
|
||||
#define USB 0x02
|
||||
#define STATUS 0x03
|
||||
#define SRX 0x01
|
||||
#define STX 0x02
|
||||
#define SPEN 0x04
|
||||
#define SCART 0x08
|
||||
#define SIRQ 0x10
|
||||
#define SNMI 0x20
|
||||
#define SA10 0x40
|
||||
#define SVRAM 0x80
|
||||
|
||||
#ifdef DEBUG_SERIAL
|
||||
static uint8 debug_serial_data[] = {
|
||||
0xDE, 0xAD, 0xBE, 0xEF, 0x00,
|
||||
0xDE, 0xAD, 0xBE, 0xEF, 0x01,
|
||||
|
||||
0x02,
|
||||
|
||||
0x14, 0x50, 0xB0,
|
||||
|
||||
0x02,
|
||||
|
||||
0x14, 0x50, 0xB0,
|
||||
|
||||
0x02,
|
||||
};
|
||||
static uint32 debug_serial_data_size = sizeof(debug_serial_data);
|
||||
static uint32 debug_serial_data_pos;
|
||||
#endif
|
||||
|
||||
static uint8 *CHRRAM = NULL;
|
||||
static uint32 CHRRAMSIZE;
|
||||
|
||||
static uint8 regs[4];
|
||||
|
||||
static readfunc def_read_ram, def_read_rom;
|
||||
static writefunc def_write_ram;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ regs, 4, "CREGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync() {
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void MCopyFamiMMC3PW(uint32 A, uint8 V) {
|
||||
if (regs[CTRL] & CCART)
|
||||
setprg8(A, V);
|
||||
else
|
||||
setprg32r(1, 0x8000, (regs[BANK] & 0x0F) ^ 0x08);
|
||||
}
|
||||
|
||||
static void MCopyFamiMMC3CW(uint32 A, uint8 V) {
|
||||
if ((regs[STATUS] & SCART) && (regs[CTRL] & CAROM))
|
||||
setchr8r(0x10, 0);
|
||||
else
|
||||
setchr1r(0, A, V);
|
||||
}
|
||||
|
||||
static void MCopyFamiMMC3MW(uint8 V) {
|
||||
if (regs[CTRL] & CAROM) {
|
||||
setmirror(MI_0 + ((regs[BANK] >> 4) & 1));
|
||||
} else {
|
||||
A000B = V;
|
||||
setmirror((V & 1) ^ 1);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32 direction = 0xffffffff;
|
||||
static uint32 bytes_count = 0;
|
||||
|
||||
static DECLFW(MCopyFamiWriteReg) {
|
||||
if (((A & 3) == USB) && !fceuindbg) {
|
||||
if (direction != 0) {
|
||||
direction = 0;
|
||||
bytes_count = 0;
|
||||
FCEU_printf(" >");
|
||||
}
|
||||
#ifndef DEBUG_SERIAL
|
||||
while (!SerialSendChar(V)) {
|
||||
}
|
||||
;
|
||||
#endif
|
||||
bytes_count++;
|
||||
/* FCEU_printf(" %02X",V); */
|
||||
} else {
|
||||
regs[A & 3] = V;
|
||||
Sync();
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(MCopyFamiReadReg) {
|
||||
#ifdef DEBUG_SERIAL
|
||||
if (debug_serial_data_pos == debug_serial_data_size)
|
||||
regs[STATUS] |= SRX;
|
||||
else
|
||||
regs[STATUS] &= ~SRX;
|
||||
#endif
|
||||
if (!fceuindbg) {
|
||||
#ifndef DEBUG_SERIAL
|
||||
if ((A & 3) == STATUS) {
|
||||
int data;
|
||||
if ((data = SerialGetChar()) == EOF)
|
||||
regs[STATUS] |= SRX;
|
||||
else
|
||||
regs[STATUS] &= ~SRX;
|
||||
regs[USB] = data & 0xff;
|
||||
} else
|
||||
#endif
|
||||
if ((A & 3) == USB) {
|
||||
#ifdef DEBUG_SERIAL
|
||||
regs[USB] = debug_serial_data[debug_serial_data_pos++];
|
||||
#endif
|
||||
if (direction != 1) {
|
||||
if (direction != 0xffffffff) FCEU_printf(" bytes sent: %08x", bytes_count);
|
||||
direction = 1;
|
||||
bytes_count = 0;
|
||||
FCEU_printf("\n<");
|
||||
}
|
||||
FCEU_printf(" %02X", regs[USB]);
|
||||
}
|
||||
}
|
||||
return regs[A & 3];
|
||||
}
|
||||
|
||||
static DECLFW(MCopyFamiMMC3Write) {
|
||||
if (regs[CTRL] & CAROM) {
|
||||
regs[BANK] = V & 0x1F;
|
||||
Sync();
|
||||
} else {
|
||||
if (A >= 0xC000)
|
||||
MMC3_IRQWrite(A, V);
|
||||
else
|
||||
MMC3_CMDWrite(A, V);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(MCopyFamiMMC3WriteNMI) {
|
||||
if (regs[CTRL] & CVNMI)
|
||||
def_write_ram(0x3FFC + (A & 1), V);
|
||||
else
|
||||
MCopyFamiMMC3Write(A, V);
|
||||
}
|
||||
|
||||
static DECLFW(MCopyFamiMMC3WriteIRQ) {
|
||||
if (regs[CTRL] & CVIRQ)
|
||||
def_write_ram(0x3FFE + (A & 1), V);
|
||||
else
|
||||
MCopyFamiMMC3Write(A, V);
|
||||
}
|
||||
|
||||
static DECLFR(MCopyFamiReadNMI) {
|
||||
if (regs[CTRL] & CVNMI)
|
||||
return def_read_ram(0x3FFC + (A & 1));
|
||||
else
|
||||
return def_read_rom(A);
|
||||
}
|
||||
|
||||
static DECLFR(MCopyFamiReadIRQ) {
|
||||
if (regs[CTRL] & CVIRQ)
|
||||
return def_read_ram(0x3FFE + (A & 1));
|
||||
else
|
||||
return def_read_rom(A);
|
||||
}
|
||||
|
||||
static void MCopyFamiMMC3Power(void) {
|
||||
regs[CTRL] = regs[USB] = 0;
|
||||
regs[STATUS] = SIRQ | SNMI | SVRAM;
|
||||
regs[BANK] = 0x08;
|
||||
#ifdef DEBUG_SERIAL
|
||||
debug_serial_data_pos = 0;
|
||||
#endif
|
||||
GenMMC3Power();
|
||||
Sync();
|
||||
|
||||
def_write_ram = GetWriteHandler(0x3FFC);
|
||||
SetWriteHandler(0x3FFC, 0x3FFF, MCopyFamiWriteReg);
|
||||
def_read_ram = GetReadHandler(0x3FFC);
|
||||
SetReadHandler(0x3FFC, 0x3FFF, MCopyFamiReadReg);
|
||||
|
||||
SetWriteHandler(0x8000, 0xFFF9, MCopyFamiMMC3Write);
|
||||
SetWriteHandler(0xFFFA, 0xFFFB, MCopyFamiMMC3WriteNMI);
|
||||
SetWriteHandler(0xFFFE, 0xFFFF, MCopyFamiMMC3WriteIRQ);
|
||||
|
||||
def_read_rom = GetReadHandler(0xFFFA);
|
||||
SetReadHandler(0xFFFA, 0xFFFB, MCopyFamiReadNMI);
|
||||
SetReadHandler(0xFFFE, 0xFFFF, MCopyFamiReadIRQ);
|
||||
}
|
||||
|
||||
static void MCopyFamiMMC3Reset(void) {
|
||||
regs[CTRL] = regs[USB] = 0;
|
||||
regs[STATUS] = SIRQ | SNMI | SVRAM;
|
||||
regs[BANK] = 0x08;
|
||||
#ifdef DEBUG_SERIAL
|
||||
debug_serial_data_pos = 0;
|
||||
#endif
|
||||
MMC3RegReset();
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void MCopyFamiClose(void) {
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
SerialClose();
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void MapperCopyFamiMMC3_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 512, 8, 0);
|
||||
|
||||
cwrap = MCopyFamiMMC3CW;
|
||||
pwrap = MCopyFamiMMC3PW;
|
||||
mwrap = MCopyFamiMMC3MW;
|
||||
|
||||
info->Reset = MCopyFamiMMC3Reset;
|
||||
info->Power = MCopyFamiMMC3Power;
|
||||
info->Close = MCopyFamiClose;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
CHRRAMSIZE = 8192;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM");
|
||||
|
||||
#ifndef DEBUG_SERIAL
|
||||
FCEU_printf("WAITING FOR PORT...\n");
|
||||
|
||||
while (!SerialOpen(20, 921600)) {
|
||||
}
|
||||
|
||||
FCEU_printf("PORT READY.\n");
|
||||
#endif
|
||||
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,596 +0,0 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2011 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
|
||||
*/
|
||||
|
||||
#ifdef COPYFAMI
|
||||
|
||||
/* *** COPY FAMICOM HARDWARE INTERFACE *** */
|
||||
|
||||
#define MESSAGE_LOG
|
||||
#define NO_CACHE
|
||||
#define NO_RAM
|
||||
|
||||
#include <streams/file_stream.h>
|
||||
|
||||
#include "__serial.h"
|
||||
#include "mapinc.h"
|
||||
|
||||
#define FNV_32_PRIME ((uint32)0x01000193)
|
||||
|
||||
#define CHR_CACHE_SIZE (1024 * 4)
|
||||
#define WRAM_CACHE_SIZE (1024 / 2)
|
||||
#define PRG_CACHE_SIZE (1024 / 4)
|
||||
#define CMD_CACHE_SIZE (1024 * 128)
|
||||
|
||||
#define CMD_MAX_SIZE (5)
|
||||
#define CMD_MAX_RETEST (16)
|
||||
#define CMD_MAX_VERIFY (16)
|
||||
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
uint8 InitVector[] = { 0xDE, 0xAD, 0xBE, 0xEF };/* args none, return DE AD BE EF */
|
||||
uint8 ResetCmd[] = { 0x00 }; /* args none, return none */
|
||||
uint8 StateCmd[] = { 0x01 }; /* args none, return 7 bytes status */
|
||||
uint8 StatusCmd[] = { 0x02 }; /* args none, return 32 bytes status */
|
||||
uint8 LoadPlugCmd[] = { 0x03, 0x00, 0x00 }; /* args 2b size, Nb data return none */
|
||||
uint8 RunPlugCmd[] = { 0x04 }; /* args none, return none */
|
||||
uint8 RunGameCmd[] = { 0x05 }; /* args none, return none */
|
||||
uint8 NROMSave[] = { 0x06 }; /* args none, return 16b + 32kb + 8kb */
|
||||
|
||||
uint8 PRGWBCmd[] = { 0x08, 0x00, 0x00, 0x00 }; /* args 2b addr, 1b data return none */
|
||||
uint8 PRGRBCmd[] = { 0x09, 0x00, 0x00 }; /* args 2b addr return 1b data */
|
||||
uint8 CHRWBCmd[] = { 0x0A, 0x00, 0x00, 0x00 }; /* args 2b addr, 1b data return none */
|
||||
uint8 CHRRBCmd[] = { 0x0B, 0x00, 0x00 }; /* args 2b addr, return 1b data */
|
||||
|
||||
uint8 PRGSUMCmd[] = { 0x10, 0x00, 0x00 }; /* args 1b addr, 1b size return (256 * N)b */
|
||||
uint8 PRG32KSUMCmd[] = { 0x10, 0x80, 0x80 }; /* args 1b addr, 1b size return 32kb */
|
||||
uint8 PRG16KSUMCmd[] = { 0x10, 0x00, 0x40 }; /* args 1b addr, 1b size return 16kb */
|
||||
uint8 PRG8KSUMCmd[] = { 0x10, 0x00, 0x20 }; /* args 1b addr, 1b size return 8kb */
|
||||
uint8 PRG4KSUMCmd[] = { 0x10, 0x00, 0x10 }; /* args 1b addr, 1b size return 4kb */
|
||||
|
||||
uint8 CHRSUMCmd[] = { 0x11, 0x00, 0x00 }; /* args 1b addr, 1b size return (256 * N)b */
|
||||
uint8 CHR8KSUMCmd[] = { 0x11, 0x00, 0x20 }; /* args 1b addr, 1b size return 8kb */
|
||||
uint8 CHR4KSUMCmd[] = { 0x11, 0x00, 0x10 }; /* args 1b addr, 1b size return 4kb */
|
||||
uint8 CHR2KSUMCmd[] = { 0x11, 0x00, 0x08 }; /* args 1b addr, 1b size return 2kb */
|
||||
uint8 CHR1KSUMCmd[] = { 0x11, 0x00, 0x04 }; /* args 1b addr, 1b size return 1kb */
|
||||
|
||||
uint8 PRGGetCmd[] = { 0x12, 0x00, 0x00 }; /* args 1b addr, 1b size return (256 * N)b */
|
||||
uint8 PRG32KGetCmd[] = { 0x12, 0x80, 0x80 }; /* args 1b addr, 1b size return 32kb */
|
||||
uint8 PRG16KGetCmd[] = { 0x12, 0x00, 0x40 }; /* args 1b addr, 1b size return 16kb */
|
||||
uint8 PRG8KGetCmd[] = { 0x12, 0x00, 0x20 }; /* args 1b addr, 1b size return 8kb */
|
||||
uint8 PRG4KGetCmd[] = { 0x12, 0x00, 0x10 }; /* args 1b addr, 1b size return 4kb */
|
||||
|
||||
uint8 CHRGetCmd[] = { 0x13, 0x00, 0x00 }; /* args 1b addr, 1b size return (256 * N)b */
|
||||
uint8 CHR8KGetCmd[] = { 0x13, 0x00, 0x20 }; /* args 1b addr, 1b size return 8kb */
|
||||
uint8 CHR4KGetCmd[] = { 0x13, 0x00, 0x10 }; /* args 1b addr, 1b size return 4kb */
|
||||
uint8 CHR2KGetCmd[] = { 0x13, 0x00, 0x08 }; /* args 1b addr, 1b size return 2kb */
|
||||
uint8 CHR1KGetCmd[] = { 0x13, 0x00, 0x04 }; /* args 1b addr, 1b size return 1kb */
|
||||
|
||||
uint8 CPUTestCmd[] = { 0x14, 0x00, 0x00 }; /* args 1b addr, 1b size return (2b + 1b) * N + 3b */
|
||||
|
||||
typedef struct {
|
||||
int32 mirror;
|
||||
int32 chrsum[8];
|
||||
int32 prgsum[4];
|
||||
} SYNC_STATE;
|
||||
|
||||
static SYNC_STATE state_cur, state_new, state_def;
|
||||
|
||||
typedef struct {
|
||||
uint8 *buf;
|
||||
int32 count;
|
||||
} DATA_BANKS;
|
||||
|
||||
static DATA_BANKS chr_data;
|
||||
static int32 chr_bank[0x10000];
|
||||
static DATA_BANKS prg_data;
|
||||
static int32 prg_bank[0x10000];
|
||||
|
||||
typedef struct {
|
||||
SYNC_STATE states[CMD_CACHE_SIZE];
|
||||
int32 seqs[CMD_CACHE_SIZE][CMD_MAX_SIZE];
|
||||
int32 count;
|
||||
} SYNC_CMDS;
|
||||
|
||||
typedef struct {
|
||||
int32 seq[CMD_MAX_SIZE];
|
||||
int32 size;
|
||||
int32 found;
|
||||
uint32 hash;
|
||||
uint16 hashf;
|
||||
} SYNC_CMD;
|
||||
|
||||
static SYNC_CMD cmd;
|
||||
static SYNC_CMDS cmds;
|
||||
|
||||
typedef struct {
|
||||
int32 index;
|
||||
int32 size;
|
||||
int32 retest;
|
||||
int32 verify;
|
||||
} CMD_CACHE;
|
||||
|
||||
static CMD_CACHE cmd_cache[0x10000];
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ state_cur.chrsum, sizeof(state_cur.chrsum), "CHRREG" },
|
||||
{ state_cur.prgsum, sizeof(state_cur.prgsum), "ROMREG" },
|
||||
{ &state_cur.mirror, sizeof(state_cur.mirror), "MIRREG" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
#define MI_U 4
|
||||
|
||||
static char *mirror_names[5] = { "Horizontal", "Vertical", "Mirror 0", "Mirror 1", "Unknown mirror" };
|
||||
static int32 mirror_modes[16] = {
|
||||
MI_0, MI_U, MI_U, MI_H, MI_U, MI_V, MI_U, MI_U,
|
||||
MI_U, MI_U, MI_U, MI_U, MI_U, MI_U, MI_U, MI_1
|
||||
};
|
||||
|
||||
#define CHRDEF(slot) (chr_bank[state_def.chrsum[slot]])
|
||||
#define PRGDEF(slot) (prg_bank[state_def.prgsum[slot]])
|
||||
#define CHRCUR(slot) (chr_bank[state_cur.chrsum[slot]])
|
||||
#define PRGCUR(slot) (prg_bank[state_cur.prgsum[slot]])
|
||||
#define CHRNEW(slot) (chr_bank[state_new.chrsum[slot]])
|
||||
#define PRGNEW(slot) (prg_bank[state_new.prgsum[slot]])
|
||||
|
||||
static void GetStatus(SYNC_STATE *state) {
|
||||
uint8 resp0;
|
||||
uint16 resp1, i;
|
||||
SEND(StatusCmd);
|
||||
GET(resp0, 1);
|
||||
state->mirror = resp0;
|
||||
GET(resp0, 1);
|
||||
for (i = 0; i < 8; i++) {
|
||||
GET(resp1, 2);
|
||||
state->chrsum[i] = resp1;
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
GET(resp1, 2);
|
||||
state->prgsum[i] = resp1;
|
||||
}
|
||||
}
|
||||
|
||||
static int32 FetchNewCHRBank(int32 slot) {
|
||||
RFILE *ofile;
|
||||
char name[256];
|
||||
int32 bank = chr_data.count++;
|
||||
CHR1KGetCmd[1] = slot << 2;
|
||||
SENDGET(CHR1KGetCmd, chr_data.buf[bank * 1024], 1024);
|
||||
sprintf(name, "%04x.chr", bank);
|
||||
ofile = filestream_open(name,
|
||||
RETRO_VFS_FILE_ACCESS_WRITE,
|
||||
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
filestream_write(ofile, (void*)&chr_data.buf[bank * 1024], 1024);
|
||||
filestream_close(ofile);
|
||||
return bank;
|
||||
}
|
||||
|
||||
static int32 FetchNewPRGBank(int32 slot) {
|
||||
RFILE *ofile;
|
||||
char name[256];
|
||||
int32 bank = prg_data.count++;
|
||||
PRG8KGetCmd[1] = 0x80 + (slot << 5);
|
||||
SENDGET(PRG8KGetCmd, prg_data.buf[bank * 8192], 8192);
|
||||
sprintf(name, "%04x.prg", bank);
|
||||
ofile = filestream_open(name,
|
||||
RETRO_VFS_FILE_ACCESS_WRITE,
|
||||
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
filestream_write(ofile, (void*)&prg_data.buf[bank * 8192], 8192);
|
||||
filestream_close(ofile);
|
||||
return bank;
|
||||
}
|
||||
|
||||
static int CheckStatus(void) {
|
||||
int32 i, ischanged = 0;
|
||||
GetStatus(&state_new);
|
||||
if (state_cur.mirror != state_new.mirror) {
|
||||
state_cur.mirror = state_new.mirror;
|
||||
#ifdef MESSAGE_LOG
|
||||
FCEU_printf(">> mirror changed to %s (%02X)\n", mirror_names[mirror_modes[state_cur.mirror]], state_cur.mirror);
|
||||
#endif
|
||||
ischanged = 1;
|
||||
} else {
|
||||
state_new.mirror = -1;
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (state_cur.chrsum[i] != state_new.chrsum[i]) {
|
||||
state_cur.chrsum[i] = state_new.chrsum[i];
|
||||
if (CHRCUR(i) == -1) {
|
||||
CHRCUR(i) = FetchNewCHRBank(i);
|
||||
#ifdef MESSAGE_LOG
|
||||
FCEU_printf(">> chr[%d] bank %d loaded\n", i, CHRCUR(i));
|
||||
#endif
|
||||
}
|
||||
#ifdef MESSAGE_LOG
|
||||
else
|
||||
FCEU_printf(">> chr[%d] bank %d switched\n", i, CHRCUR(i));
|
||||
#endif
|
||||
ischanged = 1;
|
||||
} else {
|
||||
state_new.chrsum[i] = -1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (state_cur.prgsum[i] != state_new.prgsum[i]) {
|
||||
state_cur.prgsum[i] = state_new.prgsum[i];
|
||||
if (PRGCUR(i) == -1) {
|
||||
PRGCUR(i) = FetchNewPRGBank(i);
|
||||
#ifdef MESSAGE_LOG
|
||||
FCEU_printf(">> prg[%d] bank %d loaded\n", i, PRGCUR(i));
|
||||
#endif
|
||||
}
|
||||
#ifdef MESSAGE_LOG
|
||||
else
|
||||
FCEU_printf(">> prg[%d] bank %d switched\n", i, PRGCUR(i));
|
||||
#endif
|
||||
ischanged = 1;
|
||||
} else {
|
||||
state_new.prgsum[i] = -1;
|
||||
}
|
||||
}
|
||||
return ischanged;
|
||||
}
|
||||
|
||||
#ifndef NO_CACHE
|
||||
static void ApplyStatus() {
|
||||
int32 i;
|
||||
if ((cmds.states[cmd.found].mirror != -1) && (cmds.states[cmd.found].mirror != state_cur.mirror)) {
|
||||
state_cur.mirror = cmds.states[cmd.found].mirror;
|
||||
setmirror(mirror_modes[state_cur.mirror]);
|
||||
#ifdef MESSAGE_LOG
|
||||
FCEU_printf(">> mirror changed to %s (%02X)\n", mirror_names[mirror_modes[state_cur.mirror]], state_cur.mirror);
|
||||
#endif
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
int32 sum = cmds.states[cmd.found].chrsum[i];
|
||||
if (sum != -1) {
|
||||
if (sum != state_cur.chrsum[i]) {
|
||||
state_cur.chrsum[i] = sum;
|
||||
setchr1r(1, i * 1024, CHRCUR(i));
|
||||
#ifdef MESSAGE_LOG
|
||||
FCEU_printf(">> chr[%d] bank %d switched\n", i, chr_bank[sum]);
|
||||
#endif
|
||||
} else
|
||||
#ifdef MESSAGE_LOG
|
||||
FCEU_printf(">> chr[%d] bank %d switched the same\n", i, chr_bank[sum]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
int32 sum = cmds.states[cmd.found].prgsum[i];
|
||||
if (sum != -1) {
|
||||
if (sum != state_cur.prgsum[i]) {
|
||||
state_cur.prgsum[i] = sum;
|
||||
setprg8r(2, 0x8000 + (i * 8192), PRGCUR(i));
|
||||
#ifdef MESSAGE_LOG
|
||||
FCEU_printf(">> prg[%d] bank %d switched\n", i, prg_bank[sum]);
|
||||
#endif
|
||||
} else
|
||||
#ifdef MESSAGE_LOG
|
||||
FCEU_printf(">> prg[%d] bank %d switched the same\n", i, prg_bank[sum]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void LogCmd() {
|
||||
int32 i;
|
||||
FCEU_printf(">> new cmd size %d [", cmd_cache[cmd.hashf].size);
|
||||
for (i = 0; i < cmd_cache[cmd.hashf].size; i++)
|
||||
FCEU_printf(" %06X", cmds.seqs[cmd.found][i]);
|
||||
FCEU_printf(" ], switched to (");
|
||||
if (cmds.states[cmd.found].mirror != -1)
|
||||
FCEU_printf(" mirror=%s", mirror_names[mirror_modes[cmds.states[cmd.found].mirror]]);
|
||||
for (i = 0; i < 8; i++)
|
||||
if (cmds.states[cmd.found].chrsum[i] != -1)
|
||||
FCEU_printf(" chr%d=%02X", i, chr_bank[cmds.states[cmd.found].chrsum[i]]);
|
||||
for (i = 0; i < 4; i++)
|
||||
if (cmds.states[cmd.found].prgsum[i] != -1)
|
||||
FCEU_printf(" prg%d=%02X", i, prg_bank[cmds.states[cmd.found].prgsum[i]]);
|
||||
FCEU_printf(" )\n");
|
||||
}
|
||||
#endif
|
||||
static void Sync() {
|
||||
setchr1r(1, 0x0000, CHRCUR(0));
|
||||
setchr1r(1, 0x0400, CHRCUR(1));
|
||||
setchr1r(1, 0x0800, CHRCUR(2));
|
||||
setchr1r(1, 0x0C00, CHRCUR(3));
|
||||
setchr1r(1, 0x1000, CHRCUR(4));
|
||||
setchr1r(1, 0x1400, CHRCUR(5));
|
||||
setchr1r(1, 0x1800, CHRCUR(6));
|
||||
setchr1r(1, 0x1C00, CHRCUR(7));
|
||||
#ifndef NO_RAM
|
||||
setprg8r(1, 0x6000, 0);
|
||||
#endif
|
||||
setprg8r(2, 0x8000, PRGCUR(0));
|
||||
setprg8r(2, 0xA000, PRGCUR(1));
|
||||
setprg8r(2, 0xC000, PRGCUR(2));
|
||||
setprg8r(2, 0xE000, PRGCUR(3));
|
||||
setmirror(mirror_modes[state_cur.mirror]);
|
||||
}
|
||||
#ifndef NO_CACHE
|
||||
static void UpdateCmd(uint32 val) {
|
||||
int32 index;
|
||||
if (cmd.size < CMD_MAX_SIZE) {
|
||||
index = cmd.size++;
|
||||
} else {
|
||||
/* åñëè äîñòèãíóò ìàêñèìóì äëÿ êîìàíäû, âûáðîñèòü ïîñëåäíóþþ, äîáàâèòü íîâóþ,
|
||||
* ïðîäîëæàòü äî áàíêñâè÷èíãà
|
||||
*/
|
||||
cmd.hash = 0;
|
||||
for (index = 0; index < (CMD_MAX_SIZE - 1); index++) {
|
||||
cmd.seq[index] = cmd.seq[index + 1];
|
||||
cmd.hash *= FNV_32_PRIME;
|
||||
cmd.hash ^= cmd.seq[index];
|
||||
}
|
||||
}
|
||||
cmd.seq[index] = val;
|
||||
cmd.hash *= FNV_32_PRIME;
|
||||
cmd.hash ^= val;
|
||||
cmd.hashf = (cmd.hash >> 16) ^ (cmd.hash & 0xffff);
|
||||
cmd.found = cmd_cache[cmd.hashf].index;
|
||||
}
|
||||
#endif
|
||||
|
||||
static DECLFW(MCopyFamiWrite) {
|
||||
#ifndef NO_CACHE
|
||||
int32 i;
|
||||
#endif
|
||||
|
||||
#ifdef MESSAGE_LOG
|
||||
FCEU_printf("> WRITE %04X:%02X\n", A, V);
|
||||
#endif
|
||||
|
||||
PRGWBCmd[1] = A & 0xFF;
|
||||
PRGWBCmd[2] = A >> 8;
|
||||
PRGWBCmd[3] = V & 0xFF;
|
||||
SEND(PRGWBCmd);
|
||||
#ifdef NO_CACHE
|
||||
CheckStatus();
|
||||
Sync();
|
||||
#else
|
||||
UpdateCmd((A << 8) | V);
|
||||
/* èùåì êîìàíäó â êåøå */
|
||||
if (cmd.found == -1) {
|
||||
/* íå íàéäåíà, ïðîâåðÿåì, èçìåíèëîñü ëè ñîñòîÿíèå áàíêîâ
|
||||
* ëèáî íå ïðåäåëüíîé ëè îíà äëèíû äëÿ êîìàíäû
|
||||
*/
|
||||
cmd_cache[cmd.hashf].index = cmd.found = cmds.count++;
|
||||
cmd_cache[cmd.hashf].retest = 0;
|
||||
cmd_cache[cmd.hashf].verify = 0;
|
||||
for (i = 0; i < cmd.size; i++)
|
||||
cmds.seqs[cmd.found][i] = cmd.seq[i];
|
||||
cmd_cache[cmd.hashf].size = cmd.size;
|
||||
if (CheckStatus()) {
|
||||
cmds.states[cmd.found] = state_new;
|
||||
LogCmd();
|
||||
cmd.size = 0;
|
||||
cmd.hash = 0;
|
||||
Sync();
|
||||
} else {
|
||||
/* åñëè äîáàâëåíà ïîëíàÿ êîìàíäà áåç áàíêñâèò÷èíãà */
|
||||
cmd_cache[cmd.hashf].index = -2;
|
||||
}
|
||||
} else if (cmd.found == -2) {
|
||||
/* ÷àñòè÷íîå ñîâïàäåíèå, åñëè ÷èñëî ïðîâåðîê íå ïðåâûñèëî ëèìèò */
|
||||
if (cmd_cache[cmd.hashf].retest < CMD_MAX_RETEST) {
|
||||
/* òî ïðîâåðèì ñîñòîÿíèå áàíêîâ */
|
||||
if (CheckStatus()) {
|
||||
/* èçìåíèëîñü, çàïèøåì íîâóþ êîìàíäó */
|
||||
cmd_cache[cmd.hashf].index = cmd.found = cmds.count++;
|
||||
cmd_cache[cmd.hashf].retest = 0;
|
||||
cmd_cache[cmd.hashf].verify = 0;
|
||||
for (i = 0; i < cmd.size; i++)
|
||||
cmds.seqs[cmd.found][i] = cmd.seq[i];
|
||||
cmd_cache[cmd.hashf].size = cmd.size;
|
||||
cmds.states[cmd.found] = state_new;
|
||||
LogCmd();
|
||||
cmd.size = 0;
|
||||
cmd.hash = 0;
|
||||
Sync();
|
||||
} else {
|
||||
/* íå èçìåíèëîñü, îòìåòèì óâåëè÷èì ñ÷åò÷èê ïðîâåðîê */
|
||||
cmd_cache[cmd.hashf].retest++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* íàéäåíà, ïîñëåäíèé ðóáåæ îáîðîíû îò ãîâíà */
|
||||
#if 0
|
||||
if(cmd_cache[cmd.hashf].verify < CMD_MAX_VERIFY) {
|
||||
if(CheckStatus()) {
|
||||
int32 changed = 0;
|
||||
if(cmds.states[cmd.found].mirror != state_new.mirror)
|
||||
changed = 1;
|
||||
for(i=0; i<8; i++)
|
||||
if(cmds.states[cmd.found].chrsum[i] != state_new.chrsum[i])
|
||||
changed = 1;
|
||||
for(i=0; i<4; i++)
|
||||
if(cmds.states[cmd.found].prgsum[i] != state_new.prgsum[i])
|
||||
changed = 1;
|
||||
if(changed) {
|
||||
cmd_cache[cmd.hashf].index = -1;
|
||||
cmd_cache[cmd.hashf].retest = 0;
|
||||
cmd_cache[cmd.hashf].verify = 0;
|
||||
Sync();
|
||||
}
|
||||
} else
|
||||
cmd_cache[cmd.hashf].verify++;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* ïðèìåíÿåì áåç ìàëåéøåãî çàçðåíèÿ ñîâåñòè */
|
||||
ApplyStatus();
|
||||
cmd.size = 0;
|
||||
cmd.hash = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static DECLFR(MCopyFamiRead) {
|
||||
uint8 result;
|
||||
PRGRBCmd[1] = A & 0xFF;
|
||||
PRGRBCmd[2] = A >> 8;
|
||||
SENDGET(PRGRBCmd, result, 1);
|
||||
#ifdef MESSAGE_LOG
|
||||
FCEU_printf("> READ %04X:%02X\n", A, result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
static void MCopyFamiReset(void) {
|
||||
state_cur = state_def;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void MCopyFamiPower(void) {
|
||||
/* uint32 resp, presp; */
|
||||
|
||||
FCEU_printf("NOW POWERING... ");
|
||||
|
||||
Sync();
|
||||
|
||||
SetWriteHandler(0x4018, 0x7fff, MCopyFamiWrite);
|
||||
SetReadHandler(0x4018, 0x7fff, MCopyFamiRead);
|
||||
#ifndef NO_RAM
|
||||
SetWriteHandler(0x6000, 0x7fff, CartBW);
|
||||
SetReadHandler(0x6000, 0x7fff, CartBR);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
FCEU_printf("READING MEMORY MAP...\n");
|
||||
CPUTestCmd[1] = 0x50;
|
||||
CPUTestCmd[2] = 0x30;
|
||||
SEND(CPUTestCmd);
|
||||
resp = 0;
|
||||
presp = 0xffffffff;
|
||||
while (presp != 0x00ff0000) {
|
||||
GET(resp, 3);
|
||||
if(presp != 0xffffffff) {
|
||||
switch(presp & 0x00FF0000) {
|
||||
case 0x00000000: /* BUS */
|
||||
FCEU_printf(" %04X-%04X OPEN BUS\n",presp & 0x7fff, (resp - 1) & 0x7fff);
|
||||
break;
|
||||
case 0x00010000: /* RAM */
|
||||
FCEU_printf(" %04X-%04X RAM\n",presp & 0x7fff, (resp - 1) & 0x7fff);
|
||||
SetWriteHandler(presp & 0x7fff, (resp - 1) & 0x7fff, CartBW);
|
||||
SetReadHandler(presp & 0x7fff, (resp - 1) & 0x7fff, CartBR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
presp = resp;
|
||||
}
|
||||
#endif
|
||||
SetWriteHandler(0x8000, 0xffff, MCopyFamiWrite);
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
|
||||
FCEU_printf("DONE!\nNOW COLLECTING DATA...\n");
|
||||
}
|
||||
|
||||
static void MCopyFamiClose(void) {
|
||||
if (chr_data.buf)
|
||||
FCEU_gfree(chr_data.buf);
|
||||
chr_data.buf = NULL;
|
||||
if (prg_data.buf)
|
||||
FCEU_gfree(prg_data.buf);
|
||||
prg_data.buf = NULL;
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
|
||||
SerialClose();
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void MapperCopyFami_Init(CartInfo *info) {
|
||||
uint32 resp = 0, i, size;
|
||||
|
||||
memset(chr_bank, -1, sizeof(chr_bank));
|
||||
memset(prg_bank, -1, sizeof(chr_bank));
|
||||
memset(cmd_cache, -1, sizeof(cmd_cache));
|
||||
memset(&cmds, 0, sizeof(cmds));
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
info->Reset = MCopyFamiReset;
|
||||
info->Power = MCopyFamiPower;
|
||||
info->Close = MCopyFamiClose;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
size = 1024 * CHR_CACHE_SIZE; /* ðàçìåð ñòðàíèöû 1êá */
|
||||
chr_data.buf = (uint8*)FCEU_gmalloc(size);
|
||||
SetupCartCHRMapping(1, chr_data.buf, size, 1); /* ïðîâåðÿòü ïïó ðàì, èíà÷å èãðà ìîæåò ïîðòèòü äàííûå */
|
||||
AddExState(chr_data.buf, size, 0, "CCHR");
|
||||
|
||||
size = 8192; /* ðàçìåð ñòðàíèöû 8êá */
|
||||
WRAM = (uint8*)FCEU_gmalloc(size);
|
||||
SetupCartPRGMapping(1, WRAM, size, 1);
|
||||
AddExState(WRAM, size, 0, "CPRM");
|
||||
|
||||
size = 8192 * PRG_CACHE_SIZE; /* ðàçìåð ñòðàíèöû 8êá */
|
||||
prg_data.buf = (uint8*)FCEU_gmalloc(size);
|
||||
SetupCartPRGMapping(2, prg_data.buf, size, 0);
|
||||
AddExState(prg_data.buf, size, 0, "CPPR");
|
||||
|
||||
|
||||
FCEU_printf("WAITING FOR SERIAL PORT... ");
|
||||
while (!SerialOpen(19, 921600)) {
|
||||
Sleep(500);
|
||||
}
|
||||
FCEU_printf("READY!\n");
|
||||
|
||||
FCEU_printf("WAITING FOR DEVICE... ");
|
||||
|
||||
while (resp != *(uint32*)&InitVector[0]) {
|
||||
SEND(ResetCmd);
|
||||
SENDGET(InitVector, resp, 4);
|
||||
Sleep(500);
|
||||
}
|
||||
|
||||
FCEU_printf("READY!\n");
|
||||
FCEU_printf("READING STATUS...\n");
|
||||
GetStatus(&state_cur);
|
||||
FCEU_printf("MIRRORING IS %s (%02X)\n", mirror_names[mirror_modes[state_cur.mirror]], state_cur.mirror);
|
||||
FCEU_printf("READING CHR...\n INITIAL STATE:");
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (CHRCUR(i) == -1)
|
||||
CHRCUR(i) = FetchNewCHRBank(i);
|
||||
FCEU_printf(" CHR%d=%02X", i, CHRCUR(i));
|
||||
}
|
||||
FCEU_printf("\n");
|
||||
|
||||
FCEU_printf("READING PRG...\n INITIAL STATE:");
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (PRGCUR(i) == -1)
|
||||
PRGCUR(i) = FetchNewPRGBank(i);
|
||||
FCEU_printf(" PRG%d=%02X", i, PRGCUR(i));
|
||||
}
|
||||
FCEU_printf("\nDONE!\n");
|
||||
|
||||
state_def = state_cur;
|
||||
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
#endif
|
12
src/driver.h
12
src/driver.h
@ -47,13 +47,6 @@ int FCEUI_EndWaveRecord(void);
|
||||
void FCEUI_ResetNES(void);
|
||||
void FCEUI_PowerNES(void);
|
||||
|
||||
void FCEUI_NTSCSELHUE(void);
|
||||
void FCEUI_NTSCSELTINT(void);
|
||||
void FCEUI_NTSCDEC(void);
|
||||
void FCEUI_NTSCINC(void);
|
||||
void FCEUI_GetNTSCTH(int *tint, int *hue);
|
||||
void FCEUI_SetNTSCTH(int n, int tint, int hue);
|
||||
|
||||
void FCEUI_SetInput(int port, int type, void *ptr, int attrib);
|
||||
void FCEUI_SetInputFC(int type, void *ptr, int attrib);
|
||||
void FCEUI_DisableFourScore(int s);
|
||||
@ -110,11 +103,6 @@ typedef void (*frontend_post_load_init_cb_t)(void);
|
||||
FCEUGI *FCEUI_LoadGame(const char *name, const uint8_t *databuf, size_t databufsize,
|
||||
frontend_post_load_init_cb_t frontend_post_load_init_cb);
|
||||
|
||||
#ifdef COPYFAMI
|
||||
/* Fake UNIF board to start new CFHI instance */
|
||||
FCEUGI *FCEUI_CopyFamiStart();
|
||||
#endif
|
||||
|
||||
/* allocates memory. 0 on failure, 1 on success. */
|
||||
int FCEUI_Initialize(void);
|
||||
|
||||
|
57
src/fceu.c
57
src/fceu.c
@ -166,11 +166,7 @@ void FASTAPASS(3) SetWriteHandler(int32 start, int32 end, writefunc func)
|
||||
BWrite[x] = func;
|
||||
}
|
||||
|
||||
#ifdef COPYFAMI
|
||||
uint8 RAM[0x4000];
|
||||
#else
|
||||
uint8 RAM[0x800];
|
||||
#endif
|
||||
|
||||
uint8 PAL = 0;
|
||||
|
||||
@ -184,7 +180,6 @@ static DECLFR(ARAML)
|
||||
return RAM[A];
|
||||
}
|
||||
|
||||
#ifndef COPYFAMI
|
||||
static DECLFW(BRAMH)
|
||||
{
|
||||
RAM[A & 0x7FF] = V;
|
||||
@ -194,7 +189,6 @@ static DECLFR(ARAMH)
|
||||
{
|
||||
return RAM[A & 0x7FF];
|
||||
}
|
||||
#endif
|
||||
|
||||
void FCEUI_CloseGame(void)
|
||||
{
|
||||
@ -312,49 +306,6 @@ endlseq:
|
||||
return(GameInfo);
|
||||
}
|
||||
|
||||
int CopyFamiLoad(void);
|
||||
|
||||
FCEUGI *FCEUI_CopyFamiStart(void)
|
||||
{
|
||||
ResetGameLoaded();
|
||||
|
||||
GameInfo = (FCEUGI*)malloc(sizeof(FCEUGI));
|
||||
memset(GameInfo, 0, sizeof(FCEUGI));
|
||||
|
||||
GameInfo->soundchan = 0;
|
||||
GameInfo->soundrate = 0;
|
||||
GameInfo->name = (uint8_t*)"copyfami";
|
||||
GameInfo->type = GIT_CART;
|
||||
GameInfo->vidsys = GIV_USER;
|
||||
GameInfo->input[0] = GameInfo->input[1] = -1;
|
||||
GameInfo->inputfc = -1;
|
||||
GameInfo->cspecial = 0;
|
||||
|
||||
FCEU_printf("Starting CopyFamicom...\n\n");
|
||||
|
||||
if (!CopyFamiLoad()) {
|
||||
FCEU_PrintError("An error occurred while starting CopyFamicom.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
FCEU_ResetVidSys();
|
||||
if (GameInfo->type != GIT_NSF)
|
||||
if (FSettings.GameGenie)
|
||||
FCEU_OpenGenie();
|
||||
|
||||
PowerNES();
|
||||
|
||||
if (GameInfo->type != GIT_NSF) {
|
||||
FCEU_LoadGamePalette();
|
||||
FCEU_LoadGameCheats();
|
||||
}
|
||||
|
||||
FCEU_ResetPalette();
|
||||
FCEU_ResetMessages(); /* Save state, status messages, etc. */
|
||||
|
||||
return(GameInfo);
|
||||
}
|
||||
|
||||
int FCEUI_Initialize(void) {
|
||||
if (!FCEU_InitVirtualVideo())
|
||||
return 0;
|
||||
@ -447,23 +398,17 @@ void PowerNES(void)
|
||||
|
||||
FCEU_GeniePower();
|
||||
|
||||
#ifndef COPYFAMI
|
||||
FCEU_MemoryRand(RAM, 0x800);
|
||||
#endif
|
||||
|
||||
SetReadHandler(0x0000, 0xFFFF, ANull);
|
||||
SetWriteHandler(0x0000, 0xFFFF, BNull);
|
||||
|
||||
#ifdef COPYFAMI
|
||||
SetReadHandler(0, 0x3FFF, ARAML);
|
||||
SetWriteHandler(0, 0x3FFF, BRAML);
|
||||
#else
|
||||
SetReadHandler(0, 0x7FF, ARAML);
|
||||
SetWriteHandler(0, 0x7FF, BRAML);
|
||||
|
||||
SetReadHandler(0x800, 0x1FFF, ARAMH); /* Part of a little */
|
||||
SetWriteHandler(0x800, 0x1FFF, BRAMH); /* hack for a small speed boost. */
|
||||
#endif
|
||||
|
||||
InitializeInput();
|
||||
FCEUSND_Power();
|
||||
FCEUPPU_Power();
|
||||
|
@ -55,11 +55,7 @@ extern uint8 MMC50x5130;
|
||||
extern uint8 MMC5HackSPScroll;
|
||||
extern uint8 MMC5HackSPPage;
|
||||
|
||||
#ifdef COPYFAMI
|
||||
extern uint8 RAM[0x4000];
|
||||
#else
|
||||
extern uint8 RAM[0x800];
|
||||
#endif
|
||||
|
||||
extern readfunc ARead[0x10000];
|
||||
extern writefunc BWrite[0x10000];
|
||||
|
153
src/palette.c
153
src/palette.c
@ -33,20 +33,10 @@
|
||||
#include "palette.h"
|
||||
#include "palettes/palettes.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
static int ntsccol = 0;
|
||||
static int ntsctint = 46 + 10;
|
||||
static int ntschue = 72;
|
||||
|
||||
/* These are dynamically filled/generated palettes: */
|
||||
pal palettei[64]; /* Custom palette for an individual game. */
|
||||
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;
|
||||
@ -77,14 +67,6 @@ void FCEUI_SetPaletteArray(uint8 *pal) {
|
||||
FCEU_ResetPalette();
|
||||
}
|
||||
|
||||
|
||||
void FCEUI_SetNTSCTH(int n, int tint, int hue) {
|
||||
ntsctint = tint;
|
||||
ntschue = hue;
|
||||
ntsccol = n;
|
||||
FCEU_ResetPalette();
|
||||
}
|
||||
|
||||
static uint8 lastd = 0;
|
||||
void SetNESDeemph(uint8 d, int force) {
|
||||
static uint16 rtmul[7] = { 32768 * 1.239, 32768 * .794, 32768 * 1.019, 32768 * .905, 32768 * 1.023, 32768 * .741, 32768 * .75 };
|
||||
@ -142,50 +124,6 @@ void SetNESDeemph(uint8 d, int force) {
|
||||
lastd = d;
|
||||
}
|
||||
|
||||
/* Converted from Kevin Horton's qbasic palette generator. */
|
||||
static void CalculatePalette(void) {
|
||||
int x, z;
|
||||
int r, g, b;
|
||||
double s, luma, theta;
|
||||
static uint8 cols[16] = { 0, 24, 21, 18, 15, 12, 9, 6, 3, 0, 33, 30, 27, 0, 0, 0 };
|
||||
static uint8 br1[4] = { 6, 9, 12, 12 };
|
||||
static double br2[4] = { .29, .45, .73, .9 };
|
||||
static double br3[4] = { 0, .24, .47, .77 };
|
||||
|
||||
for (x = 0; x <= 3; x++)
|
||||
for (z = 0; z < 16; z++) {
|
||||
s = (double)ntsctint / 128;
|
||||
luma = br2[x];
|
||||
if (z == 0) {
|
||||
s = 0; luma = ((double)br1[x]) / 12;
|
||||
}
|
||||
|
||||
if (z >= 13) {
|
||||
s = luma = 0;
|
||||
if (z == 13)
|
||||
luma = br3[x];
|
||||
}
|
||||
|
||||
theta = (double)M_PI * (double)(((double)cols[z] * 10 + (((double)ntschue / 2) + 300)) / (double)180);
|
||||
r = (int)((luma + s * sin(theta)) * 256);
|
||||
g = (int)((luma - (double)27 / 53 * s * sin(theta) + (double)10 / 53 * s * cos(theta)) * 256);
|
||||
b = (int)((luma - s * cos(theta)) * 256);
|
||||
|
||||
|
||||
if (r > 255) r = 255;
|
||||
if (g > 255) g = 255;
|
||||
if (b > 255) b = 255;
|
||||
if (r < 0) r = 0;
|
||||
if (g < 0) g = 0;
|
||||
if (b < 0) b = 0;
|
||||
|
||||
paletten[(x << 4) + z].r = r;
|
||||
paletten[(x << 4) + z].g = g;
|
||||
paletten[(x << 4) + z].b = b;
|
||||
}
|
||||
WritePalette();
|
||||
}
|
||||
|
||||
int ipalette = 0;
|
||||
|
||||
void FCEU_LoadGamePalette(void) {
|
||||
@ -228,10 +166,7 @@ static void ChoosePalette(void) {
|
||||
palo = 0;
|
||||
else if (ipalette)
|
||||
palo = palettei;
|
||||
else if (ntsccol && !PAL && GameInfo->type != GIT_VSUNI) {
|
||||
palo = paletten;
|
||||
CalculatePalette();
|
||||
} else
|
||||
else
|
||||
palo = palpoint[pale];
|
||||
}
|
||||
|
||||
@ -247,89 +182,3 @@ void WritePalette(void) {
|
||||
SetNESDeemph(lastd, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void FCEUI_GetNTSCTH(int *tint, int *hue) {
|
||||
*tint = ntsctint;
|
||||
*hue = ntschue;
|
||||
}
|
||||
|
||||
static int controlselect = 0;
|
||||
static int controllength = 0;
|
||||
|
||||
void FCEUI_NTSCDEC(void) {
|
||||
if (ntsccol && GameInfo->type != GIT_VSUNI && !PAL && GameInfo->type != GIT_NSF) {
|
||||
int which;
|
||||
if (controlselect) {
|
||||
if (controllength) {
|
||||
which = controlselect == 1 ? ntschue : ntsctint;
|
||||
which--;
|
||||
if (which < 0) which = 0;
|
||||
if (controlselect == 1)
|
||||
ntschue = which;
|
||||
else ntsctint = which;
|
||||
CalculatePalette();
|
||||
}
|
||||
controllength = 360;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FCEUI_NTSCINC(void) {
|
||||
if (ntsccol && GameInfo->type != GIT_VSUNI && !PAL && GameInfo->type != GIT_NSF)
|
||||
if (controlselect) {
|
||||
if (controllength) {
|
||||
switch (controlselect) {
|
||||
case 1: ntschue++;
|
||||
if (ntschue > 128) ntschue = 128;
|
||||
CalculatePalette();
|
||||
break;
|
||||
case 2: ntsctint++;
|
||||
if (ntsctint > 128) ntsctint = 128;
|
||||
CalculatePalette();
|
||||
break;
|
||||
}
|
||||
}
|
||||
controllength = 360;
|
||||
}
|
||||
}
|
||||
|
||||
void FCEUI_NTSCSELHUE(void) {
|
||||
if (ntsccol && GameInfo->type != GIT_VSUNI && !PAL && GameInfo->type != GIT_NSF) {
|
||||
controlselect = 1; controllength = 360;
|
||||
}
|
||||
}
|
||||
|
||||
void FCEUI_NTSCSELTINT(void) {
|
||||
if (ntsccol && GameInfo->type != GIT_VSUNI && !PAL && GameInfo->type != GIT_NSF) {
|
||||
controlselect = 2; controllength = 360;
|
||||
}
|
||||
}
|
||||
|
||||
void FCEU_DrawNTSCControlBars(uint8 *XBuf) {
|
||||
uint8 *XBaf;
|
||||
int which = 0;
|
||||
int x, x2;
|
||||
|
||||
if (!controllength) return;
|
||||
controllength--;
|
||||
if (!XBuf) return;
|
||||
|
||||
if (controlselect == 1) {
|
||||
DrawTextTrans(XBuf + 128 - 12 + 180 * 256, 256, (uint8*)"Hue", 0x85);
|
||||
which = ntschue << 1;
|
||||
} else if (controlselect == 2) {
|
||||
DrawTextTrans(XBuf + 128 - 16 + 180 * 256, 256, (uint8*)"Tint", 0x85);
|
||||
which = ntsctint << 1;
|
||||
}
|
||||
|
||||
XBaf = XBuf + 200 * 256;
|
||||
for (x = 0; x < which; x += 2) {
|
||||
for (x2 = 6; x2 >= -6; x2--) {
|
||||
XBaf[x - 256 * x2] = 0x85;
|
||||
}
|
||||
}
|
||||
for (; x < 256; x += 2) {
|
||||
for (x2 = 2; x2 >= -2; x2--)
|
||||
XBaf[x - 256 * x2] = 0x85;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,5 @@ void FCEU_ResetPalette(void);
|
||||
void FCEU_ResetPalette(void);
|
||||
void FCEU_ResetMessages();
|
||||
void FCEU_LoadGamePalette(void);
|
||||
void FCEU_DrawNTSCControlBars(uint8 *XBuf);
|
||||
|
||||
#endif
|
||||
|
22
src/ppu.c
22
src/ppu.c
@ -1096,26 +1096,6 @@ void FCEUPPU_Power(void) {
|
||||
memset(UPALRAM, 0x00, 0x03);
|
||||
memset(SPRAM, 0x00, 0x100);
|
||||
FCEUPPU_Reset();
|
||||
#ifdef COPYFAMI
|
||||
for (x = 0x2000; x < 0x2010; x += 8) {
|
||||
ARead[x] = A200x;
|
||||
BWrite[x] = B2000;
|
||||
ARead[x + 1] = A200x;
|
||||
BWrite[x + 1] = B2001;
|
||||
ARead[x + 2] = A2002;
|
||||
BWrite[x + 2] = B2002;
|
||||
ARead[x + 3] = A200x;
|
||||
BWrite[x + 3] = B2003;
|
||||
ARead[x + 4] = A200x; /* A2004; */
|
||||
BWrite[x + 4] = B2004;
|
||||
ARead[x + 5] = A200x;
|
||||
BWrite[x + 5] = B2005;
|
||||
ARead[x + 6] = A200x;
|
||||
BWrite[x + 6] = B2006;
|
||||
ARead[x + 7] = A2007;
|
||||
BWrite[x + 7] = B2007;
|
||||
}
|
||||
#else
|
||||
for (x = 0x2000; x < 0x4000; x += 8) {
|
||||
ARead[x] = A200x;
|
||||
BWrite[x] = B2000;
|
||||
@ -1134,7 +1114,7 @@ void FCEUPPU_Power(void) {
|
||||
ARead[x + 7] = A2007;
|
||||
BWrite[x + 7] = B2007;
|
||||
}
|
||||
#endif
|
||||
|
||||
BWrite[0x4014] = B4014;
|
||||
}
|
||||
|
||||
|
@ -61,11 +61,7 @@ SFORMAT SFCPU[] = {
|
||||
{ &X.S, 1, "S\0\0" },
|
||||
{ &X.P, 1, "P\0\0" },
|
||||
{ &X.DB, 1, "DB"},
|
||||
#ifdef COPYFAMI
|
||||
{ RAM, 0x4000, "RAM" },
|
||||
#else
|
||||
{ RAM, 0x800, "RAM" },
|
||||
#endif
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
19
src/unif.c
19
src/unif.c
@ -622,11 +622,6 @@ static BMAPPING bmap[] = {
|
||||
{ "BS-4040R", 422, Mapper422_Init, 0 },
|
||||
{ "22026", 271, Mapper271_Init, 0 },
|
||||
|
||||
#ifdef COPYFAMI
|
||||
{ "COPYFAMI_MMC3", NO_INES, MapperCopyFamiMMC3_Init, 0 },
|
||||
{ "COPYFAMI", NO_INES, MapperCopyFami_Init, 0 },
|
||||
#endif
|
||||
|
||||
{ NULL, NO_INES, NULL, 0 }
|
||||
};
|
||||
|
||||
@ -849,17 +844,3 @@ int UNIFLoad(const char *name, FCEUFILE *fp) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CopyFamiLoad() {
|
||||
ResetCartMapping();
|
||||
ResetExState(0, 0);
|
||||
|
||||
sboardname = (uint8_t*)"COPYFAMI";
|
||||
if (!InitializeBoard()) {
|
||||
Cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
GameInterface = UNIFGI;
|
||||
return 1;
|
||||
}
|
||||
|
@ -187,11 +187,6 @@ void WAIXINGFS005_Init(CartInfo *info);
|
||||
void Mapper422_Init(CartInfo *info);
|
||||
void Mapper444_Init(CartInfo *info);
|
||||
|
||||
#ifdef COPYFAMI
|
||||
void MapperCopyFamiMMC3_Init(CartInfo *info);
|
||||
void MapperCopyFami_Init(CartInfo *info);
|
||||
#endif
|
||||
|
||||
extern uint8 *UNIFchrrama; /* Meh. So I can stop CHR RAM
|
||||
* bank switcherooing with certain boards...
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user