Newer
Older
Microsoft / ice / PCBIOS.ASM
@tundra tundra on 24 May 2012 10 KB Initial revision
                PAGE    88,132
                TITLE   System Specific Routines For IBM-PC Using BIOS
                SUBTTL  Copyright (c) 1986, 1987, 1988 T.A. Daneliuk
;
;               Last Modified: 07-26-88
;


; ======================= Setup, Notes, And Facts =============================

;   Must Use /Dmemmodel=model size on MASM command line !!!!!
%               .model  memmodel,c

.LALL                           ; Want To See All MASM Generated Expansions


; =========================== Data Section ====================================
                        .data

; =========================== Actual Data =====================================

VIDEO_MODE      db      3                   ; Current Video Mode
VIDEO_PAGE      db      0                   ; Current Video Page
VIDEO_WIDTH     dw      80                  ; Current Screen Width
VIDEO_HEIGHT    dw      25                  ; Current Screen Height

; =========================== Code Section ====================================

                        .code


; ========================= Sound Generation ==================================
;
;      USAGE:  pcbios_sound(FREQ,DURATION)
;       WHERE,  FREQ is unsigned int in Hertz
;               DURATION is unsigned int (18 per second)
;
;
portb_8255      equ     61h                     ; 8255 port b
freq_8253       equ     42h                     ; 8253 timer latch
command_8253    equ     43h                     ; 8253 time command register
clockh          equ     0012h                   ; clock rate high byte - 1193180 hz
clockl          equ     34dch                   ; clock rate low byte

;
;
pcbios_sound    proc freq:word, duration:word
;
local           elapsed:word                    ; elapsed time ticks stored here
local           startl:word                     ; stores initial timer count
local           starth:word
;
;
                xor             ax,ax           ; zero register
                mov             elapsed,ax      ; init. elapsed time
                mov             startl, ax      ; init. startl
                mov             starth,ax       ; init. starth
                mov             ax,freq         ; make sure freq. <> 0!
                and             ax,ax
                jz              sound_done      ; if so, skip the whole thing
                in              al,portb_8255   ; get current 8255 value
                or              al,3            ; turn on speaker/gate signal
                out             portb_8255,al   ; write back to 8255
                mov             al,0b6h         ; tell timer, frequency is sent next 
                out             command_8253,al
                mov             dx,clockh       ; divide clock rate by passed
                mov             ax,clockl       ; frequency to get total
                mov             cx,freq         ; number of ticks to wait
                div             cx
                out             freq_8253,al    ; low byte to timer
                xchg            al,ah           ; intel's neat instruction set!
                out             freq_8253,al    ; high byte to timer
                xor             ax,ax           ; get current timer count in cx:dx
                int             1ah
                mov             starth,cx       ; save for future reference
                mov             startl,dx
delay:          mov             ax,duration     ; wait till elapsed time is
                cmp             ax,elapsed      ; >= duration passed on stack
                jbe             sound_off
                xor             ax,ax           ; get current timer count
                int             1ah
                mov             ax,starth       ; get starting time
                mov             bx,startl
                sub             dx,bx           ; low word first
                sbb             cx,ax           ; high word with carry
                jnz             sound_off       ; only can deal with 16 bit intervals
                mov             elapsed,dx      ; save time elapsed
                jmp             delay
sound_off:      in              al,portb_8255   ; turn off speaker/gate signal
                and             al,11111100b
                out             portb_8255,al
sound_done:     ret                             ; there's no place like home!
;
pcbios_sound    endp


; ========================== Set Cursor Size ==================================
;
;   usage:      pcbios_cursor(startline, endline)
;
;               startline & endline define starting and ending
;               scanlines respectively
;
;
pcbios_cursor   proc sline:byte, eline:byte
;
                mov     ah,1
                mov     ch,sline
                mov     cl,eline
                int     10h
                ret
;
pcbios_cursor   endp


; ======================== Read Current Cursor Position =======================

pcbios_rdcursor proc uses ds
;
                mov     ax,DGROUP
                mov     ds, ax
                mov     ah,3
                mov     bh,VIDEO_PAGE
                int     10h
                mov     ax,dx                       ; ah=row, al=column
                mov     dx,cx                       ; dh=1st scan line, dl=last
                ret
