#pragma once #include "IMemoryDevice.hpp" #include "../tools/GlobalData.hpp" #include #include #include namespace dragon { namespace hw { class VirtualHardDrive; class MemoryMapper; class VirtualCPU; class VirtualRAM; class VirtualBIOS : public IMemoryDevice { public: inline VirtualBIOS(void) { m_initialized = 0; } inline VirtualBIOS(const ostd::String& biosFilePath) { init(biosFilePath); } void init(const ostd::String& biosFilePath); int8_t read8(uint16_t addr) override; int16_t read16(uint16_t addr) override; int8_t write8(uint16_t addr, int8_t value) override; int16_t write16(uint16_t addr, int16_t value) override; ostd::ByteStream* getByteStream(void) override; private: ostd::ByteStream m_bios; bool m_initialized { false }; }; class InterruptVector : public IMemoryDevice { public: InterruptVector(void); int8_t read8(uint16_t addr) override; int16_t read16(uint16_t addr) override; int8_t write8(uint16_t addr, int8_t value) override; int16_t write16(uint16_t addr, int16_t value) override; ostd::ByteStream* getByteStream(void) override; private: ostd::ByteStream m_data; }; class VirtualKeyboard : public IMemoryDevice { public: enum class eKeys { Delete = (int16_t)'\x7F', Return = (int16_t)'\r', Escape = (int16_t)'\x1B', Backspace = (int16_t)'\b', Tab = (int16_t)'\t', Spacebar = (int16_t)' ', ExclamationMark = (int16_t)'!', DoubleQuote = (int16_t)'"', Hash = (int16_t)'#', Percent = (int16_t)'%', DollarSign = (int16_t)'$', Ampersand = (int16_t)'&', SingleQuote = (int16_t)'\'', LeftParenthesis = (int16_t)'(', RightParenthesis = (int16_t)')', Asterisk = (int16_t)'*', Plus = (int16_t)'+', Comma = (int16_t)',', Minus = (int16_t)'-', Period = (int16_t)'.', ForwardSlash = (int16_t)'/', Num0 = (int16_t)'0', Num1 = (int16_t)'1', Num2 = (int16_t)'2', Num3 = (int16_t)'3', Num4 = (int16_t)'4', Num5 = (int16_t)'5', Num6 = (int16_t)'6', Num7 = (int16_t)'7', Num8 = (int16_t)'8', Num9 = (int16_t)'9', Colon = (int16_t)':', Semicolon = (int16_t)';', LessThan = (int16_t)'<', Equals = (int16_t)'=', GreaterThan = (int16_t)'>', QuestionMark = (int16_t)'?', AtSign = (int16_t)'@', UpperCase_A = (int16_t)'A', UpperCase_B = (int16_t)'B', UpperCase_C = (int16_t)'C', UpperCase_D = (int16_t)'D', UpperCase_E = (int16_t)'E', UpperCase_F = (int16_t)'F', UpperCase_G = (int16_t)'G', UpperCase_H = (int16_t)'H', UpperCase_I = (int16_t)'I', UpperCase_J = (int16_t)'J', UpperCase_K = (int16_t)'K', UpperCase_L = (int16_t)'L', UpperCase_M = (int16_t)'M', UpperCase_N = (int16_t)'N', UpperCase_O = (int16_t)'O', UpperCase_P = (int16_t)'P', UpperCase_Q = (int16_t)'Q', UpperCase_R = (int16_t)'R', UpperCase_S = (int16_t)'S', UpperCase_T = (int16_t)'T', UpperCase_U = (int16_t)'U', UpperCase_V = (int16_t)'V', UpperCase_W = (int16_t)'W', UpperCase_X = (int16_t)'X', UpperCase_Y = (int16_t)'Y', UpperCase_Z = (int16_t)'Z', LeftBracket = (int16_t)'[', BackSlash = (int16_t)'\\', RightBracket = (int16_t)']', Caret = (int16_t)'^', Underscore = (int16_t)'_', BackQuote = (int16_t)'`', LowerCase_a = (int16_t)'a', LowerCase_b = (int16_t)'b', LowerCase_c = (int16_t)'c', LowerCase_d = (int16_t)'d', LowerCase_e = (int16_t)'e', LowerCase_f = (int16_t)'f', LowerCase_g = (int16_t)'g', LowerCase_h = (int16_t)'h', LowerCase_i = (int16_t)'i', LowerCase_j = (int16_t)'j', LowerCase_k = (int16_t)'k', LowerCase_l = (int16_t)'l', LowerCase_m = (int16_t)'m', LowerCase_n = (int16_t)'n', LowerCase_o = (int16_t)'o', LowerCase_p = (int16_t)'p', LowerCase_q = (int16_t)'q', LowerCase_r = (int16_t)'r', LowerCase_s = (int16_t)'s', LowerCase_t = (int16_t)'t', LowerCase_u = (int16_t)'u', LowerCase_v = (int16_t)'v', LowerCase_w = (int16_t)'w', LowerCase_x = (int16_t)'x', LowerCase_y = (int16_t)'y', LowerCase_z = (int16_t)'z', LeftCTRL = (int16_t)0x0100, RightCTRL = (int16_t)0x0101, LeftALT = (int16_t)0x0102, RightALT = (int16_t)0x0103, LeftShift = (int16_t)0x0104, RightShift = (int16_t)0x0105, KeyPadDivide = (int16_t)0x0106, KeyPadMultiply = (int16_t)0x0107, KeyPadMinus = (int16_t)0x0108, KeyPadPlus = (int16_t)0x0109, KeyPadEnter = (int16_t)0x010A, KeyPad1 = (int16_t)0x010B, KeyPad2 = (int16_t)0x010C, KeyPad3 = (int16_t)0x010D, KeyPad4 = (int16_t)0x010E, KeyPad5 = (int16_t)0x010F, KeyPad6 = (int16_t)0x0110, KeyPad7 = (int16_t)0x0111, KeyPad8 = (int16_t)0x0112, KeyPad9 = (int16_t)0x0113, KeyPad0 = (int16_t)0x0114, KeyPadPeriod = (int16_t)0x0115, PrintScreen = (int16_t)0x0116, Insert = (int16_t)0x0117, Home = (int16_t)0x0118, PageUp = (int16_t)0x0119, End = (int16_t)0x011A, PageDown = (int16_t)0x011B, RightArrow = (int16_t)0x011C, LeftArrow = (int16_t)0x011D, DownArrow = (int16_t)0x011E, UpArrow = (int16_t)0x011F, CapsLock = (int16_t)0x0120, NumLock = (int16_t)0x0121, ScrollLock = (int16_t)0x0122, F1 = (int16_t)0x0123, F2 = (int16_t)0x0124, F3 = (int16_t)0x0125, F4 = (int16_t)0x0126, F5 = (int16_t)0x0127, F6 = (int16_t)0x0128, F7 = (int16_t)0x0129, F8 = (int16_t)0x012A, F9 = (int16_t)0x012B, F10 = (int16_t)0x012C, F11 = (int16_t)0x012D, F12 = (int16_t)0x012E, LeftSuper = (int16_t)0x012F, RightSuper = (int16_t)0x0130, }; public: struct tModifierBits { inline static constexpr uint8_t LeftShift = 0; inline static constexpr uint8_t LeftControl = 1; inline static constexpr uint8_t LeftAlt = 2; inline static constexpr uint8_t LeftSuper = 3; inline static constexpr uint8_t RightShift = 4; inline static constexpr uint8_t RightControl = 5; inline static constexpr uint8_t RightAlt = 6; inline static constexpr uint8_t RightSuper = 7; inline static constexpr uint8_t CapsLock = 8; inline static constexpr uint8_t NumLock = 9; inline static constexpr uint8_t ScrolLLock = 10; }; public: struct tRegisters { inline static constexpr uint16_t Modifiers = 0x00; inline static constexpr uint16_t KeyCode = 0x02; }; public: inline VirtualKeyboard(void) { } void init(void); int8_t read8(uint16_t addr) override; int16_t read16(uint16_t addr) override; int8_t write8(uint16_t addr, int8_t value) override; int16_t write16(uint16_t addr, int16_t value) override; ostd::ByteStream* getByteStream(void) override; void handleSignal(ostd::Signal& signal) override; private: ostd::BitField_16 __construct_modifiers_bitfield(void); int8_t __write8(uint16_t addr, int8_t value); int16_t __write16(uint16_t addr, int16_t value); int16_t __sdl_key_code_convert(int32_t keyCode); private: ostd::ByteStream m_data; ostd::BitField_16 m_modifiersBitFiels; }; class VirtualMouse : public IMemoryDevice { public: VirtualMouse(void); int8_t read8(uint16_t addr) override; int16_t read16(uint16_t addr) override; int8_t write8(uint16_t addr, int8_t value) override; int16_t write16(uint16_t addr, int16_t value) override; ostd::ByteStream* getByteStream(void) override; private: }; class VirtualBootloader : public IMemoryDevice { public: VirtualBootloader(void); int8_t read8(uint16_t addr) override; int16_t read16(uint16_t addr) override; int8_t write8(uint16_t addr, int8_t value) override; int16_t write16(uint16_t addr, int16_t value) override; ostd::ByteStream* getByteStream(void) override; private: ostd::ByteStream m_mbr; }; namespace interface { class Disk : public IMemoryDevice { public: struct tRegisters { inline static constexpr uint16_t Signal = 0x00; inline static constexpr uint16_t ModeSelector = 0x01; inline static constexpr uint16_t DiskSelector = 0x02; inline static constexpr uint16_t SectorSelector = 0x03; inline static constexpr uint16_t AddressSelector = 0x05; inline static constexpr uint16_t DataSize = 0x07; inline static constexpr uint16_t DataSourceAddress = 0x09; inline static constexpr uint16_t FirstReadOnly = 0x0B; inline static constexpr uint16_t Status = 0x0B; inline static constexpr uint16_t CurrentDisk = 0x0C; inline static constexpr uint16_t CurrentSector = 0x0D; inline static constexpr uint16_t CurrentAddress = 0x0F; inline static constexpr uint16_t RestDataSize = 0x11; inline static constexpr uint16_t SourceData = 0x13; }; public: struct tSignalValues { inline static constexpr uint8_t Start = 0x00; inline static constexpr uint8_t Cancel = 0x01; inline static constexpr uint8_t Ignore = 0xFF; }; public: struct tModeValues { inline static constexpr uint8_t Read = 0x00; inline static constexpr uint8_t Write = 0x01; }; public: struct tStatusValues { inline static constexpr uint8_t Free = 0x00; inline static constexpr uint8_t Writing = 0x01; inline static constexpr uint8_t Reading = 0x02; }; public: Disk(MemoryMapper& memory, VirtualCPU& cpu); int8_t read8(uint16_t addr) override; int16_t read16(uint16_t addr) override; int8_t write8(uint16_t addr, int8_t value) override; int16_t write16(uint16_t addr, int16_t value) override; ostd::ByteStream* getByteStream(void) override; void cycleStep(void); bool connectDisk(VirtualHardDrive& hdd, data::VDiskID disk_id); bool disconnectDisk(data::VDiskID diskID); inline bool isBusy(void) const { return m_busy; } private: ostd::serial::SerialIO m_data { data::MemoryMapAddresses::DiskInterface_End - data::MemoryMapAddresses::DiskInterface_Start }; bool m_busy { false }; std::unordered_map m_connectedDisks; MemoryMapper& m_memory; VirtualCPU& m_cpu; // inline static data::VDiskID s_nextDiskID = 0; }; class Graphics : public IMemoryDevice { public: struct tText16_Cell { uint8_t backgroundColor; uint8_t foregroundColor; uint8_t character; }; public: struct tText16_CellStructure { inline static constexpr uint8_t character = 0x00; inline static constexpr uint8_t foreground = 0x01; inline static constexpr uint8_t background = 0x02; inline static constexpr uint8_t reserved = 0x03; }; public: struct tFlags { inline static constexpr uint8_t DoubleBufferingEnabled = 0; inline static constexpr uint8_t ScreenRedrawDisabled = 1; }; public: Graphics(void); int8_t read8(uint16_t addr) override; int16_t read16(uint16_t addr) override; int8_t write8(uint16_t addr, int8_t value) override; int16_t write16(uint16_t addr, int16_t value) override; bool readFlag(uint8_t flg); void setFlag(uint8_t flg, bool val = true); ostd::ByteStream* getByteStream(void) override; inline uint16_t getVRAMStart(void) { return m_vramStart; } bool readVRAM_16Colors(uint8_t x, uint8_t y, tText16_Cell& outTextCell); bool writeVRAM_16Colors(uint8_t x, uint8_t y, uint8_t character = 0, uint8_t background = 0xFF, uint8_t foreground = 0xFF); bool clearVRAM_16Colors(uint8_t character = 0, uint8_t background = 0x00, uint8_t foreground = 0xFF); void swapBuffers_16Colors(void); void scroll_16Colors(void); private: ostd::serial::SerialIO m_videoMemory; uint16_t m_vramStart { 0 }; uint8_t m_16Color_cellSize { 4 }; uint16_t m_16Color_frameSize { 0 }; uint16_t m_16Color_secondFrameAddr { 0 }; uint16_t m_16Color_currentFrameAddr { 0 }; bool m_16Color_doubleBufferingEnabled { false }; ostd::BitField_16 m_tempFlags; }; class SerialPort : public IMemoryDevice { public: SerialPort(void); int8_t read8(uint16_t addr) override; int16_t read16(uint16_t addr) override; int8_t write8(uint16_t addr, int8_t value) override; int16_t write16(uint16_t addr, int16_t value) override; ostd::ByteStream* getByteStream(void) override; private: }; class CMOS : public IMemoryDevice { public: inline CMOS(void) { m_initialized = false; } inline CMOS(const ostd::String& cmosFilePath) { init(cmosFilePath); } void init(const ostd::String& cmosFilePath); int8_t read8(uint16_t addr) override; int16_t read16(uint16_t addr) override; int8_t write8(uint16_t addr, int8_t value) override; int16_t write16(uint16_t addr, int16_t value) override; ostd::ByteStream* getByteStream(void) override; private: ostd::ByteStream m_data; uint16_t m_size { 0 }; std::fstream m_dataFile; bool m_initialized { false }; uint64_t m_fileSize { 0 }; }; } } }