2376 lines
84 KiB
C
2376 lines
84 KiB
C
/* FCE Ultra - NES/Famicom Emulator
|
||
*
|
||
* Copyright notice for this file:
|
||
* Copyright (C) 2022 Cluster
|
||
*
|
||
* This program is free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation; either version 2 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program; if not, write to the Free Software
|
||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
*
|
||
* Very complicated homebrew multicart mapper with.
|
||
* The code is so obscured and weird because it's ported from Verilog CPLD source code:
|
||
* https://github.com/ClusterM/coolgirl-famicom-multicart/blob/master/CoolGirl_mappers.vh
|
||
*
|
||
* Range: $5000-$5FFF
|
||
*
|
||
* Mask: $5007
|
||
*
|
||
* All registers are $00 on power-on and reset.
|
||
*
|
||
* $5xx0
|
||
* 7 bit 0
|
||
* ---- ----
|
||
* PPPP PPPP
|
||
* |||| ||||
|
||
* ++++-++++-- PRG base offset (A29-A22)
|
||
*
|
||
* $5xx1
|
||
* 7 bit 0
|
||
* ---- ----
|
||
* PPPP PPPP
|
||
* |||| ||||
|
||
* ++++-++++-- PRG base offset (A21-A14)
|
||
*
|
||
* $5xx2
|
||
* 7 bit 0
|
||
* ---- ----
|
||
* AMMM MMMM
|
||
* |||| ||||
|
||
* |+++-++++-- PRG mask (A20-A14, inverted+anded with PRG address)
|
||
* +---------- CHR mask (A18, inverted+anded with CHR address)
|
||
*
|
||
* $5xx3
|
||
* 7 bit 0
|
||
* ---- ----
|
||
* BBBC CCCC
|
||
* |||| ||||
|
||
* |||+-++++-- CHR bank A (bits 7-3)
|
||
* +++-------- PRG banking mode (see below)
|
||
*
|
||
* $5xx4
|
||
* 7 bit 0
|
||
* ---- ----
|
||
* DDDE EEEE
|
||
* |||| ||||
|
||
* |||+-++++-- CHR mask (A17-A13, inverted+anded with CHR address)
|
||
* +++-------- CHR banking mode (see below)
|
||
*
|
||
* $5xx5
|
||
* 7 bit 0
|
||
* ---- ----
|
||
* CDDE EEWW
|
||
* |||| ||||
|
||
* |||| ||++-- 8KiB WRAM page at $6000-$7FFF
|
||
* |+++-++---- PRG bank A (bits 5-1)
|
||
* +---------- CHR bank A (bit 8)
|
||
*
|
||
* $5xx6
|
||
* 7 bit 0
|
||
* ---- ----
|
||
* FFFM MMMM
|
||
* |||| ||||
|
||
* |||+ ++++-- Mapper code (bits 4-0, see below)
|
||
* +++-------- Flags 2-0, functionality depends on selected mapper
|
||
*
|
||
* $5xx7
|
||
* 7 bit 0
|
||
* ---- ----
|
||
* LMTR RSNO
|
||
* |||| |||+-- Enable WRAM (read and write) at $6000-$7FFF
|
||
* |||| ||+--- Allow writes to CHR RAM
|
||
* |||| |+---- Allow writes to flash chip
|
||
* |||+-+----- Mirroring (00=vertical, 01=horizontal, 10=1Sa, 11=1Sb)
|
||
* ||+-------- Enable four-screen mode
|
||
* |+-- ------ Mapper code (bit 5, see below)
|
||
* +---------- Lockout bit (prevent further writes to all registers)
|
||
*
|
||
*/
|
||
|
||
#include <ctype.h>
|
||
#include "mapinc.h"
|
||
|
||
const uint32 SAVE_FLASH_SIZE = 1024 * 1024 * 8;
|
||
const uint32 FLASH_SECTOR_SIZE = 128 * 1024;
|
||
const int ROM_CHIP = 0x00;
|
||
const int WRAM_CHIP = 0x10;
|
||
const int FLASH_CHIP = 0x11;
|
||
const int CFI_CHIP = 0x13;
|
||
|
||
static int CHR_SIZE = 0;
|
||
static uint32 WRAM_SIZE = 0;
|
||
static uint8 *WRAM = NULL;
|
||
static uint8 *SAVE_FLASH = NULL;
|
||
static uint8* CFI;
|
||
|
||
static uint8 sram_enabled = 0;
|
||
static uint8 sram_page = 0; /* [1:0] */
|
||
static uint8 can_write_chr = 0;
|
||
static uint8 map_rom_on_6000 = 0;
|
||
static uint8 flags = 0; /* [2:0] */
|
||
static uint8 mapper = 0; /* [5:0] */
|
||
static uint8 can_write_flash = 0;
|
||
static uint8 mirroring = 0; /* [1:0] */
|
||
static uint8 four_screen = 0;
|
||
static uint8 lockout = 0;
|
||
|
||
static uint32 prg_base = 0; /* [26:14] */
|
||
static uint32 prg_mask = 0xF8 << 14; /* 11111000, 128KB [20:14] */
|
||
static uint8 prg_mode = 0; /* [2:0] */
|
||
static uint8 prg_bank_6000 = 0; /* [7:0] */
|
||
static uint8 prg_bank_a = 0; /* [7:0] */
|
||
static uint8 prg_bank_b = 1; /* [7:0] */
|
||
static uint8 prg_bank_c = ~1; /* [7:0] */
|
||
static uint8 prg_bank_d = ~0; /* [7:0] */
|
||
|
||
static uint32 chr_mask = 0; /* [18:13] */
|
||
static uint8 chr_mode = 0; /* [2:0] */
|
||
static uint16 chr_bank_a = 0; /* [8:0] */
|
||
static uint16 chr_bank_b = 1; /* [8:0] */
|
||
static uint16 chr_bank_c = 2; /* [8:0] */
|
||
static uint16 chr_bank_d = 3; /* [8:0] */
|
||
static uint16 chr_bank_e = 4; /* [8:0] */
|
||
static uint16 chr_bank_f = 5; /* [8:0] */
|
||
static uint16 chr_bank_g = 6; /* [8:0] */
|
||
static uint16 chr_bank_h = 7; /* [8:0] */
|
||
|
||
static uint8 TKSMIR[8];
|
||
|
||
static uint32 prg_bank_6000_mapped = 0;
|
||
static uint32 prg_bank_a_mapped = 0;
|
||
static uint32 prg_bank_b_mapped = 0;
|
||
static uint32 prg_bank_c_mapped = 0;
|
||
static uint32 prg_bank_d_mapped = 0;
|
||
|
||
/* for MMC2/MMC4 */
|
||
static uint8 ppu_latch0 = 0;
|
||
static uint8 ppu_latch1 = 0;
|
||
/* for MMC1 */
|
||
static uint64 lreset = 0;
|
||
static uint8 mmc1_load_register = 0; /* [5:0] */
|
||
/* for MMC3 */
|
||
static uint8 mmc3_internal = 0; /* [2:0] */
|
||
/* for mapper #69 */
|
||
static uint8 mapper69_internal = 0; /* [3:0] */
|
||
/* for mapper #112 */
|
||
static uint8 mapper112_internal = 0; /* [2:0] */
|
||
/* for mapper #163 */
|
||
static uint8 mapper_163_latch = 0;
|
||
static uint8 mapper163_r0 = 0; /* [7:0] */
|
||
static uint8 mapper163_r1 = 0; /* [7:0] */
|
||
static uint8 mapper163_r2 = 0; /* [7:0] */
|
||
static uint8 mapper163_r3 = 0; /* [7:0] */
|
||
static uint8 mapper163_r4 = 0; /* [7:0] */
|
||
static uint8 mapper163_r5 = 0; /* [7:0] */
|
||
|
||
/* For mapper #90 */
|
||
static uint8 mul1 = 0;
|
||
static uint8 mul2 = 0;
|
||
|
||
/* for MMC3 scanline-based interrupts, counts A12 rises after long A12 falls */
|
||
static uint8 mmc3_irq_enabled = 0; /* register to enable/disable counter */
|
||
static uint8 mmc3_irq_latch = 0; /* [7:0], stores counter reload latch value */
|
||
static uint8 mmc3_irq_counter = 0; /* [7:0], counter itself (downcounting) */
|
||
static uint8 mmc3_irq_reload = 0; /* flag to reload counter from latch */
|
||
/* for MMC5 scanline-based interrupts, counts dummy PPU reads */
|
||
static uint8 mmc5_irq_enabled = 0; /* register to enable/disable counter */
|
||
static uint8 mmc5_irq_line = 0; /* [7:0], scanline on which IRQ will be triggered */
|
||
static uint8 mmc5_irq_out = 0; /* stores 1 when IRQ is triggered */
|
||
/* for mapper #18 */
|
||
static uint16 mapper18_irq_value = 0; /* [15:0], counter itself (downcounting) */
|
||
static uint8 mapper18_irq_control = 0; /* [3:0], IRQ settings */
|
||
static uint16 mapper18_irq_latch = 0; /* [15:0], stores counter reload latch value */
|
||
/* for mapper #65 */
|
||
static uint8 mapper65_irq_enabled = 0; /* register to enable/disable IRQ */
|
||
static uint16 mapper65_irq_value = 0; /* [15:0], counter itself (downcounting) */
|
||
static uint16 mapper65_irq_latch = 0; /* [15:0], stores counter reload latch value */
|
||
/* reg mapper65_irq_out = 0;
|
||
* for Sunsoft FME-7 */
|
||
static uint8 mapper69_irq_enabled = 0; /* register to enable/disable IRQ */
|
||
static uint8 mapper69_counter_enabled = 0; /* register to enable/disable counter */
|
||
static uint16 mapper69_irq_value = 0; /* counter itself (downcounting) */
|
||
/* for VRC4 CPU-based interrupts */
|
||
static uint8 vrc4_irq_value = 0; /* [7:0], counter itself (upcounting) */
|
||
static uint8 vrc4_irq_control = 0; /* [2:0]<5D> IRQ settings */
|
||
static uint8 vrc4_irq_latch = 0; /* [7:0], stores counter reload latch value */
|
||
static uint8 vrc4_irq_prescaler = 0; /* [6:0], prescaler counter for VRC4 */
|
||
static uint8 vrc4_irq_prescaler_counter = 0; /* prescaler cicles counter for VRC4 */
|
||
/* for VRC3 CPU-based interrupts */
|
||
static uint16 vrc3_irq_value = 0; /* [15:0], counter itself (upcounting) */
|
||
static uint8 vrc3_irq_control = 0; /* [3:0], IRQ settings */
|
||
static uint16 vrc3_irq_latch = 0; /* [15:0], stores counter reload latch value */
|
||
/* for mapper #42 (only Baby Mario) */
|
||
static uint8 mapper42_irq_enabled = 0; /* register to enable/disable counter */
|
||
static uint16 mapper42_irq_value = 0; /* [14:0], counter itself (upcounting) */
|
||
/* for mapper #83 */
|
||
static uint8 mapper83_irq_enabled_latch = 0;
|
||
static uint8 mapper83_irq_enabled = 0;
|
||
static uint16 mapper83_irq_counter = 0;
|
||
/* for mapper #90 */
|
||
static uint8 mapper90_xor = 0;
|
||
/* for mapper #67 */
|
||
static uint8 mapper67_irq_enabled = 0;
|
||
static uint8 mapper67_irq_latch = 0;
|
||
static uint16 mapper67_irq_counter = 0;
|
||
|
||
static uint8 flash_state = 0;
|
||
static uint16 flash_buffer_a[10];
|
||
static uint8 flash_buffer_v[10];
|
||
static uint8 cfi_mode = 0;
|
||
|
||
/* Micron 4-gbit memory CFI data */
|
||
const uint8 cfi_data[] =
|
||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x51, 0x52, 0x59, 0x02, 0x00, 0x40, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x27, 0x36, 0x00, 0x00, 0x06,
|
||
0x06, 0x09, 0x13, 0x03, 0x05, 0x03, 0x02, 0x1E,
|
||
0x02, 0x00, 0x06, 0x00, 0x01, 0xFF, 0x03, 0x00,
|
||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
|
||
0x50, 0x52, 0x49, 0x31, 0x33, 0x14, 0x02, 0x01,
|
||
0x00, 0x08, 0x00, 0x00, 0x02, 0xB5, 0xC5, 0x05,
|
||
0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||
|
||
#define SET_BITS(target, target_bits, source, source_bits) target = set_bits(target, target_bits, get_bits(source, source_bits))
|
||
|
||
static INLINE uint8 string_to_bits(char* bitsstr, int* bits)
|
||
{
|
||
int i;
|
||
uint8 bit1, bit2, count = 0;
|
||
for (i = 0; i < 32; i++)
|
||
bits[i] = -1;
|
||
while (*bitsstr)
|
||
{
|
||
bit1 = 0;
|
||
bit2 = 0;
|
||
if (isdigit(*bitsstr))
|
||
{
|
||
while (isdigit(*bitsstr))
|
||
{
|
||
bit1 *= 10;
|
||
bit1 += *bitsstr - '0';
|
||
bitsstr++;
|
||
}
|
||
if (*bitsstr == ':')
|
||
{
|
||
bitsstr++;
|
||
while (isdigit(*bitsstr))
|
||
{
|
||
bit2 *= 10;
|
||
bit2 += *bitsstr - '0';
|
||
bitsstr++;
|
||
}
|
||
if (bit2 < bit1)
|
||
for (i = bit1; i >= bit2; i--)
|
||
{
|
||
bits[count] = i;
|
||
count++;
|
||
}
|
||
else
|
||
for (i = bit1; i <= bit2; i++)
|
||
{
|
||
bits[count] = i;
|
||
count++;
|
||
}
|
||
}
|
||
else {
|
||
bits[count] = bit1;
|
||
count++;
|
||
}
|
||
}
|
||
else {
|
||
bitsstr++;
|
||
}
|
||
}
|
||
return count;
|
||
}
|
||
|
||
static INLINE uint32 get_bits(uint32 V, char* bitsstr)
|
||
{
|
||
int i;
|
||
uint32 result = 0;
|
||
int bits[32];
|
||
string_to_bits(bitsstr, bits);
|
||
for (i = 0; bits[i] >= 0; i++)
|
||
{
|
||
result <<= 1;
|
||
result |= (V >> bits[i]) & 1;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
static INLINE uint32 set_bits(uint32 V, char* bitsstr, uint32 new_bits)
|
||
{
|
||
int i;
|
||
int bits[32];
|
||
uint8 count = string_to_bits(bitsstr, bits);
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
if ((new_bits >> (count - i - 1)) & 1)
|
||
V |= 1 << bits[i];
|
||
else
|
||
V &= ~(1 << bits[i]);
|
||
}
|
||
return V;
|
||
}
|
||
|
||
static void COOLGIRL_Sync_PRG(void) {
|
||
uint8 REG_A_CHIP, REG_B_CHIP, REG_C_CHIP, REG_D_CHIP;
|
||
prg_bank_6000_mapped = (prg_base >> 13) | (prg_bank_6000 & ((~(prg_mask >> 13) & 0xFE) | 1));
|
||
prg_bank_a_mapped = (prg_base >> 13) | (prg_bank_a & ((~(prg_mask >> 13) & 0xFE) | 1));
|
||
prg_bank_b_mapped = (prg_base >> 13) | (prg_bank_b & ((~(prg_mask >> 13) & 0xFE) | 1));
|
||
prg_bank_c_mapped = (prg_base >> 13) | (prg_bank_c & ((~(prg_mask >> 13) & 0xFE) | 1));
|
||
prg_bank_d_mapped = (prg_base >> 13) | (prg_bank_d & ((~(prg_mask >> 13) & 0xFE) | 1));
|
||
REG_A_CHIP = (SAVE_FLASH != NULL && prg_bank_a_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP;
|
||
REG_B_CHIP = (SAVE_FLASH != NULL && prg_bank_b_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP;
|
||
REG_C_CHIP = (SAVE_FLASH != NULL && prg_bank_c_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP;
|
||
REG_D_CHIP = (SAVE_FLASH != NULL && prg_bank_d_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP;
|
||
|
||
if (!cfi_mode || !SAVE_FLASH)
|
||
{
|
||
switch (prg_mode & 7)
|
||
{
|
||
default:
|
||
case 0:
|
||
setprg16r(REG_A_CHIP, 0x8000, prg_bank_a_mapped >> 1);
|
||
setprg16r(REG_C_CHIP, 0xC000, prg_bank_c_mapped >> 1);
|
||
break;
|
||
case 1:
|
||
setprg16r(REG_C_CHIP, 0x8000, prg_bank_c_mapped >> 1);
|
||
setprg16r(REG_A_CHIP, 0xC000, prg_bank_a_mapped >> 1);
|
||
break;
|
||
case 4:
|
||
setprg8r(REG_A_CHIP, 0x8000, prg_bank_a_mapped);
|
||
setprg8r(REG_B_CHIP, 0xA000, prg_bank_b_mapped);
|
||
setprg8r(REG_C_CHIP, 0xC000, prg_bank_c_mapped);
|
||
setprg8r(REG_D_CHIP, 0xE000, prg_bank_d_mapped);
|
||
break;
|
||
case 5:
|
||
setprg8r(REG_C_CHIP, 0x8000, prg_bank_c_mapped);
|
||
setprg8r(REG_B_CHIP, 0xA000, prg_bank_b_mapped);
|
||
setprg8r(REG_A_CHIP, 0xC000, prg_bank_a_mapped);
|
||
setprg8r(REG_D_CHIP, 0xE000, prg_bank_d_mapped);
|
||
break;
|
||
case 6:
|
||
setprg32r(REG_A_CHIP, 0x8000, prg_bank_b_mapped >> 2);
|
||
break;
|
||
case 7:
|
||
setprg32r(REG_A_CHIP, 0x8000, prg_bank_a_mapped >> 2);
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
setprg32r(CFI_CHIP, 0x8000, 0);
|
||
}
|
||
|
||
if (!map_rom_on_6000 && WRAM)
|
||
setprg8r(WRAM_CHIP, 0x6000, sram_page); /* Select SRAM page */
|
||
else if (map_rom_on_6000)
|
||
setprg8(0x6000, prg_bank_6000_mapped); /* Map ROM on $6000-$7FFF */
|
||
}
|
||
|
||
static void COOLGIRL_Sync_CHR(void) {
|
||
/* calculate CHR shift */
|
||
int chr_shift_right = ((mapper == 0x18) && (flags & 0x02)) ? 1 : 0;
|
||
int chr_shift_left = 0;
|
||
|
||
/* enable or disable writes to CHR RAM, setup CHR mask */
|
||
SetupCartCHRMapping(0, UNIFchrrama, ((((~(chr_mask >> 13) & 0x3F) + 1) * 0x2000 - 1) & (CHR_SIZE - 1)) + 1, can_write_chr);
|
||
|
||
switch (chr_mode & 7)
|
||
{
|
||
default:
|
||
case 0:
|
||
setchr8(chr_bank_a >> 3 >> chr_shift_right << chr_shift_left);
|
||
break;
|
||
case 1:
|
||
setchr4(0x0000, mapper_163_latch >> chr_shift_right << chr_shift_left);
|
||
setchr4(0x1000, mapper_163_latch >> chr_shift_right << chr_shift_left);
|
||
break;
|
||
case 2:
|
||
setchr2(0x0000, chr_bank_a >> 1 >> chr_shift_right << chr_shift_left);
|
||
TKSMIR[0] = TKSMIR[1] = chr_bank_a;
|
||
setchr2(0x0800, chr_bank_c >> 1 >> chr_shift_right << chr_shift_left);
|
||
TKSMIR[2] = TKSMIR[3] = chr_bank_c;
|
||
setchr1(0x1000, chr_bank_e >> chr_shift_right << chr_shift_left);
|
||
TKSMIR[4] = chr_bank_e;
|
||
setchr1(0x1400, chr_bank_f >> chr_shift_right << chr_shift_left);
|
||
TKSMIR[5] = chr_bank_f;
|
||
setchr1(0x1800, chr_bank_g >> chr_shift_right << chr_shift_left);
|
||
TKSMIR[6] = chr_bank_g;
|
||
setchr1(0x1C00, chr_bank_h >> chr_shift_right << chr_shift_left);
|
||
TKSMIR[7] = chr_bank_h;
|
||
break;
|
||
case 3:
|
||
setchr1(0x0000, chr_bank_e >> chr_shift_right << chr_shift_left);
|
||
TKSMIR[0] = chr_bank_e;
|
||
setchr1(0x0400, chr_bank_f >> chr_shift_right << chr_shift_left);
|
||
TKSMIR[1] = chr_bank_f;
|
||
setchr1(0x0800, chr_bank_g >> chr_shift_right << chr_shift_left);
|
||
TKSMIR[2] = chr_bank_g;
|
||
setchr1(0x0C00, chr_bank_h >> chr_shift_right << chr_shift_left);
|
||
TKSMIR[3] = chr_bank_h;
|
||
setchr2(0x1000, chr_bank_a >> 1 >> chr_shift_right << chr_shift_left);
|
||
TKSMIR[4] = TKSMIR[5] = chr_bank_a;
|
||
setchr2(0x1800, chr_bank_c >> 1 >> chr_shift_right << chr_shift_left);
|
||
TKSMIR[6] = TKSMIR[7] = chr_bank_c;
|
||
break;
|
||
case 4:
|
||
setchr4(0x0000, chr_bank_a >> 2 >> chr_shift_right << chr_shift_left);
|
||
setchr4(0x1000, chr_bank_e >> 2 >> chr_shift_right << chr_shift_left);
|
||
break;
|
||
case 5:
|
||
if (!ppu_latch0)
|
||
setchr4(0x0000, chr_bank_a >> 2 >> chr_shift_right << chr_shift_left);
|
||
else
|
||
setchr4(0x0000, chr_bank_b >> 2 >> chr_shift_right << chr_shift_left);
|
||
if (!ppu_latch1)
|
||
setchr4(0x1000, chr_bank_e >> 2 >> chr_shift_right << chr_shift_left);
|
||
else
|
||
setchr4(0x1000, chr_bank_f >> 2 >> chr_shift_right << chr_shift_left);
|
||
break;
|
||
case 6:
|
||
setchr2(0x0000, chr_bank_a >> 1 >> chr_shift_right << chr_shift_left);
|
||
setchr2(0x0800, chr_bank_c >> 1 >> chr_shift_right << chr_shift_left);
|
||
setchr2(0x1000, chr_bank_e >> 1 >> chr_shift_right << chr_shift_left);
|
||
setchr2(0x1800, chr_bank_g >> 1 >> chr_shift_right << chr_shift_left);
|
||
break;
|
||
case 7:
|
||
setchr1(0x0000, chr_bank_a >> chr_shift_right << chr_shift_left);
|
||
setchr1(0x0400, chr_bank_b >> chr_shift_right << chr_shift_left);
|
||
setchr1(0x0800, chr_bank_c >> chr_shift_right << chr_shift_left);
|
||
setchr1(0x0C00, chr_bank_d >> chr_shift_right << chr_shift_left);
|
||
setchr1(0x1000, chr_bank_e >> chr_shift_right << chr_shift_left);
|
||
setchr1(0x1400, chr_bank_f >> chr_shift_right << chr_shift_left);
|
||
setchr1(0x1800, chr_bank_g >> chr_shift_right << chr_shift_left);
|
||
setchr1(0x1C00, chr_bank_h >> chr_shift_right << chr_shift_left);
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void COOLGIRL_Sync_Mirroring(void) {
|
||
if (!four_screen)
|
||
{
|
||
if (!((mapper == 0x14) && (flags & 1))) /* Mapper #189? */
|
||
setmirror((mirroring < 2) ? (mirroring ^ 1) : mirroring);
|
||
}
|
||
else {
|
||
/* four screen mode */
|
||
vnapage[0] = UNIFchrrama + 0x3F000;
|
||
vnapage[1] = UNIFchrrama + 0x3F400;
|
||
vnapage[2] = UNIFchrrama + 0x3F800;
|
||
vnapage[3] = UNIFchrrama + 0x3FC00;
|
||
}
|
||
}
|
||
|
||
static void COOLGIRL_Sync(void) {
|
||
COOLGIRL_Sync_PRG();
|
||
COOLGIRL_Sync_CHR();
|
||
COOLGIRL_Sync_Mirroring();
|
||
}
|
||
|
||
static DECLFW(COOLGIRL_Flash_Write) {
|
||
int sector;
|
||
uint32 i, flash_addr;
|
||
if (flash_state < sizeof(flash_buffer_a) / sizeof(flash_buffer_a[0]))
|
||
{
|
||
flash_buffer_a[flash_state] = A & 0xFFF;
|
||
flash_buffer_v[flash_state] = V;
|
||
flash_state++;
|
||
|
||
/* enter CFI mode */
|
||
if ((flash_state == 1) &&
|
||
(flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0x98))
|
||
{
|
||
cfi_mode = 1;
|
||
flash_state = 0;
|
||
}
|
||
|
||
/* sector erase */
|
||
if ((flash_state == 6) &&
|
||
(flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) &&
|
||
(flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) &&
|
||
(flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0x80) &&
|
||
(flash_buffer_a[3] == 0x0AAA) && (flash_buffer_v[3] == 0xAA) &&
|
||
(flash_buffer_a[4] == 0x0555) && (flash_buffer_v[4] == 0x55) &&
|
||
(flash_buffer_v[5] == 0x30))
|
||
{
|
||
sector = prg_bank_a_mapped * 0x2000 / FLASH_SECTOR_SIZE;
|
||
flash_addr = sector * FLASH_SECTOR_SIZE;
|
||
for (i = flash_addr; i < flash_addr + FLASH_SECTOR_SIZE; i++)
|
||
SAVE_FLASH[i % SAVE_FLASH_SIZE] = 0xFF;
|
||
flash_state = 0;
|
||
}
|
||
|
||
/* write byte */
|
||
if ((flash_state == 4) &&
|
||
(flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) &&
|
||
(flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) &&
|
||
(flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0xA0))
|
||
{
|
||
sector = prg_bank_a_mapped * 0x2000 / FLASH_SECTOR_SIZE;
|
||
flash_addr = prg_bank_a_mapped * 0x2000 + (A % 0x8000);
|
||
if (SAVE_FLASH[flash_addr % SAVE_FLASH_SIZE] != 0xFF) {
|
||
FCEU_PrintError("Error: can't write to 0x%08x, flash sector is not erased.\n", flash_addr);
|
||
}
|
||
else {
|
||
SAVE_FLASH[flash_addr % SAVE_FLASH_SIZE] = V;
|
||
}
|
||
flash_state = 0;
|
||
}
|
||
}
|
||
|
||
/* not a command */
|
||
if (((A & 0xFFF) != 0x0AAA) && ((A & 0xFFF) != 0x0555)) {
|
||
flash_state = 0;
|
||
}
|
||
|
||
/* reset */
|
||
if (V == 0xF0) {
|
||
flash_state = 0;
|
||
cfi_mode = 0;
|
||
}
|
||
|
||
COOLGIRL_Sync_PRG();
|
||
}
|
||
|
||
static DECLFW(COOLGIRL_WRITE) {
|
||
uint8 vrc_2b_hi, vrc_2b_low;
|
||
|
||
if (sram_enabled && A >= 0x6000 && A < 0x8000 && !map_rom_on_6000)
|
||
CartBW(A, V); /* SRAM is enabled and writable */
|
||
if (SAVE_FLASH && can_write_flash && A >= 0x8000) /* writing flash */
|
||
COOLGIRL_Flash_Write(A, V);
|
||
|
||
/* block two writes in a row */
|
||
if ((timestampbase + timestamp) < (lreset + 2)) return;
|
||
lreset = timestampbase + timestamp;
|
||
|
||
if (A >= 0x5000 && A < 0x6000 && !lockout)
|
||
{
|
||
switch (A & 7)
|
||
{
|
||
case 0:
|
||
/* {prg_base[26:22]} = cpu_data_in[4:0];
|
||
use bits 29-27 to simulate flash memory */
|
||
SET_BITS(prg_base, "29:22", V, "7:0");
|
||
break;
|
||
case 1:
|
||
/* prg_base[21:14] = cpu_data_in[7:0]; */
|
||
SET_BITS(prg_base, "21:14", V, "7:0");
|
||
break;
|
||
case 2:
|
||
/* {chr_mask[18], prg_mask[20:14]} = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_mask, "18", V, "7");
|
||
SET_BITS(prg_mask, "20:14", V, "6:0");
|
||
break;
|
||
case 3:
|
||
/* {prg_mode[2:0], chr_bank_a[7:3]} = cpu_data_in[7:0]; */
|
||
SET_BITS(prg_mode, "2:0", V, "7:5");
|
||
SET_BITS(chr_bank_a, "7:3", V, "4:0");
|
||
break;
|
||
case 4:
|
||
/* {chr_mode[2:0], chr_mask[17:13]} = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_mode, "2:0", V, "7:5");
|
||
SET_BITS(chr_mask, "17:13", V, "4:0");
|
||
break;
|
||
case 5:
|
||
/* {chr_bank_a[8], prg_bank_a[5:1], sram_page[1:0]} = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_a, "8", V, "7");
|
||
SET_BITS(prg_bank_a, "5:1", V, "6:2");
|
||
SET_BITS(sram_page, "1:0", V, "1:0");
|
||
break;
|
||
case 6:
|
||
/* {flags[2:0], mapper[4:0]} = cpu_data_in[7:0]; */
|
||
SET_BITS(flags, "2:0", V, "7:5");
|
||
SET_BITS(mapper, "4:0", V, "4:0");
|
||
break;
|
||
case 7:
|
||
/* {lockout, mapper[5], four_screen, mirroring[1:0], prg_write_enabled, chr_write_enabled, sram_enabled} = cpu_data_in[7:0]; */
|
||
SET_BITS(lockout, "0", V, "7");
|
||
SET_BITS(mapper, "5", V, "6");
|
||
SET_BITS(four_screen, "0", V, "5");
|
||
SET_BITS(mirroring, "1:0", V, "4:3");
|
||
SET_BITS(can_write_flash, "0", V, "2");
|
||
SET_BITS(can_write_chr, "0", V, "1");
|
||
SET_BITS(sram_enabled, "0", V, "0");
|
||
if (mapper == 0x11) prg_bank_b = ~2; /* if (USE_MAPPER_009_010 && mapper == 6'b010001) prg_bank_b = 8'b11111101; */
|
||
if (mapper == 0x17) map_rom_on_6000 = 1; /* if (ENABLE_MAPPER_042 && (mapper == 6'b010111)) map_rom_on_6000 <= 1; */
|
||
if (mapper == 0x0E) prg_bank_b = 1; /* if (USE_MAPPER_065 && mapper == 6'b001110) prg_bank_b = 1; */
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (A < 0x8000) /* $0000-$7FFF */
|
||
{
|
||
/* Mapper #163 */
|
||
if (mapper == 0x06)
|
||
{
|
||
if (A == 0x5101) /* if (cpu_addr_in[14:0] == 15'h5101) */
|
||
{
|
||
if (mapper163_r4 && !V) /* if ((mapper163_r4 != 0) && (cpu_data_in == 0)) */
|
||
mapper163_r5 ^= 1; /* mapper163_r5[0] = ~mapper163_r5[0]; */
|
||
mapper163_r4 = V;
|
||
}
|
||
else if (A == 0x5100 && V == 6) /* if ((cpu_addr_in[14:0] == 15'h5100) && (cpu_data_in == 6)) */
|
||
{
|
||
SET_BITS(prg_mode, "0", 0, "0"); /* prg_mode[0] = 0; */
|
||
prg_bank_b = 0x0C; /* prb_bank_b = 4'b1100; */
|
||
}
|
||
else {
|
||
if (get_bits(A, "14:12") == 0x05) /* if (cpu_addr_in[14:12] == 3'b101) begin */
|
||
{
|
||
switch (get_bits(A, "9:8")) /* case (cpu_addr_in[9:8]) */
|
||
{
|
||
case 2:
|
||
SET_BITS(prg_mode, "0", 1, "0"); /* prg_mode[0] = 1; */
|
||
SET_BITS(prg_bank_a, "7:6", V, "1:0"); /* prg_bank_a[7:6] = cpu_data_in[1:0]; */
|
||
mapper163_r0 = V;
|
||
break;
|
||
case 0:
|
||
SET_BITS(prg_mode, "0", 1, "0"); /* prg_mode[0] = 1; */
|
||
SET_BITS(prg_bank_a, "5:2", V, "3:0"); /* prg_bank_a[5:2] = cpu_data_in[3:0]; */
|
||
SET_BITS(chr_mode, "0", V, "7"); /* chr_mode[0] = cpu_data_in[7]; */
|
||
mapper163_r1 = V;
|
||
break;
|
||
case 3:
|
||
mapper163_r2 = V; /* mapper163_r2 = cpu_data_in; */
|
||
break;
|
||
case 1:
|
||
mapper163_r3 = V; /* mapper163_r3 = cpu_data_in; */
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Mapper #87 */
|
||
if (mapper == 0x0C)
|
||
{
|
||
if (get_bits(A, "14:13") == 0x03) /* if (cpu_addr_in[14:13] == 2'b11) // $6000-$7FFF */
|
||
{
|
||
/* chr_bank_a[4:3] = {cpu_data_in[0], cpu_data_in[1]}; */
|
||
SET_BITS(chr_bank_a, "4:3", V, "0,1");
|
||
}
|
||
}
|
||
|
||
/* Mapper #90 - JY */
|
||
if (mapper == 0x0D)
|
||
{
|
||
switch (A)
|
||
{
|
||
case 0x5800: mul1 = V; break;
|
||
case 0x5801: mul2 = V; break;
|
||
}
|
||
}
|
||
|
||
/* MMC5 (not really) */
|
||
if (mapper == 0x0F)
|
||
{
|
||
/* case (cpu_addr_in[14:0]) */
|
||
switch (get_bits(A, "14:0"))
|
||
{
|
||
case 0x5105:
|
||
if (V == 0xFF)
|
||
{
|
||
four_screen = 1;
|
||
}
|
||
else {
|
||
four_screen = 0;
|
||
/* case ({cpu_data_in[4], cpu_data_in[2]}) */
|
||
switch (get_bits(V, "4,2"))
|
||
{
|
||
case 0x00: /* 2'b00: mirroring = 2'b10; */
|
||
mirroring = 0x02; break;
|
||
case 0x01: /* 2'b01: mirroring = 2'b00; */
|
||
mirroring = 0x00; break;
|
||
case 0x02: /* 2'b10: mirroring = 2'b01; */
|
||
mirroring = 0x01; break;
|
||
case 0x03: /* 2'b11: mirroring = 2'b11; */
|
||
mirroring = 0x03; break;
|
||
}
|
||
}
|
||
break;
|
||
case 0x5115:
|
||
/* prg_bank_a[4:0] = { cpu_data_in[4:1], 1'b0}; */
|
||
SET_BITS(prg_bank_a, "4:1", V, "4:1");
|
||
SET_BITS(prg_bank_a, "0", 0, "0");
|
||
/* prg_bank_b[4:0] = { cpu_data_in[4:1], 1'b1}; */
|
||
SET_BITS(prg_bank_b, "4:1", V, "4:1");
|
||
SET_BITS(prg_bank_b, "0", 1, "0");
|
||
break;
|
||
case 0x5116:
|
||
/* prg_bank_c[4:0] = cpu_data_in[4:0]; */
|
||
SET_BITS(prg_bank_c, "4:0", V, "4:0");
|
||
break;
|
||
case 0x5117:
|
||
/* prg_bank_d[4:0] = cpu_data_in[4:0]; */
|
||
SET_BITS(prg_bank_d, "4:0", V, "4:0");
|
||
break;
|
||
case 0x5120:
|
||
/* chr_bank_a[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_a, "7:0", V, "7:0");
|
||
break;
|
||
case 0x5121:
|
||
/* chr_bank_b[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_b, "7:0", V, "7:0");
|
||
break;
|
||
case 0x5122:
|
||
/* chr_bank_c[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_c, "7:0", V, "7:0");
|
||
break;
|
||
case 0x5123:
|
||
/* chr_bank_d[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_d, "7:0", V, "7:0");
|
||
break;
|
||
case 0x5128:
|
||
/* chr_bank_e[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_e, "7:0", V, "7:0");
|
||
break;
|
||
case 0x5129:
|
||
/* chr_bank_f[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_f, "7:0", V, "7:0");
|
||
break;
|
||
case 0x512A:
|
||
/* chr_bank_g[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_g, "7:0", V, "7:0");
|
||
break;
|
||
case 0x512B:
|
||
/* chr_bank_h[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_h, "7:0", V, "7:0");
|
||
break;
|
||
case 0x5203:
|
||
/* mmc5_irq_ack = 1; */
|
||
X6502_IRQEnd(FCEU_IQEXT);
|
||
mmc5_irq_out = 0;
|
||
/* mmc5_irq_line[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(mmc5_irq_line, "7:0", V, "7:0");
|
||
break;
|
||
case 0x5204:
|
||
/* mmc5_irq_ack = 1; */
|
||
X6502_IRQEnd(FCEU_IQEXT);
|
||
mmc5_irq_out = 0;
|
||
/* mmc5_irq_enabled = cpu_data_in[7]; */
|
||
mmc5_irq_enabled = get_bits(V, "7");
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* Mapper #189 */
|
||
if ((mapper == 0x14) && (flags & 2))
|
||
{
|
||
if (A >= 0x4120) /* if (cpu_addr_in[14:0] >= 15'h4120) // $4120-$7FFF */
|
||
{
|
||
/* prg_bank_a[5:2] = cpu_data_in[3:0] | cpu_data_in[7:4]; */
|
||
prg_bank_a = set_bits(prg_bank_a, "5:2",
|
||
get_bits(V, "7:4") | get_bits(V, "3:0"));
|
||
}
|
||
}
|
||
|
||
/* Mappers #79 and #146 - NINA-03/06 and Sachen 3015: (flag0 = 1) */
|
||
if (mapper == 0x1B)
|
||
{
|
||
/* if ({cpu_addr_in[14:13], cpu_addr_in[8]} == 3'b101) */
|
||
if (get_bits(A, "14:13,8") == 0x05)
|
||
{
|
||
/*chr_bank_a[5:3] = cpu_data_in[2:0]; */
|
||
SET_BITS(chr_bank_a, "5:3", V, "2:0");
|
||
/*prg_bank_a[2] = cpu_data_in[3]; */
|
||
SET_BITS(prg_bank_a, "2", V, "3");
|
||
}
|
||
}
|
||
|
||
/* Mapper #133 */
|
||
if (mapper == 0x1C)
|
||
{
|
||
/* if ({cpu_addr_in[14:13], cpu_addr_in[8]} == 3'b101) */
|
||
if (get_bits(A, "14:13,8") == 0x05)
|
||
{
|
||
/*chr_bank_a[4:3] = cpu_data_in[1:0]; */
|
||
SET_BITS(chr_bank_a, "4:3", V, "1:0");
|
||
/*prg_bank_a[2] = cpu_data_in[2]; */
|
||
SET_BITS(prg_bank_a, "2", V, "2");
|
||
}
|
||
}
|
||
|
||
/* Mapper #184 */
|
||
if (mapper == 0x1F)
|
||
{
|
||
if (get_bits(A, "14:13") == 0x03) /* if (cpu_addr_in[14:13] == 2'b11) */
|
||
{
|
||
/* chr_bank_a[4:2] = cpu_data_in[2:0]; */
|
||
SET_BITS(chr_bank_a, "4:2", V, "2:0");
|
||
/* chr_bank_e[4:2] = {1'b1, cpu_data_in[5:4]}; */
|
||
SET_BITS(chr_bank_e, "3:2", V, "5:4");
|
||
SET_BITS(chr_bank_e, "4", 1, "0");
|
||
}
|
||
}
|
||
|
||
/* Mapper #38 */
|
||
if (mapper == 0x20)
|
||
{
|
||
/* if (cpu_addr_in[14:12] == 3'b111) */
|
||
if (get_bits(A, "14:12") == 0x07)
|
||
{
|
||
/* prg_bank_a[3:2] = cpu_data_in[1:0]; */
|
||
SET_BITS(prg_bank_a, "3:2", V, "1:0");
|
||
/* chr_bank_a[4:3] = cpu_data_in[3:2]; */
|
||
SET_BITS(chr_bank_a, "4:3", V, "3:2");
|
||
}
|
||
}
|
||
}
|
||
else /* $8000-$FFFF */
|
||
{
|
||
/* Mapper #2 - UxROM
|
||
* flag0 - mapper #71 - for Fire Hawk only.
|
||
* other mapper-#71 games are UxROM
|
||
* flag1 - UNROM-512 partial support */
|
||
if (mapper == 0x01)
|
||
{
|
||
/* if (!ENABLE_MAPPER_071 | ~flags[0] | (cpu_addr_in[14:12] != 3'b001)) */
|
||
if (!(flags & 1) || (get_bits(A, "14:12") != 0x01))
|
||
{
|
||
/* prg_bank_a[UxROM_BITSIZE+1:1] = cpu_data_in[UxROM_BITSIZE:0];
|
||
* UxROM_BITSIZE = 4 */
|
||
SET_BITS(prg_bank_a, "5:1", V, "4:0");
|
||
/* if (ENABLE_MAPPER_030 && flags[1]) */
|
||
if (flags & 2)
|
||
{
|
||
/* One screen mirroring select, CHR RAM bank, PRG ROM bank
|
||
* mirroring[1:0] = { 1'b1, cpu_data_in[7]}; */
|
||
SET_BITS(mirroring, "1", 1, "0");
|
||
SET_BITS(mirroring, "0", V, "7");
|
||
/* chr_bank_a[1:0] = cpu_data_in[6:5]; */
|
||
SET_BITS(chr_bank_a, "1:0", V, "6:5");
|
||
}
|
||
}
|
||
else {
|
||
/* CodeMasters, blah. Mirroring control used only by Fire Hawk
|
||
* mirroring[1:0] = {1'b1, cpu_data_in[4]}; */
|
||
SET_BITS(mirroring, "1", 1, "0");
|
||
SET_BITS(mirroring, "0", V, "4");
|
||
}
|
||
}
|
||
|
||
/* Mapper #3 - CNROM */
|
||
if (mapper == 0x02)
|
||
{
|
||
/* chr_bank_a[7:3] = cpu_data_in[4:0]; */
|
||
SET_BITS(chr_bank_a, "7:3", V, "4:0");
|
||
}
|
||
|
||
/* Mapper #78 - Holy Diver */
|
||
if (mapper == 0x03)
|
||
{
|
||
/* prg_bank_a[3:1] = cpu_data_in[2:0]; */
|
||
SET_BITS(prg_bank_a, "3:1", V, "2:0");
|
||
/* chr_bank_a[6:3] = cpu_data_in[7:4]; */
|
||
SET_BITS(chr_bank_a, "6:3", V, "7:4");
|
||
/* mirroring = { 1'b0, ~cpu_data_in[3]}; */
|
||
mirroring = get_bits(V, "3") ^ 1;
|
||
}
|
||
|
||
/* Mapper #97 - Irem's TAM-S1 */
|
||
if (mapper == 0x04)
|
||
{
|
||
/* prg_bank_a[5:1] = cpu_data_in[4:0]; */
|
||
SET_BITS(prg_bank_a, "5:1", V, "4:0");
|
||
/* mirroring = { 1'b0, ~cpu_data_in[7]}; */
|
||
mirroring = get_bits(V, "7") ^ 1;
|
||
}
|
||
|
||
/* Mapper #93 - Sunsoft-2 */
|
||
if (mapper == 0x05)
|
||
{
|
||
/* prg_bank_a[3:1] = { cpu_data_in[6:4] }; */
|
||
SET_BITS(prg_bank_a, "3:1", V, "6:4");
|
||
/* chr_write_enabled = cpu_data_in[0]; */
|
||
can_write_chr = V & 1;
|
||
}
|
||
|
||
/* Mapper #18 */
|
||
if (mapper == 0x07)
|
||
{
|
||
/* case ({cpu_addr_in[14:12], cpu_addr_in[1:0]}) */
|
||
switch (get_bits(A, "14:12,1:0"))
|
||
{
|
||
case 0x00: /* 5'b00000: prg_bank_a[3:0] = cpu_data_in[3:0]; // $8000 */
|
||
SET_BITS(prg_bank_a, "3:0", V, "3:0"); break;
|
||
case 0x01: /* 5'b00001: prg_bank_a[7:4] = cpu_data_in[3:0]; // $8001 */
|
||
SET_BITS(prg_bank_a, "7:4", V, "3:0"); break;
|
||
case 0x02: /* 5'b00010: prg_bank_b[3:0] = cpu_data_in[3:0]; // $8002 */
|
||
SET_BITS(prg_bank_b, "3:0", V, "3:0"); break;
|
||
case 0x03: /* 5'b00011: prg_bank_b[7:4] = cpu_data_in[3:0]; // $8003 */
|
||
SET_BITS(prg_bank_b, "7:4", V, "3:0"); break;
|
||
case 0x04: /* 5'b00100: prg_bank_c[3:0] = cpu_data_in[3:0]; // $9000 */
|
||
SET_BITS(prg_bank_c, "3:0", V, "3:0"); break;
|
||
case 0x05: /* 5'b00101: prg_bank_c[7:4] = cpu_data_in[3:0]; // $9001 */
|
||
SET_BITS(prg_bank_c, "7:4", V, "3:0"); break;
|
||
case 0x06:
|
||
break;
|
||
case 0x07:
|
||
break;
|
||
case 0x08: /* 5'b01000: chr_bank_a[3:0] = cpu_data_in[3:0]; // $A000 */
|
||
SET_BITS(chr_bank_a, "3:0", V, "3:0"); break;
|
||
case 0x09: /* 5'b01001: chr_bank_a[7:4] = cpu_data_in[3:0]; // $A001 */
|
||
SET_BITS(chr_bank_a, "7:4", V, "3:0"); break;
|
||
case 0x0A: /* 5'b01010: chr_bank_b[3:0] = cpu_data_in[3:0]; // $A002 */
|
||
SET_BITS(chr_bank_b, "3:0", V, "3:0"); break;
|
||
case 0x0B: /* 5'b01011: chr_bank_b[7:4] = cpu_data_in[3:0]; // $A003 */
|
||
SET_BITS(chr_bank_b, "7:4", V, "3:0"); break;
|
||
case 0x0C: /* 5'b01100: chr_bank_c[3:0] = cpu_data_in[3:0]; // $B000 */
|
||
SET_BITS(chr_bank_c, "3:0", V, "3:0"); break;
|
||
case 0x0D: /* 5'b01101: chr_bank_c[7:4] = cpu_data_in[3:0]; // $B001 */
|
||
SET_BITS(chr_bank_c, "7:4", V, "3:0"); break;
|
||
case 0x0E: /* 5'b01110: chr_bank_d[3:0] = cpu_data_in[3:0]; // $B002 */
|
||
SET_BITS(chr_bank_d, "3:0", V, "3:0"); break;
|
||
case 0x0F: /* 5'b01111: chr_bank_d[7:4] = cpu_data_in[3:0]; // $B003 */
|
||
SET_BITS(chr_bank_d, "7:4", V, "3:0"); break;
|
||
case 0x10: /* 5'b10000: chr_bank_e[3:0] = cpu_data_in[3:0]; // $C000 */
|
||
SET_BITS(chr_bank_e, "3:0", V, "3:0"); break;
|
||
case 0x11: /* 5'b10001: chr_bank_e[7:4] = cpu_data_in[3:0]; // $C001 */
|
||
SET_BITS(chr_bank_e, "7:4", V, "3:0"); break;
|
||
case 0x12: /* 5'b10010: chr_bank_f[3:0] = cpu_data_in[3:0]; // $C002 */
|
||
SET_BITS(chr_bank_f, "3:0", V, "3:0"); break;
|
||
case 0x13: /* 5'b10011: chr_bank_f[7:4] = cpu_data_in[3:0]; // $C003 */
|
||
SET_BITS(chr_bank_f, "7:4", V, "3:0"); break;
|
||
case 0x14: /* 5'b10100: chr_bank_g[3:0] = cpu_data_in[3:0]; // $D000 */
|
||
SET_BITS(chr_bank_g, "3:0", V, "3:0"); break;
|
||
case 0x15: /* 5'b10101: chr_bank_g[7:4] = cpu_data_in[3:0]; // $D001 */
|
||
SET_BITS(chr_bank_g, "7:4", V, "3:0"); break;
|
||
case 0x16: /* 5'b10110: chr_bank_h[3:0] = cpu_data_in[3:0]; // $D002 */
|
||
SET_BITS(chr_bank_h, "3:0", V, "3:0"); break;
|
||
case 0x17: /* 5'b10111: chr_bank_h[7:4] = cpu_data_in[3:0]; // $D003 */
|
||
SET_BITS(chr_bank_h, "7:4", V, "3:0"); break;
|
||
case 0x18: /* 5'b11000: mapper18_irq_latch[3:0] = cpu_data_in[3:0]; // $E000 */
|
||
SET_BITS(mapper18_irq_latch, "3:0", V, "3:0"); break;
|
||
case 0x19: /* 5'b11001: mapper18_irq_latch[7:4] = cpu_data_in[3:0]; // $E001 */
|
||
SET_BITS(mapper18_irq_latch, "7:4", V, "3:0"); break;
|
||
case 0x1A: /* 5'b11010: mapper18_irq_latch[11:8] = cpu_data_in[3:0]; // $E002 */
|
||
SET_BITS(mapper18_irq_latch, "11:8", V, "3:0"); break;
|
||
case 0x1B: /* 5'b11011: mapper18_irq_latch[15:12] = cpu_data_in[3:0]; // $E003 */
|
||
SET_BITS(mapper18_irq_latch, "15:12", V, "3:0"); break;
|
||
case 0x1C: /* 5'b11100: begin // $F000 */
|
||
/* mapper18_irq_out = 0; // ack */
|
||
X6502_IRQEnd(FCEU_IQEXT);
|
||
/* mapper18_irq_value[15:0] = mapper18_irq_latch[15:0]; */
|
||
mapper18_irq_value = mapper18_irq_latch; break; /* irq_cpu_out = 0; */
|
||
case 0x1D: /* 5'b11101: begin // $F001 */
|
||
X6502_IRQEnd(FCEU_IQEXT); /* irq_cpu_control[3:0] = cpu_data_in[3:0]; */
|
||
SET_BITS(mapper18_irq_control, "3:0", V, "3:0"); break;
|
||
case 0x1E: /* 5'b11110 */
|
||
switch (get_bits(V, "1:0")) /* case (cpu_data_in[1:0]) */
|
||
{
|
||
case 0x00: mirroring = 0x01; break; /*2'b00: mirroring = 2'b01; // Horz */
|
||
case 0x01: mirroring = 0x00; break; /*2'b01: mirroring = 2'b00; // Vert */
|
||
case 0x02: mirroring = 0x02; break; /*2'b10: mirroring = 2'b10; // 1SsA */
|
||
case 0x03: mirroring = 0x03; break; /*2'b11: mirroring = 2'b11; // 1SsB */
|
||
}
|
||
case 0x1F:
|
||
break; /* sound */
|
||
}
|
||
}
|
||
|
||
/* Mapper #7 - AxROM, mapper #241 - BNROM */
|
||
if (mapper == 0x08)
|
||
{
|
||
/* AxROM_BxROM_BITSIZE = 3
|
||
*prg_bank_a[AxROM_BxROM_BITSIZE + 2:2] = cpu_data_in[AxROM_BxROM_BITSIZE:0]; */
|
||
SET_BITS(prg_bank_a, "5:2", V, "3:0");
|
||
/*if (!ENABLE_MAPPER_034_241_BxROM || !flags[0]) // BxROM?
|
||
* mirroring = { 1'b1, cpu_data_in[4]}; */
|
||
if (!(flags & 1))
|
||
mirroring = (1 << 1) | get_bits(V, "4");
|
||
}
|
||
|
||
/* Mapper #228 - Cheetahmen II */
|
||
if (mapper == 0x09)
|
||
{
|
||
/* prg_bank_a[5:2] = cpu_addr_in[10:7]; */
|
||
SET_BITS(prg_bank_a, "5:2", A, "10:7");
|
||
/* chr_bank_a[7:3] = { cpu_addr_in[2:0], cpu_data_in[1:0] }; // only 256k, sorry */
|
||
SET_BITS(chr_bank_a, "7:5", A, "2:0");
|
||
SET_BITS(chr_bank_a, "4:3", V, "1:0");
|
||
/* mirroring = { 1'b0, cpu_addr_in[13]}; */
|
||
mirroring = get_bits(A, "13");
|
||
}
|
||
|
||
/* Mapper #11 - ColorDreams */
|
||
if (mapper == 0x0A)
|
||
{
|
||
/* prg_bank_a[3:2] = cpu_data_in[1:0]; */
|
||
SET_BITS(prg_bank_a, "3:2", V, "1:0");
|
||
/* chr_bank_a[6:3] = cpu_data_in[7:4]; */
|
||
SET_BITS(chr_bank_a, "6:3", V, "7:4");
|
||
}
|
||
|
||
/* Mapper #66 - GxROM */
|
||
if (mapper == 0x0B)
|
||
{
|
||
/* prg_bank_a[3:2] = cpu_data_in[5:4]; */
|
||
SET_BITS(prg_bank_a, "3:2", V, "5:4");
|
||
/* chr_bank_a[4:3] = cpu_data_in[1:0]; */
|
||
SET_BITS(chr_bank_a, "4:3", V, "1:0");
|
||
}
|
||
|
||
/* Mapper #90 - JY */
|
||
if (mapper == 0x0D)
|
||
{
|
||
/* if (cpu_addr_in[14:12] == 3'b000) // $800x */
|
||
if (get_bits(A, "14:12") == 0x00)
|
||
{
|
||
/* case (cpu_addr_in[1:0]) */
|
||
switch (get_bits(A, "1:0"))
|
||
{
|
||
/* 2'b00: prg_bank_a[5:0] = cpu_data_in[5:0]; */
|
||
case 0x00: SET_BITS(prg_bank_a, "5:0", V, "5:0"); break;
|
||
/* 2'b01: prg_bank_b[5:0] = cpu_data_in[5:0]; */
|
||
case 0x01: SET_BITS(prg_bank_b, "5:0", V, "5:0"); break;
|
||
/* 2'b10: prg_bank_c[5:0] = cpu_data_in[5:0]; */
|
||
case 0x02: SET_BITS(prg_bank_c, "5:0", V, "5:0"); break;
|
||
/* 2'b11: prg_bank_d[5:0] = cpu_data_in[5:0]; */
|
||
case 0x03: SET_BITS(prg_bank_d, "5:0", V, "5:0"); break;
|
||
}
|
||
}
|
||
|
||
/* if (cpu_addr_in[14:12] == 3'b001) // $900x */
|
||
if (get_bits(A, "14:12") == 0x01)
|
||
{
|
||
/* case (cpu_addr_in[2:0]) */
|
||
switch (get_bits(A, "2:0"))
|
||
{
|
||
case 0x00: /* 3'b000: chr_bank_a[7:0] = cpu_data_in[7:0]; // $9000 */
|
||
SET_BITS(chr_bank_a, "7:0", V, "7:0"); break;
|
||
case 0x01: /* 3'b001: chr_bank_b[7:0] = cpu_data_in[7:0]; // $9001 */
|
||
SET_BITS(chr_bank_b, "7:0", V, "7:0"); break;
|
||
case 0x02: /* 3'b010: chr_bank_c[7:0] = cpu_data_in[7:0]; // $9002 */
|
||
SET_BITS(chr_bank_c, "7:0", V, "7:0"); break;
|
||
case 0x03: /* 3'b011: chr_bank_d[7:0] = cpu_data_in[7:0]; // $9003 */
|
||
SET_BITS(chr_bank_d, "7:0", V, "7:0"); break;
|
||
case 0x04: /* 3'b100: chr_bank_e[7:0] = cpu_data_in[7:0]; // $9004 */
|
||
SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
|
||
case 0x05: /* 3'b101: chr_bank_f[7:0] = cpu_data_in[7:0]; // $9005 */
|
||
SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
|
||
case 0x06: /* 3'b110: chr_bank_g[7:0] = cpu_data_in[7:0]; // $9006 */
|
||
SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
|
||
case 0x07: /* 3'b111: chr_bank_h[7:0] = cpu_data_in[7:0]; // $9007 */
|
||
SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
|
||
}
|
||
}
|
||
|
||
/* if ({cpu_addr_in[14:12], cpu_addr_in[1:0]} == 5'b10101) // $D001 */
|
||
if (get_bits(A, "14:12,1:0") == 0x15)
|
||
{
|
||
/* mirroring = cpu_data_in[1:0]; */
|
||
SET_BITS(mirroring, "1:0", V, "1:0");
|
||
}
|
||
|
||
/* use MMC3's IRQs
|
||
* if (cpu_addr_in[14:12] == 3'b100) // $C00x */
|
||
if (get_bits(A, "14:12") == 0x04)
|
||
{
|
||
/* case (cpu_addr_in[2:0]) */
|
||
switch (get_bits(A, "2:0"))
|
||
{
|
||
case 0x00:
|
||
/* 3'b000: mmc3_irq_enabled = cpu_data_in[0]; */
|
||
if (V & 1)
|
||
{
|
||
mmc3_irq_enabled = 1;
|
||
}
|
||
else {
|
||
X6502_IRQEnd(FCEU_IQEXT);
|
||
mmc3_irq_enabled = 0;
|
||
}
|
||
break;
|
||
case 0x01:
|
||
break; /* who cares about this shit? */
|
||
case 0x02:
|
||
/* 3'b010: mmc3_irq_enabled = 0; */
|
||
mmc3_irq_enabled = 0;
|
||
X6502_IRQEnd(FCEU_IQEXT);
|
||
break;
|
||
case 0x03:
|
||
/* 3'b011: mmc3_irq_enabled = 1; */
|
||
mmc3_irq_enabled = 1;
|
||
break;
|
||
case 0x04:
|
||
break; /* prescaler? who cares? */
|
||
case 0x05:
|
||
/* mmc3_irq_latch = cpu_data_in ^ mapper90_xor; */
|
||
mmc3_irq_latch = V ^ mapper90_xor;
|
||
mmc3_irq_reload = 1;
|
||
break;
|
||
case 0x06:
|
||
/* mapper90_xor = cpu_data_in; */
|
||
mapper90_xor = V;
|
||
break;
|
||
case 0x07:
|
||
break; /* meh */
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Mapper #65 - Irem's H3001 */
|
||
if (mapper == 0x0E)
|
||
{
|
||
/* case ({cpu_addr_in[14:12], cpu_addr_in[2:0]}) */
|
||
switch (get_bits(A, "14:12,2:0"))
|
||
{
|
||
case 0x00:
|
||
/* 6'b000000: prg_bank_a[5:0] = cpu_data_in[5:0]; // $8000 */
|
||
SET_BITS(prg_bank_a, "5:0", V, "5:0");
|
||
break;
|
||
case 0x09:
|
||
/* 6'b001001: mirroring = {1'b0, cpu_data_in[7]}; // $9001, mirroring */
|
||
mirroring = get_bits(V, "7");
|
||
break;
|
||
case 0x0B:
|
||
/* mapper65_irq_out = 0; // ack */
|
||
X6502_IRQEnd(FCEU_IQEXT); /* irq_cpu_out = 0; */
|
||
/* mapper65_irq_enabled = cpu_data_in[7]; // $9003, enable IRQ */
|
||
mapper65_irq_enabled = get_bits(V, "7");
|
||
break;
|
||
case 0x0C:
|
||
X6502_IRQEnd(FCEU_IQEXT); /* mapper65_irq_out = 0; // ack */
|
||
mapper65_irq_value = mapper65_irq_latch; /* $9004, IRQ reload */
|
||
break;
|
||
case 0x0D: /* mapper65_irq_latch[15:8] = cpu_data_in; // $9005, IRQ high value */
|
||
SET_BITS(mapper65_irq_latch, "15:8", V, "7:0"); break;
|
||
case 0x0E: /* mapper65_irq_latch[7:0] = cpu_data_in; // $9006, IRQ low value */
|
||
SET_BITS(mapper65_irq_latch, "7:0", V, "7:0"); break;
|
||
case 0x10: /* prg_bank_b[5:0] = cpu_data_in[5:0]; // $A000 */
|
||
prg_bank_b = (prg_bank_b & 0xC0) | (V & 0x3F); break;
|
||
case 0x18: /* chr_bank_a[7:0] = cpu_data_in; // $B000 */
|
||
SET_BITS(chr_bank_a, "7:0", V, "7:0"); break;
|
||
case 0x19: /* chr_bank_b[7:0] = cpu_data_in[7:0]; // $B001 */
|
||
SET_BITS(chr_bank_b, "7:0", V, "7:0"); break;
|
||
case 0x1A: /* chr_bank_c[7:0] = cpu_data_in[7:0]; // $B002 */
|
||
SET_BITS(chr_bank_c, "7:0", V, "7:0"); break;
|
||
case 0x1B: /* chr_bank_d[7:0] = cpu_data_in[7:0]; // $B003 */
|
||
SET_BITS(chr_bank_d, "7:0", V, "7:0"); break;
|
||
case 0x1C: /* chr_bank_e[7:0] = cpu_data_in[7:0]; // $B004 */
|
||
SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
|
||
case 0x1D: /* chr_bank_f[7:0] = cpu_data_in[7:0]; // $B005 */
|
||
SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
|
||
case 0x1E: /* chr_bank_g[7:0] = cpu_data_in[7:0]; // $B006 */
|
||
SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
|
||
case 0x1F: /* chr_bank_h[7:0] = cpu_data_in[7:0]; // $B007 */
|
||
SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
|
||
case 0x20: /* 6'b100000: prg_bank_c[5:0] = cpu_data_in[5:0]; // $C000 */
|
||
SET_BITS(prg_bank_c, "5:0", V, "5:0"); break;
|
||
}
|
||
}
|
||
|
||
/* Mapper #1 - MMC1 */
|
||
/*
|
||
flag0 - 16KB of SRAM (SOROM)
|
||
*/
|
||
if (mapper == 0x10)
|
||
{
|
||
if (V & 0x80) /* reset */
|
||
{
|
||
mmc1_load_register = set_bits(mmc1_load_register, "5:0", 0x20); /* mmc1_load_register[5:0] = 6'b100000; */
|
||
prg_mode = 0; /* 0x4000 (A) + fixed last (C) */
|
||
prg_bank_c = set_bits(prg_bank_c, "4:0", 0x1E); /* prg_bank_c[4:0] = 5'b11110; */
|
||
}
|
||
else {
|
||
/* mmc1_load_register[5:0] = { cpu_data_in[0], mmc1_load_register[5:1] }; */
|
||
SET_BITS(mmc1_load_register, "4:0", mmc1_load_register, "5:1");
|
||
SET_BITS(mmc1_load_register, "5", V, "0");
|
||
/* if (mmc1_load_register[0] == 1) */
|
||
if (mmc1_load_register & 1)
|
||
{
|
||
switch ((A >> 13) & 3)
|
||
{
|
||
case 0x00: /* 2'b00: begin // $8000-$9FFF */
|
||
if (get_bits(mmc1_load_register, "4:3") == 0x03) /* if (mmc1_load_register[4:3] == 2'b11) */
|
||
{
|
||
prg_mode = 0; /* prg_mode = 3'b000; // 0x4000 (A) + fixed last (C) */
|
||
prg_bank_c = set_bits(prg_bank_c, "4:1", 0x0F); /* prg_bank_c[4:1] = 4'b1111; */
|
||
}
|
||
/*else if (mmc1_load_register[4:3] == 2'b10) */
|
||
else if (get_bits(mmc1_load_register, "4:3") == 0x02)
|
||
{
|
||
prg_mode = 0x01; /* prg_mode = 3'b001; // fixed first (C) + 0x4000 (A) */
|
||
prg_bank_c = set_bits(prg_bank_c, "4:1", 0x00); /* prg_bank_c[4:0] = 4'b0000; */
|
||
}
|
||
else
|
||
prg_mode = 0x07; /* prg_mode = 3'b111; // 0x8000 (A) */
|
||
if (get_bits(mmc1_load_register, "5"))
|
||
chr_mode = 0x04;
|
||
else
|
||
chr_mode = 0x00;
|
||
mirroring = set_bits(mirroring, "1:0", get_bits(mmc1_load_register, "2:1") ^ 0x02);
|
||
break;
|
||
case 0x01: /* 2'b01 */
|
||
SET_BITS(chr_bank_a, "6:2", mmc1_load_register, "5:1"); /* chr_bank_a[6:2] = mmc1_load_register[5:1]; */
|
||
if (flags & 1) /* (flags[0]) - 16KB of SRAM */
|
||
{
|
||
/* PRG RAM page #2 is battery backed */
|
||
sram_page = 2 | get_bits(mmc1_load_register, "4") ^ 1; /* sram_page <= {1'b1, ~mmc1_load_register[4]}; */
|
||
}
|
||
SET_BITS(prg_bank_a, "5", mmc1_load_register, "5"); /* prg_bank_a[5] = mmc1_load_register[5]; // for SUROM, 512k PRG support */
|
||
SET_BITS(prg_bank_c, "5", mmc1_load_register, "5"); /* prg_bank_c[5] = mmc1_load_register[5]; // for SUROM, 512k PRG support */
|
||
break;
|
||
case 0x02: /* 2'b10: chr_bank_e[6:2] = mmc1_load_register[5:1]; // $C000-$DFFF */
|
||
SET_BITS(chr_bank_e, "6:2", mmc1_load_register, "5:1");
|
||
break;
|
||
case 0x03: /* 2'b11 */
|
||
/* prg_bank_a[4:1] = mmc1_load_register[4:1]; */
|
||
SET_BITS(prg_bank_a, "4:1", mmc1_load_register, "4:1");
|
||
/* sram_enabled = ~mmc1_load_register[5]; */
|
||
sram_enabled = get_bits(mmc1_load_register, "5") ^ 1;
|
||
break;
|
||
}
|
||
mmc1_load_register = 0x20; /* mmc1_load_register[5:0] = 6'b100000; */
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Mapper #9 and #10 - MMC2 and MMC4
|
||
* flag0 - 0=MMC2, 1=MMC4 */
|
||
if (mapper == 0x11)
|
||
{
|
||
switch ((A >> 12) & 7)
|
||
{
|
||
case 2: /* $A000-$AFFF */
|
||
if (!(flags & 1)) {
|
||
/* MMC2 */
|
||
SET_BITS(prg_bank_a, "3:0", V, "3:0");
|
||
}
|
||
else {
|
||
/* MMC4 */
|
||
SET_BITS(prg_bank_a, "4:1", V, "3:0"); /* prg_bank_a[4:0] = { cpu_data_in[3:0], 1'b0}; */
|
||
prg_bank_a &= ~1;
|
||
}
|
||
break;
|
||
case 3: /* $B000-$BFFF */
|
||
SET_BITS(chr_bank_a, "6:2", V, "4:0"); /* chr_bank_a[6:2] = cpu_data_in[4:0]; */
|
||
break;
|
||
case 4: /* $C000-$CFFF */
|
||
SET_BITS(chr_bank_b, "6:2", V, "4:0"); /* chr_bank_b[6:2] = cpu_data_in[4:0]; */
|
||
break;
|
||
case 5: /* $D000-$DFFF */
|
||
SET_BITS(chr_bank_e, "6:2", V, "4:0"); /* chr_bank_e[6:2] = cpu_data_in[4:0]; */
|
||
break;
|
||
case 6: /* $E000-$EFFF */
|
||
SET_BITS(chr_bank_f, "6:2", V, "4:0"); /* chr_bank_f[6:2] = cpu_data_in[4:0]; */
|
||
break;
|
||
case 7: /* $F000-$FFFF */
|
||
mirroring = V & 1;
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* Mapper #152 */
|
||
if (mapper == 0x12)
|
||
{
|
||
SET_BITS(chr_bank_a, "6:3", V, "3:0"); /* chr_bank_a[6:3] = cpu_data_in[3:0]; */
|
||
SET_BITS(prg_bank_a, "3:1", V, "6:4"); /* prg_bank_a[3:1] = cpu_data_in[6:4]; */
|
||
if (flags & 1)
|
||
mirroring = 2 | get_bits(V, "7"); /* mirroring = {1'b1, cpu_data_in[7]}; // Mapper #152 */
|
||
else
|
||
SET_BITS(prg_bank_a, "4", V, "7"); /*prg_bank_a[4] <= cpu_data_in[7]; // Mapper #70 */
|
||
}
|
||
|
||
/* Mapper #73 - VRC3 */
|
||
if (mapper == 0x13)
|
||
{
|
||
switch (get_bits(A, "14:12")) /* case (cpu_addr_in[14:12]) */
|
||
{
|
||
case 0x00: /* 3'b000: vrc3_irq_latch[3:0] = cpu_data_in[3:0]; // $8000-$8FFF */
|
||
SET_BITS(vrc3_irq_latch, "3:0", V, "3:0");
|
||
break;
|
||
case 0x01: /* 3'b001: vrc3_irq_latch[7:4] = cpu_data_in[3:0]; // $9000-$9FFF */
|
||
SET_BITS(vrc3_irq_latch, "7:4", V, "3:0");
|
||
break;
|
||
case 0x02: /* 3'b010: vrc3_irq_latch[11:8] = cpu_data_in[3:0]; // $A000-$AFFF */
|
||
SET_BITS(vrc3_irq_latch, "11:8", V, "3:0");
|
||
break;
|
||
case 0x03: /* 3'b011: vrc3_irq_latch[15:12] = cpu_data_in[3:0]; // $B000-$BFFF */
|
||
SET_BITS(vrc3_irq_latch, "15:12", V, "3:0");
|
||
break;
|
||
case 0x04: /* $C000-$CFFF */
|
||
X6502_IRQEnd(FCEU_IQEXT); /* vrc3_irq_out = 0; // ack */
|
||
SET_BITS(vrc3_irq_control, "2:0", V, "2:0"); /* vrc3_irq_control[2:0] = cpu_data_in[2:0]; // mode, enabled, enabled after ack */
|
||
if (vrc3_irq_control & 2) /* if (vrc3_irq_control[1]) // if E is set */
|
||
vrc3_irq_value = vrc3_irq_latch; /* vrc3_irq_value[15:0] = vrc3_irq_latch[15:0]; // reload with latch */
|
||
break;
|
||
case 0x05: /* $D000-$DFFF */
|
||
X6502_IRQEnd(FCEU_IQEXT); /* vrc3_irq_out = 0; // ack */
|
||
SET_BITS(vrc3_irq_control, "1", vrc3_irq_control, "0"); /* vrc3_irq_control[1] = vrc3_irq_control[0]; */
|
||
break;
|
||
case 0x06: /* $E000-$EFFF */
|
||
break;
|
||
case 0x07: /* 3'b111: prg_bank_a[3:1] = cpu_data_in[2:0]; // $F000-$FFFF */
|
||
SET_BITS(prg_bank_a, "3:1", V, "2:0");
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* Mapper #4 - MMC3/MMC6 */
|
||
/*
|
||
flag0 - TxSROM
|
||
flag1 - mapper #189
|
||
*/
|
||
if (mapper == 0x14)
|
||
{
|
||
/* case ({cpu_addr_in[14:13], cpu_addr_in[0]}) */
|
||
switch (get_bits(A, "14:13,0"))
|
||
{
|
||
case 0x00: /* $8000-$9FFE, even */
|
||
SET_BITS(mmc3_internal, "2:0", V, "2:0"); /* mmc3_internal[2:0] = cpu_data_in[2:0]; */
|
||
if (!(flags & 2) && !(flags & 4)) /* if ((!USE_MAPPER_189 | ~flags[1]) & (!USE_MAPPER_206 | ~flags[2])) */
|
||
{
|
||
if (get_bits(V, "6")) /* if (cpu_data_in[6]) */
|
||
prg_mode = 0x05;
|
||
else
|
||
prg_mode = 0x04;
|
||
}
|
||
if (!(flags & 4)) /* if (!USE_MAPPER_206 | ~flags[2]) // disabled for mapper #206 */
|
||
{
|
||
if (V & 0x80) /* if (cpu_data_in[7]) */
|
||
chr_mode = 0x03;
|
||
else
|
||
chr_mode = 0x02;
|
||
}
|
||
break;
|
||
case 0x01: /* $8001-$9FFF, odd */
|
||
switch (get_bits(mmc3_internal, "2:0"))
|
||
{
|
||
case 0x00: /* 3'b000: chr_bank_a[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_a, "7:0", V, "7:0"); break;
|
||
case 0x01: /* 3'b001: chr_bank_c[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_c, "7:0", V, "7:0"); break;
|
||
case 0x02: /* 3'b010: chr_bank_e[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
|
||
case 0x03: /* 3'b011: chr_bank_f[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
|
||
case 0x04: /* 3'b100: chr_bank_g[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
|
||
case 0x05: /* 3'b101: chr_bank_h[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
|
||
case 0x06: /* 3'b110: if (!ENABLE_MAPPER_189 | ~flags[1]) prg_bank_a[(MMC3_BITSIZE-1):0] = cpu_data_in[(MMC3_BITSIZE-1):0]; */
|
||
if (!(flags & 2))
|
||
SET_BITS(prg_bank_a, "7:0", V, "7:0");
|
||
break;
|
||
case 0x07: /* 3'b111: if (!ENABLE_MAPPER_189 | ~flags[1]) prg_bank_b[(MMC3_BITSIZE-1):0] = cpu_data_in[(MMC3_BITSIZE-1):0]; */
|
||
if (!(flags & 2))
|
||
SET_BITS(prg_bank_b, "7:0", V, "7:0");
|
||
break;
|
||
}
|
||
break;
|
||
case 0x02: /* $A000-$BFFE, even (mirroring) */
|
||
/* if (!ENABLE_MAPPER_206 | ~flags[2]) // disabled for mapper #206 */
|
||
if (!(flags & 4))
|
||
mirroring = V & 1; /* mirroring = {1'b0, cpu_data_in[0]}; */
|
||
break;
|
||
case 0x03: /* RAM protect... no */
|
||
break;
|
||
case 0x04: /* 3'b100: mmc3_irq_latch = cpu_data_in; // $C000-$DFFE, even (IRQ latch) */
|
||
mmc3_irq_latch = V; break;
|
||
case 0x05: /* 3'b101: mmc3_irq_reload = 1; // $C001-$DFFF, odd */
|
||
mmc3_irq_reload = 1; break;
|
||
case 0x06: /* 3'b110: mmc3_irq_enabled = 0; // $E000-$FFFE, even */
|
||
X6502_IRQEnd(FCEU_IQEXT);
|
||
mmc3_irq_enabled = 0;
|
||
break;
|
||
case 0x07: /* $E001-$FFFF, odd */
|
||
if (!(flags & 4)) /* if (!USE_MAPPER_206 | ~flags[2]) // disabled for mapper #206 */
|
||
mmc3_irq_enabled = 1; /* mmc3_irq_enabled = 1; */
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* Mapper #112 */
|
||
if (mapper == 0x15)
|
||
{
|
||
switch (get_bits(A, "14:13"))
|
||
{
|
||
case 0x00: /* $8000-$9FFF */
|
||
SET_BITS(mapper112_internal, "2:0", V, "2:0"); /* mapper112_internal[2:0] = cpu_data_in[2:0]; */
|
||
break;
|
||
case 0x01: /* $A000-BFFF */
|
||
switch (get_bits(mapper112_internal, "2:0"))
|
||
{
|
||
case 0x00: /* 3'b000: prg_bank_a[5:0] = cpu_data_in[5:0]; */
|
||
SET_BITS(prg_bank_a, "5:0", V, "5:0"); break;
|
||
case 0x01: /* 3'b001: prg_bank_b[5:0] = cpu_data_in[5:0]; */
|
||
SET_BITS(prg_bank_b, "5:0", V, "5:0"); break;
|
||
case 0x02: /* 3'b010: chr_bank_a[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_a, "7:0", V, "7:0"); break;
|
||
case 0x03: /* 3'b011: chr_bank_c[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_c, "7:0", V, "7:0"); break;
|
||
case 0x04: /* 3'b100: chr_bank_e[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
|
||
case 0x05: /* 3'b101: chr_bank_f[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
|
||
case 0x06: /* 3'b110: chr_bank_g[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
|
||
case 0x07: /* 3'b111: chr_bank_h[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
|
||
}
|
||
break;
|
||
case 0x02: /* $C000-$DFFF */
|
||
break;
|
||
case 0x03: /* 2'b11: mirroring = {1'b0, cpu_data_in[0]}; // $E000-$FFFF */
|
||
mirroring = V & 1; break;
|
||
}
|
||
}
|
||
|
||
/* Mappers #33 + #48 - Taito
|
||
* flag0=0 - #33, flag0=1 - #48 */
|
||
if (mapper == 0x16)
|
||
{
|
||
/* case ({cpu_addr_in[14:13], cpu_addr_in[1:0]}) */
|
||
switch (get_bits(A, "14:13,1:0"))
|
||
{
|
||
case 0x00:
|
||
SET_BITS(prg_bank_a, "5:0", V, "5:0"); /* prg_bank_a[5:0] = cpu_data_in[5:0]; // $8000, PRG Reg 0 (8k @ $8000) */
|
||
if (!(flags & 1)) /* if (~flags[0]) // 33 */
|
||
mirroring = get_bits(V, "6"); /* mirroring = {1'b0, cpu_data_in[6]}; */
|
||
break;
|
||
case 0x01: /* 4'b0001: prg_bank_b[5:0] = cpu_data_in[5:0]; // $8001, PRG Reg 1 (8k @ $A000) */
|
||
SET_BITS(prg_bank_b, "5:0", V, "5:0"); break;
|
||
case 0x02: /* 4'b0010: chr_bank_a[7:1] = cpu_data_in[6:0]; // $8002, CHR Reg 0 (2k @ $0000) */
|
||
SET_BITS(chr_bank_a, "7:1", V, "6:0"); break;
|
||
case 0x03: /* 4'b0011: chr_bank_c[7:1] = cpu_data_in[6:0]; // $8003, CHR Reg 1 (2k @ $0800) */
|
||
SET_BITS(chr_bank_c, "7:1", V, "6:0"); break;
|
||
case 0x04: /* 4'b0100: chr_bank_e[7:0] = cpu_data_in[7:0]; // $A000, CHR Reg 2 (1k @ $1000) */
|
||
SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
|
||
case 0x05: /* 4'b0101: chr_bank_f[7:0] = cpu_data_in[7:0]; // $A001, CHR Reg 2 (1k @ $1400) */
|
||
SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
|
||
case 0x06: /* 4'b0110: chr_bank_g[7:0] = cpu_data_in[7:0]; // $A002, CHR Reg 2 (1k @ $1800) */
|
||
SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
|
||
case 0x07: /* 4'b0111: chr_bank_h[7:0] = cpu_data_in[7:0]; // $A003, CHR Reg 2 (1k @ $1C00) */
|
||
SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
|
||
case 0x0C: /* 4'b1100: if (flags[0]) mirroring = {1'b0, cpu_data_in[6]}; // $E000, mirroring, for mapper #48 */
|
||
if (flags & 1) /* 48 */
|
||
mirroring = get_bits(V, "6"); /* mirroring = cpu_data_in[6]; */
|
||
break;
|
||
case 0x08: /* 4'b1000: irq_scanline_latch = ~cpu_data_in; // $C000, IRQ latch */
|
||
mmc3_irq_latch = set_bits(mmc3_irq_latch, "7:0", get_bits(V, "7:0") ^ 0xFF);
|
||
break;
|
||
case 0x09: /* 4'b1001: mmc3_irq_reload = 1; // $C001, IRQ reload */
|
||
mmc3_irq_reload = 1; break;
|
||
case 0x0A: /* 4'b1010: mmc3_irq_enabled = 1; // $C002, IRQ enable */
|
||
mmc3_irq_enabled = 1; break;
|
||
case 0x0B: /* 4'b1011: mmc3_irq_enabled = 0; // $C003, IRQ disable & ack */
|
||
mmc3_irq_enabled = 0;
|
||
X6502_IRQEnd(FCEU_IQEXT); /* irq_cpu_out = 0; // ack */
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* Mapper #42 */
|
||
if (mapper == 0x17)
|
||
{
|
||
/* case ({cpu_addr_in[14], cpu_addr_in[1:0]}) */
|
||
switch (get_bits(A, "14,1:0"))
|
||
{
|
||
case 0: /* 3'b000: chr_bank_a[7:3] = cpu_data_in[4:0]; // $8000, CHR Reg (8k @ $8000) */
|
||
SET_BITS(chr_bank_a, "7:3", V, "4:0");
|
||
break;
|
||
case 4: /* 3'b100: prg_bank_6000[3:0] = cpu_data_in[3:0]; // $E000, PRG Reg (8k @ $6000) */
|
||
SET_BITS(prg_bank_6000, "3:0", V, "3:0");
|
||
break;
|
||
case 5: /* 3'b101: mirroring = {1'b0, cpu_data_in[3]}; // Mirroring */
|
||
mirroring = get_bits(V, "3");
|
||
break;
|
||
case 6: /* 3'b110: ... // IRQ */
|
||
mapper42_irq_enabled = get_bits(V, "1"); /* mapper42_irq_enabled = cpu_data_in[1]; */
|
||
if (!mapper42_irq_enabled) /* if (!mapper42_irq_enabled) */
|
||
{
|
||
X6502_IRQEnd(FCEU_IQEXT); /* irq_cpu_out = 0; */
|
||
mapper42_irq_value = 0; /* mapper42_irq_value = 0; */
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* Mapper #23 - VRC2/4 */
|
||
/*
|
||
flag0 - switches A0 and A1 lines. 0=A0,A1 like VRC2b (mapper #23), 1=A1,A0 like VRC2a(#22), VRC2c(#25)
|
||
flag1 - divides CHR bank select by two (mapper #22, VRC2a)
|
||
*/
|
||
if (mapper == 0x18)
|
||
{
|
||
vrc_2b_hi =
|
||
(flags & 5) == 0 ? /* (!flags[0] && !flags[2]) ? */
|
||
(get_bits(A, "7") | get_bits(A, "2")) /* | cpu_addr_in[7] | cpu_addr_in[2]) // mapper #21 */
|
||
: (flags & 5) == 1 ? /*: (flags[0] && !flags[2]) ? */
|
||
get_bits(A, "0") /* (cpu_addr_in[0]) // mapper #22 */
|
||
: (flags & 5) == 4 ? /* : (!flags[0] && flags[2]) ? */
|
||
(get_bits(A, "5") | get_bits(A, "3") | get_bits(A, "1")) /* (cpu_addr_in[5] | cpu_addr_in[3] | cpu_addr_in[1]) // mapper #23 */
|
||
: (get_bits(A, "2") | get_bits(A, "0")); /* : (cpu_addr_in[2] | cpu_addr_in[0]); // mapper #25 */
|
||
vrc_2b_low =
|
||
(flags & 5) == 0 ? /* (!flags[0] && !flags[2]) ? */
|
||
(get_bits(A, "6") | get_bits(A, "1")) /* (cpu_addr_in[6] | cpu_addr_in[1]) // mapper #21 */
|
||
: (flags & 5) == 1 ? /* : (flags[0] && !flags[2]) ? */
|
||
get_bits(A, "1") /* (cpu_addr_in[1]) // mapper #22 */
|
||
: (flags & 5) == 4 ?/* : (!flags[0] && flags[2]) ? */
|
||
(get_bits(A, "4") | get_bits(A, "2") | get_bits(A, "0")) /* (cpu_addr_in[4] | cpu_addr_in[2] | cpu_addr_in[0]) // mapper #23 */
|
||
: (get_bits(A, "3") | get_bits(A, "1")); /* : (cpu_addr_in[3] | cpu_addr_in[1]); // mapper #25 */
|
||
|
||
/* case ({ cpu_addr_in[14:12], vrc_2b_hi, vrc_2b_low }) */
|
||
switch ((get_bits(A, "14:12") << 2) | (vrc_2b_hi << 1) | vrc_2b_low)
|
||
{
|
||
case 0x00: /* $8000-$8003, PRG0 */
|
||
case 0x01:
|
||
case 0x02:
|
||
case 0x03:
|
||
SET_BITS(prg_bank_a, "4:0", V, "4:0"); /* prg_bank_a[4:0] = cpu_data_in[4:0]; */
|
||
break;
|
||
case 0x04: /* $9000-$9001, mirroring */
|
||
case 0x05:
|
||
/* VRC2 - using games are usually well - behaved and only write 0 or 1 to this register,
|
||
* but Wai Wai World in one instance writes $FF instead */
|
||
if (V != 0xFF) /* if (cpu_data_in != 8'b11111111) mirroring = cpu_data_in[1:0]; // $9000-$9001, mirroring */
|
||
SET_BITS(mirroring, "1:0", V, "1:0");
|
||
break;
|
||
case 0x06: /* $9002-$9004, PRG swap */
|
||
case 0x07:
|
||
SET_BITS(prg_mode, "0", V, "1"); /* prg_mode[0] = cpu_data_in[1]; */
|
||
break;
|
||
case 0x08: /* $A000-$A003, PRG1 */
|
||
case 0x09:
|
||
case 0x0A:
|
||
case 0x0B:
|
||
SET_BITS(prg_bank_b, "4:0", V, "4:0"); /* prg_bank_b[4:0] = cpu_data_in[4:0]; */
|
||
break;
|
||
case 0x0C: /* 5'b01100: chr_bank_a[3:0] = cpu_data_in[3:0]; // $B000, CHR0 low */
|
||
SET_BITS(chr_bank_a, "3:0", V, "3:0"); break;
|
||
case 0x0D: /* 5'b01101: chr_bank_a[7:4] = cpu_data_in[3:0]; // $B001, CHR0 hi */
|
||
SET_BITS(chr_bank_a, "7:4", V, "3:0"); break;
|
||
case 0x0E: /* 5'b01110: chr_bank_b[3:0] = cpu_data_in[3:0]; // $B002, CHR1 low */
|
||
SET_BITS(chr_bank_b, "3:0", V, "3:0"); break;
|
||
case 0x0F: /* 5'b01111: chr_bank_b[7:4] = cpu_data_in[3:0]; // $B003, CHR1 hi */
|
||
SET_BITS(chr_bank_b, "7:4", V, "3:0"); break;
|
||
case 0x10: /* 5'b10000: chr_bank_c[3:0] = cpu_data_in[3:0]; // $C000, CHR2 low */
|
||
SET_BITS(chr_bank_c, "3:0", V, "3:0"); break;
|
||
case 0x11: /* 5'b10001: chr_bank_c[7:4] = cpu_data_in[3:0]; // $C001, CHR2 hi */
|
||
SET_BITS(chr_bank_c, "7:4", V, "3:0"); break;
|
||
case 0x12: /* 5'b10010: chr_bank_d[3:0] = cpu_data_in[3:0]; // $C002, CHR3 low */
|
||
SET_BITS(chr_bank_d, "3:0", V, "3:0"); break;
|
||
case 0x13: /* 5'b10011: chr_bank_d[7:4] = cpu_data_in[3:0]; // $C003, CHR3 hi */
|
||
SET_BITS(chr_bank_d, "7:4", V, "3:0"); break;
|
||
case 0x14: /* 5'b10100: chr_bank_e[3:0] = cpu_data_in[3:0]; // $D000, CHR4 low */
|
||
SET_BITS(chr_bank_e, "3:0", V, "3:0"); break;
|
||
case 0x15: /* 5'b10101: chr_bank_e[7:4] = cpu_data_in[3:0]; // $D001, CHR4 hi */
|
||
SET_BITS(chr_bank_e, "7:4", V, "3:0"); break;
|
||
case 0x16: /* 5'b10110: chr_bank_f[3:0] = cpu_data_in[3:0]; // $D002, CHR5 low */
|
||
SET_BITS(chr_bank_f, "3:0", V, "3:0"); break;
|
||
case 0x17: /* 5'b10111: chr_bank_f[7:4] = cpu_data_in[3:0]; // $D003, CHR5 hi */
|
||
SET_BITS(chr_bank_f, "7:4", V, "3:0"); break;
|
||
case 0x18: /* 5'b11000: chr_bank_g[3:0] = cpu_data_in[3:0]; // $E000, CHR6 low */
|
||
SET_BITS(chr_bank_g, "3:0", V, "3:0"); break;
|
||
case 0x19: /* 5'b11001: chr_bank_g[7:4] = cpu_data_in[3:0]; // $E001, CHR6 hi */
|
||
SET_BITS(chr_bank_g, "7:4", V, "3:0"); break;
|
||
case 0x1A: /* 5'b11010: chr_bank_h[3:0] = cpu_data_in[3:0]; // $E002, CHR7 low */
|
||
SET_BITS(chr_bank_h, "3:0", V, "3:0"); break;
|
||
case 0x1B: /* 5'b11011: chr_bank_h[7:4] = cpu_data_in[3:0]; // $E003, CHR7 hi */
|
||
SET_BITS(chr_bank_h, "7:4", V, "3:0"); break;
|
||
}
|
||
|
||
/* if (cpu_addr_in[14:12] == 3'b111) */
|
||
if (get_bits(A, "14:12") == 0x07)
|
||
{
|
||
/* case (vrc_2b_hi, vrc_2b_low}) */
|
||
switch ((vrc_2b_hi << 1) | vrc_2b_low)
|
||
{
|
||
case 0x00: /* 2'b00: vrc4_irq_latch[3:0] = cpu_data_in[3:0]; // IRQ latch low */
|
||
SET_BITS(vrc4_irq_latch, "3:0", V, "3:0"); break;
|
||
case 0x01: /* 2'b01: vrc4_irq_latch[7:4] = cpu_data_in[3:0]; // IRQ latch hi */
|
||
SET_BITS(vrc4_irq_latch, "7:4", V, "3:0"); break;
|
||
case 0x02: /* 2'b10 // IRQ control */
|
||
X6502_IRQEnd(FCEU_IQEXT); /* vrc4_irq_out = 0; // ack */
|
||
SET_BITS(vrc4_irq_control, "2:0", V, "2:0"); /* vrc4_irq_control[2:0] = cpu_data_in[2:0]; // mode, enabled, enabled after ack */
|
||
if (vrc4_irq_control & 2) /* if (vrc4_irq_control[1]) begin // if E is set */
|
||
{
|
||
vrc4_irq_prescaler_counter = 0; /* vrc4_irq_prescaler_counter[1:0] = 2'b00; // reset prescaler */
|
||
vrc4_irq_prescaler = 0; /* vrc4_irq_prescaler[6:0] = 7'b0000000; */
|
||
SET_BITS(vrc4_irq_value, "7:0", vrc4_irq_latch, "7:0"); /* vrc4_irq_value[7:0] = vrc4_irq_latch[7:0]; // reload with latch */
|
||
}
|
||
break;
|
||
case 0x03: /* 2'b11 // IRQ ack */
|
||
X6502_IRQEnd(FCEU_IQEXT); /* vrc4_irq_out = 0; */
|
||
SET_BITS(vrc4_irq_control, "1", vrc4_irq_control, "0"); /* vrc4_irq_control[1] = vrc4_irq_control[0]; */
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Mapper #69 - Sunsoft FME-7 */
|
||
if (mapper == 0x19)
|
||
{
|
||
/* if (cpu_addr_in[14:13] == 2'b00) mapper69_internal[3:0] = cpu_data_in[3:0]; */
|
||
if (get_bits(A, "14:13") == 0x00) SET_BITS(mapper69_internal, "3:0", V, "3:0");
|
||
/* if (cpu_addr_in[14:13] == 2'b01) */
|
||
if (get_bits(A, "14:13") == 0x01)
|
||
{
|
||
switch (get_bits(mapper69_internal, "3:0")) /* case (mapper69_internal[3:0]) */
|
||
{
|
||
case 0x00: /* 4'b0000: chr_bank_a[7:0] = cpu_data_in[7:0]; // CHR0 */
|
||
SET_BITS(chr_bank_a, "7:0", V, "7:0"); break;
|
||
case 0x01: /* 4'b0001: chr_bank_b[7:0] = cpu_data_in[7:0]; // CHR1 */
|
||
SET_BITS(chr_bank_b, "7:0", V, "7:0"); break;
|
||
case 0x02: /* 4'b0010: chr_bank_c[7:0] = cpu_data_in[7:0]; // CHR2 */
|
||
SET_BITS(chr_bank_c, "7:0", V, "7:0"); break;
|
||
case 0x03: /* 4'b0011: chr_bank_d[7:0] = cpu_data_in[7:0]; // CHR3 */
|
||
SET_BITS(chr_bank_d, "7:0", V, "7:0"); break;
|
||
case 0x04: /* 4'b0100: chr_bank_e[7:0] = cpu_data_in[7:0]; // CHR4 */
|
||
SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
|
||
case 0x05: /* 4'b0101: chr_bank_f[7:0] = cpu_data_in[7:0]; // CHR5 */
|
||
SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
|
||
case 0x06: /* 4'b0110: chr_bank_g[7:0] = cpu_data_in[7:0]; // CHR6 */
|
||
SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
|
||
case 0x07: /* 4'b0111: chr_bank_h[7:0] = cpu_data_in[7:0]; // CHR7 */
|
||
SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
|
||
case 0x08: /* 4'b1000: {sram_enabled, map_rom_on_6000, prg_bank_6000} = {cpu_data_in[7], ~cpu_data_in[6], cpu_data_in[5:0]}; // PRG0 */
|
||
sram_enabled = (V >> 7) & 1;
|
||
map_rom_on_6000 = ((V >> 6) & 1) ^ 1;
|
||
prg_bank_6000 = V & 0x3F;
|
||
break;
|
||
case 0x09: /* 4'b1001: prg_bank_a[5:0] = cpu_data_in[5:0]; // PRG1 */
|
||
SET_BITS(prg_bank_a, "5:0", V, "5:0"); break;
|
||
case 0x0A: /* 4'b1010: prg_bank_b[5:0] = cpu_data_in[5:0]; // PRG2 */
|
||
SET_BITS(prg_bank_b, "5:0", V, "5:0"); break;
|
||
case 0x0B: /* 4'b1011: prg_bank_c[5:0] = cpu_data_in[5:0]; // PRG3 */
|
||
SET_BITS(prg_bank_c, "5:0", V, "5:0"); break;
|
||
case 0x0C: /* 4'b1100: mirroring[1:0] = cpu_data_in[1:0]; // mirroring */
|
||
SET_BITS(mirroring, "1:0", V, "1:0"); break;
|
||
case 0x0D: /* 4'b1101 */
|
||
X6502_IRQEnd(FCEU_IQEXT); /* fme7_irq_out = 0; // ack */
|
||
mapper69_counter_enabled = get_bits(V, "7"); /* fme7_counter_enabled = cpu_data_in[7]; */
|
||
mapper69_irq_enabled = get_bits(V, "0"); /* fme7_irq_enabled = cpu_data_in[0]; */
|
||
break;
|
||
case 0x0E: /* 4'b1110: fme7_irq_value[7:0] = cpu_data_in[7:0]; // IRQ low */
|
||
SET_BITS(mapper69_irq_value, "7:0", V, "7:0"); break;
|
||
case 0x0F: /* fme7_irq_value[15:8] = cpu_data_in[7:0]; // IRQ high */
|
||
SET_BITS(mapper69_irq_value, "15:8", V, "7:0"); break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Mapper #32 - Irem's G-101 */
|
||
if (mapper == 0x1A)
|
||
{
|
||
switch (get_bits(A, "14:12"))
|
||
{
|
||
case 0x00: /* 2'b00: prg_bank_a[5:0] = cpu_data_in[5:0]; // $8000-$8FFF, PRG0 */
|
||
SET_BITS(prg_bank_a, "5:0", V, "5:0");
|
||
break;
|
||
case 0x01: /* 2'b01: {prg_mode[0], mirroring} = {cpu_data_in[1], 1'b0, cpu_data_in[0]}; // $9000-$9FFF, PRG mode, mirroring */
|
||
SET_BITS(prg_mode, "0", V, "1");
|
||
mirroring = V & 1;
|
||
break;
|
||
case 0x02: /* 2'b10: prg_bank_b[5:0] = cpu_data_in[5:0]; // $A000-$AFFF, PRG1 */
|
||
SET_BITS(prg_bank_b, "5:0", V, "5:0");
|
||
break;
|
||
case 0x03: /* $B000-$BFFF, CHR regs */
|
||
switch (get_bits(A, "2:0"))
|
||
{
|
||
case 0x00: /* 3'b000: chr_bank_a[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_a, "7:0", V, "7:0"); break;
|
||
case 0x01: /* 3'b001: chr_bank_b[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_b, "7:0", V, "7:0"); break;
|
||
case 0x02: /* 3'b010: chr_bank_c[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_c, "7:0", V, "7:0"); break;
|
||
case 0x03: /* 3'b011: chr_bank_d[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_d, "7:0", V, "7:0"); break;
|
||
case 0x04: /* 3'b100: chr_bank_e[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_e, "7:0", V, "7:0"); break;
|
||
case 0x05: /* 3'b101: chr_bank_f[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_f, "7:0", V, "7:0"); break;
|
||
case 0x06: /* 3'b110: chr_bank_g[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_g, "7:0", V, "7:0"); break;
|
||
case 0x07: /* 3'b111: chr_bank_h[7:0] = cpu_data_in[7:0]; */
|
||
SET_BITS(chr_bank_h, "7:0", V, "7:0"); break;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* Mapper #36 is assigned to TXC's PCB 01-22000-400 */
|
||
if (mapper == 0x1D)
|
||
{
|
||
if (get_bits(A, "14:1") != 0x3FFF) /* (cpu_addr_in[14:1] != 14'b11111111111111) */
|
||
{
|
||
/* prg_bank_a[5:2] = cpu_data_in[7:4]; */
|
||
SET_BITS(prg_bank_a, "5:2", V, "7:4");
|
||
/* chr_bank_a[6:3] = cpu_data_in[3:0]; */
|
||
SET_BITS(chr_bank_a, "6:3", V, "3:0");
|
||
}
|
||
}
|
||
|
||
/* Mapper #70 */
|
||
if (mapper == 0x1E)
|
||
{
|
||
/* prg_bank_a[4:1] = cpu_data_in[7:4]; */
|
||
SET_BITS(prg_bank_a, "4:1", V, "7:4");
|
||
/* chr_bank_a[6:3] = cpu_data_in[3:0]; */
|
||
SET_BITS(chr_bank_a, "6:3", V, "3:0");
|
||
}
|
||
|
||
/* Mapper #75 - VRC1 */
|
||
if (mapper == 0x22)
|
||
{
|
||
/* case (cpu_addr_in[14:12]) */
|
||
switch (get_bits(A, "14:12"))
|
||
{
|
||
case 0x00: /* 3'b000: prg_bank_a[3:0] = cpu_data_in[3:0]; // $8000-$8FFF */
|
||
SET_BITS(prg_bank_a, "3:0", V, "3:0"); break;
|
||
case 0x01:
|
||
mirroring = V & 1; /* mirroring = {1'b0, cpu_data_in[0]}; */
|
||
SET_BITS(chr_bank_a, "6", V, "1"); /* chr_bank_a[6] = cpu_data_in[1]; */
|
||
SET_BITS(chr_bank_e, "6", V, "2"); /* chr_bank_e[6] = cpu_data_in[2]; */
|
||
break;
|
||
case 0x02: /* 3'b010: prg_bank_b[3:0] = cpu_data_in[3:0]; // $A000-$AFFF */
|
||
SET_BITS(prg_bank_b, "3:0", V, "3:0"); break;
|
||
case 0x04: /* 3'b100: prg_bank_c[3:0] = cpu_data_in[3:0]; // $C000-$CFFF */
|
||
SET_BITS(prg_bank_c, "3:0", V, "3:0"); break;
|
||
case 0x06: /* 3'b110: <20>hr_bank_a[5:2] = cpu_data_in[3:0]; // $E000-$EFFF */
|
||
SET_BITS(chr_bank_a, "5:2", V, "3:0"); break;
|
||
case 0x07: /* 3'b111: chr_bank_e[5:2] = cpu_data_in[3:0]; // $F000-$FFFF */
|
||
SET_BITS(chr_bank_e, "5:2", V, "3:0"); break;
|
||
}
|
||
}
|
||
|
||
/* Mapper #83 - Cony/Yoko */
|
||
if (mapper == 0x23)
|
||
{
|
||
/* case (cpu_addr_in[9:8]) */
|
||
switch (get_bits(A, "9:8"))
|
||
{
|
||
case 0x00: /* $80xx */
|
||
SET_BITS(prg_bank_a, "4:1", V, "3:0");
|
||
break;
|
||
case 0x01: /* $81xx */
|
||
mirroring = get_bits(V, "1:0"); /* mirroring <= cpu_data_in[1:0]; */
|
||
SET_BITS(prg_mode, "2", V, "4"); /* prg_mode[2] <= cpu_data_in[4]; */
|
||
map_rom_on_6000 = get_bits(V, "5"); /* map_rom_on_6000 <= cpu_data_in[5]; */
|
||
mapper83_irq_enabled_latch = get_bits(V, "7"); /* mapper83_irq_enabled_latch <= cpu_data_in[7]; */
|
||
break;
|
||
case 0x02: /* 82xx */
|
||
if (!get_bits(A, "0")) /* if (!cpu_addr_in[0]) */
|
||
{
|
||
X6502_IRQEnd(FCEU_IQEXT); /* mapper83_irq_out <= 0; */
|
||
SET_BITS(mapper83_irq_counter, "7:0", V, "7:0"); /* mapper83_irq_counter[7:0] <= cpu_data_in[7:0]; */
|
||
}
|
||
else {
|
||
mapper83_irq_enabled = mapper83_irq_enabled_latch; /*mapper83_irq_enabled <= mapper83_irq_enabled_latch; */
|
||
SET_BITS(mapper83_irq_counter, "15:8", V, "7:0"); /* mapper83_irq_counter[15:8] <= cpu_data_in[7:0]; */
|
||
}
|
||
break;
|
||
case 0x03:
|
||
if (!get_bits(A, "4")) /* if (!cpu_addr_in[4]) */
|
||
{
|
||
switch (get_bits(A, "1:0")) /* case (cpu_addr_in[1:0]) */
|
||
{
|
||
case 0x00: SET_BITS(prg_bank_a, "7:0", V, "7:0"); break; /* 2'b00: prg_bank_a[7:0] <= cpu_data_in[7:0]; */
|
||
case 0x01: SET_BITS(prg_bank_b, "7:0", V, "7:0"); break; /* 2'b01: prg_bank_b[7:0] <= cpu_data_in[7:0]; */
|
||
case 0x02: SET_BITS(prg_bank_b, "7:0", V, "7:0"); break; /* 2'b10: prg_bank_c[7:0] <= cpu_data_in[7:0]; */
|
||
case 0x03: SET_BITS(prg_bank_6000, "7:0", V, "7:0"); break; /*2'b11: prg_bank_6000[7:0] <= cpu_data_in[7:0]; */
|
||
}
|
||
}
|
||
else {
|
||
if (!(flags & 0x04))
|
||
{
|
||
switch (get_bits(A, "2:0")) /* case (cpu_addr_in[2:0]) */
|
||
{
|
||
case 0x00: SET_BITS(chr_bank_a, "7:0", V, "7:0"); break; /* 3'b000: chr_bank_a[7:0] <= cpu_data_in[7:0]; */
|
||
case 0x01: SET_BITS(chr_bank_b, "7:0", V, "7:0"); break; /* 3'b001: chr_bank_b[7:0] <= cpu_data_in[7:0]; */
|
||
case 0x02: SET_BITS(chr_bank_c, "7:0", V, "7:0"); break; /* 3'b010: chr_bank_c[7:0] <= cpu_data_in[7:0]; */
|
||
case 0x03: SET_BITS(chr_bank_d, "7:0", V, "7:0"); break; /* 3'b011: chr_bank_d[7:0] <= cpu_data_in[7:0]; */
|
||
case 0x04: SET_BITS(chr_bank_e, "7:0", V, "7:0"); break; /* 3'b100: chr_bank_e[7:0] <= cpu_data_in[7:0]; */
|
||
case 0x05: SET_BITS(chr_bank_f, "7:0", V, "7:0"); break; /* 3'b101: chr_bank_f[7:0] <= cpu_data_in[7:0]; */
|
||
case 0x06: SET_BITS(chr_bank_g, "7:0", V, "7:0"); break; /* 3'b110: chr_bank_g[7:0] <= cpu_data_in[7:0]; */
|
||
case 0x07: SET_BITS(chr_bank_h, "7:0", V, "7:0"); break; /* 3'b111: chr_bank_h[7:0] <= cpu_data_in[7:0]; */
|
||
}
|
||
}
|
||
else {
|
||
switch (get_bits(A, "2:0")) /* case (cpu_addr_in[2:0]) */
|
||
{
|
||
case 0x00:
|
||
SET_BITS(chr_bank_a, "8:1", V, "7:0"); break; /* 3'b000: chr_bank_a[8:1] <= cpu_data_in[7:0]; */
|
||
case 0x01:
|
||
SET_BITS(chr_bank_c, "8:1", V, "7:0"); break; /* 3'b001: chr_bank_c[8:1] <= cpu_data_in[7:0]; */
|
||
case 0x06:
|
||
SET_BITS(chr_bank_e, "8:1", V, "7:0"); break; /* 3'b110: chr_bank_e[8:1] <= cpu_data_in[7:0]; */
|
||
case 0x07:
|
||
SET_BITS(chr_bank_g, "8:1", V, "7:0"); break; /* 3'b111: chr_bank_g[8:1] <= cpu_data_in[7:0]; */
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* Mapper #67 - Sunsoft-3 */
|
||
if (mapper == 0x24)
|
||
{
|
||
if (get_bits(A, "11")) /* if (cpu_addr_in[11]) */
|
||
{
|
||
switch (get_bits(A, "14:12")) /* case (cpu_addr_in[14:12]) */
|
||
{
|
||
case 0x00: /* 3'b000: chr_bank_a[6:1] <= cpu_data_in[5:0]; // $8800 */
|
||
SET_BITS(chr_bank_a, "6:1", V, "5:0"); break;
|
||
case 0x01: /* 3'b001: chr_bank_c[6:1] <= cpu_data_in[5:0]; // $9800 */
|
||
SET_BITS(chr_bank_c, "6:1", V, "5:0"); break;
|
||
case 0x02: /* 3'b010: chr_bank_e[6:1] <= cpu_data_in[5:0]; // $A800 */
|
||
SET_BITS(chr_bank_e, "6:1", V, "5:0"); break;
|
||
case 0x03: /* 3'b011: chr_bank_g[6:1] <= cpu_data_in[5:0]; // $B800* */
|
||
SET_BITS(chr_bank_g, "6:1", V, "5:0"); break;
|
||
case 0x04: /* 3'b100: begin // $C800, IRQ load8 */
|
||
mapper67_irq_latch = ~mapper67_irq_latch;
|
||
if (mapper67_irq_latch)
|
||
SET_BITS(mapper67_irq_counter, "15:8", V, "7:0"); /* mapper67_irq_counter[15:8] <= cpu_data_in[7:0]; */
|
||
else
|
||
SET_BITS(mapper67_irq_counter, "7:0", V, "7:0"); /* mapper67_irq_counter[7:0] <= cpu_data_in[7:0]; */
|
||
break;
|
||
case 0x05: /* 3'b101: begin // $D800, IRQ enable */
|
||
mapper67_irq_latch = 0; /* mapper67_irq_latch <= 0; */
|
||
SET_BITS(mapper67_irq_enabled, "0", V, "4"); /* mapper67_irq_enabled <= cpu_data_in[4]; */
|
||
break;
|
||
case 0x06: /* 3'b110: mirroring[1:0] <= cpu_data_in[1:0]; // $E800 */
|
||
SET_BITS(mirroring, "1:0", V, "1:0");
|
||
break;
|
||
case 0x07: /* 3'b111: prg_bank_a[4:1] <= cpu_data_in[3:0]; // $F800 */
|
||
SET_BITS(prg_bank_a, "4:1", V, "3:0");
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
/* Interrupt Acknowledge ($8000) */
|
||
X6502_IRQEnd(FCEU_IQEXT); /* mapper67_irq_out <= 0; */
|
||
}
|
||
}
|
||
|
||
/* Mapper #89 - Sunsoft-2 chip on the Sunsoft-3 board */
|
||
if (mapper == 0x25)
|
||
{
|
||
/* prg_bank_a[3:1] <= cpu_data_in[6:4]; */
|
||
SET_BITS(prg_bank_a, "3:1", V, "6:4");
|
||
/* chr_bank_a[6:3] <= {cpu_data_in[7], cpu_data_in[2:0]}; */
|
||
SET_BITS(chr_bank_a, "6:3", V, "7,2:0");
|
||
/* mirroring[1:0] <= {1'b1, cpu_data_in[3]}; */
|
||
SET_BITS(mirroring, "1", 1, "0");
|
||
SET_BITS(mirroring, "0", V, "3");
|
||
}
|
||
}
|
||
|
||
COOLGIRL_Sync();
|
||
}
|
||
|
||
static DECLFR(MAFRAM) {
|
||
int ppuon;
|
||
uint8 r, p;
|
||
|
||
if ((mapper == 0x00) && (A >= 0x5000) && (A < 0x6000))
|
||
return 0;
|
||
|
||
/* Mapper #163
|
||
* (USE_MAPPER_163 && (mapper == 5'b00110) && m2 && romsel && cpu_rw_in && ((cpu_addr_in[14:8] & 7'h77) == 7'h51)) ? */
|
||
if ((mapper == 0x06) && ((A & 0x7700) == 0x5100))
|
||
return mapper163_r2 | mapper163_r0 | mapper163_r1 | ~mapper163_r3; /* {1'b1, r2 | r0 | r1 | ~r3} */
|
||
/* (USE_MAPPER_163 && (mapper == 5'b00110) && m2 && romsel && cpu_rw_in && ((cpu_addr_in[14:8] & 7'h77) == 7'h55)) ? */
|
||
if ((mapper == 0x06) && ((A & 0x7700) == 0x5500))
|
||
return (mapper163_r5 & 1) ? mapper163_r2 : mapper163_r1; /* {1'b1, r5[0] ? r2 : r1} */
|
||
|
||
/* MMC5 */
|
||
if ((mapper == 0x0F) && (A == 0x5204))
|
||
{
|
||
ppuon = (PPU[1] & 0x18);
|
||
r = (!ppuon || scanline + 1 >= 241) ? 0 : 1;
|
||
p = mmc5_irq_out;
|
||
X6502_IRQEnd(FCEU_IQEXT);
|
||
mmc5_irq_out = 0;
|
||
return (p << 7) | (r << 6);
|
||
}
|
||
|
||
/* Mapper #36 is assigned to TXC's PCB 01-22000-400 */
|
||
if ((mapper == 0x1D) && ((A & 0xE100) == 0x4100)) /* (USE_MAPPER_036 && mapper == 5'b11101 && {cpu_addr_in[14:13], cpu_addr_in[8]} == 3'b101) ? */
|
||
{
|
||
return (prg_bank_a & 0x0C) << 2; /* {1'b1, 2'b00, prg_bank_a[3:2], 4'b00} */
|
||
}
|
||
|
||
/* Mapper #83 - Cony/Yoko */
|
||
if ((mapper == 0x23) && ((A & 0x7000) == 0x5000)) return flags & 3;
|
||
|
||
/* Mapper #90 - JY */
|
||
if ((mapper == 0x0D) && (A == 0x5800)) return (mul1 * mul2) & 0xFF;
|
||
if ((mapper == 0x0D) && (A == 0x5801)) return ((mul1 * mul2) >> 8) & 0xFF;
|
||
|
||
if (sram_enabled && !map_rom_on_6000 && (A >= 0x6000) && (A < 0x8000))
|
||
return CartBR(A); /* SRAM */
|
||
if (map_rom_on_6000 && (A >= 0x6000) && (A < 0x8000))
|
||
return CartBR(A); /* PRG */
|
||
|
||
return X.DB; /* Open bus */
|
||
}
|
||
|
||
static void COOLGIRL_ScanlineCounter(void) {
|
||
/* for MMC3 and MMC3-based */
|
||
if (mmc3_irq_reload || !mmc3_irq_counter)
|
||
{
|
||
mmc3_irq_counter = mmc3_irq_latch;
|
||
mmc3_irq_reload = 0;
|
||
}
|
||
else
|
||
mmc3_irq_counter--;
|
||
if (!mmc3_irq_counter && mmc3_irq_enabled)
|
||
X6502_IRQBegin(FCEU_IQEXT);
|
||
|
||
/* for MMC5 */
|
||
if (mmc5_irq_line == scanline + 1)
|
||
{
|
||
if (mmc5_irq_enabled)
|
||
{
|
||
X6502_IRQBegin(FCEU_IQEXT);
|
||
mmc5_irq_out = 1;
|
||
}
|
||
}
|
||
|
||
/* for mapper #163 */
|
||
if (scanline == 239)
|
||
{
|
||
mapper_163_latch = 0;
|
||
COOLGIRL_Sync_CHR();
|
||
}
|
||
else if (scanline == 127)
|
||
{
|
||
mapper_163_latch = 1;
|
||
COOLGIRL_Sync_CHR();
|
||
}
|
||
}
|
||
|
||
static void COOLGIRL_CpuCounter(int a) {
|
||
uint8 carry;
|
||
|
||
while (a--)
|
||
{
|
||
/* Mapper #23 - VRC4 */
|
||
if (vrc4_irq_control & 2) /* if (ENABLE_MAPPER_021_022_023_025 & ENABLE_VRC4_INTERRUPTS & (vrc4_irq_control[1])) */
|
||
{
|
||
/* Cycle mode without prescaler is not used by any games? It's missed in fceux source code. */
|
||
if (vrc4_irq_control & 4) /* if (vrc4_irq_control[2]) // cycle mode */
|
||
{
|
||
vrc4_irq_value++; /* {carry, vrc4_irq_value[7:0]} = vrc4_irq_value[7:0] + 1'b1; // just count IRQ value */
|
||
if (vrc4_irq_value == 0) /* if (carry) */
|
||
{
|
||
X6502_IRQBegin(FCEU_IQEXT); /* vrc4_irq_out = 1; */
|
||
vrc4_irq_value = vrc4_irq_latch; /* vrc4_irq_value[7:0] = vrc4_irq_latch[7:0]; */
|
||
}
|
||
}
|
||
else {
|
||
vrc4_irq_prescaler++; /* vrc4_irq_prescaler = vrc4_irq_prescaler + 1'b1; // count prescaler */
|
||
/* if ((vrc4_irq_prescaler_counter[1] == 0 && vrc4_irq_prescaler == 114)
|
||
* || (vrc4_irq_prescaler_counter[1] == 1 && vrc4_irq_prescaler == 113)) // 114, 114, 113 */
|
||
if ((!(vrc4_irq_prescaler_counter & 2) && vrc4_irq_prescaler == 114) || ((vrc4_irq_prescaler_counter & 2) && vrc4_irq_prescaler == 113))
|
||
{
|
||
vrc4_irq_prescaler = 0; /* vrc4_irq_prescaler = 0; */
|
||
vrc4_irq_prescaler_counter++; /* vrc4_irq_prescaler_counter = vrc4_irq_prescaler_counter + 1'b1; */
|
||
if (vrc4_irq_prescaler_counter == 0x03) vrc4_irq_prescaler_counter = 0; /* if (vrc4_irq_prescaler_counter == 2'b11) vrc4_irq_prescaler_counter = 2'b00; */
|
||
vrc4_irq_value++; /* {carry, vrc4_irq_value[7:0]} = vrc4_irq_value[7:0] + 1'b1; */
|
||
if (vrc4_irq_value == 0) /* f (carry) */
|
||
{
|
||
X6502_IRQBegin(FCEU_IQEXT);
|
||
vrc4_irq_value = vrc4_irq_latch; /* irq_cpu_value[7:0] = vrc4_irq_latch[7:0]; */
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Mapper #73 - VRC3 */
|
||
if (vrc3_irq_control & 2)
|
||
{
|
||
if (vrc3_irq_control & 4) /* if (vrc3_irq_control[2]) */
|
||
{ /* 8-bit mode */
|
||
/*vrc3_irq_value = set_bits(vrc3_irq_value, "7:0", get_bits(vrc3_irq_value, "7:0") + 1); // vrc3_irq_value[7:0] = vrc3_irq_value[7:0] + 1'b1; */
|
||
vrc3_irq_value = (vrc3_irq_value & 0xFF00) | ((vrc3_irq_value + 1) & 0xFF);
|
||
/*if (get_bits(vrc3_irq_value, "7:0") == 0) // if (vrc3_irq_value[7:0] == 0) */
|
||
if ((vrc3_irq_value & 0xFF) == 0)
|
||
{
|
||
X6502_IRQBegin(FCEU_IQEXT); /* vrc3_irq_out = 1; */
|
||
/*SET_BITS(vrc3_irq_value, "7:0", vrc3_irq_latch, "7:0"); // vrc3_irq_value[7:0] = vrc3_irq_latch[7:0]; */
|
||
vrc3_irq_value = (vrc3_irq_value & 0xFF00) | (vrc3_irq_latch & 0xFF);
|
||
}
|
||
}
|
||
else { /* 16-bit */
|
||
/*vrc3_irq_value = set_bits(vrc3_irq_value, "15:0", get_bits(vrc3_irq_value, "15:0") + 1); // vrc3_irq_value[15:0] = vrc3_irq_value[15:0] + 1'b1; */
|
||
vrc3_irq_value += 1;
|
||
if (vrc3_irq_value == 0) /* if (vrc3_irq_value[15:0] == 0) */
|
||
{
|
||
X6502_IRQBegin(FCEU_IQEXT); /* vrc3_irq_out = 1; */
|
||
/*SET_BITS(vrc3_irq_value, "15:0", vrc3_irq_latch, "15:0"); // vrc3_irq_value[15:0] = vrc3_irq_latch[15:0]; */
|
||
vrc3_irq_value = vrc3_irq_latch;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Mapper #69 - Sunsoft FME-7
|
||
* if (ENABLE_MAPPER_069 & fme7_counter_enabled) */
|
||
if (mapper69_counter_enabled)
|
||
{
|
||
/* {carry, fme7_irq_value[15:0]} = {0'b0, fme7_irq_value[15:0]} - 1'b1; */
|
||
mapper69_irq_value--;
|
||
/* if (fme7_irq_enabled && carry) fme7_irq_out = 1; */
|
||
if (mapper69_irq_value == 0xFFFF) X6502_IRQBegin(FCEU_IQEXT);
|
||
}
|
||
|
||
/* Mapper #18 */
|
||
if (mapper18_irq_control & 1) /* if (mapper18_irq_control[0]) */
|
||
{
|
||
/*carry = get_bits(mapper18_irq_value, "3:0") - 1; */
|
||
carry = (mapper18_irq_value & 0x0F) - 1;
|
||
/*SET_BITS(mapper18_irq_value, "3:0", carry, "3:0"); */
|
||
mapper18_irq_value = (mapper18_irq_value & 0xFFF0) | (carry & 0x0F);
|
||
carry = (carry >> 4) & 1;
|
||
/* if (mapper18_irq_control[3] == 1'b0) */
|
||
if (!(mapper18_irq_control & 0x08))
|
||
{
|
||
/*carry = get_bits(mapper18_irq_value, "7:4") - carry; */
|
||
carry = ((mapper18_irq_value >> 4) & 0x0F) - carry; /*SET_BITS(mapper18_irq_value, "7:4", carry, "3:0"); */
|
||
mapper18_irq_value = (mapper18_irq_value & 0xFF0F) | ((carry & 0x0F) << 4);
|
||
carry = (carry >> 4) & 1;
|
||
}
|
||
/* if (mapper18_irq_control[3:2] == 2'b00) */
|
||
if (!(mapper18_irq_control & 0x0C))
|
||
{
|
||
/*carry = get_bits(mapper18_irq_value, "11:8") - carry; */
|
||
carry = ((mapper18_irq_value >> 8) & 0x0F) - carry;
|
||
/*SET_BITS(mapper18_irq_value, "11:8", carry, "3:0"); */
|
||
mapper18_irq_value = (mapper18_irq_value & 0xF0FF) | ((carry & 0x0F) << 8);
|
||
carry = (carry >> 4) & 1;
|
||
}
|
||
/* if (mapper18_irq_control[3:1] == 3'b000) */
|
||
if (!(mapper18_irq_control & 0x0E))
|
||
{
|
||
/*carry = get_bits(mapper18_irq_value, "15:12") - carry; */
|
||
carry = ((mapper18_irq_value >> 12) & 0x0F) - carry;
|
||
/*SET_BITS(mapper18_irq_value, "15:12", carry, "3:0"); */
|
||
mapper18_irq_value = (mapper18_irq_value & 0x0FFF) | ((carry & 0x0F) << 12);
|
||
carry = (carry >> 4) & 1;
|
||
}
|
||
if (carry)
|
||
X6502_IRQBegin(FCEU_IQEXT);
|
||
}
|
||
|
||
/* Mapper #65 - Irem's H3001
|
||
* if (mapper65_irq_enabled) */
|
||
if (mapper65_irq_enabled)
|
||
{
|
||
if (mapper65_irq_value != 0) /* if (mapper65_irq_value[15:0] != 0) */
|
||
{
|
||
mapper65_irq_value--; /* mapper65_irq_value[15:0] = mapper65_irq_value[15:0] - 1; */
|
||
if (!mapper65_irq_value)
|
||
X6502_IRQBegin(FCEU_IQEXT); /* if (mapper65_irq_value[15:0] == 0) irq_cpu_out = 1; */
|
||
}
|
||
}
|
||
|
||
/* Mapper #42 */
|
||
if (mapper42_irq_enabled)
|
||
{
|
||
/*mapper42_irq_value = set_bits(mapper42_irq_value, "14:0", get_bits(mapper42_irq_value, "14:0") + 1);
|
||
*if (get_bits(mapper42_irq_value, "14:13") == 0x03) */
|
||
mapper42_irq_value++;
|
||
if (mapper42_irq_value >> 15) mapper42_irq_value = 0;
|
||
if (((mapper42_irq_value >> 13) & 0x03) == 0x03)
|
||
X6502_IRQBegin(FCEU_IQEXT);
|
||
else
|
||
X6502_IRQEnd(FCEU_IQEXT);
|
||
}
|
||
|
||
/* Mapper #83 - Cony/Yoko */
|
||
if (mapper83_irq_enabled)
|
||
{
|
||
if (mapper83_irq_counter == 0) /* if (mapper83_irq_counter == 0) */
|
||
X6502_IRQBegin(FCEU_IQEXT); /* mapper83_irq_out <= 1; */
|
||
mapper83_irq_counter--; /* mapper83_irq_counter = mapper83_irq_counter - 1'b1; */
|
||
}
|
||
|
||
/* Mapper #67 - Sunsoft-3 */
|
||
if (mapper67_irq_enabled)
|
||
{
|
||
mapper67_irq_counter--; /* mapper67_irq_counter = mapper67_irq_counter - 1'b1; */
|
||
if (mapper67_irq_counter == 0xFFFF) /* if (mapper67_irq_counter == 16'hFFFF) */
|
||
{
|
||
X6502_IRQBegin(FCEU_IQEXT); /* mapper67_irq_out <= 1; // fire IRQ */
|
||
mapper67_irq_enabled = 0; /* mapper67_irq_enabled <= 0; // disable IRQ */
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
static void COOLGIRL_PPUHook(uint32 A) {
|
||
/* For TxROM */
|
||
if ((mapper == 0x14) && (flags & 1))
|
||
{
|
||
setmirror(MI_0 + (TKSMIR[(A & 0x1FFF) >> 10] >> 7));
|
||
}
|
||
|
||
/* Mapper #9 and #10 - MMC2 and MMC4 */
|
||
if (mapper == 0x11)
|
||
{
|
||
if ((A >> 4) == 0xFD) /* if (ppu_addr_in[13:3] == 11'b00111111011) ppu_latch0 = 0; */
|
||
{
|
||
ppu_latch0 = 0;
|
||
COOLGIRL_Sync_CHR();
|
||
}
|
||
if ((A >> 4) == 0xFE) /* if (ppu_addr_in[13:3] == 11'b00111111101) ppu_latch0 = 1; */
|
||
{
|
||
ppu_latch0 = 1;
|
||
COOLGIRL_Sync_CHR();
|
||
}
|
||
if ((A >> 4) == 0x1FD) /* if (ppu_addr_in[13:3] == 11'b01111111011) ppu_latch1 = 0; */
|
||
{
|
||
ppu_latch1 = 0;
|
||
COOLGIRL_Sync_CHR();
|
||
}
|
||
if ((A >> 4) == 0x1FE) /* if (ppu_addr_in[13:3] == 11'b01111111101) ppu_latch1 = 1; */
|
||
{
|
||
ppu_latch1 = 1;
|
||
COOLGIRL_Sync_CHR();
|
||
}
|
||
}
|
||
}
|
||
|
||
static void COOLGIRL_Reset(void) {
|
||
sram_enabled = 0;
|
||
sram_page = 0;
|
||
can_write_chr = 0;
|
||
map_rom_on_6000 = 0;
|
||
flags = 0;
|
||
mapper = 0;
|
||
can_write_flash = 0;
|
||
mirroring = 0;
|
||
four_screen = 0;
|
||
lockout = 0;
|
||
prg_base = 0;
|
||
prg_mask = 0xF8 << 14;
|
||
prg_mode = 0;
|
||
prg_bank_6000 = 0;
|
||
prg_bank_a = 0;
|
||
prg_bank_b = 1;
|
||
prg_bank_c = ~1;
|
||
prg_bank_d = ~0;
|
||
chr_mask = 0;
|
||
chr_mode = 0;
|
||
chr_bank_a = 0;
|
||
chr_bank_b = 1;
|
||
chr_bank_c = 2;
|
||
chr_bank_d = 3;
|
||
chr_bank_e = 4;
|
||
chr_bank_f = 5;
|
||
chr_bank_g = 6;
|
||
chr_bank_h = 7;
|
||
ppu_latch0 = 0;
|
||
ppu_latch1 = 0;
|
||
lreset = 0;
|
||
mmc1_load_register = 0;
|
||
mmc3_internal = 0;
|
||
mapper69_internal = 0;
|
||
mapper112_internal = 0;
|
||
mapper_163_latch = 0;
|
||
mapper163_r0 = 0;
|
||
mapper163_r1 = 0;
|
||
mapper163_r2 = 0;
|
||
mapper163_r3 = 0;
|
||
mapper163_r4 = 0;
|
||
mapper163_r5 = 0;
|
||
mul1 = 0;
|
||
mul2 = 0;
|
||
mmc3_irq_enabled = 0;
|
||
mmc3_irq_latch = 0;
|
||
mmc3_irq_counter = 0;
|
||
mmc3_irq_reload = 0;
|
||
mmc5_irq_enabled = 0;
|
||
mmc5_irq_line = 0;
|
||
mmc5_irq_out = 0;
|
||
mapper18_irq_value = 0;
|
||
mapper18_irq_control = 0;
|
||
mapper18_irq_latch = 0;
|
||
mapper65_irq_enabled = 0;
|
||
mapper65_irq_value = 0;
|
||
mapper65_irq_latch = 0;
|
||
mapper69_irq_enabled = 0;
|
||
mapper69_counter_enabled = 0;
|
||
mapper69_irq_value = 0;
|
||
vrc4_irq_value = 0;
|
||
vrc4_irq_control = 0;
|
||
vrc4_irq_latch = 0;
|
||
vrc4_irq_prescaler = 0;
|
||
vrc4_irq_prescaler_counter = 0;
|
||
vrc3_irq_value = 0;
|
||
vrc3_irq_control = 0;
|
||
vrc3_irq_latch = 0;
|
||
mapper42_irq_enabled = 0;
|
||
mapper42_irq_value = 0;
|
||
mapper90_xor = 0;
|
||
flash_state = 0;
|
||
cfi_mode = 0;
|
||
COOLGIRL_Sync();
|
||
}
|
||
|
||
static void COOLGIRL_Power(void) {
|
||
FCEU_CheatAddRAM(32, 0x6000, WRAM);
|
||
SetReadHandler(0x4020, 0x7FFF, MAFRAM);
|
||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||
SetWriteHandler(0x4020, 0xFFFF, COOLGIRL_WRITE);
|
||
GameHBIRQHook = COOLGIRL_ScanlineCounter;
|
||
MapIRQHook = COOLGIRL_CpuCounter;
|
||
PPU_hook = COOLGIRL_PPUHook;
|
||
COOLGIRL_Reset();
|
||
}
|
||
|
||
static void COOLGIRL_Close(void) {
|
||
if (WRAM)
|
||
FCEU_gfree(WRAM);
|
||
if (SAVE_FLASH)
|
||
FCEU_gfree(SAVE_FLASH);
|
||
if (CFI)
|
||
FCEU_gfree(CFI);
|
||
WRAM = SAVE_FLASH = CFI = NULL;
|
||
}
|
||
|
||
static void COOLGIRL_Restore(int version) {
|
||
COOLGIRL_Sync();
|
||
lreset = 0;
|
||
}
|
||
|
||
#define ExState(var, varname) AddExState(&var, sizeof(var), 0, varname)
|
||
|
||
void COOLGIRL_Init(CartInfo *info) {
|
||
size_t i;
|
||
CHR_SIZE = info->CHRRamSize;
|
||
|
||
WRAM_SIZE = (info->PRGRamSize + info->PRGRamSaveSize) ? (info->PRGRamSize + info->PRGRamSaveSize) : (32 * 1024);
|
||
if (WRAM_SIZE > 0) {
|
||
WRAM = (uint8*)FCEU_gmalloc(WRAM_SIZE);
|
||
memset(WRAM, 0, WRAM_SIZE);
|
||
SetupCartPRGMapping(WRAM_CHIP, WRAM, WRAM_SIZE, 1);
|
||
AddExState(WRAM, 32 * 1024, 0, "SRAM");
|
||
if (info->battery)
|
||
{
|
||
info->SaveGame[0] = WRAM;
|
||
info->SaveGameLen[0] = WRAM_SIZE;
|
||
}
|
||
}
|
||
|
||
if (info->battery)
|
||
{
|
||
SAVE_FLASH = (uint8*)FCEU_gmalloc(SAVE_FLASH_SIZE);
|
||
SetupCartPRGMapping(FLASH_CHIP, SAVE_FLASH, SAVE_FLASH_SIZE, 1);
|
||
info->SaveGame[1] = SAVE_FLASH;
|
||
info->SaveGameLen[1] = SAVE_FLASH_SIZE;
|
||
}
|
||
|
||
CFI = (uint8*)FCEU_gmalloc(sizeof(cfi_data) * 2);
|
||
for (i = 0; i < sizeof(cfi_data); i++)
|
||
CFI[i * 2] = CFI[i * 2 + 1] = cfi_data[i];
|
||
SetupCartPRGMapping(CFI_CHIP, CFI, sizeof(cfi_data) * 2, 0);
|
||
|
||
ExState(sram_enabled, "SREN");
|
||
ExState(sram_page, "SRPG");
|
||
ExState(can_write_chr, "SRWR");
|
||
ExState(map_rom_on_6000, "MR6K");
|
||
ExState(flags, "FLGS");
|
||
ExState(mapper, "MPPR");
|
||
ExState(can_write_flash, "FLWR");
|
||
ExState(mirroring, "MIRR");
|
||
ExState(four_screen, "4SCR");
|
||
ExState(lockout, "LOCK");
|
||
ExState(prg_base, "PBAS");
|
||
ExState(prg_mask, "PMSK");
|
||
ExState(prg_mode, "PMOD");
|
||
ExState(prg_bank_6000, "P6BN");
|
||
ExState(prg_bank_a, "PABN");
|
||
ExState(prg_bank_b, "PBBN");
|
||
ExState(prg_bank_c, "PCBN");
|
||
ExState(prg_bank_d, "PDBN");
|
||
ExState(chr_mask, "CMSK");
|
||
ExState(chr_mode, "CMOD");
|
||
ExState(chr_bank_a, "CABN");
|
||
ExState(chr_bank_b, "CBBN");
|
||
ExState(chr_bank_c, "CCBN");
|
||
ExState(chr_bank_d, "CDBN");
|
||
ExState(chr_bank_e, "CEBN");
|
||
ExState(chr_bank_f, "CFBN");
|
||
ExState(chr_bank_g, "CGBN");
|
||
ExState(chr_bank_h, "CHBN");
|
||
ExState(ppu_latch0, "PPU0");
|
||
ExState(ppu_latch1, "PPU1");
|
||
ExState(lreset, "LRST");
|
||
ExState(mmc1_load_register, "M01R");
|
||
ExState(mmc3_internal, "M01I");
|
||
ExState(mapper69_internal, "M69I");
|
||
ExState(mapper112_internal, "112I");
|
||
ExState(mapper_163_latch, "163L");
|
||
ExState(mapper163_r0, "1630");
|
||
ExState(mapper163_r1, "1631");
|
||
ExState(mapper163_r2, "1632");
|
||
ExState(mapper163_r3, "1633");
|
||
ExState(mapper163_r4, "1634");
|
||
ExState(mapper163_r5, "1635");
|
||
ExState(mul1, "MUL1");
|
||
ExState(mul2, "MUL2");
|
||
ExState(mmc3_irq_enabled, "M4IE");
|
||
ExState(mmc3_irq_latch, "M4IL");
|
||
ExState(mmc3_irq_counter, "M4IC");
|
||
ExState(mmc3_irq_reload, "M4IR");
|
||
ExState(mmc5_irq_enabled, "M5IE");
|
||
ExState(mmc5_irq_line, "M5IL");
|
||
ExState(mmc5_irq_out, "M5IO");
|
||
ExState(mapper18_irq_value, "18IV");
|
||
ExState(mapper18_irq_control, "18IC");
|
||
ExState(mapper18_irq_latch, "18IL");
|
||
ExState(mapper65_irq_enabled, "65IE");
|
||
ExState(mapper65_irq_value, "65IV");
|
||
ExState(mapper65_irq_latch, "65IL");
|
||
ExState(mapper69_irq_enabled, "69IE");
|
||
ExState(mapper69_counter_enabled, "69CE");
|
||
ExState(mapper69_irq_value, "69IV");
|
||
ExState(vrc4_irq_value, "V4IV");
|
||
ExState(vrc4_irq_control, "V4IC");
|
||
ExState(vrc4_irq_latch, "V4IL");
|
||
ExState(vrc4_irq_prescaler, "V4PP");
|
||
ExState(vrc4_irq_prescaler_counter, "V4PC");
|
||
ExState(vrc3_irq_value, "V3IV");
|
||
ExState(vrc3_irq_control, "V3IC");
|
||
ExState(vrc3_irq_latch, "V3IL");
|
||
ExState(mapper42_irq_enabled, "42IE");
|
||
ExState(mapper42_irq_value, "42IV");
|
||
ExState(mapper83_irq_enabled_latch, "M83L");
|
||
ExState(mapper83_irq_enabled, "M83I");
|
||
ExState(mapper83_irq_counter, "M83C");
|
||
ExState(mapper90_xor, "90XR");
|
||
ExState(mapper67_irq_enabled, "67IE");
|
||
ExState(mapper67_irq_latch, "67IL");
|
||
ExState(mapper67_irq_counter, "67IC");
|
||
ExState(flash_state, "FLST");
|
||
ExState(flash_buffer_a, "FLBA");
|
||
ExState(flash_buffer_v, "FLBV");
|
||
ExState(cfi_mode, "CFIM");
|
||
|
||
info->Power = COOLGIRL_Power;
|
||
info->Reset = COOLGIRL_Reset;
|
||
info->Close = COOLGIRL_Close;
|
||
GameStateRestore = COOLGIRL_Restore;
|
||
}
|