;
pcbios_rdcursor endp

; ======================== Absolute Cursor Positioning ========================
;
;   usage:      pcbios_rowcol(x-coordinate, y-coordinate)
;
;       if coordinates > than physical screen:
;
;               x position overflows from right end of screen to next line
;               y position wraps to top of screen
;
pcbios_rowcol   proc uses ds, ypos:word, xpos:word
;
                mov     ax,DGROUP
                mov     ds, ax
                mov     ax,VIDEO_WIDTH
                mov     bx,VIDEO_HEIGHT
                mov     dx,xpos
                mov     cx,ypos
check_xposn:    cmp     ax,dx                   ; Bounds Check On X-coord
                jg      check_yposn
                sub     dx,ax                   ; Do modulo ax arithmetic
                inc     cx                      ; And Move Down A Line
                jmp     check_xposn
check_yposn:    cmp     cx,bx                   ; Bounds Check On Y-coord
                jl      set_row_col
                sub     cx,bx
                jmp     check_yposn
set_row_col:    mov     ypos,cx                 ; Save The Normalized Values
                mov     xpos,dx
                mov     ah,2
                mov     bh,VIDEO_PAGE
                mov     dh,cl
                int     10h
                mov     ax,xpos                 ; Return Normalized Coordinates
                mov     dx,ypos
                ret
;
pcbios_rowcol   endp


; ====================Clear Screen With Video Attribute =======================

pcbios_cls      proc    cls_attrib:byte
;
                mov     ax,0600H                ; Scroll Up Whole Screen
                mov     bh,cls_attrib
                xor     cx,cx                   ; Start At 0,0
                mov     dx,184FH
                int     10H
                ret
;
pcbios_cls      endp


; =========================== Get A Keystroke =================================

pcbios_getc     proc    
;
                mov     ah,7
                int     21h
                ret
;
pcbios_getc     endp


; ===================== Write String With Video Attribute =====================

pcbios_aputs    proc uses ds es, string:ptr, attr:byte
;
local           row:word                        ; Current Row
local           col:word                        ; Current Column
local           lcount:word                     ; Length Count
;
                mov     ax,DGROUP
                mov     ds, ax
                mov     lcount,0                ; Initialize Length Count
                call    pcbios_rdcursor         ; Get Current Position
                mov     dl,ah
                xor     ah,ah
                mov     col,ax
                xor     dh,dh
                mov     row,dx
                IF @DataSize                    ; Use Pointer Based On Model
                   les  si,string
                ELSE
                   mov  si,string
                ENDIF
get_a_char:     mov     al,es:[si]              ; Get A Character
                and     al,al                   ; If 0, We're Done!
                jz      aputs_done
                mov     ah,9
                mov     bh,VIDEO_PAGE
                mov     bl,attr
                xor     cx,cx                   ; Repeat 1 Time
                inc     cx
                int     10h
                inc     col
                push    col                     ; Adjust Cursor Position
                push    row
                call    pcbios_rowcol
                pop     row                     ; Get Normalized Coordinates
                pop     col
                inc     lcount                  ; Update Counter
                inc     si                      ; And String Pointer
                jmp     get_a_char              ; Keep Looping For Whole String
aputs_done:     mov     ax,lcount               ; Return String Length
                ret
;
pcbios_aputs    endp


; ======================== Get Current Video Mode =============================

pcbios_getvmode proc uses DS
;
                mov     ax,DGROUP
                mov     ds,ax
                mov     ah,0fh
                int     10h
                mov     VIDEO_MODE,al
                mov     VIDEO_PAGE,bh
                mov     al,ah                   ; Make a word out of the width
                xor     ah,ah
                mov     VIDEO_WIDTH,ax
                ret
;
pcbios_getvmode endp


; ============================= Set Video Mode ================================

pcbios_setvmode proc vmode:byte
;
                xor     ah,ah
                mov     al,vmode
                int     10h
                call    pcbios_getvmode
                ret
;
pcbios_setvmode endp


; ============================= Set Video Page ================================

pcbios_setvpage proc vpage:byte
;
                mov     ah,5
                mov     al,vpage
                int     10h
                call    pcbios_getvmode
                ret
pcbios_setvpage endp


; ============================ END OF ROUTINES ================================
                end