Back when my only machine was an Amstrad PCW, I used it to take my first tentative steps onto the Internet. Within 24 hours of getting on-line, I realised that the VT100 emulation offered by programs such as COMM+ and QTERM was rather inadequate. Keyboard redefinition was missing, along with attributes like bold and underlining. Instead, these various attributes were all mapped to the single property of inverse video, making the use of programs like the popular text only Web browser Lynx very confusing. Furthermore, otherwise great programs like ZMP are let down by not having any VT100 emulation whatsoever.
And so EMU was born out of my own selfish need to browse the Web. Once I had an acceptable VT100 emulation working, I added support for the ISO-8859-1 character set, the preferred character set of the World Wide Web. The PCW actually already supports most of the Latin 1 characters, it's just that they're ordered differently within the PCW's BIOS, so using a hash table look-up system, I only needed to design 17 new characters.
Here, better late than never, is the source of the program. If you only want a binary version of the program, that's OK, too.
A note for users of QTERM: when making catch files, make sure that you don't use option 'J' to junk control characters, as this will remove important display codes from the catch file.
You can turn the VT100 emulation off and remove EMU from memory at any time by typing EMUOFF [RETURN].
If you use [STOP] to interrupt the display of a file containing VT100 escape codes, you may find that one or more highlighting attributes are still set. It is annoying to have to proceed with a combination of inverse video, bold and underlining, so EMU provides the EMURST command. If you type EMURST [RETURN], all textual emphasis will be turned off.
You may find that the remote system you connect with not only expects you to treat the data it sends you as VT100, but also expects to receive its input from you in VT100 form. This usually manifests itself in the refusal of the cursor keys to do anything useful in a menu on the remote system. Should this prove to be a problem, the EMUKEY command should provide the solution. Note that this will only work in combination with communications software that doesn't use the [EXIT] key for its own purposes. COMM+ and ZMP are examples of such programs, although the former allows an alternative key to be defined for this purpose.
If you use such a program, you will have to redefine the keys externally. The file EMU-B.KEY is provided for this purpose. Your CP/M master disc contains a program called SETKEYS, which you should use to install the keyboard definition file. Simply type SETKEYS EMU-B.KEY [RETURN] and the cursor keys will subsequently send the correct control codes.
Regardless of whether you use the EMUKEY command or the EMU-B.KEY file to redefine the keyboard, you will need to remove EMU from memory to restore the keys to their original state. Should it become necessary to return the keys to their default state whilst using EMU (e.g. because you have finished work on- line and now wish to use EMU off-line), you will first have to remove EMU and then reinstall it.
You should note that the built-in EMUOFF, EMURST and EMUKEY commands
will not work from within a .SUB file or Z-system alias. If you wish
to use any of these commands in a .SUB file or alias, you should
instead use the program EMUSUB. This program takes a single parameter
and has the following syntax:
Command | Effect |
---|---|
EMUSUB /O | send EMUOFF command to EMU |
EMUSUB /R | send EMURST command to EMU |
EMUSUB /K | send EMUKEY command to EMU |
EMU works by redirecting the BIOS CONOUT routine to intercept all console output. This is necessary in order to make sure that the screen output of ALL programs is trapped and acted upon. Intercepting at the BDOS level is inadequate, because there can be no guarantee that another program will use the BDOS for its output. Unfortunately, this method has the disadvantage that output redirection can't be acted upon. It is thus impossible to use EMU to make a clean print-out of a file containing VT100 escape codes.
EMU's VT100 emulation isn't complete, but it is the best available for the PCW. Significant features not implemented are:
Although some remote systems attempt to interrogate the calling system
as to its precise specification, a response does not appear to be
essential. The interrogating system simply goes ahead with VT100
transmission anyway.
EMU's VT100 emulation is based on the specification outlined in the 'Digital VT100 Programming Reference Card'.
Details of the ISO-8859-1 specification were obtained from Martin Ramsch's excellent overview.
Further interesting details on ISO-8859-1 were obtained from the ISO-8859
FAQ by Michael Gschwind.
EMU was written to be compiled with M$'s M80 assembler and linked with the standard Digital Research linker, LINK.COM. GENCOM is also needed to turn the relocatable code into an RSX, or TSR if you come from an M$-DOS background.
FYNDE is a CP/M implementation of UNIX's grep (or, if you prefer, M$-DOS's FIND) and is useful for locating entry points in the code to make sure they tally with the source. You will find it very useful if you intend on modifying the source to EMU.
In short, the following EMU.SUB file will make life somewhat easier when assembling. Note that it must be called EMU.SUB to work.
m80 =$0
link $0
m80 $02,$02=$02
link $02[op]
era $02.rsx
ren $02.rsx=$02.prl
gencom $0 $02
era $0?.rel
era $0?.sym
fynde $02.prn vtoffx:
fynde $02.prn emul:
fynde $02.prn conorg:
If you've got any questions about the code, you can drop me a line,
but be warned that this was the last program for CP/M on the PCW that
I ever programmed, and a few years have passed since then. In
other words, the code looks barely any more familiar to me than to you.
This file contains the equates used by all the other source files.
;EMUEQU.MAC - equates used by EMU1.MAC, EMU2.MAC, EMURST.MAC and EMUOFF.MAC
no equ 0
yes equ not no
wrmboot equ 0
BDOS equ 5 ;BDOS entry point
defDMA equ 080h ;default DMA buffer
charram equ 0b800h ;start of character matrix RAM
SCB equ 0fb9ch ;System Control Block
emuins equ SCB+9 ;4th user byte in SCB for use as installation status flag
conmode equ SCB+033h ;console mode. Bit 2 controls tab expansion
curDMA equ SCB+03ch ;address of current DMA buffer stored here
conout equ 0fc0dh ;jump-table entry to BIOS CONOUT routine
userf equ 0fc5ah ;address of BIOS USERFunction
teask equ 0bfh ;offset to XBIOS TE ASK routine
setexp equ 0d4h ;offset to XBIOS SET EXPAND routine
scrrun equ 0e9h ;offset to XBIOS SCR RUN routine
print equ 9
input equ 10
nul equ 0
beep equ 7
tab equ 9
lf equ 10
cr equ 13
ESC equ 27
zpm3 equ no ;set 'yes' if ZPM3 BDOS fitted and you're feeling lucky
iso8859 equ yes ;set 'yes' if support for ISO-8859-1 (Latin 1) character
;set required
xcls equ no ;ANSI systems expect the 'clear screen' sequence
;(ESC [ 2 J) to additionally home the cursor. Some
;systems also expect ASCII 12 to do this.
;set 'yes' if you need support for such a system
We try and do as much as possible in this file, since this is the transient part of EMU. When run, this part does some sanity checking and character redefinition, and then exits, leaving EMU2 loaded as an RSX and the BIOS's CONOUT routine redirected through it.
title EMU1 v1.02 2/12/95
subttl (c) Ian Macdonald (ianmacd@xs4all.nl)
.comment |
EMU provides a rudimentary VT100 emulation for the Amstrad PCW's VT52 terminal. Whilst
the VT100 implementation is not complete, it is superior to that offered by comms
programs such as COMM+ and QTERM.
Commands available:
EMU installs the RSX and turns VT100 emulation on.
EMURST resets highlighting attributes.
EMUOFF resets highlighting attributes, turns VT100 emulation off and removes the RSX.
EMUKEY configures cursor keys to produce VT100 keys.
v1.00 14/7/95 - first official release (identical to v0.14 beta)
v1.01 5/8/95 - bug which caused unimplemented escape codes to affect screen display
under certain circumstances fixed
v1.02 2/12/95 - EMUKEY command added for redefining cursor keys to VT100
|
include EMUEQU.MAC ;get equates
;The VTOFF, EMUL and CONORG entry points move according to the ZPM3 and ISO8859 equates
;in EMUEQU.MAC (which control conditional assembly in EMU2.MAC). The VTOFFX, EMUL and
;CONORG equates in this file control assembly of the correct addresses.
vtoffx set 0c9h ;jump offset to relevant part of routine in RSX
emul set 0d2h ;jump offset to routine in RSX
conorg set 02e0h ;jump offset to routine in RSX
if zpm3
conorg set conorg+2
if1
.printx * Assembling ZPM3 version of EMU1... *
endif
endif
if iso8859
vtoffx set vtoffx+00fh
emul set emul+031h
conorg set conorg+050h
if1
.printx * Assembling ISO-8859-1 (Latin 1) character set version of EMU1... *
endif
endif
if xcls
conorg set conorg+10
if1
.printx * Assembling with non-standard 'clear screen' sequences... *
endif
endif
.z80
ld de,signon
call display ;display sign-on message
ld a,(emuins)
cp 'E' ;is EMU already installed?
jr z,fail1 ;if so, abort
ld a,(BDOS+2)
cp 0c1h ;have we got enough common memory to play with?
jr c,fail2 ;if not, bye-bye
success:ld a,'E'
ld (emuins),a ;set installation flag
if iso8859
ld de,charram+180*8 ;180 is first character to replace
ld hl,newchar ;start of new character data
ld bc,6*8 ;6 characters of each 8 bytes
ld a,082h
di ;disable interrupts
out (0f2h),a ;switch in block 2 at 8000h-bfffh
ldir ;load characters 180 to 185
ld de,charram+187*8 ;187 is next character to replace
ld c,2*8 ;2 characters of each 8 bytes
ldir ;load characters 187 to 188
ld de,charram+191*8 ;191 is next character to replace
ld c,1*8 ;1 character of 8 bytes
ldir ;load character 191
ld de,charram+220*8 ;220 is next character to replace
ld c,4*8 ;4 characters of each 8 bytes
ldir ;load characters 220 to 223
ld de,charram+252*8 ;252 is next character to replace
ld c,4*8 ;4 characters of each 8 bytes
ldir ;load characters 252 to 255
ld a,086h
out (0f2h),a ;replace block 6
ei
endif
ld de,conorg+1
ld a,(BDOS+2)
ld h,a
ld l,0
add hl,de ;get actual address of CONORG in HL
ld (corg+1),hl ;store it
ld hl,(conout)
corg: ld (0000),hl ;save original CONOUT address
ld de,emul
ld h,a
ld l,0
add hl,de ;get address of RSX's EMUL routine in HL
ld (conout),hl ;redirect CONOUT via EMU
ld de,instal ;display installation message
display:ld c,print
jp BDOS
fail1: ld de,alinst
jr exit
fail2: ld de,nomem
exit: call display ;display installation failure message
ld a,(BDOS+2)
ld h,a
ld l,vtoffx ;get address of relevant part of RSX's VTOFF routine
jp (hl) ;execute it
if iso8859
newchar:db 195,60,102,102,102,60,195,0 ;international currency symbol
db 0,0,0,126,6,0,0,0 ;negation sign (logical NOT)
db 126,0,0,0,0,0,0,0 ;spacing macron
db 0,24,24,126,24,24,126,0 ;+/- sign
db 24,36,8,16,60,0,0,0 ;superscript 2
db 24,36,8,36,24,0,0,0 ;superscript 3
db 0,0,204,204,204,204,246,192 ;micro sign (lower case Mu)
db 0,0,0,0,0,0,24,56 ;spacing cedilla
db 16,48,16,16,56,0,0,0 ;superscript 1
db 248,108,102,246,102,108,248,0 ;upper case Eth
db 0,0,0,108,56,108,0,0 ;multiplication sign
db 12,24,102,60,24,24,24,0 ;upper case Y-acute
db 224,124,102,102,102,124,224,0 ;upper case Thorn
db 192,96,252,24,124,198,124,0 ;lower case Eth
db 0,0,24,0,126,0,24,0 ;division sign
db 12,24,102,102,102,62,6,124 ;lower case Y-acute
db 0,240,96,124,102,124,96,96 ;lower case Thorn
endif
signon: db 'EMU '
if xcls
db '(ANSI) '
else
if not iso8859
db '(ASCII) '
endif
endif
db 'v1.02 2/12/95 (c) Ian Macdonald (ianmacd@xs4all.nl)'
db cr,lf,lf,'$'
instal: db 'VT100 emulation now on. Commands available:',cr,lf,lf
db 'EMUOFF - uninstall emulator.',cr,lf
db 'EMURST - reset highlighting attributes.',cr,lf
db 'EMUKEY - install VT100 cursor keys.',cr,lf,'$'
alinst: db beep,'ERROR: EMU already installed.',cr,lf,'$'
nomem: db beep,'ERROR: not enough memory. Please remove some RSXes.',cr,lf,'$'
end
OK, this is the beef of the program. This part is the RSX that gets installed when EMU is run and handles all the emulation, command handling and restoration when EMU is removed from memory.
It's not always very pretty and I've probably broken some golden rules, but it had to be as fast as possible, so I optimised for speed instead of legibility.
title EMU2 v1.02 2/12/95
subttl (c) Ian Macdonald (ianmacd@xs4all.nl)
.comment |
EMU provides a rudimentary VT100 emulation for the Amstrad PCW's VT52 terminal. Whilst
the VT100 implementation is not complete, it is superior to that offered by comms
programs such as COMM+ and QTERM.
Commands available:
EMU installs the RSX and turns VT100 emulation on.
EMURST resets highlighting attributes.
EMUOFF resets highlighting attributes, turns VT100 emulation off and removes the RSX.
EMUKEY configures cursor keys to produce VT100 keys.
v1.00 14/7/95 - first official release (identical to v0.14 beta)
v1.01 5/8/95 - bug which caused unimplemented escape codes to affect screen display
under certain circumstances fixed
v1.02 2/12/95 - EMUKEY command added for redefining cursor keys to VT100
Further information:
1. Conditional assembly is provided to support the entire ISO-8859-1 (Latin 1) character
set. This is the preferred character set on the Internet. The HTTP protocol used by
World Wide Web browsers guarantees the integrity of 8 bit transmission. Furthermore,
some people break the 'rule' of only using true ASCII (ISO-646) characters in e-mail
and Usenet messages. As a consequence, characters with an ASCII value greater than 159
are almost always incorrectly displayed by the PCW, which has a non-standard character
set. Set the 'iso8859' equate in EMUEQU.MAC if required.
2. If you assemble EMU with support for the ISO-8859-1 character set (see point 1 above),
then you will be unable to correctly display native PCW documents containing
characters with ASCII values greater than 159. This is because these values are
remapped by EMU to display the Latin 1 characters. Some characters are even redefined.
3. Conditional assembly is provided for the implementation of bold. If you have installed
Simeon Cran's ZPM3 replacement BDOS, you have the option of setting the 'zpm3' equate
in EMUEQU.MAC. This will give you a faster bold routine, but also makes the program
slightly unstable. When assembled in this way, EMU may cause a crash if you
subsequently run a program which extends into memory between 8000h and BFFFh. In
practice, there will only be a danger of this if the program in question is larger
than 32k. COMM+ (36k) seems to work without problems. If using EMU in this way, I
strongly recommend that you make a point of immediately uninstalling EMU after using
any application that requires it. However, I would strongly suggest that you don't use
this option at all! Note that setting the 'zpm3' equate _guarantees_ a crash on
systems still using the original Digital Research BDOS. In short, set this equate at
your own risk!
4. Some systems erroneously expect the 'clear screen' sequence (ESC [ 2 J) to
additionally home the cursor. I am also informed that some systems expect ASCII 12 to
do the same. If you encounter such a system, set the 'xcls' equate in EMUEQU.MAC.
These non-standard features will then be supported.
5. The 4th SCB user byte is used as an installation status flag. This could cause
conflicts if also used by other programs. As a consequence, there is a very remote
chance that EMU may erroneously report that it is already installed when you attempt
to install it. Likewise, there is a slightly greater chance that double installation
may occur. A software reset is highly recommended in this latter case.
Further improvements to be made:
Any features not required by the Lynx WWW browser have been omitted for speed.
1. Highlighting attribute 5 (blink) would be nice, but probably impossible on the PCW.
2. Alternate character sets would be nice, but what software needs them?
3. Double height/width would be nice, but again, what software needs them?
4. Terminal interrogation support, particularly 'What are you?' (ESC [ c or ESC [ 0 c).
This is used by some BBS systems, but doesn't appear to be essential. The
interrogating system simply goes ahead with VT100 transmission anyway after receiving
a null response.
5. Implementation of scrolling regions, but probably superfluous. This would also be
destructive if EMU was installed under a program which defined its own windows, as the
PCW cannot cope with multiple windows.
Bugs and incompatibility:
1. EMU causes a crash when ZMP patched with ZMP15PCW.MAC dated 16/6/95 is run. This is
because both EMU and ZMP make use of the Z80 alternate register set in their screen
display routines. The version of ZMP15PCW.MAC dated 28/6/95 solves this. There should
be no conflicts with other communications software, unless screen output goes directly
via the BIOS, using the alternate registers without preserving them.
2. Any CP/M program which uses ESC M (delete line containing cursor and scroll rows below
up one line) while EMU is installed will not behave as expected. This is because ESC M
means 'reverse index' in VT100.
3. The character produced by the sequence ESC ESC (lower case Tau) cannot be displayed
while EMU is installed.
|
include EMUEQU.MAC ;get equates
if zpm3
if1
.printx * Assembling ZPM3 version of EMU2... *
endif
endif
if iso8859
if1
.printx * Assembling ISO-8859-1 (Latin 1) character set version of EMU2... *
endif
endif
if xcls
if1
.printx * Assembling with non-standard 'clear screen' sequences... *
endif
endif
.z80
;standard RSX header
serial: db 0,0,0,0,0,0
start: jp rsx
next: jp next
prev: dw 7
remove: db no
nonbank:db 0
name: db 'EMU '
loader: db 0
spare: ds 2
;general housekeeping
rsx: ld hl,conmode
set 2,(hl) ;turn off tab expansion (just doing it is much quicker
;than testing whether a print function is being called).
;we must repeatedly turn it off in case another program
;turns it back on
ld a,c
cp 10 ;BDOS 10 ?
jr nz,next ;if not, pass to BDOS (or next RSX)
ld (stadd),sp ;save calling program's stack
ld sp,tstack ;create our own
push de ;save BDOS 10 buffer location
call next ;get line input
pop hl ;get buffer location in HL
ld sp,(stadd) ;restore stack
ld a,h
or l ;is buffer at 0 ?
jr nz,getnr ;if not, standard call used
ld hl,(curDMA) ;otherwise, use current DMA buffer
getnr: inc hl
ld a,(hl) ;get number of bytes in buffer
cp 6 ;EMUOFF and EMURST commands = 6 characters each
ret nz ;if different, return to calling program
ex de,hl ;get buffer in DE
ld hl,command ;start of command table
ld bc,6 ;6 bytes in each command
loop1: call testch ;test for valid command
jr z,vtoff ;if fully matched, EMUOFF
inc hl
inc hl ;otherwise, bump up command table pointer
ld bc,3 ;3 characters to test (RST)
dec de ;prepare buffer pointer
loop2: call testch ;test for valid command
if iso8859
jp z,exit ;matched EMURST: turn attributes off and exit
else
jr z,exit ;matched EMURST: turn attributes off and exit
endif
inc hl
inc hl ;otherwise, bump up command table pointer
ld bc,0303h ;C (decremented by CPI) mustn't get in the way of B
loop3: ld a,(de) ;get input character
or 32 ;convert to lower case
cpi ;compare with command table
ret nz ;return to calling program if no match
inc de ;bump up buffer pointer
djnz loop3 ;loop if we've still got a match
emukey: ld bc,09103h ;expansion token 091h, 3 characters long
ld hl,curup ;address of new data
call setkey ;install token
ld bc,09303h ;expansion token 093h, 3 characters long
ld hl,curlft ;address of new data
call setkey ;install token
ld bc,09403h ;expansion token 094h, 3 characters long
ld hl,currgt ;address of new data
call setkey ;install token
ld bc,09603h ;expansion token 096h, 3 characters long
ld hl,curdn ;address of new data
call setkey ;install token
rst wrmboot ;return to CP/M via a warm boot
setkey: call userf
dw setexp
ret
testch: inc de ;bump up buffer pointer
ld a,(de) ;get input character
or 32 ;convert to lower case
cpi ;compare with command table
ret po ;exit loop if we've had all the characters (Z flag set)
jr z,testch ;loop if we've still got a match
ret ;otherwise, return (Z flag not set)
vtoff:
if iso8859
ld de,charram+180*8 ;180 is first character to replace
ld hl,orgchar ;start of original character data
ld bc,restore ;address of routine to restore characters
call userf ;call it
dw scrrun
endif
defkey: ld bc,09101h ;expansion token 091h, 1 character long
ld hl,defup
call setkey ;restore token
ld bc,09301h ;expansion token 093h, 1 character long
ld hl,deflft
call setkey ;restore token
ld bc,09401h ;expansion token 094h, 1 character long
ld hl,defrgt
call setkey ;restore token
ld bc,09601h ;expansion token 096h, 1 character long
ld hl,defdn
call setkey ;restore token
ld hl,(conorg+1)
ld (conout),hl ;restore original CONOUT address
xor a
ld (emuins),a ;set uninstallation flag
vtoffx: ld a,yes
ld (remove),a ;set flag to remove RSX
exit: call noatt ;turn all highlighting attributes off
rst wrmboot ;do a warm boot
if iso8859
restore:ld bc,6*8 ;6 characters of each 8 bytes
ldir ;load characters 180 to 185
ld de,charram+187*8 ;187 is next character to replace
ld c,2*8 ;2 characters of each 8 bytes
ldir ;load characters 187 to 188
ld de,charram+191*8 ;191 is next character to replace
ld c,1*8 ;1 characters of 8 bytes
ldir ;load character 191
ld de,charram+220*8 ;220 is next character to replace
ld c,4*8 ;4 characters of each 8 bytes
ldir ;load characters 220 to 223
ld de,charram+252*8 ;252 is next character to replace
ld c,4*8 ;4 characters of each 8 bytes
ldir ;load characters 252 to 255
ret
endif
;start of the emulator proper
emul: ld hl,hadESC
ld a,c ;get character in A
cp ESC ;is it an ESCape?
jr z,isESC ;if so, skip ahead
ld a,(hl)
or a ;are we in an ESCape sequence?
jp z,norm ;if not, display it as per usual
ld a,(lstch) ;get previous character
cp '?' ;was it a question-mark?
jr nz,ftest ;if not, conduct further tests
ld a,c ;get current character
cp '9'+1 ;is it probably a digit?
ret c ;if so, return
jp resfgs ;otherwise, end of ESC [ ? sequence
isESC: ld (hl),a ;otherwise, flag ESC
ret ;return without displaying
;discover from previous character in ESC sequence what to do with current one
ftest: cp '['
jr z,square
cp '#'
jp z,hash
cp '('
jp z,lftbr
cp ')'
jp z,rgtbr
ld a,c ;if none of the above, get current character
ld (lstch),a ;store it as last character
;if current character is 2nd character in longer ESCape sequence, return without
;displaying it
cp '['
ret z
cp '£'
ret z
cp '('
ret z
cp ')'
ret z
;cp 'E' ;commented out for VT52 compatibility
;jr z,nline
cp 'M'
jr z,revidx ;reverse index
cp '7'
jr z,savcur ;save cursor position
cp '8'
jr z,rescur ;restore cursor position
cp '<'
jr c,dochar ;less than '<'
cp '>'+1
jp c,resfgs ;'>' or less (weed out ESC <, ESC = and ESC > )
dochar: exx ;save character to be printed (in C)
ld c,ESC
call enorm ;send ESC
exx ;retrieve control character
call enorm ;print it
jp resfgs ;reset flags
nline: ;ld c,'B'
;jr dochar ;commented out for VT52 compatibility
revidx: ld c,'I'
jr dochar ;reverse index
savcur: ld c,'j'
jr dochar ;save cursor position
rescur: ld c,'k'
jr dochar ;restore cursor position
square: ld a,c ;get current character in A
cp '0'
jr c,notdgt ;less than a digit
cp '9'+1
jr nc,notdgt ;more than a digit
sub '0' ;convert to real figure
ld c,a ;save in C
ld hl,(lstdgt) ;get address of last digit
ld a,(haddgt)
or a ;already had a digit?
jr z,stordgt ;if not, store this one
ld a,(hl) ;otherwise, get last one, which must represent tens
add a,a ;x 2
ld b,a ;save result in B
add a,a ;x 4
add a,a ;x 8
add a,b ;x 10
add a,c ;+ units
ld (hl),a ;store the new figure
ret
stordgt:ld (hl),c ;store this digit
inc a
ld (haddgt),a ;set flag to signify presence of digit
ld hl,nrdgts
inc (hl) ;bump digit count
ret
notdgt: ld a,(nrdgts)
or a
ld a,c ;get current character in A
jr z,nodgt ;no digit pending
cp ';'
jr z,semic ;digit separator
cp 'm'
jr z,chatt ;set character attributes
cp 'A'
ret c ;less than 'A': ignore
cp 'D'+1
jp c,cursor ;A, B, C or D: move cursor
cp 'H'
jp z,curxy ;move cursor to X,Y
cp 'J'
jp z,erascr ;erase section of screen
cp 'K'
jp z,eraline ;erase section of line
cp 'f'
jp z,curxy ;move cursor to X,Y
;ret ;ignore any other codes
jp resfgs ;ignore any other codes
nodgt: cp 'H'
jr z,dochar
cp 'J'
jr z,dochar ;send straight to screen (same as VT52)
cp 'K'
jr z,dochar ;send straight to screen (same as VT52)
cp 'm'
jr z,noatt
cp ';'
ret z ;digit separator
cp '?'
jr z,qmark
cp 'A'
;ret c ;less than 'A'
jp c,resfgs ;less than 'A'
cp 'D'+1
;ret nc ;greater than 'D'
jp nc,resfgs ;greater than 'D'
jp dochar
semic: ld hl,(lstdgt)
inc hl ;bump pointer to last digit
ld (lstdgt),hl
xor a
ld (haddgt),a ;reset 'had a digit' flag
ret
chatt: ld a,(nrdgts)
ld b,a ;get number of attributes in B
ld hl,dgtbuf ;get start of attribute list in HL
attlp: ld a,(hl) ;get attribute
cp 1 ;bold?
jr nz,ntest ;if not, conduct next test
ld (bold),a ;bold on
jr natt ;get next attribute
ntest: cp 5 ;blink?
jr z,natt ;if so, get next attribute: blink not implemented
cp 8 ;attribute > 7 ?
jr nc,natt ;if so, ignore
ld (curatt),hl ;save address of current attribute
ld (hl),b ;convenient place to save attribute count
or a ;attribute 0 ? (all attributes off)
jr nz,ntest2 ;if not, next test
call noatt ;turn all attributes off
jr recov ;recover attribute address and count
ntest2: cp 7 ;highlight?
jr z,revon ;if so, turn on
ld c,'r' ;otherwise, assume attribute 4 (underline on)
jr dchar
revon: ld c,'p' ;inverse video
dchar: call dochar ;set attribute
recov: ld hl,(curatt) ;recover current attribute address
ld b,(hl) ;recover attribute count
natt: inc hl ;address of next attribute
djnz attlp ;get next attribute
jp resfgs ;reset flags
noatt: xor a
ld (bold),a ;bold off
ld c,'u'
call dochar ;underline off
ld c,'q'
jp dochar ;inverse video off
qmark: ld (lstch),a ;mark as last char. ('?' ESCapes not implemented)
ret
curxy: ld c,'Y'
call dochar ;send ESC for X,Y sequence
ld a,(dgtbuf) ;get Y co-ordinate
call setco ;set Y co-ordinate
ld a,(dgtbuf+1) ;get X co-ordinate
setco: add a,31 ;add offset
ld c,a
jp enorm ;set X co-ordinate
;flags already reset by ESC Y
cursor: ld (direct+1),a ;store cursor direction
ld a,(dgtbuf)
curtab: ld b,a ;get number of positions to move
loop4: exx ;save position count
ld c,ESC
call enorm ;send ESCape
direct: ld c,'?' ;cursor direction is patched here
call enorm ;move cursor
exx ;retrieve position count
djnz loop4 ;go around again
jr resfgs ;reset flags
eraline:ld a,(dgtbuf)
or a
jp z,dochar ;ESC [ 0 K means erase to end of line
dec a
jr z,eralcur ;ESC [ 1 K means erase line up to cursor
eralb: ld c,'l'
jp dochar ;ESC [ 2 K means erase entire line containing cursor
eralcur:ld c,'o'
jp dochar
erascr: ld a,(dgtbuf)
or a
jp z,dochar ;ESC [ 0 J means erase to end of screen
dec a
jr z,scrcur ;ESC [ 1 J means erase from top of screen to cursor
erasb:
if xcls
ld c,'H'
call dochar
endif
ld c,'E'
jp dochar ;ESC [ 2 J means erase entire screen
scrcur: ld c,'d'
jp dochar
;none of the following 3 ESCapes is implemented, so we let them drop into the
;register reset routine
hash: ;jr resfgs
lftbr: ;jr resfgs
rgtbr: ;jr resfgs
resfgs: xor a
ld hl,hadESC
ld (hl),a ;zero hadESC
inc hl
ld (hl),a ;zero haddgt
inc hl
ld (hl),a ;zero lstch
inc hl
ld (hl),a ;zero nrdgts
inc hl ;HL = lstdgt
ld de,dgtbuf
ld (hl),e
inc hl
ld (hl),d ;reset last digit pointer to start of digit buffer
ret
norm: ld a,c
cp tab ;is character a tab?
jr z,istab ;if so, take care of our own tab expansion
if xcls
cp 12
jp z,erasb
endif
cp ' '+1 ;is it a control character or a space?
jr c,enorm ;if so, don't bother to make it bold
if iso8859
sub 160 ;value of first ISO-8859-1 character
jr c,tbold ;if lower, skip ahead
ld d,0
ld b,32
sub b ;ASCII > 191 ?
jr nc,accent ;if so, accented character
add a,b ;otherwise, readjust
ld hl,lookup ;start of look-up table
jr zerob ;get character
accent: inc a ;no upper case Scharfes S
ld hl,accents ;start of accented characters in look-up table
cp b ;is it lower case?
jr c,upcase ;if not, skip ahead
sub b ;adjust for correct position in look-up table
zerob: ld b,d ;zero B for lower case
upcase: ld e,a ;offset to character in DE
add hl,de ;get address in look-up table
ld a,(hl) ;look up accented character
sub b ;if necessary, make it upper case
ld c,a ;put it in C
tbold:
endif
ld a,(bold)
or a
jr z,enorm ;bold not on: process immediately
ld de,charram ;start of character RAM
ld a,c ;get character in A
ld h,0
ld l,a ;get character in HL
add hl,hl
add hl,hl
add hl,hl ;x 8 (multiply ASCII value by 8)
add hl,de ;get address of bit-map in character RAM
ld (chadd),hl ;save it
ld de,cchar ;address to save existing bit-map
if zpm3
ld bc,8 ;8 bytes of character data
ex af,af' ;save ASCII value
ld a,082h
di ;disable interrupts
out (0f2h),a ;switch in block 2 at 8000h-bfffh
ldir ;save bit-map
ld hl,(chadd) ;restore its address in character RAM to HL
ld d,h
ld e,l ;make a copy of the address in DE
ld bc,0808h ;8 bytes to make bold (C is for later)
mbold: ld a,(hl) ;get character data
rra ;rotate data out of true
or (hl) ;superimpose original
ld (hl),a ;save it
inc hl ;get next byte of character data
djnz mbold ;loop
ld a,086h
out (0f2h),a ;replace block 6
ei
ex af,af' ;get ASCII value back in A
exx ;save BC and DE
ld c,a ;get character in C
call enorm ;display bold character
exx ;restore BC and DE
ld hl,cchar ;start of saved bit-map
ld a,082h
di ;disable interrupts
out (0f2h),a ;switch in block 2 at 8000h-bfffh
ldir ;restore original bit-map
ld a,086h
out (0f2h),a ;replace block 6
ei
ret
else
ld bc,scrrt1
call userf ;save bit-map of character and make bold
dw scrrun
call enorm ;display bold character
ld bc,scrrt2
call userf ;restore original bit-map
dw scrrun
ret
scrrt1: ld bc,8 ;8 bytes of character data
ldir ;save bit-map
ld c,a ;save ASCII value of character in C
ld hl,(chadd) ;restore its address in character RAM to HL
ld b,8 ;8 bytes to make bold
mbold: ld a,(hl) ;get character data
rra ;rotate data out of true
or (hl) ;superimpose original
ld (hl),a ;save it
inc hl ;get next byte of character data
djnz mbold ;loop
ret
scrrt2: ld de,(chadd) ;address in character RAM to copy back to
ld hl,cchar ;start of saved bit-map
ld bc,8 ;8 bytes to restore
ldir ;restore original bit-map
ret
endif
istab: ld a,'C'
ld (direct+1),a ;set direction for 'cursor right'
call userf
dw teask ;get current cursor column in L
ld a,l
cpl ;complement to obtain 255 minus L
and 00000111b ;only least significant 3 bits are important (7 minus L)
inc a ;add one to obtain true figure (8 minus L)
jp curtab ;move cursor to next tab stop (assuming 8 columns apart -
;tab setting/clearing not implemented)
enorm:
conorg: jp 0000 ;jump to BIOS CONOUT (address patched by EMU1)
command:db 'emuoffrstkey' ;3 commands: EMUOFF, EMURST and EMUKEY
curup: db ESC,'[A' ;VT100 cursor control codes
curlft: db ESC,'[D'
currgt: db ESC,'[C'
curdn: db ESC,'[B'
defup: db '_' and 01fh ;PCW cursor control codes
deflft: db 'A' and 01fh
defrgt: db 'F' and 01fh
defdn: db '^' and 01fh
if iso8859
.comment |
Look-up table for remapping ISO-8859-1 (Latin 1) characters.
Upper case accented letters are obtained by subtracting 32
from the values in the table.
PCW ISO-8859-1 Character
=== ========== =========
|
lookup: db ' ' ; 160 non-breaking space
db 175 ; 161 inverted exclamation mark
db 177 ; 162 cent sign
db 163 ; 163 pound sign
db 180 ; 164 international currency symbol
db 189 ; 165 yen sign
db '|' ; 166 broken vertical bar
db 166 ; 167 section sign
db 178 ; 168 spacing diaeresis
db 164 ; 169 copyright sign
db 160 ; 170 feminine ordinal indicator
db 171 ; 171 left double guillemet
db 181 ; 172 negation sign (logical NOT)
db '-' ; 173 soft hyphen
db 190 ; 174 registered sign
db 182 ; 175 spacing macron
db 162 ; 176 degree sign
db 183 ; 177 +/- sign
db 184 ; 178 superscript 2
db 185 ; 179 superscript 3
db 179 ; 180 spacing acute
db 187 ; 181 micro sign (lower case Mu)
db 165 ; 182 paragraph sign
db 144 ; 183 middle dot
db 188 ; 184 spacing cedilla
db 191 ; 185 superscript 1
db 161 ; 186 masculine ordinal indicator
db 172 ; 187 right double guillemet
db 168 ; 188 1/4 fraction
db 169 ; 189 1/2 fraction
db 170 ; 190 3/4 fraction
db 174 ; 191 inverted question mark
accents:db 186 ; 223 Scharfes S
db 234 ; 224 A-grave
db 224 ; 225 A-acute
db 229 ; 226 A-circumflex
db 250 ; 227 A-tilde
db 240 ; 228 A-diaeresis
db 247 ; 229 A-ring
db 246 ; 230 AE-diphthong
db 245 ; 231 C-cedilla
db 235 ; 232 E-grave
db 225 ; 233 E-acute
db 230 ; 234 E-circumflex
db 241 ; 235 E-diaeresis
db 236 ; 236 I-grave
db 226 ; 237 I-acute
db 231 ; 238 I-circumflex
db 242 ; 239 I-diaeresis
db 252 ; 240 Icelandic Eth
db 249 ; 241 N-tilde
db 237 ; 242 O-grave
db 227 ; 243 O-acute
db 232 ; 244 O-circumflex
db 251 ; 245 O-tilde
db 243 ; 246 O-diaeresis
db 253 ; 247 division sign
db 248 ; 248 O-slash
db 238 ; 249 U-grave
db 228 ; 250 U-acute
db 233 ; 251 U-circumflex
db 244 ; 252 U-diaeresis
db 254 ; 253 Y-acute
db 255 ; 254 Icelandic Thorn
db 239 ; 255 Y-diaeresis
orgchar:db 16,56,108,198,0,0,0,0 ;spacing circumflex
db 0,198,204,24,32,91,219,0 ;per thousandth
db 64,192,70,73,70,9,6,0 ;1/8 fraction
db 224,16,102,25,230,9,6,0 ;3/8 fraction
db 240,128,230,25,230,9,6,0 ;5/8 fraction
db 240,16,38,73,134,9,6,0 ;7/8 fraction
db 0,56,108,198,198,108,56,0 ;open circle
db 0,56,124,254,254,124,56,0 ;full circle
db 251,85,81,81,0,0,0,0 ;trademark sign
db 192,48,12,48,204,48,192,0 ;greater than or equal to
db 6,24,96,24,102,24,6,0 ;less than or equal to
db 6,12,126,24,126,48,96,0 ;not equal to
db 0,0,50,76,0,126,0,0 ;approximately equal to
db 8,12,254,7,254,12,8,0 ;double shafted right arrow
db 16,48,127,224,127,48,16,0 ;double shafted left arrow
db 0,36,126,195,126,36,0,0 ;double shafted left/right arrow
db 0,126,0,126,0,126,0,0 ;equivalent to
endif
hadESC: ds 1 ;flag for ESCape character
haddgt: ds 1 ;flag for 'had a digit'
lstch: ds 1 ;store for last character
nrdgts: ds 1 ;store for number of digits in buffer
lstdgt: dw dgtbuf ;pointer to current digit in buffer
dgtbuf: ds 4 ;digit buffer
curatt: ds 2 ;pointer to current attribute
bold: ds 1 ;flag for bold attribute
chadd: ds 2 ;address in character RAM of bold character
stadd: ds 2 ;address of calling program's stack
cchar: ds 8 ;store for character data when displaying in bold
ds 8 ;stack used by BDOS 10
tstack:
end
title EMUOFF v1.00 23/6/95
subttl (c) Ian Macdonald (ianmacd@xs4all.nl)
.comment |
Program to uninstall EMU from within a .SUB file or alias.
|
include EMUEQU.MAC ;get equates
.z80
ld de,defDMA
ld hl,ststr
ld bc,endstr-ststr
ldir ;relocate EMUOFF command in default DMA buffer
ld c,input
ld de,0 ;use current DMA, i.e. default
jp BDOS ;send EMUOFF command to RSX
ststr: db 6,0,'emuoff',cr,nul
endstr:
end
title EMURESET v1.00 23/6/95
subttl (c) Ian Macdonald (ianmacd@xs4all.nl)
.comment |
Program to reset EMU's highlighting attributes from within a .SUB file or alias
|
include EMUEQU.MAC ;get equates
.z80
ld c,print
ld de,signon
jp BDOS ;turn off attributes and display sign-on message
signon: db ESC,'[m' ;VT100 escape code for 'turn all attributes off'
db 'EMURESET v1.00 23/6/95 (c) Ian Macdonald (ianmacd@xs4all.nl)',cr,lf
db lf,'Highlighting attributes now reset.',cr,lf,'$'
end
title EMUSUB v1.00 3/12/95
subttl (c) Ian Macdonald (ianmacd@xs4all.nl)
.comment |
Program to send commands to EMU from within a .SUB file or Z-system alias.
|
include EMUEQU.MAC ;get equates
.z80
ld hl,defDMA
ld a,(hl) ;get number of characters in command tail
cp 3 ;is it 3?
jr nz,help ;if not, display help text
inc hl
inc hl ;move pointer to first character in command tail
ld a,(hl)
cp '/' ;is it '/'?
jr nz,help ;if not, display help text
inc hl ;move pointer to parameter
ld a,(hl)
cp 'O' ;is it 'O'?
jr z,emuoff ;if so, EMUOFF
cp 'R' ;is it 'R'?
jr z,emurst ;if so, EMURST
cp 'K' ;is it 'K'?
jr z,emukey ;if so, EMUKEY
;otherwise, display help text
help: ld de,htxt
prt: ld c,print
jp BDOS ;turn off attributes and display sign-on message
emuoff: ld hl,str1
emuk: ld de,defDMA
ld bc,str2-str1 ;string length always the same
ldir ;relocate command in default DMA buffer
ld c,input
ld de,0 ;use current DMA, i.e. default
jp BDOS ;send command to RSX
emukey: ld hl,str2
jr emuk
emurst: ld de,rsttxt
jr prt
str1: db 6,0,'emuoff',cr,nul
str2: db 6,0,'emukey',cr,nul
rsttxt: db ESC,'[m$' ;VT100 escape code for 'turn all attributes off'
htxt: db 'EMUSUB v1.00 3/12/95 (c) Ian Macdonald (ianmacd@xs4all.nl)',cr,lf,lf
db 'Commands available:',cr,lf,lf
db 'EMUSUB /O - uninstall emulator.',cr,lf
db 'EMUSUB /R - reset highlighting attributes.',cr,lf
db 'EMUSUB /K - install VT100 cursor keys.',cr,lf,'$'
end