Category : Assembly Language Source Code
Archive   : EMAC15ES.ZIP
Filename : Z100.ASM

 
Output of file : Z100.ASM contained in archive : EMAC15ES.ZIP
;History:843,1
;Sun May 07 00:41:05 1989 Move mouse code from pick.asm to z100.asm
;Mon Jan 30 22:58:01 1989 change the parameters to set_screen_color.
;05-17-88 19:40:10 remove definition of scrwait, which is not needed any longer [kdb]
;05-11-88 07:53:56 add the swap_screen_flag.
;04-20-88 08:09:40 null terminate the key buffer.
;03-30-88 23:32:08 add fore_original, back_original.
;03-30-88 20:32:23 the key_buffer was only 12 characters long, two too short. Make it 16.
;03-13-88 23:00:14 add store_debug.

page ,132

comment /

Porting EMACS and Percival to MS-DOS computers other than the Z-100:

This entire file (Z-100.ASM) needs to be re-written, since it contains
all the Z-100 dependencies. The following conventions must be maintained:
1) Never leave this module with DF=1.
2) Never destroy ES.
3) Never MOV AX,DATA, always use the copy in the appropriate segment register.
4) Return NC if a routine succeeds, or fulfills its goals.

/
.xlist

include memory.def


;the only bios call is used by check_for_key
bios_seg segment at 40h
org 27*3
bios_confunc label far
bios_seg ends


data segment byte public

public max_screen_line
max_screen_line db 22 ;number of last text row on screen.

public num_screen_cols
num_screen_cols db 80
db 0 ;in case they access a word.

public computer_name, computer_name_len
computer_name db 'Z100'
computer_name_len equ $-computer_name

fontptr dd 6fh

;the following font pointers point to a font containing the 96 printable
; characters, with the exception of the first which also contains graphics.
; The first font is numbered zero, and has all the Zedit funnies. The
; second font uses the first_font, but does inverse video for the high bit
; characters. The third font and on use the normal control character font to
; print controls. The last font is the internal font, and is used to print
; control chars, etc.
first_font dw ?,? ;fonts zero and one.

controls_ptr label word ;font eight.
dw controls,?

controls label byte
include control.asm


public scan_lines_per_char
scan_lines_per_char db 9 ;used to convert pixel position into character position.


mouse_flag db ?
mouse_buttons db ?


shifted equ 40h
key_names label byte
db ',','Comma',0
db '(','LPar',0
db ')','RPar',0
db 7fh,'Delete',0
db 0a3h+shifted,'D Chr',0
db 0a3h,'I Chr',0
db 0a4h+shifted,'Del Line',0
db 0a4h,'Ins Line',0
db -1,'Timeout',0
db -2,'Left Down',0 ;mouse button key names.
db -3,'Right Down',0
db -4,'Left Up',0
db -5,'Right Up',0
db -6,'Middle Down',0
if 0
db -7,'Middle Up',0
endif
db 0

key_shifted label byte
db 08Dh,'Enter',0
db 095h,'Help',0
db 096h,'F0',0
db 097h,'F1',0
db 098h,'F2',0
db 099h,'F3',0
db 09Ah,'F4',0
db 09Bh,'F5',0
db 09Ch,'F6',0
db 09Dh,'F7',0
db 09Eh,'F8',0
db 09Fh,'F9',0
db 0A0h,'F10',0
db 0A1h,'F11',0
db 0A2h,'F12',0
db 0A5h,'Up Arrow',0
db 0A6h,'Down Arrow',0
db 0A7h,'Right Arrow',0
db 0A8h,'Left Arrow',0
db 0A9h,'Home',0
db 0AAh,'Break',0
db 0ADh,'KP-',0
db 0AEh,'KP.',0
db 0B0h,'KP0',0
db 0B1h,'KP1',0
db 0B2h,'KP2',0
db 0B3h,'KP3',0
db 0B4h,'KP4',0
db 0B5h,'KP5',0
db 0B6h,'KP6',0
db 0B7h,'KP7',0
db 0B8h,'KP8',0
db 0B9h,'KP9',0
db 0,'Unknown',0


key_buffer label byte
db 16 dup(?)


extrn inversing: word

public fore_original, back_original
fore_original db 7
back_original db 0

color_xlat db 0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 4, 5, 2, 3, 6, 7

public swap_screen_flag
swap_screen_flag dw 0

data ends


bios_seg segment at 40h
org 9h
bios_conout label far
bios_seg ends


code segment byte public
assume cs:code, ds:data, es:nothing
;all of the code in this segment is called with the above assumes.


printchar:
call bios_conout
ret


