mirror of
https://github.com/wavemotion-dave/NINTV-DS.git
synced 2025-06-18 13:55:33 -04:00
83 lines
3.6 KiB
C++
83 lines
3.6 KiB
C++
// =====================================================================================
|
|
// Copyright (c) 2021-2023 Dave Bernazzani (wavemotion-dave)
|
|
//
|
|
// Copying and distribution of this emulator, its source code and associated
|
|
// readme files, with or without modification, are permitted in any medium without
|
|
// royalty provided the this copyright notice is used and wavemotion-dave (NINTV-DS)
|
|
// and Kyle Davis (BLISS) are thanked profusely.
|
|
//
|
|
// The NINTV-DS emulator is offered as-is, without any warranty.
|
|
// =====================================================================================
|
|
|
|
#include <nds.h>
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "ROMBanker.h"
|
|
#include "Emulator.h"
|
|
|
|
extern Emulator *currentEmu;
|
|
|
|
UINT16 gLastBankers[16] = {0}; // We use this to know what the last enabled bank write value was for each 4K page. Needed when we restore a saved state.
|
|
UINT8 gBankerIsMappedHere[16][16] = {0}; // We use this matrix to know if a 4K page has banking logic. This lets us speed up page in/out processing and handle games where there is a non-paged bank overlapping with paged banks (which is OK so long as the paged banks are all flipped out)
|
|
|
|
ROMBanker::ROMBanker(ROM* r, UINT16 address, UINT16 tm, UINT16 t, UINT16 mm, UINT16 m)
|
|
: RAM(1, address, 0, 0xFFFF),
|
|
rom(r),
|
|
triggerMask(tm),
|
|
trigger(t),
|
|
matchMask(mm),
|
|
match(m)
|
|
{
|
|
// Keep track of ROM bankers
|
|
gBankerIsMappedHere[address>>12][m] = 1;
|
|
pokeCount = 0;
|
|
}
|
|
|
|
void ROMBanker::reset()
|
|
{
|
|
rom->SetEnabled(match == 0);
|
|
memset(gLastBankers, 0x00, sizeof(gLastBankers));
|
|
pokeCount = 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------
|
|
// From intvnut on AtariAge:
|
|
// Each 4K segment in memory can have up to 16 different 4K ROM pages mapped to it.
|
|
// After "reset", all switched segments much switch to page 0. To switch pages within
|
|
// a given 4K segment, write the value $xA5y to location $xFFF, where 'x' is the upper
|
|
// 4 bits of the range you want to switch, and 'y' is the page number to switch to.
|
|
// This will switch the ROM in segment $x000 - $xFFF to page 'y'.
|
|
// If there's no ROM mapped to that page within that segment, then to the Intellivision,
|
|
// it will look like there's no ROM there.
|
|
// ----------------------------------------------------------------------------------------------
|
|
ITCM_CODE void ROMBanker::poke(UINT16 address, UINT16 value)
|
|
{
|
|
if ((value & triggerMask) == trigger)
|
|
{
|
|
bool bEnabled = ((value & matchMask) == match);
|
|
if (bEnabled != rom->IsEnabled())
|
|
{
|
|
rom->SetEnabled(bEnabled);
|
|
if (bEnabled) // If we are enabling this bank, we can quickly refresh the fast_memory[]
|
|
{
|
|
UINT16 *fast_memory = (UINT16 *)0x06860000;
|
|
for (int i=(address&0xF000); i<=((address&0xF000)|0xFFF); i++)
|
|
{
|
|
fast_memory[i] = rom->peek_fast(i&0xFFF);
|
|
}
|
|
}
|
|
else if (gBankerIsMappedHere[address>>12][value&0xF] == 0) // Nothing is here... nothing will be swapped in... We need to check the main memory as there may be an unswapped bank in there...
|
|
{
|
|
UINT16 *fast_memory = (UINT16 *)0x06860000;
|
|
for (int i=(address&0xF000); i<=((address&0xF000)|0xFFF); i++)
|
|
{
|
|
fast_memory[i] = currentEmu->memoryBus.peek_slow(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
gLastBankers[(address&0xF000)>>12] = value;
|
|
}
|
|
}
|