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