From bed680aeb2abf341dff9b7f7c74ae56e75763305 Mon Sep 17 00:00:00 2001 From: OmniaX Date: Mon, 2 Sep 2024 10:40:42 +0200 Subject: [PATCH] Started work on infrastructure for Text16Colors-Video-Mode --- extra/config/testMachine.dvm | 4 +- extra/dss/bios/data.dss | 51 +++++++++++++++--- extra/dss/bios/drivers.dss | 11 ++++ extra/dss/bios_api.dss | 17 +++--- extra/info/info | 13 +++++ src/hardware/VirtualDisplay.cpp | 88 ++++++++++++++++++++++++++----- src/hardware/VirtualDisplay.hpp | 15 ++++++ src/hardware/VirtualIODevices.cpp | 32 +++++++++++ src/hardware/VirtualIODevices.hpp | 20 +++++++ 9 files changed, 223 insertions(+), 28 deletions(-) diff --git a/extra/config/testMachine.dvm b/extra/config/testMachine.dvm index d023769..6f7116d 100644 --- a/extra/config/testMachine.dvm +++ b/extra/config/testMachine.dvm @@ -1,10 +1,12 @@ Disks = dragon/disk1.dr Bios = dragon/bios.bin CMOS = dragon/cmos.dr + cpuext = extmov, extalu fixed_clock = true clock_rate_sec = 644 memory_extension_pages = 16 SingleColor_foreground = #009900FF -SingleColor_background = #111111FF \ No newline at end of file +SingleColor_background = #111111FF +16Color_Palette = config/test_palette.dpal \ No newline at end of file diff --git a/extra/dss/bios/data.dss b/extra/dss/bios/data.dss index ef94148..3327622 100644 --- a/extra/dss/bios/data.dss +++ b/extra/dss/bios/data.dss @@ -48,15 +48,21 @@ @export_comment BIOS_API " These are the memory-mapped registers used to interact with the video card's interface." @raw_export_start BIOS_API @group VGA_Registers - VIDEO_MODE { MemoryAddresses.VGA + 0x0000 } - CLEAR_COLOR { MemoryAddresses.VGA + 0x0001 } - PALETTE { MemoryAddresses.VGA + 0x0002 } - SIGNAL { MemoryAddresses.VGA + 0x0003 } - TEXT_SINGLE_CHAR { MemoryAddresses.VGA + 0x0004 } - TEXT_SIGNLE_INVERT { MemoryAddresses.VGA + 0x0005 } - TEXT_SIGNLE_STR { MemoryAddresses.VGA + 0x0006 } + VIDEO_MODE { MemoryAddresses.VGA + 0x0000 } + CLEAR_COLOR { MemoryAddresses.VGA + 0x0001 } + PALETTE { MemoryAddresses.VGA + 0x0002 } + SIGNAL { MemoryAddresses.VGA + 0x0003 } + TEXT_SINGLE_CHAR { MemoryAddresses.VGA + 0x0004 } + TEXT_SIGNLE_INVERT { MemoryAddresses.VGA + 0x0005 } + TEXT_SIGNLE_STR { MemoryAddresses.VGA + 0x0006 } - BUFF_START { MemoryAddresses.VGA + 0x00E0 } + MEMORY_CONTROLLER_X { MemoryAddresses.VGA + 0x0080 } + MEMORY_CONTROLLER_Y { MemoryAddresses.VGA + 0x0084 } + MEMORY_CONTROLLER_CHAR { MemoryAddresses.VGA + 0x0088 } + MEMORY_CONTROLLER_BG_COL { MemoryAddresses.VGA + 0x0089 } + MEMORY_CONTROLLER_FG_COL { MemoryAddresses.VGA + 0x008A } + + BUFF_START { MemoryAddresses.VGA + 0x00E0 } @end @raw_export_end @export_comment BIOS_API " --\n" @@ -93,6 +99,22 @@ +@export_comment BIOS_API " These are signals used to comunicate with the video card's interface, when in TEXT16_COLOR mode." +@raw_export_start BIOS_API +@group Sig_VGA_Text_16_Color + CONTINUE 0x00 + + READ_VRAM 0x10 + WRITE_VRAM 0x11 + + FORCE_REFRESH_SCREEN 0xE0 + FORCE_CLEAR_SCREEN 0xE1 +@end +@raw_export_end +@export_comment BIOS_API " --\n" + + + @define S_REG_1 0x07 @define S_REG_2 0x08 @define S_REG_OFFSET 0x09 @@ -133,6 +155,19 @@ @end @raw_export_end @export_comment BIOS_API " --\n" + + +@export_comment BIOS_API " Structure to store a character cell for the Text16-Video-Mode." +@raw_export_start BIOS_API +@struct Text16VModeTextCell + Character:1 + Foreground:1 + Background:1 + CoordX:1 + CoordY:1 +@end +@raw_export_end +@export_comment BIOS_API " --\n" ## =============================================================================================== .data diff --git a/extra/dss/bios/drivers.dss b/extra/dss/bios/drivers.dss index a938ffd..8bdc665 100644 --- a/extra/dss/bios/drivers.dss +++ b/extra/dss/bios/drivers.dss @@ -57,6 +57,10 @@ _int_30_handler: jeq $_int_30_store_string_text_single, 0x000A jeq $_int_30_invert_colors_text_single, 0x000B jeq $_int_30_print_string_buffered, 0x000C + + jeq $_int_30_read_vram_text16, 0x0020 + jeq $_int_30_write_vram_text16, 0x0021 + jeq $_int_30_clear_screen, 0x00E0 jeq $_int_30_refresh_screen, 0x00E1 jmp $_int_30_end @@ -122,6 +126,13 @@ _int_30_print_string_buffered: mov [VGA_Registers.TEXT_SIGNLE_STR], R9 movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.PRINT_STRING jmp $_int_30_end + +_int_30_write_vram_text16: + + jmp $_int_30_end +_int_30_read_vram_text16: + + jmp $_int_30_end diff --git a/extra/dss/bios_api.dss b/extra/dss/bios_api.dss index 72fd70c..d7ec2c7 100644 --- a/extra/dss/bios_api.dss +++ b/extra/dss/bios_api.dss @@ -3,7 +3,7 @@ ## -- Please do not modify this file in any way. ## -- -##These are the base addresses of the memory map. +## These are the base addresses of the memory map. @group MemoryAddresses MBR 0x1380 INT_VEC 0x1080 @@ -14,7 +14,7 @@ @end ## -- -##These are the Hardware Interrupt codes of this machine. +## These are the Hardware Interrupt codes of this machine. @group HW_Int DISK_INTERFACE_FINISHED 0x80 KEY_PRESSED 0xA0 @@ -23,9 +23,11 @@ @end ## -- -##These are the memory-mapped registers used to interact with the video card's interface. +## These are the memory-mapped registers used to interact with the video card's interface. @group VGA_Registers VIDEO_MODE { MemoryAddresses.VGA + 0x0000 } + CLEAR_COLOR { MemoryAddresses.VGA + 0x0001 } + PALETTE { MemoryAddresses.VGA + 0x0002 } SIGNAL { MemoryAddresses.VGA + 0x0003 } TEXT_SINGLE_CHAR { MemoryAddresses.VGA + 0x0004 } TEXT_SIGNLE_INVERT { MemoryAddresses.VGA + 0x0005 } @@ -34,13 +36,14 @@ @end ## -- -##These are the different Video Modes that the video card supports. +## These are the different Video Modes that the video card supports. @group VGA_VideoModes TEXT_SINGLE_COLOR 0x00 + TEXT_16_COLORS 0x01 @end ## -- -##These are signals used to comunicate with the video card's interface, when in TEXT_SINGLE_COLOR mode. +## These are signals used to comunicate with the video card's interface, when in TEXT_SINGLE_COLOR mode. @group Sig_VGA_Text_Single_Color CONTINUE 0x00 PRINT_CHAR 0x02 @@ -54,7 +57,7 @@ @end ## -- -##Structure of a DPT (Dragon Partition Table). +## Structure of a DPT (Dragon Partition Table). @group DPTStructure DISK_ADDR 0x0200 ENTRIES_START 0x000C @@ -67,7 +70,7 @@ @end ## -- -##Structure to store a DPT block. +## Structure to store a DPT block. @struct DPTBlock ID:2 VersionMaj:1 diff --git a/extra/info/info b/extra/info/info index 896a2d8..042d336 100644 --- a/extra/info/info +++ b/extra/info/info @@ -92,11 +92,24 @@ 0x06: Text Single Color - Print Buffer Without Flushing 0x07: Text Single Color - Print Buffered String + 0x10: Text 16 Colors - Read Memory + 0x11: Text 16 Colors - Write Memory + 0xE0: Refresh Screen 0xE1: Clear Screen 0x04: Text Single Color Character (1 Byte) 0x05: Text Single Color Inverted colors (1 Byte) 0x06: (2 bytes) Text Single Color Buffered String Address + + 0x80: Memory Controller + 0x80: XCoordinate (4 Bytes) + 0x84: YCoordinate (4 Bytes) + 0x88: Character (1 Byte) + 0x09: Foreground (1 Byte) + 0x8A: Background (1 Byte) + + (VRAM Memory Cell: Character:1, Foreground:1, Background:1, Reserved:1) + 0x16FF ------- 0x1700 GENERIC SERIAL INTERFACE (64 Bytes) diff --git a/src/hardware/VirtualDisplay.cpp b/src/hardware/VirtualDisplay.cpp index 64d9ef9..d368f6f 100644 --- a/src/hardware/VirtualDisplay.cpp +++ b/src/hardware/VirtualDisplay.cpp @@ -1,6 +1,7 @@ #include "VirtualDisplay.hpp" #include "../gui/RawTextRenderer.hpp" #include "../runtime/DragonRuntime.hpp" +#include "../tools/GlobalData.hpp" namespace dragon { @@ -10,6 +11,9 @@ namespace dragon { m_renderer.initialize(*this); RawTextRenderer::initialize(); + + m_text16_palette = new data::BiosVideoDefaultPalette; //TODO: Delete, Memory Leak + text16_init_buffer(); } void VirtualDisplay::onDestroy(void) { } @@ -19,22 +23,44 @@ namespace dragon auto& config = DragonRuntime::machine_config; auto& mem = DragonRuntime::memMap; uint16_t vga_addr = data::MemoryMapAddresses::VideoCardInterface_Start; - uint8_t invert_colors = mem.read8(vga_addr + tRegisters::TextSingleInvertColors); - if (m_refreshScreen) + uint8_t video_mode = mem.read8(vga_addr + tRegisters::VideoMode); + if (video_mode == tVideoModeValues::TextSingleColor) { - if (invert_colors == 0) - m_renderer.clear(config.singleColor_background); - else - m_renderer.clear(config.singleColor_foreground); - for (int32_t i = 0; i < m_singleTextLines.size(); i++) + uint8_t invert_colors = mem.read8(vga_addr + tRegisters::TextSingleInvertColors); + if (m_refreshScreen) { - auto& line = m_singleTextLines[i]; if (invert_colors == 0) - RawTextRenderer::drawString(line, 0, i, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_foreground, config.singleColor_background); + m_renderer.clear(config.singleColor_background); else - RawTextRenderer::drawString(line, 0, i, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_background, config.singleColor_foreground); + m_renderer.clear(config.singleColor_foreground); + for (int32_t i = 0; i < m_singleTextLines.size(); i++) + { + auto& line = m_singleTextLines[i]; + if (invert_colors == 0) + RawTextRenderer::drawString(line, 0, i, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_foreground, config.singleColor_background); + else + RawTextRenderer::drawString(line, 0, i, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_background, config.singleColor_foreground); + } + m_refreshScreen = false; + } + } + else if (video_mode == tVideoModeValues::Text16Colors) + { + if (m_refreshScreen) + { + uint8_t clear_color = mem.read8(vga_addr + tRegisters::ClearColor); + ostd::Color clearColor = m_text16_palette->getColor(clear_color); + m_renderer.clear(clearColor); + for (int32_t i = 0; i < RawTextRenderer::CONSOLE_CHARS_V * RawTextRenderer::CONSOLE_CHARS_H; i++) + { + auto& cell = m_text16_buffer[i]; + ostd::Color background = m_text16_palette->getColor(cell.backgroundColor); + ostd::Color foreground = m_text16_palette->getColor(cell.foregroundColor); + char character = static_cast(cell.character); + auto xy = CONVERT_1D_2D(i, RawTextRenderer::CONSOLE_CHARS_H); + RawTextRenderer::drawString(ostd::String().addChar(character), xy.x, xy.y, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, foreground, background); + } } - m_refreshScreen = false; } m_renderer.updateBuffer(); m_renderer.displayBuffer(); @@ -93,10 +119,34 @@ namespace dragon single_text_refresh_screen(); } } + else if (video_mode == tVideoModeValues::Text16Colors) + { + } else return; mem.write8(vga_addr + tRegisters::Signal, tSignalValues::Continue); } + void VirtualDisplay::onFixedUpdate(void) + { + auto& config = DragonRuntime::machine_config; + auto& mem = DragonRuntime::memMap; + uint16_t vga_addr = data::MemoryMapAddresses::VideoCardInterface_Start; + uint8_t video_mode = mem.read8(vga_addr + tRegisters::VideoMode); + uint8_t signal = mem.read8(vga_addr + tRegisters::Signal); + if (signal == tSignalValues::Continue) return; + if (video_mode == tVideoModeValues::Text16Colors) + { + m_refreshScreen = true; + dragon::hw::interface::Graphics::tText16_Cell outTextCell; + for (int32_t i = 0; i < RawTextRenderer::CONSOLE_CHARS_V * RawTextRenderer::CONSOLE_CHARS_H; i++) + { + auto xy = CONVERT_1D_2D(i, RawTextRenderer::CONSOLE_CHARS_H); + DragonRuntime::vGraphicsInterface.readVRAM_16Colors(xy.x, xy.y, outTextCell); + m_text16_buffer[i] = outTextCell; + } + } + } + void VirtualDisplay::onFixedUpdate(void) { } void VirtualDisplay::onSlowUpdate(void) { } @@ -176,7 +226,6 @@ namespace dragon single_text_add_char_to_line(ch); } - void VirtualDisplay::single_text_clear_screen(void) { m_singleTextLines.clear(); @@ -187,6 +236,21 @@ namespace dragon { m_refreshScreen = true; } + + + void VirtualDisplay::text16_init_buffer(void) + { + for (int32_t i = 0; i < RawTextRenderer::CONSOLE_CHARS_V * RawTextRenderer::CONSOLE_CHARS_H; i++) + m_text16_buffer.push_back({ 0, 0, ' ' }); + } + + void VirtualDisplay::text16_buffer_diff(void) + { + for (int32_t i = 0; i < RawTextRenderer::CONSOLE_CHARS_V * RawTextRenderer::CONSOLE_CHARS_H; i++) + { + + } + } } } \ No newline at end of file diff --git a/src/hardware/VirtualDisplay.hpp b/src/hardware/VirtualDisplay.hpp index 5834ef9..a39bf10 100644 --- a/src/hardware/VirtualDisplay.hpp +++ b/src/hardware/VirtualDisplay.hpp @@ -2,9 +2,11 @@ #include "../gui/Window.hpp" #include "../gui/Renderer.hpp" +#include "../hardware/VirtualIODevices.hpp" namespace dragon { + namespace data { class IBiosVideoPalette; } namespace hw { class VirtualDisplay : public Window @@ -12,6 +14,8 @@ namespace dragon public: struct tRegisters { inline static constexpr uint8_t VideoMode = 0x00; + inline static constexpr uint8_t ClearColor = 0x01; + inline static constexpr uint8_t Palette = 0x02; inline static constexpr uint8_t Signal = 0x03; inline static constexpr uint8_t TextSingleCharacter = 0x04; inline static constexpr uint8_t TextSingleInvertColors = 0x05; @@ -20,6 +24,7 @@ namespace dragon public: struct tVideoModeValues { inline static constexpr uint8_t TextSingleColor = 0x00; + inline static constexpr uint8_t Text16Colors = 0x01; }; public: struct tSignalValues { @@ -32,6 +37,9 @@ namespace dragon inline static constexpr uint8_t TextSingleColor_DirectPrintBuffNoFlush = 0x06; inline static constexpr uint8_t TextSingleColor_DirectPrintString = 0x07; + inline static constexpr uint8_t Text16Color_ReadMemory = 0x10; + inline static constexpr uint8_t Text16Color_WriteMemory = 0x11; + inline static constexpr uint8_t RefreshScreen = 0xE0; inline static constexpr uint8_t ClearSCreen = 0xE1; }; @@ -41,6 +49,7 @@ namespace dragon void onRender(void) override; void onUpdate(void) override; void onFixedUpdate(void) override; + void onFixedUpdate(void) override; void onSlowUpdate(void) override; private: @@ -53,11 +62,17 @@ namespace dragon void single_text_clear_screen(void); void single_text_refresh_screen(void); + void text16_init_buffer(void); + void text16_buffer_diff(void); + private: Renderer m_renderer; std::vector m_singleTextLines; ostd::String m_singleTextBuffer { "" }; + + std::vector m_text16_buffer; + data::IBiosVideoPalette* m_text16_palette; }; } } \ No newline at end of file diff --git a/src/hardware/VirtualIODevices.cpp b/src/hardware/VirtualIODevices.cpp index 503728c..f7e18fd 100644 --- a/src/hardware/VirtualIODevices.cpp +++ b/src/hardware/VirtualIODevices.cpp @@ -7,6 +7,7 @@ #include "VirtualRAM.hpp" #include "../runtime/DragonRuntime.hpp" +#include "../gui/RawTextRenderer.hpp" //TODO: Fix all access functions (reads and writes) ensuring the address is not out of bounds. // Right now the check is done, but just to push an error if out of bounds; the address @@ -660,6 +661,7 @@ namespace dragon Graphics::Graphics(void) { m_videoMemory.init(0xFFFF); + m_vramStart = data::MemoryMapAddresses::VideoCardInterface_End - data::MemoryMapAddresses::VideoCardInterface_Start; } int8_t Graphics::read8(uint16_t addr) @@ -709,6 +711,36 @@ namespace dragon return &m_videoMemory.getData(); } + bool Graphics::readVRAM_16Colors(uint8_t x, uint8_t y, Graphics::tText16_Cell& outTextCell) + { + uint16_t cellOffset = static_cast(CONVERT_2D_1D(x, y, RawTextRenderer::CONSOLE_CHARS_H)) * 4; + cellOffset += m_vramStart; + int8_t outVal = 0; + if (!m_videoMemory.r_Byte(cellOffset + tText16_CellStructure::character, outVal)) + return false; //TODO: Error + outTextCell.character = outVal; + if (!m_videoMemory.r_Byte(cellOffset + tText16_CellStructure::background, outVal)) + return false; //TODO: Error + outTextCell.backgroundColor = outVal; + if (!m_videoMemory.r_Byte(cellOffset + tText16_CellStructure::foreground, outVal)) + return false; //TODO: Error + outTextCell.foregroundColor = outVal; + return true; + } + + bool Graphics::writeVRAM_16Colors(uint8_t x, uint8_t y, uint8_t character, uint8_t background, uint8_t foreground) + { + uint16_t cellOffset = static_cast(CONVERT_2D_1D(x, y, RawTextRenderer::CONSOLE_CHARS_H)) * 4; + cellOffset += m_vramStart; + if (!m_videoMemory.w_Byte(cellOffset + tText16_CellStructure::character, character)) + return false; //TODO: Error + if (!m_videoMemory.w_Byte(cellOffset + tText16_CellStructure::background, background)) + return false; //TODO: Error + if (!m_videoMemory.w_Byte(cellOffset + tText16_CellStructure::foreground, foreground)) + return false; //TODO: Error + return true; + } + diff --git a/src/hardware/VirtualIODevices.hpp b/src/hardware/VirtualIODevices.hpp index 45bd5eb..e3c0246 100644 --- a/src/hardware/VirtualIODevices.hpp +++ b/src/hardware/VirtualIODevices.hpp @@ -345,6 +345,19 @@ namespace dragon }; 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: Graphics(void); int8_t read8(uint16_t addr) override; @@ -354,8 +367,15 @@ namespace dragon 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); + private: ostd::serial::SerialIO m_videoMemory; + + uint16_t m_vramStart { 0 }; + uint8_t m_16Color_cellSize { 4 }; }; class SerialPort : public IMemoryDevice {