From d5c2a0d2b5f4969565de7126b645de71ef17c69a Mon Sep 17 00:00:00 2001 From: magnetrwn Date: Sat, 9 Nov 2024 00:44:29 +0100 Subject: [PATCH] Working toward CP/M support. --- src/core/bus/bus.hpp | 2 +- src/core/bus/card.hpp | 3 +- src/ux/ux.hpp | 4 +-- static/config.toml | 70 ++++++++++++++++++++++++++++++------------- tests/test_pty.hpp | 15 ++++++++-- 5 files changed, 67 insertions(+), 27 deletions(-) diff --git a/src/core/bus/bus.hpp b/src/core/bus/bus.hpp index c620107..bb1a683 100644 --- a/src/core/bus/bus.hpp +++ b/src/core/bus/bus.hpp @@ -136,7 +136,7 @@ class bus { inline void insert(card* card, usize slot, bool allow_conflict = false) { if (!card) throw std::invalid_argument("cannot insert nullptr"); - if (slot >= MAX_BUS_CARDS) + if (slot > MAX_BUS_CARDS) throw std::out_of_range("slot out of range"); if (cards[slot] != NO_CARD) throw std::invalid_argument("slot already occupied"); diff --git a/src/core/bus/card.hpp b/src/core/bus/card.hpp index 4f9c801..1929827 100644 --- a/src/core/bus/card.hpp +++ b/src/core/bus/card.hpp @@ -180,8 +180,7 @@ class data_card : public card { data_card(u16 start_adr, T begin, T end, bool lock = construct_then_write_lock) : start_adr(start_adr), capacity(std::distance(begin, end)) { - static_assert(std::is_same_v::value_type, u8>, - "Iterator value type must be u8."); + static_assert(std::is_same_v::value_type, u8>, "Iterator value type must be u8."); data.reserve(capacity); std::copy(begin, end, data.begin()); diff --git a/src/ux/ux.hpp b/src/ux/ux.hpp index 17c0c75..3ce9fc0 100644 --- a/src/ux/ux.hpp +++ b/src/ux/ux.hpp @@ -51,7 +51,7 @@ class emulator { } } - std::string get_bus_map_s() const { return cardbus.bus_map_s(); } + std::string info() const { return cardbus.bus_map_s(); } emulator(const char* config_filename) : conf(config_filename), @@ -65,7 +65,7 @@ struct terminal_ux { int main(int argc, char** argv) { std::cout << "\x1B[33;01m-:-:-:-:- emulator setup -:-:-:-:-\x1B[0m" << std::endl; - std::cout << emu.get_bus_map_s(); + std::cout << emu.info(); emu.setup(argc, argv); std::cout << "\x1B[33;01m-:-:-:-:- emulator run -:-:-:-:-\x1B[0m" << std::endl; diff --git a/static/config.toml b/static/config.toml index df28af6..11e4910 100644 --- a/static/config.toml +++ b/static/config.toml @@ -1,31 +1,61 @@ -# Configuration file for the emulator. -# This file is loaded by the emulator to understand how to configure the system. +############################################################################################################ +# Configuration file for the emulator. # +# This file is loaded by the emulator to understand how to configure the system. # +############################################################################################################ + +# -------------------------------------------- GENERAL SETUP --------------------------------------------- # [emulator] pseudo_bdos_enabled = true # Redirect and handle calls that match addresses of BDOS calls. -start_with_pc_at = 0x0100 # Start the program counter at this address. Note that this bypasses the reset vector. 0 to disable. - -# List of cards here, make sure to append cards you wish to add. Available parameters are: -# - slot: Slot number of the card [0, 18], which also determines IRQ priority (lower is higher priority). -# - type: Type of the card. Available types are: "ram", "rom", "serial". -# - load: Path to the file to load into the card. Only for "ram" or "rom" type. -# (you can omit this if using range, as it will automatically set the closest bigger power of 2 size) -# - at: Address of the card in the memory space. -# - range: Size or address range (like I/O register count) of the card in bytes. -# (you can omit this if using load) -# - let_collide: Allow the card to have overlapping address range with other cards. -# -# IMPORTANT: cards can be de/activated by the IORQ signal according to them being memory or I/O, so -# you might not need to enable overlapping, as overlap of I/O and memory is expected. -# Only use this in case of overlap of the same type of card (e.g. two RAM cards). -# -# Note: there is (usually) a limit of 18 cards in the system. Lower slot number means higher IRQ priority. +start_with_pc_at = 0x0100 # Start the program counter at this address. Note that this bypasses the reset vector. 0 or comment to disable. + +############################################################################################################ +# List of cards here, make sure to append cards you wish to add. Available parameters are: # +# - slot: Slot number of the card [0, 18], which also determines IRQ priority (lower is higher priority). # +# - type: Type of the card. Available types are: "ram", "rom", "serial". # +# - load: Path to the file to load into the card. Only for "ram" or "rom" type. # +# (you can omit this if using range, as it will automatically set the closest bigger power of 2 size) # +# - at: Address of the card in the memory space. # +# - range: Size or address range (like I/O register count) of the card in bytes. # +# (you can omit this if using load) # +# - let_collide: Allow the card to have overlapping address range with other cards. # +# # +# IMPORTANT: cards can be de/activated by the IORQ signal according to them being memory or I/O, so # +# you might not need to enable overlapping, as overlap of I/O and memory is expected. # +# Only use this in case of overlap of the same type of card (e.g. two RAM cards). # +# # +# Note: there is (usually) a limit of 18 cards in the system. Lower slot number means higher IRQ priority. # +############################################################################################################ + +# -------------------------------------------- CP/M ROM CARDS -------------------------------------------- # + +# [[card]] # CP/M 2.2 BIOS +# slot = 0 +# type = "rom" +# at = 0x0000 +# load = "static/bios22.bin" +# +# [[card]] # CP/M 2.2 BDOS +# slot = 1 +# type = "rom" +# at = 0x8000 +# load = "static/bdos22.bin" +# +# [[card]] # CP/M 2.2 CCP +# slot = 2 +# type = "rom" +# at = 0xC000 +# load = "static/ccp22.bin" + +# ------------------------------------------ I/O HARDWARE CARDS ------------------------------------------ # [[card]] # 88-SIO serial interface slot = 10 type = "serial" at = 0x10 +# -------------------------------------------- SOFTWARE CARDS -------------------------------------------- # + [[card]] # Diagnostics II expects to be loaded in RAM slot = 3 type = "ram" @@ -33,7 +63,7 @@ at = 0x0100 load = "tests/res/diag2.com" [[card]] # Cover all memory space with RAM just in case -slot = 4 +slot = 17 type = "ram" at = 0x0000 range = 65536 diff --git a/tests/test_pty.hpp b/tests/test_pty.hpp index b05bde1..80b9a84 100644 --- a/tests/test_pty.hpp +++ b/tests/test_pty.hpp @@ -7,7 +7,8 @@ #include "pty.hpp" constexpr static usize BUFFER_SIZE = 1024; -constexpr static usize ROUNDS = 51; +constexpr static usize ROUNDS = 384; +constexpr static usize USEC_DELAY_SERIAL_PTY = 110; inline const char* random_string(usize length) { static std::random_device rd; @@ -109,7 +110,7 @@ TEST_CASE("Pseudo-terminal operation test", "[pty]") { isize bytes_written = write(slave_fd, message, std::strlen(message)); REQUIRE(bytes_written == static_cast(std::strlen(message))); - usleep(100 * (ROUNDS - i)); + usleep(USEC_DELAY_SERIAL_PTY); REQUIRE(pty_instance.poll()); for (usize j = 0; pty_instance.poll(); ++j) @@ -117,6 +118,16 @@ TEST_CASE("Pseudo-terminal operation test", "[pty]") { REQUIRE(!pty_instance.poll()); } + + for (char c = 1; c > 0; ++c) { + isize bytes_written = write(slave_fd, &c, 1); + REQUIRE(bytes_written == 1); + + usleep(USEC_DELAY_SERIAL_PTY); + REQUIRE(pty_instance.poll()); + REQUIRE(pty_instance.getch() == c); + REQUIRE(!pty_instance.poll()); + } } close(slave_fd);