home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
ftp.demon.co.uk-pub-cpm
/
amstrad
/
setfontz.arc
/
SETFONT.Z80
< prev
Wrap
Text File
|
1994-05-06
|
60KB
|
2,137 lines
;SETFONT: A program to alter the character set.
;
; Addresses in low memory:
;
WBOOT EQU 00000H ;Warm boot.
JUMP EQU 00001H ;Address for start of BIOS
FDOS EQU 00005H ;BIOS/BDOS calls come here
FCB EQU 0005CH ;Standard file control block
CMDTAIL EQU 00080H ;The command tail, DMA buffer &c.
;
; Character set data
;
ACHRLEN EQU 00800H ;Length of the character set (Amstrad PCW/CPC only)
SCHRLEN EQU 01000H ;Length of the character set (ZX Spectrum only)
SCHRSET EQU 03000H ;Start of the character set (ZX Spectrum only)
PCHRSET EQU 0B800H ;Start of the character set (Amstrad PCW only)
CCHRSET EQU 08000H ;Start of the character set (Amstrad CPC only)
;
; Addresses in high memory:
;
BUFFER EQU 0C000H ;Buffer to load to.
SCPROG EQU 0D001H ;Relocation address for alteration code
;
; BDOS codes:
;
BDKEY EQU 01H ;BDOS code - Await a keypress
BDSCR EQU 02H ;BDOS code - Write ASCII
BDMSG EQU 09H ;BDOS code - Write a message to the screen
BDLIN EQU 0AH ;BDOS code - Read a line from the console
BDVER EQU 0CH ;BDOS code - Find the version of CP/M
BDRES EQU 0DH ;BDOS code - Reset BDOS
BDSEL EQU 0EH ;BDOS code - Select a drive
BDOPN EQU 0FH ;BDOS code - Open a file to read.
BDCLO EQU 10H ;BDOS code - Close a file
BDSCN EQU 11H ;BDOS code - Search for a file on disc
BDERA EQU 13H ;BDOS code - Erase a file.
BDRDR EQU 14H ;BDOS code - Read a record
BDWRR EQU 15H ;BDOS code - Write a record
BDOPW EQU 16H ;BDOS code - Open a file to write.
BDDEF EQU 19H ;BDOS code - Get current disc drive
BDDMA EQU 1AH ;BDOS code - Set the DMA buffer
BDUSR EQU 20H ;BDOS code - Set/get user number.
BDRRND EQU 21H ;BDOS code - Read random
BDWRND EQU 22H ;BDOS code - Write random
BDLEN EQU 23H ;BDOS code - Get file length.
BDERR EQU 2DH ;BDOS code - Set error mode.
BDSCB EQU 31H ;BDOS code - Use CP/M+ SCB
BDCODE EQU 6CH ;BDOS code - Send program code
BDPARS EQU 152 ;BDOS code - Parse a filename
;
EBVERS EQU 000E3H ;Extended BIOS code - Find machine we are using
EBSCRR EQU 000E9H ;Extended BIOS code - Run a routine in screen environment
;
FAILCOD EQU 0FF00H ;When sent to BDOS, this indicates "program failed."
;
; Miscellaneous:
;
CR EQU 0DH
LF EQU 0AH
ESC EQU 1BH
;
.Z80
CSEG
;
;Load or save a set of character data for CP/M:
;Formats supported are:
;
; Amstrad CP/M (10H records)
; Amstrad CP/M with one-record header (11H records)
; Spectrum +3 CP/M (20H records)
; Spectrum +3 CP/M with one-record header (21H records)
; Spectrum +3 +3DOS with header (7H records - CODE xxxxx,768)
; PRINTIT double-height (18H records)
; STOP PRESS (like HITEC-70)
; MASTERPAINT (like STANDARD)
;
; Files saved with a header and a .COM type will self-load.
; If it is necessary to add a +3 header to a file (only useful under +3DOS) then
; save without header and use the command :
;
; COPY "filename.xyz" TO SPECTRUM FORMAT
;
;Version History (in reverse order):
;
;v1.02a Silly mistake fixed; I had got the CPC font address wrong by 200h.
; I don't know how I arrived at the wrong figure, but I did.
;
;v1.02 Untested additions to allow use on CPC6128.
; Bug fix in "Save MasterPaint file".
; Password capabilities extended to all file-handling functions
;
;v1.01 - Added capabilities: Save & load Printit fonts. "Small" +3 font can
; now be used for all options. /Z option extended to save self-loading
; fonts. /F option replaces /P and /X. /F:? (guess) option. /F:E (EMS/EMT)
; option. /F:S (Stop Press) option. /F:C (.CAR) option. Spurious errors
; avoided due to improved EOL detection. Multi-command mode. IF
; capability in Multi-command mode. /I (invert font) option.
;
;v1.00 - Works with PCW & Spectrum +3. Load and save PCW fonts, +3DOS fonts.
; Spectrum can save +3 CP/M fonts. All fonts other than +3 CP/M use
; the large font only. Fonts selected with /P /X options. Users 0-15
; and languages 0-7 supported.
;
JP PROGST
DEFB CR,'SETFONT v1.02 for Amstrad PCW/CPC and ZX Spectrum +3',CR,LF
DEFB 'Copyright (c) J. Elliott, 7 May 1994',CR,LF
SGN: DEFB 'Not tested for use on Amstrad CPC.',cr,lf,26,'$'
PROGST: LD E,0FFH
LD C,BDUSR ; Store current user no.
CALL FDOS ; in case SETFONT changes it.
LD (USER),A
LD C,BDERR ;
LD E,0FFH ; Deactivate the "CP/M Error on X:"
CALL FDOS ; messages and associated warmboots.
LD HL,CMDTAIL
LD DE,BUF+1 ; Move the command tail up into the
LD BC,128 ; internal buffer.
LDIR
LD A,(0053H) ; Length of first file password
OR A ; No password.
JR Z,START
LD C,A
LD B,0 ; Copy file password to password buffer.
LD HL,(0051H)
LD DE,PASSWORD
LDIR
START: LD A,(BUF+1) ; Length of command line.
LD E,A
LD D,0 ; Add A to HL
LD HL,BUF+2
ADD HL,DE ; HL is now pointing to the next space in the
; buffer.
LD (HL),0 ; Zero to clear up detection routines.
CALL SUBSCAN ; Find /H switch, act on other switches.
JP C,HELP ; Act on /H switch
LD A,(LANGFLG) ; Language change required?
OR A
JR Z,START0 ; No.
LD DE,MESS22
CALL SUBPRINT ; Change language
START0: LD A,(FCB+1)
CP 020H ; No filename?
JP Z,ERR5 ; If so then ask for one.
CP '/'
JP Z,ERR5 ; Filename starts with /opt or -opt.
CP '-'
JP Z,ERR5
LD C,BDVER ; Get version number
CALL FDOS
LD A,H ; Is the program running under MP/M (unlikely)
OR A
JP NZ,ERR1 ; MP/M not allowed.
LD A,L
CP 31H
JP NZ,ERR1 ; Not CP/M 3
LD A,(7) ; Get the high byte of TPA top.
CP 0D1H ; Enough memory?
JP C,ERR9 ; No, quit.
;
;Machine-specific initialisation. This was originally written on a +3; hence
;the program self-modifies for the CPC and PCW.
;
CALL SUBUSERF
DEFW EBVERS ;For version. On return:
; A=0 => Amstrad CPC
; A=1 => Amstrad PCW
; A=3 => Spectrum +3
OR A
CALL Z,SUBCI ;Is this a CPC?
CP 01H ;Or is this a PCW?
CALL Z,SUBPI ;If so, modify program AND set A to 3.
CP 03H ;Is the machine suitable?
JP NZ,ERR1 ;If not, leave
LD A,(EMSFLG) ;Was /F:E switch encountered?
OR A
JP NZ,USEMS ;If yes, use the EMS file handler
LD A,(PLUS3)
OR A ;Was /F:+ switch encountered?
JP NZ,PL3 ;If yes, use the +3DOS file handler.
LD A,(PRINTIT)
OR A ;Was /F:P switch encountered?
JP NZ,PTR ;If yes, use PRINTIT file handler.
LD A,(PCW)
OR A ;Was /F:A switch encountered?
JP NZ,USEPCW ;If yes, force 2k font (rather than 4k)
LD A,(SPFFLG)
OR A ;Was /F:S switch encountered?
JP NZ,USESPF ;If yes, use Stop Press file handler
LD A,(CARFLG) ;Was /F:C switch encountered?
OR A ;If yes, deal with Masterpaint format.
JP NZ,USECAR
;
; Default format.
;
LD A,(LOADSAVE) ;Was /S switch encountered?
OR A
JP NZ,SAVE ; If yes, save
CALL LOAD ; Else, perform a standard load.
JP LOAD5
;
USEPCW: CALL CG0
LD A,(LOADSAVE) ;Load or save?
OR A
JR NZ,SAVEPCW
LD HL,BUFFER ;Load a PCW font file
CALL ASHL ;Auto Shift HL (allows for /F=)
LD (DMAADD),HL
LD A,10H ;File length in records
LD (REC),A
CALL LOAD ;Load
JP LOAD5 ;Install font
;
SAVEPCW:
LD HL,BUFFER
CALL ASHL ;Set correct address
LD (DMAADD),HL
LD A,10H ;File length (records)
LD (REC),A
JP SAVE
;
USESPF: LD A,(LOADSAVE) ;Load or save?
OR A
JP NZ,SAVESPF
CALL CG0
LD HL,4000H ;Load the Stop Press file at 4000H
LD (DMAADD),HL
LD A,61H ;97 records
LD (REC),A
CALL LOAD
LD B,92 ;92 CHARACTERS
LD HL,4080H ;! IN STOP PRESS
LD DE,0C108H ;! IN CP/M FONT.
CALL ASDE
USESP0: LD C,8
USESP1: LD A,(HL)
LD (DE),A
INC DE
INC HL ;UNPACK THE CHARACTER SET
INC HL
INC HL
INC HL
DEC C
JR NZ,USESP1
PUSH DE
LD DE,60H ;HL POINTS TO NEXT CHARACTER
ADD HL,DE
POP DE
DJNZ USESP0
JP LOAD5 ;FONT LOADED.
;
SAVESPF:
CALL CHARGET ;GET FONT
LD A,61H
LD (REC),A ;FILE LENGTH
LD BC,080H
LD HL,4000H
LD (DMAADD),HL ;POINT TO START OF FILE
LD DE,4001H ;FILL FIRST RECORD WITH FFs
LD (HL),0FFH
LDIR
LD (HL),0
LD BC,30FFH
LDIR ;FILL REST WITH BLANKS
LD B,92 ;92 CHARACTERS
LD DE,4080H ;! IN STOP PRESS
LD HL,0C108H ;! IN CP/M FONT.
CALL ASDE
USESP2: LD C,8
USESP3: LD A,(HL)
LD (DE),A
INC HL
INC DE ;PACK THE CHARACTER
INC DE
INC DE
INC DE
DEC C
JR NZ,USESP3
PUSH HL
LD HL,60H ;DE POINTS TO NEXT CHARACTER
ADD HL,DE
EX DE,HL
POP HL
DJNZ USESP2
JP SAVE
;
;.CAR FILE IS LOADED AT 4000H. LENGTH=60 RECORDS.
;
USECAR: LD A,(LOADSAVE)
OR A
JR NZ,SAVECAR
CALL CG0
LD HL,4000H ;LOAD AT 4000H
LD (DMAADD),HL
LD A,60
LD (REC),A ;60 RECORDS.
CALL LOAD
LD A,(04000H) ;Character width (bytes)
DEC A
JP NZ,ERR11
LD A,(04001H) ;Character height (bytes)
CP 8
JP NZ,ERR11
LD HL,04004H
LD DE,0C100H
CALL ASDE
LD C,94
LOADC1: CALL UPSDOWN ;UNPACK THE FONT
INC HL
DEC C
JR NZ,LOADC1
JP LOAD5
;
SAVECAR:
CALL CHARGET
LD HL,4000H ;LIKE /F:E, NEEDS A FILE TO MODIFY.
LD (DMAADD),HL
LD A,60
LD (REC),A
CALL LOAD ;v1.02 bug fix.
LD A,(04000H) ;Character width (bytes)
DEC A
JP NZ,ERR11
LD A,(04001H) ;Character height (bytes)
CP 8
JP NZ,ERR11
LD DE,04004H
LD HL,0C100H
CALL ASHL ;PACK THE CHARACTERS
LD C,94
SAVEC1: CALL UPSDOWN
INC DE
DEC C
JR NZ,SAVEC1
LD HL,FCB+12
LD DE,FCB+13
LD BC,23
LD (HL),0
LDIR
LD HL,4000H
LD (DMAADD),HL
LD A,60
LD (REC),A ;SAVE THE MODIFIED FILE.
JP SAVE0
;
UPSDOWN:
LD B,8
UPS0: INC DE
DJNZ UPS0
LD B,8
UPS1: LD A,(HL) ;MOVE CHARACTER AT (HL) TO
INC HL ;UPSIDE-DOWN CHARACTER AT (DE).
DEC DE
LD (DE),A
DJNZ UPS1
LD B,8
UPS2: INC DE
DJNZ UPS2 ;HL & DE POINT TO JUST OUTSIDE CHAR.
RET
;
; Load a disc file
;
LOAD: LD C,BDSCN ;Scan for first FCB
LD DE,FCB
CALL FDOS
INC A
JP Z,ERR2 ;Is file present?
LOAD8: CALL PASSPUT
LD C,BDOPN
LD DE,FCB
CALL FDOS ; Was a password required?
LD A,H ; If so, ask for it.
CP 7 ;
JP Z,LOAD9
LD C,BDDMA
LD DE,(DMAADD)
CALL FDOS ;Open file, set DMA address.
LD C,BDRDR
LD DE,FCB
CALL FDOS ;Read the first block.
LD A,(STRIP) ;
OR A ; Should the header be stripped?
JR Z,LOAD2 ;
LD DE,(DMAADD)
LD C,BDDMA ;
CALL FDOS ;Read the next record.
LD C,BDRDR
LD DE,FCB
CALL FDOS
LOAD2: LD HL,REC ;Record number variable.
DEC (HL) ;Fewer records to load.
LOAD3: LD DE,080H
LD HL,(DMAADD)
ADD HL,DE ;Increase load addr. by 80H
LD (DMAADD),HL
EX DE,HL
LD C,BDDMA ;Advance the DMA buffer.
CALL FDOS
LOAD4: LD C,BDRDR ;Read next data block.
LD DE,FCB
CALL FDOS ;End of file?
CP 01H
PUSH AF ;Save AF in DE
POP DE ;Return addr. must be top of stack
LD HL,REC
DEC (HL) ;All records loaded?
RET Z ;Loading finished
PUSH DE
POP AF
JP Z,ERR4 ;End of file met.
JP LOAD3
;
LOAD5: CALL CHARPUT
LD DE,MESS5 ; Ok message
CALL SUBPRINT
WB1: LD A,(LANGFLG)
OR A
JR Z,WB2 ;If no language option active, ignore next bit.
LD A,(LANGUAGE)
LD (MESS22A),A ;Select language in A
CALL SCR2
LD DE,MESS22
CALL SUBPRINT
CALL SCR1
WB2: LD A,(MCM) ;MULTI-COMMANDS?
OR A
JP NZ,RESET
RST 0
;
LOAD9: CALL ERR8 ;Ask for password.
JP LOAD8
;
CHARGET: ;Get font from screen bank.
CALL CG0
LD A,(INVFLG) ;Invert font?
OR A
LD HL,0C000H ;Font at 0C000H
CALL NZ,SUBINVFNT
RET
;
CG0: LD A,0EBH ;EX DE,HL just before LDIR
CG1: LD (SETGET),A
CALL SUBMOVEUP ;Move routine to high memory
LD A,(ISCPC)
OR A
JP NZ,CPCRTN
LD BC,SCPROG
CALL SUBUSERF
DEFW EBSCRR ;Run it
RET
;
CHARPUT:
LD DE,08000H
LD HL,BUFFER ;Move font to 8000H
LD BC,01000H
LDIR
LD A,(INVFLG) ;Invert the font?
OR A
LD HL,08000H
CALL NZ,SUBINVFNT
CP1: CALL CG0 ;Get current font at C000h
LD HL,(DEND)
LD DE,(DBEGIN) ;Move the portion between /B and /E (or all)
INC HL ;into the current font.
OR A
SBC HL,DE
ADD HL,HL ;*2
ADD HL,HL ;*4
ADD HL,HL ;*8
LD B,H
LD C,L ;BC=LENGTH
LD HL,(DBEGIN)
ADD HL,HL ;*2
ADD HL,HL ;*4
ADD HL,HL ;*8
EX DE,HL ;DE=START OFFSET
LD IX,08000H
ADD IX,DE
LD HL,BUFFER
ADD HL,DE
EX DE,HL ;DE=DESTINATION ADDR.
PUSH IX
POP HL ;HL=SOURCE ADDR.
LDIR ;RESTORE COMPOSITE CHARSET.
XOR A ;NOP
JR CG1
;
; Load a +3DOS font, assumed headed.
; Or save a +3DOS font, headed.
;
PL3: LD A,(LOADSAVE) ;LOADING OR SAVING?
OR A
JP NZ,SAVEP3 ;Saving
CALL CG0
LD A,06h ; 6 records
LD (REC),A
LD HL,0B000H ; Load temporarily to B000H
LD (DMAADD),HL
LD A,0FFH ; Header automatically
LD (STRIP),A ; stripped.
CALL LOAD
LD HL,0B000H ;
LD DE,0C100H ; Characters 32-95
CALL ASDE
LD BC,0200H ;
LDIR
LD HL,0B200H ;
LD DE,0C518H ; Pound sign (96)
CALL ASDE
LD BC,8 ;
LDIR
LD HL,0B208H ;
LD DE,0C308H ; Characters 97-126
CALL ASDE
LD BC,0F0H ;
LDIR
LD HL,0B2F8H ;
LD DE,0C520H ;
CALL ASDE
LD BC,8 ; Copyright sign.
LDIR ;
JP LOAD5
;
SAVEP3: LD A,07H ; 7 records, including header.
LD (REC),A ;
CALL CHARGET
LD HL,0C518H ;
CALL ASHL
LD DE,0C300H ; Move pound sign.
CALL ASDE
LD BC,8 ;
LDIR
LD HL,0C520H ;
CALL ASHL
LD DE,0C3F8H ; Move copyright sign.
CALL ASDE
LD BC,8 ;
LDIR
LD HL,HEADER ;
LD DE,0C080H ; Add a +3DOS header.
CALL ASDE
LD BC,080H ;
LDIR
XOR A
LD (STRIP),A ; Otherwise program would save with a COM header
LD HL,0C080H ;
CALL ASHL
LD (DMAADD),HL ; Save starting at 0C100h/0C900H
JR SAVE0 ;
;
; Save the current font.
;
SAVE: CALL CHARGET
SAVE0: LD C,BDDEF ;Preserve current disk drive
CALL FDOS
PUSH AF
LD C,BDRES ;Initialise BDOS
CALL FDOS
POP AF
LD E,A
LD C,BDSEL ;Restore it
CALL FDOS
LD C,BDSCN ;Check for file's existence on disc.
LD DE,FCB
CALL FDOS
INC A ;If A=0FFH, file not found.
JP NZ,ERR6
SAVE1: LD C,BDOPW ;If the file is erased, then open to write.
LD DE,FCB
CALL FDOS
INC A ;If A=0FFH, error.
JP Z,ERR7
LD A,(STRIP)
OR A
JR Z,SAVE2
LD DE,COMHED
LD C,BDDMA ;Write an extra record: the header
CALL FDOS
LD DE,FCB
LD C,BDWRR
CALL FDOS
SAVE2: LD HL,(DMAADD) ;Load address
PUSH HL ;Save HL for later.
EX DE,HL ;Move DMA address to DE.
LD C,BDDMA ;Set DMA
CALL FDOS
POP HL ;Add 80H to DMA.
LD DE,080H
ADD HL,DE
LD (DMAADD),HL ;Store DMA address.
LD C,BDWRR ;Write to disc.
LD DE,FCB
CALL FDOS
OR A ;Error if A<>0.
JP NZ,ERR7
LD A,(REC) ;Number of records remaining.
DEC A ;Decrease by 1
JR Z,SAVE3 ;If file fully written, close it.
LD (REC),A
JP SAVE2
;
SAVE3: LD DE,FCB
LD C,BDCLO ;Close the file.
CALL FDOS
JP WB1
;
SAVE9: CALL ERR8
JP SAVE0
;
USEMS: LD A,(LOADSAVE)
OR A ;LOAD OR SAVE TO THE EMS FILE?
JP NZ,SAVEMS
CALL EMSFIND ;LOAD THE EMS FILE. RETURN ADDRESS OF FONT IN HL
LD DE,0C000H
CH2: LD BC,1000H
LD A,(SIZE)
OR A
JR Z,USEMS1
LD BC,800H
USEMS1: LDIR
JP LOAD5 ;MOVE FONT TO PROPER PLACE, INSTALL IT, LEAVE.
;
SAVEMS: CALL EMSFIND
PUSH HL ;HL=FONT ADDR.
CALL CHARGET
POP DE
LD BC,800H ;MOVE FIRST PART OF FONT (ALWAYS COPIED).
LD HL,0C000H
LDIR
LD A,(SIZE)
OR A ;Move small characters (optional).
JR NZ,SAVEMS1
LD BC,800H
CH3: LDIR ;Set to NOP if PCW is used.
SAVEMS1:
LD C,BDSCN ;Check for file's existence on disc.
LD DE,FCB
CALL FDOS
INC A ;If A=0FFH, file not found. (EMS file needed to save to).
JP Z,ERR2
LD HL,FCB+12
LD DE,FCB+13 ;Blank FCB to avoid corruption.
LD BC,22
LD (HL),0
LDIR
XPASS0: CALL PASSPUT ;If the file is present, then open to update.
LD C,BDOPN ;Open to update
LD DE,FCB
CALL FDOS
LD A,(FCB+7) ;If file is R/O due to passwording, ask for
BIT 7,A ;password.
JR NZ,XPASS0X
LD A,(FCB+8) ;If file is System file in User 0, error.
BIT 7,A
JP NZ,ERR12
LD A,H
CP 7
JR NZ,XPASS1
XPASS0X:
CALL ERR8
JR XPASS0
;
XPASS1: INC A ;If A=0FFH, error.
JP Z,ERR7 ;Write error.
LD A,(REC)
INC A ;No. of records.
LD B,A
LD DE,8000H ;Prepare to write out to disc.
LD HL,(SAVREC)
SRLOOP: PUSH BC
PUSH HL
CALL WRRND
LD HL,80H ;Write the record, increase DMA.
ADD HL,DE
EX DE,HL
POP HL
INC HL
POP BC ;Next record
DJNZ SRLOOP
JP SAVE3 ;Close out file.
;
EMSFIND:
LD DE,FCB
LD C,BDSCN ;FILE NOT FOUND?
CALL FDOS
INC A
JP Z,ERR2
LD HL,FCB+12
LD DE,FCB+13 ;BLANK OUT FCB TO AVOID POSSIBLE CORRUPTION.
LD BC,22
LD (HL),0
LDIR
XPASS2: CALL PASSPUT
LD DE,FCB ;OPEN THE FILE
LD C,BDOPN
CALL FDOS
LD A,H
OR A
CP 7
JR NZ,XPASS3
CALL ERR8
JR XPASS2
;
XPASS3: INC A
JP Z,ERR4
;
LD HL,0
EMSF0: CALL RDRND1
JP C,ERR10 ;NO FONT FOUND.
PUSH HL
CALL CP128 ;CP128 RETURNS IN HL THE ADDRESS IF OK.
JR Z,EMSF1
POP HL
INC HL ;RECORD NUMBER COUNTER
JR EMSF0
;
EMSF1: POP DE ;DE=RECORD NUMBER HL=ADDRESS OF CHARACTER SET
LD (SAVREC),DE
LD (CHRPTR),HL
;BYTES FOUND.
LD A,(REC) ;NO. OF RECORDS TO LOAD.
INC A
INC A
LD B,A ;B=NO. OF RECORDS TO LOAD.
LD DE,8000H ;LOAD THE EMS FONT NEAR TO 8000H
LD HL,(SAVREC)
EMSF2: PUSH BC
PUSH HL
CALL RDRND ;READ IN A RECORD
JP C,ERR3 ;TOO SHORT.
LD HL,0080H
ADD HL,DE
EX DE,HL ;INCREASE POINTER
POP HL
INC HL ;NEXT RECORD
POP BC
DJNZ EMSF2 ;UNTIL ALL LOADED.
LD HL,(CHRPTR) ;ADDRESS OF FONT
RET
;
DSEG
PASSWORD:
DEFB ' '
SAVREC: DEFW 0
CHRPTR: DEFW 0
CSEG
;
CP128: PUSH IX ;Search 128-byte buffer for the right
LD IX,8000H ;character sequence.
LD B,128
CP128A: CALL CPIX
JR Z,CP128B ;It's a lot easier with IX, but be careful.
INC IX
DJNZ CP128A
POP IX ;Not found.
XOR A
INC A
RET
;
CP128B: XOR A
PUSH IX ;Found. Address in HL.
POP HL
POP IX
RET
;
CPIX: LD A,(IX+1) ;The byte at (IX+0) is different on +3s
OR A ;and Amstrads, so it is ignored.
RET NZ
LD A,(IX+2)
CP 66H
RET NZ
LD A,(IX+3)
CP 0DBH
RET NZ
LD A,(IX+4)
CP 0DBH
RET
;
RDRND1: PUSH HL ;Read records HL,HL+1 from file at 8000-8100.
PUSH DE
PUSH HL
LD DE,8000H
CALL RDRND
JR C,EXTR
POP HL
INC HL
LD DE,8080H
CALL RDRND
POP DE
POP HL
RET
;
RDRND: PUSH HL
PUSH DE
LD (FCB+21H),HL ;SET RECORD NUMBER
XOR A
LD (FCB+23H),A
LD C,BDDMA ;SET LOAD ADDRESS
CALL FDOS
LD C,BDRRND
LD DE,FCB ;READ RANDOM
CALL FDOS
OR A
JP Z,EXTR
INC A
JP Z,ERR4
SCF
EXTR: POP DE
POP HL
RET
;
WRRND: PUSH HL
PUSH DE
LD (FCB+21H),HL ;SET RECORD NUMBER
XOR A
LD (FCB+23H),A
LD C,BDDMA ;SET LOAD ADDRESS
CALL FDOS
LD C,BDWRND
LD DE,FCB ;READ RANDOM
CALL FDOS
OR A
JP NZ,ERR7 ;WRITE ERROR
POP DE
POP HL
RET
;
; The Subroutines:
;
;THIS IS THE SUBROUTINE WHICH IS RELOCATED TO
;D001H. IT INSTALLS THE CHARACTER SET.
SUBRS: PUSH BC ;Save BC ;D001
PCWP1: LD BC,SCHRLEN ;LENGTH OF CHAR. SET ;D002
PCWP2: LD DE,SCHRSET ;D005
LD HL,BUFFER ;SOURCE & DESTINATION ;D008
SETGET: NOP ;IF SAVING, BECOMES EX DE,HL ;D00B
LDIR ;BLOCK MOVE ;D00C
POP BC ;D00E
RET ;D00F
;
SUBMOVEUP:
LD HL,SUBRS
LD DE,SCPROG ;Destination
LD BC,SUBMOVEUP-SUBRS ;Length of routine
LDIR
RET
;
CPCRTN: CALL SUBUSERF
DEFW 0D001H
RET
;
SUBINVFNT:
PUSH AF
PUSH BC
PUSH DE
PUSH HL
LD BC,1000H ;Invert the font at (HL).
SUBINF1: ;Font length=1000h
LD A,(HL)
CPL
LD (HL),A ;Invert
INC HL
DEC BC
LD A,B ;Next byte
OR C
JR NZ,SUBINF1
POP HL
POP DE
POP BC
POP AF
RET
;
SUBCI: ;SELF-MODIFY FOR AMSTRAD CPC
LD DE,SGN
CALL SUBPRINT
XOR A
LD (ISSPEC),A
DEC A
LD (ISCPC),A
LD HL,CCHRSET ;CPC character set location
LD (PCWP2+1),HL
LD HL,0
LD (PCWP0+1),HL ;CPC isn't affected by /F=
LD (PCWP0A+1),HL
LD HL,ACHRLEN ;Amstrad character set length
LD (PCWP1+1),HL
JR SUBPI1
;
SUBPI: ;SELF-MODIFY FOR AMSTRAD PCW
XOR A ;Computer type flags
LD (ISSPEC),A
LD (ISCPC),A
LD HL,PCHRSET ;PCW character set location
LD (PCWP2+1),HL
LD HL,0
LD (PCWP0+1),HL ;PCW isn't affected by /F=
LD (PCWP0A+1),HL
LD HL,ACHRLEN ;Amstrad character set length
LD (PCWP1+1),HL
SUBPI1:
LD HL,0
LD (CH3),HL
LD HL,ACHRLEN ;PCW character set length
LD (CH1+1),HL
LD (CH2+1),HL
LD A,010H ;PCW file length
LD (REC),A
LD A,03H ;03H => Success
RET
;
INTHPCW:
CALL SUBSTRP1 ;Guess: 2k PCW file with header
LD DE,MESS30
JR INTPCW0
;
INTPCW: LD DE,MESS29 ;Guess: 2k PCW file without header
INTPCW0:
CALL SUBPRINT
POP HL
POP DE
POP BC
POP AF
SUBPI2:
PUSH HL ; This routine is
CALL SUBPI1 ; called to load PCW
LD A,0FFH ; files on a Spectrum.
LD (PCW),A ; It makes all modifications from SUBPI
POP HL ; EXCEPT alteration of the
JP SUBSCAN3 ; load address.
;
SUBEMSFNT:
LD A,0FFH ; Flag that an EMS file is being used.
LD (EMSFLG),A
JP SUBSCAN3
;
SUBINPFILE:
LD DE,INPPROMPT ;Prompt: SETFONT>
CALL SUBPRINT
LD A,0FFH ; Flag: Multi-command mode running
LD (MCM),A
LD B,80H ; Fill the buffer with spaces.
LD HL,BUF+1
SUBINP0:
LD (HL),' '
INC HL
DJNZ SUBINP0
LD C,BDLIN ; Read in the command tail.
LD DE,BUF
CALL FDOS
LD DE,CRLF
CALL SUBPRINT
LD A,(BUF+1)
OR A ;If no characters typed, abandon
JP Z,0
LD A,(BUF+2) ;Check for a conditional multi-command
CP ';' ;Or comment.
JR Z,SUBINPFILE
CP ':'
JR NZ,SUBINP0A
LD A,(MCFAIL)
OR A
JR NZ,SUBINPFILE
LD DE,BUF+2
LD HL,BUF+3 ;Remove colon.
LD BC,80H
LDIR
LD A,(BUF+1) ;Only the :?
DEC A
JP Z,SUBINPFILE
LD (BUF+1),A
LD A,(BUF+2)
SUBINP0A:
CP '/'
JR Z,SUBINP0B ;ONLY /M OR /H
CP '-'
JR Z,SUBINP0B
XOR A
LD (MCFAIL),A
SUBINP0B:
LD A,(BUF+1)
LD E,A
LD D,0
LD HL,BUF+2 ;End-of-line marker
ADD HL,DE
XOR A
LD (HL),A
LD HL,BUF+2 ; Convert the command line to upper case.
SUBINP1:
LD A,(HL)
OR A
JR Z,SUBINP1A
CALL SUBUPCASE ; Convert to upper case.
LD (HL),A ;
INC HL
JR SUBINP1
;
SUBINP1A:
LD C,BDPARS ;
LD DE,PFCB ; Parse filename, which
CALL FDOS ; usually happens during program load.
LD A,H
CP 0FFH ; If H=0FFH, Filename is invalid.
JP NZ,START
LD DE,MESS14 ;Let the user know about it.
CALL SUBPRINT
JP SUBINPFILE
;
DSEG
BUF: DEFB 128,0 ; Room for 128 bytes.
DEFS 128 ; The 128 bytes.
DEFB 0 ; End of buffer
PFCB: DEFW BUF+2 ;Parse the filename at BUF
DEFW FCB ;and place it at the usual FCB.
CSEG
;
SUBUSERF: ;FIND USERF AND CALL IT.
PUSH HL
PUSH DE ;All registers preserved.
LD HL,(JUMP)
LD DE,0057H ;Offset for func. 30
ADD HL,DE
POP DE
EX (SP),HL
RET
;
RESET: LD HL,BUFFER ;RESET ALL VARIABLES
LD (DMAADD),HL
LD A,20H
LD (REC),A
LD HL,PASSUSED
LD DE,PASSUSED+1
LD BC,16
LD (HL),0
LDIR
LD A,'0'
LD (LANGUAGE),A
LD (MESS22A),A
LD HL,511
LD (DEND),HL
LD HL,PASSWORD
LD DE,PASSWORD+1
LD BC,7
LD (HL),' '
LDIR
JP SUBINPFILE
;
PASSPUT:
LD HL,PASSWORD
LD A,(HL)
CP ' '
RET Z
LD DE,0080H
LD BC,8
LDIR
LD DE,0080H
LD C,BDDMA
JP FDOS
;
SUBPRFCB: ;PRINT THE FILENAME IN THE FILE CONTROL BLOCK
LD A,(FCB)
OR A
JR NZ,SUBPRFCB0
LD C,BDDEF
CALL FDOS
INC A
SUBPRFCB0:
ADD A,'@'
LD (FILDR),A
LD HL,FCB+1
LD DE,FILSP ;Load in name part
LD BC,08H
LDIR
LD HL,FCB+9
LD DE,FILTY ;Load in type part
LD BC,03H
LDIR
LD HL,FILSP ;
LD B,0CH ; Print 12 bytes
SUBPRFCB1:
LD E,(HL) ;
RES 7,E
LD C,BDSCR ; Print the characters one by one
PUSH HL ;
PUSH BC
CALL FDOS
POP BC
POP HL
INC HL
DJNZ SUBPRFCB1 ;Until B=0
RET
;
SUBPRINT:
PUSH AF
PUSH BC
PUSH DE ; PRINT A MESSAGE AT (DE)
PUSH HL
LD C,BDMSG ;
CALL FDOS ; Send the message.
POP HL
POP DE
POP BC
POP AF
RET
;
SUBCODE: ;INFORM BDOS OF PROGRAM CODE. Restore language.
LD A,(LANGFLG)
OR A
PUSH DE ;Save error number
JR Z,SUBFAIL1 ;If no language option active, ignore next bit.
LD A,(LANGUAGE)
LD (MESS22A),A ;Select language in A
LD DE,MESS22
CALL SUBPRINT
SUBFAIL1:
POP DE
LD D,0FFH ;Generate a program code.
LD A,E
CP 5 ;If E=5, D=0 else D=0FFH (because error 5 is not
JR NZ,SUBFAIL2 ;a fatal error).
LD D,0
SUBFAIL2:
LD A,D ;Preserve code for the MCM.
LD (MCFAIL),A
LD C,BDCODE ;Send code.
CALL FDOS
LD A,(MCM)
OR A
JP NZ,RESET
RST 0 ;Leave.
;
SUBSCAN: ;SCAN COMMAND TAIL FOR /B,/E,/F,/H,/L,/M,/S,/U,/Z
;Returns with carry set if /H found.
;Other switches are dealt with internally.
LD A,(BUF+1) ;Length of command tail.
OR A
RET Z ;No command tail?
LD HL,BUF+2 ;Start of command tail.
SUBSCAN0:
LD A,(HL) ;Search for switch indicator "/"
CP '/'
JR Z,SUBSCAN1 ;Is there a '/'?
CP '-'
JR Z,SUBSCAN1 ;Is there a '-' (also used as a switch char.)
INC HL
OR A ;0=EOL marker
JR NZ,SUBSCAN0
RET ;/H Not found.
;
SUBSCAN1:
INC HL
LD A,(HL) ;EOL Detection
OR A
RET Z
CP 'B' ; Is switch "B"?
JP Z,SUBBEGIN
CP 'E' ; Is switch "E"?
JP Z,SUBEND
CP 'F' ; Is switch "F"?
JP Z,SUBFORMAT
CP 'I' ; Is switch "I"?
JP Z,SUBSIF
CP 'L' ; Is switch "L"?
JP Z,SUBLANG
CP 'M' ; Is switch "M"?
JP Z,SUBIF
CP 'S' ; Is switch "S"?
JP Z,SUBSELSAVE
CP 'U' ; Is switch "U"?
JP Z,SUBUSER
CP 'Z' ; Is switch "Z"?
JP Z,SUBSTRIP
CP '?' ; v1.02 - /? now supported as "help" option.
JR Z,FLGHLP
CP 'H' ; Is switch "H"?
JR NZ,SUBSCAN0 ; If not, continue search.
FLGHLP: SCF
RET ; Switch found.
;
SUBSCAN3:
INC HL
JP SUBSCAN0
;
SUBFORMAT:
LD A,(FORMDAT) ;Has there been a /F switch before now?
OR A
JR Z,SUBFORM0
PUSH HL
LD DE,MESS11 ;Can't have two /F switches
CALL SUBPRINT
POP HL
JR SUBSCAN3
;
SUBFORM0:
LD A,0FFH
LD (FORMDAT),A ;Flag: format already selected
INC HL
LD A,(HL) ;EOL?
OR A
RET Z
CP '=' ;= is a modifier for extra options on the +3.
JR NZ,SUBFORM1
LD A,0FFH
LD (SIZE),A ;Flag alternative (usually small) size.
JR SUBFORM2
;
SUBFORM1:
CP ':'
JR Z,SUBFORM2 ; If not /F: or /F=, inform of a syntax error.
LD DE,MESS12
CALL SUBPRINT
JR SUBSCAN3
;
SUBFORM2:
INC HL
LD A,(HL) ;Get the actual format
OR A
RET Z
CP '+' ;+3 format
JP Z,SUBPL3
CP 'A' ;Amstrad PCW format
JP Z,SUBPI2
CP 'C' ;MasterPaint .CAR format
JP Z,SUBCARFNT
CP 'E' ;EMS/EMT file format
JP Z,SUBEMSFNT
CP 'P' ;PRINTIT format
JP Z,SUBPRIFNT
CP 'S' ;Stop Press format
JP Z,SUBSPF
CP '?' ;Unknown format
JP Z,SUBINTFNT
LD DE,MESS13 ;Inavlid /F option.
CALL SUBPRINT
JP SUBSCAN3
;
SUBINTFNT:
PUSH AF ;INiTialise an unknown font format.
PUSH BC
PUSH DE
PUSH HL
XPASS4: CALL PASSPUT
LD DE,FCB
LD C,BDOPN
CALL FDOS ;Open the file
LD A,H
CP 7
JR NZ,XPASS5
CALL ERR8
JR XPASS4
;
XPASS5: INC A
JP Z,SBINT2
LD DE,FCB ;Get length
LD C,BDLEN
CALL FDOS
LD HL,FCB+23H
LD A,(HL) ;Get file length/128. MSB must be 0.
OR A
JR NZ,SUBINT1 ;Middle byte must be 0.
DEC HL
LD A,(HL) ;LSB=length.
OR A
JR NZ,SUBINT1
DEC HL
LD A,(HL) ;Guesses by file length
CP 7
JR Z,INTPL3 ;+3DOS
CP 10H
JP Z,INTPCW ;PCW
CP 11H
JP Z,INTHPCW ;Headed PCW
CP 18H
JP Z,INTPRI ;PRINTIT
CP 19H
JP Z,INTHPRI ;Headed PRINTIT
CP 20H
JR Z,INTBIG ;4k
CP 21H
JR Z,INTHBIG ;Headed 4k
CP 60
JP Z,INTCAR
CP 61H
JP Z,INTSPF ;Stop Press
SUBINT1:
LD DE,FCB ;Unknown size
LD C,BDCLO ;Close the file
CALL FDOS
LD DE,MESS26
CALL SUBPRINT ;"Sorry, no idea"
SBINT2: POP HL
POP DE
POP BC
POP AF ;Back to scanning the command line
JP SUBSCAN3
;
INTBIG: LD DE,MESS31 ;Guess: 4k size
CALL SUBPRINT
JR SBINT2
;
INTHBIG:
LD DE,MESS32 ;Guess: 4k size with header
CALL SUBPRINT
CALL SUBSTRP1
JR SBINT2
;
INTPL3: LD DE,MESS27 ;Guess: +3 file
CALL SUBPRINT
POP HL
POP DE
POP BC
POP AF
SUBPL3: ; SELECT A 768 BYTE +3DOS FILE
PUSH HL ; Store pointer
LD A,(STRIP) ;
OR A ; If /Z switch set, say that it
CALL NZ,SUBPL31 ; isn't needed.
LD A,0FFH
LD (PLUS3),A ; Set up marker: +3DOS selected.
POP HL
JP SUBSCAN3
SUBPL31:
LD DE,MESS23 ;Print "/Z switch not needed."
JP SUBPRINT
;
SUBIF: LD A,(MCM)
OR A ;Check; /M option is only valid in
JR Z,SUBIF1 ;Multiple command mode
INC HL
LD A,(HL)
OR A
RET Z
CP ':' ;Test for /M:x
JR NZ,SUBIF0
INC HL
LD A,(HL) ;A is the M code
OR A
RET Z
CP 'E' ;ELSE
JR Z,SUBELSE
CP 'C'
JR Z,SUBICPC
CP 'P'
JR Z,SUBIPCW
CP '+' ;+3?
JR NZ,SUBIF0
LD A,(ISSPEC)
XOR 0FFH ;0 FOR +3, 0FFH FOR OTHER
SUBIFX: LD (MCFAIL),A
POP HL
JP SUBINPFILE
;
SUBICPC:
LD A,(ISCPC) ;0 FOR NOT CPC, 0FFH FOR CPC
XOR 0FFH ;SWAP THESE OVER
JR SUBIFX
;
SUBIPCW:
LD A,(ISCPC)
LD B,A
LD A,(ISSPEC)
OR B ;0 FOR PCW, ELSE 0FFH
JR SUBIFX
;
SUBELSE:
LD A,(MCFAIL) ;If...Else type command.
CPL
LD (MCFAIL),A
POP HL
JP SUBINPFILE
;
SUBIF0: LD DE,MESS36 ;Bad syntax.
CALL SUBPRINT
JP SUBSCAN3
;
SUBIF1: LD DE,MESS37 ;Not in multi-command mode.
CALL SUBPRINT
JP SUBSCAN3
;
SUBBEGIN:
CALL SUBPARSEBE ;GET THE NUMBER IN BC
PUSH HL
LD HL,(DEND) ;COMPARE WITH "END" VALUE
OR A
SBC HL,BC
JR C,SUBBEG1 ;"START" > "END"
LD (DBEGIN),BC ;STORE "START" VALUE
POP HL
JP SUBSCAN3
;
SUBBEG1:
LD DE,MESS24 ;Say that Start>End.
CALL SUBPRINT
POP HL
JP SUBSCAN3
;
SUBEND: CALL SUBPARSEBE ;GET THE NUMBER IN BC
PUSH HL
LD H,B
LD L,C
LD DE,(DBEGIN) ;COMPARE WITH "END" VALUE
OR A
SBC HL,DE
JR C,SUBBEG1 ;"START" > "END"
LD (DEND),BC ;STORE "END" VALUE
POP HL
JP SUBSCAN3
;
SUBPARSEBE: ;GET A NUMBER (IN BC) FOR THE BEGINNING/END OPTIONS.
INC HL
LD A,(HL)
OR A
JR Z,STKRET
LD BC,0 ;OFFSET FOR CHARACTER SET
CP ':' ;/B:N - OFFSET IS BC=0
JR Z,SPBE1
PUSH AF ;/B=N
LD A,(ISSPEC) ;OFFSET FOR SMALL SET - IGNORED ON PCW.
AND 01H
LD B,A ;OFFSET IS 1 (256 CHARS) ON SPECTRUM AND
POP AF ;0 ON PCW.
CP '='
JR Z,SPBE1
LD DE,MESS25
CALL SUBPRINT
JP SUBSCAN3
;
STKRET: POP HL ;TIDY UP THE STACK
RET ;LEAVE SCANNER ROUTINE ALTOGETHER
;
SPBE1: INC HL
LD A,(HL)
OR A ;IF (HL)=0, END OF LINE.
JR Z,STKRET
PUSH BC
CALL PARSENUM ;NUMBER RETURNED IN DE.
POP BC
LD C,E ;FINAL NUMBER IN BC.
RET
;
SUBUSER: ;Set the user number, given in decimal.
INC HL
LD A,(HL)
OR A ;EOL?
RET Z
CP ':'
JP NZ,SUBUSER2 ;If the switch is not /U:nn then report
INC HL ;a syntax error.
LD A,(HL) ;EOL?
OR A
RET Z
CALL PARSENUM ;Parse the number.
JP C,SUBUSER2 ;If main carry flag set, not a number.
LD A,E ;Only low byte used.
AND 0FH ;Only low Nibble used.
LD E,A
LD D,0
CALL SUBUSER1 ;Set the user.
JP SUBSCAN0
;
SUBUSER1:
LD C,BDUSR ;Set user number.
PUSH BC ;Preserve BC & HL.
PUSH HL
CALL FDOS
POP HL
POP BC
JP SUBSCAN3
;
SUBUSER2:
LD DE,MESS15 ;Print "Syntax error.."
CALL SUBPRINT
JP SUBSCAN3
;
SUBLANG:
INC HL
LD A,(HL)
OR A
RET Z
CP '=' ;Check for /L:n or /L=n
JR Z,SETL1
CP ':'
JR Z,SETL2
BADLS: LD DE,MESS21 ;Bad /L syntax
CALL SUBPRINT
JP SUBSCAN3
;
SETL1: INC HL
LD A,(HL)
OR A
RET Z
CP '0'
JR C,BADLS
CP '8'
JR NC,BADLS ;Check: is it 0-7?
LD (MESS22A),A ;File language
LD A,0FFH
LD (LANGFLG),A ;Flag that language changes are needed.
JP SUBSCAN3
;
SETL2: INC HL
LD A,(HL)
OR A
RET Z
CP '0'
JR C,BADLS
CP '8'
JR NC,BADLS ;Check: is it 0-7?
LD (LANGUAGE),A ;Computer language
LD A,0FFH
LD (LANGFLG),A ;Flag that language changes are needed.
JP SUBSCAN3
;
INTSPF: LD DE,MESS35 ;Guess: Stop Press format
CALL SUBPRINT
POP HL
POP DE
POP BC
POP AF
SUBSPF: LD A,0FFH
LD (SPFFLG),A
JP SUBSCAN3
;
INTHPRI:
LD DE,MESS33 ;Guess: PRINTIT format (headed)
JR INTPRI1
;
INTPRI: LD DE,MESS28 ;Guess: PRINTIT format (not headed)
INTPRI1:
CALL SUBPRINT
POP HL
POP DE
POP BC
POP AF
SUBPRIFNT:
LD A,0FFH
LD (PRINTIT),A
JP SUBSCAN3
;
INTCAR: LD DE,MESS38
CALL SUBPRINT ;Guess: .CAR font.
POP HL
POP DE
POP BC
POP AF
SUBCARFNT:
LD A,0FFH ;Flag .CAR font.
LD (CARFLG),A
JP SUBSCAN3
;
PARSENUM:
;
;Inputs: HL points to the start of the number. Lines 0 terminated.
;Outputs:
; DE holds the number.
; HL points to the next character.
; Carry set if the first character was not a digit.
; If end-of-line reached, A=0FFH
LD (STARTADD),HL
CALL NUMERIC
RET C
LD DE,0
NUMLP1: LD A,(HL) ;A=DIGIT (ASCII)
OR A
JR Z,NUMLP3 ;EOL
CALL NUMERIC
JR C,NUMLP2 ;NON-NUMERIC => END OF NUMBER
SUB 30H ;A=NUMBER(HEX)
CALL X10 ;MOVE DIGITS IN DE UP.
CALL ADDDE ;DE=NUMBER(DECIMAL)
INC HL
JR NUMLP1
;
NUMLP2: LD A,0
SCF
CCF
RET
;
NUMLP3: LD A,0FFH
SCF
CCF
RET
;
NUMERIC:
;CHECK FOR NUMERIC DATA IN A
;IF OK, CARRY CLEAR.
CP '0'
RET C ;NOT OK
CP ':'
JR NC,NUM1
OR A ;NUMBER OK
RET
;
NUM1: SCF ;NOT OK
RET
;
X10:
;MULTIPLY DE BY 10.
;RETURN ANSWER IN DE.
PUSH HL
EX DE,HL ;NUMBER IN HL
ADD HL,HL ;HL=HL*2
PUSH HL
POP DE ;DE=HL*2
ADD HL,HL ;HL=HL*4
ADD HL,HL ;HL=HL*8
ADD HL,DE ;HL=HL*10
EX DE,HL ;DE=DE*10
POP HL
RET
;
ADDDE:
;ADD A TO DE
;
PUSH HL
EX DE,HL ;ONLY HL CAN BE USED HERE.
LD D,0
LD E,A
ADD HL,DE
EX DE,HL ;RESULT IN DE
POP HL
RET
;
DSEG
STARTADD:
DEFW 0
ENDADD: DEFW 0
DIGITS: DEFB 0
CSEG
;
SUBERASE: ;ERASE A FILE
LD DE,CRLF
CALL SUBPRINT
SUBERA0:
CALL PASSPUT
LD DE,FCB
LD C,BDERA ;Erase file.
CALL FDOS
LD A,H
CP 7
JR NZ,SUBERA1
CALL ERR8
JR SUBERA0
;
SUBERA1: ;If the file still exists, the ERASE was
LD DE,FCB ;unsuccessful.
LD C,BDSCN
CALL FDOS
CP 0FFH ;If the file does
JP Z,SAVE1 ;not exist, OK.
LD DE,MESS18
CALL SUBPRINT ;Otherwise, there has been an error.
CALL SUBPRFCB
LD DE,MESS19
CALL SUBPRINT ;Print "Can't erase FILENAME.TYP"
LD E,1
JP SUBCODE
;
SUBSELSAVE:
PUSH HL ;SELECT SAVE RATHER THAN LOAD
LD A,255
LD (LOADSAVE),A ;Set save flag
LD A,0EBH
LD (SETGET),A ;Read char. data rather than write.
OR A
POP HL
JP SUBSCAN3
;
SUBUPCASE: ;CONVERT A CHARACTER TO UPPER CASE
CP 061H ;Below "a"?
RET C
CP 07BH ;Above "z"?
RET NC
SUB 020H ;Otherwise, subtract 20H
RET
;
SUBSIF: LD A,0FFH ;Set "invert"
LD (INVFLG),A
RET
;
SUBSTRIP:
CALL SUBSTRP1 ;Select /Z option
JP SUBSCAN3
;
SUBSTRP1:
LD A,(PLUS3) ; If +3DOS option
OR A ; selected, the /Z
JR NZ,SUBSTRP2 ; option is unnecessary.
LD A,255 ; Tell the user so.
LD (STRIP),A
RET
;
SUBSTRP2:
LD DE,MESS23 ; Tell the user that you don't
CALL SUBPRINT ; need /Z with /F:+.
RET
;
PTR: LD A,(LOADSAVE) ;LOADING OR SAVING?
OR A
JP NZ,SAVEPTR ;Saving
CALL CG0
LD A,18h ; 24 records
LD (REC),A
LD HL,0B000H ; Load temporarily to B000H
LD (DMAADD),HL
CALL LOAD ;Load the expanded font.
LD HL,0B000H ;Chars 32-224
LD DE,0C100H
CALL ASDE
LD BC,00C00H
PTRL2: LDI
INC HL
LD A,B
OR C
JR NZ,PTRL2
JP LOAD5
;
SAVEPTR:
LD A,18H ; 24 records
LD (REC),A ;
CALL CHARGET
LD DE,0B000H
LD HL,0C100H
CALL ASHL
LD BC,00C00H ;Create a PRINTIT font at B000H
SAVPT1: LD A,(HL)
LD (DE),A
INC DE
LDI
LD A,B
OR C
JR NZ,SAVPT1
LD HL,0B000H ;
LD (DMAADD),HL ; Save starting at B000H
JP SAVE0 ;
;
ASHL: PUSH AF
PUSH DE
LD A,(SIZE)
OR A
JR Z,ASHL2
PCWP0A: LD DE,800H
ADD HL,DE
ASHL2: POP DE
POP AF
RET
;
ASDE: PUSH AF
PUSH HL
LD A,(SIZE)
OR A
JR Z,ASDE2
PCWP0: LD HL,800H
ADD HL,DE
EX DE,HL
ASDE2: POP HL
POP AF
RET
;
; Error handler routines:
;
ERR1: LD DE,MESS1 ;Bad environment
CALL SUBPRINT
RST 0
;
ERR2: LD DE,MESS2 ;File not found
CALL SUBPRINT
CALL SUBPRFCB
LD DE,CRLF
CALL SUBPRINT
LD E,2
JP SUBCODE
;
ERR3: LD DE,MESS3 ;End of file met.
CALL SUBPRINT
LD E,3
JP SUBCODE
;
ERR4: LD DE,MESS4 ;Read error.
CALL SUBPRINT
CALL SUBPRFCB
LD DE,CRLF
CALL SUBPRINT
LD E,4
JP SUBCODE
;
ERR5: LD DE,MESS6 ;No file specified.
CALL SUBPRINT
JP SUBINPFILE
;
ERR6: LD A,(CARFLG) ;The .CAR file is expected to exist already.
OR A
JP NZ,SUBERA0 ;Straight to "erase".
LD DE,MESS8 ;File exists already.
CALL SUBPRINT
CALL SUBPRFCB
LD DE,MESS8A
CALL SUBPRINT
LD C,BDKEY
CALL FDOS ;Await keypress
CP 'Y'
JP Z,SUBERASE
CP 'y'
JP Z,SUBERASE
LD DE,CRLF ;New line
CALL SUBPRINT
LD E,5
JP SUBCODE
;
ERR7: LD DE,MESS9 ;Write error
CALL SUBPRINT
CALL SUBPRFCB
LD DE,MESS9A
CALL SUBPRINT
LD E,6
JP SUBCODE
;
ERR8: LD A,(PASSUSED) ;GET A PASSWORD.
CP 0FFH
JP Z,ERR8A ;If a password was wrong, leave.
CALL ERR8B
LD DE,MESS16 ;Password needed.
CALL SUBPRINT
LD A,8
LD (CMDTAIL),A ;Ask for a password,
CALL SCR0
LD C,BDLIN ;maximum 8 characters.
LD DE,CMDTAIL
CALL FDOS
CALL SCR1
LD A,(0081H) ;Length of password.
OR A
LD E,7
JP Z,SUBCODE ;If no password, abort.
LD B,8
LD HL,0082H ; Convert max. 8
ERR8C: LD A,(HL) ; bytes of password
CALL SUBUPCASE ; to uppercase.
LD (HL),A
INC HL ; Next byte
DJNZ ERR8C
LD DE,PASSWORD ; Move to permanent home for password
LD HL,0082H
LD BC,8
LDIR
LD A,0FFH ; Flag that a
LD (PASSUSED),A ; password has been tried.
LD DE,CRLF
JP SUBPRINT
;
DSEG
SCB1: DEFW 0024H ;Get CONOUT: redirection
SCB2: DEFW 0FE24H ;Set CONOUT: redirection
CONVAL: DEFW 0 ;CONOUT: redirection value to set.
CONVEC: DEFW 0 ;True CONOUT: redirection value
CSEG
;
SCR0: LD DE,SCB1 ;Disable screen output
LD C,BDSCB
CALL FDOS ;Get current CONOUT: redirection.
LD (CONVEC),HL
LD C,6DH
LD DE,0FFFFH ;Disable ^C while input is being made.
CALL FDOS
LD D,H ;Get console mode
LD E,L
SET 3,E ;Flag that ^C is disabled
LD C,6DH ;and set console mode
CALL FDOS
LD HL,0 ;CONOUT:=NUL
SCR1A: LD (CONVAL),HL ;Set CONOUT: redirection to value in HL.
LD DE,SCB2
LD C,BDSCB
JP FDOS
;
SCR1: LD HL,(CONVEC) ;Restore former CONOUT: redirection
JR SCR1A
;
SCR2: LD DE,SCB1 ;Set CONOUT:=CRT, for printing of escape codes.
LD C,BDSCB
CALL FDOS
LD (CONVEC),HL
LD HL,8000H
JR SCR1A
;
ERR8A: LD DE,MESS17 ;Password invalid.
CALL SUBPRINT
LD E,7
JP SUBCODE
;
ERR8B: LD BC,8 ;Set 8 bytes to 20H
LD HL,0082H ;Password location
LD DE,0083H ;Filler destination
LD (HL),020H ;Filler byte
LDIR ;Password buffer filled with spaces.
RET
;
ERR9: LD DE,MESS20 ;Not enough memory.
CALL SUBPRINT
LD E,8
JP SUBCODE
;
ERR10: LD DE,MESS34 ;No font in EMS file
CALL SUBPRINT
LD E,9
JP SUBCODE
;
ERR11: LD DE,MESS39 ;Invalid font size in .CAR file.
CALL SUBPRINT
LD E,10
JP SUBCODE
;
ERR12: LD DE,MESS8 ;Attempt to write to a System file in user 0.
CALL SUBPRINT
CALL SUBPRFCB
LD DE,MESS40
CALL SUBPRINT
LD E,11
JP SUBCODE
;
HELP: LD DE,MESS7 ;Print the helpscreen
CALL SUBPRINT ;(Part 1)
LD C,BDKEY ;Await a keypress
CALL FDOS
CP 3 ;^C to abandon helpscreen
JP Z,WB1
LD DE,MESS7A ;Print part 2
CALL SUBPRINT
LD C,BDKEY ;keypress
CALL FDOS
CP 3 ;^C again.
JP Z,WB1
LD DE,MESS7B
CALL SUBPRINT ;Last bit of HELP message
JP WB1
;
; Program messages
;
DSEG
MESS1: DEFB 'This program requires Amstrad PCW/CPC or Spectrum +3.',CR,LF,'$'
MESS2: DEFB 'Input file not found: $'
FILDR: DEFB ' :'
FILSP: DEFB ' .'
FILTY: DEFB ' ',CR,LF,'$'
MESS3: DEFB 'End of file met.',CR,LF,'$'
MESS4: DEFB 'Disc read error: $'
MESS5: DEFB 'Character set loaded.',CR,LF,'$'
MESS6: DEFB 'SETFONT v1.02a Multiple Command Mode',cr,lf
DEFB 'For help type /H. To leave press RETURN.',CR,LF,lf,'$'
MESS7: DEFB 'SETFONT v1.02a',CR,LF,LF
DEFB 'Syntax:',CR,LF,' SETFONT {d:filename.ext} {/option /option...}'
DEFB CR,LF,LF
DEFB 'Options are /B /E /F /H /I /L /M /S /U /Z',cr,lf
;1...5...10...15...20...25...30...35...40...45...50...55...60...65...70...75...80
DEFB '/B and /E limit the loading of the font; only that part which lies between the',cr,lf
DEFB ' /B(egin) number and the /E(nd) number is used. Syntax is /B:n /B=n /E:n /E=n',cr,lf
DEFB ' On the Spectrum +3, if an equals sign is used, the number refers to the small',cr,lf
DEFB ' font.',cr,lf
DEFB '/F selects the font format:',cr,lf
DEFB ' F:+ - Spectrum +3DOS type. +3DOS fonts are saved or loaded with the correct',cr,lf
DEFB ' +3DOS header. The pound and copyright signs are loaded correctly.',cr,lf
DEFB ' F:A - Amstrad PCW/CPC type. Only useful on a Spectrum; others use this',cr,lf
DEFB ' format anyway.',cr,lf
DEFB ' F:C - MasterPaint .CAR font. When saving, modifies a file already present.',cr,lf
DEFB ' (Similar in size to STANDARD.CAR).',cr,lf
DEFB ' F:E - Contained in an EMS/EMT file. LocoScript 2 EMS files are not suitable',cr,lf
DEFB ' When saving, this modifies an EMS file already present.',cr,lf
DEFB '[More]',cr,'$'
MESS7A: DEFB ' F=E - On a Spectrum +3, restricts the /F:E action to the large font.',cr,lf
DEFB ' F:P - PRINTIT double-height font.',cr,lf
DEFB ' F:S - Stop Press font (similar in size to HITEC-70)',CR,LF
DEFB ' F:? - If you don`t know what it is',21h,' SETFONT will try to guess the',cr,lf
DEFB ' type (only useful when loading)',cr,lf
DEFB ' On the Spectrum +3, if you use an = sign instead of the colon (eg /F=P) then',cr,lf
DEFB 'the small font will be used (Except /F=E above).',cr,lf
DEFB '/H brings up this screen.',CR,LF
DEFB '/I inverts the font being loaded or saved.',cr,lf
DEFB '/L:n and /L=n select the CP/M language to use, as follows:',CR,LF
DEFB ' /L:n specifies which language the computer is in at the moment.',cr,lf
DEFB ' /L=n specifies which language the file should be in.',cr,lf
DEFB ' If only one of these is present, the other is assumed to be 0.',cr,lf
DEFB '/M:x Multi-command mode options. x can be +, C, E or P (see documentation)',cr,lf
DEFB '/S will make the program save instead of loading.',CR,LF
DEFB '/U needs a colon and then a user number from 0 to 15. It selects that area to',cr,lf
DEFB ' load or save with.',CR,LF
DEFB '[More]',cr,'$'
MESS7B: DEFB '/Z indicates that there is a "header" record on the file. If saving, the',cr,lf
DEFB ' "header record" contains machine code which makes the character set self-',cr,lf
DEFB ' loading. eg:',cr,lf,lf
DEFB ' SETFONT MYFONT.COM /Z /S ',cr,lf,lf
DEFB ' then typing MYFONT will load the font. The use when loading is to remove',cr,lf
DEFB ' +3DOS header information.',CR,LF
DEFB ' SETFONT with no filename or options enters the multiple command mode (like',cr,lf
DEFB 'PIP).',cr,lf
DEFB ' The program will work with Amstrad PCW 8000 and 9000 series, CPC 6128s and',cr,lf
DEFB 'ZX Spectrum +3 with CP/M. It uses a character set file. For information about',cr,lf
DEFB 'the format of the character set, see the documentation.',CR,LF,LF,'$'
MESS8: DEFB 'File $'
MESS8A: DEFB ' exists, delete (Y/N) ?$'
MESS9: DEFB 'Write error on file: $'
MESS9A: DEFB CR,LF,'The disc or directory may be full.',CR,LF,'$'
MESS10: DEFB 'This option is not valid: $'
MESS11: DEFB 'You can only have one /F switch in a command. Using first /F',cr,lf,'$'
MESS12: DEFB 'Syntax for /F switch is /F:f or /F=f',cr,lf,'$'
MESS13: DEFB 'Valid formats are +,?,A,C,E,P,S only.',cr,lf,'$'
MESS14: DEFB 'That filename is not valid.',cr,lf,'$'
INPPROMPT:
DEFB 'SETFONT>$'
CRLF: DEFB CR,LF,'$' ;
MESS15: DEFB 'The /U option must be followed by a colon. Only users 0-15 allowed.',CR,LF,'$'
MESS16: DEFB 'This file is password protected.',CR,LF,'Please enter password:$'
MESS17: DEFB 'Password was wrong.',CR,LF,'$'
MESS18: DEFB 'Can`t delete file: $'
MESS19: DEFB CR,LF,'The file may be read only.',CR,LF,'$'
MESS20: DEFB 'Not enough memory. Please remove RSXs etc.',cr,lf,'$'
MESS21: DEFB 'Syntax for /L option is /L:n or /L=n where n is a one-digit number.',cr,lf,'$'
MESS22: DEFB ESC,'2'
MESS22A: DEFB '0$'
MESS23: DEFB 'The /Z is unnecessary in +3DOS format.',cr,lf,'$'
MESS24: DEFB 'The "begin" number must be less than the "end" number.',cr,lf,'$'
MESS25: DEFB 'The "begin" and "end" options must be formed /B:n /B=n /E:n or /E=n',cr,lf,'$'
MESS26: DEFB 'File type unknown. Attempting to load as full font.',cr,lf,'$'
MESS27: DEFB 'Guess: Spectrum +3DOS type.',cr,lf,'$'
MESS28: DEFB 'Guess: PRINTIT type.',cr,lf,'$'
MESS29: DEFB 'Guess: Amstrad standard.',cr,lf,'$'
MESS30: DEFB 'Guess: Amstrad standard with header.',cr,lf,'$'
MESS31: DEFB 'Guess: Spectrum +3 CP/M.',cr,lf,'$'
MESS32: DEFB 'Guess: Spectrum +3 CP/M with header.',cr,lf,'$'
MESS33: DEFB 'Guess: PRINTIT type with header.',cr,lf,'$'
MESS35: DEFB 'Guess: Stop Press font.',cr,lf,'$'
MESS38: DEFB 'Guess: MasterPaint .CAR format font.',cr,lf,'$'
MESS34: DEFB 'This file contains no suitable font.',cr,lf,'$'
MESS36: DEFB '/M option must be formed /M:x where x is +,C,E or P',cr,lf,'$'
MESS37: DEFB 'Not in multiple command mode - /M option ignored.',cr,lf,'$'
MESS39: DEFB 'The font does not have 8x8 character size.',cr,lf,'$'
MESS40: DEFB ' is a System file in User 0 - Cannot write to it from here.',cr,lf,'$'
;
; Program data
;
DMAADD: DEFW BUFFER
REC: DEFB 020H
PASSUSED: DEFB 0 ;Was a password used?
USER: DEFB 0 ;Startup user number.
FORMDAT: DEFB 0 ;was there a /F switch?
PLUS3: DEFB 0 ;/F:+ switch?
PCW: DEFB 0 ;/F:A switch?
EMSFLG: DEFB 0 ;/F:E switch?
PRINTIT: DEFB 0 ;/F:P switch?
SPFFLG: DEFB 0 ;/F:S switch?
CARFLG: DEFB 0 ;/F:C switch?
SIZE: DEFB 0 ;/F= switch?
INVFLG: DEFB 0 ;/I switch?
LANGUAGE: DEFB 0 ;/L: switch?
LANGFLG: DEFB 0 ;/L switch?
LOADSAVE: DEFB 0 ;/S switch?
STRIP: DEFB 0 ;/Z switch?
DBEGIN: DEFW 0
DEND: DEFW 511
ISSPEC: DEFB 0FFH ;SPECTRUM OR AMSTRAD?
ISCPC: DEFB 0 ;PCW OR CPC?
MCM: DEFB 0 ;MULTI-COMMAND MODE?
MCFAIL: DEFB 0 ;MULTI-COMMAND MODE FAILURE FLAG
PASS1: DEFB ' '
;
; There now follows the +3DOS header for a character set file:
;
HEADER: DEFB 'PLUS3DOS',01AH ; +3DOS signature
DEFB 1,0 ; Version 1.0
DEFW 0380H,0 ; Length=768+Header
;Now follows +3BASIC information
DEFB 3 ; +3DOS CODE type file.
DEFW 768 ; 768 bytes
DEFW 0 ; Load address not specified.
DEFB 0,0,0 ; Unused bytes.
; The next 104 bytes are reserved.
DEFS 104
;
DEFB 01 ; Header checksum
CSEG
;
COMHED:
;
; This section will be loaded 0100h relative.
CH1:
.phase 0100h
LD BC,01000H
LD HL,0180H
LD DE,0C080H
LDIR ;MOVE FONT UP TO 0C000H
LD BC,007FH
LD HL,CHHHH
LD DE,0C000H
LDIR
LD HL,(0101H)
LD (0C001H),HL
CALL CHUSF
DEFW 00E3H
CP 01H
JR Z,CHPCW
OR A
JP Z,CHCPC
LD HL,SCHRSET
LD (CHRTX+1),HL
CHRUN: LD BC,CHRTN
CALL CHUSF
DEFW 00E9H
RST 0
;
CHPCW: LD HL,0800H
LD (CHRTN+1),HL
LD HL,PCHRSET
LD (CHRTX+1),HL
JR CHRUN
;
CHCPC: LD HL,0800H
LD (CHRTN+1),HL
CALL CHUSF
DEFW 0C000H
RST 0
;
CHUSF: LD HL,(1)
LD DE,0057H
ADD HL,DE
JP (HL)
;
CHHHH: .DEPHASE
.PHASE 0C000H
CHRTN: LD BC,01000H ;C000
CHRTX: LD DE,CCHRSET ;C003
LD HL,0C080H
LDIR
RET
;
.DEPHASE
DEFB 13,27,'MCharacter set',13,10,26
;
END