public init_entry
init_entry:
;called when entering. May destroy any but seg-regs.
push es
xor ax,ax
mov es,ax
mov ax,es:3feh ;the monitor segment
mov word ptr fontptr+2,ax
les si,fontptr
mov ax,es:[si]
mov first_font,ax
mov bx,es:[si+2]
mov first_font+2,bx
pop es
mov controls_ptr+2,ds
mov al,'y' ;disable key expansion
call printesc
mov al,'?'
call printchar
mov al,'y'
call printesc
mov al,'1'
call printchar
mov al,'x'
call printesc
mov al,'1'
call printchar
mov dx,0*256 + 49 ;try to put the cursor way down low.
call position_cursor
push ds ;see if it got there.
xor ax,ax
mov ds,ax
mov ds,ds:[3feh]
mov al,ds:[292h]
pop ds
cmp al,49 ;go if it didn't
jne init_entry_1
mov max_screen_line,47 ;it did - remember the last scrollable line.
init_entry_1:
ret


public uninit_exit
uninit_exit:
;called when exiting. May destroy any but seg-regs.
call restore_font
mov al,'x' ;enable key expansion
call printesc
mov al,'?'
call printchar
mov al,'y' ;disable the 25th line.
call printesc
mov al,'1'
call printchar
mov dh,0 ;put the cursor on the last scrollable line.
mov dl,max_screen_line
inc dl
call position_cursor

ret


restore_font:
push es
les si,fontptr
mov ax,first_font
mov es:[si],ax
mov ax,first_font+2
mov es:[si+2],ax
pop es
ret


public read_ibm_cga
read_ibm_cga:
xor al,al
ret


public store_ibm_cga
store_ibm_cga:
ret



;this routine should check for a break character. Return cy if none,
; nc if we should break.
public check_breakchar
check_breakchar:
push ax
call check_for_key
jz check_breakchar_1
cmp ax,7 ;^G?
jne check_breakchar_1
call get_key_value
clc
pop ax
ret
check_breakchar_1:
stc
pop ax
ret


public check_for_key
check_for_key:
;return zr if no key is waiting.
;return nz,ax=key if a key is waiting, but don't input the key yet.
push bx ; Save regs
push di
push si
push dx
push ax
mov ah,4 ; get look function
call bios_confunc ; get copy of first char in queue, empty?
mov bl,0 ; assume queue empty, was it ?
jc check_for_key_1 ; yes, skip
mov bl,al ; no, save char
check_for_key_1:
mov al,0ffh ; get -1
adc al,0 ; set 'z' flag appropriately
pop ax ; recover ax
mov al,bl ; get char
pop dx ; restore regs
pop si
pop di
pop bx
mov ah,0
ret


public get_key_value
get_key_value:
mov ah,7
int 21h
mov ah,0
ret


public decode_key
decode_key:
;enter with al=key value.
;exit with si,cx -> the key's name in ASCII.
mov di,offset key_buffer
mov ah,al
mov si,offset key_names
call decode_search ;search for the literal names.
jne decode_key_1
mov si,offset key_shifted ;search for the unshifted versions.
call decode_search
jne decode_key_1
push ax ;save the key's value.
and ah,not shifted ;search for the shifted versions.
mov si,offset key_shifted ;search for the unshifted versions.
call decode_search
pop ax ;restore the key's value.
jne decode_key_5 ;prefix with "S-"
mov al,ah
cmp al,' ' ;control char?
jb decode_key_3 ;yes.
stosb ;no - just return the char.
jmp decode_key_2
decode_key_3:
mov word ptr [di],'C' + '-'*256
add di,2
add al,'@'
cmp al,'A'
jb decode_key_4
cmp al,'Z'
ja decode_key_4
add al,20h ;convert to lower case.
decode_key_4:
stosb
jmp decode_key_2
decode_key_5:
mov word ptr [di],'S' + '-'*256
add di,2
decode_key_1:
lodsb ;copy to the next null.
stosb
or al,al
jne decode_key_1
dec di ;don't include the null.
decode_key_2:
xor al,al ;terminate with a null
stosb
mov si,offset key_buffer
ret


decode_search:
;enter with ah=key to search for, si->table.
;exit with al=key, nz if found, al=0, zr if not found.
lodsb
or al,al ;end of table?
je decode_search_2 ;yes - try shifted values.
cmp al,ah ;is this the key?
je decode_search_2 ;yes.
decode_search_1:
lodsb ;skip to the next null.
or al,al
jne decode_search_1
jmp decode_search
decode_search_2:
or al,al
ret

printesc:
;print an escape followed by the char in al.
push ax
mov al,'['-40h
call printchar
pop ax
call printchar
ret


public store_debug
store_debug:
ret ;regrettably, the Z-100 screen isn't fast enough for this.


public ring_the_bell
ring_the_bell:
mov al,'G'-40h
call printchar
ret

