1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-25 03:32:01 +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:
Thomas Harte 2017-11-07 21:19:51 -05:00
parent 35da3edf60
commit ddcdd07dd0
15 changed files with 252 additions and 139 deletions

View File

@ -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[] = {
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);
}

View File

@ -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;
};
}

View File

@ -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;

View File

@ -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_;
};
}

View File

@ -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) {

View File

@ -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();
}
}
};
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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[] = {
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
View 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 */

View File

@ -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[] = {
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);
}

View File

@ -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;

View File

@ -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 */,

View File

@ -179,7 +179,9 @@ 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>> {
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) {
@ -187,7 +189,10 @@ int main(int argc, char *argv[]) {
file = fopen(path.c_str(), "r");
}
if(!file) return nullptr;
if(!file) {
results.emplace_back(nullptr);
continue;
}
std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>);
@ -197,7 +202,10 @@ int main(int argc, char *argv[]) {
fread(data->data(), 1, data->size(), file);
fclose(file);
return data;
results.emplace_back(std::move(data));
}
return results;
});
machine->configuration_target()->configure_as_target(targets.front());