bitshifter
Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
|
Hello, i spent the last few days writing what will eventually be the front end for my 16bit operating system, which for now is being tested in windows console.
It has some cool features like a command lookup table with function pointers which process user commands into realtime function calls, and also some string formatting tricks to change character colors or print newlines.
I thought i might share what i have learned with you because there are a lot of beginners here who probably would like to study or modify this code.
It doesnt do much, but it does what its supposed to and thats a good start.
Any comments or constructive criticism as always are greatly appreciated.
;------------------------------------------------
;
;------------------------------------------------
use16
org 0x100
jmp ProgramEntryPoint
;------------------------------------------------
; string formatting flags for PrintString function
;
; \r - set color to red
; \g - set color to green
; \b - set color to blue
; \w - set color to white
; \n - advance caret newline
;------------------------------------------------
;------------------------------------------------
;
;------------------------------------------------
buffer rb 16
maxlen db 15
length db 0
prompt db '\wInput command >> ',0
unknown db '\gUnknown command.\n',0
exiting db '\gExiting program.',0
paused db '\wPress any key to continue...',0
color db 0x0F
commands db 'help',0,\
'quit',0,\
'cls',0,\
0xFF
handlers dw on_help,\
on_quit,\
on_cls,\
on_unknown
; 'x3d game engine by bitshifter'
intromsg db '\rx\g3\bd \rg\ga\bm\re \ge\bn\rg\gi\bn\re \gb\by \rb\gi\bt\rs\gh\bi\rf\gt\be\rr\n',0
helpmsg db '\n\ghelp called\n',0
quitmsg db '\n\gquit called\n',0
;------------------------------------------------
;
;------------------------------------------------
on_help:
push si
mov si,helpmsg
call PrintString
pop si
ret
on_quit:
push si
mov si,quitmsg
call PrintString
pop si
ret
on_cls:
push ax
mov al,0x00 ; number of lines to scroll (0 = clear entire window)
call ScrollWindowUp
pop ax
push dx
xor dx,dx
call SetCaretPosition
pop dx
ret
on_unknown:
push si
mov si,unknown
call AdvanceCaretNewline
call PrintString
pop si
ret
;------------------------------------------------
;
;------------------------------------------------
ProcessCommand:
push si
push di
push bp
push ax
xor bp,bp
mov si,commands
.for_each_command:
mov di,buffer
cmp byte[si],0xFF
je .execute_command
.for_each_character:
mov al,byte[si]
cmp al,byte[di]
jne .get_next_command
or al,al
jz .execute_command
inc si
inc di
jmp .for_each_character
.get_next_command:
lodsb
or al,al
jnz .get_next_command
inc bp
jmp .for_each_command
.execute_command:
shl bp,1
call word[bp+handlers]
pop ax
pop bp
pop di
pop si
ret
;------------------------------------------------
;
;------------------------------------------------
SetTextColorRed:
mov [color],0x04
ret
SetTextColorGreen:
mov [color],0x02
ret
SetTextColorBlue:
mov [color],0x01
ret
SetTextColorWhite:
mov [color],0x0F
ret
;------------------------------------------------
; Params:
; AL: number of lines to scroll (0 = clear entire window)
;------------------------------------------------
ScrollWindowUp:
push ax
push bx
push cx
push dx
mov ah,0x06 ; function id
mov bl,0x00 ; empty
mov bh,0x0F ; bk+fg colors (bk = black, fg = white)
mov cl,0x00 ; top left column
mov ch,0x00 ; top left row
mov dl,79 ; bottom right column
mov dh,24 ; bottom right row
int 0x10 ; invoke bios
call GetCaretPosition
mov dl,0x00
call SetCaretPosition
pop dx
pop cx
pop bx
pop ax
ret
;------------------------------------------------
; Returns:
; DL - caret column number
; DH - caret row number
;
; Notes:
; 1) assumes page number 0
;------------------------------------------------
GetCaretPosition:
push ax
push bx
push cx ; silently modified
mov al,0x00 ; empty
mov ah,0x03 ; function id
mov bl,0x00 ; empty
mov bh,0x00 ; page number
int 0x10 ; invoke bios
pop cx
pop bx
pop ax
ret
;------------------------------------------------
; Params:
; DL - caret column number
; DH - caret row number
;
; Notes:
; 1) does not check caret bounds
; 2) assumes page number 0
;------------------------------------------------
SetCaretPosition:
push ax
push bx
mov al,0x00 ; empty
mov ah,0x02 ; function id
mov bl,0x00 ; empty
mov bh,0x00 ; page number
int 0x10 ; invoke bios
pop bx
pop ax
ret
;------------------------------------------------
; Notes:
; 1) does not check caret bounds
; 2) assumes page number 0
;------------------------------------------------
AdvanceCaretPosition:
push dx
call GetCaretPosition
inc dl
call SetCaretPosition
pop dx
ret
;------------------------------------------------
; Notes:
; 1) does not check caret bounds
; 2) assumes page number 0
;------------------------------------------------
RetreatCaretPosition:
push dx
call GetCaretPosition
dec dl
call SetCaretPosition
pop dx
ret
;------------------------------------------------
; Notes:
; 1) assumes page number 0
; 2) scrolls window up one line if needed
;------------------------------------------------
AdvanceCaretNewline:
push dx
call GetCaretPosition
cmp dh,24
je .scroll_up
mov dl,0x00 ; reset column
inc dh ; increase row
call SetCaretPosition
jmp .finished
.scroll_up:
push ax
mov al,0x01 ; scroll up one line
call ScrollWindowUp
pop ax
.finished:
pop dx
ret
;------------------------------------------------
; Params:
; AL - ascii character to print
;
; Notes:
; 1) does not advance caret
; 2) assumes page number 0
;------------------------------------------------
PrintCharacter:
push ax
push bx
push cx
mov ah,0x09 ; function id
mov bl,[color] ; bg+fg colors
mov bh,0x00 ; page number
mov cx,0x01 ; repeat count
int 0x10 ; invoke bios
pop cx
pop bx
pop ax
ret
;------------------------------------------------
; Notes:
; 1) erases character at caret position
; 2) assumes page number 0
;------------------------------------------------
EraseCharacter:
push ax
xor ax,ax
call SetTextColorWhite
call PrintCharacter
pop ax
ret
;------------------------------------------------
; Params:
; SI: pointer to NULL terminated string
;
; Notes:
; 1) does not check caret bounds
; 2) assumes page number 0
; 3) accepts formatting flags
;------------------------------------------------
PrintString:
push ax
push si
push cx
xor cx,cx
.load_character:
lodsb
or al,al
jz .end_of_string
cmp al,'\'
je .activate_sequence
cmp al,'r'
je .set_to_red
cmp al,'g'
je .set_to_green
cmp al,'b'
je .set_to_blue
cmp al,'w'
je .set_to_white
cmp al,'n'
je .do_newline
.print_character:
call PrintCharacter
call AdvanceCaretPosition
jmp .load_character
.activate_sequence:
mov cx,1
jmp .load_character
.set_to_red:
cmp cx,1
jne .print_character
mov cx,0
call SetTextColorRed
jmp .load_character
.set_to_green:
cmp cx,1
jne .print_character
mov cx,0
call SetTextColorGreen
jmp .load_character
.set_to_blue:
cmp cx,1
jne .print_character
mov cx,0
call SetTextColorBlue
jmp .load_character
.set_to_white:
cmp cx,1
jne .print_character
mov cx,0
call SetTextColorWhite
jmp .load_character
.do_newline:
cmp cx,1
jne .print_character
mov cx,0
call AdvanceCaretNewline
jmp .load_character
.end_of_string:
pop cx
pop si
pop ax
ret
;------------------------------------------------
;
;------------------------------------------------
ProgramEntryPoint:
; set video mode (first mode13 then mode3)
; this can be removed but to go fullscreen
; you will need to press the alt-enter keys
mov al,0x13 ; graphics mode (40*25, 256 colors, 1 page)
mov ah,0x00 ; function id
int 0x10 ; invoke bios
mov al,0x03 ; text mode (80*25, 16 colors, 8 pages)
mov ah,0x00 ; function id
int 0x10 ; invoke bios
; print intro
mov si,intromsg
call PrintString
.reset:
; reset command buffer
mov [buffer],0
mov [length],0
mov di,buffer
; print command prompt
mov si,prompt
call PrintString
.input:
; wait for keystroke
xor ax,ax
int 0x16
; handle special keys
cmp al,0x1B ; VK_ESCAPE
je .vk_escape
cmp al,0x08 ; VK_BACK
je .vk_back
cmp al,0x0D ; VK_RETURN
je .vk_return
; is command buffer full?
mov ah,[length]
cmp ah,[maxlen]
je .input
; append character to buffer
mov byte[di],al
inc di
mov byte[di],0
inc [length]
; print character to screen
call SetTextColorBlue
call PrintCharacter
call AdvanceCaretPosition
jmp .input
.vk_back:
; backspace limiter (keeps us from erasing the prompt)
cmp [length],0 ; is command buffer empty?
je .input
; remove character from buffer
dec di ; decease buffer pointer
mov byte[di],0 ; insert NULL terminator
dec [length] ; decrement command length
; update screen
call RetreatCaretPosition
call EraseCharacter
jmp .input
.vk_return:
; check for empty command buffer
cmp [length],0
je .input
call ProcessCommand
jmp .reset
.vk_escape:
; print exiting message
mov si,exiting
call AdvanceCaretNewline
call PrintString
; print paused message
mov si,paused
call AdvanceCaretNewline
call PrintString
; wait for keystroke
xor ax,ax
int 0x16
; exit to operating system
int 0x20 ; invoke bios
; dos version
;mov al,0x00 ; exit code
;mov ah,0x4C ; function id
;int 0x21 ; invoke bios
ret
Last edited by bitshifter on 06 May 2009, 08:03; edited 5 times in total
|