.model  large
.stack  1024
.386

.data
extrn           fontset1:word
message         db      'hey man',0

.code

_Init_Font              PROC    FAR
                push    bp
                mov     bp,sp

                lds     si,dword ptr [bp + 6]
                mov     cl,byte ptr [si + 3]            ; load # of colors used
                xor     ch,ch
                mov     al,byte ptr [si + 4]            ; load starting color
                xor     ah,ah
                add     cx,ax                           ; end color =
                dec     cx                              ; numcolors + start - 1
                add     si,05h                          ; point to palette
                push    ds
                push    si                              ; start of RGB colors
                push    255
                push    0
                call    _Restore_Palette
                add     sp,8

                pop     bp
                ret
_Init_Font              ENDP

;******************************************************************************
; void Draw_String(byte far *fontdata, byte far *string,
;                  word xcoord, word ycoord, byte page);
;******************************************************************************
_Draw_String            PROC    FAR
                push    bp
                mov     bp,sp

                mov     ax,0a000h
                mov     es,ax

                lds     si,dword ptr [bp + 6]           ; DS:SI -> fontdata
                add     si,773                          ; point to offset table
                mov     dx,[bp + 14]                    ; X coord

                mov     di,[bp + 16]                    ; Y coord
                shl     di,1                            ; *16
                shl     di,1
                shl     di,1
                shl     di,1
                mov     bx,di                           ; save
                shl     di,1                            ; *64
                shl     di,1
                add     di,bx                           ; *64 + *16 = *80

                mov     cl,dl                   ; get plane bits from X pos
                and     cl,00000011b            ; keep in 0-3 range
                mov     ah,00010001b            ; start at plane 0
                rol     ah,cl                   ; shift to proper plane

                shr     dx,1                    ; divide X coord by 4
                shr     dx,1
                add     di,dx                   ; video offset to start at
                mov     bl,byte ptr [bp + 18]   ; page
                and     bx,00003h               ; keep in 0-3 range
                shl     bx,1                    ; index *2 for word
                add     di,page_add[bx]         ; final video offset

                lfs     bx,dword ptr [bp + 10]  ; FS:BP -> string
                mov     bp,bx
                mov     al,02h                          ; 02h = map mask index

setupletter:    xor     bh,bh
                mov     bl,byte ptr fs:[bp]             ; load letter from message
                shl     bx,1                            ; *2 = word sized

                mov     cx,word ptr [si + bx]
                mov     gs,si                           ; save font pointer
                sub     si,773                          ; back to start
                add     si,cx                           ; point to proper spot in font file

                mov     ch,byte ptr [si + 1]            ; get X size
                mov     cl,byte ptr [si + 2]            ; get Y size
                add     si,03h                          ; point to start of data

newplane:       mov     dx,03c4h                        ; sequencer reg
                out     dx,ax
                mov     dl,cl                           ; loop Y count

                mov     bx,di                           ; save video pointer
drawcolumn:     mov     dh,byte ptr [si]                ; draw a column
                mov     es:[di],dh
                inc     si                              ; next byte in column
                add     di,80                           ; next video line
                dec     dl                              ; decrement height
                jnz     drawcolumn
                mov     di,bx                           ; restore video pointer

                rol     ah,1
                adc     di,0
                dec     ch
                jnz     newplane

nextletter:     mov     si,gs
                inc     bp                              ; next letter in message
                cmp     byte ptr fs:[bp],00h
                jne     setupletter

                        pop     bp
                        ret
_Draw_String            ENDP

;******************************************************************************
; void Draw_Char(byte far *fontdata, byte far *string,
;                word xcoord, word ycoord, byte page);
;******************************************************************************
_Draw_Char              PROC    FAR
                push    bp
                mov     bp,sp

                mov     ax,0a000h
                mov     es,ax

                lds     si,dword ptr [bp + 6]           ; DS:SI -> fontdata
                add     si,773                          ; point to offset table
                mov     dx,[bp + 14]                    ; X coord

                mov     di,[bp + 16]                    ; Y coord
                shl     di,1                            ; *16
                shl     di,1
                shl     di,1
                shl     di,1
                mov     bx,di                           ; save
                shl     di,1                            ; *64
                shl     di,1
                add     di,bx                           ; *64 + *16 = *80

                mov     cl,dl                   ; get plane bits from X pos
                and     cl,00000011b            ; keep in 0-3 range
                mov     ah,00010001b            ; start at plane 0
                rol     ah,cl                   ; shift to proper plane

                shr     dx,1                    ; divide X coord by 4
                shr     dx,1
                add     di,dx                   ; video offset to start at
                mov     bl,byte ptr [bp + 18]   ; page
                and     bx,00003h               ; keep in 0-3 range
                shl     bx,1                    ; index *2 for word
                add     di,page_add[bx]         ; final video offset

                lfs     bx,dword ptr [bp + 10]  ; FS:BP -> string
                mov     bp,bx
                mov     al,02h                          ; 02h = map mask index

setupletter1:   xor     bh,bh
                mov     bl,byte ptr fs:[bp]             ; load letter from message
                shl     bx,1                            ; *2 = word sized

                mov     cx,word ptr [si + bx]
                mov     gs,si                           ; save font pointer
                sub     si,773                          ; back to start
                add     si,cx                           ; point to proper spot in font file

                mov     ch,byte ptr [si + 1]            ; get X size
                mov     cl,byte ptr [si + 2]            ; get Y size
                add     si,03h                          ; point to start of data

newplane1:      mov     dx,03c4h                        ; sequencer reg
                out     dx,ax
                mov     dl,cl                           ; loop Y count

                mov     bx,di                           ; save video pointer
drawcolumn1:    mov     dh,byte ptr [si]                ; draw a column
                mov     es:[di],dh
                inc     si                              ; next byte in column
                add     di,80                           ; next video line
                dec     dl                              ; decrement height
                jnz     drawcolumn1
                mov     di,bx                           ; restore video pointer

                rol     ah,1
                adc     di,0
                dec     ch
                jnz     newplane1

                        pop     bp
                        ret
_Draw_Char              ENDP

start:          mov     ax,@data
                mov     ds,ax

; Initialize 320x200x256 tweaked mode
                push    0
                call    _Init_Tweaked_Mode
                add     sp,2

                push    ds
                push    offset fontset1
                call    _Init_Font
                add     sp,4

                push    0
                push    80
                push    65
                push    ds
                push    offset message
                push    ds
                push    offset fontset1
                call    _Draw_String
                add     sp,14

                call    _Wait_Key

                mov     ax,0003h
                int     10h
                mov     ax,4c00h
                int     21h

                end     start
