please dont rip this site
;
; Low level IBM/PC console keyboard/window interface routines
; for use with the DDS MICRO-C compiler.
;
; Copyright 1989-2000 Dave Dunfield
; All rights reserved.
;
; Permission granted for personal (non-commercial) use only.
;
?CBASE  EQU     $B800           ; Color video screen segment
?MBASE  EQU     $B000           ; Monochrome video screen segment
;
; Initialized variables & tables
;
W_BASE  DW      ?CBASE          ; Mono=B000, Cga=B800
W_PAGE  DB      0               ; Current video page
W_OPEN  DW      0               ; Last opened window
; Special key table - General keys
?W_KEYS DW      $4800           ; KUA   (Up arrow)
        DW      $5000           ; KDA   (Down arrow)
        DW      $4B00           ; KLA   (Left arrow)
        DW      $4D00           ; KRA   (Right arrow)
        DW      $4900           ; KPU   (PgUp)
        DW      $5100           ; KPD   (PgDn)
        DW      $4700           ; KHO   (Home)
        DW      $4F00           ; KEN   (End)
        DW      $4E2B           ; KKP   (Keypad '+')
        DW      $4A2D           ; KKM   (Keypad '-')
        DW      $5200           ; KIN   (Ins)
        DW      $5300           ; KDL   (Del)
        DW      $0E08           ; KBS   (Backspace)
; Function keys
        DW      $3B00           ; K1    (F1)
        DW      $3C00           ; K2    (F2)
        DW      $3D00           ; K3    (F3)
        DW      $3E00           ; K4    (F4)
        DW      $3F00           ; K5    (F5)
        DW      $4000           ; K6    (F6)
        DW      $4100           ; K7    (F7)
        DW      $4200           ; K8    (F8)
        DW      $4300           ; K9    (F9)
        DW      $4400           ; K10   (F10)
; Special control keys
        DW      $8400           ; CPU   (CTRL-PgUp)
        DW      $7600           ; CPD   (CTRL-PgDn)
        DW      $7700           ; CHO   (CTRL-Home)
        DW      $7500           ; CEN   (CTRL-End)
        DW      0
; BOX character table
?BOXTAB DB      $C4,$B3,$DA,$BF,$C0,$D9
        DB      $CD,$BA,$C9,$BB,$C8,$BC
        DB      $CD,$B3,$D5,$B8,$D4,$BE
;
; Open a window: w_open(px, py, sx, sy, flags)
;
wopen   PUSH    BP              ; Save callers stack frame
        MOV     BP,SP           ; Address parameters
        PUSH    ES              ; Save ES
; Set up video mode
        MOV     AH,#$0F         ; Get video mode
        INT     $10             ; Call BIOS
        MOV     W_PAGE,BH       ; Save video page
        MOV     BX,#?CBASE      ; Assume COLOR address
        CMP     AL,#$07         ; Monochrome?
        JNZ     ?oinit1         ; No, assumption correct
        MOV     BX,#?MBASE      ; Get MONOCHROME address
?oinit1 MOV     W_BASE,BX       ; Set video base address
        MOV     ES,BX           ; Set up segment
; Allocate a window buffer
        XOR     AH,AH           ; zero high
        MOV     AL,5[BP]        ; Get video flags
        AND     AL,#$80         ; Do we save screen
        JZ      ?oinit2         ; No, do not
        MOV     AL,6[BP]        ; Get 'Y' size
        MOV     BL,8[BP]        ; Get 'X' size
        MUL     BL              ; Calculate total size
        SHL     AX,1            ; X2 for attributes
?oinit2 ADD     AX,#14          ; Include overhead
        PUSH    AX              ; Pass as parameter
        CALL    malloc          ; Allocate the buffer
        MOV     SI,AX           ; Set up pointer
        POP     DX              ; Clean up stack
        AND     SI,SI           ; Did we get it?
        JNZ     ?oinit3         ; Yes, proceed
; Couldn't allocate, return with bad news
        POP     ES              ; Restore extra set
        POP     BP              ; Restore caller
        RET
; Fill in window parameter block
?oinit3 MOV     DL,12[BP]       ; Get 'X' position
        MOV     DH,10[BP]       ; Get 'Y' position
        MOV     2[SI],DX        ; Save it
        MOV     DL,8[BP]        ; Get 'X' size
        MOV     DH,6[BP]        ; Get 'Y' size
        MOV     4[SI],DX        ; Save size
        MOV     BX,4[BP]        ; Get window flags
        MOV     [SI],BX         ; Save attributes & flags
        MOV     DX,W_OPEN       ; Get last opened window
        MOV     8[SI],DX        ; Save in buffer
        XOR     DX,DX           ; Reset cursor position
        MOV     6[SI],DX        ; Save initial cursor position
