mirror of
https://github.com/holub/mame
synced 2025-04-20 23:42:22 +03:00
nes_slot.cpp: Unified CHR banking into a common function. (#9261)
* nes_slot.cpp: Unified CHR banking into a common function. - Removed PPU_MIRROR_NONE as an option for nametable mirroring. - Shrunk over-allocated 4-screen NT RAM to correct 4K size. - Sundry minor clean ups. - Only calculate start of bank once.
This commit is contained in:
parent
fff6c5e9fd
commit
09c4c23136
@ -2678,12 +2678,11 @@ void nes_bmc_jy208_device::write_m(offs_t offset, u8 data)
|
||||
nes_bmc_hik8_device::write_m(offset, data);
|
||||
|
||||
if (BIT(m_reg[2], 6))
|
||||
{
|
||||
set_nt_mirroring(PPU_MIRROR_4SCREEN); // actually change NT pointers
|
||||
m_mirroring = PPU_MIRROR_4SCREEN; // prevent MMC3 mirror switching
|
||||
}
|
||||
m_mirroring = PPU_MIRROR_4SCREEN; // prevent MMC3 mirror switching
|
||||
else
|
||||
m_mirroring = PPU_MIRROR_NONE; // allow MMC3 mirror switching
|
||||
m_mirroring = BIT(m_mmc_mirror, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT; // allow MMC3 mirror switching and get its current setting
|
||||
|
||||
set_nt_mirroring(m_mirroring); // actually change nametable pointers
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
|
@ -130,7 +130,7 @@ device_nes_cart_interface::device_nes_cart_interface(const machine_config &mconf
|
||||
, m_outer_prg_size(0)
|
||||
, m_outer_chr_size(0)
|
||||
, m_smd133_addr(0x6000)
|
||||
, m_mirroring(PPU_MIRROR_NONE)
|
||||
, m_mirroring(PPU_MIRROR_HORZ)
|
||||
, m_pcb_ctrl_mirror(false)
|
||||
, m_four_screen_vram(false)
|
||||
, m_has_trainer(false)
|
||||
@ -174,26 +174,24 @@ void device_nes_cart_interface::prg_alloc(size_t size, const char *tag)
|
||||
m_prg_chunks--;
|
||||
}
|
||||
|
||||
m_prg_mask = ((m_prg_chunks << 1) - 1);
|
||||
m_prg_mask = (m_prg_chunks << 1) - 1;
|
||||
|
||||
// printf("first mask %x!\n", m_prg_mask);
|
||||
if ((m_prg_chunks << 1) & m_prg_mask)
|
||||
{
|
||||
int mask_bits = 0, temp = (m_prg_chunks << 1), mapsize;
|
||||
int mask_bits = 0;
|
||||
// contrary to what happens with later systems, like e.g. SNES or MD,
|
||||
// only half a dozen of NES carts have PRG which is not a power of 2
|
||||
// so we use this bank_map only as an exception
|
||||
// printf("uneven rom!\n");
|
||||
|
||||
// 1. redefine mask as (next power of 2)-1
|
||||
for (; temp; )
|
||||
{
|
||||
for (int temp = m_prg_chunks << 1; temp; temp >>= 1)
|
||||
mask_bits++;
|
||||
temp >>= 1;
|
||||
}
|
||||
|
||||
m_prg_mask = (1 << mask_bits) - 1;
|
||||
// printf("new mask %x!\n", m_prg_mask);
|
||||
mapsize = (1 << mask_bits)/2;
|
||||
int mapsize = (1 << mask_bits) / 2;
|
||||
|
||||
// 2. create a bank_map for banks in the range mask/2 -> mask
|
||||
m_prg_bank_map.resize(mapsize);
|
||||
@ -206,7 +204,7 @@ void device_nes_cart_interface::prg_alloc(size_t size, const char *tag)
|
||||
while (j % mapsize)
|
||||
{
|
||||
int k = 0, repeat_banks;
|
||||
while ((j % (mapsize >> k)) && k < mask_bits)
|
||||
while (j % (mapsize >> k) && k < mask_bits)
|
||||
k++;
|
||||
repeat_banks = j % (mapsize >> (k - 1));
|
||||
for (int l = 0; l < repeat_banks; l++)
|
||||
@ -271,20 +269,20 @@ void device_nes_cart_interface::battery_alloc(size_t size)
|
||||
|
||||
inline int device_nes_cart_interface::prg_8k_bank_num(int bank_8k)
|
||||
{
|
||||
if (m_prg_mask == ((m_prg_chunks << 1) - 1))
|
||||
if (m_prg_mask == (m_prg_chunks << 1) - 1)
|
||||
return bank_8k & m_prg_mask;
|
||||
|
||||
// only a few pirate games (less than a dozen) have PRG which is not power of 2
|
||||
// so we treat it here separately, rather than forcing all games to use m_prg_bank_map
|
||||
|
||||
// case 1: if we are accessing a bank before the end of the image, just return that bank
|
||||
if (bank_8k < ((m_prg_chunks << 1) - 1))
|
||||
if (bank_8k < (m_prg_chunks << 1) - 1)
|
||||
return bank_8k;
|
||||
|
||||
// case 2: otherwise return a mirror using the bank_map!
|
||||
// uint8_t temp = bank_8k;
|
||||
bank_8k &= m_prg_mask;
|
||||
bank_8k -= (m_prg_mask/2 + 1);
|
||||
bank_8k -= m_prg_mask / 2 + 1;
|
||||
// printf("bank: accessed %x (top: %x), returned %x\n", temp, (m_prg_chunks << 1) - 1, m_prg_bank_map[bank_8k]);
|
||||
return m_prg_bank_map[bank_8k];
|
||||
}
|
||||
@ -303,11 +301,11 @@ inline void device_nes_cart_interface::update_prg_banks(int prg_bank_start, int
|
||||
|
||||
void device_nes_cart_interface::prg32(int bank)
|
||||
{
|
||||
/* if there is only 16k PRG, return */
|
||||
// if there is only 16k PRG, return
|
||||
if (!(m_prg_chunks >> 1))
|
||||
return;
|
||||
|
||||
/* assumes that bank references a 32k chunk */
|
||||
// assumes that bank references a 32k chunk
|
||||
bank = prg_8k_bank_num(bank * 4);
|
||||
|
||||
m_prg_bank[0] = bank + 0;
|
||||
@ -319,7 +317,7 @@ void device_nes_cart_interface::prg32(int bank)
|
||||
|
||||
void device_nes_cart_interface::prg16_89ab(int bank)
|
||||
{
|
||||
/* assumes that bank references a 16k chunk */
|
||||
// assumes that bank references a 16k chunk
|
||||
bank = prg_8k_bank_num(bank * 2);
|
||||
|
||||
m_prg_bank[0] = bank + 0;
|
||||
@ -329,7 +327,7 @@ void device_nes_cart_interface::prg16_89ab(int bank)
|
||||
|
||||
void device_nes_cart_interface::prg16_cdef(int bank)
|
||||
{
|
||||
/* assumes that bank references a 16k chunk */
|
||||
// assumes that bank references a 16k chunk
|
||||
bank = prg_8k_bank_num(bank * 2);
|
||||
|
||||
m_prg_bank[2] = bank + 0;
|
||||
@ -353,110 +351,36 @@ void device_nes_cart_interface::prg8_x(int start, int bank)
|
||||
// CHR helpers
|
||||
//-------------------------------------------------
|
||||
|
||||
inline void device_nes_cart_interface::chr_sanity_check( int source )
|
||||
void device_nes_cart_interface::bank_chr(int shift, int start, int bank, int source)
|
||||
{
|
||||
if (source == CHRRAM && m_vram.empty())
|
||||
fatalerror("CHRRAM bankswitch with no VRAM\n");
|
||||
|
||||
if (source == CHRROM && m_vrom == nullptr)
|
||||
fatalerror("CHRROM bankswitch with no VROM\n");
|
||||
}
|
||||
|
||||
void device_nes_cart_interface::chr8(int bank, int source)
|
||||
{
|
||||
chr_sanity_check(source);
|
||||
uint8_t *base_ptr;
|
||||
uint32_t chr_chunks;
|
||||
|
||||
if (source == CHRRAM)
|
||||
{
|
||||
bank &= (m_vram_chunks - 1);
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
m_chr_src[i] = source;
|
||||
m_chr_orig[i] = (bank * 0x2000) + (i * 0x400); // for save state uses!
|
||||
m_chr_access[i] = &m_vram[m_chr_orig[i]];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bank &= (m_vrom_chunks - 1);
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
m_chr_src[i] = source;
|
||||
m_chr_orig[i] = (bank * 0x2000) + (i * 0x400); // for save state uses!
|
||||
m_chr_access[i] = &m_vrom[m_chr_orig[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(!m_vram.empty());
|
||||
|
||||
void device_nes_cart_interface::chr4_x(int start, int bank, int source)
|
||||
{
|
||||
chr_sanity_check(source);
|
||||
|
||||
if (source == CHRRAM)
|
||||
{
|
||||
bank &= ((m_vram_chunks << 1) - 1);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
m_chr_src[i + start] = source;
|
||||
m_chr_orig[i + start] = (bank * 0x1000) + (i * 0x400); // for save state uses!
|
||||
m_chr_access[i + start] = &m_vram[m_chr_orig[i + start]];
|
||||
}
|
||||
base_ptr = &m_vram[0];
|
||||
chr_chunks = m_vram_chunks;
|
||||
}
|
||||
else
|
||||
else // source == CHRROM
|
||||
{
|
||||
bank &= ((m_vrom_chunks << 1) - 1);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
m_chr_src[i + start] = source;
|
||||
m_chr_orig[i + start] = (bank * 0x1000) + (i * 0x400); // for save state uses!
|
||||
m_chr_access[i + start] = &m_vrom[m_chr_orig[i + start]];
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(m_vrom != nullptr);
|
||||
|
||||
void device_nes_cart_interface::chr2_x(int start, int bank, int source)
|
||||
{
|
||||
chr_sanity_check(source);
|
||||
|
||||
if (source == CHRRAM)
|
||||
{
|
||||
bank &= ((m_vram_chunks << 2) - 1);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
m_chr_src[i + start] = source;
|
||||
m_chr_orig[i + start] = (bank * 0x800) + (i * 0x400); // for save state uses!
|
||||
m_chr_access[i + start] = &m_vram[m_chr_orig[i + start]];
|
||||
}
|
||||
base_ptr = m_vrom;
|
||||
chr_chunks = m_vrom_chunks;
|
||||
}
|
||||
else
|
||||
{
|
||||
bank &= ((m_vrom_chunks << 2) - 1);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
m_chr_src[i + start] = source;
|
||||
m_chr_orig[i + start] = (bank * 0x800) + (i * 0x400); // for save state uses!
|
||||
m_chr_access[i + start] = &m_vrom[m_chr_orig[i + start]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void device_nes_cart_interface::chr1_x(int start, int bank, int source)
|
||||
{
|
||||
chr_sanity_check(source);
|
||||
bank &= (chr_chunks << (3 - shift)) - 1;
|
||||
int size = 0x400 << shift;
|
||||
int bank_start = bank * size;
|
||||
int kbyte = 1 << shift;
|
||||
|
||||
if (source == CHRRAM)
|
||||
for (int i = 0; i < kbyte; i++)
|
||||
{
|
||||
bank &= ((m_vram_chunks << 3) - 1);
|
||||
m_chr_src[start] = source;
|
||||
m_chr_orig[start] = (bank * 0x400); // for save state uses!
|
||||
m_chr_access[start] = &m_vram[m_chr_orig[start]];
|
||||
}
|
||||
else
|
||||
{
|
||||
bank &= ((m_vrom_chunks << 3) - 1);
|
||||
m_chr_src[start] = source;
|
||||
m_chr_orig[start] = (bank * 0x400); // for save state uses!
|
||||
m_chr_access[start] = &m_vrom[m_chr_orig[start]];
|
||||
m_chr_src[i + start] = source;
|
||||
m_chr_orig[i + start] = bank_start + i * 0x400; // for save state uses!
|
||||
m_chr_access[i + start] = &base_ptr[m_chr_orig[i + start]];
|
||||
}
|
||||
}
|
||||
|
||||
@ -466,7 +390,7 @@ void device_nes_cart_interface::chr1_x(int start, int bank, int source)
|
||||
|
||||
void device_nes_cart_interface::set_nt_page(int page, int source, int bank, int writable)
|
||||
{
|
||||
uint8_t* base_ptr;
|
||||
uint8_t *base_ptr;
|
||||
|
||||
switch (source)
|
||||
{
|
||||
@ -474,7 +398,7 @@ void device_nes_cart_interface::set_nt_page(int page, int source, int bank, int
|
||||
base_ptr = &m_ext_ntram[0];
|
||||
break;
|
||||
case VROM:
|
||||
bank &= ((m_vrom_chunks << 3) - 1);
|
||||
bank &= (m_vrom_chunks << 3) - 1;
|
||||
base_ptr = m_vrom;
|
||||
break;
|
||||
case EXRAM:
|
||||
@ -487,7 +411,7 @@ void device_nes_cart_interface::set_nt_page(int page, int source, int bank, int
|
||||
break;
|
||||
}
|
||||
|
||||
page &= 3; /* mask down to the 4 logical pages */
|
||||
page &= 3; // mask down to the 4 logical pages
|
||||
m_nt_src[page] = source;
|
||||
|
||||
if (base_ptr)
|
||||
@ -501,16 +425,10 @@ void device_nes_cart_interface::set_nt_page(int page, int source, int bank, int
|
||||
|
||||
void device_nes_cart_interface::set_nt_mirroring(int mirroring)
|
||||
{
|
||||
/* setup our videomem handlers based on mirroring */
|
||||
// setup our videomem handlers based on mirroring
|
||||
switch (mirroring)
|
||||
{
|
||||
case PPU_MIRROR_VERT:
|
||||
set_nt_page(0, CIRAM, 0, 1);
|
||||
set_nt_page(1, CIRAM, 1, 1);
|
||||
set_nt_page(2, CIRAM, 0, 1);
|
||||
set_nt_page(3, CIRAM, 1, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
case PPU_MIRROR_HORZ:
|
||||
set_nt_page(0, CIRAM, 0, 1);
|
||||
set_nt_page(1, CIRAM, 0, 1);
|
||||
@ -518,6 +436,13 @@ void device_nes_cart_interface::set_nt_mirroring(int mirroring)
|
||||
set_nt_page(3, CIRAM, 1, 1);
|
||||
break;
|
||||
|
||||
case PPU_MIRROR_VERT:
|
||||
set_nt_page(0, CIRAM, 0, 1);
|
||||
set_nt_page(1, CIRAM, 1, 1);
|
||||
set_nt_page(2, CIRAM, 0, 1);
|
||||
set_nt_page(3, CIRAM, 1, 1);
|
||||
break;
|
||||
|
||||
case PPU_MIRROR_HIGH:
|
||||
set_nt_page(0, CIRAM, 1, 1);
|
||||
set_nt_page(1, CIRAM, 1, 1);
|
||||
@ -539,14 +464,6 @@ void device_nes_cart_interface::set_nt_mirroring(int mirroring)
|
||||
set_nt_page(2, CART_NTRAM, 2, 1);
|
||||
set_nt_page(3, CART_NTRAM, 3, 1);
|
||||
break;
|
||||
|
||||
case PPU_MIRROR_NONE:
|
||||
default:
|
||||
set_nt_page(0, CIRAM, 0, 1);
|
||||
set_nt_page(1, CIRAM, 0, 1);
|
||||
set_nt_page(2, CIRAM, 1, 1);
|
||||
set_nt_page(3, CIRAM, 1, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -623,7 +540,7 @@ uint8_t device_nes_cart_interface::chr_r(offs_t offset)
|
||||
|
||||
void device_nes_cart_interface::nt_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
int page = ((offset & 0xc00) >> 10);
|
||||
int page = (offset & 0xc00) >> 10;
|
||||
|
||||
if (!m_nt_writable[page])
|
||||
return;
|
||||
@ -633,7 +550,7 @@ void device_nes_cart_interface::nt_w(offs_t offset, uint8_t data)
|
||||
|
||||
uint8_t device_nes_cart_interface::nt_r(offs_t offset)
|
||||
{
|
||||
int page = ((offset & 0xc00) >> 10);
|
||||
int page = (offset & 0xc00) >> 10;
|
||||
return m_nt_access[page][offset & 0x3ff];
|
||||
}
|
||||
|
||||
@ -708,7 +625,7 @@ void device_nes_cart_interface::pcb_start(running_machine &machine, uint8_t *cir
|
||||
|
||||
if (m_four_screen_vram)
|
||||
{
|
||||
m_ext_ntram.resize(0x2000);
|
||||
m_ext_ntram.resize(0x1000);
|
||||
device().save_item(NAME(m_ext_ntram));
|
||||
}
|
||||
|
||||
@ -803,7 +720,7 @@ void nes_cart_slot_device::pcb_reset()
|
||||
|
||||
-------------------------------------------------*/
|
||||
|
||||
/* Include emulation of NES PCBs for softlist */
|
||||
// Include emulation of NES PCBs for softlist
|
||||
#include "nes_pcb.hxx"
|
||||
|
||||
|
||||
@ -813,7 +730,7 @@ void nes_cart_slot_device::pcb_reset()
|
||||
|
||||
-------------------------------------------------*/
|
||||
|
||||
/* Include emulation of UNIF Boards for .unf files */
|
||||
// Include emulation of UNIF Boards for .unf files
|
||||
#include "nes_unif.hxx"
|
||||
|
||||
|
||||
@ -823,7 +740,7 @@ void nes_cart_slot_device::pcb_reset()
|
||||
|
||||
-------------------------------------------------*/
|
||||
|
||||
/* Include emulation of iNES Mappers for .nes files */
|
||||
// Include emulation of iNES Mappers for .nes files
|
||||
#include "nes_ines.hxx"
|
||||
|
||||
|
||||
@ -835,11 +752,11 @@ image_init_result nes_cart_slot_device::call_load()
|
||||
{
|
||||
char magic[4];
|
||||
|
||||
/* Check first 4 bytes of the image to decide if it is UNIF or iNES */
|
||||
/* Unfortunately, many .unf files have been released as .nes, so we cannot rely on extensions only */
|
||||
// Check first 4 bytes of the image to decide if it is UNIF or iNES
|
||||
// Unfortunately, many .unf files have been released as .nes, so we cannot rely on extensions only
|
||||
fread(magic, 4);
|
||||
|
||||
if ((magic[0] == 'N') && (magic[1] == 'E') && (magic[2] == 'S')) /* If header starts with 'NES' it is iNES */
|
||||
if ((magic[0] == 'N') && (magic[1] == 'E') && (magic[2] == 'S')) // If header starts with 'NES' it is iNES
|
||||
{
|
||||
if (length() <= 0x10)
|
||||
{
|
||||
@ -849,7 +766,7 @@ image_init_result nes_cart_slot_device::call_load()
|
||||
|
||||
call_load_ines();
|
||||
}
|
||||
else if ((magic[0] == 'U') && (magic[1] == 'N') && (magic[2] == 'I') && (magic[3] == 'F')) /* If header starts with 'UNIF' it is UNIF */
|
||||
else if ((magic[0] == 'U') && (magic[1] == 'N') && (magic[2] == 'I') && (magic[3] == 'F')) // If header starts with 'UNIF' it is UNIF
|
||||
{
|
||||
if (length() <= 0x20)
|
||||
{
|
||||
|
@ -170,7 +170,6 @@ enum
|
||||
#define CART_NTRAM 4
|
||||
|
||||
|
||||
#define PPU_MIRROR_NONE 0
|
||||
#define PPU_MIRROR_VERT 1
|
||||
#define PPU_MIRROR_HORZ 2
|
||||
#define PPU_MIRROR_HIGH 3
|
||||
@ -334,7 +333,6 @@ public:
|
||||
|
||||
// CHR
|
||||
int m_chr_source; // global source for the 8 VROM banks
|
||||
inline void chr_sanity_check(int source);
|
||||
|
||||
//these were previously called chr_map. they are a quick banking structure,
|
||||
//because some of these change multiple times per scanline!
|
||||
@ -346,24 +344,27 @@ public:
|
||||
uint32_t m_vram_chunks;
|
||||
|
||||
// CHR helpers
|
||||
void chr8(int bank, int source);
|
||||
void chr4_x(int start, int bank, int source);
|
||||
void chr4_0(int bank, int source) { chr4_x(0, bank, source); }
|
||||
void chr4_4(int bank, int source) { chr4_x(4, bank, source); }
|
||||
void chr2_x(int start, int bank, int source);
|
||||
void chr2_0(int bank, int source) { chr2_x(0, bank, source); }
|
||||
void chr2_2(int bank, int source) { chr2_x(2, bank, source); }
|
||||
void chr2_4(int bank, int source) { chr2_x(4, bank, source); }
|
||||
void chr2_6(int bank, int source) { chr2_x(6, bank, source); }
|
||||
void chr1_x(int start, int bank, int source);
|
||||
void chr1_0(int bank, int source) { chr1_x(0, bank, source); }
|
||||
void chr1_1(int bank, int source) { chr1_x(1, bank, source); }
|
||||
void chr1_2(int bank, int source) { chr1_x(2, bank, source); }
|
||||
void chr1_3(int bank, int source) { chr1_x(3, bank, source); }
|
||||
void chr1_4(int bank, int source) { chr1_x(4, bank, source); }
|
||||
void chr1_5(int bank, int source) { chr1_x(5, bank, source); }
|
||||
void chr1_6(int bank, int source) { chr1_x(6, bank, source); }
|
||||
void chr1_7(int bank, int source) { chr1_x(7, bank, source); }
|
||||
private:
|
||||
void bank_chr(int shift, int start, int bank, int source);
|
||||
public:
|
||||
void chr8(int bank, int source) { bank_chr(3, 0, bank, source); }
|
||||
void chr4_x(int start, int bank, int source) { bank_chr(2, start, bank, source); }
|
||||
void chr4_0(int bank, int source) { bank_chr(2, 0, bank, source); }
|
||||
void chr4_4(int bank, int source) { bank_chr(2, 4, bank, source); }
|
||||
void chr2_x(int start, int bank, int source) { bank_chr(1, start, bank, source); }
|
||||
void chr2_0(int bank, int source) { bank_chr(1, 0, bank, source); }
|
||||
void chr2_2(int bank, int source) { bank_chr(1, 2, bank, source); }
|
||||
void chr2_4(int bank, int source) { bank_chr(1, 4, bank, source); }
|
||||
void chr2_6(int bank, int source) { bank_chr(1, 6, bank, source); }
|
||||
void chr1_x(int start, int bank, int source) { bank_chr(0, start, bank, source); }
|
||||
void chr1_0(int bank, int source) { bank_chr(0, 0, bank, source); }
|
||||
void chr1_1(int bank, int source) { bank_chr(0, 1, bank, source); }
|
||||
void chr1_2(int bank, int source) { bank_chr(0, 2, bank, source); }
|
||||
void chr1_3(int bank, int source) { bank_chr(0, 3, bank, source); }
|
||||
void chr1_4(int bank, int source) { bank_chr(0, 4, bank, source); }
|
||||
void chr1_5(int bank, int source) { bank_chr(0, 5, bank, source); }
|
||||
void chr1_6(int bank, int source) { bank_chr(0, 6, bank, source); }
|
||||
void chr1_7(int bank, int source) { bank_chr(0, 7, bank, source); }
|
||||
|
||||
|
||||
// NameTable & Mirroring
|
||||
|
Loading…
Reference in New Issue
Block a user