code ends

code segment byte public
assume cs:code, ds:nothing, es:data
;all of the code in this segment is called with the above assumes.

public position_cursor
position_cursor:
;enter with dh=col (0...num_screen_cols), dl=row (0..max_screen_line)
;exit with cursor set to that position.
mov al,'Y'
call printesc
mov al,dl
add al,' '
call printchar
mov al,dh
add al,' '
call printchar
ret


public solid_cursor
solid_cursor:
mov al,'x'
call printesc
mov al,';'
call printchar
ret


public blink_cursor
blink_cursor:
mov al,'y'
call printesc
mov al,';'
call printchar
ret


public block_cursor
block_cursor:
mov al,'x'
call printesc
mov al,'4'
call printchar
ret

public underscore_cursor
underscore_cursor:
mov al,'y'
call printesc
mov al,'4'
call printchar
ret


public set_screen_color
set_screen_color:
;enter with si -> color list. Ignore control color and whitespace color.
mov al,'m'
call printesc
mov bx,offset color_xlat
lodsb
xlat ;translate from the stupid ibm scheme.
add al,'0' ;print the fore color number.
call printchar
lodsb ;print the back color number.
xlat
add al,'0'
call printchar
ret


public move_line
move_line:
;enter with dl=source row, al=destination row.
push ax
push bx
push cx
push dx
push si
push di
push bp
push es
push ds
;start pushing mtr_mdl parameters
push dx ;source line.
push ax ;destination line.
xor ax,ax
mov ds,ax
mov ds,ds:3feh ;the monitor segment
call dword ptr ds:[77h] ;mtr_mdl
pop ds
pop es
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret


public clear_to_eol
clear_to_eol:
;enter with dl=current row, dh=current column.
push bx
mov bl,num_screen_cols
call clear_count
pop bx
ret


public clear_count
clear_count:
;enter with dl=current row, dh=current column, bl=column to clear to.
cmp dh,bl ;already past it?
jae clear_count_1 ;yes.
push ax
push bx
push cx
push dx
push si
push di
push bp
push es
push ds
;start pushing edc parameters.
push dx ;push row,
xchg dl,dh
push dx ;push col.
sub bl,dl
push bx ;push count of columns to clear.
xor ax,ax
mov ds,ax
mov ds,ds:3feh ;the monitor segment
call dword ptr ds:[67h] ;mtr_edl
pop ds
pop es
pop bp
pop di
pop si ;restore saved registers.
pop dx
pop cx
pop bx
pop ax
clear_count_1:
ret


public xychrout
xychrout:
;enter with dh=col, dl=row, al=character to print, ah=font to print it in.
push ax ;save everything that we might need.
push bx
push cx
push dx
push di
push si
push es
push ds
cmp dh,num_screen_cols ;past the right margin?
jae xychrout_3 ;yes - don't print.
mov si,offset first_font
cmp ah,0 ;font zero?
jne xychrout_5 ;no - print specially.
mov bx,0 ;assume no inverse video
cmp al,80h-'^'+7fh
jb xychrout_1 ;print all normal chars normally.
jmp short xychrout_0
xychrout_5:
mov si,offset controls_ptr
xor bx,bx ;assume no inverse video.
or al,al ;high bit set?
jns xychrout_1 ;no - no inverse video.
xychrout_0:
not bx
and al,7fh
xychrout_1:
xor bx,inversing ;set the inverse video flag.
cmp al,' ' ;print controls specially.
jb xychrout_2
cmp al,7fh ;print delete specially.
je xychrout_4
sub al,' '
jmp short xychrout_6
xychrout_4:
sub al,7fh-2fh ;convert del to proper index in control font.
xychrout_2:
mov si,offset controls_ptr
xychrout_6:
mov cx,es ;ensure that ds:si ->font pointer.
mov ds,cx
les di,fontptr
movsw
movsw
push ds
;push four words as parameters to mtr_dfc
xchg dh,dl
push dx ;push col first
xchg dh,dl
push dx ;push row next.
push ax ;push font index.
push bx ;push inverse video flag.
xor ax,ax
mov ds,ax
mov ds,ds:3feh ;the monitor segment
call dword ptr ds:[5fh] ;mtr_dfc
pop ds
call restore_font
xychrout_3:
pop ds
pop es
pop si
pop di
pop dx
pop cx
pop bx
pop ax
ret


public hardware_roll_down
hardware_roll_down:
;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
; otherwise, exit with cy=1. The hardware roll must leave the last line
; on the screen as the last line.
;preserve bx.
cmp ah,0
jnz no_hardware_roll
cmp al,max_screen_line
jnz no_hardware_roll
push dx
mov al,max_screen_line ;move the lower status line up.
mov dl,al
inc dl
call move_line ;dl=source, al=dest.
pop dx
mov al,'H' ;home up.
call printesc
mov al,'I' ;reverse index.
call printesc
clc
ret
no_hardware_roll:
stc
ret