; Save window contents if required
        TEST    BH,#$80         ; Do we save it?
        JZ      ?oinit5         ; No we don't
; ... Set up pointers to screen & save area
        CALL    ?xyaddr         ; Get base address
        MOV     DX,4[SI]        ; Get 'X' and 'Y' sizes
        LEA     DI,14[SI]       ; Offset to data area
        PUSH    SI              ; Save SI
        MOV     SI,BX           ; Get base window address
; ... Save one line at a time
        PUSH    ES              ; Stack ES
        PUSH    DS              ; And DS
        POP     ES              ; For swap
        POP     DS              ; ES <> DS
?oinit4 PUSH    SI              ; Save source
        MOV     CL,DL           ; Get 'X' size
        XOR     CH,CH           ; Zero high size
        REP
        MOVSW                   ; Move one line
        POP     SI              ; Restore it
        ADD     SI,#160         ; Offset to next line
        DEC     DH              ; Reduce count
        JNZ     ?oinit4         ; And proceed
; ... Restore registers and continue
        PUSH    ES              ; Stack ES
        PUSH    DS              ; And DS
        POP     ES              ; For swap
        POP     DS              ; ES <> DS
        POP     SI              ; Restore SI
        XOR     DX,DX           ; Reset cursor position
        MOV     BH,5[BP]        ; Get flags back
; Draw box if required
?oinit5 MOV     BP,#?BOXTAB     ; Point to BOX table
        MOV     CX,4[SI]        ; Get size of box
        SUB     CH,#2           ; Adjust for bar
        DEC     CL              ; Adjust for bar
        AND     BH,#$60         ; Draw BOX?
        JZ      ?oinit8         ; No we don't
; ... Select box type
        CMP     BH,#$40         ; Box1?
        JZ      ?oinit6         ; Use this one
        ADD     BP,#6           ; Offset to next
        CMP     BH,#$20         ; Box2?
        JZ      ?oinit6         ; Use this one
        ADD     BP,#6           ; Offset to next
?oinit6 PUSH    CX              ; Save size
        CALL    ?xyaddr         ; Get address
; ... Draw the top (With corners)
        MOV     AH,[SI]         ; Get attribute
        MOV     AL,2[BP]        ; Top left corner
        MOV     ES:[BX],AX      ; Write top corner
        LEA     DI,2[BX]        ; Get value
        XOR     CH,CH           ; Zero high
        DEC     CL              ; Adjust for bar
        MOV     AL,0[BP]        ; Horizontal line
        REP
        STOSW                   ; Draw the line
        MOV     AL,3[BP]        ; Top right hand corner
        MOV     ES:[DI],AX      ; Write it
        POP     CX              ; Restore position
; ... Draw the box sides
?oinit7 INC     DH              ; Advance
        MOV     AL,1[BP]        ; Box side
        CALL    ?xyaddr         ; Get position
        MOV     ES:[BX],AX      ; Write it
        ADD     DL,CL           ; Offset
        CALL    ?xyaddr         ; Get position
        MOV     ES:[BX],AX      ; Write it
        SUB     DL,CL           ; Backup
        DEC     CH              ; Reduce count
        JNZ     ?oinit7         ; Do them all
; ... Draw the bottom (With corners)
        INC     DH              ; Advance to bottom
        CALL    ?xyaddr         ; get address
        MOV     AL,4[BP]        ; Lower left corner
        MOV     ES:[BX],AX      ; Write it
        LEA     DI,2[BX]        ; Position to line
        DEC     CL              ; Adjust for bar
        MOV     AL,0[BP]        ; Horizontal line
        REP
        STOSW                   ; Write it out
        MOV     AL,5[BP]        ; Lower right corner
        MOV     ES:[DI],AX      ; Write it out
; ... Reduce size of active region
        MOV     AX,2[SI]        ; Get position
        INC     AL              ; Advance 'X'
        INC     AH              ; Advance 'Y'
        MOV     2[SI],AX        ; Resave
        MOV     AX,4[SI]        ; Get size
        SUB     AH,#2           ; Chop out bars
        SUB     AL,#2           ; Chop out bars
        MOV     4[SI],AX        ; And resave
        XOR     DX,DX           ; Reset cursor position
