mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +00:00
Add basic implementation of fast RAM.
This commit is contained in:
parent
bdf0a1941c
commit
9796b308dc
@ -17,7 +17,21 @@ namespace Static {
|
|||||||
namespace Amiga {
|
namespace Amiga {
|
||||||
|
|
||||||
struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Target> {
|
struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Target> {
|
||||||
Target() : Analyser::Static::Target(Machine::Amiga) {}
|
ReflectableEnum(FastRAM,
|
||||||
|
None,
|
||||||
|
OneMegabyte,
|
||||||
|
TwoMegabytes,
|
||||||
|
FourMegabytes,
|
||||||
|
EightMegabytes);
|
||||||
|
|
||||||
|
FastRAM fast_ram = FastRAM::TwoMegabytes;
|
||||||
|
|
||||||
|
Target() : Analyser::Static::Target(Machine::Amiga) {
|
||||||
|
if(needs_declare()) {
|
||||||
|
DeclareField(fast_ram);
|
||||||
|
AnnounceEnum(FastRAM);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ class ConcreteMachine:
|
|||||||
public:
|
public:
|
||||||
ConcreteMachine(const Analyser::Static::Amiga::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
|
ConcreteMachine(const Analyser::Static::Amiga::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
|
||||||
mc68000_(*this),
|
mc68000_(*this),
|
||||||
|
memory_(target.fast_ram),
|
||||||
chipset_(memory_, PALClockRate)
|
chipset_(memory_, PALClockRate)
|
||||||
{
|
{
|
||||||
// Temporary: use a hard-coded Kickstart selection.
|
// Temporary: use a hard-coded Kickstart selection.
|
||||||
@ -146,6 +147,13 @@ class ConcreteMachine:
|
|||||||
// LOG("CIA " << (((address >> 12) & 3)^3) << " " << (cycle.operation & Microcycle::Read ? "read " : "write ") << std::dec << (reg & 0xf) << " of " << PADHEX(4) << +cycle.value16());
|
// LOG("CIA " << (((address >> 12) & 3)^3) << " " << (cycle.operation & Microcycle::Read ? "read " : "write ") << std::dec << (reg & 0xf) << " of " << PADHEX(4) << +cycle.value16());
|
||||||
} else if(address >= 0xdf'f000 && address <= 0xdf'f1be) {
|
} else if(address >= 0xdf'f000 && address <= 0xdf'f1be) {
|
||||||
chipset_.perform(cycle);
|
chipset_.perform(cycle);
|
||||||
|
} else if(address >= 0xe8'0000 && address < 0xe9'0000) {
|
||||||
|
// This is the Autoconf space; right now the only
|
||||||
|
// Autoconf device this emulator implements is fast RAM,
|
||||||
|
// which if present is provided as part of the memory map.
|
||||||
|
//
|
||||||
|
// Relevant quote: "The Zorro II configuration space is the 64K memory block $00E8xxxx"
|
||||||
|
memory_.perform(cycle);
|
||||||
} else {
|
} else {
|
||||||
// This'll do for open bus, for now.
|
// This'll do for open bus, for now.
|
||||||
if(cycle.operation & Microcycle::Read) {
|
if(cycle.operation & Microcycle::Read) {
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#ifndef MemoryMap_hpp
|
#ifndef MemoryMap_hpp
|
||||||
#define MemoryMap_hpp
|
#define MemoryMap_hpp
|
||||||
|
|
||||||
|
#include "../../Analyser/Static/Amiga/Target.hpp"
|
||||||
|
|
||||||
namespace Amiga {
|
namespace Amiga {
|
||||||
|
|
||||||
class MemoryMap {
|
class MemoryMap {
|
||||||
@ -19,15 +21,16 @@ class MemoryMap {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// TODO: decide what of the below I want to be dynamic.
|
// TODO: decide what of the below I want to be dynamic.
|
||||||
std::array<uint8_t, 1024*1024> chip_ram{};
|
|
||||||
std::array<uint8_t, 512*1024> kickstart{0xff};
|
std::array<uint8_t, 512*1024> kickstart{0xff};
|
||||||
|
std::array<uint8_t, 1024*1024> chip_ram{};
|
||||||
|
|
||||||
struct MemoryRegion {
|
struct MemoryRegion {
|
||||||
uint8_t *contents = nullptr;
|
uint8_t *contents = nullptr;
|
||||||
unsigned int read_write_mask = 0;
|
unsigned int read_write_mask = 0;
|
||||||
} regions[64]; // i.e. top six bits are used as an index.
|
} regions[64]; // i.e. top six bits are used as an index.
|
||||||
|
|
||||||
MemoryMap() {
|
using FastRAM = Analyser::Static::Amiga::Target::FastRAM;
|
||||||
|
MemoryMap(FastRAM fast_ram_size) {
|
||||||
// Address spaces that matter:
|
// Address spaces that matter:
|
||||||
//
|
//
|
||||||
// 00'0000 – 08'0000: chip RAM. [or overlayed KickStart]
|
// 00'0000 – 08'0000: chip RAM. [or overlayed KickStart]
|
||||||
@ -45,6 +48,29 @@ class MemoryMap {
|
|||||||
// f8'0000 — : 256kb Kickstart if 2.04 or higher.
|
// f8'0000 — : 256kb Kickstart if 2.04 or higher.
|
||||||
// fc'0000 – : 256kb Kickstart otherwise.
|
// fc'0000 – : 256kb Kickstart otherwise.
|
||||||
set_region(0xfc'0000, 0x1'00'0000, kickstart.data(), PermitRead);
|
set_region(0xfc'0000, 0x1'00'0000, kickstart.data(), PermitRead);
|
||||||
|
|
||||||
|
switch(fast_ram_size) {
|
||||||
|
default:
|
||||||
|
fast_autoconf_visible_ = false;
|
||||||
|
break;
|
||||||
|
case FastRAM::OneMegabyte:
|
||||||
|
fast_ram_.resize(1 * 1024 * 1024);
|
||||||
|
fast_ram_size_ = 5;
|
||||||
|
break;
|
||||||
|
case FastRAM::TwoMegabytes:
|
||||||
|
fast_ram_.resize(2 * 1024 * 1024);
|
||||||
|
fast_ram_size_ = 6;
|
||||||
|
break;
|
||||||
|
case FastRAM::FourMegabytes:
|
||||||
|
fast_ram_.resize(4 * 1024 * 1024);
|
||||||
|
fast_ram_size_ = 7;
|
||||||
|
break;
|
||||||
|
case FastRAM::EightMegabytes:
|
||||||
|
fast_ram_.resize(8 * 1024 * 1024);
|
||||||
|
fast_ram_size_ = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +90,76 @@ class MemoryMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs the provided microcycle, which the caller guarantees to be a memory access,
|
||||||
|
/// and in the Zorro register range.
|
||||||
|
bool perform(const CPU::MC68000::Microcycle &cycle) {
|
||||||
|
if(!fast_autoconf_visible_) return false;
|
||||||
|
|
||||||
|
const uint32_t register_address = *cycle.address & 0xfe;
|
||||||
|
|
||||||
|
using Microcycle = CPU::MC68000::Microcycle;
|
||||||
|
if(cycle.operation & Microcycle::Read) {
|
||||||
|
// Re: Autoconf:
|
||||||
|
//
|
||||||
|
// "All read registers physically return only the top 4 bits of data, on D31-D28";
|
||||||
|
// (this is from Zorro III documentation; I'm assuming it to be D15–D11 for the
|
||||||
|
// 68000's 16-bit bus);
|
||||||
|
//
|
||||||
|
// "Every AUTOCONFIG register is logically considered to be 8 bits wide; the
|
||||||
|
// 8 bits actually being nybbles from two paired addresses."
|
||||||
|
|
||||||
|
uint8_t value = 0xf;
|
||||||
|
switch(register_address) {
|
||||||
|
default: break;
|
||||||
|
|
||||||
|
case 0x00: // er_Type (high)
|
||||||
|
value =
|
||||||
|
0xc | // Zoro II-style PIC.
|
||||||
|
0x2; // Memory will be linked into the free pool
|
||||||
|
break;
|
||||||
|
case 0x02: // er_Type (low)
|
||||||
|
value = fast_ram_size_;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// er_Manufacturer
|
||||||
|
//
|
||||||
|
// On the manufacturer number: this is supposed to be assigned
|
||||||
|
// by Commodore. TODO: find and crib a real fast RAM number, if it matters.
|
||||||
|
//
|
||||||
|
// (0xffff seems to be invalid, so _something_ needs to be supplied)
|
||||||
|
case 0x10: case 0x12:
|
||||||
|
value = 0xa; // Manufacturer's number, high byte.
|
||||||
|
break;
|
||||||
|
case 0x14: case 0x16:
|
||||||
|
value = 0xb; // Manufacturer's number, low byte.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shove the value into the top of the data bus.
|
||||||
|
cycle.set_value16(uint16_t(0x0fff | (value << 12)));
|
||||||
|
} else {
|
||||||
|
fast_autoconf_visible_ &= !(register_address >= 0x4c && register_address < 0x50);
|
||||||
|
|
||||||
|
switch(register_address) {
|
||||||
|
default: break;
|
||||||
|
|
||||||
|
case 0x48: { // ec_BaseAddress (A23–A16)
|
||||||
|
const auto address = uint32_t(cycle.value8_high()) << 16;
|
||||||
|
printf("Mapping fast RAM to %08x", address);
|
||||||
|
set_region(address, uint32_t(address + fast_ram_.size()), fast_ram_.data(), PermitRead | PermitWrite);
|
||||||
|
fast_autoconf_visible_ = false;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::vector<uint8_t> fast_ram_{};
|
||||||
|
uint8_t fast_ram_size_ = 0;
|
||||||
|
|
||||||
|
bool fast_autoconf_visible_ = true;
|
||||||
bool overlay_ = false;
|
bool overlay_ = false;
|
||||||
|
|
||||||
void set_region(uint32_t start, uint32_t end, uint8_t *base, unsigned int read_write_mask) {
|
void set_region(uint32_t start, uint32_t end, uint8_t *base, unsigned int read_write_mask) {
|
||||||
|
Loading…
Reference in New Issue
Block a user