[0.1.1544] - Remove BIOSVideo interface, because it was too messy + Fixed long time bug
This commit is contained in:
parent
ddc3b9b0cd
commit
758b1e41b8
47 changed files with 1236 additions and 1751 deletions
|
|
@ -30,10 +30,7 @@ list(APPEND RUNTIME_SOURCE_FILES
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/runtime/ConfigLoader.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/runtime/ConfigLoader.cpp
|
||||||
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/gui/Window.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/gui/Window.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/gui/widgets/VirtualConsoleWidget.cpp
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/gui/RawTextRenderer.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/gui/RawTextRenderer.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/gui/VirtualConsoleOutputHandler.cpp
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/gui/VirtualConsole.cpp
|
|
||||||
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualCPU.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualCPU.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualRAM.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualRAM.cpp
|
||||||
|
|
@ -48,11 +45,8 @@ list(APPEND DEBUGGER_SOURCE_FILES
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/debugger/DisassemblyLoader.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/debugger/DisassemblyLoader.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/debugger/Debugger.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/debugger/Debugger.cpp
|
||||||
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/gui/DebuggerWindow.cpp
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/gui/Window.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/gui/Window.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/gui/widgets/VirtualConsoleWidget.cpp
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/gui/RawTextRenderer.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/gui/RawTextRenderer.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/gui/VirtualConsoleOutputHandler.cpp
|
|
||||||
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualCPU.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualCPU.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualRAM.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualRAM.cpp
|
||||||
|
|
|
||||||
2
build.nr
2
build.nr
|
|
@ -1 +1 @@
|
||||||
1542
|
1544
|
||||||
|
|
|
||||||
20
compile
20
compile
|
|
@ -6,10 +6,26 @@ if [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
|
||||||
cmake -B bin -S ./
|
cmake -B bin -S ./
|
||||||
cd bin
|
cd bin
|
||||||
make
|
make
|
||||||
cd ..
|
if [ $? -eq 0 ]; then
|
||||||
|
cd ..
|
||||||
|
typeset -i build_number=$(cat build.nr)
|
||||||
|
((build_number++))
|
||||||
|
truncate -s 0 build.nr
|
||||||
|
echo $build_number >> build.nr
|
||||||
|
else
|
||||||
|
cd ..
|
||||||
|
fi
|
||||||
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
|
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
|
||||||
cmake -B bin -S ./ -G "MinGW Makefiles"
|
cmake -B bin -S ./ -G "MinGW Makefiles"
|
||||||
cd bin
|
cd bin
|
||||||
mingw32-make.exe
|
mingw32-make.exe
|
||||||
cd ..
|
if [ $? -eq 0 ]; then
|
||||||
|
cd ..
|
||||||
|
typeset -i build_number=$(cat build.nr)
|
||||||
|
((build_number++))
|
||||||
|
truncate -s 0 build.nr
|
||||||
|
echo $build_number >> build.nr
|
||||||
|
else
|
||||||
|
cd ..
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
@ -1,79 +1,69 @@
|
||||||
0x0000
|
0x0000 BIOS (4096 Bytes)
|
||||||
BIOS (1024 Bytes)
|
0x0FFF
|
||||||
0x03FF
|
|
||||||
-------
|
-------
|
||||||
0x0400
|
0x1000 CMOS (128 Bytes)
|
||||||
CMOS (128 Bytes)
|
BootDisk: 0x0010
|
||||||
BootDisk: 0x0010
|
0x107F
|
||||||
0x047F
|
|
||||||
-------
|
-------
|
||||||
0x0480
|
0x1080 INTERRUPT VECTOR (512 Bytes)
|
||||||
INTERRUPT VECTOR (512 Bytes)
|
Status: 1 Byte
|
||||||
0x067F
|
0xFF: Enabled
|
||||||
|
0x00: Disabled
|
||||||
|
Handler Address: 2 Byte
|
||||||
|
...Repeat...
|
||||||
|
0x127F
|
||||||
-------
|
-------
|
||||||
0x0680
|
0x1280 KEYBOARD MAPPING (224 Bytes)
|
||||||
KEYBOARD MAPPING (224 Bytes)
|
0x135F
|
||||||
0x075F
|
|
||||||
-------
|
-------
|
||||||
0x0760
|
0x1360 MOUSE MAPPING (32 Bytes)
|
||||||
MOUSE MAPPING (32 Bytes)
|
0x137F
|
||||||
0x077F
|
|
||||||
-------
|
-------
|
||||||
0x0780
|
0x1380 BOOTLOADER (512 Bytes)
|
||||||
BIOS VIDEO MEMORY (3840 Bytes)
|
0x157F
|
||||||
0x000: Clear Color (1 Byte)
|
|
||||||
0x001: Palette (1 Byte)
|
|
||||||
0x002: UseTransparencyOn0x5 (1 Byte)
|
|
||||||
0x003: Signal (1 Byte)
|
|
||||||
0x00: Continue
|
|
||||||
0x01: Clear Screen
|
|
||||||
0x03C - 0xEFF: 3780 Bytes
|
|
||||||
Structure:
|
|
||||||
90x21 characters
|
|
||||||
1 Byte ascii
|
|
||||||
1 byte: 4 Bits background/4 bits foreground
|
|
||||||
0x167F
|
|
||||||
-------
|
-------
|
||||||
0x1680
|
0x1580 DISK INTERFACE (128 Bytes)
|
||||||
BOOTLOADER (512 Bytes)
|
Read/Write:
|
||||||
0x187F
|
Signal: 1 Byte
|
||||||
|
0x00: Start Operation
|
||||||
|
0x01: Cancel Current Operation
|
||||||
|
0xFF: Ignore
|
||||||
|
Mode: 1 Byte
|
||||||
|
0x00: Read
|
||||||
|
0x01: Write
|
||||||
|
Disk: 1 Byte
|
||||||
|
Sector: 2 Bytes
|
||||||
|
Address: 2 Bytes
|
||||||
|
DataSize: 2 Bytes
|
||||||
|
DataAddress: 2 Byte
|
||||||
|
ReadOnly:
|
||||||
|
Status: 1 Byte
|
||||||
|
0x00: Free
|
||||||
|
0x01: Writing
|
||||||
|
0x02: Reading
|
||||||
|
CurrentDisk: 1 Byte
|
||||||
|
CurrentSector: 2 Bytes
|
||||||
|
CurrentAddress: 2 Bytes
|
||||||
|
RestDataSize: 2 Bytes
|
||||||
|
SourceData: 2 Bytes
|
||||||
|
Free: 107 Byte
|
||||||
|
0x15FF
|
||||||
-------
|
-------
|
||||||
0x1880
|
0x1600 VIDEO CARD INTERFACE (256 Bytes)
|
||||||
DISK INTERFACE (128 Bytes)
|
0x00: Video Mode (1 Byte)
|
||||||
Read/Write:
|
0x00: Single Color
|
||||||
Signal: 1 Byte
|
0x01: 16-color
|
||||||
0x00: Start Operation
|
0x02: 256-color
|
||||||
0x01: Cancel Current Operation
|
0x03: True Color Mode
|
||||||
0xFF: Ignore
|
0x01: Clear Color (1 Byte)
|
||||||
Mode: 1 Byte
|
0x02: Palette (1 Byte)
|
||||||
0x00: Read
|
0x03: Signal (1 Byte)
|
||||||
0x01: Write
|
0x00: Continue
|
||||||
Disk: 1 Byte
|
0x01: Clear Screen
|
||||||
Sector: 2 Bytes
|
0x16FF
|
||||||
Address: 2 Bytes
|
|
||||||
DataSize: 2 Bytes
|
|
||||||
DataAddress: 2 Byte
|
|
||||||
ReadOnly:
|
|
||||||
Status: 1 Byte
|
|
||||||
0x00: Free
|
|
||||||
0x01: Writing
|
|
||||||
0x02: Reading
|
|
||||||
CurrentDisk: 1 Byte
|
|
||||||
CurrentSector: 2 Bytes
|
|
||||||
CurrentAddress: 2 Bytes
|
|
||||||
RestDataSize: 2 Bytes
|
|
||||||
SourceData: 2 Bytes
|
|
||||||
Free: 107 Byte
|
|
||||||
0x18FF
|
|
||||||
-------
|
-------
|
||||||
0x1900
|
0x1700 GENERIC SERIAL INTERFACE (64 Bytes)
|
||||||
VIDEO CARD INTERFACE (256 Bytes)
|
0x173F
|
||||||
0x19FF
|
|
||||||
-------
|
-------
|
||||||
0x1A00
|
0x1740 RAM (59583 Bytes)
|
||||||
GENERIC SERIAL INTERFACE (64 Bytes)
|
|
||||||
0x1A3F
|
|
||||||
-------
|
|
||||||
0x1A40
|
|
||||||
RAM (58815 Bytes)
|
|
||||||
0xFFFF
|
0xFFFF
|
||||||
|
|
|
||||||
|
|
@ -10,61 +10,4 @@ Software Interrupts:
|
||||||
|
|
||||||
Hardware Interrupts:
|
Hardware Interrupts:
|
||||||
====================
|
====================
|
||||||
0x80: Disk Interface Finished
|
0x80: Disk Interface Finished
|
||||||
0x81: BiosVideo Screen Refreshed
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Default Palette BIOS Colors:
|
|
||||||
====================
|
|
||||||
0x0: Black
|
|
||||||
0, 0, 0
|
|
||||||
#000000
|
|
||||||
0x1: Gray
|
|
||||||
157, 157, 157
|
|
||||||
#9D9D9D
|
|
||||||
0x2: White
|
|
||||||
255, 255, 255
|
|
||||||
#FFFFFF
|
|
||||||
0x3: Red
|
|
||||||
190, 38, 51
|
|
||||||
#BE2633
|
|
||||||
0x4: Pimk
|
|
||||||
224, 111, 139
|
|
||||||
#E06F8B
|
|
||||||
OLD -- 0x5: DarkBrown
|
|
||||||
OLD -- 73, 60, 43
|
|
||||||
OLD -- #493C2B
|
|
||||||
0x5: Transparent
|
|
||||||
--
|
|
||||||
0x6: Brown
|
|
||||||
164, 100, 34
|
|
||||||
#A46422
|
|
||||||
0x7: Orange
|
|
||||||
235, 137, 49
|
|
||||||
#EB8931
|
|
||||||
0x8: Yellow
|
|
||||||
247, 226, 107
|
|
||||||
#F7E26B
|
|
||||||
0x9: Dark Green
|
|
||||||
47, 80, 42
|
|
||||||
#2F502A
|
|
||||||
0xA: Green
|
|
||||||
68, 137, 26
|
|
||||||
#44891A
|
|
||||||
0xB: Slime Green
|
|
||||||
163, 206, 39
|
|
||||||
#A3CE27
|
|
||||||
0xC: Night Blue
|
|
||||||
27, 38, 50
|
|
||||||
#1B2632
|
|
||||||
0xD: Sea Blue
|
|
||||||
0, 87, 132
|
|
||||||
#005784
|
|
||||||
0xE: Sky Blue
|
|
||||||
49, 162, 242
|
|
||||||
#31A2F2
|
|
||||||
0xF: Cloud Blue
|
|
||||||
178, 220, 239
|
|
||||||
#B2DCEF
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,25 +1,21 @@
|
||||||
## ============================= Memory Mapped Devices and Registers =============================
|
## ============================= Memory Mapped Devices and Registers =============================
|
||||||
@define MBR_START_ADDRESS 0x1680
|
@define MBR_START_ADDRESS 0x1380
|
||||||
@define INT_VEC_START_ADDRESS 0x0480
|
@define INT_VEC_START_ADDRESS 0x1080
|
||||||
@define DISK_INTERFACE_START_ADDRESS 0x1880
|
@define DISK_INTERFACE_START_ADDRESS 0x1580
|
||||||
@define MEMORY_START_ADDRESS 0x1A40
|
@define MEMORY_START_ADDRESS 0x1740
|
||||||
@define CMOS_START_ADDRESS 0x0400
|
@define CMOS_START_ADDRESS 0x1000
|
||||||
@define BIOS_VIDEO_START_ADDRESS 0x0780
|
|
||||||
@define BIOS_VIDEO_MEMORY_START_ADDRESS 0x07BC
|
|
||||||
@define BIOS_VIDEO_MEMORY_END_ADDRESS 0x167F
|
|
||||||
|
|
||||||
@define _BIOS_VIDEO_REG_CLEAR_COLOR {BIOS_VIDEO_START_ADDRESS + 0x0000}
|
|
||||||
@define _BIOS_VIDEO_REG_SIGNAL {BIOS_VIDEO_START_ADDRESS + 0x0003}
|
|
||||||
## ===============================================================================================
|
## ===============================================================================================
|
||||||
|
|
||||||
@define _CMOS_REG_BOOT_DISK {CMOS_START_ADDRESS + 0x0010}
|
@define _CMOS_REG_BOOT_DISK {CMOS_START_ADDRESS + 0x0010}
|
||||||
|
|
||||||
.load 0x0000 ## BIOS is mapped to address 0x0000 in memory
|
.load 0x0000 ## BIOS is mapped to address 0x0000 in memory
|
||||||
.data
|
.data
|
||||||
$bios_version_number 0x00, 0x01 ## BIOS Version stored in memory
|
$bios_version_number 0x04, 0x01 ## BIOS Version stored in memory
|
||||||
|
|
||||||
## ============================= BIOS Program =============================
|
## ============================= BIOS Program =============================
|
||||||
.code
|
.code
|
||||||
|
## mov FL, 0
|
||||||
|
## jmp 0x1740
|
||||||
mov FL, 0b0000000000000001 ## Zero the FL Register and enable interrupts
|
mov FL, 0b0000000000000001 ## Zero the FL Register and enable interrupts
|
||||||
movb [{INT_VEC_START_ADDRESS + (0x20 * 3)}], 0xFF ## Setting up int 0x20 handler
|
movb [{INT_VEC_START_ADDRESS + (0x20 * 3)}], 0xFF ## Setting up int 0x20 handler
|
||||||
mov [{INT_VEC_START_ADDRESS + (0x20 * 3) + 1}], $_int_20_handler ## --
|
mov [{INT_VEC_START_ADDRESS + (0x20 * 3) + 1}], $_int_20_handler ## --
|
||||||
|
|
@ -38,6 +34,7 @@
|
||||||
call $_load_mbr_data_block
|
call $_load_mbr_data_block
|
||||||
## ----
|
## ----
|
||||||
|
|
||||||
|
debug_break
|
||||||
jmp MBR_START_ADDRESS ## Jump to start of MBR in memory
|
jmp MBR_START_ADDRESS ## Jump to start of MBR in memory
|
||||||
hlt ## Just in case somehow execution reaches this point
|
hlt ## Just in case somehow execution reaches this point
|
||||||
## ========================================================================
|
## ========================================================================
|
||||||
|
|
@ -89,7 +86,7 @@ _int_30_handler:
|
||||||
jeq $_int_30_clear_screen, 0x0000
|
jeq $_int_30_clear_screen, 0x0000
|
||||||
jmp $_int_30_end
|
jmp $_int_30_end
|
||||||
_int_30_clear_screen:
|
_int_30_clear_screen:
|
||||||
movb [_BIOS_VIDEO_REG_SIGNAL], 0x01 ## Signal = ClearScreen
|
nop
|
||||||
_int_30_end:
|
_int_30_end:
|
||||||
rti
|
rti
|
||||||
## ==================================================================================
|
## ==================================================================================
|
||||||
|
|
@ -101,8 +98,7 @@ _load_mbr_data_block:
|
||||||
movb [{DISK_INTERFACE_START_ADDRESS + 0x2}], R1 ## Disk = Default
|
movb [{DISK_INTERFACE_START_ADDRESS + 0x2}], R1 ## Disk = Default
|
||||||
mov [{DISK_INTERFACE_START_ADDRESS + 0x3}],0x0000 ## Sector = 0x0000
|
mov [{DISK_INTERFACE_START_ADDRESS + 0x3}],0x0000 ## Sector = 0x0000
|
||||||
mov [{DISK_INTERFACE_START_ADDRESS + 0x5}],0x0000 ## Address = 0x0000 (Start of Disk)
|
mov [{DISK_INTERFACE_START_ADDRESS + 0x5}],0x0000 ## Address = 0x0000 (Start of Disk)
|
||||||
##//TODO: currently set to 20 instead of 512, for debugging purposes
|
mov [{DISK_INTERFACE_START_ADDRESS + 0x7}], 20 ## Size = 512 (Size of MBR is 512 bytes)
|
||||||
mov [{DISK_INTERFACE_START_ADDRESS + 0x7}], 20 ## Size = 512 (Size of MBR is 512 bytes)
|
|
||||||
mov [{DISK_INTERFACE_START_ADDRESS + 0x9}], MBR_START_ADDRESS ## MemoryAddress = MBR Address in memory
|
mov [{DISK_INTERFACE_START_ADDRESS + 0x9}], MBR_START_ADDRESS ## MemoryAddress = MBR Address in memory
|
||||||
movb [DISK_INTERFACE_START_ADDRESS], 0x00 ## Signal = Start
|
movb [DISK_INTERFACE_START_ADDRESS], 0x00 ## Signal = Start
|
||||||
_load_mbr_data_block_wait_loop:
|
_load_mbr_data_block_wait_loop:
|
||||||
|
|
@ -137,4 +133,4 @@ _set_interrupt_vector_entry_end:
|
||||||
mov *R1, ACC
|
mov *R1, ACC
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.fixed 1024, 0x00 ## BIOS Needs to be 1024 Bytes exactly
|
.fixed 4096, 0x00 ## BIOS Needs to be 4096 Bytes exactly
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
.load 0x1A40
|
.load 0x1740
|
||||||
|
|
||||||
##@struct Rectangle {
|
##@struct Rectangle {
|
||||||
## width:2,
|
## width:2,
|
||||||
|
|
@ -20,14 +20,12 @@
|
||||||
## $rect => Rectangle
|
## $rect => Rectangle
|
||||||
|
|
||||||
.code
|
.code
|
||||||
debug_break
|
|
||||||
infinite_loop:
|
infinite_loop:
|
||||||
push 0
|
push 0
|
||||||
call $clear_screen
|
call $clear_screen
|
||||||
|
|
||||||
## mov $rect.x, 200
|
## mov $rect.x, 200
|
||||||
|
|
||||||
## debug_break
|
|
||||||
|
|
||||||
push $string
|
push $string
|
||||||
push 1
|
push 1
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
.load 0x1680
|
.load 0x1380
|
||||||
|
|
||||||
.code
|
.code
|
||||||
jmp 0x1A40
|
jmp 0x1740
|
||||||
hlt
|
hlt
|
||||||
|
|
||||||
.fixed 512, 0x00
|
.fixed 512, 0x00
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,74 @@
|
||||||
.load 0x1A40
|
.load 0x1740
|
||||||
|
|
||||||
.data
|
.data
|
||||||
$v1 0x00, 0x01
|
$cursor_pos 0x00, 0x00
|
||||||
$v2 0x00, 0x01
|
$color 0x02
|
||||||
$v3 0x00, 0x01, 0x00, 0x01, 0x00, 0x01
|
$current_video_addr 0x07, 0xBC
|
||||||
|
|
||||||
|
$string "Hello World!!"
|
||||||
|
|
||||||
.code
|
.code
|
||||||
mov R1, 0xAA
|
|
||||||
mov R2, 0xBB
|
|
||||||
mov R3, 0xCC
|
|
||||||
debug_break
|
debug_break
|
||||||
|
infinite_loop:
|
||||||
|
push 0
|
||||||
|
call $clear_screen
|
||||||
|
|
||||||
|
jmp $infinite_loop
|
||||||
hlt
|
hlt
|
||||||
|
|
||||||
|
|
||||||
|
print_string:
|
||||||
|
mov R1, *PP
|
||||||
|
dec PP
|
||||||
|
dec PP
|
||||||
|
|
||||||
|
push R1
|
||||||
|
push 1
|
||||||
|
call $strlen
|
||||||
|
mov R2, RV
|
||||||
|
|
||||||
|
push 65
|
||||||
|
push 1
|
||||||
|
call $print_char
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
strlen:
|
||||||
|
mov R1, *PP
|
||||||
|
dec PP
|
||||||
|
dec PP
|
||||||
|
mov R2, 0
|
||||||
|
_strlen_loop:
|
||||||
|
movb ACC, *R1
|
||||||
|
jeq $_strlen_end_loop, 0
|
||||||
|
inc R2
|
||||||
|
inc R1
|
||||||
|
jmp $_strlen_loop
|
||||||
|
_strlen_end_loop:
|
||||||
|
mov RV, R2
|
||||||
|
ret
|
||||||
|
|
||||||
|
print_char:
|
||||||
|
mov R2, *PP
|
||||||
|
dec PP
|
||||||
|
dec PP
|
||||||
|
mov R1, [$current_video_addr]
|
||||||
|
mov R3, [$cursor_pos]
|
||||||
|
mul R3, 2
|
||||||
|
mov R3, ACC
|
||||||
|
add R1, R3
|
||||||
|
mov R1, ACC
|
||||||
|
movb *R1, R2
|
||||||
|
inc R1
|
||||||
|
movb *R1, [$color]
|
||||||
|
mov R3, [$cursor_pos]
|
||||||
|
inc R3
|
||||||
|
mov [$cursor_pos], R3
|
||||||
|
ret
|
||||||
|
|
||||||
|
clear_screen:
|
||||||
|
mov R10, 0x00
|
||||||
|
int 0x30
|
||||||
|
ret
|
||||||
|
|
||||||
.fixed 512, 0x00
|
.fixed 512, 0x00
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
.load 0x1A40
|
.load 0x1740
|
||||||
|
|
||||||
.code
|
.code
|
||||||
mov R1, 0xABCD
|
mov R1, 0xABCD
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
printf "${green}\n============================================[ Building Application ]============================================\n\n${clear}"
|
printf "${green}\n============================================[ Building Application ]============================================\n\n${clear}"
|
||||||
\cp -r ../extra/* ./
|
\cp -r ../extra/* ./
|
||||||
if [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
|
if [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
|
||||||
make
|
make
|
||||||
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
|
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
|
||||||
mingw32-make.exe
|
mingw32-make.exe
|
||||||
cp ../../omnia-framework/bin/libostd.dll ./
|
|
||||||
fi
|
fi
|
||||||
printf "${green}\n=================================================================================================================\n\n"
|
printf "${green}\n=================================================================================================================\n\n"
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
|
|
@ -16,10 +14,10 @@ if [ $? -eq 0 ]; then
|
||||||
/bin/bash ./load_mbr
|
/bin/bash ./load_mbr
|
||||||
cd ..
|
cd ..
|
||||||
printf "${green}Compiling Test Program...\n"
|
printf "${green}Compiling Test Program...\n"
|
||||||
./dasm dss/handlerTest.dss -o handlerTest.bin --save-disassembly disassembly/handlerTest.dds
|
./dasm dss/newTest.dss -o newTest.bin --save-disassembly disassembly/newTest.dds
|
||||||
printf "\n${green}Running Application...\n\n${clear}"
|
printf "\n${green}Running Application...\n\n${clear}"
|
||||||
./ddb config/testMachine.dvm --force-load handlerTest.bin 0x00 --verbose-load --track-step-diff --hide-vdisplay
|
./ddb config/testMachine.dvm --force-load newTest.bin 0x00 --verbose-load --hide-vdisplay
|
||||||
#./dvm config/testMachine.dvm --debug --force-load newTest.bin 0x00 --verbose-load
|
# ./dvm config/testMachine.dvm --debug --force-load newTest.bin 0x00 --verbose-load
|
||||||
cp dragon/disk1.dr ../extra/dragon/disk1.dr
|
cp dragon/disk1.dr ../extra/dragon/disk1.dr
|
||||||
cp dragon/cmos.dr ../extra/dragon/cmos.dr
|
cp dragon/cmos.dr ../extra/dragon/cmos.dr
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ namespace dragon
|
||||||
void Assembler::loadSource(ostd::String source)
|
void Assembler::loadSource(ostd::String source)
|
||||||
{
|
{
|
||||||
m_rawSource = source;
|
m_rawSource = source;
|
||||||
m_lines = ostd::StringEditor(source).tokenize("\n").getRawData();
|
m_lines = ostd::String(source).tokenize("\n").getRawData();
|
||||||
}
|
}
|
||||||
|
|
||||||
ostd::ByteStream Assembler::assembleToFile(ostd::String sourceFileName, ostd::String binaryFileName)
|
ostd::ByteStream Assembler::assembleToFile(ostd::String sourceFileName, ostd::String binaryFileName)
|
||||||
|
|
@ -77,21 +77,21 @@ namespace dragon
|
||||||
if (m_code.size() == 0 || m_disassembly.size() == 0) return false;
|
if (m_code.size() == 0 || m_disassembly.size() == 0) return false;
|
||||||
ostd::String header_string = "{ DRAGON_DEBUG_DISASSEMBLY }";
|
ostd::String header_string = "{ DRAGON_DEBUG_DISASSEMBLY }";
|
||||||
uint64_t da_size = 0;
|
uint64_t da_size = 0;
|
||||||
da_size += (header_string.length() + 1) * ostd::tTypeSize::BYTE;
|
da_size += (header_string.len() + 1) * ostd::tTypeSize::BYTE;
|
||||||
da_size += m_disassembly.size() * ostd::tTypeSize::DWORD; //Addresses
|
da_size += m_disassembly.size() * ostd::tTypeSize::DWORD; //Addresses
|
||||||
da_size += m_disassembly.size() * ostd::tTypeSize::BYTE; //Null Termination
|
da_size += m_disassembly.size() * ostd::tTypeSize::BYTE; //Null Termination
|
||||||
for (auto& da : m_disassembly)
|
for (auto& da : m_disassembly)
|
||||||
da_size += da.code.length() * ostd::tTypeSize::BYTE; //Code Strings
|
da_size += da.code.len() * ostd::tTypeSize::BYTE; //Code Strings
|
||||||
ostd::serial::SerialIO serializer(da_size, ostd::serial::SerialIO::tEndianness::BigEndian);
|
ostd::serial::SerialIO serializer(da_size, ostd::serial::SerialIO::tEndianness::BigEndian);
|
||||||
ostd::StreamIndex stream_addr = 0;
|
ostd::StreamIndex stream_addr = 0;
|
||||||
serializer.w_String(stream_addr, header_string);
|
serializer.w_String(stream_addr, header_string);
|
||||||
stream_addr += (header_string.length() + 1) * ostd::tTypeSize::BYTE;
|
stream_addr += (header_string.len() + 1) * ostd::tTypeSize::BYTE;
|
||||||
for (auto& da : m_disassembly)
|
for (auto& da : m_disassembly)
|
||||||
{
|
{
|
||||||
serializer.w_DWord(stream_addr, da.addr);
|
serializer.w_DWord(stream_addr, da.addr);
|
||||||
stream_addr += ostd::tTypeSize::DWORD;
|
stream_addr += ostd::tTypeSize::DWORD;
|
||||||
serializer.w_String(stream_addr, da.code);
|
serializer.w_String(stream_addr, da.code);
|
||||||
stream_addr += (da.code.length() + 1) * ostd::tTypeSize::BYTE;
|
stream_addr += (da.code.len() + 1) * ostd::tTypeSize::BYTE;
|
||||||
// ostd::ByteStream code_stream = ostd::Utils::stringToByteStream(da.code);
|
// ostd::ByteStream code_stream = ostd::Utils::stringToByteStream(da.code);
|
||||||
// for (int32_t i = 0; i < code_stream.size(); i++)
|
// for (int32_t i = 0; i < code_stream.size(); i++)
|
||||||
// {
|
// {
|
||||||
|
|
@ -107,7 +107,7 @@ namespace dragon
|
||||||
void Assembler::removeComments(void)
|
void Assembler::removeComments(void)
|
||||||
{
|
{
|
||||||
std::vector<ostd::String> newLines;
|
std::vector<ostd::String> newLines;
|
||||||
ostd::StringEditor lineEdit;
|
ostd::String lineEdit;
|
||||||
for (auto& line : m_lines)
|
for (auto& line : m_lines)
|
||||||
{
|
{
|
||||||
lineEdit = line;
|
lineEdit = line;
|
||||||
|
|
@ -119,7 +119,7 @@ namespace dragon
|
||||||
lineEdit = lineEdit.substr(0, lineEdit.indexOf("##"));
|
lineEdit = lineEdit.substr(0, lineEdit.indexOf("##"));
|
||||||
lineEdit.trim();
|
lineEdit.trim();
|
||||||
}
|
}
|
||||||
newLines.push_back(lineEdit.str());
|
newLines.push_back(lineEdit);
|
||||||
}
|
}
|
||||||
m_lines.clear();
|
m_lines.clear();
|
||||||
m_lines = newLines;
|
m_lines = newLines;
|
||||||
|
|
@ -141,8 +141,8 @@ namespace dragon
|
||||||
};
|
};
|
||||||
std::vector<tDefine> defines;
|
std::vector<tDefine> defines;
|
||||||
std::vector<ostd::String> newLines;
|
std::vector<ostd::String> newLines;
|
||||||
ostd::StringEditor lineEdit;
|
ostd::String lineEdit;
|
||||||
ostd::StringEditor tmpLineEdit;
|
ostd::String tmpLineEdit;
|
||||||
for (auto& line : m_lines)
|
for (auto& line : m_lines)
|
||||||
{
|
{
|
||||||
lineEdit = line;
|
lineEdit = line;
|
||||||
|
|
@ -157,9 +157,9 @@ namespace dragon
|
||||||
std::cout << "Invalid @define directive: " << line << "\n";
|
std::cout << "Invalid @define directive: " << line << "\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ostd::String define_name = lineEdit.substr(0, lineEdit.indexOf(" "));
|
ostd::String define_name = lineEdit.new_substr(0, lineEdit.indexOf(" "));
|
||||||
define_name = ostd::StringEditor(define_name).trim().str();
|
define_name = ostd::String(define_name).trim();
|
||||||
ostd::String define_value = lineEdit.substr(lineEdit.indexOf(" ") + 1);
|
ostd::String define_value = lineEdit.new_substr(lineEdit.indexOf(" ") + 1);
|
||||||
if (listContainsDefine(defines, define_name))
|
if (listContainsDefine(defines, define_name))
|
||||||
{
|
{
|
||||||
std::cout << "Redefinition of @define value: " << line << "\n";
|
std::cout << "Redefinition of @define value: " << line << "\n";
|
||||||
|
|
@ -169,14 +169,14 @@ namespace dragon
|
||||||
// std::cout << define_name << ": " << define_value << "\n";
|
// std::cout << define_name << ": " << define_value << "\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
newLines.push_back(lineEdit.str());
|
newLines.push_back(lineEdit);
|
||||||
}
|
}
|
||||||
for (auto& line : newLines)
|
for (auto& line : newLines)
|
||||||
{
|
{
|
||||||
ostd::StringEditor lineEdit(line);
|
ostd::String lineEdit(line);
|
||||||
for (int32_t i = defines.size() - 1; i >= 0; i--)
|
for (int32_t i = defines.size() - 1; i >= 0; i--)
|
||||||
lineEdit.replaceAll(defines[i].name, defines[i].value);
|
lineEdit.replaceAll(defines[i].name, defines[i].value);
|
||||||
line = lineEdit.str();
|
line = lineEdit;
|
||||||
}
|
}
|
||||||
m_lines.clear();
|
m_lines.clear();
|
||||||
m_lines = newLines;
|
m_lines = newLines;
|
||||||
|
|
@ -191,7 +191,7 @@ namespace dragon
|
||||||
|
|
||||||
for (auto& line : m_lines)
|
for (auto& line : m_lines)
|
||||||
{
|
{
|
||||||
ostd::StringEditor lineEdit(line);
|
ostd::String lineEdit(line);
|
||||||
if (lineEdit.startsWith(".data"))
|
if (lineEdit.startsWith(".data"))
|
||||||
currentSection = DATA_SECTION;
|
currentSection = DATA_SECTION;
|
||||||
else if (lineEdit.startsWith(".code"))
|
else if (lineEdit.startsWith(".code"))
|
||||||
|
|
@ -212,7 +212,7 @@ namespace dragon
|
||||||
std::cout << "Invalid .fixed value: " << lineEdit << "\n";
|
std::cout << "Invalid .fixed value: " << lineEdit << "\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ostd::StringEditor fixedSizeEdit = lineEdit.substr(0, lineEdit.indexOf(","));
|
ostd::String fixedSizeEdit = lineEdit.new_substr(0, lineEdit.indexOf(","));
|
||||||
fixedSizeEdit.trim();
|
fixedSizeEdit.trim();
|
||||||
lineEdit = lineEdit.substr(lineEdit.indexOf(",") + 1);
|
lineEdit = lineEdit.substr(lineEdit.indexOf(",") + 1);
|
||||||
lineEdit.trim();
|
lineEdit.trim();
|
||||||
|
|
@ -278,14 +278,14 @@ namespace dragon
|
||||||
{
|
{
|
||||||
for (auto& line : m_rawDataSection)
|
for (auto& line : m_rawDataSection)
|
||||||
{
|
{
|
||||||
ostd::StringEditor lineEdit(line);
|
ostd::String lineEdit(line);
|
||||||
tSymbol symbol;
|
tSymbol symbol;
|
||||||
if (!lineEdit.startsWith("$") || lineEdit.indexOf(" ") < 2)
|
if (!lineEdit.startsWith("$") || lineEdit.indexOf(" ") < 2)
|
||||||
{
|
{
|
||||||
std::cout << "Invalid data entry: " << lineEdit << "\n";
|
std::cout << "Invalid data entry: " << lineEdit << "\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ostd::StringEditor symbolName = lineEdit.substr(0, lineEdit.indexOf(" "));
|
ostd::String symbolName = lineEdit.new_substr(0, lineEdit.indexOf(" "));
|
||||||
symbolName.trim();
|
symbolName.trim();
|
||||||
lineEdit = lineEdit.substr(lineEdit.indexOf(" ") + 1);
|
lineEdit = lineEdit.substr(lineEdit.indexOf(" ") + 1);
|
||||||
lineEdit.trim();
|
lineEdit.trim();
|
||||||
|
|
@ -304,18 +304,18 @@ namespace dragon
|
||||||
symbol.bytes.push_back(value);
|
symbol.bytes.push_back(value);
|
||||||
symbol.address = m_currentDataAddr;
|
symbol.address = m_currentDataAddr;
|
||||||
m_currentDataAddr += 1;
|
m_currentDataAddr += 1;
|
||||||
m_symbolTable[symbolName.str()] = symbol;
|
m_symbolTable[symbolName] = symbol;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (lineEdit.startsWith("\"") && lineEdit.endsWith("\"") && lineEdit.len() > 2)
|
else if (lineEdit.startsWith("\"") && lineEdit.endsWith("\"") && lineEdit.len() > 2)
|
||||||
{
|
{
|
||||||
lineEdit = lineEdit.substr(1, lineEdit.len() - 1);
|
lineEdit = lineEdit.substr(1, lineEdit.len() - 1);
|
||||||
for (auto c : lineEdit.str())
|
for (auto c : lineEdit)
|
||||||
symbol.bytes.push_back((uint8_t)c);
|
symbol.bytes.push_back((uint8_t)c);
|
||||||
symbol.bytes.push_back((uint8_t)0); //NULL Termination
|
symbol.bytes.push_back((uint8_t)0); //NULL Termination
|
||||||
symbol.address = m_currentDataAddr;
|
symbol.address = m_currentDataAddr;
|
||||||
m_currentDataAddr += lineEdit.len();
|
m_currentDataAddr += lineEdit.len();
|
||||||
m_symbolTable[symbolName.str()] = symbol;
|
m_symbolTable[symbolName] = symbol;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (lineEdit.contains(","))
|
else if (lineEdit.contains(","))
|
||||||
|
|
@ -338,7 +338,7 @@ namespace dragon
|
||||||
}
|
}
|
||||||
symbol.address = m_currentDataAddr;
|
symbol.address = m_currentDataAddr;
|
||||||
m_currentDataAddr += symbol.bytes.size();
|
m_currentDataAddr += symbol.bytes.size();
|
||||||
m_symbolTable[symbolName.str()] = symbol;
|
m_symbolTable[symbolName] = symbol;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -358,14 +358,14 @@ namespace dragon
|
||||||
{
|
{
|
||||||
for (auto& line : m_rawCodeSection)
|
for (auto& line : m_rawCodeSection)
|
||||||
{
|
{
|
||||||
ostd::StringEditor lineEdit(line);
|
ostd::String lineEdit(line);
|
||||||
uint32_t commaCount = lineEdit.count(",");
|
uint32_t commaCount = lineEdit.count(",");
|
||||||
uint32_t spaceCount = lineEdit.count(" ");
|
uint32_t spaceCount = lineEdit.count(" ");
|
||||||
if (lineEdit.endsWith(":") && commaCount == 0 && spaceCount == 0) //Labels
|
if (lineEdit.endsWith(":") && commaCount == 0 && spaceCount == 0) //Labels
|
||||||
{
|
{
|
||||||
lineEdit = lineEdit.substr(0, lineEdit.len() - 1);
|
lineEdit = lineEdit.substr(0, lineEdit.len() - 1);
|
||||||
lineEdit.trim();
|
lineEdit.trim();
|
||||||
m_labelTable["$" + lineEdit.str()] = { { }, 0x0000 };
|
m_labelTable["$" + lineEdit] = { { }, 0x0000 };
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -373,55 +373,55 @@ namespace dragon
|
||||||
tDisassemblyLine _disassembly_line;
|
tDisassemblyLine _disassembly_line;
|
||||||
for (auto& line : m_rawCodeSection)
|
for (auto& line : m_rawCodeSection)
|
||||||
{
|
{
|
||||||
ostd::StringEditor lineEdit(line);
|
ostd::String lineEdit(line);
|
||||||
uint32_t commaCount = lineEdit.count(",");
|
uint32_t commaCount = lineEdit.count(",");
|
||||||
uint32_t spaceCount = lineEdit.count(" ");
|
uint32_t spaceCount = lineEdit.count(" ");
|
||||||
if (lineEdit.endsWith(":") && commaCount == 0 && spaceCount == 0) //Labels
|
if (lineEdit.endsWith(":") && commaCount == 0 && spaceCount == 0) //Labels
|
||||||
{
|
{
|
||||||
// _disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
|
// _disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
|
||||||
// _disassembly_line.code = lineEdit.str();
|
// _disassembly_line.code = lineEdit;
|
||||||
// m_disassembly.push_back(_disassembly_line);
|
// m_disassembly.push_back(_disassembly_line);
|
||||||
lineEdit = lineEdit.substr(0, lineEdit.len() - 1);
|
lineEdit = lineEdit.substr(0, lineEdit.len() - 1);
|
||||||
lineEdit.trim();
|
lineEdit.trim();
|
||||||
m_labelTable["$" + lineEdit.str()].address = m_dataSize + m_loadAddress + m_code.size() + 3;
|
m_labelTable["$" + lineEdit].address = m_dataSize + m_loadAddress + m_code.size() + 3;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (commaCount == 0 && spaceCount <= 0) //0 Operands
|
else if (commaCount == 0 && spaceCount <= 0) //0 Operands
|
||||||
{
|
{
|
||||||
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
|
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
|
||||||
ostd::StringEditor _tmp_edit(lineEdit.str());
|
ostd::String _tmp_edit(lineEdit);
|
||||||
if (_tmp_edit.toLower().trim().startsWith("debug_"))
|
if (_tmp_edit.toLower().trim().startsWith("debug_"))
|
||||||
parseDebugOperands(lineEdit.str());
|
parseDebugOperands(lineEdit);
|
||||||
else
|
else
|
||||||
parse0Operand(lineEdit.str());
|
parse0Operand(lineEdit);
|
||||||
_disassembly_line.code = lineEdit.str();
|
_disassembly_line.code = lineEdit;
|
||||||
m_disassembly.push_back(_disassembly_line);
|
m_disassembly.push_back(_disassembly_line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (commaCount == 0) //1 Operands
|
else if (commaCount == 0) //1 Operands
|
||||||
{
|
{
|
||||||
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
|
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
|
||||||
lineEdit = replaceSymbols(lineEdit.str());
|
lineEdit = replaceSymbols(lineEdit);
|
||||||
parse1Operand(lineEdit.str());
|
parse1Operand(lineEdit);
|
||||||
_disassembly_line.code = lineEdit.str();
|
_disassembly_line.code = lineEdit;
|
||||||
m_disassembly.push_back(_disassembly_line);
|
m_disassembly.push_back(_disassembly_line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (commaCount == 1) //2 Operands
|
else if (commaCount == 1) //2 Operands
|
||||||
{
|
{
|
||||||
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
|
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
|
||||||
lineEdit = replaceSymbols(lineEdit.str());
|
lineEdit = replaceSymbols(lineEdit);
|
||||||
parse2Operand(lineEdit.str());
|
parse2Operand(lineEdit);
|
||||||
_disassembly_line.code = lineEdit.str();
|
_disassembly_line.code = lineEdit;
|
||||||
m_disassembly.push_back(_disassembly_line);
|
m_disassembly.push_back(_disassembly_line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (commaCount == 2) // 3 Operands
|
else if (commaCount == 2) // 3 Operands
|
||||||
{
|
{
|
||||||
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
|
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
|
||||||
lineEdit = replaceSymbols(lineEdit.str());
|
lineEdit = replaceSymbols(lineEdit);
|
||||||
parse3Operand(lineEdit.str());
|
parse3Operand(lineEdit);
|
||||||
_disassembly_line.code = lineEdit.str();
|
_disassembly_line.code = lineEdit;
|
||||||
m_disassembly.push_back(_disassembly_line);
|
m_disassembly.push_back(_disassembly_line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -435,22 +435,22 @@ namespace dragon
|
||||||
|
|
||||||
void Assembler::parse0Operand(ostd::String line)
|
void Assembler::parse0Operand(ostd::String line)
|
||||||
{
|
{
|
||||||
if (ostd::StringEditor(line).toLower().startsWith("nop"))
|
if (ostd::String(line).toLower().startsWith("nop"))
|
||||||
{
|
{
|
||||||
m_code.push_back(data::OpCodes::NoOp);
|
m_code.push_back(data::OpCodes::NoOp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (ostd::StringEditor(line).toLower().startsWith("ret"))
|
else if (ostd::String(line).toLower().startsWith("ret"))
|
||||||
{
|
{
|
||||||
m_code.push_back(data::OpCodes::Ret);
|
m_code.push_back(data::OpCodes::Ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (ostd::StringEditor(line).toLower().startsWith("rti"))
|
else if (ostd::String(line).toLower().startsWith("rti"))
|
||||||
{
|
{
|
||||||
m_code.push_back(data::OpCodes::RetInt);
|
m_code.push_back(data::OpCodes::RetInt);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (ostd::StringEditor(line).toLower().startsWith("hlt"))
|
else if (ostd::String(line).toLower().startsWith("hlt"))
|
||||||
{
|
{
|
||||||
m_code.push_back(data::OpCodes::Halt);
|
m_code.push_back(data::OpCodes::Halt);
|
||||||
return;
|
return;
|
||||||
|
|
@ -459,7 +459,7 @@ namespace dragon
|
||||||
|
|
||||||
void Assembler::parseDebugOperands(ostd::String line)
|
void Assembler::parseDebugOperands(ostd::String line)
|
||||||
{
|
{
|
||||||
if (ostd::StringEditor(line).toLower().startsWith("debug_break"))
|
if (ostd::String(line).toLower().startsWith("debug_break"))
|
||||||
{
|
{
|
||||||
m_code.push_back(data::OpCodes::DEBUG_Break);
|
m_code.push_back(data::OpCodes::DEBUG_Break);
|
||||||
return;
|
return;
|
||||||
|
|
@ -468,15 +468,15 @@ namespace dragon
|
||||||
|
|
||||||
void Assembler::parse1Operand(ostd::String line)
|
void Assembler::parse1Operand(ostd::String line)
|
||||||
{
|
{
|
||||||
ostd::StringEditor lineEdit(line);
|
ostd::String lineEdit(line);
|
||||||
ostd::StringEditor instEdit(lineEdit.substr(0, lineEdit.indexOf(" ")));
|
ostd::String instEdit(lineEdit.new_substr(0, lineEdit.indexOf(" ")));
|
||||||
instEdit.trim().toLower();
|
instEdit.trim().toLower();
|
||||||
ostd::StringEditor opEdit(lineEdit.substr(lineEdit.indexOf(" ") + 1));
|
ostd::String opEdit(lineEdit.new_substr(lineEdit.indexOf(" ") + 1));
|
||||||
opEdit.trim();
|
opEdit.trim();
|
||||||
int16_t word = 0x0000;
|
int16_t word = 0x0000;
|
||||||
if (instEdit.str() == "inc")
|
if (instEdit == "inc")
|
||||||
{
|
{
|
||||||
eOperandType opType = parseOperand(opEdit.str(), word);
|
eOperandType opType = parseOperand(opEdit, word);
|
||||||
if (opType != eOperandType::Register)
|
if (opType != eOperandType::Register)
|
||||||
{
|
{
|
||||||
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n";
|
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n";
|
||||||
|
|
@ -487,9 +487,9 @@ namespace dragon
|
||||||
m_code.push_back((uint8_t)word);
|
m_code.push_back((uint8_t)word);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (instEdit.str() == "dec")
|
else if (instEdit == "dec")
|
||||||
{
|
{
|
||||||
eOperandType opType = parseOperand(opEdit.str(), word);
|
eOperandType opType = parseOperand(opEdit, word);
|
||||||
if (opType != eOperandType::Register)
|
if (opType != eOperandType::Register)
|
||||||
{
|
{
|
||||||
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n";
|
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n";
|
||||||
|
|
@ -500,9 +500,9 @@ namespace dragon
|
||||||
m_code.push_back((uint8_t)word);
|
m_code.push_back((uint8_t)word);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (instEdit.str() == "push")
|
else if (instEdit == "push")
|
||||||
{
|
{
|
||||||
eOperandType opType = parseOperand(opEdit.str(), word);
|
eOperandType opType = parseOperand(opEdit, word);
|
||||||
if (opType == eOperandType::Immediate || opType == eOperandType::Label)
|
if (opType == eOperandType::Immediate || opType == eOperandType::Label)
|
||||||
{
|
{
|
||||||
m_code.push_back(data::OpCodes::PushImm);
|
m_code.push_back(data::OpCodes::PushImm);
|
||||||
|
|
@ -521,9 +521,9 @@ namespace dragon
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (instEdit.str() == "pop")
|
else if (instEdit == "pop")
|
||||||
{
|
{
|
||||||
eOperandType opType = parseOperand(opEdit.str(), word);
|
eOperandType opType = parseOperand(opEdit, word);
|
||||||
if (opType != eOperandType::Register)
|
if (opType != eOperandType::Register)
|
||||||
{
|
{
|
||||||
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n";
|
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n";
|
||||||
|
|
@ -534,10 +534,10 @@ namespace dragon
|
||||||
m_code.push_back((uint8_t)word);
|
m_code.push_back((uint8_t)word);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (instEdit.str() == "call")
|
else if (instEdit == "call")
|
||||||
{
|
{
|
||||||
m_code.push_back(0x00);
|
m_code.push_back(0x00);
|
||||||
eOperandType opType = parseOperand(opEdit.str(), word);
|
eOperandType opType = parseOperand(opEdit, word);
|
||||||
if (opType == eOperandType::Immediate || opType == eOperandType::Label)
|
if (opType == eOperandType::Immediate || opType == eOperandType::Label)
|
||||||
{
|
{
|
||||||
m_code[m_code.size() - 1] = data::OpCodes::CallImm;
|
m_code[m_code.size() - 1] = data::OpCodes::CallImm;
|
||||||
|
|
@ -556,9 +556,9 @@ namespace dragon
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (instEdit.str() == "not")
|
else if (instEdit == "not")
|
||||||
{
|
{
|
||||||
eOperandType opType = parseOperand(opEdit.str(), word);
|
eOperandType opType = parseOperand(opEdit, word);
|
||||||
if (opType != eOperandType::Register)
|
if (opType != eOperandType::Register)
|
||||||
{
|
{
|
||||||
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n";
|
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n";
|
||||||
|
|
@ -569,10 +569,10 @@ namespace dragon
|
||||||
m_code.push_back((uint8_t)word);
|
m_code.push_back((uint8_t)word);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (instEdit.str() == "jmp")
|
else if (instEdit == "jmp")
|
||||||
{
|
{
|
||||||
m_code.push_back(data::OpCodes::Jmp);
|
m_code.push_back(data::OpCodes::Jmp);
|
||||||
eOperandType opType = parseOperand(opEdit.str(), word);
|
eOperandType opType = parseOperand(opEdit, word);
|
||||||
if (opType != eOperandType::Label && opType != eOperandType::Immediate)
|
if (opType != eOperandType::Label && opType != eOperandType::Immediate)
|
||||||
{
|
{
|
||||||
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Immediate (or label) required\n";
|
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Immediate (or label) required\n";
|
||||||
|
|
@ -583,9 +583,9 @@ namespace dragon
|
||||||
m_code.push_back((uint8_t)(word & 0x00FF));
|
m_code.push_back((uint8_t)(word & 0x00FF));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (instEdit.str() == "int")
|
else if (instEdit == "int")
|
||||||
{
|
{
|
||||||
eOperandType opType = parseOperand(opEdit.str(), word);
|
eOperandType opType = parseOperand(opEdit, word);
|
||||||
if (opType != eOperandType::Immediate)
|
if (opType != eOperandType::Immediate)
|
||||||
{
|
{
|
||||||
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Immediate required\n";
|
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Immediate required\n";
|
||||||
|
|
@ -605,14 +605,14 @@ namespace dragon
|
||||||
|
|
||||||
void Assembler::parse2Operand(ostd::String line)
|
void Assembler::parse2Operand(ostd::String line)
|
||||||
{
|
{
|
||||||
ostd::StringEditor lineEdit(line);
|
ostd::String lineEdit(line);
|
||||||
ostd::StringEditor instEdit(lineEdit.substr(0, lineEdit.indexOf(" ")));
|
ostd::String instEdit(lineEdit.new_substr(0, lineEdit.indexOf(" ")));
|
||||||
instEdit.trim().toLower();
|
instEdit.trim().toLower();
|
||||||
ostd::StringEditor opEdit(lineEdit.substr(lineEdit.indexOf(" ") + 1));
|
ostd::String opEdit(lineEdit.new_substr(lineEdit.indexOf(" ") + 1));
|
||||||
opEdit.trim();
|
opEdit.trim();
|
||||||
int16_t word = 0x0000;
|
int16_t word = 0x0000;
|
||||||
auto st = opEdit.tokenize(",");
|
auto st = opEdit.tokenize(",");
|
||||||
if (instEdit.str() == "mov")
|
if (instEdit == "mov")
|
||||||
{
|
{
|
||||||
m_code.push_back(0x00);
|
m_code.push_back(0x00);
|
||||||
int16_t word1 = 0x0000;
|
int16_t word1 = 0x0000;
|
||||||
|
|
@ -711,7 +711,7 @@ namespace dragon
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (instEdit.str() == "movb")
|
else if (instEdit == "movb")
|
||||||
{
|
{
|
||||||
m_code.push_back(0x00);
|
m_code.push_back(0x00);
|
||||||
int16_t word1 = 0x0000;
|
int16_t word1 = 0x0000;
|
||||||
|
|
@ -800,7 +800,7 @@ namespace dragon
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (instEdit.str() == "add" || instEdit.str() == "sub" || instEdit.str() == "mul")
|
else if (instEdit == "add" || instEdit == "sub" || instEdit == "mul")
|
||||||
{
|
{
|
||||||
m_code.push_back(0x00);
|
m_code.push_back(0x00);
|
||||||
eOperandType opType = parseOperand(st.next(), word);
|
eOperandType opType = parseOperand(st.next(), word);
|
||||||
|
|
@ -815,17 +815,17 @@ namespace dragon
|
||||||
|
|
||||||
if (opType == eOperandType::Immediate)
|
if (opType == eOperandType::Immediate)
|
||||||
{
|
{
|
||||||
if (instEdit.str() == "add") m_code[m_code.size() - 2] = data::OpCodes::AddImmReg;
|
if (instEdit == "add") m_code[m_code.size() - 2] = data::OpCodes::AddImmReg;
|
||||||
else if (instEdit.str() == "sub") m_code[m_code.size() - 2] = data::OpCodes::SubImmReg;
|
else if (instEdit == "sub") m_code[m_code.size() - 2] = data::OpCodes::SubImmReg;
|
||||||
else if (instEdit.str() == "mul") m_code[m_code.size() - 2] = data::OpCodes::MulImmReg;
|
else if (instEdit == "mul") m_code[m_code.size() - 2] = data::OpCodes::MulImmReg;
|
||||||
m_code.push_back((uint8_t)((word & 0xFF00) >> 8));
|
m_code.push_back((uint8_t)((word & 0xFF00) >> 8));
|
||||||
m_code.push_back((uint8_t)(word & 0x00FF));
|
m_code.push_back((uint8_t)(word & 0x00FF));
|
||||||
}
|
}
|
||||||
else if (opType == eOperandType::Register)
|
else if (opType == eOperandType::Register)
|
||||||
{
|
{
|
||||||
if (instEdit.str() == "add") m_code[m_code.size() - 2] = data::OpCodes::AddRegReg;
|
if (instEdit == "add") m_code[m_code.size() - 2] = data::OpCodes::AddRegReg;
|
||||||
else if (instEdit.str() == "sub") m_code[m_code.size() - 2] = data::OpCodes::SubRegReg;
|
else if (instEdit == "sub") m_code[m_code.size() - 2] = data::OpCodes::SubRegReg;
|
||||||
else if (instEdit.str() == "mul") m_code[m_code.size() - 2] = data::OpCodes::MulRegReg;
|
else if (instEdit == "mul") m_code[m_code.size() - 2] = data::OpCodes::MulRegReg;
|
||||||
m_code.push_back((uint8_t)word);
|
m_code.push_back((uint8_t)word);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -836,7 +836,7 @@ namespace dragon
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (instEdit.str() == "lsh" || instEdit.str() == "rsh" || instEdit.str() == "and" || instEdit.str() == "or" || instEdit.str() == "xor")
|
else if (instEdit == "lsh" || instEdit == "rsh" || instEdit == "and" || instEdit == "or" || instEdit == "xor")
|
||||||
{
|
{
|
||||||
eOperandType opType = parseOperand(st.next(), word);
|
eOperandType opType = parseOperand(st.next(), word);
|
||||||
if (opType != eOperandType::Register)
|
if (opType != eOperandType::Register)
|
||||||
|
|
@ -849,22 +849,22 @@ namespace dragon
|
||||||
opType = parseOperand(st.next(), word);
|
opType = parseOperand(st.next(), word);
|
||||||
if (opType == eOperandType::Immediate)
|
if (opType == eOperandType::Immediate)
|
||||||
{
|
{
|
||||||
if (instEdit.str() == "lsh") m_code.push_back(data::OpCodes::LShiftRegImm);
|
if (instEdit == "lsh") m_code.push_back(data::OpCodes::LShiftRegImm);
|
||||||
else if (instEdit.str() == "rsh") m_code.push_back(data::OpCodes::RShiftRegImm);
|
else if (instEdit == "rsh") m_code.push_back(data::OpCodes::RShiftRegImm);
|
||||||
else if (instEdit.str() == "and") m_code.push_back(data::OpCodes::AndRegImm);
|
else if (instEdit == "and") m_code.push_back(data::OpCodes::AndRegImm);
|
||||||
else if (instEdit.str() == "or") m_code.push_back(data::OpCodes::OrRegImm);
|
else if (instEdit == "or") m_code.push_back(data::OpCodes::OrRegImm);
|
||||||
else if (instEdit.str() == "xor") m_code.push_back(data::OpCodes::XorRegImm);
|
else if (instEdit == "xor") m_code.push_back(data::OpCodes::XorRegImm);
|
||||||
m_code.push_back((uint8_t)((word & 0xFF00) >> 8));
|
m_code.push_back((uint8_t)((word & 0xFF00) >> 8));
|
||||||
m_code.push_back((uint8_t)(word & 0x00FF));
|
m_code.push_back((uint8_t)(word & 0x00FF));
|
||||||
m_code.push_back((uint8_t)regAddr);
|
m_code.push_back((uint8_t)regAddr);
|
||||||
}
|
}
|
||||||
else if (opType == eOperandType::Register)
|
else if (opType == eOperandType::Register)
|
||||||
{
|
{
|
||||||
if (instEdit.str() == "lsh") m_code.push_back(data::OpCodes::LShiftRegReg);
|
if (instEdit == "lsh") m_code.push_back(data::OpCodes::LShiftRegReg);
|
||||||
else if (instEdit.str() == "rsh") m_code.push_back(data::OpCodes::RShiftRegReg);
|
else if (instEdit == "rsh") m_code.push_back(data::OpCodes::RShiftRegReg);
|
||||||
else if (instEdit.str() == "and") m_code.push_back(data::OpCodes::AndRegReg);
|
else if (instEdit == "and") m_code.push_back(data::OpCodes::AndRegReg);
|
||||||
else if (instEdit.str() == "or") m_code.push_back(data::OpCodes::OrRegReg);
|
else if (instEdit == "or") m_code.push_back(data::OpCodes::OrRegReg);
|
||||||
else if (instEdit.str() == "xor") m_code.push_back(data::OpCodes::XorRegReg);
|
else if (instEdit == "xor") m_code.push_back(data::OpCodes::XorRegReg);
|
||||||
m_code.push_back((uint8_t)word);
|
m_code.push_back((uint8_t)word);
|
||||||
m_code.push_back((uint8_t)regAddr);
|
m_code.push_back((uint8_t)regAddr);
|
||||||
}
|
}
|
||||||
|
|
@ -876,7 +876,7 @@ namespace dragon
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (instEdit.str() == "jne" || instEdit.str() == "jeq" || instEdit.str() == "jgr" || instEdit.str() == "jls" || instEdit.str() == "jge" || instEdit.str() == "jle")
|
else if (instEdit == "jne" || instEdit == "jeq" || instEdit == "jgr" || instEdit == "jls" || instEdit == "jge" || instEdit == "jle")
|
||||||
{
|
{
|
||||||
m_code.push_back(0x00);
|
m_code.push_back(0x00);
|
||||||
eOperandType opType = parseOperand(st.next(), word);
|
eOperandType opType = parseOperand(st.next(), word);
|
||||||
|
|
@ -893,23 +893,23 @@ namespace dragon
|
||||||
|
|
||||||
if (opType == eOperandType::Immediate)
|
if (opType == eOperandType::Immediate)
|
||||||
{
|
{
|
||||||
if (instEdit.str() == "jeq") m_code[m_code.size() - 3] = data::OpCodes::JmpEqImm;
|
if (instEdit == "jeq") m_code[m_code.size() - 3] = data::OpCodes::JmpEqImm;
|
||||||
else if (instEdit.str() == "jne") m_code[m_code.size() - 3] = data::OpCodes::JmpNotEqImm;
|
else if (instEdit == "jne") m_code[m_code.size() - 3] = data::OpCodes::JmpNotEqImm;
|
||||||
else if (instEdit.str() == "jgr") m_code[m_code.size() - 3] = data::OpCodes::JmpGrImm;
|
else if (instEdit == "jgr") m_code[m_code.size() - 3] = data::OpCodes::JmpGrImm;
|
||||||
else if (instEdit.str() == "jls") m_code[m_code.size() - 3] = data::OpCodes::JmpLessImm;
|
else if (instEdit == "jls") m_code[m_code.size() - 3] = data::OpCodes::JmpLessImm;
|
||||||
else if (instEdit.str() == "jge") m_code[m_code.size() - 3] = data::OpCodes::JmpGeImm;
|
else if (instEdit == "jge") m_code[m_code.size() - 3] = data::OpCodes::JmpGeImm;
|
||||||
else if (instEdit.str() == "jle") m_code[m_code.size() - 3] = data::OpCodes::JmpLeImm;
|
else if (instEdit == "jle") m_code[m_code.size() - 3] = data::OpCodes::JmpLeImm;
|
||||||
m_code.push_back((uint8_t)((word & 0xFF00) >> 8));
|
m_code.push_back((uint8_t)((word & 0xFF00) >> 8));
|
||||||
m_code.push_back((uint8_t)(word & 0x00FF));
|
m_code.push_back((uint8_t)(word & 0x00FF));
|
||||||
}
|
}
|
||||||
else if (opType == eOperandType::Register)
|
else if (opType == eOperandType::Register)
|
||||||
{
|
{
|
||||||
if (instEdit.str() == "jeq") m_code[m_code.size() - 3] = data::OpCodes::JmpEqReg;
|
if (instEdit == "jeq") m_code[m_code.size() - 3] = data::OpCodes::JmpEqReg;
|
||||||
else if (instEdit.str() == "jne") m_code[m_code.size() - 3] = data::OpCodes::JmpNotEqReg;
|
else if (instEdit == "jne") m_code[m_code.size() - 3] = data::OpCodes::JmpNotEqReg;
|
||||||
else if (instEdit.str() == "jgr") m_code[m_code.size() - 3] = data::OpCodes::JmpGrReg;
|
else if (instEdit == "jgr") m_code[m_code.size() - 3] = data::OpCodes::JmpGrReg;
|
||||||
else if (instEdit.str() == "jls") m_code[m_code.size() - 3] = data::OpCodes::JmpLessReg;
|
else if (instEdit == "jls") m_code[m_code.size() - 3] = data::OpCodes::JmpLessReg;
|
||||||
else if (instEdit.str() == "jge") m_code[m_code.size() - 3] = data::OpCodes::JmpGeReg;
|
else if (instEdit == "jge") m_code[m_code.size() - 3] = data::OpCodes::JmpGeReg;
|
||||||
else if (instEdit.str() == "jle") m_code[m_code.size() - 3] = data::OpCodes::JmpLeReg;
|
else if (instEdit == "jle") m_code[m_code.size() - 3] = data::OpCodes::JmpLeReg;
|
||||||
m_code.push_back((uint8_t)word);
|
m_code.push_back((uint8_t)word);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -929,13 +929,13 @@ namespace dragon
|
||||||
|
|
||||||
void Assembler::parse3Operand(ostd::String line)
|
void Assembler::parse3Operand(ostd::String line)
|
||||||
{
|
{
|
||||||
ostd::StringEditor lineEdit(line);
|
ostd::String lineEdit(line);
|
||||||
ostd::StringEditor instEdit(lineEdit.substr(0, lineEdit.indexOf(" ")));
|
ostd::String instEdit(lineEdit.new_substr(0, lineEdit.indexOf(" ")));
|
||||||
instEdit.trim().toLower();
|
instEdit.trim().toLower();
|
||||||
ostd::StringEditor opEdit(lineEdit.substr(lineEdit.indexOf(" ") + 1));
|
ostd::String opEdit(lineEdit.new_substr(lineEdit.indexOf(" ") + 1));
|
||||||
opEdit.trim();
|
opEdit.trim();
|
||||||
int16_t word = 0x0000;
|
int16_t word = 0x0000;
|
||||||
if (instEdit.str() == "mov")
|
if (instEdit == "mov")
|
||||||
{
|
{
|
||||||
auto st = opEdit.tokenize(",");
|
auto st = opEdit.tokenize(",");
|
||||||
eOperandType opType = parseOperand(st.next(), word);
|
eOperandType opType = parseOperand(st.next(), word);
|
||||||
|
|
@ -983,7 +983,7 @@ namespace dragon
|
||||||
newCode.push_back((uint8_t)(entryAddr & 0x00FF));
|
newCode.push_back((uint8_t)(entryAddr & 0x00FF));
|
||||||
if (m_dataSize > 0)
|
if (m_dataSize > 0)
|
||||||
m_disassembly.insert(m_disassembly.begin(), { (uint16_t)(m_loadAddress + 3), "[----------DATA_SECTION----------]" });
|
m_disassembly.insert(m_disassembly.begin(), { (uint16_t)(m_loadAddress + 3), "[----------DATA_SECTION----------]" });
|
||||||
m_disassembly.insert(m_disassembly.begin(), { m_loadAddress, ostd::StringEditor("jmp ").add(ostd::Utils::getHexStr(entryAddr, true, 2)).str() });
|
m_disassembly.insert(m_disassembly.begin(), { m_loadAddress, ostd::String("jmp ").add(ostd::Utils::getHexStr(entryAddr, true, 2)) });
|
||||||
for (auto& d : m_symbolTable)
|
for (auto& d : m_symbolTable)
|
||||||
symbols.push_back(d.second);
|
symbols.push_back(d.second);
|
||||||
for (int32_t i = symbols.size() - 1; i >= 0; i--)
|
for (int32_t i = symbols.size() - 1; i >= 0; i--)
|
||||||
|
|
@ -1009,10 +1009,10 @@ namespace dragon
|
||||||
|
|
||||||
ostd::String Assembler::replaceSymbols(ostd::String line)
|
ostd::String Assembler::replaceSymbols(ostd::String line)
|
||||||
{
|
{
|
||||||
ostd::StringEditor lineEdit(line);
|
ostd::String lineEdit(line);
|
||||||
for (auto& symbol : m_symbolTable)
|
for (auto& symbol : m_symbolTable)
|
||||||
lineEdit.replaceAll(symbol.first, ostd::Utils::getHexStr(symbol.second.address, true, 2));
|
lineEdit.replaceAll(symbol.first, ostd::Utils::getHexStr(symbol.second.address, true, 2));
|
||||||
return lineEdit.str();
|
return lineEdit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assembler::replaceLabelRefs(void)
|
void Assembler::replaceLabelRefs(void)
|
||||||
|
|
@ -1029,7 +1029,7 @@ namespace dragon
|
||||||
|
|
||||||
Assembler::eOperandType Assembler::parseOperand(ostd::String op, int16_t& outOp)
|
Assembler::eOperandType Assembler::parseOperand(ostd::String op, int16_t& outOp)
|
||||||
{
|
{
|
||||||
ostd::StringEditor opEdit(op);
|
ostd::String opEdit(op);
|
||||||
bool derefReg = false;
|
bool derefReg = false;
|
||||||
if (opEdit.startsWith("*"))
|
if (opEdit.startsWith("*"))
|
||||||
{
|
{
|
||||||
|
|
@ -1037,7 +1037,7 @@ namespace dragon
|
||||||
opEdit.trim();
|
opEdit.trim();
|
||||||
derefReg = true;
|
derefReg = true;
|
||||||
}
|
}
|
||||||
int8_t reg = parseRegister(opEdit.str());
|
int8_t reg = parseRegister(opEdit);
|
||||||
if (reg != data::Registers::Last)
|
if (reg != data::Registers::Last)
|
||||||
{
|
{
|
||||||
outOp = (int16_t)reg;
|
outOp = (int16_t)reg;
|
||||||
|
|
@ -1057,14 +1057,14 @@ namespace dragon
|
||||||
}
|
}
|
||||||
if (opEdit.startsWith("$"))
|
if (opEdit.startsWith("$"))
|
||||||
{
|
{
|
||||||
if (m_labelTable.count(opEdit.str()) == 0)
|
if (m_labelTable.count(opEdit) == 0)
|
||||||
{
|
{
|
||||||
std::cout << "Unknown symbol: " << opEdit << "\n";
|
std::cout << "Unknown symbol: " << opEdit << "\n";
|
||||||
return eOperandType::Error;
|
return eOperandType::Error;
|
||||||
}
|
}
|
||||||
uint16_t labelAddr = m_labelTable[opEdit.str()].address;
|
uint16_t labelAddr = m_labelTable[opEdit].address;
|
||||||
if (labelAddr == 0x0000)
|
if (labelAddr == 0x0000)
|
||||||
m_labelTable[opEdit.str()].references.push_back(m_code.size());
|
m_labelTable[opEdit].references.push_back(m_code.size());
|
||||||
outOp = (int16_t)labelAddr;
|
outOp = (int16_t)labelAddr;
|
||||||
return eOperandType::Label;
|
return eOperandType::Label;
|
||||||
}
|
}
|
||||||
|
|
@ -1072,7 +1072,7 @@ namespace dragon
|
||||||
{
|
{
|
||||||
opEdit = opEdit.substr(1, opEdit.len() - 1);
|
opEdit = opEdit.substr(1, opEdit.len() - 1);
|
||||||
opEdit.trim();
|
opEdit.trim();
|
||||||
outOp = (int16_t)ostd::Utils::solveIntegerExpression(opEdit.str());
|
outOp = (int16_t)ostd::Utils::solveIntegerExpression(opEdit);
|
||||||
return eOperandType::Immediate;
|
return eOperandType::Immediate;
|
||||||
}
|
}
|
||||||
if (opEdit.startsWith("[") && opEdit.endsWith("]"))
|
if (opEdit.startsWith("[") && opEdit.endsWith("]"))
|
||||||
|
|
@ -1083,7 +1083,7 @@ namespace dragon
|
||||||
{
|
{
|
||||||
opEdit = opEdit.substr(1, opEdit.len() - 1);
|
opEdit = opEdit.substr(1, opEdit.len() - 1);
|
||||||
opEdit.trim();
|
opEdit.trim();
|
||||||
outOp = (int16_t)ostd::Utils::solveIntegerExpression(opEdit.str());
|
outOp = (int16_t)ostd::Utils::solveIntegerExpression(opEdit);
|
||||||
return eOperandType::DerefMemory;
|
return eOperandType::DerefMemory;
|
||||||
}
|
}
|
||||||
if (!opEdit.isNumeric())
|
if (!opEdit.isNumeric())
|
||||||
|
|
@ -1099,25 +1099,25 @@ namespace dragon
|
||||||
|
|
||||||
uint8_t Assembler::parseRegister(ostd::String op)
|
uint8_t Assembler::parseRegister(ostd::String op)
|
||||||
{
|
{
|
||||||
ostd::StringEditor opEdit(op);
|
ostd::String opEdit(op);
|
||||||
opEdit.trim().toLower();
|
opEdit.trim().toLower();
|
||||||
if (opEdit.str() == "r1") return data::Registers::R1;
|
if (opEdit == "r1") return data::Registers::R1;
|
||||||
if (opEdit.str() == "r2") return data::Registers::R2;
|
if (opEdit == "r2") return data::Registers::R2;
|
||||||
if (opEdit.str() == "r3") return data::Registers::R3;
|
if (opEdit == "r3") return data::Registers::R3;
|
||||||
if (opEdit.str() == "r4") return data::Registers::R4;
|
if (opEdit == "r4") return data::Registers::R4;
|
||||||
if (opEdit.str() == "r5") return data::Registers::R5;
|
if (opEdit == "r5") return data::Registers::R5;
|
||||||
if (opEdit.str() == "r6") return data::Registers::R6;
|
if (opEdit == "r6") return data::Registers::R6;
|
||||||
if (opEdit.str() == "r7") return data::Registers::R7;
|
if (opEdit == "r7") return data::Registers::R7;
|
||||||
if (opEdit.str() == "r8") return data::Registers::R8;
|
if (opEdit == "r8") return data::Registers::R8;
|
||||||
if (opEdit.str() == "r9") return data::Registers::R9;
|
if (opEdit == "r9") return data::Registers::R9;
|
||||||
if (opEdit.str() == "r10") return data::Registers::R10;
|
if (opEdit == "r10") return data::Registers::R10;
|
||||||
if (opEdit.str() == "acc") return data::Registers::ACC;
|
if (opEdit == "acc") return data::Registers::ACC;
|
||||||
if (opEdit.str() == "fp") return data::Registers::FP;
|
if (opEdit == "fp") return data::Registers::FP;
|
||||||
if (opEdit.str() == "sp") return data::Registers::SP;
|
if (opEdit == "sp") return data::Registers::SP;
|
||||||
if (opEdit.str() == "ip") return data::Registers::IP;
|
if (opEdit == "ip") return data::Registers::IP;
|
||||||
if (opEdit.str() == "pp") return data::Registers::PP;
|
if (opEdit == "pp") return data::Registers::PP;
|
||||||
if (opEdit.str() == "rv") return data::Registers::RV;
|
if (opEdit == "rv") return data::Registers::RV;
|
||||||
if (opEdit.str() == "fl") return data::Registers::FL;
|
if (opEdit == "fl") return data::Registers::FL;
|
||||||
return data::Registers::Last;
|
return data::Registers::Last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ namespace dragon
|
||||||
public: struct tDisassemblyLine {
|
public: struct tDisassemblyLine {
|
||||||
uint32_t addr = 0;
|
uint32_t addr = 0;
|
||||||
ostd::String code = "";
|
ostd::String code = "";
|
||||||
|
inline bool operator<(const tDisassemblyLine& second) const { return addr < second.addr; }
|
||||||
|
inline bool operator>(const tDisassemblyLine& second) const { return addr > second.addr; }
|
||||||
};
|
};
|
||||||
public: struct tSymbol
|
public: struct tSymbol
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#include <ostd/Utils.hpp>
|
#include <ostd/Utils.hpp>
|
||||||
#include <ostd/IOHandlers.hpp>
|
#include <ostd/IOHandlers.hpp>
|
||||||
|
|
||||||
ostd::legacy::ConsoleOutputHandler out;
|
ostd::ConsoleOutputHandler out;
|
||||||
|
|
||||||
|
|
||||||
struct tCommandLineArgs
|
struct tCommandLineArgs
|
||||||
|
|
@ -19,8 +19,8 @@ int main(int argc, char** argv)
|
||||||
tCommandLineArgs args;
|
tCommandLineArgs args;
|
||||||
if (argc < 4)
|
if (argc < 4)
|
||||||
{
|
{
|
||||||
out.col("red").p("Error: too few arguments.").nl();
|
out.fg("red").p("Error: too few arguments.").nl();
|
||||||
out.col("red").p(" Usage: ./dasm <source> -o <destination> [...options...]").resetColors().nl();
|
out.fg("red").p(" Usage: ./dasm <source> -o <destination> [...options...]").reset().nl();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -28,15 +28,15 @@ int main(int argc, char** argv)
|
||||||
args.source_file_path = argv[1];
|
args.source_file_path = argv[1];
|
||||||
for (int32_t i = 2; i < argc; i++)
|
for (int32_t i = 2; i < argc; i++)
|
||||||
{
|
{
|
||||||
ostd::StringEditor edit(argv[i]);
|
ostd::String edit(argv[i]);
|
||||||
if (edit.str() == "-o")
|
if (edit == "-o")
|
||||||
{
|
{
|
||||||
if (i == argc - 1)
|
if (i == argc - 1)
|
||||||
break; //TODO: Warning
|
break; //TODO: Warning
|
||||||
i++;
|
i++;
|
||||||
args.dest_file_path = argv[i];
|
args.dest_file_path = argv[i];
|
||||||
}
|
}
|
||||||
else if (edit.str() == "--save-disassembly")
|
else if (edit == "--save-disassembly")
|
||||||
{
|
{
|
||||||
if (i == argc - 1)
|
if (i == argc - 1)
|
||||||
break; //TODO: Warning
|
break; //TODO: Warning
|
||||||
|
|
@ -44,7 +44,7 @@ int main(int argc, char** argv)
|
||||||
args.disassembly_file_path = argv[i];
|
args.disassembly_file_path = argv[i];
|
||||||
args.save_disassembly = true;
|
args.save_disassembly = true;
|
||||||
}
|
}
|
||||||
else if (edit.str() == "--verbose")
|
else if (edit == "--verbose")
|
||||||
args.verbose = true;
|
args.verbose = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -17,9 +17,10 @@ namespace dragon
|
||||||
bool verbose_load = false;
|
bool verbose_load = false;
|
||||||
bool force_load = false;
|
bool force_load = false;
|
||||||
bool step_exec = false;
|
bool step_exec = false;
|
||||||
bool track_step_diff = false;
|
bool track_step_diff = true;
|
||||||
bool auto_start_debug = false;
|
bool auto_start_debug = false;
|
||||||
bool hide_virtual_display = false;
|
bool hide_virtual_display = false;
|
||||||
|
bool track_call_stack = true;
|
||||||
ostd::String force_load_file = "";
|
ostd::String force_load_file = "";
|
||||||
uint16_t force_load_mem_offset = 0x00;
|
uint16_t force_load_mem_offset = 0x00;
|
||||||
};
|
};
|
||||||
|
|
@ -31,20 +32,20 @@ namespace dragon
|
||||||
DisassemblyList labels;
|
DisassemblyList labels;
|
||||||
DisassemblyList data;
|
DisassemblyList data;
|
||||||
std::vector<uint16_t> trackedAddresses;
|
std::vector<uint16_t> trackedAddresses;
|
||||||
ostd::StringEditor command;
|
ostd::String command;
|
||||||
int32_t labelLineLength { 20 };
|
int32_t labelLineLength { 20 };
|
||||||
uint16_t currentAddress { 0 };
|
uint16_t currentAddress { 0 };
|
||||||
bool userQuit { false };
|
bool userQuit { false };
|
||||||
ostd::StringEditor disassemblyDirectory { "disassembly" };
|
ostd::String disassemblyDirectory { "disassembly" };
|
||||||
};
|
};
|
||||||
public: class Utils
|
public: class Utils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static DisassemblyList findCodeRegion(const DisassemblyList& code, uint16_t address, uint16_t codeRegionMargin);
|
static DisassemblyList findCodeRegion(const DisassemblyList& code, uint16_t address, uint16_t codeRegionMargin);
|
||||||
static ostd::String findSymbol(const DisassemblyList& labels, uint16_t address);
|
static ostd::String findSymbol(const DisassemblyList& labels, uint16_t address);
|
||||||
static uint16_t findSymbol(const DisassemblyList& labels, const ostd::StringEditor& symbol);
|
static uint16_t findSymbol(const DisassemblyList& labels, const ostd::String& symbol);
|
||||||
static bool isValidLabelNameChar(char c);
|
static bool isValidLabelNameChar(char c);
|
||||||
static ostd::StringEditor fillString(const ostd::StringEditor& str, char fill, int32_t totalLength); //TODO: Implement in omnia-framework
|
static void clearConsoleLine(void);
|
||||||
};
|
};
|
||||||
public: class Display
|
public: class Display
|
||||||
{
|
{
|
||||||
|
|
@ -54,19 +55,22 @@ namespace dragon
|
||||||
static void printPrompt(void);
|
static void printPrompt(void);
|
||||||
static void printStep(void);
|
static void printStep(void);
|
||||||
static void printDiff(void);
|
static void printDiff(void);
|
||||||
static void printTrackedAddresses(const std::vector<uint16_t>& trackedAddresses);
|
static void printTrackedAddresses(void);
|
||||||
static ostd::StringEditor changeScreen(void);
|
static void printStack(void);
|
||||||
|
static void printCallStack(void);
|
||||||
|
static ostd::String changeScreen(void);
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
static void processErrors(void);
|
static void processErrors(void);
|
||||||
static int32_t loadArguments(int argc, char** argv);
|
static int32_t loadArguments(int argc, char** argv);
|
||||||
static int32_t initRuntime(void);
|
static int32_t initRuntime(void);
|
||||||
static ostd::StringEditor getCommandInput(void);
|
static ostd::String getCommandInput(void);
|
||||||
static inline tDebuggerData& data(void) { return debugger; }
|
static inline tDebuggerData& data(void) { return debugger; }
|
||||||
static inline ostd::legacy::ConsoleOutputHandler& output(void) { return out; }
|
static inline ostd::ConsoleOutputHandler& output(void) { return out; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline static tDebuggerData debugger;
|
inline static tDebuggerData debugger;
|
||||||
inline static ostd::legacy::ConsoleOutputHandler out;
|
inline static ostd::ConsoleOutputHandler out;
|
||||||
|
inline static std::vector<ostd::String> commandHistory;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
#include "../tools/Utils.hpp"
|
#include "../tools/Utils.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace dragon
|
namespace dragon
|
||||||
{
|
{
|
||||||
const DisassemblyTable DisassemblyTable::DefaultObject;
|
const DisassemblyTable DisassemblyTable::DefaultObject;
|
||||||
|
|
@ -31,24 +33,14 @@ namespace dragon
|
||||||
ostd::String header_string = "";
|
ostd::String header_string = "";
|
||||||
serializer.r_NullTerminatedString(0, header_string);
|
serializer.r_NullTerminatedString(0, header_string);
|
||||||
if (header_string != "{ DRAGON_DEBUG_DISASSEMBLY }") return;
|
if (header_string != "{ DRAGON_DEBUG_DISASSEMBLY }") return;
|
||||||
addr += (header_string.length() + 1) * ostd::tTypeSize::BYTE;
|
addr += (header_string.len() + 1) * ostd::tTypeSize::BYTE;
|
||||||
while (addr < serializer.size())
|
while (addr < serializer.size())
|
||||||
{
|
{
|
||||||
serializer.r_DWord(addr, line_addr);
|
serializer.r_DWord(addr, line_addr);
|
||||||
addr += ostd::tTypeSize::DWORD;
|
addr += ostd::tTypeSize::DWORD;
|
||||||
// ostd::ByteStream str_stream;
|
|
||||||
// serializer.r_Byte(addr, line_code_char);
|
|
||||||
// addr += ostd::tTypeSize::BYTE;
|
|
||||||
// do
|
|
||||||
// {
|
|
||||||
// str_stream.push_back(line_code_char);
|
|
||||||
// serializer.r_Byte(addr, line_code_char);
|
|
||||||
// addr += ostd::tTypeSize::BYTE;
|
|
||||||
// } while(line_code_char != 0);
|
|
||||||
// ostd::String code_line = ostd::Utils::byteStreamToString(str_stream);
|
|
||||||
ostd::String code_line = "";
|
ostd::String code_line = "";
|
||||||
serializer.r_NullTerminatedString(addr, code_line);
|
serializer.r_NullTerminatedString(addr, code_line);
|
||||||
addr += (code_line.length() + 1) * ostd::tTypeSize::BYTE;
|
addr += (code_line.len() + 1) * ostd::tTypeSize::BYTE;
|
||||||
if (code_line == "{ DATA }")
|
if (code_line == "{ DATA }")
|
||||||
{
|
{
|
||||||
mode = MODE_DATA;
|
mode = MODE_DATA;
|
||||||
|
|
@ -69,19 +61,19 @@ namespace dragon
|
||||||
line.code = code_line;
|
line.code = code_line;
|
||||||
if (mode == MODE_CODE)
|
if (mode == MODE_CODE)
|
||||||
{
|
{
|
||||||
ostd::StringEditor codeEdit(line.code);
|
ostd::String codeEdit(line.code);
|
||||||
codeEdit.trim();
|
codeEdit.trim();
|
||||||
if (codeEdit.contains(" "))
|
if (codeEdit.contains(" "))
|
||||||
{
|
{
|
||||||
ostd::StringEditor part1 = codeEdit.substr(0, codeEdit.indexOf(" "));
|
ostd::String part1 = codeEdit.new_substr(0, codeEdit.indexOf(" "));
|
||||||
ostd::StringEditor part2 = codeEdit.substr(codeEdit.indexOf(" ") + 1);
|
ostd::String part2 = codeEdit.new_substr(codeEdit.indexOf(" ") + 1);
|
||||||
part1.trim();
|
part1.trim();
|
||||||
part2.trim();
|
part2.trim();
|
||||||
int32_t opCodeLen = 10;
|
int32_t opCodeLen = 10;
|
||||||
if (part1.len() < opCodeLen)
|
if (part1.len() < opCodeLen)
|
||||||
{
|
{
|
||||||
codeEdit = part1.str() + ostd::Utils::duplicateChar(' ', opCodeLen - part1.len()) + part2.str();
|
codeEdit = part1 + ostd::Utils::duplicateChar(' ', opCodeLen - part1.len()) + part2;
|
||||||
line.code = codeEdit.str();
|
line.code = codeEdit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_code.push_back(line);
|
m_code.push_back(line);
|
||||||
|
|
@ -116,6 +108,7 @@ namespace dragon
|
||||||
std::vector<code::Assembler::tDisassemblyLine> fullTable;
|
std::vector<code::Assembler::tDisassemblyLine> fullTable;
|
||||||
for (auto& table : m_tables)
|
for (auto& table : m_tables)
|
||||||
fullTable.insert(fullTable.end(), table.getCodeTable().begin(), table.getCodeTable().end());
|
fullTable.insert(fullTable.end(), table.getCodeTable().begin(), table.getCodeTable().end());
|
||||||
|
std::sort(fullTable.begin(), fullTable.end());
|
||||||
return fullTable;
|
return fullTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,6 +117,7 @@ namespace dragon
|
||||||
std::vector<code::Assembler::tDisassemblyLine> fullTable;
|
std::vector<code::Assembler::tDisassemblyLine> fullTable;
|
||||||
for (auto& table : m_tables)
|
for (auto& table : m_tables)
|
||||||
fullTable.insert(fullTable.end(), table.getDataTable().begin(), table.getDataTable().end());
|
fullTable.insert(fullTable.end(), table.getDataTable().begin(), table.getDataTable().end());
|
||||||
|
std::sort(fullTable.begin(), fullTable.end());
|
||||||
return fullTable;
|
return fullTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,6 +126,7 @@ namespace dragon
|
||||||
std::vector<code::Assembler::tDisassemblyLine> fullTable;
|
std::vector<code::Assembler::tDisassemblyLine> fullTable;
|
||||||
for (auto& table : m_tables)
|
for (auto& table : m_tables)
|
||||||
fullTable.insert(fullTable.end(), table.getLabelTable().begin(), table.getLabelTable().end());
|
fullTable.insert(fullTable.end(), table.getLabelTable().begin(), table.getLabelTable().end());
|
||||||
|
std::sort(fullTable.begin(), fullTable.end());
|
||||||
return fullTable;
|
return fullTable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,50 @@
|
||||||
#include "Debugger.hpp"
|
#include "Debugger.hpp"
|
||||||
#include "../runtime/DragonRuntime.hpp"
|
#include "../runtime/DragonRuntime.hpp"
|
||||||
|
|
||||||
|
void exec_watch_command(void)
|
||||||
|
{
|
||||||
|
using namespace dragon;
|
||||||
|
|
||||||
|
auto tokens = Debugger::data().command.tokenize();
|
||||||
|
for (auto& addr : tokens)
|
||||||
|
{
|
||||||
|
Debugger::data().command = addr;
|
||||||
|
if (Debugger::data().command.isNumeric())
|
||||||
|
Debugger::data().trackedAddresses.push_back((uint16_t)Debugger::data().command.toInt());
|
||||||
|
else if (Debugger::data().command.startsWith("$"))
|
||||||
|
{
|
||||||
|
uint8_t nbytes = 1;
|
||||||
|
if (Debugger::data().command.contains("[") && Debugger::data().command.endsWith("]"))
|
||||||
|
{
|
||||||
|
ostd::String str_nbytes = Debugger::data().command.new_substr(Debugger::data().command.indexOf("[") + 1).trim();
|
||||||
|
str_nbytes.substr(0, str_nbytes.len() - 1);
|
||||||
|
std::cout << str_nbytes << "\n";
|
||||||
|
std::cout << Debugger::data().command << "\n";
|
||||||
|
Debugger::data().command.substr(0, Debugger::data().command.indexOf("[")).trim();
|
||||||
|
std::cout << Debugger::data().command << "\n";
|
||||||
|
if (str_nbytes.isNumeric())
|
||||||
|
nbytes = str_nbytes.toInt();
|
||||||
|
if (nbytes < 1) nbytes = 1;
|
||||||
|
}
|
||||||
|
uint16_t addr = Debugger::Utils::findSymbol(Debugger::data().data, Debugger::data().command);
|
||||||
|
if (addr > 0)
|
||||||
|
{
|
||||||
|
for (int32_t i = 0; i < nbytes; i++)
|
||||||
|
Debugger::data().trackedAddresses.push_back(addr + i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr = Debugger::Utils::findSymbol(Debugger::data().labels, Debugger::data().command);
|
||||||
|
if (addr > 0)
|
||||||
|
{
|
||||||
|
for (int32_t i = 0; i < nbytes; i++)
|
||||||
|
Debugger::data().trackedAddresses.push_back(addr + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << (int)Debugger::data().trackedAddresses.size() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
|
@ -10,6 +54,8 @@ int main(int argc, char** argv)
|
||||||
rValue = Debugger::initRuntime();
|
rValue = Debugger::initRuntime();
|
||||||
if (rValue != 0) return rValue;
|
if (rValue != 0) return rValue;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!Debugger::data().args.auto_start_debug)
|
if (!Debugger::data().args.auto_start_debug)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
|
|
@ -17,33 +63,18 @@ int main(int argc, char** argv)
|
||||||
Debugger::Display::printPrompt();
|
Debugger::Display::printPrompt();
|
||||||
Debugger::data().command = Debugger::getCommandInput();
|
Debugger::data().command = Debugger::getCommandInput();
|
||||||
Debugger::data().command.trim().toLower();
|
Debugger::data().command.trim().toLower();
|
||||||
if (Debugger::data().command.str() == "r" || Debugger::data().command.str() == "run")
|
if (Debugger::data().command == "r" || Debugger::data().command == "run")
|
||||||
break;
|
break;
|
||||||
else if (Debugger::data().command.str() == "q" || Debugger::data().command.str() == "quit")
|
else if (Debugger::data().command == "q" || Debugger::data().command == "quit")
|
||||||
return rValue;
|
return rValue;
|
||||||
else if (Debugger::data().command.startsWith("watch "))
|
else if (Debugger::data().command.startsWith("watch "))
|
||||||
{
|
{
|
||||||
Debugger::data().command = Debugger::data().command.substr(6);
|
Debugger::data().command.substr(6).trim();
|
||||||
Debugger::data().command.trim();
|
exec_watch_command();
|
||||||
auto tokens = Debugger::data().command.tokenize();
|
}
|
||||||
for (auto& addr : tokens)
|
else if (Debugger::data().command == "step")
|
||||||
{
|
{
|
||||||
Debugger::data().command = addr;
|
Debugger::data().args.step_exec = true;
|
||||||
if (Debugger::data().command.isNumeric())
|
|
||||||
Debugger::data().trackedAddresses.push_back((uint16_t)Debugger::data().command.toInt());
|
|
||||||
else if (Debugger::data().command.startsWith("$"))
|
|
||||||
{
|
|
||||||
uint16_t addr = Debugger::Utils::findSymbol(Debugger::data().data, Debugger::data().command);
|
|
||||||
if (addr > 0)
|
|
||||||
Debugger::data().trackedAddresses.push_back(addr);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
addr = Debugger::Utils::findSymbol(Debugger::data().labels, Debugger::data().command);
|
|
||||||
if (addr > 0)
|
|
||||||
Debugger::data().trackedAddresses.push_back(addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +97,7 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
if (!result || userQuit)
|
if (!result || userQuit)
|
||||||
{
|
{
|
||||||
Debugger::output().nl().col(ostd::legacy::ConsoleCol::Yellow).p("Execution Finished. Pres <Enter> to exit...").nl().reset();
|
Debugger::output().nl().fg(ostd::ConsoleColors::Yellow).p("Execution Finished. Pres <Enter> to exit...").nl().reset();
|
||||||
std::cin.get();
|
std::cin.get();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -78,14 +109,14 @@ int main(int argc, char** argv)
|
||||||
Debugger::data().args.step_exec = true;
|
Debugger::data().args.step_exec = true;
|
||||||
}
|
}
|
||||||
Debugger::data().command.trim().toLower();
|
Debugger::data().command.trim().toLower();
|
||||||
while (Debugger::data().command.str() != "")
|
while (Debugger::data().command != "")
|
||||||
{
|
{
|
||||||
if (Debugger::data().command.str() == "q" || Debugger::data().command.str() == "quit")
|
if (Debugger::data().command == "q" || Debugger::data().command == "quit")
|
||||||
{
|
{
|
||||||
userQuit = true;
|
userQuit = true;
|
||||||
Debugger::data().command = "";
|
Debugger::data().command = "";
|
||||||
}
|
}
|
||||||
else if (Debugger::data().command.str() == "c" || Debugger::data().command.str() == "continue")
|
else if (Debugger::data().command == "c" || Debugger::data().command == "continue")
|
||||||
{
|
{
|
||||||
Debugger::data().args.step_exec = false;
|
Debugger::data().args.step_exec = false;
|
||||||
Debugger::data().command = "";
|
Debugger::data().command = "";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#include "DebuggerWindow.hpp"
|
|
||||||
|
|
||||||
namespace dragon
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace dragon
|
|
||||||
{
|
|
||||||
class DebuggerWindow
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
} // namespace dragon
|
|
||||||
|
|
@ -13,11 +13,11 @@ namespace dragon
|
||||||
|
|
||||||
bool RawTextRenderer::drawString(ostd::String str, uint32_t column, uint32_t row, uint32_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint32_t* fontPixels, ostd::Color color, ostd::Color background)
|
bool RawTextRenderer::drawString(ostd::String str, uint32_t column, uint32_t row, uint32_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint32_t* fontPixels, ostd::Color color, ostd::Color background)
|
||||||
{
|
{
|
||||||
ostd::StringEditor se(str);
|
ostd::String se(str);
|
||||||
if (se.str() == "") return false;
|
if (se == "") return false;
|
||||||
if (row >= CONSOLE_CHARS_V) return false;
|
if (row >= CONSOLE_CHARS_V) return false;
|
||||||
if (column >= CONSOLE_CHARS_H) return false;
|
if (column >= CONSOLE_CHARS_H) return false;
|
||||||
if (column + str.length() > CONSOLE_CHARS_H) return false;
|
if (column + str.len() > CONSOLE_CHARS_H) return false;
|
||||||
int32_t x = column * FONT_CHAR_W;
|
int32_t x = column * FONT_CHAR_W;
|
||||||
int32_t y = row * FONT_CHAR_H;
|
int32_t y = row * FONT_CHAR_H;
|
||||||
for (auto& c : str)
|
for (auto& c : str)
|
||||||
|
|
|
||||||
|
|
@ -1,158 +0,0 @@
|
||||||
#include "VirtualConsole.hpp"
|
|
||||||
#include "RawTextRenderer.hpp"
|
|
||||||
#include <ostd/Defines.hpp>
|
|
||||||
|
|
||||||
#include "../hardware/VirtualIODevices.hpp"
|
|
||||||
#include "../hardware/VirtualCPU.hpp"
|
|
||||||
|
|
||||||
namespace dragon
|
|
||||||
{
|
|
||||||
void VirtualConsole::initialize(void)
|
|
||||||
{
|
|
||||||
m_windowWidth = RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::FONT_CHAR_W; //60 * 16;
|
|
||||||
m_windowHeight = RawTextRenderer::CONSOLE_CHARS_V * RawTextRenderer::FONT_CHAR_H; //60 * 9;
|
|
||||||
|
|
||||||
SDL_Init(SDL_INIT_VIDEO);
|
|
||||||
m_window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_windowWidth, m_windowHeight, SDL_WINDOW_RESIZABLE);
|
|
||||||
SDL_SetWindowResizable(m_window, SDL_FALSE);
|
|
||||||
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED);
|
|
||||||
SDL_SetWindowMinimumSize(m_window, m_windowWidth, m_windowHeight);
|
|
||||||
m_screenTexture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, m_windowWidth, m_windowHeight);
|
|
||||||
m_fontSurface = SDL_LoadBMP("font.bmp");
|
|
||||||
if (m_fontSurface == NULL)
|
|
||||||
out.bg(ostd::ConsoleColors::Red).p("Error loading font.").nl();
|
|
||||||
m_fontPixels = (uint32_t*)m_fontSurface->pixels;
|
|
||||||
m_screenPixels = (uint32_t*)malloc(m_windowWidth * m_windowHeight * 4);
|
|
||||||
|
|
||||||
dragon::RawTextRenderer::initialize();
|
|
||||||
|
|
||||||
vout.init(m_screenPixels, m_windowWidth, m_windowHeight, m_fontPixels);
|
|
||||||
vout.enableFixedScreen();
|
|
||||||
|
|
||||||
m_palettes.push_back(new data::BiosVideoDefaultPalette); //TODO: Possible Memory Leak, palettes are never destroyed
|
|
||||||
|
|
||||||
m_initialized = true;
|
|
||||||
m_running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsole::update(void)
|
|
||||||
{
|
|
||||||
if (!m_initialized) return;
|
|
||||||
Uint64 start = SDL_GetPerformanceCounter();
|
|
||||||
handleEvents();
|
|
||||||
if (m_redrawConsole)
|
|
||||||
{
|
|
||||||
uint8_t signal = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::Signal);
|
|
||||||
switch (signal)
|
|
||||||
{
|
|
||||||
case tSignals::ClearScreen:
|
|
||||||
m_clearMemory = true;
|
|
||||||
break;
|
|
||||||
case tSignals::Continue: break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
m_biosVideo.write8(hw::VirtualBIOSVideo::tRegisters::Signal, tSignals::Continue);
|
|
||||||
drawConsole();
|
|
||||||
m_redrawConsole = false;
|
|
||||||
}
|
|
||||||
finalizeRender();
|
|
||||||
Uint64 end = SDL_GetPerformanceCounter();
|
|
||||||
float elapsed = (end - start) / (float)SDL_GetPerformanceFrequency();
|
|
||||||
m_redrawAccumulator += elapsed;
|
|
||||||
if (m_redrawAccumulator >= 0.2f)
|
|
||||||
{
|
|
||||||
m_redrawConsole = true;
|
|
||||||
m_redrawAccumulator = 0.0f;
|
|
||||||
}
|
|
||||||
end = SDL_GetPerformanceCounter();
|
|
||||||
elapsed = (end - start) / (float)SDL_GetPerformanceFrequency();
|
|
||||||
m_timeAccumulator += elapsed;
|
|
||||||
if (m_timeAccumulator >= 0.5f)
|
|
||||||
{
|
|
||||||
m_title.clr().add("FPS: ").addi((int)(1.0f / elapsed));
|
|
||||||
SDL_SetWindowTitle(m_window, m_title.c_str());
|
|
||||||
m_timeAccumulator = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsole::handleEvents(void)
|
|
||||||
{
|
|
||||||
if (!m_initialized) return;
|
|
||||||
SDL_Event event;
|
|
||||||
while (SDL_PollEvent(&event))
|
|
||||||
{
|
|
||||||
if (event.type == SDL_QUIT) exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsole::finalizeRender(void)
|
|
||||||
{
|
|
||||||
SDL_RenderClear(m_renderer);
|
|
||||||
SDL_UpdateTexture(m_screenTexture, NULL, m_screenPixels, m_windowWidth * 4);
|
|
||||||
SDL_RenderCopy(m_renderer, m_screenTexture, NULL, NULL);
|
|
||||||
SDL_RenderPresent(m_renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsole::drawConsole(void)
|
|
||||||
{
|
|
||||||
const uint8_t TRANSPARENCY_COLOR_INDEX = 0x5;
|
|
||||||
|
|
||||||
uint8_t clearColor = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::ClearColor);
|
|
||||||
uint8_t palette = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::Palette);
|
|
||||||
bool useTransparency = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::UseTransparencyOn0x5) != 0;
|
|
||||||
|
|
||||||
if (palette >= m_palettes.size())
|
|
||||||
palette = 0; //TODO: Error
|
|
||||||
|
|
||||||
auto& pal = *m_palettes[palette];
|
|
||||||
|
|
||||||
ostd::Color clrCol = pal.getColor(clearColor);
|
|
||||||
if (m_clearMemory)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < m_windowHeight; ++y)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < m_windowWidth; ++x)
|
|
||||||
{
|
|
||||||
m_screenPixels[x + y * m_windowWidth] = clrCol.asInteger();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_clearMemory = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::Color fgCol;
|
|
||||||
ostd::Color bgCol;
|
|
||||||
uint16_t index = hw::VirtualBIOSVideo::tRegisters::VideoMemoryStart;
|
|
||||||
|
|
||||||
// if (m_clearMemory)
|
|
||||||
// {
|
|
||||||
// for (int32_t i = index; i < (index + (RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::CONSOLE_CHARS_V * 2)); i += 2)
|
|
||||||
// {
|
|
||||||
// m_biosVideo.write8((uint16_t)i, 0x00);
|
|
||||||
// m_biosVideo.write8((uint16_t)(i + 1), clearColor);
|
|
||||||
// }
|
|
||||||
// m_clearMemory = false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
for (int32_t i = index; i < (index + (RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::CONSOLE_CHARS_V * 2)); i += 2)
|
|
||||||
{
|
|
||||||
uint8_t character = m_biosVideo.read8((uint16_t)i);
|
|
||||||
uint8_t colors = m_biosVideo.read8((uint16_t)(i + 1));
|
|
||||||
uint8_t bgcol = (colors >> 4) & 0xF;
|
|
||||||
uint8_t fgcol = (colors & 0xF);
|
|
||||||
if (!isprint(character))
|
|
||||||
{
|
|
||||||
character = ' ';
|
|
||||||
fgCol = pal.getColor(fgcol);
|
|
||||||
bgCol = clrCol;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fgCol = pal.getColor(fgcol);
|
|
||||||
bgCol = pal.getColor(bgcol);
|
|
||||||
}
|
|
||||||
vout.bgcol(bgCol).col(fgCol).p((char)character).flush().bgcol(clrCol);
|
|
||||||
}
|
|
||||||
vout.refreshScreen();
|
|
||||||
m_cpu.handleInterrupt(data::InterruptCodes::BiosVideoScreenRefresh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../tools/SDLInclude.hpp"
|
|
||||||
|
|
||||||
#include <ostd/Utils.hpp>
|
|
||||||
#include "VirtualConsoleOutputHandler.hpp"
|
|
||||||
#include "../tools/GlobalData.hpp"
|
|
||||||
|
|
||||||
namespace dragon
|
|
||||||
{
|
|
||||||
namespace hw
|
|
||||||
{
|
|
||||||
class VirtualBIOSVideo;
|
|
||||||
class VirtualCPU;
|
|
||||||
}
|
|
||||||
class VirtualConsole
|
|
||||||
{
|
|
||||||
public: struct tSignals
|
|
||||||
{
|
|
||||||
inline static constexpr uint8_t Continue = 0x00;
|
|
||||||
inline static constexpr uint8_t ClearScreen = 0x01;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
inline VirtualConsole(hw::VirtualBIOSVideo& biosVideo, hw::VirtualCPU& cpu) : m_biosVideo(biosVideo), m_cpu(cpu) { }
|
|
||||||
inline bool isInitialized(void) const { return m_initialized; }
|
|
||||||
inline bool isRunning(void) const { return m_running; }
|
|
||||||
void initialize(void);
|
|
||||||
void update(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void handleEvents(void);
|
|
||||||
void finalizeRender(void);
|
|
||||||
void drawConsole(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
ostd::ConsoleOutputHandler out;
|
|
||||||
dragon::VirtualConsoleOutputHandler vout;
|
|
||||||
|
|
||||||
SDL_Window* m_window { nullptr };
|
|
||||||
SDL_Renderer* m_renderer { nullptr };
|
|
||||||
SDL_Texture* m_screenTexture { nullptr };
|
|
||||||
SDL_Surface* m_fontSurface { nullptr };
|
|
||||||
|
|
||||||
int32_t m_windowWidth { 0 };
|
|
||||||
int32_t m_windowHeight { 0 };
|
|
||||||
|
|
||||||
uint32_t* m_fontPixels { nullptr };
|
|
||||||
uint32_t* m_screenPixels { nullptr };
|
|
||||||
|
|
||||||
bool m_redrawConsole { true };
|
|
||||||
float m_timeAccumulator { 0.0f };
|
|
||||||
bool m_running { false };
|
|
||||||
|
|
||||||
ostd::StringEditor m_title { "" };
|
|
||||||
float m_redrawAccumulator { 0.0f };
|
|
||||||
bool m_initialized { false };
|
|
||||||
bool m_clearMemory { false };
|
|
||||||
|
|
||||||
hw::VirtualBIOSVideo& m_biosVideo;
|
|
||||||
hw::VirtualCPU& m_cpu;
|
|
||||||
std::vector<data::IBiosVideoPalette*> m_palettes;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,303 +0,0 @@
|
||||||
#include "VirtualConsoleOutputHandler.hpp"
|
|
||||||
#include "RawTextRenderer.hpp"
|
|
||||||
|
|
||||||
#include <ostd/Defines.hpp>
|
|
||||||
#include <ostd/Logger.hpp>
|
|
||||||
|
|
||||||
namespace dragon
|
|
||||||
{
|
|
||||||
tRichChar RichString::at(uint32_t index) const
|
|
||||||
{
|
|
||||||
if (index >= m_text.size())
|
|
||||||
{
|
|
||||||
OX_WARN("ox::RichString::at(...): Index out of bounds.");
|
|
||||||
return tRichChar();
|
|
||||||
}
|
|
||||||
return { (unsigned char)m_text[index], m_foreground[index], m_background[index] };
|
|
||||||
}
|
|
||||||
|
|
||||||
void RichString::add(tRichChar rchar)
|
|
||||||
{
|
|
||||||
m_text += rchar.ascii;
|
|
||||||
m_foreground.push_back(rchar.foreground);
|
|
||||||
m_background.push_back(rchar.background);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RichString::add(ostd::String str, ostd::Color fg, ostd::Color bg)
|
|
||||||
{
|
|
||||||
for (auto& c : str)
|
|
||||||
{
|
|
||||||
m_text += c;
|
|
||||||
m_foreground.push_back(fg);
|
|
||||||
m_background.push_back(bg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RichString::add(ostd::String str)
|
|
||||||
{
|
|
||||||
ostd::Color fcol(255);
|
|
||||||
ostd::Color bcol(0, 0);
|
|
||||||
if (m_text.length() > 0)
|
|
||||||
{
|
|
||||||
fcol = m_foreground[m_foreground.size() - 1];
|
|
||||||
bcol = m_background[m_background.size() - 1];
|
|
||||||
}
|
|
||||||
add(str, fcol, bcol);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RichString::clear(void)
|
|
||||||
{
|
|
||||||
m_text = "";
|
|
||||||
m_background.clear();
|
|
||||||
m_foreground.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::col(ostd::String color)
|
|
||||||
{
|
|
||||||
//TODO: Maybe implement??
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::col(const ostd::Color& color)
|
|
||||||
{
|
|
||||||
m_currentForegroundColor = color;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::p(char c)
|
|
||||||
{
|
|
||||||
check_if_new_line();
|
|
||||||
m_currentBufferEditor.add(c);
|
|
||||||
add_current_to_rich_buffer();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::p(const ostd::StringEditor& se)
|
|
||||||
{
|
|
||||||
check_if_new_line();
|
|
||||||
m_currentBufferEditor.add(se.str());
|
|
||||||
add_current_to_rich_buffer();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(uint8_t i)
|
|
||||||
{
|
|
||||||
check_if_new_line();
|
|
||||||
m_currentBufferEditor.addi(i);
|
|
||||||
add_current_to_rich_buffer();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(int8_t i)
|
|
||||||
{
|
|
||||||
check_if_new_line();
|
|
||||||
m_currentBufferEditor.addi(i);
|
|
||||||
add_current_to_rich_buffer();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(uint16_t i)
|
|
||||||
{
|
|
||||||
check_if_new_line();
|
|
||||||
m_currentBufferEditor.addi(i);
|
|
||||||
add_current_to_rich_buffer();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(int16_t i)
|
|
||||||
{
|
|
||||||
check_if_new_line();
|
|
||||||
m_currentBufferEditor.addi(i);
|
|
||||||
add_current_to_rich_buffer();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(uint32_t i)
|
|
||||||
{
|
|
||||||
check_if_new_line();
|
|
||||||
m_currentBufferEditor.addi(i);
|
|
||||||
add_current_to_rich_buffer();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(int32_t i)
|
|
||||||
{
|
|
||||||
check_if_new_line();
|
|
||||||
m_currentBufferEditor.addi(i);
|
|
||||||
add_current_to_rich_buffer();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(uint64_t i)
|
|
||||||
{
|
|
||||||
check_if_new_line();
|
|
||||||
m_currentBufferEditor.addi(i);
|
|
||||||
add_current_to_rich_buffer();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(int64_t i)
|
|
||||||
{
|
|
||||||
check_if_new_line();
|
|
||||||
m_currentBufferEditor.addi(i);
|
|
||||||
add_current_to_rich_buffer();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pf(float f, uint8_t precision)
|
|
||||||
{
|
|
||||||
//TODO: Implement precision
|
|
||||||
check_if_new_line();
|
|
||||||
m_currentBufferEditor.addf(f);
|
|
||||||
add_current_to_rich_buffer();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pf(double f, uint8_t precision)
|
|
||||||
{
|
|
||||||
//TODO: Implement precision
|
|
||||||
check_if_new_line();
|
|
||||||
m_currentBufferEditor.addf(f);
|
|
||||||
add_current_to_rich_buffer();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::nl(void)
|
|
||||||
{
|
|
||||||
m_newLine = true;
|
|
||||||
flush();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::flush(void)
|
|
||||||
{
|
|
||||||
if (!isInitialized()) return *this;
|
|
||||||
if (m_currentBuffer.getText() == "") return *this;
|
|
||||||
|
|
||||||
m_lines.push_back(m_currentBuffer);
|
|
||||||
m_currentBuffer.clear();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::reset(void)
|
|
||||||
{
|
|
||||||
m_currentBuffer.clear();
|
|
||||||
m_currentBufferEditor.clr();
|
|
||||||
m_lines.clear();
|
|
||||||
m_newLine = true;
|
|
||||||
resetColors();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::clear(void)
|
|
||||||
{
|
|
||||||
//TODO: Implement
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::bgcol(const ostd::Color& color)
|
|
||||||
{
|
|
||||||
m_currentBackgroundColor = color;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::bgcol(ostd::String color)
|
|
||||||
{
|
|
||||||
//TODO: Maybe implement
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::resetColors(void)
|
|
||||||
{
|
|
||||||
m_currentForegroundColor = m_defaultForegroundColor;
|
|
||||||
m_currentBackgroundColor = m_defaultBackgroundColor;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsoleOutputHandler::init(uint32_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint32_t* fontPixels)
|
|
||||||
{
|
|
||||||
m_screenPixels = screenPixels;
|
|
||||||
m_fontPixels = fontPixels;
|
|
||||||
m_screenHeight = screenHeight;
|
|
||||||
m_screenWidth = screenWidth;
|
|
||||||
|
|
||||||
m_initialized = m_screenHeight > 0 && m_screenWidth > 0 && m_screenPixels != nullptr && m_fontPixels != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsoleOutputHandler::add_current_to_rich_buffer(void)
|
|
||||||
{
|
|
||||||
if (m_currentBuffer.getText().length() + m_currentBufferEditor.len() <= RawTextRenderer::CONSOLE_CHARS_H)
|
|
||||||
{
|
|
||||||
m_currentBuffer.add(m_currentBufferEditor.str(), m_currentForegroundColor, m_currentBackgroundColor);
|
|
||||||
m_currentBufferEditor.clr();
|
|
||||||
if (m_currentBuffer.getText().length() == RawTextRenderer::CONSOLE_CHARS_H)
|
|
||||||
nl();
|
|
||||||
else
|
|
||||||
m_newLine = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int32_t extraStringLength = (m_currentBuffer.getText().length() + m_currentBufferEditor.len()) - RawTextRenderer::CONSOLE_CHARS_H;
|
|
||||||
ostd::String excess = m_currentBufferEditor.substr(RawTextRenderer::CONSOLE_CHARS_H);
|
|
||||||
ostd::String end = m_currentBufferEditor.substr(0, RawTextRenderer::CONSOLE_CHARS_H);
|
|
||||||
m_currentBuffer.add(end, m_currentForegroundColor, m_currentBackgroundColor);
|
|
||||||
nl();
|
|
||||||
m_currentBufferEditor = excess;
|
|
||||||
add_current_to_rich_buffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsoleOutputHandler::check_if_new_line(void)
|
|
||||||
{
|
|
||||||
if (m_newLine) return;
|
|
||||||
if (m_lines.size() > 0)
|
|
||||||
{
|
|
||||||
m_currentBuffer = m_lines[m_lines.size() - 1];
|
|
||||||
m_lines.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsoleOutputHandler::draw_rich_String(const RichString& rstr, uint32_t row)
|
|
||||||
{
|
|
||||||
for (int32_t i = 0; i < rstr.getText().length(); i++)
|
|
||||||
{
|
|
||||||
auto rchar = rstr.at(i);
|
|
||||||
RawTextRenderer::drawString(ostd::StringEditor().add(rchar.ascii).str(), i, row, m_screenPixels, m_screenWidth, m_screenHeight, m_fontPixels, rchar.foreground, rchar.background);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsoleOutputHandler::refreshScreen(void)
|
|
||||||
{
|
|
||||||
uint32_t row = 0;
|
|
||||||
if (m_lines.size() > RawTextRenderer::CONSOLE_CHARS_V - 1)
|
|
||||||
{
|
|
||||||
if (m_fixedScreen)
|
|
||||||
{
|
|
||||||
for (int32_t i = 0; i < RawTextRenderer::CONSOLE_CHARS_V; i++)
|
|
||||||
{
|
|
||||||
draw_rich_String(m_lines[i], row);
|
|
||||||
row++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int32_t i = m_lines.size() - RawTextRenderer::CONSOLE_CHARS_V + 1; i < m_lines.size(); i++)
|
|
||||||
{
|
|
||||||
draw_rich_String(m_lines[i], row);
|
|
||||||
row++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (auto& line : m_lines)
|
|
||||||
{
|
|
||||||
draw_rich_String(line, row);
|
|
||||||
row++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_lines.clear();
|
|
||||||
m_currentBuffer.clear();
|
|
||||||
m_currentBufferEditor.clr();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ostd/Utils.hpp>
|
|
||||||
#include <ostd/Color.hpp>
|
|
||||||
|
|
||||||
#include <ostd/IOHandlers.hpp>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace dragon
|
|
||||||
{
|
|
||||||
struct tRichChar
|
|
||||||
{
|
|
||||||
unsigned char ascii { 0 };
|
|
||||||
ostd::Color foreground { 0, 0 };
|
|
||||||
ostd::Color background { 0, 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
class RichString //TODO: Legacy RichString should be replaced with new tStyledString
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline RichString(void) { }
|
|
||||||
inline ostd::String getText(void) const { return m_text; }
|
|
||||||
tRichChar at(uint32_t index) const;
|
|
||||||
void add(tRichChar rchar);
|
|
||||||
void add(ostd::String str, ostd::Color fg, ostd::Color bg);
|
|
||||||
void add(ostd::String str);
|
|
||||||
void clear(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
ostd::String m_text { "" };
|
|
||||||
std::vector<ostd::Color> m_foreground;
|
|
||||||
std::vector<ostd::Color> m_background;
|
|
||||||
};
|
|
||||||
|
|
||||||
class VirtualConsoleOutputHandler : public ostd::legacy::IOutputHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ostd::legacy::IOutputHandler& col(ostd::String color) override;
|
|
||||||
ostd::legacy::IOutputHandler& col(const ostd::Color& color) override;
|
|
||||||
ostd::legacy::IOutputHandler& p(char c) override;
|
|
||||||
ostd::legacy::IOutputHandler& p(const ostd::StringEditor& se) override;
|
|
||||||
ostd::legacy::IOutputHandler& pi(uint8_t i) override;
|
|
||||||
ostd::legacy::IOutputHandler& pi(int8_t i) override;
|
|
||||||
ostd::legacy::IOutputHandler& pi(uint16_t i) override;
|
|
||||||
ostd::legacy::IOutputHandler& pi(int16_t i) override;
|
|
||||||
ostd::legacy::IOutputHandler& pi(uint32_t i) override;
|
|
||||||
ostd::legacy::IOutputHandler& pi(int32_t i) override;
|
|
||||||
ostd::legacy::IOutputHandler& pi(uint64_t i) override;
|
|
||||||
ostd::legacy::IOutputHandler& pi(int64_t i) override;
|
|
||||||
ostd::legacy::IOutputHandler& pf(float f, uint8_t precision = 0) override;
|
|
||||||
ostd::legacy::IOutputHandler& pf(double f, uint8_t precision = 0) override;
|
|
||||||
ostd::legacy::IOutputHandler& nl(void) override;
|
|
||||||
inline ostd::legacy::IOutputHandler& pStyled(const ostd::StringEditor& styled) override { return *this; } //TODO: Implement
|
|
||||||
inline ostd::legacy::IOutputHandler& pStyled(const ostd::TextStyleBuilder::IRichStringBase& styled) override { return *this; } //TODO: Implement
|
|
||||||
inline ostd::legacy::IOutputHandler& pStyled(const ostd::TextStyleParser::tStyledString& styled) override { return *this; }; //TODO: Implement
|
|
||||||
ostd::legacy::IOutputHandler& flush(void) override;
|
|
||||||
ostd::legacy::IOutputHandler& reset(void) override;
|
|
||||||
ostd::legacy::IOutputHandler& clear(void) override;
|
|
||||||
|
|
||||||
ostd::legacy::IOutputHandler& bgcol(const ostd::Color& color) override;
|
|
||||||
ostd::legacy::IOutputHandler& bgcol(ostd::String color) override;
|
|
||||||
ostd::legacy::IOutputHandler& resetColors(void) override;
|
|
||||||
|
|
||||||
void init(uint32_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint32_t* fontPixels);
|
|
||||||
inline bool isInitialized(void) const { return m_initialized; }
|
|
||||||
inline bool isFixedScreen(void) const { return m_fixedScreen; }
|
|
||||||
inline void enableFixedScreen(bool fs = true) { m_fixedScreen = fs; }
|
|
||||||
|
|
||||||
void refreshScreen(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void add_current_to_rich_buffer(void);
|
|
||||||
void check_if_new_line(void);
|
|
||||||
void draw_rich_String(const RichString& rstr, uint32_t row);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<RichString> m_lines;
|
|
||||||
RichString m_currentBuffer;
|
|
||||||
ostd::StringEditor m_currentBufferEditor;
|
|
||||||
|
|
||||||
// std::vector<ostd::String> m_allLines;
|
|
||||||
// ostd::StringEditor m_buffer;
|
|
||||||
// int32_t m_currentRow { 0 };
|
|
||||||
// int32_t m_currentColumn { 0 };
|
|
||||||
ostd::Color m_currentForegroundColor { 255, 255, 255, 255 };
|
|
||||||
ostd::Color m_currentBackgroundColor { 255, 255, 255, 0 };
|
|
||||||
ostd::Color m_defaultForegroundColor { 255, 255, 255, 255 };
|
|
||||||
ostd::Color m_defaultBackgroundColor { 255, 255, 255, 0 };
|
|
||||||
|
|
||||||
uint32_t* m_screenPixels { nullptr };
|
|
||||||
uint32_t* m_fontPixels { nullptr };
|
|
||||||
int32_t m_screenWidth { 0 };
|
|
||||||
int32_t m_screenHeight { 0 };
|
|
||||||
bool m_initialized { false };
|
|
||||||
bool m_newLine { true };
|
|
||||||
bool m_fixedScreen { false };
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -2,25 +2,51 @@
|
||||||
|
|
||||||
namespace dragon
|
namespace dragon
|
||||||
{
|
{
|
||||||
void Window::initialize(int32_t width, int32_t height, const ostd::String& fontPath)
|
Window::~Window(void)
|
||||||
{
|
{
|
||||||
|
onDestroy();
|
||||||
|
SDL_FreeSurface(m_fontSurface);
|
||||||
|
SDL_DestroyRenderer(m_renderer);
|
||||||
|
SDL_DestroyWindow(m_window);
|
||||||
|
IMG_Quit();
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::initialize(int32_t width, int32_t height, const ostd::String& windowTitle, const ostd::String& fontPath)
|
||||||
|
{
|
||||||
|
if (m_initialized) return;
|
||||||
m_windowWidth = width;
|
m_windowWidth = width;
|
||||||
m_windowHeight = height;
|
m_windowHeight = height;
|
||||||
|
m_title = windowTitle;
|
||||||
SDL_Init(SDL_INIT_VIDEO);
|
if (SDL_Init(SDL_INIT_VIDEO) != 0)
|
||||||
|
{
|
||||||
|
printf( "SDL could not initialize! Error: %s\n", SDL_GetError() );
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
int imgFlags = IMG_INIT_PNG;
|
||||||
|
if (!(IMG_Init(imgFlags) & imgFlags))
|
||||||
|
{
|
||||||
|
printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
m_window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_windowWidth, m_windowHeight, SDL_WINDOW_RESIZABLE);
|
m_window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_windowWidth, m_windowHeight, SDL_WINDOW_RESIZABLE);
|
||||||
SDL_SetWindowResizable(m_window, SDL_FALSE);
|
SDL_SetWindowResizable(m_window, SDL_FALSE);
|
||||||
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED);
|
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED);
|
||||||
SDL_SetWindowMinimumSize(m_window, m_windowWidth, m_windowHeight);
|
SDL_SetWindowMinimumSize(m_window, m_windowWidth, m_windowHeight);
|
||||||
// m_screenTexture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, m_windowWidth, m_windowHeight);
|
SDL_SetWindowTitle(m_window, m_title.c_str());
|
||||||
m_fontSurface = SDL_LoadBMP(fontPath.c_str());
|
m_fontSurface = SDL_LoadBMP(fontPath.c_str());
|
||||||
if (m_fontSurface == NULL)
|
if (m_fontSurface == NULL)
|
||||||
out.bg(ostd::ConsoleColors::Red).p("Error loading font.").reset().nl();
|
out.bg(ostd::ConsoleColors::Red).p("Error loading font.").reset().nl();
|
||||||
m_fontPixels = (uint32_t*)m_fontSurface->pixels;
|
m_fontPixels = (uint32_t*)m_fontSurface->pixels;
|
||||||
// m_screenPixels = (uint32_t*)malloc(m_windowWidth * m_windowHeight * 4);
|
|
||||||
|
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
m_running = true;
|
m_running = true;
|
||||||
|
|
||||||
|
setTypeName("lspp::app::Window");
|
||||||
|
enableSignals(true);
|
||||||
|
validate();
|
||||||
|
|
||||||
|
onInitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::update(void)
|
void Window::update(void)
|
||||||
|
|
@ -28,24 +54,16 @@ namespace dragon
|
||||||
if (!m_initialized) return;
|
if (!m_initialized) return;
|
||||||
Uint64 start = SDL_GetPerformanceCounter();
|
Uint64 start = SDL_GetPerformanceCounter();
|
||||||
handleEvents();
|
handleEvents();
|
||||||
|
onUpdate();
|
||||||
SDL_RenderClear(m_renderer);
|
SDL_RenderClear(m_renderer);
|
||||||
for (int32_t i = 0; i < m_widgets.size(); i++)
|
onRender();
|
||||||
{
|
|
||||||
if (m_widgets[i] == nullptr) continue;
|
|
||||||
m_widgets[i]->draw();
|
|
||||||
}
|
|
||||||
SDL_RenderPresent(m_renderer);
|
SDL_RenderPresent(m_renderer);
|
||||||
// finalizeRender();
|
|
||||||
Uint64 end = SDL_GetPerformanceCounter();
|
Uint64 end = SDL_GetPerformanceCounter();
|
||||||
float elapsed = (end - start) / (float)SDL_GetPerformanceFrequency();
|
float elapsed = (end - start) / (float)SDL_GetPerformanceFrequency();
|
||||||
m_redrawAccumulator += elapsed;
|
m_redrawAccumulator += elapsed;
|
||||||
if (m_redrawAccumulator >= 0.2f)
|
if (m_redrawAccumulator >= 0.2f)
|
||||||
{
|
{
|
||||||
for (int32_t i = 0; i < m_widgets.size(); i++)
|
onFixedUpdate();
|
||||||
{
|
|
||||||
if (m_widgets[i] == nullptr) continue;
|
|
||||||
m_widgets[i]->fixedUpdate();
|
|
||||||
}
|
|
||||||
m_redrawAccumulator = 0.0f;
|
m_redrawAccumulator = 0.0f;
|
||||||
}
|
}
|
||||||
end = SDL_GetPerformanceCounter();
|
end = SDL_GetPerformanceCounter();
|
||||||
|
|
@ -53,46 +71,78 @@ namespace dragon
|
||||||
m_timeAccumulator += elapsed;
|
m_timeAccumulator += elapsed;
|
||||||
if (m_timeAccumulator >= 0.5f)
|
if (m_timeAccumulator >= 0.5f)
|
||||||
{
|
{
|
||||||
for (int32_t i = 0; i < m_widgets.size(); i++)
|
onSlowUpdate();
|
||||||
{
|
m_fps = (int32_t)(1.0f / elapsed);
|
||||||
if (m_widgets[i] == nullptr) continue;
|
|
||||||
m_widgets[i]->slowUpdate();
|
|
||||||
}
|
|
||||||
m_title.clr().add("FPS: ").addi((int)(1.0f / elapsed));
|
|
||||||
SDL_SetWindowTitle(m_window, m_title.c_str());
|
|
||||||
m_timeAccumulator = 0.0f;
|
m_timeAccumulator = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::addWidget(Widget& widget)
|
|
||||||
{
|
|
||||||
widget.__init(*this);
|
|
||||||
m_widgets.push_back(&widget);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::setSize(int32_t width, int32_t height)
|
void Window::setSize(int32_t width, int32_t height)
|
||||||
{
|
{
|
||||||
if (!isInitialized()) return;
|
if (!isInitialized()) return;
|
||||||
SDL_SetWindowSize(m_window, width, height);
|
SDL_SetWindowSize(m_window, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::setTitle(const ostd::String& title)
|
||||||
|
{
|
||||||
|
if (!isInitialized()) return;
|
||||||
|
m_title = title;
|
||||||
|
SDL_SetWindowTitle(m_window, m_title.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
void Window::handleEvents(void)
|
void Window::handleEvents(void)
|
||||||
{
|
{
|
||||||
if (!m_initialized) return;
|
if (!m_initialized) return;
|
||||||
|
auto l_getMouseState = [this](void) -> MouseEventData {
|
||||||
|
int32_t mx = 0, my = 0;
|
||||||
|
uint32_t btn = SDL_GetMouseState(&mx, &my);
|
||||||
|
MouseEventData::eButton button = MouseEventData::eButton::None;
|
||||||
|
switch (btn)
|
||||||
|
{
|
||||||
|
case SDL_BUTTON(1): button = MouseEventData::eButton::Left; break;
|
||||||
|
case SDL_BUTTON(2): button = MouseEventData::eButton::Middle; break;
|
||||||
|
case SDL_BUTTON(3): button = MouseEventData::eButton::Right; break;
|
||||||
|
default: button = MouseEventData::eButton::None; break;
|
||||||
|
}
|
||||||
|
MouseEventData mmd(*this, mx, my, button);
|
||||||
|
return mmd;
|
||||||
|
};
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event))
|
while (SDL_PollEvent(&event))
|
||||||
{
|
{
|
||||||
if (event.type == SDL_QUIT)
|
if (event.type == SDL_QUIT)
|
||||||
{
|
{
|
||||||
m_running = false;
|
m_running = false;
|
||||||
|
ostd::SignalHandler::emitSignal(Signal_OnWindowClosed, ostd::tSignalPriority::Normal, *this);
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_WINDOWEVENT)
|
||||||
|
{
|
||||||
|
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||||
|
WindowResizedData wrd(*this, m_windowWidth, m_windowHeight, 0, 0);
|
||||||
|
SDL_GetWindowSize(m_window, &m_windowWidth, &m_windowHeight);
|
||||||
|
wrd.new_width = m_windowWidth;
|
||||||
|
wrd.new_height = m_windowHeight;
|
||||||
|
ostd::SignalHandler::emitSignal(Signal_OnWindowResized, ostd::tSignalPriority::RealTime, wrd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_MOUSEMOTION)
|
||||||
|
{
|
||||||
|
MouseEventData mmd = l_getMouseState();
|
||||||
|
if (isMouseDragEventEnabled() && mmd.button != MouseEventData::eButton::None)
|
||||||
|
ostd::SignalHandler::emitSignal(Signal_OnMouseDragged, ostd::tSignalPriority::RealTime, mmd);
|
||||||
|
else
|
||||||
|
ostd::SignalHandler::emitSignal(Signal_OnMouseMoved, ostd::tSignalPriority::RealTime, mmd);
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_MOUSEBUTTONDOWN)
|
||||||
|
{
|
||||||
|
MouseEventData mmd = l_getMouseState();
|
||||||
|
ostd::SignalHandler::emitSignal(Signal_OnMousePressed, ostd::tSignalPriority::RealTime, mmd);
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_MOUSEBUTTONUP)
|
||||||
|
{
|
||||||
|
MouseEventData mmd = l_getMouseState();
|
||||||
|
ostd::SignalHandler::emitSignal(Signal_OnMouseReleased, ostd::tSignalPriority::RealTime, mmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::finalizeRender(void)
|
|
||||||
{
|
|
||||||
// SDL_UpdateTexture(m_screenTexture, NULL, m_screenPixels, m_windowWidth * 4);
|
|
||||||
// SDL_RenderCopy(m_renderer, m_screenTexture, NULL, NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -3,55 +3,105 @@
|
||||||
#include "../tools/SDLInclude.hpp"
|
#include "../tools/SDLInclude.hpp"
|
||||||
#include <ostd/Utils.hpp>
|
#include <ostd/Utils.hpp>
|
||||||
#include <ostd/Signals.hpp>
|
#include <ostd/Signals.hpp>
|
||||||
#include "VirtualConsoleOutputHandler.hpp"
|
#include <ostd/IOHandlers.hpp>
|
||||||
#include "../tools/GlobalData.hpp"
|
|
||||||
#include "../gui/widgets/Widget.hpp"
|
|
||||||
|
|
||||||
namespace dragon
|
namespace dragon
|
||||||
{
|
{
|
||||||
class Window
|
class Window : public ostd::BaseObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline Window(void) { }
|
inline Window(void) { }
|
||||||
|
~Window(void);
|
||||||
|
inline Window(int32_t width, int32_t height, const ostd::String& windowTitle, const ostd::String& fontPath) { initialize(width, height, windowTitle, fontPath); }
|
||||||
|
void initialize(int32_t width, int32_t height, const ostd::String& windowTitle, const ostd::String& fontPath);
|
||||||
|
|
||||||
|
void update(void);
|
||||||
|
void setSize(int32_t width, int32_t height);
|
||||||
|
void setTitle(const ostd::String& title);
|
||||||
|
|
||||||
|
inline virtual void onRender(void) { }
|
||||||
|
inline virtual void onUpdate(void) { }
|
||||||
|
inline virtual void onFixedUpdate(void) { }
|
||||||
|
inline virtual void onSlowUpdate(void) { }
|
||||||
|
inline virtual void onInitialize(void) { }
|
||||||
|
inline virtual void onDestroy(void) { }
|
||||||
|
|
||||||
inline bool isInitialized(void) const { return m_initialized; }
|
inline bool isInitialized(void) const { return m_initialized; }
|
||||||
inline bool isRunning(void) const { return m_running; }
|
inline bool isRunning(void) const { return m_running; }
|
||||||
inline void hide(void) { SDL_HideWindow(m_window); }
|
inline void hide(void) { SDL_HideWindow(m_window); }
|
||||||
inline void show(void) { SDL_ShowWindow(m_window); }
|
inline void show(void) { SDL_ShowWindow(m_window); }
|
||||||
void initialize(int32_t width, int32_t height, const ostd::String& fontPath);
|
inline ostd::String getTitle(void) const { return m_title; }
|
||||||
void update(void);
|
inline int32_t getFPS(void) const { return m_fps; }
|
||||||
bool addWidget(Widget& widget);
|
inline int32_t getWindowWidth(void) const { return m_windowWidth; }
|
||||||
void setSize(int32_t width, int32_t height);
|
inline int32_t getWindowHeight(void) const { return m_windowHeight; }
|
||||||
|
inline SDL_Renderer* getSDLRenderer(void) const { return m_renderer; }
|
||||||
|
inline bool isMouseDragEventEnabled(void) const { return m_deagEventEnabled; }
|
||||||
|
inline void enableMouseDragEvent(bool enable = true) { m_deagEventEnabled = enable; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleEvents(void);
|
void handleEvents(void);
|
||||||
void finalizeRender(void);
|
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
ostd::ConsoleOutputHandler out;
|
ostd::ConsoleOutputHandler out;
|
||||||
|
|
||||||
std::vector<Widget*> m_widgets;
|
|
||||||
|
|
||||||
SDL_Window* m_window { nullptr };
|
SDL_Window* m_window { nullptr };
|
||||||
SDL_Renderer* m_renderer { nullptr };
|
SDL_Renderer* m_renderer { nullptr };
|
||||||
// SDL_Texture* m_screenTexture { nullptr };
|
|
||||||
SDL_Surface* m_fontSurface { nullptr };
|
SDL_Surface* m_fontSurface { nullptr };
|
||||||
|
uint32_t* m_fontPixels { nullptr };
|
||||||
|
|
||||||
|
private:
|
||||||
int32_t m_windowWidth { 0 };
|
int32_t m_windowWidth { 0 };
|
||||||
int32_t m_windowHeight { 0 };
|
int32_t m_windowHeight { 0 };
|
||||||
|
ostd::String m_title { "" };
|
||||||
uint32_t* m_fontPixels { nullptr };
|
int32_t m_fps { 0 };
|
||||||
// uint32_t* m_screenPixels { nullptr };
|
|
||||||
|
|
||||||
float m_timeAccumulator { 0.0f };
|
float m_timeAccumulator { 0.0f };
|
||||||
bool m_running { false };
|
|
||||||
|
|
||||||
ostd::StringEditor m_title { "" };
|
|
||||||
float m_redrawAccumulator { 0.0f };
|
float m_redrawAccumulator { 0.0f };
|
||||||
|
|
||||||
|
bool m_deagEventEnabled { false };
|
||||||
|
bool m_running { false };
|
||||||
bool m_initialized { false };
|
bool m_initialized { false };
|
||||||
|
|
||||||
|
public:
|
||||||
//Signals
|
//Signals
|
||||||
inline static const uint32_t Signal_OnMousePressed = ostd::SignalHandler::newCustomSignal(4096);
|
inline static const uint32_t Signal_OnMousePressed = ostd::SignalHandler::newCustomSignal(1000);
|
||||||
|
inline static const uint32_t Signal_OnMouseReleased = ostd::SignalHandler::newCustomSignal(1001);
|
||||||
|
inline static const uint32_t Signal_OnMouseMoved = ostd::SignalHandler::newCustomSignal(1002);
|
||||||
|
inline static const uint32_t Signal_OnMouseDragged = ostd::SignalHandler::newCustomSignal(1003);
|
||||||
|
|
||||||
friend class VirtualConsoleWidtget;
|
inline static const uint32_t Signal_OnWindowClosed = ostd::SignalHandler::newCustomSignal(2000);
|
||||||
|
inline static const uint32_t Signal_OnWindowResized = ostd::SignalHandler::newCustomSignal(2001);
|
||||||
|
};
|
||||||
|
class WindowResizedData : public ostd::BaseObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline WindowResizedData(Window& parent, int32_t _oldx, int32_t _oldy, int32_t _newx, int32_t _newy) : parentWindow(parent), old_width(_oldx), old_height(_oldy), new_width(_newx), new_height(_newy)
|
||||||
|
{
|
||||||
|
setTypeName("lspp::app::WindowResizedData");
|
||||||
|
validate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
int32_t new_width;
|
||||||
|
int32_t new_height;
|
||||||
|
int32_t old_width;
|
||||||
|
int32_t old_height;
|
||||||
|
Window& parentWindow;
|
||||||
|
};
|
||||||
|
class MouseEventData : public ostd::BaseObject
|
||||||
|
{
|
||||||
|
public: enum class eButton { None = 0, Left, Middle, Right };
|
||||||
|
public:
|
||||||
|
inline MouseEventData(Window& parent, int32_t mousex, int32_t mousey, eButton btn) : parentWindow(parent), position_x(mousex), position_y(mousey), button(btn)
|
||||||
|
{
|
||||||
|
setTypeName("lspp::app::MouseEventData");
|
||||||
|
validate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
int32_t position_x;
|
||||||
|
int32_t position_y;
|
||||||
|
eButton button;
|
||||||
|
Window& parentWindow;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
#include "VirtualConsoleWidget.hpp"
|
|
||||||
#include "../../gui/RawTextRenderer.hpp"
|
|
||||||
#include "../../gui/Window.hpp"
|
|
||||||
#include "../../hardware/VirtualIODevices.hpp"
|
|
||||||
#include "../../hardware/VirtualCPU.hpp"
|
|
||||||
|
|
||||||
namespace dragon
|
|
||||||
{
|
|
||||||
void VirtualConsoleWidtget::init(void)
|
|
||||||
{
|
|
||||||
setw(RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::FONT_CHAR_W); //60 * 16;
|
|
||||||
seth(RawTextRenderer::CONSOLE_CHARS_V * RawTextRenderer::FONT_CHAR_H); //60 * 9;
|
|
||||||
setPosition(0, 0);
|
|
||||||
|
|
||||||
dragon::RawTextRenderer::initialize();
|
|
||||||
|
|
||||||
m_pixels = new uint32_t[getw() * geth()]; //TODO: Delete (Memory Leak)
|
|
||||||
|
|
||||||
vout.init(m_pixels, getw(), geth(), m_parent->m_fontPixels);
|
|
||||||
vout.enableFixedScreen();
|
|
||||||
|
|
||||||
m_palettes.push_back(new data::BiosVideoDefaultPalette); //TODO: Possible Memory Leak, palettes are never destroyed
|
|
||||||
|
|
||||||
m_texture = SDL_CreateTexture(m_parent->m_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, getw(), geth());
|
|
||||||
|
|
||||||
m_initialized = true;
|
|
||||||
validate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsoleWidtget::draw(void)
|
|
||||||
{
|
|
||||||
if (isInvalid()) return;
|
|
||||||
SDL_Rect rect { (int)getx(), (int)gety(), (int)getw(), (int)geth() };
|
|
||||||
SDL_RenderCopy(m_parent->m_renderer, m_texture, NULL, &rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsoleWidtget::drawConsole(void)
|
|
||||||
{
|
|
||||||
if (isInvalid()) return;
|
|
||||||
const uint8_t TRANSPARENCY_COLOR_INDEX = 0x5;
|
|
||||||
|
|
||||||
uint8_t clearColor = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::ClearColor);
|
|
||||||
uint8_t palette = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::Palette);
|
|
||||||
bool useTransparency = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::UseTransparencyOn0x5) != 0;
|
|
||||||
|
|
||||||
if (palette >= m_palettes.size())
|
|
||||||
palette = 0; //TODO: Error
|
|
||||||
|
|
||||||
auto& pal = *m_palettes[palette];
|
|
||||||
|
|
||||||
ostd::Color clrCol = pal.getColor(clearColor);
|
|
||||||
if (m_clearMemory)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < m_parent->m_windowHeight; ++y)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < m_parent->m_windowWidth; ++x)
|
|
||||||
{
|
|
||||||
m_pixels[x + y * m_parent->m_windowWidth] = clrCol.asInteger();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_clearMemory = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::Color fgCol;
|
|
||||||
ostd::Color bgCol;
|
|
||||||
uint16_t index = hw::VirtualBIOSVideo::tRegisters::VideoMemoryStart;
|
|
||||||
|
|
||||||
// if (m_clearMemory)
|
|
||||||
// {
|
|
||||||
// for (int32_t i = index; i < (index + (RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::CONSOLE_CHARS_V * 2)); i += 2)
|
|
||||||
// {
|
|
||||||
// m_biosVideo.write8((uint16_t)i, 0x00);
|
|
||||||
// m_biosVideo.write8((uint16_t)(i + 1), clearColor);
|
|
||||||
// }
|
|
||||||
// m_clearMemory = false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
for (int32_t i = index; i < (index + (RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::CONSOLE_CHARS_V * 2)); i += 2)
|
|
||||||
{
|
|
||||||
uint8_t character = m_biosVideo.read8((uint16_t)i);
|
|
||||||
uint8_t colors = m_biosVideo.read8((uint16_t)(i + 1));
|
|
||||||
uint8_t bgcol = (colors >> 4) & 0xF;
|
|
||||||
uint8_t fgcol = (colors & 0xF);
|
|
||||||
if (!isprint(character))
|
|
||||||
{
|
|
||||||
character = ' ';
|
|
||||||
fgCol = pal.getColor(fgcol);
|
|
||||||
bgCol = clrCol;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fgCol = pal.getColor(fgcol);
|
|
||||||
bgCol = pal.getColor(bgcol);
|
|
||||||
}
|
|
||||||
vout.bgcol(bgCol).col(fgCol).p((char)character).flush().bgcol(clrCol);
|
|
||||||
}
|
|
||||||
vout.refreshScreen();
|
|
||||||
m_cpu.handleInterrupt(data::InterruptCodes::BiosVideoScreenRefresh);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsoleWidtget::update(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsoleWidtget::fixedUpdate(void)
|
|
||||||
{
|
|
||||||
if (isInvalid()) return;
|
|
||||||
uint8_t signal = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::Signal);
|
|
||||||
switch (signal)
|
|
||||||
{
|
|
||||||
case tSignals::ClearScreen:
|
|
||||||
m_clearMemory = true;
|
|
||||||
break;
|
|
||||||
case tSignals::Continue: break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
m_biosVideo.write8(hw::VirtualBIOSVideo::tRegisters::Signal, tSignals::Continue);
|
|
||||||
drawConsole();
|
|
||||||
SDL_UpdateTexture(m_texture, NULL, m_pixels, getw() * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualConsoleWidtget::slowUpdate(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Widget.hpp"
|
|
||||||
|
|
||||||
#include "../../tools/SDLInclude.hpp"
|
|
||||||
|
|
||||||
#include "../../gui/VirtualConsoleOutputHandler.hpp"
|
|
||||||
#include "../../tools/GlobalData.hpp"
|
|
||||||
|
|
||||||
namespace dragon
|
|
||||||
{
|
|
||||||
namespace hw
|
|
||||||
{
|
|
||||||
class VirtualBIOSVideo;
|
|
||||||
class VirtualCPU;
|
|
||||||
}
|
|
||||||
class VirtualConsoleWidtget : public Widget
|
|
||||||
{
|
|
||||||
public: struct tSignals
|
|
||||||
{
|
|
||||||
inline static constexpr uint8_t Continue = 0x00;
|
|
||||||
inline static constexpr uint8_t ClearScreen = 0x01;
|
|
||||||
};
|
|
||||||
public:
|
|
||||||
inline VirtualConsoleWidtget(hw::VirtualBIOSVideo& biosVideo, hw::VirtualCPU& cpu) : m_biosVideo(biosVideo), m_cpu(cpu) { invalidate(); }
|
|
||||||
void init(void) override;
|
|
||||||
void draw(void) override;
|
|
||||||
void update(void) override;
|
|
||||||
void fixedUpdate(void) override;
|
|
||||||
void slowUpdate(void) override;
|
|
||||||
|
|
||||||
inline bool isInitialized(void) const { return m_initialized; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void drawConsole(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
dragon::VirtualConsoleOutputHandler vout;
|
|
||||||
|
|
||||||
// SDL_Window* m_window { nullptr };
|
|
||||||
// SDL_Renderer* m_renderer { nullptr };
|
|
||||||
// SDL_Texture* m_screenTexture { nullptr };
|
|
||||||
// SDL_Surface* m_fontSurface { nullptr };
|
|
||||||
|
|
||||||
// int32_t m_windowWidth { 0 };
|
|
||||||
// int32_t m_windowHeight { 0 };
|
|
||||||
|
|
||||||
// uint32_t* m_fontPixels { nullptr };
|
|
||||||
// uint32_t* m_screenPixels { nullptr };
|
|
||||||
|
|
||||||
uint32_t* m_pixels { nullptr };
|
|
||||||
SDL_Texture* m_texture;
|
|
||||||
|
|
||||||
// bool m_redrawConsole { true };
|
|
||||||
// float m_timeAccumulator { 0.0f };
|
|
||||||
// bool m_running { false };
|
|
||||||
|
|
||||||
// ostd::StringEditor m_title { "" };
|
|
||||||
// float m_redrawAccumulator { 0.0f };
|
|
||||||
bool m_initialized { false };
|
|
||||||
bool m_clearMemory { false };
|
|
||||||
|
|
||||||
hw::VirtualBIOSVideo& m_biosVideo;
|
|
||||||
hw::VirtualCPU& m_cpu;
|
|
||||||
std::vector<data::IBiosVideoPalette*> m_palettes;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <ostd/Geometry.hpp>
|
|
||||||
#include <ostd/BaseObject.hpp>
|
|
||||||
|
|
||||||
namespace dragon
|
|
||||||
{
|
|
||||||
class Window;
|
|
||||||
class Widget : public ostd::Rectangle, public ostd::BaseObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void __init(Window& parent) { m_parent = &parent; init(); }
|
|
||||||
virtual void draw(void) { }
|
|
||||||
virtual void update(void) { }
|
|
||||||
virtual void fixedUpdate(void) { }
|
|
||||||
virtual void slowUpdate(void) { }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void init(void) { }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Window* m_parent { nullptr };
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -68,7 +68,7 @@ namespace dragon
|
||||||
if (address >= region.startAddress && address <= region.endAddress)
|
if (address >= region.startAddress && address <= region.endAddress)
|
||||||
return ®ion;
|
return ®ion;
|
||||||
}
|
}
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::MM_RegionNotFound, ostd::StringEditor("Memory device not found for address: ").add(ostd::Utils::getHexStr(address, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::MM_RegionNotFound, ostd::String("Memory device not found for address: ").add(ostd::Utils::getHexStr(address, true, 2)));
|
||||||
return nullptr; //TODO: Error
|
return nullptr; //TODO: Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "IMemoryDevice.hpp"
|
#include "IMemoryDevice.hpp"
|
||||||
|
#include <ostd/String.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace dragon
|
namespace dragon
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include "VirtualCPU.hpp"
|
#include "VirtualCPU.hpp"
|
||||||
#include "../tools/GlobalData.hpp"
|
#include "../tools/GlobalData.hpp"
|
||||||
|
|
||||||
|
#include <ostd/Defines.hpp>
|
||||||
#include <ostd/Utils.hpp>
|
#include <ostd/Utils.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
@ -10,8 +11,8 @@ namespace dragon
|
||||||
{
|
{
|
||||||
VirtualCPU::VirtualCPU(IMemoryDevice& memory) : m_memory(memory)
|
VirtualCPU::VirtualCPU(IMemoryDevice& memory) : m_memory(memory)
|
||||||
{
|
{
|
||||||
writeRegister(data::Registers::SP, (uint16_t)(0xFFFF - 1 - 1));
|
writeRegister(data::Registers::SP, (uint16_t)(0xFFFF - 1));
|
||||||
writeRegister(data::Registers::FP, (uint16_t)(0xFFFF - 1 - 1));
|
writeRegister(data::Registers::FP, (uint16_t)(0xFFFF - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t VirtualCPU::readRegister(uint8_t reg)
|
int16_t VirtualCPU::readRegister(uint8_t reg)
|
||||||
|
|
@ -62,6 +63,11 @@ namespace dragon
|
||||||
|
|
||||||
void VirtualCPU::pushStackFrame(void)
|
void VirtualCPU::pushStackFrame(void)
|
||||||
{
|
{
|
||||||
|
if (m_debugModeEnabled)
|
||||||
|
{
|
||||||
|
__debug_store_stack_frame_string_on_push();
|
||||||
|
return;
|
||||||
|
}
|
||||||
uint16_t argStartAddr = readRegister(data::Registers::SP) + 2;
|
uint16_t argStartAddr = readRegister(data::Registers::SP) + 2;
|
||||||
uint16_t argCount = m_memory.read16(argStartAddr);
|
uint16_t argCount = m_memory.read16(argStartAddr);
|
||||||
if (argCount == 0)
|
if (argCount == 0)
|
||||||
|
|
@ -82,7 +88,8 @@ namespace dragon
|
||||||
pushToStack(readRegister(data::Registers::PP));
|
pushToStack(readRegister(data::Registers::PP));
|
||||||
pushToStack(readRegister(data::Registers::ACC));
|
pushToStack(readRegister(data::Registers::ACC));
|
||||||
pushToStack(readRegister(data::Registers::IP));
|
pushToStack(readRegister(data::Registers::IP));
|
||||||
pushToStack(m_stackFrameSize + 2);
|
pushToStack(readRegister(data::Registers::FP));
|
||||||
|
pushToStack(m_stackFrameSize);
|
||||||
|
|
||||||
writeRegister(data::Registers::PP, argStartAddr);
|
writeRegister(data::Registers::PP, argStartAddr);
|
||||||
writeRegister(data::Registers::FP, readRegister(data::Registers::SP));
|
writeRegister(data::Registers::FP, readRegister(data::Registers::SP));
|
||||||
|
|
@ -94,8 +101,9 @@ namespace dragon
|
||||||
uint16_t framePointerAddr = readRegister(data::Registers::FP);
|
uint16_t framePointerAddr = readRegister(data::Registers::FP);
|
||||||
writeRegister(data::Registers::SP, framePointerAddr);
|
writeRegister(data::Registers::SP, framePointerAddr);
|
||||||
m_stackFrameSize = popFromStack();
|
m_stackFrameSize = popFromStack();
|
||||||
uint16_t tmpStackFrameSize = m_stackFrameSize;
|
// uint16_t tmpStackFrameSize = m_stackFrameSize;
|
||||||
|
|
||||||
|
writeRegister(data::Registers::FP, popFromStack());
|
||||||
writeRegister(data::Registers::IP, popFromStack());
|
writeRegister(data::Registers::IP, popFromStack());
|
||||||
writeRegister(data::Registers::ACC, popFromStack());
|
writeRegister(data::Registers::ACC, popFromStack());
|
||||||
writeRegister(data::Registers::PP, popFromStack());
|
writeRegister(data::Registers::PP, popFromStack());
|
||||||
|
|
@ -112,9 +120,12 @@ namespace dragon
|
||||||
|
|
||||||
uint16_t nArgs = popFromStack();
|
uint16_t nArgs = popFromStack();
|
||||||
for (int32_t i = 0; i < nArgs; i++)
|
for (int32_t i = 0; i < nArgs; i++)
|
||||||
|
{
|
||||||
popFromStack();
|
popFromStack();
|
||||||
|
// writeRegister(data::Registers::FP, readRegister(data::Registers::FP) - 2);
|
||||||
|
}
|
||||||
|
|
||||||
writeRegister(data::Registers::FP, framePointerAddr + tmpStackFrameSize);
|
// writeRegister(data::Registers::FP, framePointerAddr + tmpStackFrameSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VirtualCPU::readFlag(uint8_t flg)
|
bool VirtualCPU::readFlag(uint8_t flg)
|
||||||
|
|
@ -134,7 +145,6 @@ namespace dragon
|
||||||
|
|
||||||
void VirtualCPU::handleInterrupt(uint8_t intValue)
|
void VirtualCPU::handleInterrupt(uint8_t intValue)
|
||||||
{
|
{
|
||||||
// std::cout << "Interrupt: " << ostd::Utils::getHexStr(intValue, true, 1) << "\n";
|
|
||||||
uint16_t entryPointer = data::MemoryMapAddresses::IntVector_Start + (intValue * 3);
|
uint16_t entryPointer = data::MemoryMapAddresses::IntVector_Start + (intValue * 3);
|
||||||
uint8_t interruptStatus = m_memory.read8(entryPointer);
|
uint8_t interruptStatus = m_memory.read8(entryPointer);
|
||||||
if (interruptStatus != 0xFF) return;
|
if (interruptStatus != 0xFF) return;
|
||||||
|
|
@ -664,6 +674,7 @@ namespace dragon
|
||||||
uint16_t subroutineAddr = fetch16();
|
uint16_t subroutineAddr = fetch16();
|
||||||
pushStackFrame();
|
pushStackFrame();
|
||||||
writeRegister(data::Registers::IP, subroutineAddr);
|
writeRegister(data::Registers::IP, subroutineAddr);
|
||||||
|
m_subroutineCounter++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case data::OpCodes::CallReg:
|
case data::OpCodes::CallReg:
|
||||||
|
|
@ -672,17 +683,22 @@ namespace dragon
|
||||||
uint16_t subroutineAddr = readRegister(regAddr);
|
uint16_t subroutineAddr = readRegister(regAddr);
|
||||||
pushStackFrame();
|
pushStackFrame();
|
||||||
writeRegister(data::Registers::IP, subroutineAddr);
|
writeRegister(data::Registers::IP, subroutineAddr);
|
||||||
|
m_subroutineCounter++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case data::OpCodes::Ret:
|
case data::OpCodes::Ret:
|
||||||
{
|
{
|
||||||
popStackFrame();
|
popStackFrame();
|
||||||
|
// m_subroutineCounter = ZERO(m_subroutineCounter - 1);
|
||||||
|
m_subroutineCounter--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case data::OpCodes::RetInt:
|
case data::OpCodes::RetInt:
|
||||||
{
|
{
|
||||||
m_isInInterruptHandler = false;
|
m_isInInterruptHandler = false;
|
||||||
popStackFrame();
|
popStackFrame();
|
||||||
|
// m_subroutineCounter = ZERO(m_subroutineCounter - 1);
|
||||||
|
m_subroutineCounter--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case data::OpCodes::Int:
|
case data::OpCodes::Int:
|
||||||
|
|
@ -691,11 +707,12 @@ namespace dragon
|
||||||
if (!readFlag(data::Flags::InterruptsEnabled))
|
if (!readFlag(data::Flags::InterruptsEnabled))
|
||||||
return true;
|
return true;
|
||||||
handleInterrupt(intValue);
|
handleInterrupt(intValue);
|
||||||
|
m_subroutineCounter++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::CPU_UnknownInstruction, ostd::StringEditor("Unknown instruction: ").add(ostd::Utils::getHexStr(inst, true, 1)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::CPU_UnknownInstruction, ostd::String("Unknown instruction: ").add(ostd::Utils::getHexStr(inst, true, 1)));
|
||||||
m_halt = true;
|
m_halt = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -703,5 +720,60 @@ namespace dragon
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VirtualCPU::__debug_store_stack_frame_string_on_push(void)
|
||||||
|
{
|
||||||
|
if (!m_debugModeEnabled) return;
|
||||||
|
ostd::String stackFrameString = "";
|
||||||
|
|
||||||
|
uint16_t argStartAddr = readRegister(data::Registers::SP) + 2;
|
||||||
|
uint16_t argCount = m_memory.read16(argStartAddr);
|
||||||
|
if (argCount == 0)
|
||||||
|
argStartAddr = 0;
|
||||||
|
else
|
||||||
|
argStartAddr += (argCount * 2);
|
||||||
|
|
||||||
|
stackFrameString.add("args: ").add(ostd::Utils::getHexStr(argStartAddr, true, 2)).add(", argc: ").add(argCount).add("\n");
|
||||||
|
|
||||||
|
pushToStack(readRegister(data::Registers::R1));
|
||||||
|
stackFrameString.add("R1: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R1), true, 2));
|
||||||
|
pushToStack(readRegister(data::Registers::R2));
|
||||||
|
stackFrameString.add(" R2: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R2), true, 2));
|
||||||
|
pushToStack(readRegister(data::Registers::R3));
|
||||||
|
stackFrameString.add(" R3: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R3), true, 2));
|
||||||
|
pushToStack(readRegister(data::Registers::R4));
|
||||||
|
stackFrameString.add(" R4: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R4), true, 2));
|
||||||
|
pushToStack(readRegister(data::Registers::R5));
|
||||||
|
stackFrameString.add(" R5: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R5), true, 2));
|
||||||
|
pushToStack(readRegister(data::Registers::R6));
|
||||||
|
stackFrameString.add(" R6: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R6), true, 2));
|
||||||
|
pushToStack(readRegister(data::Registers::R7));
|
||||||
|
stackFrameString.add(" R7: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R7), true, 2));
|
||||||
|
pushToStack(readRegister(data::Registers::R8));
|
||||||
|
stackFrameString.add(" R8: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R8), true, 2));
|
||||||
|
pushToStack(readRegister(data::Registers::R9));
|
||||||
|
stackFrameString.add(" R9: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R9), true, 2));
|
||||||
|
pushToStack(readRegister(data::Registers::R10));
|
||||||
|
stackFrameString.add(" R10: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R10), true, 2));
|
||||||
|
stackFrameString.add("\n");
|
||||||
|
pushToStack(readRegister(data::Registers::PP));
|
||||||
|
stackFrameString.add("PP: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::PP), true, 2));
|
||||||
|
pushToStack(readRegister(data::Registers::ACC));
|
||||||
|
stackFrameString.add(" ACC: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::ACC), true, 2));
|
||||||
|
pushToStack(readRegister(data::Registers::IP));
|
||||||
|
stackFrameString.add(" IP: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::IP), true, 2));
|
||||||
|
pushToStack(readRegister(data::Registers::FP));
|
||||||
|
stackFrameString.add(" FP: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::FP), true, 2));
|
||||||
|
stackFrameString.add("\n");
|
||||||
|
pushToStack(m_stackFrameSize);
|
||||||
|
stackFrameString.add("StackFrame: ").add(m_stackFrameSize).add(", ");
|
||||||
|
|
||||||
|
writeRegister(data::Registers::PP, argStartAddr);
|
||||||
|
writeRegister(data::Registers::FP, readRegister(data::Registers::SP));
|
||||||
|
stackFrameString.add("New FP: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::FP), true, 2));
|
||||||
|
m_stackFrameSize = 0;
|
||||||
|
|
||||||
|
m_debug_stackFrameStrings.push_back(stackFrameString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
#include <ostd/Bitfields.hpp>
|
#include <ostd/Bitfields.hpp>
|
||||||
#include "IMemoryDevice.hpp"
|
#include "IMemoryDevice.hpp"
|
||||||
|
|
||||||
|
#include "../debugger/Debugger.hpp"
|
||||||
|
|
||||||
namespace dragon
|
namespace dragon
|
||||||
{
|
{
|
||||||
class DragonRuntime;
|
class DragonRuntime;
|
||||||
|
|
@ -36,6 +38,11 @@ namespace dragon
|
||||||
inline bool isHalted(void) const { return m_halt; }
|
inline bool isHalted(void) const { return m_halt; }
|
||||||
inline uint8_t getCurrentInstruction(void) const { return m_currentInst; }
|
inline uint8_t getCurrentInstruction(void) const { return m_currentInst; }
|
||||||
inline bool isInDebugBreakPoint(void) const { return m_isDebugBreakPoint; }
|
inline bool isInDebugBreakPoint(void) const { return m_isDebugBreakPoint; }
|
||||||
|
inline bool isInSubRoutine(void) const { return m_subroutineCounter > 0; }
|
||||||
|
inline int32_t getSubRoutineCounter(void) const { return m_subroutineCounter; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void __debug_store_stack_frame_string_on_push(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int16_t m_registers[20];
|
int16_t m_registers[20];
|
||||||
|
|
@ -47,8 +54,14 @@ namespace dragon
|
||||||
bool m_biosMode { true };
|
bool m_biosMode { true };
|
||||||
bool m_isInInterruptHandler { false };
|
bool m_isInInterruptHandler { false };
|
||||||
bool m_isDebugBreakPoint { false };
|
bool m_isDebugBreakPoint { false };
|
||||||
|
bool m_debugModeEnabled { false };
|
||||||
|
int32_t m_subroutineCounter { 0 };
|
||||||
|
|
||||||
|
std::vector<ostd::String> m_debug_stackFrameStrings;
|
||||||
|
|
||||||
friend class dragon::DragonRuntime;
|
friend class dragon::DragonRuntime;
|
||||||
|
friend class dragon::Debugger::Display;
|
||||||
|
friend class dragon::Debugger;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,10 +9,10 @@ namespace dragon
|
||||||
{
|
{
|
||||||
void VirtualHardDrive::init(const ostd::String& dataFilePath)
|
void VirtualHardDrive::init(const ostd::String& dataFilePath)
|
||||||
{
|
{
|
||||||
m_dataFile.open(dataFilePath, std::ios::out | std::ios::in | std::ios::binary);
|
m_dataFile.open(dataFilePath.cpp_str(), std::ios::out | std::ios::in | std::ios::binary);
|
||||||
if(!m_dataFile)
|
if(!m_dataFile)
|
||||||
{
|
{
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::HardDrive_UnableToMount, ostd::StringEditor("Unable to mount virtual HardDrive: ").add(dataFilePath).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::HardDrive_UnableToMount, ostd::String("Unable to mount virtual HardDrive: ").add(dataFilePath));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_fileSize = m_dataFile.tellg();
|
m_fileSize = m_dataFile.tellg();
|
||||||
|
|
|
||||||
|
|
@ -15,22 +15,22 @@ namespace dragon
|
||||||
bool loaded = ostd::Utils::loadByteStreamFromFile(biosFilePath, m_bios);
|
bool loaded = ostd::Utils::loadByteStreamFromFile(biosFilePath, m_bios);
|
||||||
if (!loaded)
|
if (!loaded)
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_FailedToLoad, "Failed to load BIOS data.");
|
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_FailedToLoad, "Failed to load BIOS data.");
|
||||||
if (m_bios.size() != 1024)
|
if (m_bios.size() != 4096) //TODO: Hardcoded
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidSize, ostd::StringEditor("Invalid BIOS size: ").add(ostd::Utils::getHexStr(m_bios.size(), true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidSize, ostd::String("Invalid BIOS size: ").add(ostd::Utils::getHexStr(m_bios.size(), true, 2)));
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t VirtualBIOS::read8(uint16_t addr)
|
int8_t VirtualBIOS::read8(uint16_t addr)
|
||||||
{
|
{
|
||||||
if (addr >= m_bios.size())
|
if (addr >= m_bios.size())
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, ostd::StringEditor("Invalid Byte BIOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, ostd::String("Invalid Byte BIOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
return m_bios[addr];
|
return m_bios[addr];
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t VirtualBIOS::read16(uint16_t addr)
|
int16_t VirtualBIOS::read16(uint16_t addr)
|
||||||
{
|
{
|
||||||
if (addr >= m_bios.size() - 1)
|
if (addr >= m_bios.size() - 1)
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, ostd::StringEditor("Invalid Word BIOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, ostd::String("Invalid Word BIOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
return ((m_bios[addr + 0] << 8) & 0xFF00U)
|
return ((m_bios[addr + 0] << 8) & 0xFF00U)
|
||||||
| ( m_bios[addr + 1] & 0x00FFU);
|
| ( m_bios[addr + 1] & 0x00FFU);
|
||||||
}
|
}
|
||||||
|
|
@ -66,14 +66,14 @@ namespace dragon
|
||||||
int8_t InterruptVector::read8(uint16_t addr)
|
int8_t InterruptVector::read8(uint16_t addr)
|
||||||
{
|
{
|
||||||
if (addr >= m_data.size())
|
if (addr >= m_data.size())
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::StringEditor("Invalid Byte IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::String("Invalid Byte IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
return m_data[addr];
|
return m_data[addr];
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t InterruptVector::read16(uint16_t addr)
|
int16_t InterruptVector::read16(uint16_t addr)
|
||||||
{
|
{
|
||||||
if (addr >= m_data.size() - 1)
|
if (addr >= m_data.size() - 1)
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::StringEditor("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::String("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
return ((m_data[addr + 0] << 8) & 0xFF00U)
|
return ((m_data[addr + 0] << 8) & 0xFF00U)
|
||||||
| ( m_data[addr + 1] & 0x00FFU);
|
| ( m_data[addr + 1] & 0x00FFU);
|
||||||
}
|
}
|
||||||
|
|
@ -81,7 +81,7 @@ namespace dragon
|
||||||
int8_t InterruptVector::write8(uint16_t addr, int8_t value)
|
int8_t InterruptVector::write8(uint16_t addr, int8_t value)
|
||||||
{
|
{
|
||||||
if (addr >= m_data.size())
|
if (addr >= m_data.size())
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::StringEditor("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::String("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
m_data[addr] = value;
|
m_data[addr] = value;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +89,7 @@ namespace dragon
|
||||||
int16_t InterruptVector::write16(uint16_t addr, int16_t value)
|
int16_t InterruptVector::write16(uint16_t addr, int16_t value)
|
||||||
{
|
{
|
||||||
if (addr >= m_data.size() - 1)
|
if (addr >= m_data.size() - 1)
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::StringEditor("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::String("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
m_data[addr + 0] = (value >> 8) & 0xFF;
|
m_data[addr + 0] = (value >> 8) & 0xFF;
|
||||||
m_data[addr + 1] = value & 0xFF;
|
m_data[addr + 1] = value & 0xFF;
|
||||||
return value;
|
return value;
|
||||||
|
|
@ -179,14 +179,14 @@ namespace dragon
|
||||||
int8_t VirtualBootloader::read8(uint16_t addr)
|
int8_t VirtualBootloader::read8(uint16_t addr)
|
||||||
{
|
{
|
||||||
if (addr >= m_mbr.size())
|
if (addr >= m_mbr.size())
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, ostd::StringEditor("Invalid Byte MBR location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, ostd::String("Invalid Byte MBR location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
return m_mbr[addr];
|
return m_mbr[addr];
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t VirtualBootloader::read16(uint16_t addr)
|
int16_t VirtualBootloader::read16(uint16_t addr)
|
||||||
{
|
{
|
||||||
if (addr >= m_mbr.size() - 1)
|
if (addr >= m_mbr.size() - 1)
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, ostd::StringEditor("Invalid Word MBR location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, ostd::String("Invalid Word MBR location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
return ((m_mbr[addr + 0] << 8) & 0xFF00U)
|
return ((m_mbr[addr + 0] << 8) & 0xFF00U)
|
||||||
| ( m_mbr[addr + 1] & 0x00FFU);
|
| ( m_mbr[addr + 1] & 0x00FFU);
|
||||||
}
|
}
|
||||||
|
|
@ -194,7 +194,7 @@ namespace dragon
|
||||||
int8_t VirtualBootloader::write8(uint16_t addr, int8_t value)
|
int8_t VirtualBootloader::write8(uint16_t addr, int8_t value)
|
||||||
{
|
{
|
||||||
if (addr >= m_mbr.size())
|
if (addr >= m_mbr.size())
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::StringEditor("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::String("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
m_mbr[addr] = value;
|
m_mbr[addr] = value;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
@ -202,7 +202,7 @@ namespace dragon
|
||||||
int16_t VirtualBootloader::write16(uint16_t addr, int16_t value)
|
int16_t VirtualBootloader::write16(uint16_t addr, int16_t value)
|
||||||
{
|
{
|
||||||
if (addr >= m_mbr.size() - 1)
|
if (addr >= m_mbr.size() - 1)
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::StringEditor("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::String("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
m_mbr[addr + 0] = (value >> 8) & 0xFF;
|
m_mbr[addr + 0] = (value >> 8) & 0xFF;
|
||||||
m_mbr[addr + 1] = value & 0xFF;
|
m_mbr[addr + 1] = value & 0xFF;
|
||||||
return value;
|
return value;
|
||||||
|
|
@ -216,57 +216,6 @@ namespace dragon
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VirtualBIOSVideo::VirtualBIOSVideo(VirtualRAM& memory) : m_memory(memory)
|
|
||||||
{
|
|
||||||
intptr_t iMemPtr = reinterpret_cast<intptr_t>(memory.getByteStream()->data());
|
|
||||||
iMemPtr += data::MemoryMapAddresses::BIOSVideo_Start;
|
|
||||||
m_dataPtr = reinterpret_cast<ostd::Byte*>(iMemPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
int8_t VirtualBIOSVideo::read8(uint16_t addr)
|
|
||||||
{
|
|
||||||
if (addr >= m_size)
|
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::BIOSVideo_InvalidAddress, ostd::StringEditor("Invalid read Byte BiosVideo location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
|
||||||
return m_dataPtr[addr];
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t VirtualBIOSVideo::read16(uint16_t addr)
|
|
||||||
{
|
|
||||||
if (addr >= m_size - 1)
|
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::BIOSVideo_InvalidAddress, ostd::StringEditor("Invalid read Word BiosVideo location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
|
||||||
return ((m_dataPtr[addr + 0] << 8) & 0xFF00U)
|
|
||||||
| ( m_dataPtr[addr + 1] & 0x00FFU);
|
|
||||||
}
|
|
||||||
|
|
||||||
int8_t VirtualBIOSVideo::write8(uint16_t addr, int8_t value)
|
|
||||||
{
|
|
||||||
if (addr >= m_size)
|
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::BIOSVideo_InvalidAddress, ostd::StringEditor("Invalid read Byte BiosVideo location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
|
||||||
m_dataPtr[addr] = value;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t VirtualBIOSVideo::write16(uint16_t addr, int16_t value)
|
|
||||||
{
|
|
||||||
if (addr >= m_size - 1)
|
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::BIOSVideo_InvalidAddress, ostd::StringEditor("Invalid read Word BiosVideo location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
|
||||||
m_dataPtr[addr + 0] = (value >> 8) & 0xFF;
|
|
||||||
m_dataPtr[addr + 1] = value & 0xFF;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::ByteStream* VirtualBIOSVideo::getByteStream(void)
|
|
||||||
{
|
|
||||||
m_dataCopy.clear();
|
|
||||||
m_dataCopy.insert(m_dataCopy.end(), &m_dataPtr[0], &m_dataPtr[m_size]);
|
|
||||||
return &m_dataCopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace interface
|
namespace interface
|
||||||
{
|
{
|
||||||
Disk::Disk(MemoryMapper& memory, VirtualCPU& cpu) : m_memory(memory), m_cpu(cpu)
|
Disk::Disk(MemoryMapper& memory, VirtualCPU& cpu) : m_memory(memory), m_cpu(cpu)
|
||||||
|
|
@ -556,7 +505,7 @@ namespace dragon
|
||||||
void CMOS::init(const ostd::String& cmosFilePath)
|
void CMOS::init(const ostd::String& cmosFilePath)
|
||||||
{
|
{
|
||||||
m_size = data::MemoryMapAddresses::CMOS_End - data::MemoryMapAddresses::CMOS_Start + 1;
|
m_size = data::MemoryMapAddresses::CMOS_End - data::MemoryMapAddresses::CMOS_Start + 1;
|
||||||
m_dataFile.open(cmosFilePath, std::ios::out | std::ios::in | std::ios::binary);
|
m_dataFile.open(cmosFilePath.cpp_str(), std::ios::out | std::ios::in | std::ios::binary);
|
||||||
if(!m_dataFile)
|
if(!m_dataFile)
|
||||||
{
|
{
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_UnableToMount, "Unable to mount virtual CMOS chip.");
|
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_UnableToMount, "Unable to mount virtual CMOS chip.");
|
||||||
|
|
@ -568,7 +517,7 @@ namespace dragon
|
||||||
m_dataFile.seekg( 0, std::ios::beg );
|
m_dataFile.seekg( 0, std::ios::beg );
|
||||||
if (m_fileSize != m_size)
|
if (m_fileSize != m_size)
|
||||||
{
|
{
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidSize, ostd::StringEditor("Invalid virtual CMOS chhip size: ").addi(m_fileSize).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidSize, ostd::String("Invalid virtual CMOS chhip size: ").add(m_fileSize));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
|
|
@ -583,7 +532,7 @@ namespace dragon
|
||||||
}
|
}
|
||||||
if (addr >= m_size)
|
if (addr >= m_size)
|
||||||
{
|
{
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::StringEditor("Invalid Byte CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::String("Invalid Byte CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int8_t value = 0;
|
int8_t value = 0;
|
||||||
|
|
@ -601,7 +550,7 @@ namespace dragon
|
||||||
}
|
}
|
||||||
if (addr >= m_size - 1)
|
if (addr >= m_size - 1)
|
||||||
{
|
{
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::StringEditor("Invalid Word CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::String("Invalid Word CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int8_t b1 = read8(addr);
|
int8_t b1 = read8(addr);
|
||||||
|
|
@ -619,7 +568,7 @@ namespace dragon
|
||||||
}
|
}
|
||||||
if (addr >= m_size)
|
if (addr >= m_size)
|
||||||
{
|
{
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::StringEditor("Invalid Byte CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::String("Invalid Byte CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
m_dataFile.seekp(addr);
|
m_dataFile.seekp(addr);
|
||||||
|
|
@ -636,7 +585,7 @@ namespace dragon
|
||||||
}
|
}
|
||||||
if (addr >= m_size - 1)
|
if (addr >= m_size - 1)
|
||||||
{
|
{
|
||||||
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::StringEditor("Invalid Word CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
|
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::String("Invalid Word CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int8_t b1 = (value >> 8) & 0xFF;
|
int8_t b1 = (value >> 8) & 0xFF;
|
||||||
|
|
|
||||||
|
|
@ -86,34 +86,6 @@ namespace dragon
|
||||||
private:
|
private:
|
||||||
ostd::ByteStream m_mbr;
|
ostd::ByteStream m_mbr;
|
||||||
};
|
};
|
||||||
class VirtualBIOSVideo : public IMemoryDevice
|
|
||||||
{
|
|
||||||
public: struct tRegisters
|
|
||||||
{
|
|
||||||
inline static constexpr uint16_t ClearColor = 0x00;
|
|
||||||
inline static constexpr uint16_t Palette = 0x01;
|
|
||||||
inline static constexpr uint16_t UseTransparencyOn0x5 = 0x02;
|
|
||||||
inline static constexpr uint16_t Signal = 0x03;
|
|
||||||
|
|
||||||
inline static constexpr uint16_t VideoMemoryStart = 0x003C;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
VirtualBIOSVideo(VirtualRAM& memory);
|
|
||||||
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:
|
|
||||||
uint16_t m_baseAddress { data::MemoryMapAddresses::BIOSVideo_Start };
|
|
||||||
uint16_t m_size { (data::MemoryMapAddresses::BIOSVideo_End + 1) - data::MemoryMapAddresses::BIOSVideo_Start };
|
|
||||||
ostd::Byte* m_dataPtr { nullptr };
|
|
||||||
ostd::ByteStream m_dataCopy;
|
|
||||||
VirtualRAM& m_memory;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace interface
|
namespace interface
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,13 @@ namespace dragon
|
||||||
auto lines = file.getLines();
|
auto lines = file.getLines();
|
||||||
for (auto& line : lines)
|
for (auto& line : lines)
|
||||||
{
|
{
|
||||||
ostd::StringEditor lineEdit = line;
|
ostd::String lineEdit = line;
|
||||||
if (!lineEdit.contains("=")) continue; //TODO: Warning
|
if (!lineEdit.contains("=")) continue; //TODO: Warning
|
||||||
auto tokens = lineEdit.tokenize("=");
|
auto tokens = lineEdit.tokenize("=");
|
||||||
if (tokens.count() != 2) continue; //TODO: Warning
|
if (tokens.count() != 2) continue; //TODO: Warning
|
||||||
lineEdit = tokens.next();
|
lineEdit = tokens.next();
|
||||||
lineEdit = lineEdit.toLower();
|
lineEdit = lineEdit.toLower();
|
||||||
if (lineEdit.str() == "disks")
|
if (lineEdit == "disks")
|
||||||
{
|
{
|
||||||
lineEdit = tokens.next();
|
lineEdit = tokens.next();
|
||||||
tokens = lineEdit.tokenize(",");
|
tokens = lineEdit.tokenize(",");
|
||||||
|
|
@ -27,18 +27,18 @@ namespace dragon
|
||||||
while (tokens.hasNext())
|
while (tokens.hasNext())
|
||||||
{
|
{
|
||||||
lineEdit = tokens.next();
|
lineEdit = tokens.next();
|
||||||
config.vdisk_paths[disk_nr++] = lineEdit.str();
|
config.vdisk_paths[disk_nr++] = lineEdit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (lineEdit.str() == "bios")
|
else if (lineEdit == "bios")
|
||||||
{
|
{
|
||||||
lineEdit = tokens.next();
|
lineEdit = tokens.next();
|
||||||
config.bios_path = lineEdit.str();
|
config.bios_path = lineEdit;
|
||||||
}
|
}
|
||||||
else if (lineEdit.str() == "cmos")
|
else if (lineEdit == "cmos")
|
||||||
{
|
{
|
||||||
lineEdit = tokens.next();
|
lineEdit = tokens.next();
|
||||||
config.cmos_path = lineEdit.str();
|
config.cmos_path = lineEdit;
|
||||||
}
|
}
|
||||||
else continue; //TODO: Warning
|
else continue; //TODO: Warning
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ostd/Types.hpp>
|
#include <ostd/String.hpp>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
namespace dragon
|
namespace dragon
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,44 @@
|
||||||
#include "DragonRuntime.hpp"
|
#include "DragonRuntime.hpp"
|
||||||
|
#include <ostd/Defines.hpp>
|
||||||
|
#include "../gui/RawTextRenderer.hpp"
|
||||||
|
|
||||||
namespace dragon
|
namespace dragon
|
||||||
{
|
{
|
||||||
void DragonRuntime::printRegisters(dragon::hw::VirtualCPU& cpu)
|
void DragonRuntime::printRegisters(dragon::hw::VirtualCPU& cpu)
|
||||||
{
|
{
|
||||||
out.col("green").p("IP: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::IP), true, 2));
|
out.fg("green").p("IP: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::IP), true, 2).cpp_str());
|
||||||
out.p(" ");
|
out.p(" ");
|
||||||
out.col("yellow").p("R1: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R1), true, 2));
|
out.fg("yellow").p("R1: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R1), true, 2).cpp_str());
|
||||||
out.p(" ");
|
out.p(" ");
|
||||||
out.col("yellow").p("R2: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R2), true, 2)).nl();
|
out.fg("yellow").p("R2: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R2), true, 2).cpp_str()).nl();
|
||||||
|
|
||||||
out.col("green").p("SP: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::SP), true, 2));
|
out.fg("green").p("SP: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::SP), true, 2).cpp_str());
|
||||||
out.p(" ");
|
out.p(" ");
|
||||||
out.col("yellow").p("R3: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R3), true, 2));
|
out.fg("yellow").p("R3: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R3), true, 2).cpp_str());
|
||||||
out.p(" ");
|
out.p(" ");
|
||||||
out.col("yellow").p("R4: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R4), true, 2)).nl();
|
out.fg("yellow").p("R4: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R4), true, 2).cpp_str()).nl();
|
||||||
|
|
||||||
out.col("green").p("FP: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::FP), true, 2));
|
out.fg("green").p("FP: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::FP), true, 2).cpp_str());
|
||||||
out.p(" ");
|
out.p(" ");
|
||||||
out.col("yellow").p("R5: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R5), true, 2));
|
out.fg("yellow").p("R5: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R5), true, 2).cpp_str());
|
||||||
out.p(" ");
|
out.p(" ");
|
||||||
out.col("yellow").p("R6: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R6), true, 2)).nl();
|
out.fg("yellow").p("R6: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R6), true, 2).cpp_str()).nl();
|
||||||
|
|
||||||
out.col("green").p("RV: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::RV), true, 2));
|
out.fg("green").p("RV: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::RV), true, 2).cpp_str());
|
||||||
out.p(" ");
|
out.p(" ");
|
||||||
out.col("yellow").p("R7: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R7), true, 2));
|
out.fg("yellow").p("R7: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R7), true, 2).cpp_str());
|
||||||
out.p(" ");
|
out.p(" ");
|
||||||
out.col("yellow").p("R8: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R8), true, 2)).nl();
|
out.fg("yellow").p("R8: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R8), true, 2).cpp_str()).nl();
|
||||||
|
|
||||||
out.col("green").p("PP: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::PP), true, 2));
|
out.fg("green").p("PP: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::PP), true, 2).cpp_str());
|
||||||
out.p(" ");
|
out.p(" ");
|
||||||
out.col("yellow").p("R9: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R9), true, 2));
|
out.fg("yellow").p("R9: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R9), true, 2).cpp_str());
|
||||||
out.p(" ");
|
out.p(" ");
|
||||||
out.col("yellow").p("R10: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R10), true, 2)).nl();
|
out.fg("yellow").p("R10: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R10), true, 2).cpp_str()).nl();
|
||||||
|
|
||||||
out.col("green").p("ACC: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::ACC), true, 2));
|
out.fg("green").p("ACC: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::ACC), true, 2).cpp_str());
|
||||||
out.p(" ");
|
out.p(" ");
|
||||||
out.col("yellow").p("FL: ").col("white").p(ostd::Utils::getBinStr(cpu.readRegister(dragon::data::Registers::FL), true, 2));
|
out.fg("yellow").p("FL: ").fg("white").p(ostd::Utils::getBinStr(cpu.readRegister(dragon::data::Registers::FL), true, 2).cpp_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DragonRuntime::processErrors(void)
|
void DragonRuntime::processErrors(void)
|
||||||
|
|
@ -44,7 +46,7 @@ namespace dragon
|
||||||
while (dragon::data::ErrorHandler::hasError())
|
while (dragon::data::ErrorHandler::hasError())
|
||||||
{
|
{
|
||||||
auto err = dragon::data::ErrorHandler::popError();
|
auto err = dragon::data::ErrorHandler::popError();
|
||||||
out.nl().col(ostd::legacy::ConsoleCol::Red).p("Error ").p(ostd::Utils::getHexStr(err.code, true, 8)).p(": ").p(err.text).nl();
|
out.nl().fg(ostd::ConsoleColors::Red).p("Error ").p(ostd::Utils::getHexStr(err.code, true, 8).cpp_str()).p(": ").p(err.text.cpp_str()).nl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,23 +63,29 @@ namespace dragon
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t DragonRuntime::initMachine(const ostd::String& configFilePath, bool verbose, bool trackMachineInfoDiff, bool hideVirtualDisplay)
|
int32_t DragonRuntime::initMachine(const ostd::String& configFilePath,
|
||||||
|
bool verbose,
|
||||||
|
bool trackMachineInfoDiff,
|
||||||
|
bool hideVirtualDisplay,
|
||||||
|
bool trackCallStack,
|
||||||
|
bool debugModeEnabled)
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
out.p("Loading machine config: ").p(configFilePath).nl();
|
out.p("Loading machine config: ").p(configFilePath.cpp_str()).nl();
|
||||||
machine_config = dragon::MachineConfigLoader::loadConfig(configFilePath);
|
machine_config = dragon::MachineConfigLoader::loadConfig(configFilePath);
|
||||||
if (!machine_config.isValid()) return 1; //TODO: Error
|
if (!machine_config.isValid()) return 1; //TODO: Error
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
out.p(" Initializing virtual display:").nl();
|
out.p(" Initializing virtual display:").nl();
|
||||||
vDisplay.initialize(800, 600, "font.bmp");
|
vDisplay.initialize(800, 600, "DragonVM", "font.bmp");
|
||||||
vDisplay.addWidget(vConsWidg);
|
int32_t w = RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::FONT_CHAR_W; //60 * 16;
|
||||||
vDisplay.setSize(vConsWidg.getw(), vConsWidg.geth());
|
int32_t h = RawTextRenderer::CONSOLE_CHARS_V * RawTextRenderer::FONT_CHAR_H; //60 * 9;
|
||||||
|
vDisplay.setSize(w, h);
|
||||||
if (hideVirtualDisplay)
|
if (hideVirtualDisplay)
|
||||||
vDisplay.hide();
|
vDisplay.hide();
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
out.p(" Done. (").pi((int)vConsWidg.getw()).p("x").pi((int)vConsWidg.geth()).p(")");
|
out.p(" Done. (").p(w).p("x").p(h).p(")");
|
||||||
if (hideVirtualDisplay)
|
if (hideVirtualDisplay)
|
||||||
out.p(" - HIDDEN").nl();
|
out.p(" - HIDDEN").nl();
|
||||||
else
|
else
|
||||||
|
|
@ -92,114 +100,105 @@ namespace dragon
|
||||||
vDisks[disk_path.first] = dragon::hw::VirtualHardDrive(disk_path.second);
|
vDisks[disk_path.first] = dragon::hw::VirtualHardDrive(disk_path.second);
|
||||||
vDiskInterface.connectDisk(vDisks[disk_path.first]);
|
vDiskInterface.connectDisk(vDisks[disk_path.first]);
|
||||||
if (verbose)
|
if (verbose)
|
||||||
out.p(" Disk").pi(disk_path.first).p(" connected: ").p(disk_path.second).nl();
|
out.p(" Disk").p(disk_path.first).p(" connected: ").p(disk_path.second.cpp_str()).nl();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
out.p(" Loading vBIOS file: ").p(machine_config.bios_path).nl();
|
out.p(" Loading vBIOS file: ").p(machine_config.bios_path.cpp_str()).nl();
|
||||||
vBIOS.init(machine_config.bios_path);
|
vBIOS.init(machine_config.bios_path);
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
out.p(" Loading vCMOS file: ").p(machine_config.cmos_path).nl();
|
out.p(" Loading vCMOS file: ").p(machine_config.cmos_path.cpp_str()).nl();
|
||||||
vCMOS.init(machine_config.cmos_path);
|
vCMOS.init(machine_config.cmos_path);
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
out.p(" Initializing Memory Mapper:").nl();
|
out.p(" Initializing Memory Mapper:").nl();
|
||||||
out.p(" vBIOS: ");
|
out.p(" vBIOS: ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::BIOS_Start, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::BIOS_Start, true, 2).cpp_str());
|
||||||
out.p(" to ");
|
out.p(" to ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::BIOS_End, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::BIOS_End, true, 2).cpp_str());
|
||||||
out.p(" (remap=false)").nl();
|
out.p(" (remap=false)").nl();
|
||||||
}
|
}
|
||||||
memMap.mapDevice(vBIOS, dragon::data::MemoryMapAddresses::BIOS_Start, dragon::data::MemoryMapAddresses::BIOS_End, false, "vBIOS");
|
memMap.mapDevice(vBIOS, dragon::data::MemoryMapAddresses::BIOS_Start, dragon::data::MemoryMapAddresses::BIOS_End, false, "vBIOS");
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
out.p(" vCMOS: ");
|
out.p(" vCMOS: ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::CMOS_Start, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::CMOS_Start, true, 2).cpp_str());
|
||||||
out.p(" to ");
|
out.p(" to ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::CMOS_End, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::CMOS_End, true, 2).cpp_str());
|
||||||
out.p(" (remap=true)").nl();
|
out.p(" (remap=true)").nl();
|
||||||
}
|
}
|
||||||
memMap.mapDevice(vCMOS, dragon::data::MemoryMapAddresses::CMOS_Start, dragon::data::MemoryMapAddresses::CMOS_End, true, "vCMOS");
|
memMap.mapDevice(vCMOS, dragon::data::MemoryMapAddresses::CMOS_Start, dragon::data::MemoryMapAddresses::CMOS_End, true, "vCMOS");
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
out.p(" intVec: ");
|
out.p(" intVec: ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::IntVector_Start, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::IntVector_Start, true, 2).cpp_str());
|
||||||
out.p(" to ");
|
out.p(" to ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::IntVector_End, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::IntVector_End, true, 2).cpp_str());
|
||||||
out.p(" (remap=true)").nl();
|
out.p(" (remap=true)").nl();
|
||||||
}
|
}
|
||||||
memMap.mapDevice(intVec, dragon::data::MemoryMapAddresses::IntVector_Start, dragon::data::MemoryMapAddresses::IntVector_End, true, "intVec");
|
memMap.mapDevice(intVec, dragon::data::MemoryMapAddresses::IntVector_Start, dragon::data::MemoryMapAddresses::IntVector_End, true, "intVec");
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
out.p(" vKeyboard: ");
|
out.p(" vKeyboard: ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Keyboard_Start, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Keyboard_Start, true, 2).cpp_str());
|
||||||
out.p(" to ");
|
out.p(" to ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Keyboard_End, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Keyboard_End, true, 2).cpp_str());
|
||||||
out.p(" (remap=false)").nl();
|
out.p(" (remap=false)").nl();
|
||||||
}
|
}
|
||||||
memMap.mapDevice(vKeyboard, dragon::data::MemoryMapAddresses::Keyboard_Start, dragon::data::MemoryMapAddresses::Keyboard_End, false, "vKeyboard");
|
memMap.mapDevice(vKeyboard, dragon::data::MemoryMapAddresses::Keyboard_Start, dragon::data::MemoryMapAddresses::Keyboard_End, false, "vKeyboard");
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
out.p(" vMouse: ");
|
out.p(" vMouse: ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Mouse_Start, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Mouse_Start, true, 2).cpp_str());
|
||||||
out.p(" to ");
|
out.p(" to ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Mouse_End, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Mouse_End, true, 2).cpp_str());
|
||||||
out.p(" (remap=false)").nl();
|
out.p(" (remap=false)").nl();
|
||||||
}
|
}
|
||||||
memMap.mapDevice(vMouse, dragon::data::MemoryMapAddresses::Mouse_Start, dragon::data::MemoryMapAddresses::Mouse_End, false, "vMouse");
|
memMap.mapDevice(vMouse, dragon::data::MemoryMapAddresses::Mouse_Start, dragon::data::MemoryMapAddresses::Mouse_End, false, "vMouse");
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
|
||||||
out.p(" vBIOSVideo: ");
|
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::BIOSVideo_Start, true, 2));
|
|
||||||
out.p(" to ");
|
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::BIOSVideo_End, true, 2));
|
|
||||||
out.p(" (remap=true)").nl();
|
|
||||||
}
|
|
||||||
memMap.mapDevice(vBIOSVideo, dragon::data::MemoryMapAddresses::BIOSVideo_Start, dragon::data::MemoryMapAddresses::BIOSVideo_End, true, "vBIOSVideo");
|
|
||||||
if (verbose)
|
|
||||||
{
|
{
|
||||||
out.p(" vMBR: ");
|
out.p(" vMBR: ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::MBR_Start, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::MBR_Start, true, 2).cpp_str());
|
||||||
out.p(" to ");
|
out.p(" to ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::MBR_End, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::MBR_End, true, 2).cpp_str());
|
||||||
out.p(" (remap=true)").nl();
|
out.p(" (remap=true)").nl();
|
||||||
}
|
}
|
||||||
memMap.mapDevice(vMBR, dragon::data::MemoryMapAddresses::MBR_Start, dragon::data::MemoryMapAddresses::MBR_End, true, "vMBR");
|
memMap.mapDevice(vMBR, dragon::data::MemoryMapAddresses::MBR_Start, dragon::data::MemoryMapAddresses::MBR_End, true, "vMBR");
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
out.p(" vDiskInterface: ");
|
out.p(" vDiskInterface: ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::DiskInterface_Start, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::DiskInterface_Start, true, 2).cpp_str());
|
||||||
out.p(" to ");
|
out.p(" to ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::DiskInterface_End, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::DiskInterface_End, true, 2).cpp_str());
|
||||||
out.p(" (remap=true)").nl();
|
out.p(" (remap=true)").nl();
|
||||||
}
|
}
|
||||||
memMap.mapDevice(vDiskInterface, dragon::data::MemoryMapAddresses::DiskInterface_Start, dragon::data::MemoryMapAddresses::DiskInterface_End, true, "vDiskInterface");
|
memMap.mapDevice(vDiskInterface, dragon::data::MemoryMapAddresses::DiskInterface_Start, dragon::data::MemoryMapAddresses::DiskInterface_End, true, "vDiskInterface");
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
out.p(" vGraphicsInterface: ");
|
out.p(" vGraphicsInterface: ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::VideoCardInterface_Start, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::VideoCardInterface_Start, true, 2).cpp_str());
|
||||||
out.p(" to ");
|
out.p(" to ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::VideoCardInterface_End, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::VideoCardInterface_End, true, 2).cpp_str());
|
||||||
out.p(" (remap=true)").nl();
|
out.p(" (remap=true)").nl();
|
||||||
}
|
}
|
||||||
memMap.mapDevice(vGraphicsInterface, dragon::data::MemoryMapAddresses::VideoCardInterface_Start, dragon::data::MemoryMapAddresses::VideoCardInterface_End, true, "vGraphicsInterface");
|
memMap.mapDevice(vGraphicsInterface, dragon::data::MemoryMapAddresses::VideoCardInterface_Start, dragon::data::MemoryMapAddresses::VideoCardInterface_End, true, "vGraphicsInterface");
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
out.p(" vSerialInterface: ");
|
out.p(" vSerialInterface: ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::SerialInterface_Start, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::SerialInterface_Start, true, 2).cpp_str());
|
||||||
out.p(" to ");
|
out.p(" to ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::SerialInterface_End, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::SerialInterface_End, true, 2).cpp_str());
|
||||||
out.p(" (remap=true)").nl();
|
out.p(" (remap=true)").nl();
|
||||||
}
|
}
|
||||||
memMap.mapDevice(vSerialInterface, dragon::data::MemoryMapAddresses::SerialInterface_Start, dragon::data::MemoryMapAddresses::SerialInterface_End, true, "vSerialInterface");
|
memMap.mapDevice(vSerialInterface, dragon::data::MemoryMapAddresses::SerialInterface_Start, dragon::data::MemoryMapAddresses::SerialInterface_End, true, "vSerialInterface");
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
out.p(" RAM: ");
|
out.p(" RAM: ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Memory_Start, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Memory_Start, true, 2).cpp_str());
|
||||||
out.p(" to ");
|
out.p(" to ");
|
||||||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Memory_End, true, 2));
|
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Memory_End, true, 2).cpp_str());
|
||||||
out.p(" (remap=false)").nl();
|
out.p(" (remap=false)").nl();
|
||||||
}
|
}
|
||||||
memMap.mapDevice(ram, dragon::data::MemoryMapAddresses::Memory_Start, dragon::data::MemoryMapAddresses::Memory_End, false, "RAM");
|
memMap.mapDevice(ram, dragon::data::MemoryMapAddresses::Memory_Start, dragon::data::MemoryMapAddresses::Memory_End, false, "RAM");
|
||||||
|
|
@ -209,17 +208,22 @@ namespace dragon
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
out.p(" Initializing vCPU reset sequence:").nl();
|
out.p(" Initializing vCPU reset sequence:").nl();
|
||||||
out.p(" BIOSVideo default colors: ").p(ostd::Utils::getHexStr(default_bios_video_color)).nl();
|
// out.p(" BIOSVideo default colors: ").p(ostd::Utils::getHexStr(default_bios_video_color).cpp_str()).nl();
|
||||||
}
|
}
|
||||||
memMap.write8(dragon::data::MemoryMapAddresses::BIOSVideo_Start, default_bios_video_color);
|
// memMap.write8(dragon::data::MemoryMapAddresses::BIOSVideo_Start, default_bios_video_color);
|
||||||
|
|
||||||
uint16_t reset_ip_addr = 0x0000;
|
uint16_t reset_ip_addr = 0x0000;
|
||||||
if (verbose)
|
if (verbose)
|
||||||
out.p(" Reset IP register: ").p(ostd::Utils::getHexStr(reset_ip_addr, true, 2)).nl();
|
out.p(" Reset IP register: ").p(ostd::Utils::getHexStr(reset_ip_addr, true, 2).cpp_str()).nl();
|
||||||
cpu.writeRegister(dragon::data::Registers::IP, reset_ip_addr);
|
cpu.writeRegister(dragon::data::Registers::IP, reset_ip_addr);
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
out.p(" Debug mode enabled: ").p(STR_BOOL(debugModeEnabled)).nl();
|
||||||
|
cpu.m_debugModeEnabled = debugModeEnabled;
|
||||||
|
|
||||||
out.nl().nl();
|
out.nl().nl();
|
||||||
s_trackMachineInfo = trackMachineInfoDiff;
|
s_trackMachineInfo = trackMachineInfoDiff;
|
||||||
|
s_trackCallStack = trackCallStack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,9 +234,11 @@ namespace dragon
|
||||||
uint8_t currentInst = 0x00;
|
uint8_t currentInst = 0x00;
|
||||||
uint32_t instSize = 0;
|
uint32_t instSize = 0;
|
||||||
ostd::ByteStream& ramData = *ram.getByteStream();
|
ostd::ByteStream& ramData = *ram.getByteStream();
|
||||||
while ((running || vDiskInterface.isBusy()) && cycleCounter++ < 2048)
|
// while ((running || vDiskInterface.isBusy()) && cycleCounter++ < 2048)
|
||||||
|
while (running || vDiskInterface.isBusy())
|
||||||
{
|
{
|
||||||
out.clear();
|
if (basic_debug)
|
||||||
|
out.clear();
|
||||||
uint16_t addr = cpu.readRegister(dragon::data::Registers::IP);
|
uint16_t addr = cpu.readRegister(dragon::data::Registers::IP);
|
||||||
uint16_t spAddr = cpu.readRegister(dragon::data::Registers::SP);
|
uint16_t spAddr = cpu.readRegister(dragon::data::Registers::SP);
|
||||||
running = cpu.execute() && vDisplay.isRunning();
|
running = cpu.execute() && vDisplay.isRunning();
|
||||||
|
|
@ -244,13 +250,12 @@ namespace dragon
|
||||||
{
|
{
|
||||||
instSize = dragon::data::OpCodes::getInstructionSIze(currentInst);
|
instSize = dragon::data::OpCodes::getInstructionSIze(currentInst);
|
||||||
ostd::Utils::printByteStream(ramData, dragon::data::MemoryMapAddresses::Memory_Start, 16, 10, newOut, addr, instSize, " MEMORY");
|
ostd::Utils::printByteStream(ramData, dragon::data::MemoryMapAddresses::Memory_Start, 16, 10, newOut, addr, instSize, " MEMORY");
|
||||||
ostd::Utils::printByteStream(*vBIOSVideo.getByteStream(), 0x0000, 16, 16, newOut, -1, 1, " Bios Video");
|
|
||||||
printRegisters(cpu);
|
printRegisters(cpu);
|
||||||
out.nl().col("yellow").p("Current Instruction: ").col("white").p(ostd::Utils::getHexStr(currentInst, true, 1));
|
out.nl().fg("yellow").p("Current Instruction: ").fg("white").p(ostd::Utils::getHexStr(currentInst, true, 1).cpp_str());
|
||||||
out.nl();
|
out.nl();
|
||||||
out.col(ostd::legacy::ConsoleCol::Magenta).p("######### Reached Break Point at ");
|
out.fg(ostd::ConsoleColors::Magenta).p("######### Reached Break Point at ");
|
||||||
out.p(ostd::Utils::getHexStr(addr, true, 2));
|
out.p(ostd::Utils::getHexStr(addr, true, 2).cpp_str());
|
||||||
out.nl().resetColors();
|
out.nl().reset();
|
||||||
std::cin.get();
|
std::cin.get();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -263,13 +268,12 @@ namespace dragon
|
||||||
}
|
}
|
||||||
instSize = dragon::data::OpCodes::getInstructionSIze(currentInst);
|
instSize = dragon::data::OpCodes::getInstructionSIze(currentInst);
|
||||||
ostd::Utils::printByteStream(ramData, dragon::data::MemoryMapAddresses::Memory_Start, 16, 10, newOut, addr, instSize, " MEMORY");
|
ostd::Utils::printByteStream(ramData, dragon::data::MemoryMapAddresses::Memory_Start, 16, 10, newOut, addr, instSize, " MEMORY");
|
||||||
ostd::Utils::printByteStream(*vBIOSVideo.getByteStream(), 0x0000, 16, 16, newOut, -1, 1, " Bios Video");
|
|
||||||
printRegisters(cpu);
|
printRegisters(cpu);
|
||||||
out.nl().col("yellow").p("Current Instruction: ").col("white").p(ostd::Utils::getHexStr(currentInst, true, 1));
|
out.nl().fg("yellow").p("Current Instruction: ").fg("white").p(ostd::Utils::getHexStr(currentInst, true, 1).cpp_str());
|
||||||
out.nl();
|
out.nl();
|
||||||
out.col(ostd::legacy::ConsoleCol::Red).p("######### Error occurred at ");
|
out.fg(ostd::ConsoleColors::Red).p("######### Error occurred at ");
|
||||||
out.p(ostd::Utils::getHexStr(addr, true, 2));
|
out.p(ostd::Utils::getHexStr(addr, true, 2).cpp_str());
|
||||||
out.nl().resetColors();
|
out.nl().reset();
|
||||||
processErrors();
|
processErrors();
|
||||||
std::cin.get();
|
std::cin.get();
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -280,6 +284,7 @@ namespace dragon
|
||||||
bool DragonRuntime::runStep(std::vector<uint16_t> trackedAddresses)
|
bool DragonRuntime::runStep(std::vector<uint16_t> trackedAddresses)
|
||||||
{
|
{
|
||||||
__get_machine_footprint(&s_machineInfo, trackedAddresses, true);
|
__get_machine_footprint(&s_machineInfo, trackedAddresses, true);
|
||||||
|
__track_call_stack(&s_machineInfo);
|
||||||
bool running = cpu.execute() && vDisplay.isRunning();
|
bool running = cpu.execute() && vDisplay.isRunning();
|
||||||
vDisplay.update();
|
vDisplay.update();
|
||||||
vDiskInterface.cycleStep();
|
vDiskInterface.cycleStep();
|
||||||
|
|
@ -332,11 +337,13 @@ namespace dragon
|
||||||
uint8_t instSize = data::OpCodes::getInstructionSIze(memMap.read8(instAddr));
|
uint8_t instSize = data::OpCodes::getInstructionSIze(memMap.read8(instAddr));
|
||||||
ostd::String opCode = data::OpCodes::getOpCodeString(memMap.read8(instAddr));
|
ostd::String opCode = data::OpCodes::getOpCodeString(memMap.read8(instAddr));
|
||||||
uint16_t stackFrameSize = cpu.m_stackFrameSize;
|
uint16_t stackFrameSize = cpu.m_stackFrameSize;
|
||||||
|
int32_t subRoutineCounter = cpu.m_subroutineCounter;
|
||||||
|
|
||||||
|
|
||||||
bool debugBreak = cpu.m_isDebugBreakPoint;
|
bool debugBreak = cpu.m_isDebugBreakPoint;
|
||||||
bool intHandler = cpu.m_isInInterruptHandler;
|
bool intHandler = cpu.m_isInInterruptHandler;
|
||||||
bool biosMode = cpu.m_biosMode;
|
bool biosMode = cpu.m_biosMode;
|
||||||
|
bool isInSubRoutine = cpu.isInSubRoutine();
|
||||||
|
|
||||||
if (previous)
|
if (previous)
|
||||||
{
|
{
|
||||||
|
|
@ -344,6 +351,7 @@ namespace dragon
|
||||||
minfo.previousInstructionFootprintSize = instSize;
|
minfo.previousInstructionFootprintSize = instSize;
|
||||||
minfo.previousInstructionStackFrameSize = stackFrameSize;
|
minfo.previousInstructionStackFrameSize = stackFrameSize;
|
||||||
minfo.previousInstructionOpCode = opCode;
|
minfo.previousInstructionOpCode = opCode;
|
||||||
|
minfo.previousSubRoutineCounter = subRoutineCounter;
|
||||||
|
|
||||||
for (int8_t i = 0; i < instSize; i++)
|
for (int8_t i = 0; i < instSize; i++)
|
||||||
minfo.previousInstructionFootprint[i] = memMap.read8(instAddr + i);
|
minfo.previousInstructionFootprint[i] = memMap.read8(instAddr + i);
|
||||||
|
|
@ -357,6 +365,7 @@ namespace dragon
|
||||||
minfo.previousInstructionDebugBreak = debugBreak;
|
minfo.previousInstructionDebugBreak = debugBreak;
|
||||||
minfo.previousInstructionInterruptHandler = intHandler;
|
minfo.previousInstructionInterruptHandler = intHandler;
|
||||||
minfo.previousInstructionBiosMode = biosMode;
|
minfo.previousInstructionBiosMode = biosMode;
|
||||||
|
minfo.previousIsInSubRoutine = isInSubRoutine;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -364,6 +373,7 @@ namespace dragon
|
||||||
minfo.currentInstructionFootprintSize = instSize;
|
minfo.currentInstructionFootprintSize = instSize;
|
||||||
minfo.currentInstructionStackFrameSize = stackFrameSize;
|
minfo.currentInstructionStackFrameSize = stackFrameSize;
|
||||||
minfo.currentInstructionOpCode = opCode;
|
minfo.currentInstructionOpCode = opCode;
|
||||||
|
minfo.currentSubRoutineCounter = subRoutineCounter;
|
||||||
|
|
||||||
for (int8_t i = 0; i < instSize; i++)
|
for (int8_t i = 0; i < instSize; i++)
|
||||||
minfo.currentInstructionFootprint[i] = memMap.read8(instAddr + i);
|
minfo.currentInstructionFootprint[i] = memMap.read8(instAddr + i);
|
||||||
|
|
@ -377,6 +387,43 @@ namespace dragon
|
||||||
minfo.currentInstructionDebugBreak = debugBreak;
|
minfo.currentInstructionDebugBreak = debugBreak;
|
||||||
minfo.currentInstructionInterruptHandler = intHandler;
|
minfo.currentInstructionInterruptHandler = intHandler;
|
||||||
minfo.currentInstructionBiosMode = biosMode;
|
minfo.currentInstructionBiosMode = biosMode;
|
||||||
|
minfo.currentIsInSubRoutine = isInSubRoutine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DragonRuntime::__track_call_stack(tMachineDebugInfo* machineInfo)
|
||||||
|
{
|
||||||
|
if (!s_trackCallStack || machineInfo == nullptr) return;
|
||||||
|
auto& minfo = *machineInfo;
|
||||||
|
|
||||||
|
bool interrupts_enabled = cpu.readFlag(data::Flags::InterruptsEnabled);
|
||||||
|
|
||||||
|
uint16_t instAddr = cpu.readRegister(data::Registers::IP);
|
||||||
|
uint8_t inst = memMap.read8(instAddr);
|
||||||
|
|
||||||
|
if (inst == data::OpCodes::CallImm)
|
||||||
|
{
|
||||||
|
uint16_t call_addr = memMap.read16(instAddr + 1);
|
||||||
|
minfo.callStack.push_back({ "CALL IMM", call_addr });
|
||||||
|
}
|
||||||
|
else if (inst == data::OpCodes::CallReg)
|
||||||
|
{
|
||||||
|
uint8_t reg_addr = memMap.read8(instAddr + 1);
|
||||||
|
uint16_t call_addr = cpu.readRegister(reg_addr);
|
||||||
|
minfo.callStack.push_back({ "CALL REG", call_addr });
|
||||||
|
}
|
||||||
|
else if (interrupts_enabled && inst == data::OpCodes::Int)
|
||||||
|
{
|
||||||
|
uint8_t int_num = memMap.read8(instAddr + 1);
|
||||||
|
minfo.callStack.push_back({ "INT", int_num });
|
||||||
|
}
|
||||||
|
else if (inst == data::OpCodes::Ret)
|
||||||
|
{
|
||||||
|
minfo.callStack.push_back({ "RET", 0x0000 });
|
||||||
|
}
|
||||||
|
else if (interrupts_enabled && inst == data::OpCodes::RetInt)
|
||||||
|
{
|
||||||
|
minfo.callStack.push_back({ "RET INT", 0x0000 });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../gui/Window.hpp"
|
#include "../gui/Window.hpp"
|
||||||
#include "../gui/widgets/VirtualConsoleWidget.hpp"
|
|
||||||
|
|
||||||
#include "../hardware/VirtualCPU.hpp"
|
#include "../hardware/VirtualCPU.hpp"
|
||||||
#include "../hardware/MemoryMapper.hpp"
|
#include "../hardware/MemoryMapper.hpp"
|
||||||
|
|
@ -17,6 +16,11 @@ namespace dragon
|
||||||
{
|
{
|
||||||
class DragonRuntime
|
class DragonRuntime
|
||||||
{
|
{
|
||||||
|
public: struct tCallInfo {
|
||||||
|
ostd::String info;
|
||||||
|
uint16_t addr;
|
||||||
|
};
|
||||||
|
|
||||||
public: struct tMachineDebugInfo {
|
public: struct tMachineDebugInfo {
|
||||||
inline tMachineDebugInfo(void) { }
|
inline tMachineDebugInfo(void) { }
|
||||||
|
|
||||||
|
|
@ -26,6 +30,8 @@ namespace dragon
|
||||||
int8_t currentInstructionFootprintSize { 0x00 };
|
int8_t currentInstructionFootprintSize { 0x00 };
|
||||||
uint16_t previousInstructionStackFrameSize { 0x00 };
|
uint16_t previousInstructionStackFrameSize { 0x00 };
|
||||||
uint16_t currentInstructionStackFrameSize { 0x00 };
|
uint16_t currentInstructionStackFrameSize { 0x00 };
|
||||||
|
int32_t previousSubRoutineCounter { 0x00000000 };
|
||||||
|
int32_t currentSubRoutineCounter { 0x00000000 };
|
||||||
|
|
||||||
ostd::String previousInstructionOpCode { "" };
|
ostd::String previousInstructionOpCode { "" };
|
||||||
ostd::String currentInstructionOpCode { "" };
|
ostd::String currentInstructionOpCode { "" };
|
||||||
|
|
@ -45,14 +51,24 @@ namespace dragon
|
||||||
bool currentInstructionInterruptHandler { false };
|
bool currentInstructionInterruptHandler { false };
|
||||||
bool previousInstructionBiosMode { false };
|
bool previousInstructionBiosMode { false };
|
||||||
bool currentInstructionBiosMode { false };
|
bool currentInstructionBiosMode { false };
|
||||||
|
bool previousIsInSubRoutine { false };
|
||||||
|
bool currentIsInSubRoutine { false };
|
||||||
|
|
||||||
bool vCPUHalt { false };
|
bool vCPUHalt { false };
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<tCallInfo> callStack;
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
static void printRegisters(dragon::hw::VirtualCPU& cpu);
|
static void printRegisters(dragon::hw::VirtualCPU& cpu);
|
||||||
static void processErrors(void);
|
static void processErrors(void);
|
||||||
static std::vector<data::ErrorHandler::tError> getErrorList(void);
|
static std::vector<data::ErrorHandler::tError> getErrorList(void);
|
||||||
static int32_t initMachine(const ostd::String& configFilePath, bool verbose = false, bool trackMachineInfoDiff = false, bool hideVirtualDisplay = false);
|
static int32_t initMachine(const ostd::String& configFilePath,
|
||||||
|
bool verbose = false,
|
||||||
|
bool trackMachineInfoDiff = false,
|
||||||
|
bool hideVirtualDisplay = false,
|
||||||
|
bool rackCallStack = false,
|
||||||
|
bool debugModeEnabled = false);
|
||||||
static void runMachine(int32_t cycleLimit, bool basic_debug, bool step_exec);
|
static void runMachine(int32_t cycleLimit, bool basic_debug, bool step_exec);
|
||||||
static bool runStep(std::vector<uint16_t> trackedAddresses = { });
|
static bool runStep(std::vector<uint16_t> trackedAddresses = { });
|
||||||
static void forceLoad(const ostd::String& filePath, uint16_t loadAddress);
|
static void forceLoad(const ostd::String& filePath, uint16_t loadAddress);
|
||||||
|
|
@ -62,9 +78,10 @@ namespace dragon
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void __get_machine_footprint(tMachineDebugInfo* machineInfo, std::vector<uint16_t> trackedAddresses, bool previous);
|
static void __get_machine_footprint(tMachineDebugInfo* machineInfo, std::vector<uint16_t> trackedAddresses, bool previous);
|
||||||
|
static void __track_call_stack(tMachineDebugInfo* machineInfo);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline static ostd::legacy::ConsoleOutputHandler out;
|
inline static ostd::ConsoleOutputHandler out;
|
||||||
|
|
||||||
inline static dragon::hw::MemoryMapper memMap;
|
inline static dragon::hw::MemoryMapper memMap;
|
||||||
inline static dragon::hw::VirtualCPU cpu { memMap };
|
inline static dragon::hw::VirtualCPU cpu { memMap };
|
||||||
|
|
@ -72,7 +89,6 @@ namespace dragon
|
||||||
inline static dragon::hw::InterruptVector intVec;
|
inline static dragon::hw::InterruptVector intVec;
|
||||||
inline static dragon::hw::VirtualBIOS vBIOS;
|
inline static dragon::hw::VirtualBIOS vBIOS;
|
||||||
inline static dragon::hw::interface::CMOS vCMOS;
|
inline static dragon::hw::interface::CMOS vCMOS;
|
||||||
inline static dragon::hw::VirtualBIOSVideo vBIOSVideo { ram };
|
|
||||||
inline static dragon::hw::VirtualBootloader vMBR;
|
inline static dragon::hw::VirtualBootloader vMBR;
|
||||||
inline static dragon::hw::VirtualKeyboard vKeyboard;
|
inline static dragon::hw::VirtualKeyboard vKeyboard;
|
||||||
inline static dragon::hw::VirtualMouse vMouse;
|
inline static dragon::hw::VirtualMouse vMouse;
|
||||||
|
|
@ -83,12 +99,12 @@ namespace dragon
|
||||||
inline static std::unordered_map<int32_t, dragon::hw::VirtualHardDrive> vDisks;
|
inline static std::unordered_map<int32_t, dragon::hw::VirtualHardDrive> vDisks;
|
||||||
|
|
||||||
inline static dragon::Window vDisplay;
|
inline static dragon::Window vDisplay;
|
||||||
inline static dragon::VirtualConsoleWidtget vConsWidg { vBIOSVideo, cpu };
|
|
||||||
|
|
||||||
inline static dragon::tMachineConfig machine_config;
|
inline static dragon::tMachineConfig machine_config;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline static tMachineDebugInfo s_machineInfo;
|
inline static tMachineDebugInfo s_machineInfo;
|
||||||
inline static bool s_trackMachineInfo { false };
|
inline static bool s_trackMachineInfo { false };
|
||||||
|
inline static bool s_trackCallStack { false };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -29,14 +29,14 @@ int main(int argc, char** argv)
|
||||||
args.machine_config_path = argv[1];
|
args.machine_config_path = argv[1];
|
||||||
for (int32_t i = 2; i < argc; i++)
|
for (int32_t i = 2; i < argc; i++)
|
||||||
{
|
{
|
||||||
ostd::StringEditor edit(argv[i]);
|
ostd::String edit(argv[i]);
|
||||||
if (edit.str() == "--debug")
|
if (edit == "--debug")
|
||||||
args.basic_debug = true;
|
args.basic_debug = true;
|
||||||
else if (edit.str() == "--step")
|
else if (edit == "--step")
|
||||||
args.step_exec = true;
|
args.step_exec = true;
|
||||||
else if (edit.str() == "--verbose-load")
|
else if (edit == "--verbose-load")
|
||||||
args.verbose_load = true;
|
args.verbose_load = true;
|
||||||
else if (edit.str() == "--limit-cycles")
|
else if (edit == "--limit-cycles")
|
||||||
{
|
{
|
||||||
if (i == argc - 1)
|
if (i == argc - 1)
|
||||||
break; //TODO: Warning
|
break; //TODO: Warning
|
||||||
|
|
@ -46,7 +46,7 @@ int main(int argc, char** argv)
|
||||||
continue; //TODO: Error
|
continue; //TODO: Error
|
||||||
args.cycle_limit = (int32_t)edit.toInt();
|
args.cycle_limit = (int32_t)edit.toInt();
|
||||||
}
|
}
|
||||||
else if (edit.str() == "--force-load")
|
else if (edit == "--force-load")
|
||||||
{
|
{
|
||||||
if ((argc - 1) - i < 2)
|
if ((argc - 1) - i < 2)
|
||||||
break; //TODO: Warning
|
break; //TODO: Warning
|
||||||
|
|
|
||||||
|
|
@ -79,36 +79,33 @@ namespace dragon
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline static constexpr uint16_t BIOS_Start = 0x0000;
|
inline static constexpr uint16_t BIOS_Start = 0x0000;
|
||||||
inline static constexpr uint16_t BIOS_End = 0x03FF;
|
inline static constexpr uint16_t BIOS_End = 0x0FFF;
|
||||||
|
|
||||||
inline static constexpr uint16_t CMOS_Start = 0x0400;
|
inline static constexpr uint16_t CMOS_Start = 0x1000;
|
||||||
inline static constexpr uint16_t CMOS_End = 0x047F;
|
inline static constexpr uint16_t CMOS_End = 0x107F;
|
||||||
|
|
||||||
inline static constexpr uint16_t IntVector_Start = 0x0480;
|
inline static constexpr uint16_t IntVector_Start = 0x1080;
|
||||||
inline static constexpr uint16_t IntVector_End = 0x067F;
|
inline static constexpr uint16_t IntVector_End = 0x127F;
|
||||||
|
|
||||||
inline static constexpr uint16_t Keyboard_Start = 0x0680;
|
inline static constexpr uint16_t Keyboard_Start = 0x1280;
|
||||||
inline static constexpr uint16_t Keyboard_End = 0x075F;
|
inline static constexpr uint16_t Keyboard_End = 0x135F;
|
||||||
|
|
||||||
inline static constexpr uint16_t Mouse_Start = 0x0760;
|
inline static constexpr uint16_t Mouse_Start = 0x1360;
|
||||||
inline static constexpr uint16_t Mouse_End = 0x077F;
|
inline static constexpr uint16_t Mouse_End = 0x137F;
|
||||||
|
|
||||||
inline static constexpr uint16_t BIOSVideo_Start = 0x0780;
|
inline static constexpr uint16_t MBR_Start = 0x1380;
|
||||||
inline static constexpr uint16_t BIOSVideo_End = 0x167F;
|
inline static constexpr uint16_t MBR_End = 0x157F;
|
||||||
|
|
||||||
inline static constexpr uint16_t MBR_Start = 0x1680;
|
inline static constexpr uint16_t DiskInterface_Start = 0x1580;
|
||||||
inline static constexpr uint16_t MBR_End = 0x187F;
|
inline static constexpr uint16_t DiskInterface_End = 0x15FF;
|
||||||
|
|
||||||
inline static constexpr uint16_t DiskInterface_Start = 0x1880;
|
inline static constexpr uint16_t VideoCardInterface_Start = 0x1600;
|
||||||
inline static constexpr uint16_t DiskInterface_End = 0x18FF;
|
inline static constexpr uint16_t VideoCardInterface_End = 0x16FF;
|
||||||
|
|
||||||
inline static constexpr uint16_t VideoCardInterface_Start = 0x1900;
|
inline static constexpr uint16_t SerialInterface_Start = 0x1700;
|
||||||
inline static constexpr uint16_t VideoCardInterface_End = 0x19FF;
|
inline static constexpr uint16_t SerialInterface_End = 0x173F;
|
||||||
|
|
||||||
inline static constexpr uint16_t SerialInterface_Start = 0x1A00;
|
inline static constexpr uint16_t Memory_Start = 0x1740;
|
||||||
inline static constexpr uint16_t SerialInterface_End = 0x1A3F;
|
|
||||||
|
|
||||||
inline static constexpr uint16_t Memory_Start = 0x1A40;
|
|
||||||
inline static constexpr uint16_t Memory_End = 0xFFFF;
|
inline static constexpr uint16_t Memory_End = 0xFFFF;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -190,9 +187,9 @@ namespace dragon
|
||||||
inline static constexpr uint8_t Keyboard = 0x10;
|
inline static constexpr uint8_t Keyboard = 0x10;
|
||||||
inline static constexpr uint8_t Mouse = 0x11;
|
inline static constexpr uint8_t Mouse = 0x11;
|
||||||
inline static constexpr uint8_t BiosInterrupt = 0x20;
|
inline static constexpr uint8_t BiosInterrupt = 0x20;
|
||||||
|
inline static constexpr uint8_t BiosVideoInterrupt = 0x30;
|
||||||
|
|
||||||
inline static constexpr uint8_t DiskInterfaceFFinished = 0x80;
|
inline static constexpr uint8_t DiskInterfaceFFinished = 0x80;
|
||||||
inline static constexpr uint8_t BiosVideoScreenRefresh = 0x81;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class OpCodes
|
class OpCodes
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,5 @@
|
||||||
#undef __linux__
|
#undef __linux__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
|
|
@ -18,11 +18,11 @@ constexpr int ErrorLoadProgUnableToLoadDataFile = 8;
|
||||||
|
|
||||||
constexpr int ErrorNoError = 0;
|
constexpr int ErrorNoError = 0;
|
||||||
|
|
||||||
ostd::legacy::ConsoleOutputHandler out;
|
ostd::ConsoleOutputHandler out;
|
||||||
|
|
||||||
bool createVirtualHardDrive(uint32_t sizeInBytes, const ostd::String& dataFilePath)
|
bool createVirtualHardDrive(uint32_t sizeInBytes, const ostd::String& dataFilePath)
|
||||||
{
|
{
|
||||||
std::ofstream rf(dataFilePath, std::ios::out | std::ios::binary);
|
std::ofstream rf(dataFilePath.cpp_str(), std::ios::out | std::ios::binary);
|
||||||
if(!rf) return false;
|
if(!rf) return false;
|
||||||
ostd::ByteStream stream;
|
ostd::ByteStream stream;
|
||||||
for (int32_t i = 0; i < sizeInBytes; i++)
|
for (int32_t i = 0; i < sizeInBytes; i++)
|
||||||
|
|
@ -36,46 +36,46 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
{
|
{
|
||||||
out.col("red").p("Error: too few arguments.").nl();
|
out.fg("red").p("Error: too few arguments.").nl();
|
||||||
out.col("red").p(" Usage: ./dtools <tool_name> [...arguments...]").resetColors().nl();
|
out.fg("red").p(" Usage: ./dtools <tool_name> [...arguments...]").reset().nl();
|
||||||
return ErrorTopLevelTooFewArgs;
|
return ErrorTopLevelTooFewArgs;
|
||||||
}
|
}
|
||||||
ostd::StringEditor tool = argv[1];
|
ostd::String tool = argv[1];
|
||||||
tool = tool.trim().toLower();
|
tool = tool.trim().toLower();
|
||||||
|
|
||||||
//Nex Virtual Disk
|
//Nex Virtual Disk
|
||||||
if (tool.str() == "new-vdisk")
|
if (tool == "new-vdisk")
|
||||||
{
|
{
|
||||||
if (argc < 4)
|
if (argc < 4)
|
||||||
{
|
{
|
||||||
out.col("red").p("Error: too few arguments.").nl();
|
out.fg("red").p("Error: too few arguments.").nl();
|
||||||
out.col("red").p(" Usage: ./dtools new-vdisk <destination_file> <size_in_bytes>").resetColors().nl();
|
out.fg("red").p(" Usage: ./dtools new-vdisk <destination_file> <size_in_bytes>").reset().nl();
|
||||||
return ErrorNewVDiskTooFewArgs;
|
return ErrorNewVDiskTooFewArgs;
|
||||||
}
|
}
|
||||||
ostd::String dest = argv[2];
|
ostd::String dest = argv[2];
|
||||||
ostd::String str_size = argv[3];
|
ostd::String str_size = argv[3];
|
||||||
if (!ostd::Utils::isInt(str_size))
|
if (!ostd::Utils::isInt(str_size))
|
||||||
{
|
{
|
||||||
out.col("red").p("Error: <size_in_bytes> parameter must be integer.").resetColors().nl();
|
out.fg("red").p("Error: <size_in_bytes> parameter must be integer.").reset().nl();
|
||||||
return ErrorNewVDiskNonIntSize;
|
return ErrorNewVDiskNonIntSize;
|
||||||
}
|
}
|
||||||
bool result = createVirtualHardDrive(ostd::Utils::strToInt(str_size), dest);
|
bool result = createVirtualHardDrive(ostd::Utils::strToInt(str_size), dest);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
out.col("red").p("Error: Unable to create virtual disk.").resetColors().nl();
|
out.fg("red").p("Error: Unable to create virtual disk.").reset().nl();
|
||||||
return ErrorNewVDiskUnable;
|
return ErrorNewVDiskUnable;
|
||||||
}
|
}
|
||||||
out.col("green").p("Success. Virtual disk created:").nl();
|
out.fg("green").p("Success. Virtual disk created:").nl();
|
||||||
out.p(" Path: ").p(dest).nl();
|
out.p(" Path: ").p(dest.cpp_str()).nl();
|
||||||
out.p(" Size: ").p(str_size).resetColors().nl();
|
out.p(" Size: ").p(str_size.cpp_str()).reset().nl();
|
||||||
}
|
}
|
||||||
//Load Program
|
//Load Program
|
||||||
else if (tool.str() == "load-program")
|
else if (tool == "load-program")
|
||||||
{
|
{
|
||||||
if (argc < 5)
|
if (argc < 5)
|
||||||
{
|
{
|
||||||
out.col("red").p("Error: too few arguments.").nl();
|
out.fg("red").p("Error: too few arguments.").nl();
|
||||||
out.col("red").p(" Usage: ./dtools load-program <virtual_disk_file> <data_file> <destination_address>").resetColors().nl();
|
out.fg("red").p(" Usage: ./dtools load-program <virtual_disk_file> <data_file> <destination_address>").reset().nl();
|
||||||
return ErrorLoadProgTooFewArgs;
|
return ErrorLoadProgTooFewArgs;
|
||||||
}
|
}
|
||||||
ostd::String vdisk_file = argv[2];
|
ostd::String vdisk_file = argv[2];
|
||||||
|
|
@ -83,19 +83,19 @@ int main(int argc, char** argv)
|
||||||
ostd::String str_addr = argv[4];
|
ostd::String str_addr = argv[4];
|
||||||
if (!ostd::Utils::isInt(str_addr))
|
if (!ostd::Utils::isInt(str_addr))
|
||||||
{
|
{
|
||||||
out.col("red").p("Error: <destination_address> parameter must be integer.").resetColors().nl();
|
out.fg("red").p("Error: <destination_address> parameter must be integer.").reset().nl();
|
||||||
return ErrorLoadProgNonIntAddr;
|
return ErrorLoadProgNonIntAddr;
|
||||||
}
|
}
|
||||||
dragon::hw::VirtualHardDrive vHDD(vdisk_file);
|
dragon::hw::VirtualHardDrive vHDD(vdisk_file);
|
||||||
if (!vHDD.isInitialized())
|
if (!vHDD.isInitialized())
|
||||||
{
|
{
|
||||||
out.col("red").p("Error: Unable to load virtual disk.").resetColors().nl();
|
out.fg("red").p("Error: Unable to load virtual disk.").reset().nl();
|
||||||
return ErrorLoadProgUnableToLoadVDisk;
|
return ErrorLoadProgUnableToLoadVDisk;
|
||||||
}
|
}
|
||||||
ostd::ByteStream code;
|
ostd::ByteStream code;
|
||||||
if (!ostd::Utils::loadByteStreamFromFile(data_file, code))
|
if (!ostd::Utils::loadByteStreamFromFile(data_file, code))
|
||||||
{
|
{
|
||||||
out.col("red").p("Error: Unable to load data file.").resetColors().nl();
|
out.fg("red").p("Error: Unable to load data file.").reset().nl();
|
||||||
return ErrorLoadProgUnableToLoadDataFile;
|
return ErrorLoadProgUnableToLoadDataFile;
|
||||||
}
|
}
|
||||||
int16_t index = 0;
|
int16_t index = 0;
|
||||||
|
|
@ -106,16 +106,16 @@ int main(int argc, char** argv)
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
vHDD.unmount();
|
vHDD.unmount();
|
||||||
out.col("green").p("Success. Data writte to Virtual Disk:").nl();
|
out.fg("green").p("Success. Data writte to Virtual Disk:").nl();
|
||||||
out.p(" Data Path: ").p(data_file).nl();
|
out.p(" Data Path: ").p(data_file.cpp_str()).nl();
|
||||||
out.p(" Disk Path: ").p(vdisk_file).nl();
|
out.p(" Disk Path: ").p(vdisk_file.cpp_str()).nl();
|
||||||
out.p(" Data Address: ").p(ostd::Utils::getHexStr(addr, true, 4)).nl();
|
out.p(" Data Address: ").p(ostd::Utils::getHexStr(addr, true, 4).cpp_str()).nl();
|
||||||
out.p(" Size: ").pi(code.size()).resetColors().nl();
|
out.p(" Size: ").p(code.size()).reset().nl();
|
||||||
}
|
}
|
||||||
//Unknown
|
//Unknown
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out.col("red").p("Error: Unknown tool.").resetColors().nl();
|
out.fg("red").p("Error: Unknown tool.").reset().nl();
|
||||||
return ErrorTopLevelUnknownTool;
|
return ErrorTopLevelUnknownTool;
|
||||||
}
|
}
|
||||||
return ErrorNoError;
|
return ErrorNoError;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue