Started work on infrastructure for Text16Colors-Video-Mode

This commit is contained in:
OmniaX 2024-09-02 10:40:42 +02:00
parent d1dfc42a50
commit bed680aeb2
9 changed files with 223 additions and 28 deletions

View file

@ -1,6 +1,7 @@
Disks = dragon/disk1.dr
Bios = dragon/bios.bin
CMOS = dragon/cmos.dr
cpuext = extmov, extalu
fixed_clock = true
clock_rate_sec = 644
@ -8,3 +9,4 @@ memory_extension_pages = 16
SingleColor_foreground = #009900FF
SingleColor_background = #111111FF
16Color_Palette = config/test_palette.dpal

View file

@ -56,6 +56,12 @@
TEXT_SIGNLE_INVERT { MemoryAddresses.VGA + 0x0005 }
TEXT_SIGNLE_STR { MemoryAddresses.VGA + 0x0006 }
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
@ -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

View file

@ -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
@ -123,6 +127,13 @@ _int_30_print_string_buffered:
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
_int_30_clear_screen:

View file

@ -26,6 +26,8 @@
## 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 }
@ -37,6 +39,7 @@
## These are the different Video Modes that the video card supports.
@group VGA_VideoModes
TEXT_SINGLE_COLOR 0x00
TEXT_16_COLORS 0x01
@end
## --

View file

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

View file

@ -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,6 +23,9 @@ namespace dragon
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);
if (video_mode == tVideoModeValues::TextSingleColor)
{
uint8_t invert_colors = mem.read8(vga_addr + tRegisters::TextSingleInvertColors);
if (m_refreshScreen)
{
@ -36,6 +43,25 @@ namespace dragon
}
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<char>(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_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();
@ -188,5 +237,20 @@ 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++)
{
}
}
}
}

View file

@ -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<ostd::String> m_singleTextLines;
ostd::String m_singleTextBuffer { "" };
std::vector<hw::interface::Graphics::tText16_Cell> m_text16_buffer;
data::IBiosVideoPalette* m_text16_palette;
};
}
}

View file

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

View file

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