; Clear screen if required
?oinit8 MOV     BH,1[SI]        ; Get flags back
        TEST    BH,#$10         ; Clear screen?
        JZ      ?oinit9         ; No, its ok
        CALL    ?cleos          ; Clear one line
; Save cursor information
?oinit9 MOV     BH,W_PAGE       ; Get video page
        MOV     AH,#$03         ; Get cursor info
        INT     $10             ; Get cursor
        MOV     10[SI],CX       ; Save shape
        MOV     12[SI],DX       ; Save position
        MOV     AX,SI           ; Get buffer address
        MOV     W_OPEN,AX       ; Save this window pointer
        POP     ES              ; Restore ES
        POP     BP              ; Restore callers stack frame
        RET
;
; Close current window: wclose()
;
wclose  CALL    ?xsetup         ; Get last window
        JMP     <?wclos0        ; And proceed
;
; Close a window: w_close(window)
;
w_close CALL    ?wsetup         ; Get parameters
?wclos0 XOR     DX,DX           ; Zero position
        MOV     BH,1[SI]        ; Get open flags
; If window was BOXed, adjust sizes first
        TEST    BH,#$60         ; Was it BOXed
        JZ      ?wclos1         ; No, don't adjust
        MOV     AX,2[SI]        ; Get position
        DEC     AL              ; Expand 'X'
        DEC     AH              ; Expand 'Y'
        MOV     2[SI],AX        ; Resave
        MOV     AX,4[SI]        ; Get size
        ADD     AH,#2           ; Adjust for bars
        ADD     AL,#2           ; Adjust for bars
        MOV     4[SI],AX        ; Resave
; Clear window if requested
?wclos1 TEST    BH,#$08         ; Clear window?
        JZ      ?wclos2         ; No, try next
        CALL    ?cleos          ; Clear the window
        MOV     BH,1[SI]        ; Get flags back
; Restore previous contents if saved
?wclos2 TEST    BH,#$80         ; Do we restore it
        JZ      ?wclos4         ; No, just clear
; ... Set up pointers to screen & save area
        CALL    ?xyaddr         ; Calculate base address
        MOV     DX,4[SI]        ; Get 'X' and 'Y' sizes
        PUSH    SI              ; Save SI
        LEA     SI,14[SI]       ; Offset to data area
        MOV     DI,BX           ; Get base window address
; ... Restore one line at a time
?wclos3 PUSH    DI              ; Save source
        MOV     CL,DL           ; Get 'X' size
        XOR     CH,CH           ; Zero high size
        REP
        MOVSW                   ; Move one line
        POP     DI              ; Restore it
        ADD     DI,#160         ; Offset to next line
        DEC     DH              ; Reduce count
        JNZ     ?wclos3         ; And proceed
        POP     SI              ; Restore SI
        MOV     BH,1[SI]        ; Get flags back
; Restore the cursor
?wclos4 MOV     CX,10[SI]       ; Get cursor shape
        MOV     AH,#$01         ; Set shape
        INT     $10             ; Call BIOS
        MOV     DX,12[SI]       ; Get position
        MOV     BH,W_PAGE       ; Get display page
        MOV     AH,#$02         ; Set position
        INT     $10             ; Call BIOS
; If this is the active window, switch to previously open
        CMP     SI,W_OPEN       ; Is this it?
        JNZ     ?wclos5         ; No, don't reset
        MOV     AX,8[SI]        ; Get last free
        MOV     W_OPEN,AX       ; Save it
; Release the buffer contents
?wclos5 PUSH    SI              ; Save address of buffer
        CALL    free            ; Release it
        POP     SI              ; Fixup stack
        POP     ES              ; Restore ES
        POP     BP              ; Restore BP
        RET
;
; Write character into current window: wputc(int c)
;
wputc   CALL    ?xsetup         ; Get last open window
        MOV     AX,4[BP]        ; Get character
        JMP     <?tstbel        ; And proceed
;
; Write a character to the video display: w_putc(int c, window)
;
w_putc  CALL    ?wsetup         ; Set up video addresses
        MOV     AX,6[BP]        ; Get character to display
; Handle BELL
?tstbel CMP     AX,#'G'-$40     ; BELL code?
        JNZ     ?tstcr          ; No, try next
        MOV     AX,#$0E07       ; Write BELL code
        XOR     BX,BX           ; Write to page 0
        INT     $10             ; Call BIOS
        JMP     <?vedit         ; and exit