public hardware_roll_up
hardware_roll_up:
;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
; otherwise, exit with cy=1. The hardware roll must leave the last line
; on the screen as the last line.
;preserve bx.
cmp ah,0
jnz no_hardware_roll
cmp al,max_screen_line
jnz no_hardware_roll
push dx
mov dl,max_screen_line
inc dl
mov dh,0
call position_cursor
mov al,LF ;roll the screen up.
call printchar
mov al,max_screen_line ;move the lower status line up.
mov dl,al
dec dl
call move_line ;dl=source, al=dest.
pop dx
clc
ret


public pick_init, pick_on, pick_off, check_pick, get_pick_values
pick_init:
call mouse_exists
mov ax,0
int 33h
mov mouse_flag,al ;remember if the mouse exists.
mov mouse_buttons,bl ;remember the number of buttons.
mov ax,4 ;move the mouse to the upper right hand.
mov cx,635
mov dx,0
int 33h
mov ax,10 ;set text cursor (ignored on Z-100).
mov bx,0 ;software text cursor.
mov cx,77ffh ;screen mask
mov dx,7700h ;cursor mask
int 33h

mov al,max_screen_line ;compute the "number of scan lines"
add al,2
mul scan_lines_per_char
dec dx
mov dx,ax ;set the "number of scan lines"
mov cx,0
mov ax,8
int 33h

mov al,8 ;we're assuming nine bits per char.
mul num_screen_cols
dec ax
mov dx,ax ;set the "number of bit columns"
mov cx,0
mov ax,7
int 33h

call check_pick ;ensure that there are no up or down
call check_pick ; events left.
call check_pick
call check_pick
call check_pick
call check_pick
ret


pick_on:
call mouse_exists
mov ax,1
int 33h
ret


pick_off:
call mouse_exists
mov ax,1 ;ensure that we work with MOUSEKEY.
int 33h
mov ax,2
int 33h
ret


check_pick:
;return nz and al=pick character. return zr if no pick.
call mouse_exists
push bx
push cx
push dx
cmp mouse_flag,0 ;inhibit mouse presses if it isn't there.
je check_pick_1
mov ax,5
mov bx,0 ;left button press
int 33h
mov ax,0feh
or bx,bx
jne check_pick_1
mov ax,5 ;right button press
mov bx,1
int 33h
mov ax,0fdh
or bx,bx
jne check_pick_1
mov ax,6 ;left button release
mov bx,0
int 33h
mov ax,0fch
or bx,bx
jne check_pick_1
mov ax,6 ;right button release
mov bx,1
int 33h
mov ax,0fbh
or bx,bx
jne check_pick_1
cmp mouse_buttons,2 ;do we have only two buttons?
je check_pick_1 ;yes - no pick.
mov ax,6 ;middle button release
mov bx,2
int 33h
mov ax,0f9h
or bx,bx
jne check_pick_1
mov ax,5 ;middle button press
mov bx,2
int 33h
mov ax,0fah
or bx,bx
jne check_pick_1
check_pick_1:
pop dx
pop cx
pop bx
ret

get_pick_values:
mov cx,0
mov dx,0
call mouse_exists
mov ax,3
int 33h

push cx ;save the x value.

mov ax,dx
div scan_lines_per_char
mov ah,0
push ax
call read_linesbefore
push ax
call read_newrow
pop bx
sub bx,ax ;bx=linesbefore - newrow.
pop dx
add dx,bx ;add y-value.
inc dx ;ax= y-value - newrow + linesbefore + 1.
pop ax ;compute the x-value.

push dx

mov cl,8
div cl
mov ah,0
inc ax
push ax ;add in firstcolumn.
call read_firstcolumn
pop cx
add cx,ax

pop dx

ret

extrn read_firstcolumn: near
extrn read_linesbefore: near
extrn read_newrow: near


;this routine returns from the routine that called it if the mouse is not
; installed.
mouse_exists:
push ds
xor ax,ax
mov ds,ax
mov ax,word ptr ds:[33h*4+2]
pop ds
cmp ax,0 ;any mouse interrupt at all?
je mouse_exists_2 ;no - no mouse.
cmp ax,40h ;is the mouse interrupt in the bios?
jne mouse_exists_1 ;no - must be a real mouse.
mouse_exists_2:
add sp,2
xor ax,ax
ret
mouse_exists_1:
ret

code ends

end


  3 Responses to “Category : Assembly Language Source Code
Archive   : EMAC15ES.ZIP
Filename : Z100.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/