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