; Memory layout after execution:
; Character drawn at (x, y) in destination image
-xcharput:
- mov eax, [es:edi] ; chary
- mov [chary], eax
- mov ecx, [es:edi+4] ; charx
- mov eax, [es:edi+8] ; addrdest
- add eax, [xms_addr]
- mov ebx, [es:eax]
- mov [sizex], ebx
- add eax, 8
- add eax, ecx
- push eax
- sub edx, edx
- mov eax, [chary]
- mul dword [sizex]
- pop ebx
- add eax, ebx
- mov [addrdst], eax
- mov eax, [es:edi+12]
- add eax, [xms_addr]
- mov [addrsrc], eax
- mov al, [es:edi+16]
- mov [colorbg], al
- mov al, [es:edi+20]
- mov [colorfg], al
- add edi, 24
+op_47_xcharput:
+ mov eax, [es:edi] ; eax = y coordinate (top of stack)
+ mov [chary], eax ; store y coordinate
+ mov ecx, [es:edi+4] ; ecx = x coordinate (second on stack)
+ mov eax, [es:edi+8] ; eax = addrdest (destination image virtual address)
+ add eax, [xms_addr] ; convert virtual address to physical address
+ mov ebx, [es:eax] ; ebx = destination image width from image header
+ mov [sizex], ebx ; store destination image width (stride)
+ add eax, 8 ; skip past image header (width + height = 8 bytes)
+ add eax, ecx ; add x offset to base of pixel data
+ push eax ; save partial destination address on x86 stack
+ sub edx, edx ; clear edx for multiplication
+ mov eax, [chary] ; eax = y coordinate
+ mul dword [sizex] ; eax = y * image width (row offset in bytes)
+ pop ebx ; ebx = base + x offset
+ add eax, ebx ; eax = final destination pixel address
+ mov [addrdst], eax ; store destination address for character drawing
+ mov eax, [es:edi+12] ; eax = addrsrc (source font data virtual address)
+ add eax, [xms_addr] ; convert virtual address to physical address
+ mov [addrsrc], eax ; store source font data address
+ mov al, [es:edi+16] ; al = background color value
+ mov [colorbg], al ; store background color
+ mov al, [es:edi+20] ; al = foreground color value
+ mov [colorfg], al ; store foreground color
+ add edi, 24 ; pop all six arguments off the data stack
- mov [linenum], 8
+ mov [linenum], 8 ; linenum = 8 (number of rows in character glyph)
charl1:
- mov eax, [addrsrc]
- mov bx, [es:eax]
- mov edx, [addrdst]
- mov cx, 8
+ mov eax, [addrsrc] ; eax = current source font data address
+ mov bx, [es:eax] ; bx = current row bitmap (8 bits used)
+ mov edx, [addrdst] ; edx = current destination pixel address
+ mov cx, 8 ; cx = 8 (number of pixels per row)
charl2:
- dec cx
- bt bx, cx
- jnc charl3
- mov al, [colorfg]
- jmp charl4
+ dec cx ; decrement bit index (process bits 7 down to 0)
+ bt bx, cx ; test bit cx of the row bitmap
+ jnc charl3 ; if bit is 0 (clear), use background color
+ mov al, [colorfg] ; bit is 1 (set): al = foreground color
+ jmp charl4 ; skip to pixel write
charl3:
- mov al, [colorbg]
+ mov al, [colorbg] ; bit is 0 (clear): al = background color
charl4:
- mov [es:edx], al
- inc edx
- cmp cx, 0
- jne charl2
+ mov [es:edx], al ; write pixel color to destination
+ inc edx ; advance destination to next pixel (next column)
+ cmp cx, 0 ; check if all 8 pixels in this row are done
+ jne charl2 ; if not, process next pixel
- mov eax, [sizex]
- add [addrdst], eax
- inc [addrsrc]
- dec [linenum]
- mov al, [linenum]
- cmp al, 0
- jne charl1
+ mov eax, [sizex] ; eax = image width (stride)
+ add [addrdst], eax ; advance destination to next row
+ inc [addrsrc] ; advance source to next byte (next row bitmap)
+ dec [linenum] ; decrement remaining line count
+ mov al, [linenum] ; al = remaining lines
+ cmp al, 0 ; check if all 8 rows are done
+ jne charl1 ; if not, draw next row
- jmp emu
+ jmp emu ; return to emulation loop
colorfg db 0
colorbg db 0