home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware 1 2 the Maxx
/
sw_1.zip
/
sw_1
/
PROGRAM
/
ZSIM12.ZIP
/
CONIO.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-01-09
|
22KB
|
855 lines
;
; BILDSCHIRMTREIBER FUER CP/M EMULATOR
;
;
; (C) 1990,1991 by Jürgen Weber
;
LOCALS
INCLUDE DOS.INC
WS_KEY equ TRUE
EMU_SCR_PAGE EQU 0
DOS_SCR_PAGE EQU 1
HIGHLIGHT_ATTR EQU 1000b
UNDERLINE_ATTR EQU 110b
BLINK_ATTR EQU 10000000b
SCRNWIDTH EQU 79
LASTLINE EQU 24
emudata_seg segment para public 'DATA'
IF WS_KEY
after_ctrl_q db 0
CTRL_MASK EQU 111111B
ext_keys db 72, 'E' AND CTRL_MASK,0 ; up
db 73, 'R' AND CTRL_MASK,0 ; page up
db 75, 'S' AND CTRL_MASK,0 ; left
db 77, 'D' AND CTRL_MASK,0 ; right
db 80, 'X' AND CTRL_MASK,0 ; down
db 81, 'C' AND CTRL_MASK,0 ; page down
db 82, 'V' AND CTRL_MASK,0 ; ins
db 83, 'G' AND CTRL_MASK,0 ; del
db 115, 'A' AND CTRL_MASK,0 ; ctrl-left
db 116, 'F' AND CTRL_MASK,0 ; ctrl-right
db 71, 'Q' AND CTRL_MASK,'S' ; home
db 79, 'Q' AND CTRL_MASK,'D' ; end
db 117, 'Q' AND CTRL_MASK,'X' ; ctrl-end
db 118, 'Q' AND CTRL_MASK,'C' ; ctrl-pgdn
db 119, 'Q' AND CTRL_MASK,'E' ; ctrl-home
db 132, 'Q' AND CTRL_MASK,'R' ; ctrl-pgup
db 0,0 ; 2. Null damit bei not found was geladen
ENDIF
tr_usa db '#','$','@','[','\',']'
db '^','`','{','|','}','~'
tr_french db '#','$','à','°','ç',21
db '^','`','é','ù','è','~'
tr_german db '#','$', 21,'Ä','Ö','Ü'
db '^','`','ä','ö','ü','ß'
tr_english db '£','$','@','[','\',']'
db '^','`','{','|','}','~'
tr_danish db '#','$','@','Æ','Θ','Å'
db '^','`','æ','φ','å','~'
tr_swedish db '#','$','É','Ä','Ö','Å'
db 'Ü','é','ä','ö','å','ü'
tr_italian db '#','$','@','°','\','é'
db '^','ù','à','ò','è','ì'
tr_spanish db '₧','$','@','î','Ñ','¿'
db '^','`','~','ñ','}','~'
tr_end equ this byte
tr_tab_poi dw offset tr_usa
char_tran_flag db FALSE
cursor_size dw (?)
cursor_on_flag db TRUE
cursor_pos dw 0
txt_attribute db 7
ESC_flag db FALSE
ctrl_paramcount db 0
ctrl_address dw (?)
ctrl_buf_entries db 0
ctrl_buf_poi dw offset ctrl_buf
ctrl_buf db 10 dup (?)
; Struktur zur beschreibung der einzelnen Bildschirmtreiberfunktionen
termfkt struc
db (?) ; Funktionsnummer
db (?) ; Paramameterzahl
dw offset (?) ; Adresse des zugehoerigen UPs
termfkt ends
; Tabelle fuer Terminalfunktionen des Schneider CPC
; (noch nicht alle Funktionen implementiert)
CPC_tab termfkt <0,0,dummy_rout>
termfkt <1,0,dummy_rout>
termfkt <2,0,cursor_off>
termfkt <3,0,cursor_on>
termfkt <4,0,dummy_rout>
termfkt <5,0,dummy_rout>
termfkt <6,0,dummy_rout>
termfkt <7,0,char_out> ; Bell macht Bios
termfkt <8,0,char_out> ; csr left macht bios
termfkt <9,0,csr_right>
termfkt <10,0,char_out> ; csr down macht bios
termfkt <11,0,csr_up>
termfkt <12,0,clear_screen>
termfkt <13,0,csr_to_lstart>
termfkt <14,0,dummy_rout>
termfkt <15,0,dummy_rout>
termfkt <16,0,clr_chr_at_cursor>
termfkt <17,0,del_line_to_cursor>
termfkt <18,0,del_line_from_cursor>
termfkt <19,0,clear_window_to_cursor>
termfkt <20,0,clear_window_from_cursor>
termfkt <21,0,dummy_rout>
termfkt <22,0,dummy_rout>
termfkt <23,0,dummy_rout>
termfkt <24,0,txt_inverse>
termfkt <25,0,dummy_rout>
termfkt <26,0,dummy_rout>
termfkt <27,0,use_esc_tab>
termfkt <28,0,dummy_rout>
termfkt <29,0,dummy_rout>
termfkt <30,0,cursor_home>
termfkt <31,2,set_cursor>
db 0ffh ; sentinel
; Tabelle fuer Terminalfunktionen von CP/M Plus
; (noch nicht alle Funktionen implementiert)
ESC_tab label byte
; die erste Routine stammt nicht von CP/M Plus, sondern
; ist eigendefiniert (entsprechend zu Epson Druckern)
termfkt <'@',0,Reset_Screen>
termfkt <'0',0,dummy_rout> ; Statuszeile aus
termfkt <'1',0,dummy_rout> ; Statuszeile an
termfkt <'2',1,select_country>
termfkt <'3',1,dummy_rout> ; waehle Bildschirmmodus
termfkt <'A',0,csr_up>
termfkt <'B',0,ESC_csr_down>
termfkt <'C',0,ESC_csr_right>
termfkt <'D',0,ESC_csr_left>
termfkt <'E',0,ESC_clear_screen>
termfkt <'H',0,cursor_home>
termfkt <'I',0,csr_up_scr_down>
termfkt <'J',0,clear_window_from_cursor>
termfkt <'K',0,del_line_from_cursor>
termfkt <'L',0,insert_line>
termfkt <'M',0,delete_line>
termfkt <'N',0,delete_char_at_cursor>
termfkt <'Y',2,ESC_set_cursor>
termfkt <'b',0,dummy_rout> ; setze Zeichenhelligkeit
termfkt <'c',0,dummy_rout> ; setze Hintergrundhelligkeit
termfkt <'d',0,del_line_to_cursor>
termfkt <'e',0,cursor_on>
termfkt <'f',0,cursor_off>
termfkt <'j',0,push_cursor_pos>
termfkt <'k',0,pop_cursor_pos>
termfkt <'l',0,dummy_rout> ; loesche Zeile des Cursors
termfkt <'o',0,del_line_to_cursor>
termfkt <'p',0,inverse_on>
termfkt <'q',0,inverse_off>
termfkt <'r',0,underline_on>
termfkt <'s',0,blink_on>
termfkt <'t',0,blink_off>
termfkt <'u',0,underline_off>
termfkt <'v',0,dummy_rout>
termfkt <'w',0,dummy_rout>
termfkt <'x',0,dummy_rout> ; setze 24x80
termfkt <'y',0,dummy_rout> ; 24x80 wieder weg
db 0ffh ; sentinel
emudata_seg ends
emulator_seg segment para public 'CODE'
assume cs:emulator_seg,ds:emudata_seg,es:nothing,ss:nothing
PUBLIC reset_conout,conout,conin,sel_scr_page,cursor_off,cursor_on
EXTRN prg_exit:far
EXTRN breakflag:byte
reset_conout proc
mov ctrl_buf_entries,0
mov ctrl_paramcount,0
mov ctrl_buf_poi,offset ctrl_buf
ret
reset_conout endp
;
conout proc
;
; console character output aus register c
;
; es gibt zwei Sprungtabellen: ESC_tab für mit ESC eingeleitete
; CP/M Plus Steuercodes und
; CPC_tab für die Steuercodes des CPC
PUSHR <si,di,bp,ax>
mov al,ctrl_paramcount
cmp al,0
jnz short @@not_empty
cmp byte ptr ESC_flag,TRUE
mov byte ptr ESC_flag,FALSE
mov di,offset ESC_tab
jz short @@search_entrie
cmp cl,' '
jnc short @@write_out
mov di,offset CPC_tab
@@search_entrie:
cmp byte ptr [di],0ffh
jz short @@execon ; nicht gefunden
cmp cl,[di]
jz short @@entrie_found
add di,4 ; jeder Eintrag belegt 4 Bytes
jmp short @@search_entrie
@@entrie_found:
mov al,[di+1] ; benoetigte Parameter
cmp al,0
jz short @@execute
mov ctrl_paramcount,al
mov di,[di+2]
mov ctrl_address,di ; Adresse des zugehoerigen UP merken
jmp short @@exit
@@not_empty:
mov bx,ctrl_buf_poi
mov [bx],cl ; Parameter merken
inc bx
mov ctrl_buf_poi,bx
inc ctrl_buf_entries
mov al,ctrl_paramcount
cmp al,ctrl_buf_entries ; alle Parameter komplett ?
jnz short @@exit
mov di,offset ctrl_address - 2
@@execute:
call [di+2]
@@execon:
call reset_conout
jmp short @@exit
@@write_out:
call char_out
@@exit:
POPR <ax,bp,di,si>
ret
conout endp
;
; display 0 terminated string in ds:si
;
use_esc_tab proc
mov byte ptr ESC_flag,TRUE
ret
use_esc_tab endp
;
dummy_rout proc
ret
dummy_rout endp
Reset_Screen proc
call ESC_clear_screen
call cursor_home
call inverse_off
call cursor_on
call underline_off
mov char_tran_flag,FALSE
ret
Reset_Screen endp
push_cursor_pos proc
call get_cursor_pos
mov cursor_pos,dx
ret
push_cursor_pos endp
pop_cursor_pos proc
mov dx,cursor_pos
call bios_set_cursor
ret
pop_cursor_pos endp
get_cursor_pos proc
PUSHR <ax,si,di,bp>
mov ah,3
mov bh,EMU_SCR_PAGE
int 10h
POPR <bp,di,si,ax>
ret
get_cursor_pos endp
cursor_off proc
cmp cursor_on_flag,FALSE
jz short @@exit
PUSHR <ax,bx,cx,si,di,bp>
call get_cursor_pos
mov cursor_size,cx
mov ah,1 ; define cursor
mov cx,0ffffh ; unmoeglicher Wert = Cursor aus
mov bh,EMU_SCR_PAGE
int 10h
mov cursor_on_flag,FALSE
POPR <bp,di,si,cx,bx,ax>
@@exit:
ret
cursor_off endp
cursor_on proc
cmp cursor_on_flag,TRUE
jz short @@exit
PUSHR <ax,bx,cx,si,di,bp>
mov cx,cursor_size
mov ah,1 ; define cursor
mov bh,EMU_SCR_PAGE
int 10h
mov cursor_on_flag,TRUE
POPR <bp,di,si,cx,bx,ax>
@@exit:
ret
cursor_on endp
csr_up_scr_down proc ; ESC I
PUSHR <ax,bx,cx,si,di,bp>
call get_cursor_pos
cmp dh,0 ; vorher schon oben ?
jz short @@is_up
dec dh ; y
call bios_set_cursor
jmp short @@exit
@@is_up:
push dx
mov ah,7 ; scroll down window
mov al,1 ; um eine Zeile
mov bh,txt_attribute
mov cx,0
mov dh,LASTLINE
mov dl,SCRNWIDTH
int 10h
pop dx
call bios_set_cursor
@@exit:
POPR <bp,di,si,cx,bx,ax>
ret
csr_up_scr_down endp
insert_line proc
PUSHR <ax,bx,cx,si,di,bp>
call get_cursor_pos
push dx
; scrolle den Rest des Bildschirms ab Cursorpos eine Zeile nach unten
; Cursorpos bleibt erhalten
mov ah,7 ; scroll down window
mov al,1 ; eine Zeile
mov bh,txt_attribute
mov ch,dh
mov cl,0
mov dh,LASTLINE
mov dl,SCRNWIDTH
int 10h
pop dx
call bios_set_cursor
POPR <bp,di,si,cx,bx,ax>
ret
insert_line endp
delete_line proc
PUSHR <ax,bx,cx,si,di,bp>
call get_cursor_pos
push dx
; scrolle den Rest des Bildschirms ab Cursorzeile+1 eine Zeile nach unten
; Cursorpos bleibt erhalten
mov ah,6 ; scroll up window
mov al,1 ; um eine Zeile
mov bh,txt_attribute
mov ch,dh
mov cl,0
mov dh,LASTLINE
mov dl,SCRNWIDTH
int 10h
pop dx
call bios_set_cursor
POPR <bp,di,si,cx,bx,ax>
ret
delete_line endp
delete_char_at_cursor proc
PUSHR <ax,bx,cx,si,di,bp>
call get_cursor_pos
push dx
@@while: ; WHILE XPos <SCRNWIDTH DO
; schlürfe Rest der Zeile ein
inc dl
cmp dl,SCRNWIDTH
ja short @@endwhile
call bios_set_cursor
call read_from_screen
push ax
dec dl
call bios_set_cursor
pop ax
mov bl,ah ; attribute
mov bh,EMU_SCR_PAGE
mov cx,1
mov ah,9 ; write char
int 10h
inc dl
jmp short @@while
@@endwhile:
pop dx
call bios_set_cursor
POPR <bp,di,si,cx,bx,ax>
ret
delete_char_at_cursor endp
read_from_screen proc ; nach ax
PUSHR <si,di,bp>
mov ah,8 ; bios read from screen
mov bh,EMU_SCR_PAGE
int 10h
POPR <bp,di,si>
ret
read_from_screen endp
csr_up proc
PUSHR <ax,bx,cx,si,di,bp>
call get_cursor_pos
cmp dh,0 ; vorher schon oben ?
jz short @@dont
dec dh
call bios_set_cursor
@@dont:
POPR <bp,di,si,cx,bx,ax>
ret
csr_up endp
ESC_csr_down proc
PUSHR <ax,bx,cx,si,di,bp>
call get_cursor_pos
cmp dh,LASTLINE ; vorher schon unten ?
jz short @@dont
inc dh
call bios_set_cursor
@@dont:
POPR <bp,di,si,cx,bx,ax>
ret
ESC_csr_down endp
ESC_csr_right proc
PUSHR <ax,bx,cx,si,di,bp>
call get_cursor_pos
cmp dl,SCRNWIDTH
jz short @@dont
inc dl
call bios_set_cursor
@@dont:
POPR <bp,di,si,cx,bx,ax>
ret
ESC_csr_right endp
ESC_csr_left proc
PUSHR <ax,bx,cx,si,di,bp>
call get_cursor_pos
cmp dl,0
jz short @@dont
dec dl
call bios_set_cursor
@@dont:
POPR <bp,di,si,cx,bx,ax>
ret
ESC_csr_left endp
csr_right proc
PUSHR <ax,bx,cx,si,di,bp>
call get_cursor_pos
cmp dl,SCRNWIDTH
jz short @@dont
inc dl
call bios_set_cursor
@@dont:
POPR <bp,di,si,cx,bx,ax>
ret
csr_right endp
clear_window proc
PUSHR <ax,bx,cx,si,di,bp>
mov ah,6 ; scroll window
mov al,0 ; clear window
mov bh,txt_attribute
int 10h
POPR <bp,di,si,cx,bx,ax>
ret
clear_window endp
ESC_clear_screen proc
PUSHR <cx,dx>
mov ch,0 ; y oben
mov dh,25 ; y unten
mov cl,0 ; x links
mov dl,SCRNWIDTH ; x rechts
call clear_window
POPR <dx,cx>
ret
ESC_clear_screen endp
clear_screen proc
call ESC_clear_screen
clear_screen endp ; und weiter mit Home
cursor_home proc
push dx
mov dx,0 ; x=y=0
call bios_set_cursor
pop dx
ret
cursor_home endp
set_cursor proc
PUSHR <dx,si>
mov si,offset ctrl_buf
mov dx,[si]
dec dh
dec dl ; offset 1 beim CPC
call bios_set_cursor
POPR <si,dx>
ret
set_cursor endp
ESC_set_cursor proc
PUSHR <dx,si>
mov si,offset ctrl_buf
mov dx,[si]
sub dh,20h
sub dl,20h ; offset 32 bei CP/M Plus
cmp dl,LASTLINE
jna short @@yok
mov dl,LASTLINE
@@yok:
cmp dh,SCRNWIDTH
jna short @@xok
mov dh,SCRNWIDTH
@@xok:
xchg dh,dl
call bios_set_cursor
POPR <si,dx>
ret
ESC_set_cursor endp
;
; dh=y
; dl=x
;
bios_set_cursor proc
PUSHR <ax,cx,si,di,bp>
mov bh,EMU_SCR_PAGE
mov ah,2
int 10h
POPR <bp,di,si,cx,ax>
ret
bios_set_cursor endp
sel_scr_page proc
PUSHR <ax,si,di,bp>
mov ah,5
int 10h
POPR <bp,di,si,ax>
ret
sel_scr_page endp
csr_to_lstart proc ; Cursor an Zeilenanfang
PUSHR <ax,bx,cx,si,di,bp>
call get_cursor_pos
mov bh,EMU_SCR_PAGE
xor dl,dl ; x:= 0
call bios_set_cursor
POPR <bp,di,si,cx,bx,ax>
ret
csr_to_lstart endp
clr_chr_at_cursor proc
mov cx,1 ; 1 char
call clr_chars
ret
clr_chr_at_cursor endp
; Zeichenzahl in cx
clr_chars proc
PUSHR <ax,bx,cx,si,di,bp>
mov al,' '
mov bh,EMU_SCR_PAGE
mov bl,txt_attribute
mov ah,9
int 10h
POPR <bp,di,si,cx,bx,ax>
ret
clr_chars endp
del_line_to_cursor proc
PUSHR <ax,bx,cx,si,di,bp>
call get_cursor_pos
push dx
mov cl,dl ; x
mov dl,0
call bios_set_cursor
mov ch,0
call clr_chars
pop dx
call bios_set_cursor
POPR <bp,di,si,cx,bx,ax>
ret
del_line_to_cursor endp
del_line_from_cursor proc
PUSHR <cx,dx>
call get_cursor_pos
mov cl,SCRNWIDTH
sub cl,dl
mov ch,0
call clr_chars
POPR <dx,cx>
ret
del_line_from_cursor endp
clear_window_to_cursor proc
PUSHR <cx,dx>
call get_cursor_pos
dec dh ; y
mov ch,0
mov cl,0
mov dl,SCRNWIDTH
call clear_window
call del_line_to_cursor
POPR <dx,cx>
ret
clear_window_to_cursor endp
clear_window_from_cursor proc
PUSHR <cx,dx>
call del_line_from_cursor
call get_cursor_pos
inc dh ; y++
mov ch,dh
mov dh,24
mov cl,0
mov dl,SCRNWIDTH
call clear_window
POPR <dx,cx>
ret
clear_window_from_cursor endp
txt_inverse proc
xor txt_attribute,HIGHLIGHT_ATTR
ret
txt_inverse endp
inverse_on proc
or txt_attribute,HIGHLIGHT_ATTR
ret
inverse_on endp
inverse_off proc
and txt_attribute,not HIGHLIGHT_ATTR
ret
inverse_off endp
underline_on proc
and txt_attribute,not UNDERLINE_ATTR
ret
underline_on endp
underline_off proc
or txt_attribute,UNDERLINE_ATTR
ret
underline_off endp
blink_on proc
or txt_attribute,BLINK_ATTR
ret
blink_on endp
blink_off proc
and txt_attribute,not BLINK_ATTR
ret
blink_off endp
;
; jedes Zeichen wird 2 mal ausgegeben, da Funktion 9 nicht den Cursor
; bewegt und Funktion 14 kein Attribut aendert
; dies selbst zu erledigen waere zu aufwendig
; Fkt 14 wird auf jeden Fall benoetigt, da sie u.a. piepsen kann
;
char_out proc
PUSHR <si,di,bp,ax,cx>
mov al,cl ;get to accumulator
cmp al,' ' ; Piepser oder CR ?
jb short @@dont
call char_tran
push ax
mov ah,9
mov bl,txt_attribute
mov bh,EMU_SCR_PAGE
mov cx,1
int 10h ; erst mal Attribut setzen
pop ax
@@dont:
mov ah,14 ; character output
mov bl,txt_attribute
int 10h ; und nochmal um den Cursor weiterzusetzen
POPR <cx,ax,bp,di,si>
ret
char_out endp
char_tran proc
cmp char_tran_flag,FALSE
jz short @@exit
push es
push ds
pop es
mov di,offset tr_usa
mov cx,tr_french-tr_usa
; muss Zeichen uebersetzt werden ?
repnz scasb
pop es
jnz short @@exit
sub di,offset tr_usa ; di:= # zu uebersetzendes Zeichen
dec di ; da scas eins zuviel inct
mov bx,tr_tab_poi
mov al,bx[di]
@@exit:
ret
char_tran endp
select_country proc
mov si,offset ctrl_buf
mov al,[si]
cmp al,7
ja short @@exit
mov byte ptr char_tran_flag,FALSE
cmp al,0
jz @@noflag
mov byte ptr char_tran_flag,TRUE
@@noflag:
mov bl,tr_french-tr_usa ; Eintraege pro Land
mul bl
add ax,offset tr_usa
mov tr_tab_poi,ax
@@exit:
ret
select_country endp
conin proc
;
; console character nach register a
;
; Out: al=ascii
; ah zerstoert
;
IF WS_KEY
mov al,after_ctrl_q
mov after_ctrl_q,0
cmp al,0
jnz @@end_conin
ENDIF
mov ah,0 ; keybord input
push bx
int 16h
pop bx
cmp breakflag,TRUE
mov breakflag,FALSE
jnz short @@nobreak
call prg_exit
jmp conin
@@nobreak:
IF WS_KEY ; erweiterte Codes nach WS übersetzen
cmp al,0
jnz short @@no_extended
push bx
mov bx,offset ext_keys
mov cx,ax
@@cmp_loop:
mov al,[bx] ; extended code
mov after_ctrl_q,0 ; damit es bei Aussprung richtig
cmp al,0
jz short @@no_key_tr ; z = Tabellen ende
cmp al,ch
pushf
inc bx
mov al,[bx] ; CTRL-...
inc bx
mov ah,[bx] ; CTRL-Q-...
inc bx
mov after_ctrl_q,ah
popf
jnz @@cmp_loop
@@no_key_tr:
pop bx
@@no_extended:
ENDIF
; Umlaute werden in CP/M Form übersetzt
push di
push cx
push es
push ds
pop es
mov di,offset tr_french
mov cx,tr_end-tr_french
; muss Zeichen uebersetzt werden ?
repnz scasb
pop es
jnz short @@exit
sub di,offset tr_french ; di:= # zu uebersetzendes Zeichen
dec di ; da scas eins zuviel inct
mov ax,di
mov bx,tr_french-tr_usa
mov dx,0
div bx
mov di,dx
mov bx,offset tr_usa
mov al,bx[di]
@@exit:
pop cx
pop di
; and al,7fh ;strip parity bit von DR vorgeschlagen
@@end_conin:
ret
conin endp
emulator_seg ends
end