mirror of https://github.com/stella-emu/stella.git
More peek/poke refactoring, and improved comments in bankswitching schemes.
This commit is contained in:
parent
68f80f04d9
commit
31907f4be1
|
@ -102,7 +102,7 @@ void CartridgeDFSCWidget::saveOldState()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeDFSCWidget::loadConfig()
|
||||
{
|
||||
myBank->setSelectedIndex(myCart.myCurrentBank);
|
||||
myBank->setSelectedIndex(myCart.getBank());
|
||||
|
||||
CartDebugWidget::loadConfig();
|
||||
}
|
||||
|
@ -131,8 +131,8 @@ string CartridgeDFSCWidget::bankState()
|
|||
"$FFD0", "$FFD1", "$FFD2", "$FFD3", "$FFD4", "$FFD5", "$FFD6", "$FFE7",
|
||||
"$FFD8", "$FFD9", "$FFDA", "$FFDB", "$FFDC", "$FFDD", "$FFDE", "$FFDF"
|
||||
};
|
||||
buf << "Bank = " << std::dec << myCart.myCurrentBank
|
||||
<< ", hotspot = " << spot[myCart.myCurrentBank];
|
||||
buf << "Bank = " << std::dec << myCart.getBank()
|
||||
<< ", hotspot = " << spot[myCart.getBank()];
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ CartridgeDFWidget::CartridgeDFWidget(
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeDFWidget::loadConfig()
|
||||
{
|
||||
myBank->setSelectedIndex(myCart.myCurrentBank);
|
||||
myBank->setSelectedIndex(myCart.getBank());
|
||||
|
||||
CartDebugWidget::loadConfig();
|
||||
}
|
||||
|
@ -118,8 +118,8 @@ string CartridgeDFWidget::bankState()
|
|||
"$FFD0", "$FFD1", "$FFD2", "$FFD3", "$FFD4", "$FFD5", "$FFD6", "$FFD7",
|
||||
"$FFD8", "$FFD9", "$FFDA", "$FFDB", "$FFDC", "$FFDD", "$FFDE", "$FFDF"
|
||||
};
|
||||
buf << "Bank = " << std::dec << myCart.myCurrentBank
|
||||
<< ", hotspot = " << spot[myCart.myCurrentBank];
|
||||
buf << "Bank = " << std::dec << myCart.getBank()
|
||||
<< ", hotspot = " << spot[myCart.getBank()];
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
|
|
@ -218,7 +218,7 @@ void CartridgeDPCPlusWidget::saveOldState()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeDPCPlusWidget::loadConfig()
|
||||
{
|
||||
myBank->setSelectedIndex(myCart.myCurrentBank);
|
||||
myBank->setSelectedIndex(myCart.getBank());
|
||||
|
||||
// Get registers, using change tracking
|
||||
IntArray alist;
|
||||
|
@ -327,8 +327,8 @@ string CartridgeDPCPlusWidget::bankState()
|
|||
static const char* const spot[] = {
|
||||
"$FFF6", "$FFF7", "$FFF8", "$FFF9", "$FFFA", "$FFFB"
|
||||
};
|
||||
buf << "Bank = " << std::dec << myCart.myCurrentBank
|
||||
<< ", hotspot = " << spot[myCart.myCurrentBank];
|
||||
buf << "Bank = " << std::dec << myCart.getBank()
|
||||
<< ", hotspot = " << spot[myCart.getBank()];
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ void CartridgeDPCWidget::saveOldState()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeDPCWidget::loadConfig()
|
||||
{
|
||||
myBank->setSelectedIndex(myCart.myCurrentBank);
|
||||
myBank->setSelectedIndex(myCart.getBank());
|
||||
|
||||
// Get registers, using change tracking
|
||||
IntArray alist;
|
||||
|
@ -228,8 +228,8 @@ string CartridgeDPCWidget::bankState()
|
|||
ostringstream& buf = buffer();
|
||||
|
||||
static const char* const spot[] = { "$FFF8", "$FFF9" };
|
||||
buf << "Bank = " << std::dec << myCart.myCurrentBank
|
||||
<< ", hotspot = " << spot[myCart.myCurrentBank];
|
||||
buf << "Bank = " << std::dec << myCart.getBank()
|
||||
<< ", hotspot = " << spot[myCart.getBank()];
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ void CartridgeEFSCWidget::saveOldState()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeEFSCWidget::loadConfig()
|
||||
{
|
||||
myBank->setSelectedIndex(myCart.myCurrentBank);
|
||||
myBank->setSelectedIndex(myCart.getBank());
|
||||
|
||||
CartDebugWidget::loadConfig();
|
||||
}
|
||||
|
@ -113,8 +113,8 @@ string CartridgeEFSCWidget::bankState()
|
|||
"$FFE0", "$FFE1", "$FFE2", "$FFE3", "$FFE4", "$FFE5", "$FFE6", "$FFE7",
|
||||
"$FFE8", "$FFE9", "$FFEA", "$FFEB", "$FFEC", "$FFED", "$FFEE", "$FFEF"
|
||||
};
|
||||
buf << "Bank = " << std::dec << myCart.myCurrentBank
|
||||
<< ", hotspot = " << spot[myCart.myCurrentBank];
|
||||
buf << "Bank = " << std::dec << myCart.getBank()
|
||||
<< ", hotspot = " << spot[myCart.getBank()];
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ CartridgeEFWidget::CartridgeEFWidget(
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeEFWidget::loadConfig()
|
||||
{
|
||||
myBank->setSelectedIndex(myCart.myCurrentBank);
|
||||
myBank->setSelectedIndex(myCart.getBank());
|
||||
|
||||
CartDebugWidget::loadConfig();
|
||||
}
|
||||
|
@ -100,8 +100,8 @@ string CartridgeEFWidget::bankState()
|
|||
"$FFE0", "$FFE1", "$FFE2", "$FFE3", "$FFE4", "$FFE5", "$FFE6", "$FFE7",
|
||||
"$FFE8", "$FFE9", "$FFEA", "$FFEB", "$FFEC", "$FFED", "$FFEE", "$FFEF"
|
||||
};
|
||||
buf << "Bank = " << std::dec << myCart.myCurrentBank
|
||||
<< ", hotspot = " << spot[myCart.myCurrentBank];
|
||||
buf << "Bank = " << std::dec << myCart.getBank()
|
||||
<< ", hotspot = " << spot[myCart.getBank()];
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ CartridgeF0Widget::CartridgeF0Widget(
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeF0Widget::loadConfig()
|
||||
{
|
||||
myBank->setSelectedIndex(myCart.myCurrentBank);
|
||||
myBank->setSelectedIndex(myCart.getBank());
|
||||
|
||||
CartDebugWidget::loadConfig();
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ string CartridgeF0Widget::bankState()
|
|||
{
|
||||
ostringstream& buf = buffer();
|
||||
|
||||
buf << "Bank = " << std::dec << myCart.myCurrentBank << ", hotspot = $FFF0";
|
||||
buf << "Bank = " << std::dec << myCart.getBank() << ", hotspot = $FFF0";
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
|
|
@ -31,11 +31,8 @@ Cartridge2K::Cartridge2K(const BytePtr& image, uInt32 size,
|
|||
while(mySize < size)
|
||||
mySize <<= 1;
|
||||
|
||||
// The smallest addressable area by Stella is 64 bytes
|
||||
// This should really be read from the System, but for now I'm going
|
||||
// to cheat a little and hard-code it to 64 (aka 2^6)
|
||||
if(mySize < 64)
|
||||
mySize = 64;
|
||||
// We can't use a size smaller than the minimum page size in Stella
|
||||
mySize = std::max(mySize, 1u << System::PAGE_SHIFT);
|
||||
|
||||
// Initialize ROM with illegal 6502 opcode that causes a real 6502 to jam
|
||||
myImage = make_unique<uInt8[]>(mySize);
|
||||
|
@ -62,6 +59,8 @@ void Cartridge2K::install(System& system)
|
|||
mySystem = &system;
|
||||
|
||||
// Map ROM image into the system
|
||||
// Note that we don't need our own peek/poke methods, since the mapping
|
||||
// takes care of the entire address space
|
||||
System::PageAccess access(this, System::PA_READ);
|
||||
for(uInt32 address = 0x1000; address < 0x2000; address += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
|
|
|
@ -27,11 +27,12 @@ class System;
|
|||
#endif
|
||||
|
||||
/**
|
||||
This is the standard Atari 2K cartridge. These cartridges
|
||||
are not bankswitched, however, the data repeats twice in the
|
||||
2600's 4K cartridge addressing space.
|
||||
This is the standard Atari 2K cartridge. These cartridges are not
|
||||
bankswitched, however, the data repeats twice in the 2600's 4K cartridge
|
||||
addressing space. For 'Sub2K' ROMs (ROMs less than 2K in size), the
|
||||
data repeats in intervals based on the size of the ROM.
|
||||
|
||||
@author Bradford W. Mott
|
||||
@author Stephen Anthony
|
||||
*/
|
||||
class Cartridge2K : public Cartridge
|
||||
{
|
||||
|
|
|
@ -40,6 +40,8 @@ void Cartridge4K::install(System& system)
|
|||
mySystem = &system;
|
||||
|
||||
// Map ROM image into the system
|
||||
// Note that we don't need our own peek/poke methods, since the mapping
|
||||
// takes care of the entire address space
|
||||
System::PageAccess access(this, System::PA_READ);
|
||||
for(uInt32 address = 0x1000; address < 0x2000;
|
||||
address += (1 << System::PAGE_SHIFT))
|
||||
|
|
|
@ -28,6 +28,7 @@ class System;
|
|||
|
||||
/**
|
||||
Cartridge class used for 4K games with 128 bytes of RAM.
|
||||
RAM read port is $1080 - $10FF, write port is $1000 - $107F.
|
||||
*/
|
||||
|
||||
class Cartridge4KSC : public Cartridge
|
||||
|
|
|
@ -29,6 +29,7 @@ class System;
|
|||
/**
|
||||
There are 64 4K banks (total of 256K ROM) with 128 bytes of RAM.
|
||||
Accessing $1F80 - $1FBF switches to each bank.
|
||||
RAM read port is $1080 - $10FF, write port is $1000 - $107F.
|
||||
|
||||
@author Stephen Anthony
|
||||
*/
|
||||
|
|
|
@ -29,98 +29,98 @@ class CartridgeDASHWidget;
|
|||
#endif
|
||||
|
||||
/**
|
||||
Cartridge class for new tiling engine "Boulder Dash" format games with RAM.
|
||||
Kind of a combination of 3F and 3E, with better switchability.
|
||||
B.Watson's Cart3E was used as a template for building this implementation.
|
||||
Cartridge class for new tiling engine "Boulder Dash" format games with RAM.
|
||||
Kind of a combination of 3F and 3E, with better switchability.
|
||||
B.Watson's Cart3E was used as a template for building this implementation.
|
||||
|
||||
The destination bank (0-3) is held in the top bits of the value written to
|
||||
$3E (for RAM switching) or $3F (for ROM switching). The low 6 bits give
|
||||
the actual bank number (0-63) corresponding to 512 byte blocks for RAM and
|
||||
1024 byte blocks for ROM. The maximum size is therefore 32K RAM and 64K ROM.
|
||||
The destination bank (0-3) is held in the top bits of the value written to
|
||||
$3E (for RAM switching) or $3F (for ROM switching). The low 6 bits give
|
||||
the actual bank number (0-63) corresponding to 512 byte blocks for RAM and
|
||||
1024 byte blocks for ROM. The maximum size is therefore 32K RAM and 64K ROM.
|
||||
|
||||
D7D6 indicate the bank number (0-3)
|
||||
D5D4D3D2D1D0 indicate the actual # (0-63) from the image/ram
|
||||
D7D6 indicate the bank number (0-3)
|
||||
D5D4D3D2D1D0 indicate the actual # (0-63) from the image/ram
|
||||
|
||||
ROM:
|
||||
ROM:
|
||||
|
||||
Note: in descriptions $F000 is equivalent to $1000 -- that is, we only deal
|
||||
with the low 13 bits of addressing. Stella code uses $1000, I'm used to $F000
|
||||
So, mask with top bits clear :) when reading this document.
|
||||
Note: in descriptions $F000 is equivalent to $1000 -- that is, we only deal
|
||||
with the low 13 bits of addressing. Stella code uses $1000, I'm used to $F000
|
||||
So, mask with top bits clear :) when reading this document.
|
||||
|
||||
In this scheme, the 4K address space is broken into four 1K ROM segments.
|
||||
living at 0x1000, 0x1400, 0x1800, 0x1C00 (or, same thing, 0xF000... etc.),
|
||||
and four 512 byte RAM segments, living at 0x1000, 0x1200, 0x1400, 0x1600
|
||||
with write-mirrors +0x800 of these. The last 1K ROM ($FC00-$FFFF) segment
|
||||
in the 6502 address space (ie: $1C00-$1FFF) is initialised to point to the
|
||||
FIRST 1K of the ROM image, so the reset vectors must be placed at the
|
||||
end of the first 1K in the ROM image. Note, this is DIFFERENT to 3E which
|
||||
switches in the UPPER bank and this bank is fixed. This allows variable sized
|
||||
ROM without having to detect size. First bank (0) in ROM is the default fixed
|
||||
bank mapped to $FC00.
|
||||
In this scheme, the 4K address space is broken into four 1K ROM segments.
|
||||
living at 0x1000, 0x1400, 0x1800, 0x1C00 (or, same thing, 0xF000... etc.),
|
||||
and four 512 byte RAM segments, living at 0x1000, 0x1200, 0x1400, 0x1600
|
||||
with write-mirrors +0x800 of these. The last 1K ROM ($FC00-$FFFF) segment
|
||||
in the 6502 address space (ie: $1C00-$1FFF) is initialised to point to the
|
||||
FIRST 1K of the ROM image, so the reset vectors must be placed at the
|
||||
end of the first 1K in the ROM image. Note, this is DIFFERENT to 3E which
|
||||
switches in the UPPER bank and this bank is fixed. This allows variable sized
|
||||
ROM without having to detect size. First bank (0) in ROM is the default fixed
|
||||
bank mapped to $FC00.
|
||||
|
||||
The system requires the reset vectors to be valid on a reset, so either the
|
||||
hardware first switches in the first bank, or the programmer must ensure
|
||||
that the reset vector is present in ALL ROM banks which might be switched
|
||||
into the last bank area. Currently the latter (programmer onus) is required,
|
||||
but it would be nice for the cartridge hardware to auto-switch on reset.
|
||||
The system requires the reset vectors to be valid on a reset, so either the
|
||||
hardware first switches in the first bank, or the programmer must ensure
|
||||
that the reset vector is present in ALL ROM banks which might be switched
|
||||
into the last bank area. Currently the latter (programmer onus) is required,
|
||||
but it would be nice for the cartridge hardware to auto-switch on reset.
|
||||
|
||||
ROM switching (write of block+bank number to $3F) D7D6 upper 2 bits of bank #
|
||||
indicates the destination segment (0-3, corresponding to $F000, $F400, $F800,
|
||||
$FC00), and lower 6 bits indicate the 1K bank to switch in. Can handle 64
|
||||
x 1K ROM banks (64K total).
|
||||
ROM switching (write of block+bank number to $3F) D7D6 upper 2 bits of bank #
|
||||
indicates the destination segment (0-3, corresponding to $F000, $F400, $F800,
|
||||
$FC00), and lower 6 bits indicate the 1K bank to switch in. Can handle 64
|
||||
x 1K ROM banks (64K total).
|
||||
|
||||
D7 D6 D5D4D3D2D1D0
|
||||
0 0 x x x x x x switch a 1K ROM bank xxxxx to $F000
|
||||
0 1 switch a 1K ROM bank xxxxx to $F400
|
||||
1 0 switch a 1K ROM bank xxxxx to $F800
|
||||
1 1 switch a 1K ROM bank xxxxx to $FC00
|
||||
D7 D6 D5D4D3D2D1D0
|
||||
0 0 x x x x x x switch a 1K ROM bank xxxxx to $F000
|
||||
0 1 switch a 1K ROM bank xxxxx to $F400
|
||||
1 0 switch a 1K ROM bank xxxxx to $F800
|
||||
1 1 switch a 1K ROM bank xxxxx to $FC00
|
||||
|
||||
RAM switching (write of segment+bank number to $3E) with D7D6 upper 2 bits of
|
||||
bank # indicates the destination RAM segment (0-3, corresponding to $F000,
|
||||
$F200, $F400, $F600). Note that this allows contiguous 2K of RAM to be
|
||||
configured by setting 4 consecutive RAM segments each 512 bytes with
|
||||
consecutive addresses. However, as the write address of RAM is +0x800, this
|
||||
invalidates ROM access as described below.
|
||||
RAM switching (write of segment+bank number to $3E) with D7D6 upper 2 bits of
|
||||
bank # indicates the destination RAM segment (0-3, corresponding to $F000,
|
||||
$F200, $F400, $F600). Note that this allows contiguous 2K of RAM to be
|
||||
configured by setting 4 consecutive RAM segments each 512 bytes with
|
||||
consecutive addresses. However, as the write address of RAM is +0x800, this
|
||||
invalidates ROM access as described below.
|
||||
|
||||
can handle 64 x 512 byte RAM banks (32K total)
|
||||
can handle 64 x 512 byte RAM banks (32K total)
|
||||
|
||||
D7 D6 D5D4D3D2D1D0
|
||||
0 0 x x x x x x switch a 512 byte RAM bank xxxxx to $F000 with write @ $F800
|
||||
0 1 switch a 512 byte RAM bank xxxxx to $F200 with write @ $FA00
|
||||
1 0 switch a 512 byte RAM bank xxxxx to $F400 with write @ $FC00
|
||||
1 1 switch a 512 byte RAM bank xxxxx to $F600 with write @ $FE00
|
||||
D7 D6 D5D4D3D2D1D0
|
||||
0 0 x x x x x x switch a 512 byte RAM bank xxxxx to $F000 with write @ $F800
|
||||
0 1 switch a 512 byte RAM bank xxxxx to $F200 with write @ $FA00
|
||||
1 0 switch a 512 byte RAM bank xxxxx to $F400 with write @ $FC00
|
||||
1 1 switch a 512 byte RAM bank xxxxx to $F600 with write @ $FE00
|
||||
|
||||
It is possible to switch multiple RAM banks and ROM banks together
|
||||
It is possible to switch multiple RAM banks and ROM banks together
|
||||
|
||||
For example,
|
||||
F000-F1FF RAM bank A (512 byte READ)
|
||||
F200-F3FF high 512 bytes of ROM bank previously loaded at F000
|
||||
F400 ROM bank 0 (1K)
|
||||
F800 RAM bank A (512 byte WRITE)
|
||||
FA00-FBFF high 512 bytes of ROM bank previously loaded at F400
|
||||
FC00 ROM bank 1
|
||||
For example,
|
||||
F000-F1FF RAM bank A (512 byte READ)
|
||||
F200-F3FF high 512 bytes of ROM bank previously loaded at F000
|
||||
F400 ROM bank 0 (1K)
|
||||
F800 RAM bank A (512 byte WRITE)
|
||||
FA00-FBFF high 512 bytes of ROM bank previously loaded at F400
|
||||
FC00 ROM bank 1
|
||||
|
||||
This example shows 512 bytes of RAM, and 2 1K ROM banks and two 512 byte ROM
|
||||
bank halves.
|
||||
This example shows 512 bytes of RAM, and 2 1K ROM banks and two 512 byte ROM
|
||||
bank halves.
|
||||
|
||||
Switching RAM blocks (D7D6 of $3E) partially invalidates ROM blocks, as below...
|
||||
Switching RAM blocks (D7D6 of $3E) partially invalidates ROM blocks, as below...
|
||||
|
||||
RAM block Invalidates ROM block
|
||||
0 0 (lower half), 2 (lower half)
|
||||
1 0 (upper half), 2 (upper half)
|
||||
2 1 (lower half), 3 (upper half)
|
||||
3 1 (upper half), 3 (lower half)
|
||||
RAM block Invalidates ROM block
|
||||
0 0 (lower half), 2 (lower half)
|
||||
1 0 (upper half), 2 (upper half)
|
||||
2 1 (lower half), 3 (upper half)
|
||||
3 1 (upper half), 3 (lower half)
|
||||
|
||||
For example, RAM block 1 uses address $F200-$F3FF and $FA00-$FBFF
|
||||
ROM block 0 uses address $F000-$F3FF, and ROM block 2 uses address $F800-$FBFF
|
||||
Switching in RAM block 1 makes F200-F3FF ROM inaccessible, however F000-F1FF is
|
||||
still readable. So, care must be paid.
|
||||
For example, RAM block 1 uses address $F200-$F3FF and $FA00-$FBFF
|
||||
ROM block 0 uses address $F000-$F3FF, and ROM block 2 uses address $F800-$FBFF
|
||||
Switching in RAM block 1 makes F200-F3FF ROM inaccessible, however F000-F1FF is
|
||||
still readable. So, care must be paid.
|
||||
|
||||
This crazy RAM layout is useful as it allows contiguous RAM to be switched in,
|
||||
up to 2K in one sequentially accessible block. This means you CAN have 2K of
|
||||
consecutive RAM (don't forget to copy your reset vectors!)
|
||||
This crazy RAM layout is useful as it allows contiguous RAM to be switched in,
|
||||
up to 2K in one sequentially accessible block. This means you CAN have 2K of
|
||||
consecutive RAM (don't forget to copy your reset vectors!)
|
||||
|
||||
@author Andrew Davie
|
||||
@author Andrew Davie
|
||||
*/
|
||||
|
||||
class CartridgeDASH: public Cartridge
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
CartridgeDF::CartridgeDF(const BytePtr& image, uInt32 size,
|
||||
const Settings& settings)
|
||||
: Cartridge(settings),
|
||||
myCurrentBank(0)
|
||||
myBankOffset(0)
|
||||
{
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image.get(), std::min(131072u, size));
|
||||
|
@ -57,7 +57,7 @@ uInt8 CartridgeDF::peek(uInt16 address)
|
|||
if((address >= 0x0FC0) && (address <= 0x0FDF))
|
||||
bank(address - 0x0FC0);
|
||||
|
||||
return myImage[(myCurrentBank << 12) + address];
|
||||
return myImage[myBankOffset + address];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -78,8 +78,7 @@ bool CartridgeDF::bank(uInt16 bank)
|
|||
if(bankLocked()) return false;
|
||||
|
||||
// Remember what bank we're in
|
||||
myCurrentBank = bank;
|
||||
uInt32 offset = myCurrentBank << 12;
|
||||
myBankOffset = bank << 12;
|
||||
|
||||
System::PageAccess access(this, System::PA_READ);
|
||||
|
||||
|
@ -87,7 +86,7 @@ bool CartridgeDF::bank(uInt16 bank)
|
|||
for(uInt32 i = (0x1FC0 & ~System::PAGE_MASK); i < 0x2000;
|
||||
i += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (i & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (i & 0x0FFF)];
|
||||
mySystem->setPageAccess(i >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
|
||||
|
@ -95,8 +94,8 @@ bool CartridgeDF::bank(uInt16 bank)
|
|||
for(uInt32 address = 0x1000; address < (0x1FC0U & ~System::PAGE_MASK);
|
||||
address += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
|
||||
access.directPeekBase = &myImage[myBankOffset + (address & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (address & 0x0FFF)];
|
||||
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
@ -105,7 +104,7 @@ bool CartridgeDF::bank(uInt16 bank)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeDF::getBank() const
|
||||
{
|
||||
return myCurrentBank;
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -117,7 +116,7 @@ uInt16 CartridgeDF::bankCount() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeDF::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
myImage[(myCurrentBank << 12) + (address & 0x0FFF)] = value;
|
||||
myImage[myBankOffset + (address & 0x0FFF)] = value;
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
|
@ -134,7 +133,7 @@ bool CartridgeDF::save(Serializer& out) const
|
|||
try
|
||||
{
|
||||
out.putString(name());
|
||||
out.putShort(myCurrentBank);
|
||||
out.putInt(myBankOffset);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -153,7 +152,7 @@ bool CartridgeDF::load(Serializer& in)
|
|||
if(in.getString() != name())
|
||||
return false;
|
||||
|
||||
myCurrentBank = in.getShort();
|
||||
myBankOffset = in.getInt();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -162,7 +161,7 @@ bool CartridgeDF::load(Serializer& in)
|
|||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myCurrentBank);
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -152,8 +152,8 @@ class CartridgeDF : public Cartridge
|
|||
// The 128K ROM image of the cartridge
|
||||
uInt8 myImage[32 * 4096];
|
||||
|
||||
// Indicates which bank is currently active
|
||||
uInt16 myCurrentBank;
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt32 myBankOffset;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
CartridgeDFSC::CartridgeDFSC(const BytePtr& image, uInt32 size,
|
||||
const Settings& settings)
|
||||
: Cartridge(settings),
|
||||
myCurrentBank(0)
|
||||
myBankOffset(0)
|
||||
{
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image.get(), std::min(131072u, size));
|
||||
|
@ -95,7 +95,7 @@ uInt8 CartridgeDFSC::peek(uInt16 address)
|
|||
}
|
||||
}
|
||||
else
|
||||
return myImage[(myCurrentBank << 12) + address];
|
||||
return myImage[myBankOffset + address];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -107,7 +107,7 @@ bool CartridgeDFSC::poke(uInt16 address, uInt8)
|
|||
if((address >= 0x0FC0) && (address <= 0x0FDF))
|
||||
bank(address - 0x0FC0);
|
||||
|
||||
// NOTE: This does not handle accessing RAM, however, this function
|
||||
// NOTE: This does not handle accessing RAM, however, this method
|
||||
// should never be called for RAM because of the way page accessing
|
||||
// has been setup
|
||||
return false;
|
||||
|
@ -119,8 +119,7 @@ bool CartridgeDFSC::bank(uInt16 bank)
|
|||
if(bankLocked()) return false;
|
||||
|
||||
// Remember what bank we're in
|
||||
myCurrentBank = bank;
|
||||
uInt32 offset = myCurrentBank << 12;
|
||||
myBankOffset = bank << 12;
|
||||
|
||||
System::PageAccess access(this, System::PA_READ);
|
||||
|
||||
|
@ -128,7 +127,7 @@ bool CartridgeDFSC::bank(uInt16 bank)
|
|||
for(uInt32 i = (0x1FC0 & ~System::PAGE_MASK); i < 0x2000;
|
||||
i += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (i & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (i & 0x0FFF)];
|
||||
mySystem->setPageAccess(i >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
|
||||
|
@ -136,8 +135,8 @@ bool CartridgeDFSC::bank(uInt16 bank)
|
|||
for(uInt32 address = 0x1100; address < (0x1FC0U & ~System::PAGE_MASK);
|
||||
address += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
|
||||
access.directPeekBase = &myImage[myBankOffset + (address & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (address & 0x0FFF)];
|
||||
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
@ -146,7 +145,7 @@ bool CartridgeDFSC::bank(uInt16 bank)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeDFSC::getBank() const
|
||||
{
|
||||
return myCurrentBank;
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -168,7 +167,7 @@ bool CartridgeDFSC::patch(uInt16 address, uInt8 value)
|
|||
myRAM[address & 0x007F] = value;
|
||||
}
|
||||
else
|
||||
myImage[(myCurrentBank << 12) + address] = value;
|
||||
myImage[myBankOffset + address] = value;
|
||||
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
@ -186,7 +185,7 @@ bool CartridgeDFSC::save(Serializer& out) const
|
|||
try
|
||||
{
|
||||
out.putString(name());
|
||||
out.putShort(myCurrentBank);
|
||||
out.putInt(myBankOffset);
|
||||
out.putByteArray(myRAM, 128);
|
||||
}
|
||||
catch(...)
|
||||
|
@ -206,7 +205,7 @@ bool CartridgeDFSC::load(Serializer& in)
|
|||
if(in.getString() != name())
|
||||
return false;
|
||||
|
||||
myCurrentBank = in.getShort();
|
||||
myBankOffset = in.getInt();
|
||||
in.getByteArray(myRAM, 128);
|
||||
}
|
||||
catch(...)
|
||||
|
@ -216,7 +215,7 @@ bool CartridgeDFSC::load(Serializer& in)
|
|||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myCurrentBank);
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ class System;
|
|||
/**
|
||||
There are 32 4K banks (total of 128K ROM) with 128 bytes of RAM.
|
||||
Accessing $1FC0 - $1FDF switches to each bank.
|
||||
RAM read port is $1080 - $10FF, write port is $1000 - $107F.
|
||||
|
||||
@author Stephen Anthony
|
||||
*/
|
||||
|
@ -154,8 +155,8 @@ class CartridgeDFSC : public Cartridge
|
|||
// The 128 bytes of RAM
|
||||
uInt8 myRAM[128];
|
||||
|
||||
// Indicates which bank is currently active
|
||||
uInt16 myCurrentBank;
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt32 myBankOffset;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeDPC::CartridgeDPC(const BytePtr& image, uInt32 size,
|
|||
mySize(size),
|
||||
mySystemCycles(0),
|
||||
myFractionalClocks(0.0),
|
||||
myCurrentBank(0)
|
||||
myBankOffset(0)
|
||||
{
|
||||
// Make a copy of the entire image
|
||||
memcpy(myImage, image.get(), std::min(size, 8192u + 2048u + 256u));
|
||||
|
@ -163,7 +163,7 @@ uInt8 CartridgeDPC::peek(uInt16 address)
|
|||
// In debugger/bank-locked mode, we ignore all hotspots and in general
|
||||
// anything that can change the internal state of the cart
|
||||
if(bankLocked())
|
||||
return myProgramImage[(myCurrentBank << 12) + address];
|
||||
return myProgramImage[myBankOffset + address];
|
||||
|
||||
// Clock the random number generator. This should be done for every
|
||||
// cartridge access, however, we're only doing it for the DPC and
|
||||
|
@ -279,7 +279,7 @@ uInt8 CartridgeDPC::peek(uInt16 address)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
return myProgramImage[(myCurrentBank << 12) + address];
|
||||
return myProgramImage[myBankOffset + address];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -395,8 +395,7 @@ bool CartridgeDPC::bank(uInt16 bank)
|
|||
if(bankLocked()) return false;
|
||||
|
||||
// Remember what bank we're in
|
||||
myCurrentBank = bank;
|
||||
uInt16 offset = myCurrentBank << 12;
|
||||
myBankOffset = bank << 12;
|
||||
|
||||
System::PageAccess access(this, System::PA_READ);
|
||||
|
||||
|
@ -404,7 +403,7 @@ bool CartridgeDPC::bank(uInt16 bank)
|
|||
for(uInt32 i = (0x1FF8 & ~System::PAGE_MASK); i < 0x2000;
|
||||
i += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (i & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (i & 0x0FFF)];
|
||||
mySystem->setPageAccess(i >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
|
||||
|
@ -412,8 +411,8 @@ bool CartridgeDPC::bank(uInt16 bank)
|
|||
for(uInt32 address = 0x1080; address < (0x1FF8U & ~System::PAGE_MASK);
|
||||
address += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.directPeekBase = &myProgramImage[offset + (address & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
|
||||
access.directPeekBase = &myProgramImage[myBankOffset + (address & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (address & 0x0FFF)];
|
||||
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
@ -422,7 +421,7 @@ bool CartridgeDPC::bank(uInt16 bank)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeDPC::getBank() const
|
||||
{
|
||||
return myCurrentBank;
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -439,7 +438,7 @@ bool CartridgeDPC::patch(uInt16 address, uInt8 value)
|
|||
// For now, we ignore attempts to patch the DPC address space
|
||||
if(address >= 0x0080)
|
||||
{
|
||||
myProgramImage[(myCurrentBank << 12) + (address & 0x0FFF)] = value;
|
||||
myProgramImage[myBankOffset + (address & 0x0FFF)] = value;
|
||||
return myBankChanged = true;
|
||||
}
|
||||
else
|
||||
|
@ -461,7 +460,7 @@ bool CartridgeDPC::save(Serializer& out) const
|
|||
out.putString(name());
|
||||
|
||||
// Indicates which bank is currently active
|
||||
out.putShort(myCurrentBank);
|
||||
out.putShort(myBankOffset);
|
||||
|
||||
// The top registers for the data fetchers
|
||||
out.putByteArray(myTops, 8);
|
||||
|
@ -503,7 +502,7 @@ bool CartridgeDPC::load(Serializer& in)
|
|||
return false;
|
||||
|
||||
// Indicates which bank is currently active
|
||||
myCurrentBank = in.getShort();
|
||||
myBankOffset = in.getShort();
|
||||
|
||||
// The top registers for the data fetchers
|
||||
in.getByteArray(myTops, 8);
|
||||
|
@ -535,7 +534,7 @@ bool CartridgeDPC::load(Serializer& in)
|
|||
}
|
||||
|
||||
// Now, go to the current bank
|
||||
bank(myCurrentBank);
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -208,8 +208,8 @@ class CartridgeDPC : public Cartridge
|
|||
// Fractional DPC music OSC clocks unused during the last update
|
||||
double myFractionalClocks;
|
||||
|
||||
// Indicates which bank is currently active
|
||||
uInt16 myCurrentBank;
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -33,7 +33,7 @@ CartridgeDPCPlus::CartridgeDPCPlus(const BytePtr& image, uInt32 size,
|
|||
mySystemCycles(0),
|
||||
myFractionalClocks(0.0),
|
||||
myARMCycles(0),
|
||||
myCurrentBank(0)
|
||||
myBankOffset(0)
|
||||
{
|
||||
// Image is always 32K, but in the case of ROM > 29K, the image is
|
||||
// copied to the end of the buffer
|
||||
|
@ -221,7 +221,7 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
|
|||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
uInt8 peekvalue = myProgramImage[(myCurrentBank << 12) + address];
|
||||
uInt8 peekvalue = myProgramImage[myBankOffset + address];
|
||||
uInt8 flag;
|
||||
|
||||
// In debugger/bank-locked mode, we ignore all hotspots and in general
|
||||
|
@ -593,8 +593,7 @@ bool CartridgeDPCPlus::bank(uInt16 bank)
|
|||
if(bankLocked()) return false;
|
||||
|
||||
// Remember what bank we're in
|
||||
myCurrentBank = bank;
|
||||
uInt16 offset = myCurrentBank << 12;
|
||||
myBankOffset = bank << 12;
|
||||
|
||||
// Setup the page access methods for the current bank
|
||||
System::PageAccess access(this, System::PA_READ);
|
||||
|
@ -603,7 +602,7 @@ bool CartridgeDPCPlus::bank(uInt16 bank)
|
|||
for(uInt32 address = 0x1080; address < 0x2000;
|
||||
address += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (address & 0x0FFF)];
|
||||
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
@ -612,7 +611,7 @@ bool CartridgeDPCPlus::bank(uInt16 bank)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeDPCPlus::getBank() const
|
||||
{
|
||||
return myCurrentBank;
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -629,7 +628,7 @@ bool CartridgeDPCPlus::patch(uInt16 address, uInt8 value)
|
|||
// For now, we ignore attempts to patch the DPC address space
|
||||
if(address >= 0x0080)
|
||||
{
|
||||
myProgramImage[(myCurrentBank << 12) + (address & 0x0FFF)] = value;
|
||||
myProgramImage[myBankOffset + (address & 0x0FFF)] = value;
|
||||
return myBankChanged = true;
|
||||
}
|
||||
else
|
||||
|
@ -651,7 +650,7 @@ bool CartridgeDPCPlus::save(Serializer& out) const
|
|||
out.putString(name());
|
||||
|
||||
// Indicates which bank is currently active
|
||||
out.putShort(myCurrentBank);
|
||||
out.putShort(myBankOffset);
|
||||
|
||||
// Harmony RAM
|
||||
out.putByteArray(myDPCRAM, 8192);
|
||||
|
@ -715,7 +714,7 @@ bool CartridgeDPCPlus::load(Serializer& in)
|
|||
return false;
|
||||
|
||||
// Indicates which bank is currently active
|
||||
myCurrentBank = in.getShort();
|
||||
myBankOffset = in.getShort();
|
||||
|
||||
// Harmony RAM
|
||||
in.getByteArray(myDPCRAM, 8192);
|
||||
|
@ -768,7 +767,7 @@ bool CartridgeDPCPlus::load(Serializer& in)
|
|||
}
|
||||
|
||||
// Now, go to the current bank
|
||||
bank(myCurrentBank);
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -272,8 +272,8 @@ class CartridgeDPCPlus : public Cartridge
|
|||
// System cycle count when the last Thumbulator::run() occurred
|
||||
Int32 myARMCycles;
|
||||
|
||||
// Indicates which bank is currently active
|
||||
uInt16 myCurrentBank;
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -136,7 +136,7 @@ bool CartridgeE7::poke(uInt16 address, uInt8)
|
|||
}
|
||||
|
||||
// NOTE: This does not handle writing to RAM, however, this
|
||||
// function should never be called for RAM because of the
|
||||
// method should never be called for RAM because of the
|
||||
// way page accessing has been setup
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
CartridgeEF::CartridgeEF(const BytePtr& image, uInt32 size,
|
||||
const Settings& settings)
|
||||
: Cartridge(settings),
|
||||
myCurrentBank(0)
|
||||
myBankOffset(0)
|
||||
{
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image.get(), std::min(65536u, size));
|
||||
|
@ -57,7 +57,7 @@ uInt8 CartridgeEF::peek(uInt16 address)
|
|||
if((address >= 0x0FE0) && (address <= 0x0FEF))
|
||||
bank(address - 0x0FE0);
|
||||
|
||||
return myImage[(myCurrentBank << 12) + address];
|
||||
return myImage[myBankOffset + address];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -78,8 +78,7 @@ bool CartridgeEF::bank(uInt16 bank)
|
|||
if(bankLocked()) return false;
|
||||
|
||||
// Remember what bank we're in
|
||||
myCurrentBank = bank;
|
||||
uInt16 offset = myCurrentBank << 12;
|
||||
myBankOffset = bank << 12;
|
||||
|
||||
System::PageAccess access(this, System::PA_READ);
|
||||
|
||||
|
@ -87,7 +86,7 @@ bool CartridgeEF::bank(uInt16 bank)
|
|||
for(uInt32 i = (0x1FE0 & ~System::PAGE_MASK); i < 0x2000;
|
||||
i += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (i & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (i & 0x0FFF)];
|
||||
mySystem->setPageAccess(i >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
|
||||
|
@ -95,8 +94,8 @@ bool CartridgeEF::bank(uInt16 bank)
|
|||
for(uInt32 address = 0x1000; address < (0x1FE0U & ~System::PAGE_MASK);
|
||||
address += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
|
||||
access.directPeekBase = &myImage[myBankOffset + (address & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (address & 0x0FFF)];
|
||||
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
@ -105,7 +104,7 @@ bool CartridgeEF::bank(uInt16 bank)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeEF::getBank() const
|
||||
{
|
||||
return myCurrentBank;
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -117,7 +116,7 @@ uInt16 CartridgeEF::bankCount() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeEF::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
myImage[(myCurrentBank << 12) + (address & 0x0FFF)] = value;
|
||||
myImage[myBankOffset + (address & 0x0FFF)] = value;
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
|
@ -134,7 +133,7 @@ bool CartridgeEF::save(Serializer& out) const
|
|||
try
|
||||
{
|
||||
out.putString(name());
|
||||
out.putShort(myCurrentBank);
|
||||
out.putShort(myBankOffset);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -153,7 +152,7 @@ bool CartridgeEF::load(Serializer& in)
|
|||
if(in.getString() != name())
|
||||
return false;
|
||||
|
||||
myCurrentBank = in.getShort();
|
||||
myBankOffset = in.getShort();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -162,7 +161,7 @@ bool CartridgeEF::load(Serializer& in)
|
|||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myCurrentBank);
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -31,9 +31,6 @@ class System;
|
|||
There are 16 4K banks (total of 64K ROM).
|
||||
Accessing $1FE0 - $1FEF switches to each bank.
|
||||
|
||||
This interpretation is based on analysis of the z26 assembly code,
|
||||
as this scheme doesn't seem to be documented anywhere.
|
||||
|
||||
@author Stephen Anthony
|
||||
*/
|
||||
class CartridgeEF : public Cartridge
|
||||
|
@ -155,8 +152,8 @@ class CartridgeEF : public Cartridge
|
|||
// The 64K ROM image of the cartridge
|
||||
uInt8 myImage[65536];
|
||||
|
||||
// Indicates which bank is currently active
|
||||
uInt16 myCurrentBank;
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
CartridgeEFSC::CartridgeEFSC(const BytePtr& image, uInt32 size,
|
||||
const Settings& settings)
|
||||
: Cartridge(settings),
|
||||
myCurrentBank(0)
|
||||
myBankOffset(0)
|
||||
{
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image.get(), std::min(65536u, size));
|
||||
|
@ -95,7 +95,7 @@ uInt8 CartridgeEFSC::peek(uInt16 address)
|
|||
}
|
||||
}
|
||||
else
|
||||
return myImage[(myCurrentBank << 12) + address];
|
||||
return myImage[myBankOffset + address];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -119,8 +119,7 @@ bool CartridgeEFSC::bank(uInt16 bank)
|
|||
if(bankLocked()) return false;
|
||||
|
||||
// Remember what bank we're in
|
||||
myCurrentBank = bank;
|
||||
uInt16 offset = myCurrentBank << 12;
|
||||
myBankOffset = bank << 12;
|
||||
|
||||
System::PageAccess access(this, System::PA_READ);
|
||||
|
||||
|
@ -128,7 +127,7 @@ bool CartridgeEFSC::bank(uInt16 bank)
|
|||
for(uInt32 i = (0x1FE0 & ~System::PAGE_MASK); i < 0x2000;
|
||||
i += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (i & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (i & 0x0FFF)];
|
||||
mySystem->setPageAccess(i >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
|
||||
|
@ -136,8 +135,8 @@ bool CartridgeEFSC::bank(uInt16 bank)
|
|||
for(uInt32 address = 0x1100; address < (0x1FE0U & ~System::PAGE_MASK);
|
||||
address += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
|
||||
access.directPeekBase = &myImage[myBankOffset + (address & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (address & 0x0FFF)];
|
||||
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
@ -146,7 +145,7 @@ bool CartridgeEFSC::bank(uInt16 bank)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeEFSC::getBank() const
|
||||
{
|
||||
return myCurrentBank;
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -168,7 +167,7 @@ bool CartridgeEFSC::patch(uInt16 address, uInt8 value)
|
|||
myRAM[address & 0x007F] = value;
|
||||
}
|
||||
else
|
||||
myImage[(myCurrentBank << 12) + address] = value;
|
||||
myImage[myBankOffset + address] = value;
|
||||
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
@ -186,7 +185,7 @@ bool CartridgeEFSC::save(Serializer& out) const
|
|||
try
|
||||
{
|
||||
out.putString(name());
|
||||
out.putShort(myCurrentBank);
|
||||
out.putShort(myBankOffset);
|
||||
out.putByteArray(myRAM, 128);
|
||||
}
|
||||
catch(...)
|
||||
|
@ -206,7 +205,7 @@ bool CartridgeEFSC::load(Serializer& in)
|
|||
if(in.getString() != name())
|
||||
return false;
|
||||
|
||||
myCurrentBank = in.getShort();
|
||||
myBankOffset = in.getShort();
|
||||
in.getByteArray(myRAM, 128);
|
||||
}
|
||||
catch(...)
|
||||
|
@ -216,7 +215,7 @@ bool CartridgeEFSC::load(Serializer& in)
|
|||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myCurrentBank);
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -30,9 +30,7 @@ class System;
|
|||
Cartridge class used for Homestar Runner by Paul Slocum.
|
||||
There are 16 4K banks (total of 64K ROM) with 128 bytes of RAM.
|
||||
Accessing $1FE0 - $1FEF switches to each bank.
|
||||
|
||||
This interpretation is based on analysis of the z26 assembly code,
|
||||
as this scheme doesn't seem to be documented anywhere.
|
||||
RAM read port is $1080 - $10FF, write port is $1000 - $107F.
|
||||
|
||||
@author Stephen Anthony
|
||||
*/
|
||||
|
@ -158,8 +156,8 @@ class CartridgeEFSC : public Cartridge
|
|||
// The 128 bytes of RAM
|
||||
uInt8 myRAM[128];
|
||||
|
||||
// Indicates which bank is currently active
|
||||
uInt16 myCurrentBank;
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
CartridgeF0::CartridgeF0(const BytePtr& image, uInt32 size,
|
||||
const Settings& settings)
|
||||
: Cartridge(settings),
|
||||
myCurrentBank(0)
|
||||
myBankOffset(0)
|
||||
{
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image.get(), std::min(65536u, size));
|
||||
|
@ -35,9 +35,8 @@ CartridgeF0::CartridgeF0(const BytePtr& image, uInt32 size,
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeF0::reset()
|
||||
{
|
||||
// Upon reset we switch to bank 15
|
||||
myCurrentBank = 14;
|
||||
incbank();
|
||||
// Upon reset we switch to the startup bank
|
||||
bank(myStartBank);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -45,9 +44,8 @@ void CartridgeF0::install(System& system)
|
|||
{
|
||||
mySystem = &system;
|
||||
|
||||
// Install pages for bank 1
|
||||
myCurrentBank = 0;
|
||||
incbank();
|
||||
// Install pages for the startup bank
|
||||
bank(myStartBank);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -59,7 +57,7 @@ uInt8 CartridgeF0::peek(uInt16 address)
|
|||
if(address == 0x0FF0)
|
||||
incbank();
|
||||
|
||||
return myImage[(myCurrentBank << 12) + address];
|
||||
return myImage[myBankOffset + address];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -77,32 +75,9 @@ bool CartridgeF0::poke(uInt16 address, uInt8)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeF0::incbank()
|
||||
{
|
||||
if(bankLocked()) return;
|
||||
|
||||
// Remember what bank we're in
|
||||
myCurrentBank++;
|
||||
myCurrentBank &= 0x0F;
|
||||
uInt16 offset = myCurrentBank << 12;
|
||||
|
||||
System::PageAccess access(this, System::PA_READ);
|
||||
|
||||
// Set the page accessing methods for the hot spots
|
||||
for(uInt32 i = (0x1FF0 & ~System::PAGE_MASK); i < 0x2000;
|
||||
i += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (i & 0x0FFF)];
|
||||
mySystem->setPageAccess(i >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
|
||||
// Setup the page access methods for the current bank
|
||||
for(uInt32 address = 0x1000; address < (0x1FF0U & ~System::PAGE_MASK);
|
||||
address += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
|
||||
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
myBankChanged = true;
|
||||
// Determine current bank, and increment to the next one
|
||||
uInt8 nextBank = ((myBankOffset >> 12) + 1) & 0x0F;
|
||||
bank(nextBank);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -110,8 +85,27 @@ bool CartridgeF0::bank(uInt16 bank)
|
|||
{
|
||||
if(bankLocked()) return false;
|
||||
|
||||
myCurrentBank = bank - 1;
|
||||
incbank();
|
||||
// Remember what bank we're in
|
||||
myBankOffset = bank << 12;
|
||||
|
||||
System::PageAccess access(this, System::PA_READ);
|
||||
|
||||
// Set the page accessing methods for the hot spots
|
||||
for(uInt32 i = (0x1FF0 & ~System::PAGE_MASK); i < 0x2000;
|
||||
i += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (i & 0x0FFF)];
|
||||
mySystem->setPageAccess(i >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
|
||||
// Setup the page access methods for the current bank
|
||||
for(uInt32 address = 0x1000; address < (0x1FF0U & ~System::PAGE_MASK);
|
||||
address += (1 << System::PAGE_SHIFT))
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (address & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (address & 0x0FFF)];
|
||||
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
|
||||
}
|
||||
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
@ -119,7 +113,7 @@ bool CartridgeF0::bank(uInt16 bank)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeF0::getBank() const
|
||||
{
|
||||
return myCurrentBank;
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -131,7 +125,7 @@ uInt16 CartridgeF0::bankCount() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF0::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
myImage[(myCurrentBank << 12) + (address & 0x0FFF)] = value;
|
||||
myImage[myBankOffset + (address & 0x0FFF)] = value;
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
|
@ -148,7 +142,7 @@ bool CartridgeF0::save(Serializer& out) const
|
|||
try
|
||||
{
|
||||
out.putString(name());
|
||||
out.putShort(myCurrentBank);
|
||||
out.putShort(myBankOffset);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -167,7 +161,7 @@ bool CartridgeF0::load(Serializer& in)
|
|||
if(in.getString() != name())
|
||||
return false;
|
||||
|
||||
myCurrentBank = in.getShort();
|
||||
myBankOffset = in.getShort();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -176,8 +170,7 @@ bool CartridgeF0::load(Serializer& in)
|
|||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
--myCurrentBank;
|
||||
incbank();
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -158,8 +158,8 @@ class CartridgeF0 : public Cartridge
|
|||
// The 64K ROM image of the cartridge
|
||||
uInt8 myImage[65536];
|
||||
|
||||
// Indicates which bank is currently active
|
||||
uInt16 myCurrentBank;
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
Loading…
Reference in New Issue