; Handle CARRIAGE RETURN
?tstcr  CMP     AX,#'M'-$40     ; Is it carriage return
        JNZ     ?tstbs          ; No, try next
        XOR     DL,DL           ; Reset 'X' position
        JMP     <?vedit         ; and proceed
; Handle BACKSPACE
?tstbs  CMP     AX,#'H'-$40     ; Is it backspace
        JNZ     ?tstnl          ; No, try line-feed
        AND     DL,DL           ; Already at first col?
        JZ      ?vedit          ; Yes, don't backup
        DEC     DL              ; Reduce 'X' position
        JMP     <?vedit         ; And exit
; Handle NEWLINE
?tstnl  CMP     AX,#'J'-$40     ; Is it newline?
        JNZ     ?norchr         ; Yes, advance line
        MOV     AL,1[SI]        ; Get flags
        TEST    AL,#$04         ; Special case?
        JNZ     ?advy           ; Yes, don't reset 'X'
        XOR     DL,DL           ; Reset cursor
        JMP     <?advy          ; And goto a new line
; Normal Character, output it
?norchr CALL    ?xyaddr         ; Calculate address
        MOV     AH,[SI]         ; Get video attributes
        MOV     ES:[BX],AX      ; Write to video display
; Advance 'X' position
?advx   INC     DL              ; Advance 'X'
        CMP     DL,4[SI]        ; Are we over?
        JB      ?vedit          ; No, its ok
        DEC     DL              ; Restore it
        MOV     AL,1[SI]        ; Get flags
        TEST    AL,#$01         ; Line wrap enabled?
        JZ      ?vedit          ; No, skip it
        XOR     DL,DL           ; Reset 'X' position
; Advance 'Y' position
?advy   INC     DH              ; Advance 'Y' position
        CMP     DH,5[SI]        ; are we over?
        JB      ?vedit          ; No, Its OK
        DEC     DH              ; Reset it
        MOV     AL,1[SI]        ; Get flags
        TEST    AL,#$02         ; Screen wrap enabled?
        JZ      ?vedit          ; No, skip it
        CALL    ?scroll         ; Scroll window
; Restore callers environment & exit
?vedit  MOV     6[SI],DX        ; Resave 'X' and 'Y'
        POP     ES              ; Restore callers ES
        POP     BP              ; Restore callers stack frame
        RET
;
; CLEAR current window: wclwin()
;
wclwin  CALL    ?xsetup         ; Get current window
        JMP     <?clscr1        ; And proceed
;
; CLEAR entire window: w_clwin(window)
;
w_clwin CALL ?wsetup                ; Setup video
?clscr1 XOR     DX,DX           ; Reset to top of screen
        MOV     6[SI],DX        ; Reset cursor
        CALL    ?updt2          ; Position cursor
        XOR     DX,DX           ; Reset again
        JMP     <?clscr2        ; And proceed
;
; CLEAR to end of current window: wcleow()
;
wcleow  CALL    ?xsetup         ; Get current window
        JMP     <?clscr2        ; And proceed
;
; CLEAR to END OF WINDOW: w_cleow(window)
;
w_cleow CALL    ?wsetup         ; Setup video
?clscr2 CALL    ?cleos          ; Clear to end
        POP     ES              ; Restore ES
        POP     BP              ; Restore caller
        RET
;
; CLEAR to end of line in current: wcleol()
;
wcleol  CALL    ?xsetup         ; Get current window
        JMP     <?cleol1        ; And proceed
;
; CLEAR to END OF LINE: w_cleol(window)
;
w_cleol CALL    ?wsetup         ; Setup video
?cleol1 CALL    ?xyaddr         ; Get address
        MOV     DI,BX           ; Set up address
        MOV     CL,4[SI]        ; Get size of line
        SUB     CL,DL           ; Calculate remaining
        XOR     CH,CH           ; Zero high
        MOV     AH,[SI]         ; Get attribute
        MOV     AL,#' '         ; Clear to space
        REP
        STOSW                   ; Clear a line
        POP     ES              ; REstore ES
?cleol2 POP     BP              ; Restore caller
        RET
;
; Position the cursor in current window: wgotoxy(int x, int y)
;
wgotoxy PUSH    BP              ; Save callers stack frame
        MOV     BP,SP           ; Address parameters
        MOV     AL,6[BP]        ; Get 'X' value
        MOV     AH,4[BP]        ; Get 'Y' value
        MOV     SI,W_OPEN   ; Get open window
        JMP     <?goto1         ; And proceed
