org 0x0
bits 16
%define ENDL 0x0D, 0x0A
; Constants for SoftGPU
SCREEN_WIDTH equ 320
SCREEN_HEIGHT equ 200
VGA_SEGMENT equ 0xA000
start:
; Initialize stack
xor ax, ax
mov ss, ax
mov sp, 0x7C00
call clear_screen
; Print welcome message
mov si, msg_welcome
call puts
; Add this after the gets call in your command_loop
; to ensure proper newline after input
command_loop:
mov si, msg_prompt
call puts
mov di, input_buffer
call gets
; ADD THIS: Print newline after getting input
mov si, msg_newline
call puts
call parse_command
jmp command_loop
; -------------------------------------
; Clear screen via setting text mode
clear_screen:
push ax
push bx
mov ah, 0x00
mov al, 0x03
int 0x10
mov ah, 0x02
mov bh, 0
mov dh, 0
mov dl, 0
int 0x10
pop bx
pop ax
ret
; -------------------------------------
; Read a line from keyboard into [DI] (buffer)
; - DI: pointer to buffer (caller sets)
; - Buffer will be NUL-terminated
; - Max length = 79 characters (keeps room for NUL)
; - Echoes characters, supports Backspace (ASCII 8)
; - Stops on Enter (CR, 0x0D)
gets:
push ax
push bx
push cx
push dx
push si
push di
push bp
mov si, di ; SI = base pointer to buffer
xor cx, cx ; CX = count
.get_char:
; Wait for keystroke (BIOS)
mov ah, 0x00
int 0x16 ; AL = ASCII, AH = scancode
cmp al, 0x0D ; Enter? (CR)
je .done
cmp al, 0x08 ; Backspace?
je .backspace
; Ignore NUL
cmp al, 0x00
je .get_char
; If printable, store and echo
; Check length limit (79 chars)
cmp cx, 79
jae .beep_and_wait
; Store char - use BP as temporary index register
mov bp, si
add bp, cx
mov [bp], al
inc cx
; Echo char using teletype (int10 AH=0x0E)
push dx ; preserve DX
mov ah, 0x0E
mov bh, 0x00 ; page 0
mov bl, 0x00
int 0x10
pop dx
jmp .get_char
.backspace:
cmp cx, 0
je .get_char ; nothing to delete -> continue waiting
dec cx
; Erase char on screen: Backspace, space, Backspace
push dx
mov ah, 0x0E
mov bh, 0x00
mov al, 0x08 ; BS
int 0x10
mov ah, 0x0E
mov al, ' '
int 0x10
mov ah, 0x0E
mov al, 0x08
int 0x10
pop dx
jmp .get_char
.beep_and_wait:
; optional feedback when buffer full: flash beep
mov ah, 0x0E
mov al, 0x07
int 0x10
jmp .get_char
.done:
; Null-terminate buffer - use BP as temporary
mov bp, si
add bp, cx
mov byte [bp], 0
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
; -------------------------------------
; Parse and execute command
parse_command:
push si
push di
push bx
mov si, input_buffer
.skip_spaces:
mov al, [si]
cmp al, ' '
jne .not_space
inc si
jmp .skip_spaces
.not_space:
cmp byte [si], 0
je .done
mov di, cmd_help
call strcmp
cmp ax, 0
je cmd_help_handler
mov di, cmd_clear
call strcmp
cmp ax, 0
je cmd_clear_handler
mov di, cmd_echo
call strcmp
cmp ax, 0
je cmd_echo_handler
mov di, cmd_reboot
call strcmp
cmp ax, 0
je cmd_reboot_handler
mov di, cmd_beep
call strcmp
cmp ax, 0
je cmd_beep_handler
mov di, cmd_test
call strcmp
cmp ax, 0
je cmd_test_handler
mov di, cmd_color
call strcmp
cmp ax, 0
je cmd_color_handler
mov di, cmd_pixel
call strcmp
cmp ax, 0
je cmd_pixel_handler
mov di, cmd_softgpu
call strcmp
cmp ax, 0
je cmd_softgpu_handler
.done:
pop bx
pop di
pop si
ret
; -------------------------------------
; String compare
strcmp:
push ax
push bx
push si
push di
.compare_loop:
mov al, [si]
mov ah, [di]
cmp al, ah
jne .not_equal
test al, al
jz .equal
cmp al, ' '
je .equal
inc si
inc di
jmp .compare_loop
.equal:
xor ax, ax ; AX = 0 (equal)
test ax, ax ; set ZF = 1
jmp .done
.not_equal:
mov ax, 1 ; AX = 1 (not equal)
test ax, ax ; set ZF = 0
.done:
pop di
pop si
pop bx
pop ax
ret
; -------------------------------------
; Command handlers
cmd_help_handler:
mov si, msg_help_text
call puts
ret
cmd_clear_handler:
call clear_screen
mov si, msg_welcome
call puts
ret
cmd_echo_handler:
mov si, input_buffer
.skip_token:
mov al, [si]
cmp al, ' '
je .found_space
cmp al, 0
je .no_text
inc si
jmp .skip_token
.found_space:
inc si
.skip_spaces2:
mov al, [si]
cmp al, ' '
jne .start_text
cmp al, 0
je .no_text
inc si
jmp .skip_spaces2
.start_text:
call puts
mov si, msg_newline
call puts
ret
.no_text:
mov si, msg_newline
call puts
ret
cmd_reboot_handler:
mov si, msg_rebooting
call puts
mov cx, 0xFFFF
.wait:
loop .wait
jmp 0xFFFF:0x0000
cmd_beep_handler:
mov ah, 0x0E
mov al, 0x07
int 0x10
ret
cmd_test_handler:
mov si, msg_test
call puts
mov ah, 0x00
mov al, 0x13
int 0x10
push es
mov ax, 0xA000
mov es, ax
mov ax, 100
mov bx, 320
mul bx
add ax, 160
mov di, ax
mov byte [es:di], 15
mov byte [es:di+1], 12
mov byte [es:di+320], 12
mov byte [es:di+321], 12
pop es
mov ah, 0x00
int 0x16
mov ah, 0x00
mov al, 0x03
int 0x10
mov si, msg_welcome
call puts
ret
cmd_color_handler:
mov si, msg_color_demo
call puts
mov ah, 0x02
mov bh, 0
mov dh, 10
mov dl, 10
int 0x10
mov si, msg_colored
mov bl, 0x4F
call puts_with_color
mov ah, 0x02
mov bh, 0
mov dh, 12
mov dl, 15
int 0x10
mov si, msg_colored2
mov bl, 0x2E
call puts_with_color
ret
cmd_pixel_handler:
mov si, msg_pixel_demo
call puts
mov ah, 0x00
mov al, 0x13
int 0x10
push es
mov ax, 0xA000
mov es, ax
mov cx, 50
xor dx, dx
.square_loop:
mov ax, 75
mov bx, 320
mul bx
add ax, 135
add ax, dx
mov di, ax
mov byte [es:di], 14
mov ax, 75
add ax, 49
mov bx, 320
mul bx
add ax, 135
add ax, dx
mov di, ax
mov byte [es:di], 14
mov ax, 75
add ax, dx
mov bx, 320
mul bx
add ax, 135
mov di, ax
mov byte [es:di], 14
add ax, 49
mov di, ax
mov byte [es:di], 14
inc dx
loop .square_loop
pop es
mov ah, 0x00
int 0x16
mov ah, 0x00
mov al, 0x03
int 0x10
mov si, msg_welcome
call puts
ret
; -------------------------------------
; SoftGPU Command Handler
cmd_softgpu_handler:
mov si, msg_softgpu
call puts
call gpu_init
call softgpu_draw_demo
mov ah, 0x00
int 0x16
call gpu_exit
mov si, msg_welcome
call puts
ret
; -------------------------------------
; SoftGPU Demo
softgpu_draw_demo:
push ax
push bx
push cx
push dx
push si
push di
; Clear to dark blue
mov al, 1
call gpu_clear_fast
; Yellow filled rectangle
mov cx, 50
mov dx, 50
mov si, 100
mov di, 60
mov al, 14
call gpu_fill_rect
; White rectangle outline
mov cx, 180
mov dx, 30
mov si, 80
mov di, 50
mov al, 15
call gpu_draw_rect
; Red diagonal line
mov cx, 10
mov dx, 10
mov si, 200
mov di, 150
mov al, 12
call gpu_draw_line
; Green horizontal line
mov cx, 30
mov dx, 180
mov si, 100
mov al, 10
call gpu_draw_hline
; Cyan vertical line
mov cx, 300
mov dx, 20
mov si, 150
mov al, 11
call gpu_draw_vline
; White pixel cross
mov cx, 160
mov dx, 100
mov al, 15
call gpu_set_pixel
mov cx, 159
call gpu_set_pixel
mov cx, 161
call gpu_set_pixel
mov cx, 160
mov dx, 99
call gpu_set_pixel
mov dx, 101
call gpu_set_pixel
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
; ============================================================================
; SOFTGPU LIBRARY - CORRECTED VERSION
; ============================================================================
gpu_init:
push ax
mov ax, 0x0013
int 0x10
pop ax
ret
gpu_exit:
push ax
mov ax, 0x0003
int 0x10
pop ax
ret
gpu_set_pixel:
push ax
push bx
push di
push es
push dx
push cx
; Bounds check
cmp cx, SCREEN_WIDTH
jae .done
cmp dx, SCREEN_HEIGHT
jae .done
; Calculate offset
mov ax, dx
mov bx, SCREEN_WIDTH
mul bx
add ax, cx
mov di, ax
; Write pixel
mov bx, VGA_SEGMENT
mov es, bx
; Get color from stack (original AL value)
mov bx, sp
mov al, [ss:bx+12]
mov [es:di], al
.done:
pop cx
pop dx
pop es
pop di
pop bx
pop ax
ret
gpu_clear_fast:
push ax
push cx
push di
push es
mov bx, VGA_SEGMENT
mov es, bx
xor di, di
mov cx, SCREEN_WIDTH * SCREEN_HEIGHT
rep stosb
pop es
pop di
pop cx
pop ax
ret
gpu_draw_hline:
push ax
push bx
push cx
push dx
push di
push es
push si
; Bounds check
cmp dx, SCREEN_HEIGHT
jae .done
cmp cx, SCREEN_WIDTH
jae .done
; Clip length
mov ax, cx
add ax, si
cmp ax, SCREEN_WIDTH
jbe .len_ok
mov ax, SCREEN_WIDTH
sub ax, cx
mov si, ax
.len_ok:
test si, si
jz .done
; Calculate offset
mov ax, dx
mov bx, SCREEN_WIDTH
mul bx
add ax, cx
mov di, ax
; Setup ES
mov bx, VGA_SEGMENT
mov es, bx
; Get color
mov bx, sp
mov al, [ss:bx+14]
; Draw
mov cx, si
.loop:
mov [es:di], al
inc di
loop .loop
.done:
pop si
pop es
pop di
pop dx
pop cx
pop bx
pop ax
ret
gpu_draw_vline:
push ax
push bx
push cx
push dx
push di
push es
push si
; Bounds check
cmp cx, SCREEN_WIDTH
jae .done
cmp dx, SCREEN_HEIGHT
jae .done
; Clip length
mov ax, dx
add ax, si
cmp ax, SCREEN_HEIGHT
jbe .len_ok
mov ax, SCREEN_HEIGHT
sub ax, dx
mov si, ax
.len_ok:
test si, si
jz .done
; Calculate offset
mov ax, dx
mov bx, SCREEN_WIDTH
mul bx
add ax, cx
mov di, ax
; Setup ES
mov bx, VGA_SEGMENT
mov es, bx
; Get color
mov bx, sp
mov al, [ss:bx+14]
; Draw
.loop:
mov [es:di], al
add di, SCREEN_WIDTH
dec si
jnz .loop
.done:
pop si
pop es
pop di
pop dx
pop cx
pop bx
pop ax
ret
gpu_fill_rect:
push ax
push bx
push cx
push dx
push si
push di
push bp
; Bounds check
cmp cx, SCREEN_WIDTH
jae .done
cmp dx, SCREEN_HEIGHT
jae .done
; Clip width
mov ax, cx
add ax, si
cmp ax, SCREEN_WIDTH
jbe .width_ok
mov ax, SCREEN_WIDTH
sub ax, cx
mov si, ax
.width_ok:
test si, si
jz .done
; Clip height
mov ax, dx
add ax, di
cmp ax, SCREEN_HEIGHT
jbe .height_ok
mov ax, SCREEN_HEIGHT
sub ax, dx
mov di, ax
.height_ok:
test di, di
jz .done
; Get color from stack
mov bx, sp
mov al, [ss:bx+14]
; Save height counter
mov bp, di
.row_loop:
; Save registers for each row
push cx
push dx
push si
push ax
; Call hline
call gpu_draw_hline
; Restore and advance
pop ax
pop si
pop dx
pop cx
inc dx
dec bp
jnz .row_loop
.done:
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
gpu_draw_rect:
push ax
push bx
push cx
push dx
push si
push di
push bp
; Save all parameters on stack
mov bp, sp
mov word [bp-2], cx ; x
mov word [bp-4], dx ; y
mov word [bp-6], si ; width
mov word [bp-8], di ; height
mov byte [bp-9], al ; color
; Draw top line
mov cx, [bp-2]
mov dx, [bp-4]
mov si, [bp-6]
mov al, [bp-9]
call gpu_draw_hline
; Draw bottom line
mov cx, [bp-2]
mov dx, [bp-4]
add dx, [bp-8]
dec dx
mov si, [bp-6]
mov al, [bp-9]
call gpu_draw_hline
; Draw left line
mov cx, [bp-2]
mov dx, [bp-4]
mov si, [bp-8]
mov al, [bp-9]
call gpu_draw_vline
; Draw right line
mov cx, [bp-2]
add cx, [bp-6]
dec cx
mov dx, [bp-4]
mov si, [bp-8]
mov al, [bp-9]
call gpu_draw_vline
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
gpu_draw_line:
push bp
mov bp, sp
sub sp, 16
push bx
push cx
push dx
push si
push di
; Save color
mov byte [bp-15], al
; Save endpoints
mov word [bp-12], si
mov word [bp-14], di
; Calculate dx = abs(x1 - x0)
mov ax, si
sub ax, cx
test ax, ax
jns .dx_positive
neg ax
.dx_positive:
mov word [bp-2], ax
; Calculate dy = abs(y1 - y0)
mov ax, di
sub ax, dx
test ax, ax
jns .dy_positive
neg ax
.dy_positive:
mov word [bp-4], ax
; Determine sx
mov ax, 1
cmp si, cx
jge .sx_done
neg ax
.sx_done:
mov word [bp-6], ax
; Determine sy
mov ax, 1
cmp di, dx
jge .sy_done
neg ax
.sy_done:
mov word [bp-8], ax
; err = dx - dy
mov ax, word [bp-2]
sub ax, word [bp-4]
mov word [bp-10], ax
.loop:
; Plot pixel
mov al, byte [bp-15]
push cx
push dx
call gpu_set_pixel
pop dx
pop cx
; Check if done
cmp cx, word [bp-12]
jne .continue
cmp dx, word [bp-14]
je .done_line
.continue:
; e2 = 2 * err
mov bx, word [bp-10]
shl bx, 1
; if (e2 > -dy)
mov ax, word [bp-4]
neg ax
cmp bx, ax
jle .skip_x
; err -= dy
mov ax, word [bp-10]
sub ax, word [bp-4]
mov word [bp-10], ax
; x0 += sx
add cx, word [bp-6]
.skip_x:
; if (e2 < dx)
cmp bx, word [bp-2]
jge .skip_y
; err += dx
mov ax, word [bp-10]
add ax, word [bp-2]
mov word [bp-10], ax
; y0 += sy
add dx, word [bp-8]
.skip_y:
jmp .loop
.done_line:
pop di
pop si
pop dx
pop cx
pop bx
mov sp, bp
pop bp
ret
; -------------------------------------
; Print string with color attribute
puts_with_color:
push ax
push bx
push si
push dx
.color_loop:
lodsb
test al, al
jz .done
mov ah, 0x09
mov bh, 0
mov cx, 1
int 0x10
push dx
mov ah, 0x03
mov bh, 0
int 0x10
inc dl
mov ah, 0x02
mov bh, 0
int 0x10
pop dx
jmp .color_loop
.done:
pop dx
pop si
pop bx
pop ax
ret
; -------------------------------------
; Print string
puts:
push ax
push bx
push si
.loop:
lodsb
test al, al
jz .done
mov ah, 0x0E
mov bh, 0
int 0x10
jmp .loop
.done:
pop si
pop bx
pop ax
ret
; -------------------------------------
; Data section
msg_welcome: db 'Codename "Sytrus-harmor" OS v1.0 - [C.V.D.: 9/6/25]', ENDL
db 'Type "help" for available commands.', ENDL
db 'Early versions have many errors, bugs, and other such things!', ENDL
db 'Ascii test: abcdefghijklmnopqrstuvwxyz', ENDL, 0
msg_prompt: db 'root/> ', 0
msg_newline: db ENDL, 0
msg_unknown: db 'Couldnt find command. Type "help" for help.', ENDL, 0
msg_rebooting: db 'Restarting... ', ENDL, 0
msg_help_text: db 'Available commands:', ENDL
db ' help - Show this help', ENDL
db ' clear - Clear the screen', ENDL
db ' echo - Echo text to screen', ENDL
db ' beep - Make a beep sound', ENDL
db ' test - Simple graphics test', ENDL
db ' color - Colorful text demo', ENDL
db ' pixel - Pixel graphics demo', ENDL
db ' softgpu - Software GPU demonstration', ENDL
db ' reboot - Restart the system', ENDL, 0
msg_test: db 'Testing graphics mode...', ENDL, 0
msg_color_demo: db 'Color text demonstration:', ENDL, 0
msg_pixel_demo: db 'Entering pixel graphics mode...', ENDL, 0
msg_softgpu: db 'Software GPU Demo - Press any key to return', ENDL, 0
msg_colored: db 'This is colored text!', 0
msg_colored2: db 'Different colors!', 0
; Command strings
cmd_help: db 'help', 0
cmd_clear: db 'clear', 0
cmd_echo: db 'echo', 0
cmd_reboot: db 'reboot', 0
cmd_beep: db 'beep', 0
cmd_test: db 'test', 0
cmd_color: db 'color', 0
cmd_pixel: db 'pixel', 0
cmd_softgpu: db 'softgpu', 0
; Buffers
input_buffer: times 80 db 0
edit_buffer: times 80 db 0