; ========================================================================================
; Print16 params Print16 (a)
; p1: a ascii r8 ascii character, 0-255
align 16
export Print16: ; print a 16x16 text character
sub rsp, 28h
mov [rsp+00h], rsi
mov [rsp+08h], rdi
mov [rsp+10h], rbx
mov [rsp+18h], rbp
; ---- Enter -----
; 1. src
; get a ptr to the font data
mov esi, FONT16$ ; ptr to font sets in emulator ram @ $A000
; add offset to char bitmap data
mov ebx, r8d ; preserve char# in r8
shl ebx, 5 ; offset = char# * (32 bytes/char)
add esi, ebx ; add offset = ptr to this character's bitmap data
; 2. dst
mov edi, VIDEO$ ; base
; add (x,y) offsets
mov eax, [CursorX] ; get (x)
mov ebx, [CursorY] ; get (y)
shl eax, 2 ; x-offset = x * 4
shl ebx, 13 ; y-offset = y * 2000h
add edi, eax ; add x-offset to base surface
add edi, ebx ; add y-offset to base address
mov ebp, edi ; copy print address to rowptr
mov r10d, [BGcolor] ; get bg color
mov r11d, [FGcolor] ; get fg color
; 3. ----- the print loop -----
mov dl, 16 ; init rowctr (16 rows, 16 pixels each)
do16rows: ; 16-bit processing of one screen row of char data
mov ax, [esi] ; ax = bitmap data for 1 row (16 pixels, 2 bytes)
xchg al, ah ; swap the order of bytes for 16-bit access
mov cl, 16 ; 16 pixels per screen row
do16pixels: ; 16 shifts = 1 row (2 bytes) of pixel data, poke on 1-bits only
shl ax, 1 ; shift bit 15 into carry flag
cmovnc ebx, r10d ; when bit = 0, use bg color
cmovc ebx, r11d ; when bit = 1, use fg color
mov [edi], ebx ; poke the color to surface memory
add edi, 4 ; advance to next x-pixel (right 1)
dec cl ; pixelctr = pixelctr-1
jnz < do16pixels ; loop until pixelctr = 0
; re-sync the pointers for the next row (down 1)
add esi, 2 ; advance fontptr to next source row (+2 bytes)
add ebp, 2000h ; rowptr + pitch = next row
mov edi, ebp ; copy rowptr to colptr
dec dl ; rowctr = rowctr-1
jnz < do16rows ; loop until rowctr = 0
add D[CursorX], 16 ; get CursorX ready for next Print (+16 pixels)
; ----- EXIT -----
mov rsi, [rsp+00h]
mov rdi, [rsp+08h]
mov rbx, [rsp+10h]
mov rbp, [rsp+18h]
add rsp, 28h
ret
; ========================================================================================
; Plot(x,y)
; p1: x
; p2: y
align 16
export Plot:
mov [CursorX], r8d
mov [CursorY], r9d
ret
; ========================================================================================
; SetTextColor(bg_color,fg_color)
; p1: bg color
; p2: fg color
align 16
export SetTextColor:
mov [BGcolor], r8d
mov [FGcolor], r9d
ret
; ========================================================================================
; SetFont(font_num)
; p1: font# (0 = serif, 1 = sans)
align 16
export SetFont:
mov [FontNum], r8d
ret
; ========================================================================================
; String16 String16 (pStringz)
; p1: pStringz r8 ptr to text string
align 16
export String16: ; String prints a 0-term ascii string
sub rsp, 18h
mov [rsp+00h], rsi ; preserve
mov [rsp+08h], rbx ; preserve
; ----- Enter -----
; loop to print a 0-term string
mov esi, r8d ; get the string ptr
xor ebx, ebx ; init string length index = 0
strloop:
movzx r8d, B[esi+ebx] ; get a character from the string
or r8d, r8d ; check to see if character = 0
jz > strExit ; if yes, exit
call Print16 ; print the character in r8
inc ebx ; increment string length index
jmp < strloop ; always loop back for more
; ----- Exit -----
strExit:
mov rsi, [rsp+00h] ; restore
mov rbx, [rsp+08h] ; restore
add rsp, 18h
ret
; ========================================================================================
; GetStringLen (pStringz)
; p1: pStringz r8 ptr to 0-term text string
; return: eax string's character count
align 16
export GetStringLen: ; GetStringLen (pStringz): returns the length of a 0-term string
sub rsp, 18h
mov [rsp+00h], rsi ; preserve
mov [rsp+08h], rbx ; preserve
; ----- Enter -----
mov esi, r8d ; get string ptr
xor eax, eax ; init string index = 0
; loop to gather a string
gstrloop:
mov bl, [rsi+rax] ; get a character from the string
or bl, bl ; is ascii char = 0?
jz > gstrExit ; if = 0, exit loop with charcount in eax
inc eax ; if <> 0, increment charcount
jmp < gstrloop ; always loop to get another char
; ----- Exit -----
gstrExit:
mov rsi, [rsp+00h] ; preserve
mov rbx, [rsp+08h] ; preserve
add rsp, 18h
ret
; ========================================================================================
; Print16DecD (n)
; p1: n number r8
align 16
export Print16DecD:
sub rsp, 18h
mov [rsp+00h], rsi ; save (x) for String16
mov [rsp+08h], rdi ; save (y) for String16
mov [rsp+10h], rbx
; ----- ENTER -----
lea edi, textBuffer + 15 ; Point RDI to the last byte of the buffer
mov B[edi], 0 ; Null-terminate the string
dec edi ; Move to the previous byte
mov ebx, 10 ; Divisor for base-10 conversion
mov eax, r8d ; number to convert (can be any unsigned 32-bit value)
; Handle the special case of 0
test eax, eax
jnz > convert_loop16
mov B[edi], '0'
jmp > donep16
convert_loop16:
xor edx, edx ; Clear EDX for division (EDX:EAX / EBX)
div ebx ; EAX = EAX / 10, EDX = remainder (0-9)
add dl, '0' ; Convert remainder to ASCII
mov [edi], dl ; Store ASCII digit
dec edi ; Move backward in buffer
test eax, eax
jnz < convert_loop16 ; Repeat if quotient is not zero
donep16:
inc edi ; RDI now points to the first digit
; At this point, RDI points to the start of the null-terminated string in textBuffer
; Print the string
mov r8d, edi ; ptr to number string
call String16 ; print the string
; ----- EXIT -----
mov rsi, [rsp+00h]
mov rdi, [rsp+08h]
mov rbx, [rsp+10h]
add rsp, 18h ; fix the stack
ret
; ========================================================================================
; Print16HexB (n)
; p1: n r8
align 16
export Print16HexB:
call dw2hex ; convert to an ascii string
lea r8d, textBuffer+6 ; address of the number as a text string
call String16 ; print the number
ret
; ========================================================================================
; Print16HexW (n)
; p1: n r8
align 16
export Print16HexW:
call dw2hex ; convert to an ascii string
lea r8d, textBuffer+4 ; address of the number as a text string
call String16 ; print the number
ret
;=========================================================================
; Print16HexD (n)
; p1: n r8
align 16
export Print16HexD:
call dw2hex ; convert to an ascii string
lea r8d, textBuffer ; address of the number as a text string
call String16 ; print the number
ret
;=========================================================================
; Print16BinB (n)
; p1: n r8
align 16
export Print16BinB:
call dw2bin ; convert to an ascii string
lea r8d, textBuffer+24 ; address of the number as a text string
call String16 ; print the number
ret
;=========================================================================
; Print16BinW (n)
; p1: n r8
align 16
export Print16BinW:
call dw2bin ; convert to an ascii string
lea r8d, textBuffer+16 ; address of the number as a text string
call String16 ; print the number
ret
;=========================================================================
; Print16BinD (n)
; p1: n r8
align 16
export Print16BinD:
call dw2bin ; convert to an ascii string
lea r8d, textBuffer ; address of the number as a text string
call String16 ; print the number
ret
;=========================================================================