;
; Position the cursor in window: w_gotoxy(int x, int y, window)
;
w_gotoxy PUSH   BP              ; Save callers stack frame
        MOV     BP,SP           ; Address parameters
        MOV     AL,8[BP]        ; Get 'X' value
        MOV     AH,6[BP]        ; Get 'Y' value
        MOV     SI,4[BP]        ; Get window buffer
?goto1  CMP     AL,4[SI]        ; In range?
        JAE     ?cleol2         ; No, error
        CMP     AH,5[SI]        ; In range
        JAE     ?cleol2         ; No, error
        MOV     6[SI],AX        ; Save values
        JMP     <?updt1         ; And proceed
;
; Update the cursor in current window: wgotoxy()
;
wupdatexy MOV   SI,W_OPEN       ; Get open window
        JMP     <?updt2         ; And proceed
;
; Update the cursor position: w_updatexy(window)
;
w_updatexy PUSH BP              ; Save callers stack frame
        MOV     BP,SP           ; Address parameters
        MOV     SI,4[BP]        ; Get caller
?updt1  POP     BP              ; Resture caller
?updt2  MOV     DX,2[SI]        ; Get starting address
        ADD     DX,6[SI]        ; Offset into window
        MOV     BH,W_PAGE       ; Get video page
        MOV     AH,#$02         ; Set cursor function
        INT     $10             ; Call DOS
        RET
;
; Check for a key from the keyboard: c = w_tstc(window)
;
w_tstc  MOV     AH,#$01         ; Check for key
        INT     $16             ; Do we have key?
        JNZ     w_getc          ; Yes, read it
?wtst1  XOR     AX,AX           ; No key today
        RET
;
; Check for key with cursor in current window: c = wtstc()
;
wtstc   MOV     AH,#$01         ; Check for key
        INT     $16             ; Do we have key?
        JZ      ?wtst1          ; No, return zero
;
; Get in cursor in current window: c = wgetc()
;
wgetc   MOV     SI,W_OPEN       ; Get active window
        JMP     <?getc1         ; And proceed
;
; Get a key from the keyboard with translations: c = w_getc(window)
;
w_getc  MOV     BX,SP           ; Address parameters
        MOV     SI,2[BX]        ; Get window
?getc1  CALL    ?updt2          ; Update the cursor position
; Call BIOS to read key
        XOR     AH,AH           ; Function code 0 - read key
        INT     $16             ; Call bios
; Lookup key for special entries
        MOV     CL,#$80         ; Beginning function code
        MOV     BX,#?W_KEYS     ; Address of keys array
?lokkey MOV     DX,[BX]         ; Get key entry
        CMP     AX,DX           ; Does it match?
        JZ      ?fndkey         ; We found it
        ADD     BX,#2           ; Skip ahead
        INC     CL              ; Advance key code
        OR      DH,DL           ; End of table?
        JNZ     ?lokkey         ; Keep looking
; Translate ENTER key to newline
        CMP     AX,#$1C0D       ; ENTER key?
        JNZ     ?norkey         ; Yes, we have it
        MOV     CL,#'J'-$40     ; Newline is LINE-FEED
; Translate special keys
?fndkey MOV     AL,CL           ; Set return value
?norkey CBW                     ; Set high bits
        RET
;
; Set the CURSOR OFF: wcursor_off()
;
wcursor_off EQU *
        MOV     CX,#$2020       ; Value for cursor off
        JMP     <?setc2         ; And set it
;
; Set the CURSOR to a block: wcursor_block()
;
wcursor_block EQU *
        MOV     CX,#$0006       ; Color block cursor
        MOV     DX,#$000B       ; Monochrome block cursor
        JMP     <?setc1         ; and proceed
;
; Set the CURSOR to a LINE: wcursor_line()
;
wcursor_line EQU *
        MOV     CX,#$0607       ; Color line cursor
        MOV     DX,#$0B0C       ; Monochrome line cursor
?setc1  MOV     AX,W_BASE       ; Get video base
        CMP     AX,#?MBASE      ; Monochrome?
        JNZ     ?setc2          ; No, do it
        MOV     CX,DX           ; Copy for later
; Set cursor to value in CX
?setc2  MOV     AH,#1           ; Set cursor type
        INT     $10             ; Call BIOS
        RET
;
; Set up addressability to video display & stack registers
; Exit: ES = video base address
;       SI = window buffer address
;       DX = cursor address (X/Y)
;
?wsetup POP     AX              ; Get return address
        PUSH    BP              ; Save callers stack frame
        MOV     BP,SP           ; Address parameters
        MOV     SI,4[BP]        ; Get window buffer
