mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +00:00
Modifies the Vic-20 and C1540 to bring them into the realm of self-ROM fetching.
Hence enables Vic-20 support within kiosk mode as currently drafted.
This commit is contained in:
parent
35da3edf60
commit
ddcdd07dd0
@ -919,21 +919,23 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
// See header; provides the system ROMs.
|
||||
void set_rom(ROMType type, std::vector<uint8_t> data) override final {
|
||||
void set_rom(ROMType type, const std::vector<uint8_t> &data) override final {
|
||||
roms_[static_cast<int>(type)] = data;
|
||||
}
|
||||
|
||||
// Obtains the system ROMs.
|
||||
bool install_roms(const std::function<std::unique_ptr<std::vector<uint8_t>>(const std::string &machine, const std::string &name)> &rom_with_name) override {
|
||||
const char *os_files[] = {
|
||||
"os464.rom", "basic464.rom",
|
||||
"os664.rom", "basic664.rom",
|
||||
"os6128.rom", "basic6128.rom",
|
||||
"amsdos.rom"
|
||||
};
|
||||
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> &roms_with_names) override {
|
||||
auto roms = roms_with_names(
|
||||
"AmstradCPC",
|
||||
{
|
||||
"os464.rom", "basic464.rom",
|
||||
"os664.rom", "basic664.rom",
|
||||
"os6128.rom", "basic6128.rom",
|
||||
"amsdos.rom"
|
||||
});
|
||||
|
||||
for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) {
|
||||
auto data = rom_with_name("AmstradCPC", os_files[index]);
|
||||
for(size_t index = 0; index < roms.size(); ++index) {
|
||||
auto &data = roms[index];
|
||||
if(!data) return false;
|
||||
set_rom(static_cast<ROMType>(index), *data);
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ class Machine:
|
||||
static Machine *AmstradCPC();
|
||||
|
||||
/// Sets the contents of rom @c type to @c data. Assumed to be a setup step; has no effect once a machine is running.
|
||||
virtual void set_rom(ROMType type, std::vector<uint8_t> data) = 0;
|
||||
virtual void set_rom(ROMType type, const std::vector<uint8_t> &data) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "../Outputs/CRT/CRT.hpp"
|
||||
#include "../Outputs/Speaker.hpp"
|
||||
#include "../ClockReceiver/ClockReceiver.hpp"
|
||||
#include "ROMMachine.hpp"
|
||||
|
||||
namespace CRTMachine {
|
||||
|
||||
@ -20,7 +21,7 @@ namespace CRTMachine {
|
||||
that optionally provide a speaker, and that nominate a clock rate and can announce to a delegate
|
||||
should that clock rate change.
|
||||
*/
|
||||
class Machine {
|
||||
class Machine: public ROMMachine::Machine {
|
||||
public:
|
||||
Machine() : clock_is_unlimited_(false), delegate_(nullptr) {}
|
||||
|
||||
@ -36,11 +37,6 @@ class Machine {
|
||||
*/
|
||||
virtual void close_output() = 0;
|
||||
|
||||
/*!
|
||||
Provides the machine with a way to obtain such ROMs as it needs.
|
||||
*/
|
||||
virtual bool install_roms(const std::function<std::unique_ptr<std::vector<uint8_t>>(const std::string &machine, const std::string &name)> &rom_with_name) { return true; }
|
||||
|
||||
/// @returns The CRT this machine is drawing to. Should not be @c nullptr.
|
||||
virtual std::shared_ptr<Outputs::CRT::CRT> get_crt() = 0;
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define Commodore1540_hpp
|
||||
|
||||
#include "../SerialBus.hpp"
|
||||
#include "../../ROMMachine.hpp"
|
||||
#include "../../../Storage/Disk/Disk.hpp"
|
||||
#include "Implementation/C1540Base.hpp"
|
||||
|
||||
@ -19,12 +20,18 @@ namespace C1540 {
|
||||
/*!
|
||||
Provides an emulation of the C1540.
|
||||
*/
|
||||
class Machine: public MachineBase {
|
||||
class Machine: public MachineBase, public ROMMachine::Machine {
|
||||
public:
|
||||
enum Personality {
|
||||
C1540,
|
||||
C1541
|
||||
};
|
||||
Machine(Personality p);
|
||||
|
||||
/*!
|
||||
Sets the ROM image to use for this drive; it is asserted that the buffer provided is 16 kb in size.
|
||||
Sets the source for this drive's ROM image.
|
||||
*/
|
||||
void set_rom(const std::vector<uint8_t> &rom);
|
||||
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> &roms_with_names);
|
||||
|
||||
/*!
|
||||
Sets the serial bus to which this drive should attach itself.
|
||||
@ -36,6 +43,9 @@ class Machine: public MachineBase {
|
||||
|
||||
/// Inserts @c disk into the drive.
|
||||
void set_disk(std::shared_ptr<Storage::Disk::Disk> disk);
|
||||
|
||||
private:
|
||||
Personality personality_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ MachineBase::MachineBase() :
|
||||
set_drive(drive_);
|
||||
}
|
||||
|
||||
Machine::Machine(Commodore::C1540::Machine::Personality personality) : personality_(personality) {}
|
||||
|
||||
void Machine::set_serial_bus(std::shared_ptr<::Commodore::Serial::Bus> serial_bus) {
|
||||
Commodore::Serial::AttachPortAndBus(serial_port_, serial_bus);
|
||||
}
|
||||
@ -80,9 +82,17 @@ Cycles MachineBase::perform_bus_operation(CPU::MOS6502::BusOperation operation,
|
||||
return Cycles(1);
|
||||
}
|
||||
|
||||
void Machine::set_rom(const std::vector<uint8_t> &rom) {
|
||||
assert(rom.size() == sizeof(rom_));
|
||||
memcpy(rom_, rom.data(), std::min(sizeof(rom_), rom.size()));
|
||||
bool Machine::set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> &roms_with_names) {
|
||||
std::string rom_name;
|
||||
switch(personality_) {
|
||||
case Personality::C1540: rom_name = "1540.bin"; break;
|
||||
case Personality::C1541: rom_name = "1541.bin"; break;
|
||||
}
|
||||
|
||||
auto roms = roms_with_names("Commodore1540", {rom_name});
|
||||
if(!roms[0]) return false;
|
||||
memcpy(rom_, roms[0]->data(), std::min(sizeof(rom_), roms[0]->size()));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Machine::set_disk(std::shared_ptr<Storage::Disk::Disk> disk) {
|
||||
|
@ -37,6 +37,18 @@ enum JoystickInput {
|
||||
Fire = 0x20
|
||||
};
|
||||
|
||||
enum ROM {
|
||||
CharactersDanish = 0,
|
||||
CharactersEnglish,
|
||||
CharactersJapanese,
|
||||
CharactersSwedish,
|
||||
KernelDanish,
|
||||
KernelJapanese,
|
||||
KernelNTSC,
|
||||
KernelPAL,
|
||||
KernelSwedish
|
||||
};
|
||||
|
||||
/*!
|
||||
Models the user-port VIA, which is the Vic's connection point for controlling its tape recorder —
|
||||
sensing the presence or absence of a tape and controlling the tape motor — and reading the current
|
||||
@ -280,12 +292,6 @@ class ConcreteMachine:
|
||||
keyboard_via_port_handler_->set_interrupt_delegate(this);
|
||||
tape_->set_delegate(this);
|
||||
|
||||
// establish the memory maps
|
||||
set_memory_size(MemorySize::Default);
|
||||
|
||||
// set the NTSC clock rate
|
||||
set_region(NTSC);
|
||||
|
||||
// install a joystick
|
||||
joysticks_.emplace_back(new Joystick(*user_port_via_port_handler_, *keyboard_via_port_handler_));
|
||||
}
|
||||
@ -294,24 +300,32 @@ class ConcreteMachine:
|
||||
delete[] rom_;
|
||||
}
|
||||
|
||||
void set_rom(ROMSlot slot, size_t length, const uint8_t *data) override final {
|
||||
uint8_t *target = nullptr;
|
||||
size_t max_length = 0x2000;
|
||||
switch(slot) {
|
||||
case Kernel: target = kernel_rom_; break;
|
||||
case Characters: target = character_rom_; max_length = 0x1000; break;
|
||||
case BASIC: target = basic_rom_; break;
|
||||
case Drive:
|
||||
drive_rom_.resize(length);
|
||||
memcpy(drive_rom_.data(), data, length);
|
||||
install_disk_rom();
|
||||
return;
|
||||
}
|
||||
void set_rom(ROMSlot slot, const std::vector<uint8_t> &data) override final {
|
||||
}
|
||||
|
||||
if(target) {
|
||||
size_t length_to_copy = std::min(max_length, length);
|
||||
memcpy(target, data, length_to_copy);
|
||||
// Obtains the system ROMs.
|
||||
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> &roms_with_names) override {
|
||||
auto roms = roms_with_names(
|
||||
"Vic20",
|
||||
{
|
||||
"characters-danish.bin",
|
||||
"characters-english.bin",
|
||||
"characters-japanese.bin",
|
||||
"characters-swedish.bin",
|
||||
"kernel-danish.bin",
|
||||
"kernel-japanese.bin",
|
||||
"kernel-ntsc.bin",
|
||||
"kernel-pal.bin",
|
||||
"kernel-swedish.bin",
|
||||
"basic.bin"
|
||||
});
|
||||
|
||||
for(size_t index = 0; index < roms.size(); ++index) {
|
||||
auto &data = roms[index];
|
||||
if(!data) return false;
|
||||
if(index < 9) roms_[index] = *data; else basic_rom_ = *data;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void configure_as_target(const StaticAnalyser::Target &target) override final {
|
||||
@ -333,13 +347,13 @@ class ConcreteMachine:
|
||||
|
||||
if(target.media.disks.size()) {
|
||||
// construct the 1540
|
||||
c1540_.reset(new ::Commodore::C1540::Machine);
|
||||
c1540_.reset(new ::Commodore::C1540::Machine(Commodore::C1540::Machine::C1540));
|
||||
|
||||
// attach it to the serial bus
|
||||
c1540_->set_serial_bus(serial_bus_);
|
||||
|
||||
// install the ROM if it was previously set
|
||||
install_disk_rom();
|
||||
// give it a means to obtain its ROM
|
||||
c1540_->set_rom_fetcher(rom_fetcher_);
|
||||
}
|
||||
|
||||
insert_media(target.media);
|
||||
@ -383,10 +397,38 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
void set_memory_size(MemorySize size) override final {
|
||||
memory_size_ = size;
|
||||
needs_configuration_ = true;
|
||||
}
|
||||
|
||||
void set_region(Region region) override final {
|
||||
region_ = region;
|
||||
needs_configuration_ = true;
|
||||
}
|
||||
|
||||
void configure_memory() {
|
||||
// Determine PAL/NTSC
|
||||
if(region_ == American || region_ == Japanese) {
|
||||
// NTSC
|
||||
set_clock_rate(1022727);
|
||||
if(mos6560_) {
|
||||
mos6560_->set_output_mode(MOS::MOS6560<Commodore::Vic20::Vic6560>::OutputMode::NTSC);
|
||||
mos6560_->set_clock_rate(1022727);
|
||||
}
|
||||
} else {
|
||||
// PAL
|
||||
set_clock_rate(1108404);
|
||||
if(mos6560_) {
|
||||
mos6560_->set_output_mode(MOS::MOS6560<Commodore::Vic20::Vic6560>::OutputMode::PAL);
|
||||
mos6560_->set_clock_rate(1108404);
|
||||
}
|
||||
}
|
||||
|
||||
memset(processor_read_memory_map_, 0, sizeof(processor_read_memory_map_));
|
||||
memset(processor_write_memory_map_, 0, sizeof(processor_write_memory_map_));
|
||||
memset(mos6560_->video_memory_map, 0, sizeof(mos6560_->video_memory_map));
|
||||
|
||||
switch(size) {
|
||||
switch(memory_size_) {
|
||||
default: break;
|
||||
case ThreeKB:
|
||||
write_to_map(processor_read_memory_map_, expansion_ram_, 0x0000, 0x1000);
|
||||
@ -402,40 +444,52 @@ class ConcreteMachine:
|
||||
write_to_map(processor_read_memory_map_, user_basic_memory_, 0x0000, sizeof(user_basic_memory_));
|
||||
write_to_map(processor_read_memory_map_, screen_memory_, 0x1000, sizeof(screen_memory_));
|
||||
write_to_map(processor_read_memory_map_, colour_memory_, 0x9400, sizeof(colour_memory_));
|
||||
write_to_map(processor_read_memory_map_, character_rom_, 0x8000, sizeof(character_rom_));
|
||||
write_to_map(processor_read_memory_map_, basic_rom_, 0xc000, sizeof(basic_rom_));
|
||||
write_to_map(processor_read_memory_map_, kernel_rom_, 0xe000, sizeof(kernel_rom_));
|
||||
|
||||
write_to_map(processor_write_memory_map_, user_basic_memory_, 0x0000, sizeof(user_basic_memory_));
|
||||
write_to_map(processor_write_memory_map_, screen_memory_, 0x1000, sizeof(screen_memory_));
|
||||
write_to_map(processor_write_memory_map_, colour_memory_, 0x9400, sizeof(colour_memory_));
|
||||
|
||||
write_to_map(mos6560_->video_memory_map, user_basic_memory_, 0x2000, sizeof(user_basic_memory_));
|
||||
write_to_map(mos6560_->video_memory_map, screen_memory_, 0x3000, sizeof(screen_memory_));
|
||||
mos6560_->colour_memory = colour_memory_;
|
||||
|
||||
write_to_map(processor_read_memory_map_, basic_rom_.data(), 0xc000, basic_rom_.size());
|
||||
|
||||
ROM character_rom;
|
||||
ROM kernel_rom;
|
||||
switch(region_) {
|
||||
case American:
|
||||
character_rom = CharactersEnglish;
|
||||
kernel_rom = KernelNTSC;
|
||||
break;
|
||||
case Danish:
|
||||
character_rom = CharactersDanish;
|
||||
kernel_rom = KernelDanish;
|
||||
break;
|
||||
case Japanese:
|
||||
character_rom = CharactersJapanese;
|
||||
kernel_rom = KernelJapanese;
|
||||
break;
|
||||
case European:
|
||||
character_rom = CharactersEnglish;
|
||||
kernel_rom = KernelPAL;
|
||||
break;
|
||||
case Swedish:
|
||||
character_rom = CharactersSwedish;
|
||||
kernel_rom = KernelSwedish;
|
||||
break;
|
||||
}
|
||||
|
||||
write_to_map(processor_read_memory_map_, roms_[character_rom].data(), 0x8000, roms_[character_rom].size());
|
||||
write_to_map(mos6560_->video_memory_map, roms_[character_rom].data(), 0x0000, roms_[character_rom].size());
|
||||
write_to_map(processor_read_memory_map_, roms_[kernel_rom].data(), 0xe000, roms_[kernel_rom].size());
|
||||
|
||||
// install the inserted ROM if there is one
|
||||
if(rom_) {
|
||||
write_to_map(processor_read_memory_map_, rom_, rom_address_, rom_length_);
|
||||
}
|
||||
}
|
||||
|
||||
void set_region(Region region) override final {
|
||||
region_ = region;
|
||||
switch(region) {
|
||||
case PAL:
|
||||
set_clock_rate(1108404);
|
||||
if(mos6560_) {
|
||||
mos6560_->set_output_mode(MOS::MOS6560<Commodore::Vic20::Vic6560>::OutputMode::PAL);
|
||||
mos6560_->set_clock_rate(1108404);
|
||||
}
|
||||
break;
|
||||
case NTSC:
|
||||
set_clock_rate(1022727);
|
||||
if(mos6560_) {
|
||||
mos6560_->set_output_mode(MOS::MOS6560<Commodore::Vic20::Vic6560>::OutputMode::NTSC);
|
||||
mos6560_->set_clock_rate(1022727);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void set_use_fast_tape_hack(bool activate) override final {
|
||||
use_fast_tape_hack_ = activate;
|
||||
}
|
||||
@ -542,19 +596,16 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
void run_for(const Cycles cycles) override final {
|
||||
if(needs_configuration_) {
|
||||
needs_configuration_ = false;
|
||||
configure_memory();
|
||||
}
|
||||
m6502_.run_for(cycles);
|
||||
}
|
||||
|
||||
void setup_output(float aspect_ratio) override final {
|
||||
mos6560_.reset(new Vic6560());
|
||||
mos6560_->get_speaker()->set_high_frequency_cut_off(1600); // There is a 1.6Khz low-pass filter in the Vic-20.
|
||||
set_region(region_);
|
||||
|
||||
memset(mos6560_->video_memory_map, 0, sizeof(mos6560_->video_memory_map));
|
||||
write_to_map(mos6560_->video_memory_map, character_rom_, 0x0000, sizeof(character_rom_));
|
||||
write_to_map(mos6560_->video_memory_map, user_basic_memory_, 0x2000, sizeof(user_basic_memory_));
|
||||
write_to_map(mos6560_->video_memory_map, screen_memory_, 0x3000, sizeof(screen_memory_));
|
||||
mos6560_->colour_memory = colour_memory_;
|
||||
}
|
||||
|
||||
void close_output() override final {
|
||||
@ -590,9 +641,11 @@ class ConcreteMachine:
|
||||
private:
|
||||
CPU::MOS6502::Processor<ConcreteMachine, false> m6502_;
|
||||
|
||||
uint8_t character_rom_[0x1000];
|
||||
uint8_t basic_rom_[0x2000];
|
||||
uint8_t kernel_rom_[0x2000];
|
||||
std::vector<uint8_t> roms_[9];
|
||||
|
||||
std::vector<uint8_t> character_rom_;
|
||||
std::vector<uint8_t> basic_rom_;
|
||||
std::vector<uint8_t> kernel_rom_;
|
||||
uint8_t expansion_ram_[0x8000];
|
||||
|
||||
uint8_t *rom_;
|
||||
@ -601,7 +654,8 @@ class ConcreteMachine:
|
||||
uint8_t user_basic_memory_[0x0400];
|
||||
uint8_t screen_memory_[0x1000];
|
||||
uint8_t colour_memory_[0x0400];
|
||||
std::vector<uint8_t> drive_rom_;
|
||||
|
||||
std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> rom_fetcher_;
|
||||
|
||||
uint8_t *processor_read_memory_map_[64];
|
||||
uint8_t *processor_write_memory_map_[64];
|
||||
@ -615,7 +669,10 @@ class ConcreteMachine:
|
||||
}
|
||||
}
|
||||
|
||||
Region region_;
|
||||
Region region_ = European;
|
||||
MemorySize memory_size_ = MemorySize::Default;
|
||||
bool needs_configuration_ = true;
|
||||
|
||||
Commodore::Vic20::KeyboardMapper keyboard_mapper_;
|
||||
std::vector<std::unique_ptr<Inputs::Joystick>> joysticks_;
|
||||
|
||||
@ -635,13 +692,6 @@ class ConcreteMachine:
|
||||
|
||||
// Disk
|
||||
std::shared_ptr<::Commodore::C1540::Machine> c1540_;
|
||||
void install_disk_rom() {
|
||||
if(!drive_rom_.empty() && c1540_) {
|
||||
c1540_->set_rom(drive_rom_);
|
||||
c1540_->run_for(Cycles(2000000));
|
||||
drive_rom_.clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ namespace Commodore {
|
||||
namespace Vic20 {
|
||||
|
||||
enum ROMSlot {
|
||||
Kernel,
|
||||
Kernel = 0,
|
||||
BASIC,
|
||||
Characters,
|
||||
Drive
|
||||
@ -33,8 +33,11 @@ enum MemorySize {
|
||||
};
|
||||
|
||||
enum Region {
|
||||
NTSC,
|
||||
PAL
|
||||
American,
|
||||
Danish,
|
||||
Japanese,
|
||||
European,
|
||||
Swedish
|
||||
};
|
||||
|
||||
class Machine:
|
||||
@ -49,8 +52,7 @@ class Machine:
|
||||
static Machine *Vic20();
|
||||
|
||||
/// Sets the contents of the rom in @c slot to the buffer @c data of length @c length.
|
||||
virtual void set_rom(ROMSlot slot, size_t length, const uint8_t *data) = 0;
|
||||
// TODO: take a std::vector<uint8_t> to collapse length and data.
|
||||
virtual void set_rom(ROMSlot slot, const std::vector<uint8_t> &data) = 0;
|
||||
|
||||
/// Sets the memory size of this Vic-20.
|
||||
virtual void set_memory_size(MemorySize size) = 0;
|
||||
|
@ -39,7 +39,7 @@ class ConcreteMachine:
|
||||
set_clock_rate(2000000);
|
||||
}
|
||||
|
||||
void set_rom(ROMSlot slot, std::vector<uint8_t> data, bool is_writeable) override final {
|
||||
void set_rom(ROMSlot slot, const std::vector<uint8_t> &data, bool is_writeable) override final {
|
||||
uint8_t *target = nullptr;
|
||||
switch(slot) {
|
||||
case ROMSlotDFS: dfs_ = data; return;
|
||||
@ -57,20 +57,22 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
// Obtains the system ROMs.
|
||||
bool install_roms(const std::function<std::unique_ptr<std::vector<uint8_t>>(const std::string &machine, const std::string &name)> &rom_with_name) override {
|
||||
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> &roms_with_names) override {
|
||||
auto roms = roms_with_names(
|
||||
"Electron",
|
||||
{
|
||||
"DFS-1770-2.20.rom",
|
||||
"ADFS-E00_1.rom", "ADFS-E00_2.rom",
|
||||
"basic.rom", "os.rom"
|
||||
});
|
||||
ROMSlot slots[] = {
|
||||
ROMSlotDFS,
|
||||
ROMSlotADFS1, ROMSlotADFS2,
|
||||
ROMSlotBASIC, ROMSlotOS
|
||||
};
|
||||
const char *os_files[] = {
|
||||
"DFS-1770-2.20.rom",
|
||||
"ADFS-E00_1.rom", "ADFS-E00_2.rom",
|
||||
"basic.rom", "os.rom"
|
||||
};
|
||||
|
||||
for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) {
|
||||
auto data = rom_with_name("Electron", os_files[index]);
|
||||
for(size_t index = 0; index < roms.size(); ++index) {
|
||||
auto &data = roms[index];
|
||||
if(!data) return false;
|
||||
set_rom(slots[index], *data, false);
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class Machine:
|
||||
Sets the contents of @c slot to @c data. If @c is_writeable is @c true then writing to the slot
|
||||
is enabled — it acts as if it were sideways RAM. Otherwise the slot is modelled as containing ROM.
|
||||
*/
|
||||
virtual void set_rom(ROMSlot slot, std::vector<uint8_t> data, bool is_writeable) = 0;
|
||||
virtual void set_rom(ROMSlot slot, const std::vector<uint8_t> &data, bool is_writeable) = 0;
|
||||
|
||||
/// Enables or disables turbo-speed tape loading.
|
||||
virtual void set_use_fast_tape_hack(bool activate) = 0;
|
||||
|
@ -204,14 +204,16 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
// Obtains the system ROMs.
|
||||
bool install_roms(const std::function<std::unique_ptr<std::vector<uint8_t>>(const std::string &machine, const std::string &name)> &rom_with_name) override {
|
||||
const char *os_files[] = {
|
||||
"basic10.rom", "basic11.rom",
|
||||
"microdisc.rom", "colour.rom"
|
||||
};
|
||||
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> &roms_with_names) override {
|
||||
auto roms = roms_with_names(
|
||||
"Oric",
|
||||
{
|
||||
"basic10.rom", "basic11.rom",
|
||||
"microdisc.rom", "colour.rom"
|
||||
});
|
||||
|
||||
for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) {
|
||||
auto data = rom_with_name("Oric", os_files[index]);
|
||||
for(size_t index = 0; index < roms.size(); ++index) {
|
||||
auto &data = roms[index];
|
||||
if(!data) return false;
|
||||
set_rom(static_cast<ROM>(index), *data);
|
||||
}
|
||||
|
27
Machines/ROMMachine.hpp
Normal file
27
Machines/ROMMachine.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// ROMMachine.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 07/11/2017.
|
||||
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef ROMMachine_hpp
|
||||
#define ROMMachine_hpp
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace ROMMachine {
|
||||
|
||||
struct Machine {
|
||||
/*!
|
||||
Provides the machine with a way to obtain such ROMs as it needs.
|
||||
*/
|
||||
virtual bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> &rom_with_name) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* ROMMachine_h */
|
@ -290,7 +290,7 @@ template<bool is_zx81> class ConcreteMachine:
|
||||
Utility::TypeRecipient::set_typer_for_string(string, std::move(mapper));
|
||||
}
|
||||
|
||||
void set_rom(ROMType type, std::vector<uint8_t> data) override final {
|
||||
void set_rom(ROMType type, const std::vector<uint8_t> &data) override final {
|
||||
switch(type) {
|
||||
case ZX80: zx80_rom_ = data; break;
|
||||
case ZX81: zx81_rom_ = data; break;
|
||||
@ -298,13 +298,15 @@ template<bool is_zx81> class ConcreteMachine:
|
||||
}
|
||||
|
||||
// Obtains the system ROMs.
|
||||
bool install_roms(const std::function<std::unique_ptr<std::vector<uint8_t>>(const std::string &machine, const std::string &name)> &rom_with_name) override {
|
||||
const char *os_files[] = {
|
||||
"zx80.rom", "zx81.rom",
|
||||
};
|
||||
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> &roms_with_names) override {
|
||||
auto roms = roms_with_names(
|
||||
"ZX8081",
|
||||
{
|
||||
"zx80.rom", "zx81.rom",
|
||||
});
|
||||
|
||||
for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) {
|
||||
auto data = rom_with_name("ZX8081", os_files[index]);
|
||||
for(size_t index = 0; index < roms.size(); ++index) {
|
||||
auto &data = roms[index];
|
||||
if(!data) return false;
|
||||
set_rom(static_cast<ROMType>(index), *data);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ class Machine:
|
||||
static Machine *ZX8081(const StaticAnalyser::Target &target_hint);
|
||||
virtual ~Machine();
|
||||
|
||||
virtual void set_rom(ROMType type, std::vector<uint8_t> data) = 0;
|
||||
virtual void set_rom(ROMType type, const std::vector<uint8_t> &data) = 0;
|
||||
|
||||
virtual void set_use_fast_tape_hack(bool activate) = 0;
|
||||
virtual void set_tape_is_playing(bool is_playing) = 0;
|
||||
|
@ -1210,6 +1210,7 @@
|
||||
4BD5F1931D13528900631CD1 /* CSBestEffortUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSBestEffortUpdater.h; path = Updater/CSBestEffortUpdater.h; sourceTree = "<group>"; };
|
||||
4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CSBestEffortUpdater.mm; path = Updater/CSBestEffortUpdater.mm; sourceTree = "<group>"; };
|
||||
4BD9137D1F311BC5009BCF85 /* i8255.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = i8255.hpp; path = 8255/i8255.hpp; sourceTree = "<group>"; };
|
||||
4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ROMMachine.hpp; sourceTree = "<group>"; };
|
||||
4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MachineCycleTests.swift; sourceTree = "<group>"; };
|
||||
4BE77A2C1D84ADFB00BC3827 /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = File.cpp; path = ../../StaticAnalyser/Commodore/File.cpp; sourceTree = "<group>"; };
|
||||
4BE77A2D1D84ADFB00BC3827 /* File.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = File.hpp; path = ../../StaticAnalyser/Commodore/File.hpp; sourceTree = "<group>"; };
|
||||
@ -2352,6 +2353,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */,
|
||||
4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */,
|
||||
4BA9C3CF1D8164A9002DDB61 /* ConfigurationTarget.hpp */,
|
||||
4B046DC31CFE651500E9E45E /* CRTMachine.hpp */,
|
||||
4B7041271F92C26900735E45 /* JoystickMachine.hpp */,
|
||||
|
@ -179,25 +179,33 @@ int main(int argc, char *argv[]) {
|
||||
//
|
||||
// /usr/local/share/CLK/[system]; or
|
||||
// /usr/share/CLK/[system]
|
||||
machine->crt_machine()->install_roms( [] (const std::string &machine, const std::string &name) -> std::unique_ptr<std::vector<uint8_t>> {
|
||||
std::string local_path = "/usr/local/share/CLK/" + machine + "/" + name;
|
||||
FILE *file = fopen(local_path.c_str(), "r");
|
||||
if(!file) {
|
||||
std::string path = "/usr/share/CLK/" + machine + "/" + name;
|
||||
file = fopen(path.c_str(), "r");
|
||||
machine->crt_machine()->set_rom_fetcher( [] (const std::string &machine, const std::vector<std::string> &names) -> std::vector<std::unique_ptr<std::vector<uint8_t>>> {
|
||||
std::vector<std::unique_ptr<std::vector<uint8_t>>> results;
|
||||
for(auto &name: names) {
|
||||
std::string local_path = "/usr/local/share/CLK/" + machine + "/" + name;
|
||||
FILE *file = fopen(local_path.c_str(), "r");
|
||||
if(!file) {
|
||||
std::string path = "/usr/share/CLK/" + machine + "/" + name;
|
||||
file = fopen(path.c_str(), "r");
|
||||
}
|
||||
|
||||
if(!file) {
|
||||
results.emplace_back(nullptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>);
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
data->resize(ftell(file));
|
||||
fseek(file, 0, SEEK_SET);
|
||||
fread(data->data(), 1, data->size(), file);
|
||||
fclose(file);
|
||||
|
||||
results.emplace_back(std::move(data));
|
||||
}
|
||||
|
||||
if(!file) return nullptr;
|
||||
|
||||
std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>);
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
data->resize(ftell(file));
|
||||
fseek(file, 0, SEEK_SET);
|
||||
fread(data->data(), 1, data->size(), file);
|
||||
fclose(file);
|
||||
|
||||
return data;
|
||||
return results;
|
||||
});
|
||||
|
||||
machine->configuration_target()->configure_as_target(targets.front());
|
||||
|
Loading…
Reference in New Issue
Block a user