diff --git a/build.nr b/build.nr index f800fc8..871215b 100644 --- a/build.nr +++ b/build.nr @@ -1 +1 @@ -1617 +1618 diff --git a/extra/dragon/bios.bin b/extra/dragon/bios.bin index 7a15e06..5390afe 100644 Binary files a/extra/dragon/bios.bin and b/extra/dragon/bios.bin differ diff --git a/extra/dragon/disk1.dr b/extra/dragon/disk1.dr index ac3c3c0..2f5e452 100644 Binary files a/extra/dragon/disk1.dr and b/extra/dragon/disk1.dr differ diff --git a/extra/dss/bios/data.dss b/extra/dss/bios/data.dss index b5b6df9..4ee11e8 100644 --- a/extra/dss/bios/data.dss +++ b/extra/dss/bios/data.dss @@ -17,6 +17,7 @@ RAM 0x1740 CMOS 0x1000 VGA 0x1600 + KEYBOARD 0x1280 @end @raw_export_end @export_comment BIOS_API " --\n" @@ -74,6 +75,17 @@ +@export_comment BIOS_API " These are the memory-mapped registers used to interact with the keyboard's interface." +@raw_export_start BIOS_API +@group Keyboard_Registers + MODIFIERS_BITFIELD { MemoryAddresses.KEYBOARD + 0x0000 } + KEYCODE { MemoryAddresses.KEYBOARD + 0x0002 } +@end +@raw_export_end +@export_comment BIOS_API " --\n" + + + @export_comment BIOS_API " These are the different Video Modes that the video card supports." @raw_export_start BIOS_API @group VGA_VideoModes diff --git a/extra/dss/bios/display.dss b/extra/dss/bios/display.dss index baf88f1..67e8516 100644 --- a/extra/dss/bios/display.dss +++ b/extra/dss/bios/display.dss @@ -22,6 +22,39 @@ _print_string_text16_loop: +_print_integer_text16: ## _print_integer_text16(int16_t number, TextCell16* cell) + arg ACC ## @Param: number + arg R2 ## @Param: cell + mov R3, R2 + addip R3, 3 ## R3 is now a pointer to the X coord in the cell + mov R1, 0 + jne $_print_integer_text16_loop, 0 + push 48 ## '0' ASCII is 48 + inc R1 + jmp $_print_integer_text16_loop_end +_print_integer_text16_loop: + jeq $_print_integer_text16_loop_end, 0 + divipu ACC, 10 + addipu RV, 48 + push RV + inc R1 + jmp $_print_integer_text16_loop +_print_integer_text16_loop_end: + pop R4 ## Put next char in R4 + dec R1 + movb *R2, R4 ## Store next char in first byte of cell + mov R10, 0x21 ## int 0x30 param for write vram + mov R9, R2 ## int 0x30 param for textCell16 + int 0x30 + debug_break + movb R5, *R3 ## Retrieve current X coord from cell + inc R5 ## Increment X coord + movb *R3, R5 ## Store new X coord in cell + mov ACC, R1 + jne $_print_integer_text16_loop_end, 0 + ret + + _print_integer_signle_color: mov R1, 0 diff --git a/extra/dss/bios/drivers.dss b/extra/dss/bios/drivers.dss index 0218e36..9f99cf0 100644 --- a/extra/dss/bios/drivers.dss +++ b/extra/dss/bios/drivers.dss @@ -17,16 +17,13 @@ _int_20_disk_interface: movb [{MemoryAddresses.DISK_INTERFACE + 0x2}], *R9 ## Disk inc R9 mov [{MemoryAddresses.DISK_INTERFACE + 0x3}], *R9 ## Sector - inc R9 - inc R9 + addip R9, 2 mov [{MemoryAddresses.DISK_INTERFACE + 0x5}], *R9 ## Address - inc R9 - inc R9 + addip R9, 2 mov [{MemoryAddresses.DISK_INTERFACE + 0x7}], *R9 ## Size - inc R9 - inc R9 + addip R9, 2 mov [{MemoryAddresses.DISK_INTERFACE + 0x9}], *R9 ## Memory Address - movb [MemoryAddresses.DISK_INTERFACE], 0x00 ## Signal set to "Start Operation" + movb [MemoryAddresses.DISK_INTERFACE], DiskSignals.START ## Signal set to "Start Operation" jmp $_int_20_end _int_20_disk_interface_get_disk_list: jmp $_int_20_end @@ -68,6 +65,8 @@ _int_30_handler: jeq $_int_30_write_vram_text16, 0x0021 jeq $_int_30_print_string_text16, 0x0022 + jeq $_int_30_print_integer_text16, 0x0023 + jeq $_int_30_clear_screen_text16, 0x0024 jeq $_int_30_clear_screen, 0x00E0 jeq $_int_30_refresh_screen, 0x00E1 @@ -153,6 +152,20 @@ _int_30_print_string_text16: push 2 call $_print_string_text16 jmp $_int_30_end +_int_30_print_integer_text16: + push R8 ## number + push R9 ## TextCell16 addr + push 2 + call $_print_integer_text16 + jmp $_int_30_end +_int_30_clear_screen_text16: + movb [VGA_Registers.MEMORY_CONTROLLER_CHAR], *R9 + inc R9 + movb [VGA_Registers.MEMORY_CONTROLLER_FG_COL], *R9 + inc R9 + movb [VGA_Registers.MEMORY_CONTROLLER_BG_COL], *R9 + movb [VGA_Registers.SIGNAL], Sig_VGA_Text_16_Color.FORCE_CLEAR_SCREEN + jmp $_int_30_end _int_30_clear_screen: movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.CLEAR_SCREEN diff --git a/extra/dss/bios_api.dss b/extra/dss/bios_api.dss index f90afce..8dbfc86 100644 --- a/extra/dss/bios_api.dss +++ b/extra/dss/bios_api.dss @@ -1,5 +1,5 @@ ## -- -## -- This file is automatically generated by the DragonAssembler (version 0.4.1616) +## -- This file is automatically generated by the DragonAssembler (version 0.4.1617) ## -- Please do not modify this file in any way. ## -- @@ -11,6 +11,7 @@ RAM 0x1740 CMOS 0x1000 VGA 0x1600 + KEYBOARD 0x1280 @end ## -- @@ -44,6 +45,13 @@ @end ## -- +## These are the memory-mapped registers used to interact with the keyboard's interface. +@group Keyboard_Registers + MODIFIERS_BITFIELD { MemoryAddresses.KEYBOARD + 0x0000 } + KEYCODE { MemoryAddresses.KEYBOARD + 0x0002 } +@end +## -- + ## These are the different Video Modes that the video card supports. @group VGA_VideoModes TEXT_SINGLE_COLOR 0x00 diff --git a/extra/dss/drake/bootsector.dss b/extra/dss/drake/bootsector.dss index c22f868..80f7353 100644 --- a/extra/dss/drake/bootsector.dss +++ b/extra/dss/drake/bootsector.dss @@ -3,58 +3,119 @@ @include <../bios_api.dss> @include +@include .data - $string "Hello " + ## Disk data structures $ddd $dpt_block - $textCell + + $textCell + $counter 0x00 + $current_char 65 + + $dpt_version_str "DPT Version " + $drake_version_str "Drake 0.1 -- " + $invalid_dpt_block_str "Error: Invalid DPT Block..." .code _drake_bootsector_entry_point: - push $ddd - push $dpt_block + ## Load DPT block from disk 0 + push $ddd ## Empty DiskDriverData used to load from disk + push $dpt_block ## Empty DPT Block to store the partition table push 2 call $_load_dpt_block - + ## Enable Text16 Video Mode movb [VGA_Registers.VIDEO_MODE], VGA_VideoModes.TEXT_16_COLORS - - push 2 + ## Validate DPT Block + mov ACC, [$dpt_block] + jne $_invalid_dpt_block, 0xF1CA + ## Init Keyboard driver + push $_key_pressed ## KeyPressed handler address passed to the _init_keyboard subroutine push 1 - push 2 - call $_draw_palette + call $_init_keyboard - - movb [$textCell.CoordX], 2 - movb [$textCell.CoordY], 2 - movb [$textCell.Foreground], DefaultPalette.Orange + movb [$textCell.CoordX], 0 + movb [$textCell.CoordY], 0 + movb [$textCell.Foreground], DefaultPalette.Pink movb [$textCell.Background], DefaultPalette.Black mov R10, 0x22 - mov R8, $string + mov R8, $drake_version_str mov R9, $textCell int 0x30 - - movb [$textCell.CoordX], 8 - movb [$textCell.CoordY], 2 - movb [$textCell.Foreground], DefaultPalette.Black - movb [$textCell.Background], DefaultPalette.Orange - + movb [$textCell.CoordX], 13 mov R10, 0x22 - mov R8, { $dpt_block + DPTStructure.ENTRIES_START + (2 * DPTStructure.ENTRY_SIZE_B) + DPTStructure.ENTRY_PART_LBL } + mov R8, $dpt_version_str mov R9, $textCell int 0x30 + movb [$textCell.CoordX], 26 + mov R10, 0x23 + movb R8, [{ $dpt_block + 2 }] + mov R9, $textCell + int 0x30 + + movb [$textCell.CoordX], 27 + movb [$textCell.Character], 0x2E + mov R10, 0x21 + mov R9, $textCell + int 0x30 + + movb [$textCell.CoordX], 28 + mov R10, 0x23 + movb R8, [{ $dpt_block + 3 }] + mov R9, $textCell + int 0x30 + + ## mov R10, 0x23 + ## mov R9, $textCell + ## mov R8, 2341 + ## int 0x30 - hlt + ## mov R10, 0x22 + ## mov R8, { $dpt_block + DPTStructure.ENTRIES_START + (2 * DPTStructure.ENTRY_SIZE_B) + DPTStructure.ENTRY_PART_LBL } + ## mov R9, $textCell + ## int 0x30 + + jmp $_endless_loop +_invalid_dpt_block: + push $invalid_dpt_block_str + push 1 + call $_print_error_msg +_endless_loop: + jmp $_endless_loop + hlt + + +_key_pressed: + mov ACC, [Keyboard_Registers.KEYCODE] + jne $_key_pressed_end, 0x0127 + + movb R1, [$counter] + movb [$textCell.CoordX], R1 + movb [$textCell.CoordY], 12 + movb [$textCell.Foreground], DefaultPalette.Orange + movb [$textCell.Background], DefaultPalette.Black + movb [$textCell.Character], 65 + + inc R1 + movb [$counter], R1 + + mov R10, 0x21 + mov R9, $textCell + int 0x30 + +_key_pressed_end: + ret @@ -79,5 +140,19 @@ _load_dpt_block: ## _load_dpt_block(DiskDriverData* ddd, DPTBlock* dpt_block) ret +_print_error_msg: ## _print_error_msg(string* error_msg) + arg R1 ## @Param: error_msg + ## TODO: Clear the screen + movb [$textCell.CoordX], 0 + movb [$textCell.CoordY], 0 + movb [$textCell.Foreground], DefaultPalette.Red + movb [$textCell.Background], DefaultPalette.Black + mov R10, 0x22 + mov R8, R1 + mov R9, $textCell + int 0x30 + ret + + .fixed 5120, 0xFF diff --git a/extra/dss/drake/keyboard_driver.dss b/extra/dss/drake/keyboard_driver.dss new file mode 100644 index 0000000..6caee03 --- /dev/null +++ b/extra/dss/drake/keyboard_driver.dss @@ -0,0 +1,10 @@ +@guard _KEYBOARD_DRIVER_DSS_ + +.code + +_init_keyboard: ## _init_keyboard(func_ptr* key_pressed_handler) + arg R9 ## @Param: key_pressed_handler + mov R10, 0x00 ## int 0x20 param for set_interrupt_handler + mov R8, 0xA0 ## 0xA0 is the hardware interrupt for KeyPressed + int 0x20 + ret \ No newline at end of file diff --git a/extra/info/info b/extra/info/info index 9f5c855..e0b4b4e 100644 --- a/extra/info/info +++ b/extra/info/info @@ -129,6 +129,8 @@ 0x00: Set Interrupt Handler 0x01: Clear Interrupt Handler 0x10: Disk Interface + 0x11: Disk Interface - Get disk list + 0x12: Disk Interface - Load from DDD - BLOCKING 0x30: BIOS Video Interrupt (Uses R10 register for specific functionality) 0x01: Print Char in Text Single Mode (char stored in R9 register) 0x02: New Line in Text Single Mode @@ -142,8 +144,10 @@ 0x0A: Store Null-Terminated String in buffer in Text Single Mode (string address stored in R9 register) 0x0B: Toggles inverted colors in Text Single Mode - 0x20: Read VRAM in Text16 Colors Mode (Cell address stored in R9) 0x21: Write VRAM in Text16 Colors Mode (Cell address stored in R9) + 0x22: Print String in Text16 Colors Mode (String address stored in R8, Cell address stored in R9) + 0x23: Print Integer in Text16 Colors Mode (Integer stored in R8, Cell address stored in R9) + 0x24: Clear Screen in Text16 Colors Mode (Cell address stored in R9) 0xE0: Refresh Screen 0xE1: Clear Screen diff --git a/src/assembler/Assembler.cpp b/src/assembler/Assembler.cpp index 8bed21c..b5d0664 100644 --- a/src/assembler/Assembler.cpp +++ b/src/assembler/Assembler.cpp @@ -503,16 +503,13 @@ namespace dragon { std::vector newLines; ostd::String lineEdit; - bool in_group = false; - ostd::String group_name = ""; for (auto& line : m_rawDataSection) { lineEdit = line; lineEdit.trim(); - if (!lineEdit.startsWith("$") || lineEdit.indexOf(" ") < 2) + if (!lineEdit.startsWith("$")) { - std::cout << "Invalid data entry: " << lineEdit << "\n"; - return; + continue; } ostd::String symbolName = lineEdit.new_substr(0, lineEdit.indexOf(" ")); symbolName.trim(); @@ -853,6 +850,8 @@ namespace dragon { ostd::String lineEdit(line); tSymbol symbol; + ostd::String symbolName = ""; + bool array = false; if (lineEdit.startsWith("!")) { if (lineEdit.contains(" ")) @@ -866,15 +865,52 @@ namespace dragon m_symbolTable[lineEdit] = symbol; continue; } - if (!lineEdit.startsWith("$") || lineEdit.indexOf(" ") < 2) + if (!lineEdit.startsWith("$")) { - std::cout << "Invalid data entry: " << lineEdit << "\n"; + std::cout << "Invalid data entry (name must start with $): " << line << "\n"; continue; } - ostd::String symbolName = lineEdit.new_substr(0, lineEdit.indexOf(" ")); - symbolName.trim(); - lineEdit.substr(lineEdit.indexOf(" ") + 1); - lineEdit.trim(); + if (lineEdit.contains(":") && (!lineEdit.contains("\"") || lineEdit.indexOf(":") < lineEdit.indexOf("\""))) + { + if (lineEdit.indexOf(":") < 2 || lineEdit.indexOf(":") == lineEdit.len() - 1) + { + std::cout << "Invalid array data entry: " << line << "\n"; + continue; + } + symbolName = lineEdit.new_substr(0, lineEdit.indexOf(":")).trim(); + lineEdit.substr(lineEdit.indexOf(":") + 1).trim(); + if (!lineEdit.isNumeric()) + { + std::cout << "Invalid array data entry size (must be numeric): " << line << "\n"; + continue; + } + array = true; + } + else if (lineEdit.indexOf(" ") >= 2) + { + symbolName = lineEdit.new_substr(0, lineEdit.indexOf(" ")).trim(); + lineEdit.substr(lineEdit.indexOf(" ") + 1).trim(); + } + else + { + std::cout << "Invalid data entry1: " << line << "\n"; + continue; + } + + if (array) + { + uint16_t array_size = lineEdit.toInt(); + if (array_size == 0) + { + std::cout << "Invalid array data entry size (must be greater than 0): " << line << "\n"; + continue; + } + lineEdit = ""; + for (int32_t i = 0; i < array_size; i++) + lineEdit.add("0x00, "); + lineEdit.trim().substr(0, lineEdit.len() - 1).trim(); + } + if (lineEdit.isNumeric()) { // union valueSplit { @@ -909,7 +945,7 @@ namespace dragon auto tokens = lineEdit.tokenize(","); if (tokens.count() < 2) { - std::cout << "Invalid data entry: " << lineEdit << "\n"; + std::cout << "Invalid data entry2: " << line << "\n"; return; } for (auto& token : tokens) @@ -929,7 +965,7 @@ namespace dragon } else { - std::cout << "Invalid data entry: " << lineEdit << "\n"; + std::cout << "Invalid data entry3: " << line << "\n"; continue; } } @@ -1176,16 +1212,21 @@ namespace dragon } else if (instEdit == "push") { + m_code.push_back(0x00); eOperandType opType = parseOperand(opEdit, word); if (opType == eOperandType::Immediate || opType == eOperandType::Label) { - m_code.push_back(data::OpCodes::PushImm); + // if (opType == eOperandType::Label) + // std::cout << ostd::Utils::getHexStr(word, true, 2) << "\n"; + m_code[m_code.size() - 1] = data::OpCodes::PushImm; + // m_code.push_back(data::OpCodes::PushImm); m_code.push_back((uint8_t)((word & 0xFF00) >> 8)); m_code.push_back((uint8_t)(word & 0x00FF)); } else if (opType == eOperandType::Register) { - m_code.push_back(data::OpCodes::PushReg); + // m_code.push_back(data::OpCodes::PushReg); + m_code[m_code.size() - 1] = data::OpCodes::PushReg; m_code.push_back((uint8_t)word); } else @@ -2467,6 +2508,9 @@ namespace dragon if (labelAddr == 0x0000) m_labelTable[opEdit].references.push_back(m_code.size()); outOp = (int16_t)labelAddr; + // std::cout << "LABEL: " << opEdit << "\n"; + // std::cout << " : " << ostd::Utils::getHexStr(labelAddr, true, 2) << "\n"; + // std::cout << " : " << ostd::Utils::getHexStr(outOp, true, 2) << "\n"; return eOperandType::Label; } if (opEdit.startsWith("{") && opEdit.endsWith("}")) diff --git a/src/hardware/VirtualDisplay.cpp b/src/hardware/VirtualDisplay.cpp index f2b60ad..fd8cf8a 100644 --- a/src/hardware/VirtualDisplay.cpp +++ b/src/hardware/VirtualDisplay.cpp @@ -157,6 +157,16 @@ namespace dragon DragonRuntime::vGraphicsInterface.writeVRAM_16Colors(static_cast(x), static_cast(y), textCell.character, textCell.backgroundColor, textCell.foregroundColor); } + else if (signal == tSignalValues::ClearSCreen) + { + hw::interface::Graphics::tText16_Cell textCell; + + textCell.foregroundColor = mem.read8(vga_addr + tRegisters::MemControllerFGCol); + textCell.backgroundColor = mem.read8(vga_addr + tRegisters::MemControllerBGCol); + textCell.character = mem.read8(vga_addr + tRegisters::MemControllerChar); + + DragonRuntime::vGraphicsInterface.clearVRAM_16Colors(textCell.character, textCell.backgroundColor, textCell.foregroundColor); + } } else return; mem.write8(vga_addr + tRegisters::Signal, tSignalValues::Continue); diff --git a/src/hardware/VirtualIODevices.cpp b/src/hardware/VirtualIODevices.cpp index f7e18fd..f6047b5 100644 --- a/src/hardware/VirtualIODevices.cpp +++ b/src/hardware/VirtualIODevices.cpp @@ -45,13 +45,13 @@ namespace dragon int8_t VirtualBIOS::write8(uint16_t addr, int8_t value) { - data::ErrorHandler::pushError(data::ErrorCodes::BIOS_WriteAttempt, ostd::String("Attempting to write to BIOS memory map.").add(addr)); + data::ErrorHandler::pushError(data::ErrorCodes::BIOS_WriteAttempt, ostd::String("Attempting to write to BIOS memory map: ").add(ostd::Utils::getHexStr(addr, true, 2))); return 0x00; } int16_t VirtualBIOS::write16(uint16_t addr, int16_t value) { - data::ErrorHandler::pushError(data::ErrorCodes::BIOS_WriteAttempt, ostd::String("Attempting to write to BIOS memory map.").add(addr)); + data::ErrorHandler::pushError(data::ErrorCodes::BIOS_WriteAttempt, ostd::String("Attempting to write to BIOS memory map: ").add(ostd::Utils::getHexStr(addr, true, 2))); return 0x0000; } @@ -741,6 +741,20 @@ namespace dragon return true; } + bool Graphics::clearVRAM_16Colors(uint8_t character, uint8_t background, uint8_t foreground) + { + for (int32_t i = m_vramStart; i < m_vramStart + (RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::CONSOLE_CHARS_V); i++) + { + if (!m_videoMemory.w_Byte(i + tText16_CellStructure::character, character)) + return false; //TODO: Error + if (!m_videoMemory.w_Byte(i + tText16_CellStructure::background, background)) + return false; //TODO: Error + if (!m_videoMemory.w_Byte(i + tText16_CellStructure::foreground, foreground)) + return false; //TODO: Error + } + return true; + } + diff --git a/src/hardware/VirtualIODevices.hpp b/src/hardware/VirtualIODevices.hpp index e3c0246..8cf827d 100644 --- a/src/hardware/VirtualIODevices.hpp +++ b/src/hardware/VirtualIODevices.hpp @@ -370,6 +370,7 @@ namespace dragon 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); private: ostd::serial::SerialIO m_videoMemory;