?wset1  PUSH    ES              ; Save callers Extra segment
        PUSH    AX              ; Replace return address
        MOV     ES,W_BASE   ; Point to video base
        MOV     DX,6[SI]        ; Get 'X' and 'Y' position
        RET
;
; Set up addressability to currently open window
;
?xsetup POP     AX              ; Get return address
        PUSH    BP              ; Save callers stack frame
        MOV     BP,SP           ; Address parameters
        MOV     SI,W_OPEN   ; Get open window
        JMP     <?wset1         ; And proceed
;
; Scroll window forward one line
;
?scroll PUSH    DS              ; Save data segment
        PUSH    DX              ; Save cursor
        PUSH    SI              ; Save SI
; First, calculate base address of window
        MOV     AL,3[SI]        ; Get 'Y' position
        MOV     BL,#160         ; Size of line
        MUL     BL              ; Calculate 'Y' offset
        MOV     BL,2[SI]        ; Get 'X' position
        XOR     BH,BH           ; Zero high
        SHL     BX,1            ; * 2 for char & attribute bytes        
        ADD     BX,AX           ; BX = character position
        MOV     DI,BX           ; Get base window address
; Scroll one line at a time
        MOV     DX,4[SI]        ; Get 'X' and 'Y' sizes
        DEC     DH              ; Don't copy to last
        PUSH    ES              ; Stack ES
        POP     DS              ; To place in DS
?scrol1 PUSH    DI              ; Save DI
        MOV     SI,DI           ; Begin with same address
        ADD     SI,#160         ; Offset to next line
        MOV     CL,DL           ; Get 'X' size
        XOR     CH,CH           ; Zero high size
        REP
        MOVSW                   ; Move one line
        POP     DI              ; Restore it
        ADD     DI,#160         ; Offset to next line
        DEC     DH              ; Reduce count
        JNZ     ?scrol1         ; And proceed
; Clear bottom line of screen
        MOV     CL,DL           ; Get 'X' size
        POP     SI              ; Restore SI
        POP     DX              ; Restore cursor
        POP     DS              ; Restore data segment
        MOV     AH,[SI]         ; Get attribute
        MOV     AL,#' '         ; And space
        REP
        STOSW                   ; Clear it
        RET
;
; Clear from cursor(DX) to end of line
;
?cleos  PUSH    DX              ; Save cursor
?cleos1 CALL    ?xyaddr         ; Get address
        MOV     DI,BX           ; Set up address
        MOV     CL,4[SI]        ; Get size of line
        SUB     CL,DL           ; Calculate remaining
        XOR     CH,CH           ; Zero high
        MOV     AH,[SI]         ; Get attribute
        MOV     AL,#' '         ; Clear to space
        REP
        STOSW                   ; Clear a line
        XOR     DL,DL           ; Zero 'X'
        INC     DH              ; Advance 'Y'
        CMP     DH,5[SI]        ; Are we finished
        JB      ?cleos1         ; Keep going
        POP     DX              ; Restore cursor
        RET
;
; Calculate screen address from X/Y position (in DX)
; On exit: BX = address
;
?xyaddr PUSH    AX              ; Save AX
        MOV     AL,DH           ; Get 'Y' position
        ADD     AL,3[SI]        ; Offset from start of screen
        MOV     BL,#160         ; Size of physical screen
        MUL     BL              ; Calculate 'Y' offset
        MOV     BL,DL           ; Get 'X' position
        ADD     BL,2[SI]        ; Offset from start of screen
        XOR     BH,BH           ; Zero high byte
        SHL     BX,1            ; * 2 for char & attribute bytes
        ADD     BX,AX           ; BX = character position
        POP     AX              ; Restore it
        RET
$EX:malloc
$EX:free

file: /Techref/com/dunfield/ftp/embedpc/window_asm.htm, 56KB, , updated: 2000/5/5 10:47, local time: 2022/8/11 20:15,
TOP NEW HELP FIND: 
3.239.4.127:LOG IN

 ©2022 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://www.sxlist.com/techref/com/dunfield/ftp/embedpc/window_asm.htm"> Window.asm </A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?

 

Welcome to sxlist.com!


Site supported by
sales, advertizing,
& kind contributors
just like you!

Please don't rip/copy
(here's why

Copies of the site on CD
are available at minimal cost.
 

Welcome to www.sxlist.com!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .