2953 lines
182 KiB
NASM
2953 lines
182 KiB
NASM
;
|
|
; SHARP MZ-800 Monitor 1Z-013B
|
|
; (C) Sharp Corporation, 1982-84
|
|
;
|
|
; This source based on the printer listing of the original rom dissassembled by the Czech Sharp Users Club 1987.
|
|
;
|
|
; Dissassembly had missing data definition areas which have now been added along with translation
|
|
; of the comments and changes to better match the Sharp original listing labels.
|
|
;
|
|
; Re-assembly of this source using the Glass Z80 assembler results in identical output compared with the original rom.
|
|
;
|
|
; This code is targetted in the lower monitor region, 0x0000 - 0x0FFF
|
|
;
|
|
|
|
ORG 00000H
|
|
INCLUDE "macros.asm"
|
|
|
|
; Printer interface
|
|
PCPR: EQU 0FCH ; Z80 / PIO
|
|
PLPT: EQU PCPR+3 ; printer data output
|
|
PLPTS: EQU PCPR+2 ; printer strobe
|
|
PLPTI: EQU PCPR+1 ; printer data port inic
|
|
PLPTSI: EQU PCPR+0 ; printer strobe port inic
|
|
; Program sound generator
|
|
PPSG: EQU 0F2H ; Prog. Sound Gen.
|
|
; Joystick registers
|
|
PJ1: EQU 0F1H ; joystick-2 input port
|
|
PJ0: EQU 0F0H ; joystick-1 input port
|
|
; Pallet write
|
|
PPAL: EQU 0F0H ; pallet write
|
|
; Memory managerment ports OUT / IN
|
|
MMIO0: EQU 0E0H ; DRAM up / VRAM
|
|
MMIO1: EQU 0E1H ; DRAM up / VRAM pryc
|
|
; Memory managerment ports OUT
|
|
MMIO2: EQU 0E2H ; ROM down
|
|
MMIO3: EQU 0E3H ; ROM up
|
|
MMIO4: EQU 0E4H ; maximum neRAM as far as possible
|
|
MMIO5: EQU 0E5H ; Inhibit upper memory access
|
|
MMIO6: EQU 0E6H ; Restore upper memory access
|
|
; Floppy disk
|
|
PFD: EQU 0D8H
|
|
PFDSIZ: EQU PFD+5 ; floppy side settings
|
|
PFDMOT: EQU PFD+4 ; drive on / off
|
|
PFDDAT: EQU PFD+3 ; register that
|
|
PFDSEC: EQU PFD+2 ; sector register
|
|
PFDTRK: EQU PFD+1 ; track register
|
|
PFDCTR: EQU PFD+0 ; driving word
|
|
; 8253 I/O. mapped. - interupt, clock, etc.
|
|
P8253: EQU 0D4H ; 8253 I / O. Mapped
|
|
PCTCC: EQU P8253+3 ; control word 8253
|
|
PCTC2: EQU P8253+2 ; counter 2
|
|
PCTC1: EQU P8253+1 ; counter 1
|
|
PCTC0: EQU P8253+0 ; counter 0
|
|
; 8255 I/O mapped - klavesnice, joystick, CMT
|
|
P8255: EQU 0D0H
|
|
PCWR55: EQU P8255+3 ; control word 8255
|
|
PPORTC: EQU P8255+2 ; port C - CMT and control
|
|
PKBDIN: EQU P8255+1 ; keyboard input
|
|
PKBOUT: EQU P8255+0 ; keyboard strobe
|
|
; GDG I/O ports
|
|
GDCRTC: EQU 0CFH ; CRTC control register
|
|
GDCMD: EQU 0CEH ; CRTC Mode register
|
|
GDGRF: EQU 0CDH ; read format register
|
|
GDGWF: EQU 0CCH ; write format register
|
|
;
|
|
; Memory mapping
|
|
;
|
|
MGATE0: EQU 0E008H ; enable / disable music
|
|
; 8253 mem. mapped - Interupt, clock
|
|
M8253: EQU 0E004H ; 8253 Mem. Mapped
|
|
MCTCC: EQU M8253+3 ; control word 8253
|
|
MCTC2: EQU M8253+2 ; counter 2
|
|
MCTC1: EQU M8253+1 ; counter 1
|
|
MCTC0: EQU M8253+0 ; counter 0
|
|
; 8255 mem. mapped - klavesnice, joystick, CMT
|
|
M8255: EQU 0E000H
|
|
MCWR55: EQU M8255+3 ; control word 8255
|
|
MPORTC: EQU M8255+2 ; port C - CMT and control
|
|
MKBDIN: EQU M8255+1 ; keyboard input
|
|
MKBOUT: EQU M8255+0 ; keyboard strobe
|
|
;
|
|
; ASCII constants
|
|
CR: EQU 0DH ; novy line
|
|
SPACE: EQU 20H ; gap
|
|
ESC: EQU 1BH ; escape
|
|
CLS: EQU 16H ; clear the screen
|
|
CRD: EQU 0CDH ; CR in display code
|
|
NOKEY: EQU 0F0H ; code NO KEY
|
|
; definition of display addresses
|
|
ADRCRT: EQU 0D000H ; address MZ-700 VRAM
|
|
ADRATB: EQU 0D800H ; the address of the CRS attribute
|
|
IMPATB: EQU 71H ; default display attribute
|
|
; priznaky pro podprogramy CMT
|
|
CHEAD: EQU 0CCH ; indication of CMT work with header
|
|
CDATA: EQU 053H ; ---- "---- with data
|
|
CWRITE: EQU 0D7H ; CMT indication write data
|
|
CREAD: EQU 0D2H ; --- "--- read"
|
|
;
|
|
HBLNK: EQU 50*312+11 ; frequency of line decomposition
|
|
;
|
|
INTSRQ: EQU 1038H ; PjpM
|
|
INTADR: EQU 1039H ; 038Dh ... bounce from INT (38h)
|
|
HEAD: EQU 10F0H ; file control block:
|
|
NEWSP: EQU HEAD ; processor tray
|
|
FNAME: EQU 10F1H ; filename
|
|
FSIZE: EQU 1102H ; length
|
|
BEGIN: EQU 1104H ; storage address
|
|
ENTRY: EQU 1106H ; start address
|
|
OLDSP: EQU 1148H ; used to postpone SP
|
|
CONMOD: EQU 1170H ; 0b = alpha / graph, 1b = display
|
|
CURSOR: EQU 1171H ; cursor position (row / column)
|
|
QATBLN: EQU 1173H ; line join attribute table
|
|
AKCHAR: EQU 118EH ; the character under the cursor when the cursor is blinking
|
|
CURCH: EQU 1192H ; graphical cursor character
|
|
CSRH: EQU 1194H ; position on the line
|
|
TMLONG: EQU 1195H ; current length TAPE MARK
|
|
MGCRC: EQU 1197H ; checksum for CMT
|
|
MGCRCV: EQU 1199H ; checksum verify CMT
|
|
AMPM: EQU 119BH ; morning / afternoon flag
|
|
EIFLG: EQU 119CH ; EI / DI flag
|
|
BPFLG: EQU 119DH ; BEEP ON / OFF flag
|
|
TEMPO: EQU 119EH ; tempo for music 0-7
|
|
NOTLEN: EQU 119FH ; length of current sheet music
|
|
OKTNUM: EQU 11A0H ; octave number 1,2,3
|
|
FREQ: EQU 11A1H ; frequency of the current tone
|
|
IOBUF: EQU 11A3H ; input buffer for GETL
|
|
MGBASE: EQU 1200H ; boot address
|
|
COLD: EQU 0E800H ; cold start system
|
|
RBASE: EQU 0FFF0H ; run the program in RAM
|
|
;
|
|
;
|
|
; MZ-700 monitor services vector
|
|
;
|
|
@COLD: JP COLD ; cold start
|
|
@GETL: JP GETL ; read a line from KBD
|
|
@LETNL: JP LETNL ; CRLF and CRT
|
|
@IFNL?: JP IFNL? ; conditional CRLF
|
|
@PRNTS: JP PRNTS ; space on CRT
|
|
@TAB: JP TAB ; tabulation on CRT
|
|
@PRNTC: JP PRNTC ; character on CRT
|
|
@MSG: JP MSG ; CRT string
|
|
@RST18: JP RST18 ; reported to CRT
|
|
@GETKY: JP GETKY ; character from KBD
|
|
@BRKEY: JP BRKEY ; test on BREAK
|
|
@WHEAD: JP WHEAD ; write headers to CMT
|
|
@WDATA: JP WDATA ; write the program to CMT
|
|
@RHEAD: JP RHEAD ; read headers from CMT
|
|
@RDATA: JP RDATA ; read the program from CMT
|
|
@VERIF: JP VERIF ; program comparison
|
|
@MELDY: JP MELDY ; melody
|
|
@TIMST: JP TIMST ; time setting
|
|
DB 0,0 ; called for RST 38H
|
|
@RST38: JP INTSRQ ; interrupt service
|
|
@TIMRD: JP TIMRD ; read time
|
|
@BEEP: JP BEEP ; acoustic signal
|
|
@XTEMP: JP XTEMP ; tempo for melodies
|
|
@MSTA: JP MSTA ; sound start
|
|
@MSTP: JP MSTP ; stopped sound
|
|
;
|
|
; COLD - leftover from the MZ-700 computer
|
|
;
|
|
LD SP,NEWSP
|
|
IM 1
|
|
CALL @INI55
|
|
CALL BRKEY
|
|
JR NC,J0070 ; CTRL or SHIFT
|
|
CP 20H
|
|
JR NZ,J0070 ; SHIFT, that's uninteresting
|
|
GORAM: ; jump to RAM from address 0
|
|
OUT (MMIO1),A ; mapping - end = DRAM
|
|
LD DE,RBASE ; where
|
|
LD HL,QRUNT ; what
|
|
LD BC,5 ; pin
|
|
LDIR ; MOVE
|
|
JP RBASE ; ... jump
|
|
;
|
|
QRUNT: OUT (MMIO0),A ; ... for copying
|
|
JP 0 ; jump to RAM
|
|
;
|
|
J0070:
|
|
LD B,255 ; zero
|
|
LD HL,FNAME ; memory info
|
|
CALL @F0B ; cartridge block
|
|
LD A,CLS
|
|
CALL @PRNTC ; clear display
|
|
LD A,IMPATB ; default attribute 71H
|
|
LD HL,ADRATB ; attribute address in VRAM
|
|
CALL @FILLA ; CRT attribute settings
|
|
LD HL,@CLOCK ; initialization interrupted
|
|
LD A,0C3H ; C3 = JP
|
|
LD (INTSRQ),A
|
|
LD (INTADR),HL ; the address of the basic interrupt routine
|
|
LD A,4
|
|
LD (TEMPO),A ; music tempo initialization
|
|
CALL MSTP ; stop music
|
|
CALL @IFNL?
|
|
LD DE,SMON7 ; introductory message of the monitor
|
|
RST 18H
|
|
CALL BEEP
|
|
LD A,1
|
|
J00A4:
|
|
LD (BPFLG),A ; turn off BEEP
|
|
LD HL,0E800H ; if it is on the E800h ROM
|
|
LD (HL),A ; so there is a sale
|
|
JR J0102
|
|
;
|
|
; Input and display decryption
|
|
; DE .... address of the chain
|
|
; B ..... its length
|
|
;
|
|
FPRMPT:
|
|
CALL @IFNL?
|
|
LD A,'*' ; Reporting sign
|
|
CALL @PRNTC
|
|
LD DE,IOBUF ; Input buffer address
|
|
CALL @GETL ; Honor the display
|
|
PRMLOP: LD A,(DE)
|
|
INC DE
|
|
CP CR
|
|
JR Z,FPRMPT ; sell monitor control
|
|
CP 'J'
|
|
JR Z,FJUMP ; sell control of the program
|
|
CP 'L'
|
|
JR Z,FLOAD ; upload and run the program
|
|
CP 'F'
|
|
JR Z,FF???? ; jump up when ROM
|
|
CP 'B'
|
|
JR Z,FBEEPX ; beep on / off after the character
|
|
CP '#'
|
|
JR Z,GORAM ; jump to RAM from 0
|
|
CP 'P'
|
|
JR Z,FPRINT ; printer operator
|
|
CP 'M'
|
|
JP Z,FMODIF ; memory modification
|
|
CP 'S'
|
|
JP Z,FSAVE ; save the program to CMT
|
|
CP 'V'
|
|
JP Z,FVERIF ; program comparison on CMT
|
|
CP 'D'
|
|
JP Z,FDUMP ; listing of memory contents
|
|
NOP
|
|
NOP
|
|
NOP
|
|
NOP
|
|
JR PRMLOP ; the first character is not a display, perhaps another
|
|
;
|
|
FJUMP:
|
|
CALL FHLHEX ; decode the jump address
|
|
JP (HL) ; and sell control
|
|
;
|
|
FBEEPX: ; controlled whistling after each character
|
|
LD A,(BPFLG)
|
|
RRA
|
|
CCF
|
|
RLA
|
|
JR J00A4
|
|
;
|
|
FF????: ; look up
|
|
LD HL,0F000H ; if there is something a lot
|
|
J0102: ; zajimaveho
|
|
LD A,(HL) ; when there is zero,
|
|
OR A ; so he won't jump there
|
|
JR NZ,FPRMPT ; and when there will be zero
|
|
JP (HL) ; so jump right there
|
|
;
|
|
FCMTER: ; recognizes and responds
|
|
CP 2 ; type of error you
|
|
JR Z,FPRMPT ; return routines for
|
|
LD DE,SCHECK ; works with CMT:
|
|
RST 18H
|
|
FPRMP1: ; relative jumps are
|
|
JR FPRMPT ; sometimes too short
|
|
;
|
|
FLOAD:
|
|
CALL RHEAD ; read the program header
|
|
JR C,FCMTER
|
|
CALL @IFNL?
|
|
LD DE,SLOAD ; lists LOADING
|
|
RST 18H
|
|
LD DE,FNAME ; and the name of the program
|
|
RST 18H
|
|
CALL RDATA ; read the program
|
|
JR C,FCMTER
|
|
LD HL,(ENTRY)
|
|
LD A,H ; if the start address is
|
|
CP MGBASE/256 ; less than 1200H so
|
|
JR C,FPRMP1 ; return to the monitor and v
|
|
JP (HL) ; otherwise the sale
|
|
; control of the recorded program
|
|
FGETL: ; read the row from the keyboard
|
|
EX (SP),HL
|
|
POP BC
|
|
LD DE,IOBUF ; works with standard
|
|
CALL @GETL ; I / O buffer
|
|
LD A,(DE)
|
|
CP ESC ; break?
|
|
JR Z,FPRMP1 ; yes, return to monitor
|
|
JP (HL) ; no, return
|
|
;
|
|
FHLHEX: ; decodes the address in the display
|
|
EX (SP),IY ; returned to IY
|
|
POP AF ; and out of the cellar
|
|
CALL @HLHEX ; try to decode
|
|
JR C,FPRMP1 ; not possible, so to the monitor
|
|
JP (IY) ; return
|
|
;
|
|
SCHECK: DB "CHECK SUM ER."
|
|
DB CR
|
|
FPRINT: ; dump the rest of the display
|
|
LD A,(DE) ; on the printer
|
|
CP '&' ; & is a special feature flag
|
|
JR NZ,FP ; & was not, list everything
|
|
J015A: INC DE ; testing character for &
|
|
LD A,(DE)
|
|
CP 'L'
|
|
JR Z,FPL ; 60 characters per line
|
|
CP 'S'
|
|
JR Z,FPS ; 80 characters per line
|
|
CP 'C'
|
|
JR Z,FPC ; exchange per
|
|
CP 'G'
|
|
JR Z,FPG ; graphically mod
|
|
CP 'T'
|
|
JR Z,FPT ; test
|
|
FP:
|
|
CALL FPTEXT
|
|
JP FPRMPT
|
|
;
|
|
FPL:
|
|
LD DE,QPRN2 ; 60 characters per line
|
|
JR FP
|
|
;
|
|
FPS:
|
|
LD DE,QPRN1 ; 80 characters per line
|
|
JR FP
|
|
;
|
|
FPT:
|
|
LD A,4 ; test
|
|
JR J0186
|
|
;
|
|
FPG:
|
|
LD A,2 ; graphically mod
|
|
J0186: CALL FPCHAR
|
|
JR J015A
|
|
;
|
|
FPC:
|
|
LD A,1DH ; exchange per
|
|
JR J0186
|
|
;
|
|
FPCHAR: ; print character to LPT
|
|
LD C,0
|
|
LD B,A
|
|
CALL FPTEST ; check for LPT
|
|
LD A,B
|
|
OUT (PLPT),A ; after sign
|
|
LD A,10000000B
|
|
OUT (PLPTS),A ; and confirm it
|
|
LD C,1 ; waiting for LPT to be taken over
|
|
CALL FPTEST
|
|
XOR A
|
|
OUT (PLPTS),A ; and match confirmed
|
|
RET
|
|
;
|
|
FPTEXT: ; print text to a printer
|
|
PUSH DE ; in DE is the address
|
|
PUSH BC ; the text must end CR
|
|
PUSH AF ; and it also prints
|
|
PTELOP: LD A,(DE) ; character from the buffer
|
|
CALL FPCHAR ; and LPT
|
|
LD A,(DE) ; again this character
|
|
INC DE ; point to the next
|
|
CP CR ; CR was sent
|
|
JR NZ,PTELOP ; No, let's go
|
|
POP AF ; CR sent, end of
|
|
POP BC
|
|
POP DE
|
|
RET
|
|
;
|
|
FPTEST: ; printer readiness test
|
|
IN A,(PLPTS)
|
|
AND 00001101B
|
|
CP C
|
|
RET Z ; hura, READY printer
|
|
CALL @BRKEY
|
|
JR NZ,FPTEST ; when the printer is silent
|
|
LD SP,NEWSP ; and BREAK is pressed
|
|
JP FPRMPT ; jump to the monitor
|
|
;
|
|
; Plays music stored on DE, terminated by CR,
|
|
; it is there ASCII in the MZ-700 Basic conventions
|
|
;
|
|
; input: DE - string address
|
|
; output: AF
|
|
;
|
|
MELDY:
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD A,2 ; standard octave number
|
|
LD (OKTNUM),A
|
|
LD B,1
|
|
MELOOP:
|
|
LD A,(DE)
|
|
CP CR ; the end?
|
|
JR Z,J0211 ; Yes
|
|
CP 0C8H ; or, such an end?
|
|
JR Z,J0211 ; Yes
|
|
CP 0CFH
|
|
JR Z,J0205 ; o oktavu niz
|
|
CP '-'
|
|
JR Z,J0205 ; o oktavu niz
|
|
CP '+'
|
|
JR Z,J020D ; o oktavu vys
|
|
CP 0D7H
|
|
JR Z,J020D ; o oktavu vys
|
|
CP '#'
|
|
LD HL,MTBL
|
|
JR NZ,J01F5 ; normal tons
|
|
LD HL,MTBLS
|
|
INC DE ; pultony
|
|
J01F5: CALL @MELTB ; look for the note
|
|
JR C,MELOOP ; not found
|
|
CALL @MELW ; wait for the end last time
|
|
JR C,J0214 ; BREAK
|
|
CALL MSTA ; turn on food
|
|
LD B,C
|
|
JR MELOOP
|
|
J0205: LD A,3 ; o oktavu vys
|
|
J0207: LD (OKTNUM),A
|
|
INC DE
|
|
JR MELOOP
|
|
J020D: LD A,1 ; o oktavu niz
|
|
JR J0207
|
|
J0211: CALL @MELW ; we play
|
|
J0214: PUSH AF
|
|
CALL MSTP ; and it will no longer be played
|
|
POP AF
|
|
JP POPX2 ; POP and RET
|
|
;
|
|
; Finds the actual frequency and length in the melody table
|
|
; according to the ASCII chain
|
|
;
|
|
; input: HL - table address
|
|
; DE - address to the music buffer
|
|
; (DE) - ASCII note sought
|
|
;
|
|
; exit:
|
|
;
|
|
; note found: DE = address of next item
|
|
; (FREQ) = frequency 2 bytes
|
|
; C = length of the note
|
|
; A = 0
|
|
; HL = undefined
|
|
;
|
|
; If the 1st character is not a note number, it returns CY = 1 and adjusts only DE
|
|
; If the 2nd character is not a length, the drive binds the specified length
|
|
;
|
|
@MELTB:
|
|
PUSH BC
|
|
LD B,8
|
|
LD A,(DE)
|
|
J0220: CP (HL) ; look in the sheet music
|
|
JR Z,J022C
|
|
INC HL
|
|
INC HL
|
|
INC HL
|
|
DJNZ J0220
|
|
SCF ; bad note
|
|
INC DE
|
|
POP BC
|
|
RET
|
|
J022C: ; we found a note
|
|
INC HL
|
|
PUSH DE
|
|
LD E,(HL) ; frequency to DE
|
|
INC HL
|
|
LD D,(HL)
|
|
EX DE,HL
|
|
LD A,H
|
|
OR A ; is small ?
|
|
JR Z,J023F ; yes, ignore octaves
|
|
LD A,(OKTNUM) ; octave number
|
|
J0239: DEC A
|
|
JR Z,J023F ; finally donated
|
|
ADD HL,HL ; multiple of frequency
|
|
JR J0239
|
|
J023F: LD (FREQ),HL
|
|
LD HL,OKTNUM
|
|
LD (HL),2 ; middle octave
|
|
DEC HL ; points to the length of the note
|
|
POP DE
|
|
INC DE
|
|
LD A,(DE) ; length of the buffer
|
|
LD B,A
|
|
AND NOKEY
|
|
CP '0'
|
|
JR Z,J0255 ; it can be a number
|
|
LD A,(HL) ; it's nonsense
|
|
JR J025A ; so we go from the last length
|
|
J0255: INC DE
|
|
LD A,B
|
|
AND 0FH
|
|
LD (HL),A ; save note length (0-9)
|
|
J025A: LD HL,QMELEN ; indexing of the TEMPO table
|
|
ADD A,L
|
|
LD L,A
|
|
LD C,(HL) ; actual length
|
|
LD A,(TEMPO)
|
|
LD B,A
|
|
XOR A
|
|
J0265: ADD A,C ; multiply with pace
|
|
DJNZ J0265
|
|
POP BC
|
|
LD C,A
|
|
XOR A
|
|
RET
|
|
;
|
|
; melody table for normal notes
|
|
;
|
|
MTBL: DB 'C'
|
|
DW 2118
|
|
DB 'D'
|
|
DW 1887
|
|
DB 'E'
|
|
DW 1681
|
|
DB 'F'
|
|
DW 1587
|
|
DB 'G'
|
|
DW 1414
|
|
DB 'A'
|
|
DW 1260
|
|
DB 'B'
|
|
DW 1124
|
|
DB 'R'
|
|
DW 0
|
|
;
|
|
; Frequency table for # notes
|
|
;
|
|
MTBLS: DB 'C'
|
|
DW 1999
|
|
DB 'D'
|
|
DW 1781
|
|
DB 'E'
|
|
DW 1587
|
|
DB 'F'
|
|
DW 1498
|
|
DB 'G'
|
|
DW 1335
|
|
DB 'A'
|
|
DW 1189
|
|
DB 'B'
|
|
DW 1059
|
|
DB 'R'
|
|
DW 0
|
|
;
|
|
; Table of length notes
|
|
;
|
|
QMELEN: DB 1,2,3,4,6,8,12,16,24,32
|
|
;
|
|
; DE = DE + 4 (if it were a macro assembler)
|
|
;
|
|
@IC4DE: INC DE
|
|
INC DE
|
|
INC DE
|
|
INC DE
|
|
RET
|
|
;
|
|
; Turns on music at (FREQ),
|
|
; writes it to 8253 and executes LD (M GATE0), 1
|
|
; this will start it
|
|
;
|
|
MSTA:
|
|
LD HL,(FREQ) ; frequency here
|
|
LD A,H
|
|
OR A
|
|
JR Z,MSTP ; if it is 0 then stop
|
|
PUSH DE
|
|
EX DE,HL
|
|
LD HL,MCTC0
|
|
LD (HL),E ; set frequency
|
|
LD (HL),D
|
|
LD A,1 ; turn on the music
|
|
POP DE
|
|
JR J02C4
|
|
;
|
|
; Stop the music
|
|
;
|
|
MSTP:
|
|
LD A,36H ; will not be quoted anymore
|
|
LD (MCTCC),A
|
|
XOR A ; ban music
|
|
J02C4: LD (MGATE0),A ; and it goes to GATE 8253
|
|
RET
|
|
;
|
|
; Wait for the melody to finish
|
|
;
|
|
; input: B = length of waiting
|
|
; output: HL = E000
|
|
; A = 0
|
|
; CY = 1 ... break
|
|
; 0 ... waited
|
|
;
|
|
@MELW:
|
|
LD HL,MKBOUT ; key strobe
|
|
LD (HL),0F8H
|
|
INC HL
|
|
LD A,(HL) ; key input
|
|
AND 81H
|
|
JR NZ,J02D5 ; no one is squeezing anything
|
|
SCF ; it was a break
|
|
RET
|
|
J02D5: LD A,(MGATE0)
|
|
RRCA
|
|
JR C,J02D5 ; wait for one
|
|
J02DB: LD A,(MGATE0)
|
|
RRCA
|
|
JR NC,J02DB ; wait for zero
|
|
DJNZ J02D5 ; and more expectations
|
|
XOR A
|
|
RET
|
|
;
|
|
; Set melody tempo 0-7
|
|
; 8-A -M TIME
|
|
;
|
|
XTEMP:
|
|
PUSH AF
|
|
PUSH BC
|
|
AND 0FH ; only the lower 4 bits
|
|
LD B,A ; we read from eight
|
|
LD A,8
|
|
SUB B
|
|
LD (TEMPO),A ; and store where it belongs
|
|
POP BC
|
|
POP AF
|
|
RET
|
|
;
|
|
; Returns the display attributes
|
|
;
|
|
; output: HL = cursor position
|
|
; DE = address in the next row table
|
|
; A bit 0 = attribute of the current line
|
|
; A bit 7 = CY = next line attribute
|
|
;
|
|
@ATBLN:
|
|
LD HL,QATBLN
|
|
LD A,(CURSOR+1) ; row number
|
|
ADD A,L ; index table
|
|
LD L,A
|
|
LD A,(HL) ; attribute of our line
|
|
INC HL
|
|
RL (HL)
|
|
OR (HL) ; and complete the attribute
|
|
RR (HL) ; dalsiho radku
|
|
RRCA ; to the tech bits where it belongs
|
|
EX DE,HL
|
|
LD HL,(CURSOR) ; current position
|
|
RET ; cursor
|
|
;
|
|
; Time setting
|
|
;
|
|
; A = 0 ... in the morning
|
|
; 1 ... in the afternoon
|
|
;
|
|
; DE = number of seconds since the beginning of the field
|
|
;
|
|
; CT1 ... period 1 second (mod 2)
|
|
; CT2 ... period 43200 period CT1 = 12 hours (mod 0)
|
|
;
|
|
TIMST:
|
|
DI
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD (AMPM),A
|
|
LD A,NOKEY
|
|
LD (EIFLG),A ; enable disruption
|
|
LD HL,43200
|
|
XOR A
|
|
SBC HL,DE ; how much is left until 12
|
|
PUSH HL ; so much to hide
|
|
NOP
|
|
EX DE,HL
|
|
LD HL,MCTCC
|
|
LD (HL),01110100B ; CT1 mod 2
|
|
LD (HL),10110000B ; CT2 mod 0
|
|
DEC HL
|
|
LD (HL),E ; set CT2
|
|
LD (HL),D
|
|
DEC HL
|
|
LD (HL),10 ; then 10 to CT1
|
|
LD (HL),0
|
|
INC HL
|
|
INC HL
|
|
LD (HL),10000000B ; CT2 mod 0 latch
|
|
DEC HL
|
|
J0331: LD C,(HL) ; wait for CT2
|
|
LD A,(HL) ; docita, so far
|
|
CP D ; goes fast
|
|
JR NZ,J0331
|
|
LD A,C
|
|
CP E
|
|
JR NZ,J0331
|
|
DEC HL
|
|
NOP
|
|
NOP
|
|
NOP
|
|
LD (HL),HBLNK % 256 ; to CT1 is saved
|
|
LD (HL),HBLNK/256 ; what belongs there
|
|
INC HL
|
|
POP DE
|
|
J0344: LD C,(HL) ; and we'll wait for CT2
|
|
LD A,(HL) ; either not expected at all or
|
|
CP D ; 12 hours
|
|
JR NZ,J0344
|
|
LD A,C
|
|
CP E
|
|
JR NZ,J0344
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
EI
|
|
RET
|
|
;
|
|
; sheet music for BEEP
|
|
;
|
|
QBEEP: DB 0D7H,'A','0',CR
|
|
N01U02: DB 0,0
|
|
;
|
|
; read time in the same format as TIMST
|
|
;
|
|
TIMRD:
|
|
PUSH HL
|
|
LD HL,MCTCC
|
|
LD (HL),10000000B ; CT2 mod 0 latch
|
|
DEC HL
|
|
DI
|
|
LD E,(HL)
|
|
LD D,(HL)
|
|
EI
|
|
LD A,E
|
|
OR D
|
|
JR Z,J0375 ; 0 hours is 12 hours
|
|
XOR A
|
|
LD HL,43200 ; we really have so much
|
|
SBC HL,DE
|
|
JR C,J037F ; it can't even happen
|
|
EX DE,HL ; if only someone
|
|
LD A,(AMPM) ; played with a quote
|
|
POP HL
|
|
RET
|
|
J0375: LD DE,43200
|
|
J0378: LD A,(AMPM)
|
|
XOR 1
|
|
POP HL
|
|
RET
|
|
J037F: DI ; someone played with him,
|
|
LD HL,MCTC2 ; that must be explained
|
|
LD A,(HL) ; the time is complemented
|
|
CPL
|
|
LD E,A
|
|
LD A,(HL)
|
|
CPL
|
|
LD D,A
|
|
EI
|
|
INC DE
|
|
JR J0378
|
|
;
|
|
; Standard interrupt handler routine
|
|
; activates once every 12 hours
|
|
; and switches the AMPM to the second state
|
|
;
|
|
; sets mod 0 to CT2
|
|
; CT2 = CT2 + 43200 - 2
|
|
;
|
|
@CLOCK: PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD HL,AMPM
|
|
LD A,(HL)
|
|
XOR 1 ; from morning to afternoon
|
|
LD (HL),A ; and from afternoon to morning
|
|
LD HL,MCTCC
|
|
LD (HL),10000000B ; CT2 mod 0 latch
|
|
DEC HL
|
|
PUSH HL
|
|
LD E,(HL) ; pull time
|
|
LD D,(HL)
|
|
LD HL,43200
|
|
ADD HL,DE ; + 12 hours
|
|
DEC HL ; there is some correction
|
|
DEC HL
|
|
EX DE,HL ; to DE
|
|
POP HL
|
|
LD (HL),E ; and stuff back
|
|
LD (HL),D
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
POP AF
|
|
EI
|
|
RET
|
|
;
|
|
; List of contents (HL) in the nun system, before the byte
|
|
; there will be a gap
|
|
;
|
|
; input: HL = address to memory
|
|
; output: A = (HL)
|
|
;
|
|
@MHEX:
|
|
CALL PRNTS
|
|
LD A,(HL)
|
|
CALL @BTHEX
|
|
LD A,(HL)
|
|
RET
|
|
;
|
|
; Listing HL in the nun system
|
|
;
|
|
; input: HL = number we want to list
|
|
; output: AF
|
|
;
|
|
@HEXHL:
|
|
LD A,H
|
|
CALL @BTHEX
|
|
LD A,L
|
|
JR @BTHEX
|
|
;
|
|
DB 0,0
|
|
;
|
|
; Output of content A in the colon system
|
|
;
|
|
; input: A = number we want to list
|
|
; output: AF
|
|
;
|
|
@BTHEX:
|
|
PUSH AF
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
CALL @ASC
|
|
CALL @PRNTC
|
|
POP AF
|
|
CALL @ASC
|
|
JP @PRNTC
|
|
;
|
|
; Table setting of 60 characters per line
|
|
;
|
|
QPRN1: DB 1,9,9,9,CR
|
|
;
|
|
; Convert the lower four bits of the A register
|
|
; to the hexadecimal digit
|
|
;
|
|
; input: A = lower four bits
|
|
; output: A = corresponding hexadecimal digit
|
|
; (in ASCII)
|
|
;
|
|
@ASC:
|
|
AND 0FH
|
|
CP 10
|
|
JR C,J03E2
|
|
ADD A,'A'-'0'-10
|
|
J03E2: ADD A,'0'
|
|
RET
|
|
;
|
|
; Converts a hexadecimal digit to
|
|
; four-bit value
|
|
;
|
|
; input: A = digits in ASCII
|
|
; output: CY = 0 and A = corresponding value
|
|
; CY = 1 cannot convert
|
|
; (in A the value is undefined)
|
|
;
|
|
HEX:
|
|
SUB '0'
|
|
RET C
|
|
CP 10
|
|
CCF
|
|
RET NC
|
|
SUB 'A'-'0'-10
|
|
CP 16
|
|
CCF
|
|
RET C
|
|
CP 10
|
|
RET
|
|
;
|
|
N02U04: DB 0,0,0,0
|
|
;
|
|
@HEX:
|
|
JR HEX
|
|
;
|
|
SPLAY: DB 7FH
|
|
DB " PLAY"
|
|
DB CR
|
|
SREC: DB 7FH
|
|
DB " RECORD."
|
|
DB CR
|
|
;
|
|
N03U04: DB 0,0,0,0
|
|
;
|
|
;
|
|
; It stores the value written in the noun in HL
|
|
; system as ASCII characters
|
|
;
|
|
; input: DE = string address
|
|
; output: CY = 0 and HL = corresponding value
|
|
; CY = 1 conversion cannot be performed
|
|
; (HL contains undefined state)
|
|
;
|
|
@HLHEX:
|
|
PUSH DE
|
|
CALL @2HEX
|
|
JR C,J041D
|
|
LD H,A
|
|
CALL @2HEX
|
|
JR C,J041D
|
|
LD L,A
|
|
J041D: POP DE
|
|
RET
|
|
;
|
|
;
|
|
; Converts 2 ASCII characters from a string
|
|
; to A as a number in the hexadecimal system
|
|
;
|
|
; input: DE = string address
|
|
; output: CY = 1 error, DE and A contains nedef. state
|
|
; CY = 0 and DE = DE + 1, A = number
|
|
;
|
|
@2HEX:
|
|
PUSH BC
|
|
LD A,(DE)
|
|
INC DE
|
|
CALL @HEX
|
|
JR C,J0434
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
LD C,A
|
|
LD A,(DE)
|
|
INC DE
|
|
CALL @HEX
|
|
JR C,J0434
|
|
OR C
|
|
J0434: POP BC
|
|
RET
|
|
;
|
|
; Oblast podprogramu pro praci s CMT
|
|
;
|
|
;
|
|
; Write the file header to CMT
|
|
;
|
|
; Output: CY = 1 an error has occurred
|
|
;
|
|
WHEAD:
|
|
DI
|
|
PUSH DE
|
|
PUSH BC
|
|
PUSH HL
|
|
LD D,CWRITE ; sign of the record
|
|
LD E,CHEAD ; header flag
|
|
LD HL,HEAD ; header storage address
|
|
LD BC,128 ; head length
|
|
J0444: CALL @CHECK
|
|
CALL @MGON
|
|
JR C,J0464 ; BREAK while waiting for CMT
|
|
LD A,E
|
|
CP CHEAD ; if a header is written
|
|
JR NZ,J045E ; listing WRITING filename
|
|
CALL @IFNL?
|
|
PUSH DE
|
|
LD DE,SWRITE
|
|
RST 18H
|
|
LD DE,FNAME
|
|
RST 18H
|
|
POP DE
|
|
J045E:
|
|
CALL @WTMRK
|
|
CALL @WBLOK
|
|
J0464:
|
|
JP CMTEND
|
|
;
|
|
SWRITE: DB "WRITING ", CR
|
|
QPRN2: DB 1,9,9,11,CR
|
|
;
|
|
; Write the program on CMT
|
|
;
|
|
; CY = 1 an error has occurred
|
|
;
|
|
WDATA:
|
|
DI
|
|
PUSH DE
|
|
PUSH BC
|
|
PUSH HL
|
|
LD D,CWRITE ; sign of the record
|
|
LD E,CDATA ; program flag
|
|
LD BC,(FSIZE) ; program length
|
|
LD HL,(BEGIN) ; the beginning of the program
|
|
LD A,B ; this information is taken
|
|
OR C ; from the file header
|
|
JR Z,POPX1 ; length = 0 =M POP and RET
|
|
JR J0444 ;
|
|
;
|
|
; Write a block of data to the CMT
|
|
; It assumes the tape recorder is turned on and saved
|
|
; TAPE MARK and the existence of a checksum
|
|
; at the standard MGCRC address
|
|
;
|
|
; input: HL = data block storage address
|
|
; BC = its length
|
|
; output: CY = 1 an error has occurred
|
|
;
|
|
@WBLOK:
|
|
PUSH DE
|
|
PUSH BC
|
|
PUSH HL ; all data is saved
|
|
LD D,2 ; on CMT twice
|
|
LD A,11111000B ; Key strobe for advice with BREAK
|
|
LD (MKBOUT),A
|
|
WBLOOP: LD A,(HL)
|
|
CALL @WBYTE
|
|
LD A,(MKBDIN) ; octeni keyboard
|
|
AND 10000001B ; test on BREAK
|
|
JP NZ,J04A5
|
|
LD A,2 ; if BREAK was detected
|
|
SCF ; set A = 2, CY = 1
|
|
JR POPX1 ; and POP and RET are performed
|
|
J04A5: INC HL
|
|
DEC BC
|
|
LD A,B ; and is stored until
|
|
OR C ; neni BC = 0
|
|
JP NZ,WBLOOP
|
|
LD HL,(MGCRC) ; read the control
|
|
LD A,H ; respect and its imposition
|
|
CALL @WBYTE ; and CMT
|
|
LD A,L
|
|
CALL @WBYTE
|
|
CALL @MG1 ; write last bit = 1
|
|
DEC D ; should I save one more time?
|
|
JP NZ,J04C2 ; Yes
|
|
OR A ; resets CY
|
|
JP POPX1 ; POP and RET
|
|
;
|
|
J04C2: LD B,0 ; will be saved again
|
|
J04C4: CALL @MG0 ; will send to CMT
|
|
DEC B ; 256 times zero
|
|
JP NZ,J04C4
|
|
POP HL ; the contents of the registry are restored
|
|
POP BC
|
|
PUSH BC
|
|
PUSH HL
|
|
JP WBLOOP ; and we're going for it again
|
|
;
|
|
POPX1: POP HL
|
|
POP BC
|
|
POP DE
|
|
RET
|
|
;
|
|
DB 0EH,0 ; someone forgot this here
|
|
;
|
|
; Read headers from CMT
|
|
;
|
|
; Output: CY = 1 an error has occurred
|
|
; A = 1 checksum error
|
|
; A = 2 detected BREAK
|
|
; CY = 0 OK
|
|
; (content A is undefined)
|
|
;
|
|
RHEAD:
|
|
DI
|
|
PUSH DE
|
|
PUSH BC
|
|
PUSH HL
|
|
LD D,CREAD ; reading flag
|
|
LD E,CHEAD ; header flag
|
|
LD BC,128 ; head length
|
|
LD HL,HEAD ; header storage address
|
|
J04E6: CALL @MGON
|
|
JP C,CMTBRK ; error
|
|
CALL @RTMRK
|
|
JP C,CMTBRK ; error
|
|
CALL @RBLOK
|
|
JP CMTEND
|
|
;
|
|
; Read the program from the CMT according to the information
|
|
; stored in the header
|
|
;
|
|
; output: CY with the meaning as for RHEAD
|
|
;
|
|
RDATA:
|
|
DI
|
|
PUSH DE
|
|
PUSH BC
|
|
PUSH HL
|
|
LD D,CREAD ; reading flag
|
|
LD E,CDATA ; program flag
|
|
LD BC,(FSIZE) ; program length
|
|
LD HL,(BEGIN) ; boot address
|
|
LD A,B ; if it is a length
|
|
OR C ; zero, so be it
|
|
JP Z,CMTEND ; does not record anything
|
|
JR J04E6
|
|
;
|
|
; Read a block of data from the CMT
|
|
;
|
|
; input: BC = data block length
|
|
; HL = storage address
|
|
; output: CY with the meaning as for RHEAD
|
|
;
|
|
@RBLOK:
|
|
PUSH DE
|
|
PUSH BC
|
|
PUSH HL
|
|
LD H,2 ; try to clean 2 blocks
|
|
J0513: LD BC,MKBDIN
|
|
LD DE,MPORTC
|
|
J0519: CALL W0TO1 ; wait for the edge
|
|
JR C,CMTBRK ; did not reach
|
|
CALL @D331 ; pocka and READ POINT
|
|
LD A,(DE) ; she made a sample
|
|
AND 00100000B ; is it zero?
|
|
JP Z,J0519 ; Yes
|
|
LD D,H
|
|
LD HL,0
|
|
LD (MGCRC),HL ; resets the CRC
|
|
POP HL ; restore registries
|
|
POP BC
|
|
PUSH BC
|
|
PUSH HL
|
|
J0532: CALL @RBYTE
|
|
JR C,CMTBRK ; error
|
|
LD (HL),A
|
|
INC HL
|
|
DEC BC
|
|
LD A,B ; until BC = 0
|
|
OR C ; so read
|
|
JR NZ,J0532
|
|
LD HL,(MGCRC)
|
|
CALL @RBYTE ; read the CRC
|
|
JR C,CMTBRK ; error
|
|
LD E,A
|
|
CALL @RBYTE
|
|
JR C,CMTBRK ; error
|
|
CP L
|
|
JR NZ,J0565 ; if the CRC does not agree
|
|
LD A,E ; so he jumps off
|
|
CP H
|
|
JR NZ,J0565
|
|
J0553: XOR A ; A = 0, CY = 0
|
|
;
|
|
; Here I jump all routines for CMT operation
|
|
; CMT is turned off here, enable interrupt if it is
|
|
; Enable interrupt enabled and perform nqvrat
|
|
;
|
|
CMTEND: POP HL
|
|
POP BC
|
|
POP DE
|
|
CALL @MGOFF ; turn off CMT
|
|
PUSH AF
|
|
LD A,(EIFLG)
|
|
CP NOKEY ; when music is on
|
|
JR NZ,J0563 ; so you are allowed to interrupt
|
|
EI
|
|
J0563: POP AF
|
|
RET
|
|
;
|
|
J0565: DEC D ; can i try to clean?
|
|
JR Z,J056E ; no -M
|
|
LD H,D ; Yes
|
|
CALL @RINTR ; skip the zero area
|
|
JR J0513 ; and I'm going for it again
|
|
;
|
|
J056E: LD A,1 ; checksum error
|
|
JR J0574
|
|
;
|
|
CMTBRK: LD A,2 ; detected BREAK
|
|
J0574: SCF
|
|
JR CMTEND
|
|
;
|
|
; Acoustic signal
|
|
;
|
|
; Nici: AF
|
|
;
|
|
BEEP:
|
|
PUSH DE
|
|
LD DE,QBEEP
|
|
RST 30H ; P=M CALL MELDY
|
|
POP DE
|
|
RET
|
|
;
|
|
; Click the cursor and test the KBD in the display code,
|
|
;
|
|
; output: A = read character
|
|
; Z = 1 ... key not pressed
|
|
;
|
|
@?KBDC:
|
|
CALL BLIKC
|
|
CALL @GETKD
|
|
CP NOKEY
|
|
RET
|
|
DB 0
|
|
;
|
|
; Just a trap program with facts in mind
|
|
;
|
|
; output: CY = 1 an error has occurred
|
|
; A = 1 checksum error
|
|
; A = 2 detected BREAK
|
|
; CY = 0 OK
|
|
; (content A is undefined)
|
|
;
|
|
VERIF:
|
|
DI
|
|
PUSH DE
|
|
PUSH BC
|
|
PUSH HL
|
|
LD BC,(FSIZE) ; program length
|
|
LD HL,(BEGIN) ; address of the beginning of the program
|
|
LD D,CREAD ; reading flag
|
|
LD E,CDATA ; program flag
|
|
LD A,B
|
|
OR C ; when the length is zero
|
|
JR Z,CMTEND ; so nothing happens
|
|
CALL @CHECK
|
|
CALL @MGON
|
|
JR C,CMTBRK ; error
|
|
CALL @RTMRK
|
|
JR C,CMTBRK ; error
|
|
CALL @VBLOK
|
|
JR CMTEND
|
|
;
|
|
; Verifies a block of data from the CMT
|
|
;
|
|
; Input: HL = data block address
|
|
; BC = length of the data
|
|
; Output: CY with the meaning of VERIF
|
|
;
|
|
@VBLOK:
|
|
PUSH DE
|
|
PUSH BC
|
|
PUSH HL
|
|
LD H,2
|
|
J05B2: LD BC,MKBDIN
|
|
LD DE,MPORTC
|
|
J05B8: CALL W0TO1 ; wait for the edge
|
|
JP C,CMTBRK ; did not reach
|
|
CALL @D331
|
|
LD A,(DE)
|
|
AND 00100000B
|
|
JP Z,J05B8 ; it is not a LONG bit
|
|
LD D,H
|
|
POP HL ; restore the registry
|
|
POP BC
|
|
PUSH BC
|
|
PUSH HL
|
|
J05CC: CALL @RBYTE ; read until BC = 0
|
|
JR C,CMTBRK ; error
|
|
CP (HL)
|
|
JR NZ,J056E ; error
|
|
INC HL
|
|
DEC BC
|
|
LD A,B
|
|
OR C
|
|
JR NZ,J05CC
|
|
LD HL,(MGCRCV)
|
|
CALL @RBYTE ; read checksum
|
|
CP H
|
|
JR NZ,J056E ; error
|
|
CALL @RBYTE
|
|
CP L
|
|
JR NZ,J056E ; error
|
|
DEC D ; I still have to check
|
|
JP Z,J0553 ; one block?
|
|
LD H,D ; Yes
|
|
JR J05B2 ; I'm on it
|
|
;
|
|
; Turns off the cursor
|
|
; character (AKCHAR) da at the cursor position, it was there
|
|
; hidden by the @CURON subroutine
|
|
;
|
|
; output: HL = cursor address
|
|
;
|
|
@CUROF:
|
|
PUSH AF
|
|
LD A,(AKCHAR)
|
|
CALL @?POINT
|
|
LD (HL),A
|
|
POP AF
|
|
RET
|
|
;
|
|
; Prints the HL address on a new CRT line
|
|
;
|
|
; input: HL = displayed word
|
|
; output: AF
|
|
;
|
|
@?NLHL:
|
|
CALL @IFNL?
|
|
CALL @HEXHL
|
|
RET
|
|
;
|
|
; Waiting for the leading edge of the signal from the CMT
|
|
;
|
|
; input: BC =M KBDIN
|
|
; DE =M PORTC
|
|
; output: CY = 0 reached
|
|
; CY = 1 was BREAK
|
|
; output: AF
|
|
;
|
|
W0TO1:
|
|
LD A,11111000B ; strobe keyboard
|
|
LD (MKBOUT),A
|
|
NOP ; they forgot something here again
|
|
J0607: LD A,(BC)
|
|
AND 10000001B ; is a break?
|
|
JR NZ,J060E ; No
|
|
SCF ; Yes
|
|
RET
|
|
;
|
|
J060E: LD A,(DE) ; we are waiting for zero from CMT
|
|
AND 00100000B
|
|
JR NZ,J0607
|
|
J0613: LD A,(BC) ; when we got there
|
|
AND 10000001B ; so we will test BREAK
|
|
JR NZ,J061A ; and let's go
|
|
SCF ; was BREAK
|
|
RET
|
|
;
|
|
J061A: LD A,(DE) ; we are waiting for one
|
|
AND 00100000B
|
|
JR Z,J0613 ; and we test it
|
|
RET ; BREAK
|
|
;
|
|
DB 0,0,0,0
|
|
;
|
|
; Read the apartment from CMT
|
|
;
|
|
; Output: CY = 0 and A contains the read byte
|
|
; CY = 1 was detected by BREAK
|
|
; (content A is not defined)
|
|
;
|
|
@RBYTE:
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD HL,8*256+0 ; in H is the number of bits in the byte
|
|
LD BC,MKBDIN ; preparation of values
|
|
LD DE,MPORTC ; for W0TO1
|
|
J0630: CALL W0TO1
|
|
JP C,J0654 ; error, POP and RET
|
|
CALL @D331 ; waiting for READ POINT
|
|
LD A,(DE)
|
|
AND 00100000B ; sampled
|
|
JP Z,J0649 ; for zero it is skipped
|
|
PUSH HL ; checksum
|
|
LD HL,(MGCRC)
|
|
INC HL
|
|
LD (MGCRC),HL
|
|
POP HL
|
|
SCF
|
|
J0649: LD A,L ; stores the value in L
|
|
RLA ; read bit
|
|
LD L,A
|
|
DEC H ; has it been 8 bits?
|
|
JP NZ,J0630 ; No
|
|
CALL W0TO1 ; if so, wait
|
|
LD A,L ; to the leading edge of another
|
|
J0654: POP HL ; signal, save the read
|
|
POP DE ; value to the A register
|
|
POP BC ; and end up
|
|
RET
|
|
;
|
|
DB 0,0,0
|
|
;
|
|
; Skip loading tons
|
|
; and pocka on TAPE MARK
|
|
;
|
|
; Input: E = 0CCH as header flag
|
|
; or E = anything other than
|
|
; program flag
|
|
;
|
|
; Output: CY = 1 detected BREAK
|
|
; CY = 0 OK
|
|
; Nici: AF
|
|
;
|
|
@RTMRK:
|
|
CALL @RINTR ; skip bootloader
|
|
PUSH BC ; tone
|
|
PUSH DE
|
|
PUSH HL
|
|
LD HL,40*256+40
|
|
LD A,E ; produce to H and L
|
|
CP CHEAD ; lengths LONG and SHORT
|
|
JR Z,J066C ; areas in TAPE MARK
|
|
LD HL,20*256+20 ; according to the symptom of E
|
|
J066C: LD (TMLONG),HL ; and hide them
|
|
LD BC,MKBDIN ; initializes values
|
|
LD DE,MPORTC ; for W0TO1
|
|
J0675: LD HL,(TMLONG) ; restores the length of TAPE MARK
|
|
J0678: CALL W0TO1
|
|
JR C,POPX2 ; error
|
|
CALL @D331 ; pocka to READ POINT
|
|
LD A,(DE)
|
|
AND 00100000B ; is sampled
|
|
JR Z,J0675 ; it's zero and now it's waiting
|
|
DEC H ; to ones =M again
|
|
JR NZ,J0678 ; can continue
|
|
J0688: CALL W0TO1 ; and now he will wait
|
|
JR C,POPX2 ; to block zero
|
|
CALL @D331
|
|
LD A,(DE)
|
|
AND 00100000B
|
|
JR NZ,J0675 ; the one read
|
|
DEC L
|
|
JR NZ,J0688
|
|
CALL W0TO1 ; wait for the leading edge
|
|
POPX2: POP HL ; the following signal
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
;
|
|
; Turn on the tape recorder
|
|
;
|
|
; input: D = D2 as read flag
|
|
; or anything else
|
|
; as a sign of writing
|
|
; output: CY = 1 BREAK detected
|
|
; CY = 0 OK
|
|
;
|
|
@MGON:
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD B,10 ; number of power-up attempts
|
|
J06A4: LD A,(MPORTC)
|
|
AND 00010000B ; is it going
|
|
JR Z,J06B9 ; No
|
|
J06AB: LD B,255 ; if so then take a moment
|
|
J06AD: CALL @D7000 ; pocka na motor
|
|
JR J06B4 ; about 1.8 secondsQ
|
|
;
|
|
JR @MGON ; they forgot something here, IT'S NOWQ
|
|
;
|
|
J06B4: DJNZ J06AD
|
|
XOR A
|
|
J06B7: JR POPX2 ; and we're leaving
|
|
;
|
|
J06B9: LD A,00000110B ; this sequence instruction
|
|
LD HL,MCWR55 ; after the signal
|
|
LD (HL),A ; ENGINE edge that would
|
|
INC A ; she should have run it if
|
|
LD (HL),A ; the drive is on
|
|
DJNZ J06A4
|
|
CALL @IFNL? ; it failed at ten
|
|
LD A,D ; experiment and so it is written
|
|
CP CWRITE ; prompt 'RECORD.PLAY'
|
|
JR Z,J06D0 ; respectively 'PLAY'
|
|
LD DE,SPLAY
|
|
JR J06D7
|
|
J06D0: LD DE,SREC
|
|
RST 18H
|
|
LD DE,3FDH
|
|
J06D7: RST 18H
|
|
J06D8: LD A,(MPORTC) ; and will wait for
|
|
AND 10H ; until the CMT user turns on
|
|
JR NZ,J06AB ; he succeeded
|
|
CALL BRKEY ; BREAK?
|
|
JR NZ,J06D8 ; no, wait
|
|
SCF ; Yes
|
|
JR J06B7 ; balime to
|
|
;
|
|
SMON7: DB "** MONITOR 1Z-013B **"
|
|
DB CR
|
|
;
|
|
DB 0
|
|
;
|
|
; Turns off CMT
|
|
;
|
|
; Protects all registries
|
|
;
|
|
@MGOFF:
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
LD B,10 ; number of attempts
|
|
J0705: LD A,(MPORTC)
|
|
AND 00010000B ; has he stopped yet?
|
|
JR Z,J0717 ; yes, we are
|
|
LD A,00000110B ; No, we're sending him
|
|
LD (MCWR55),A ; food
|
|
INC A
|
|
LD (MCWR55),A ; and when it doesn't work either
|
|
DJNZ J0705 ; tenth attempt, so
|
|
J0717: JP J0EE6 ; it will be left flat
|
|
;
|
|
; Counts the checksum of the data block
|
|
; and save it to the default addresses
|
|
; MGCRC and MGCRCV
|
|
;
|
|
; input: HL = data block address
|
|
; BC = its length
|
|
;
|
|
@CHECK:
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD DE,0 ; at the beginning is a control
|
|
J0720: LD A,B ; the sum is equal to zero
|
|
OR C ; are we done yet?
|
|
JR NZ,J072F ; not yet, it's time to work
|
|
EX DE,HL
|
|
LD (MGCRC),HL ; so let's save it
|
|
LD (MGCRCV),HL ; and we will return
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
J072F: LD A,(HL) ; this is where the CRC of the apartment took place
|
|
PUSH BC
|
|
LD B,8 ; number of bits in the apartment
|
|
J0733: RLCA
|
|
JR NC,J0737
|
|
INC DE ; added
|
|
J0737: DJNZ J0733 ; I'll finish it for the apartment
|
|
POP BC
|
|
INC HL ; edit addresses
|
|
DEC BC ; and I'm going for it again
|
|
JR J0720
|
|
;
|
|
; Initialization routine
|
|
;
|
|
; sets I8255 to mode 0
|
|
; And, Cl as an exit
|
|
; B, Ch as input
|
|
; sends an edge to the MOTOR signal
|
|
; so turn it on if
|
|
; was turned off and vice versa
|
|
; allows periodic interrupts
|
|
; from timer I8253
|
|
;
|
|
; output: HL
|
|
;
|
|
@INI55:
|
|
LD HL,MCWR55
|
|
LD (HL),10001010B ; mode 8255
|
|
LD (HL),00000111B ; switch CMT
|
|
LD (HL),00000101B ; allow interupt
|
|
RET
|
|
;
|
|
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
;
|
|
; Delay approx. 111 microseconds
|
|
;
|
|
; output: AF
|
|
;
|
|
@D111:
|
|
LD A,27
|
|
J075B: DEC A
|
|
JP NZ,J075B
|
|
RET
|
|
;
|
|
; Delay about 103 microseconds
|
|
;
|
|
; output: AF
|
|
;
|
|
@D103:
|
|
LD A,25
|
|
J0762: DEC A
|
|
JP NZ,J0762
|
|
RET
|
|
;
|
|
; Writes a byte from the A register to the CMT
|
|
;
|
|
; output: AF
|
|
;
|
|
@WBYTE:
|
|
PUSH BC
|
|
LD B,8 ; number of bits in the apartment
|
|
CALL @MG1 ; start / stop bit
|
|
J076D: RLCA
|
|
CALL C,@MG1
|
|
CALL NC,@MG0
|
|
DEC B
|
|
JP NZ,J076D
|
|
POP BC
|
|
RET
|
|
;
|
|
; Writes the boot signal and TAPE MARK
|
|
;
|
|
; input: E = 0CCH as header flag, or
|
|
; any value, as a program flag
|
|
; output: AF
|
|
;
|
|
@WTMRK:
|
|
PUSH BC
|
|
PUSH DE
|
|
LD A,E
|
|
LD BC,22000
|
|
LD DE,40*256+40
|
|
CP CHEAD ; according to the symptom
|
|
JP Z,J078E ; you set up
|
|
LD BC,11000 ; parameters
|
|
LD DE,20*256+20
|
|
J078E: CALL @MG0 ; writes BC times zero
|
|
DEC BC
|
|
LD A,B
|
|
OR C
|
|
JR NZ,J078E
|
|
J0796: CALL @MG1 ; writes D times to one
|
|
DEC D
|
|
JR NZ,J0796
|
|
J079C: CALL @MG0 ; writes E times a unit
|
|
DEC E
|
|
JR NZ,J079C
|
|
CALL @MG1
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
;
|
|
; Execute part of the MODIFY display
|
|
;
|
|
FMODIF:
|
|
CALL FHLHEX ; entered address
|
|
FMOD1:
|
|
CALL @?NLHL ; write it on a new line
|
|
CALL @MHEX ; and a flat on it with a space
|
|
CALL PRNTS
|
|
CALL FGETL ; honor string character
|
|
CALL @HLHEX ; and immediately get a HEXA number from it
|
|
JR C,J07D7 ; that should be our address
|
|
CALL @IC4DE
|
|
INC DE
|
|
CALL @2HEX ; and this is old content
|
|
JR C,FMOD1 ; it was not a hexadecimal number
|
|
CP (HL) ;
|
|
JR NZ,FMOD1 ; the old contents do not fit
|
|
INC DE
|
|
LD A,(DE)
|
|
CP CR
|
|
JR Z,J07D4 ; only CR pressed
|
|
CALL @2HEX ; new content
|
|
JR C,FMOD1 ; incorrect entry
|
|
LD (HL),A ; modify in memory
|
|
J07D4: INC HL ; next byte
|
|
JR FMOD1 ; and again
|
|
J07D7: LD H,B
|
|
LD L,C
|
|
JR FMOD1
|
|
;
|
|
QT????: DB 'N','K',CR,';',CR,';',CR,';',' ',' ',' '
|
|
;
|
|
;
|
|
; Reads the character string from the keyboard.
|
|
; When reading a character, it stores it in VRAM, it is possible
|
|
; use all allowable editing commands
|
|
; (arrows, tab, inst, del, clr, home, etc.)
|
|
; Enter the string at the end by pressing CR, then read, working
|
|
; 40 or 80 character line (depending on the line attribute)
|
|
; to the input buffer, the rest of the line to 40 or 80
|
|
; is filled with the constant CR.
|
|
;
|
|
; AttentionQ The subroutine saves the line from the beginning,
|
|
; namely the one on which CR was pressed, at the beginning
|
|
; the cursor position does not matter at allQ
|
|
;
|
|
; input: DE = I / O buffer address
|
|
;
|
|
GETL: PUSH AF
|
|
PUSH BC
|
|
PUSH HL
|
|
PUSH DE
|
|
GETLOP: CALL @??KEY ; flash the cursor and honor KBD
|
|
PUSH AF
|
|
LD B,A
|
|
LD A,(BPFLG)
|
|
RRCA
|
|
CALL NC,BEEP ; pipni, when you have
|
|
LD A,B
|
|
LD HL,CONMOD ; NO ONE SETTINGS
|
|
AND NOKEY ; DOES NOT NEED
|
|
CP 0C0H ; driving sign?
|
|
POP DE
|
|
LD A,B
|
|
JR NZ,J0818 ; no, send
|
|
CP 0CDH
|
|
JR Z,J085B ; CR came, finally the end
|
|
CP 0CBH
|
|
JP Z,J0822 ; BREAK
|
|
CP 0CFH
|
|
JR Z,J0818 ; CF is always written (PROC?)
|
|
CP 0C7H
|
|
JR NC,J081D ; larger than C6 is controlled
|
|
RR E ; A NENSI SNAD NE ?Q
|
|
LD A,B
|
|
JR NC,J081D
|
|
J0818: CALL @AVRAM ; character to VRAM
|
|
JR GETLOP
|
|
J081D: CALL @?DPCT ; management
|
|
JR GETLOP
|
|
J0822: POP HL ; BREAK at GETL
|
|
PUSH HL
|
|
LD (HL),ESC
|
|
INC HL
|
|
LD (HL),CR
|
|
JR J087E ; new line, POP and RET
|
|
J082B: RRCA
|
|
JR NC,J0865 ; the starting point of the line
|
|
JR J0863 ; continued to reach the line
|
|
;
|
|
; Wait 7 milliseconds and honor the keyboard via KBDIN
|
|
;
|
|
@WGKEY:
|
|
CALL @D7000
|
|
CALL @KBDIN
|
|
RET
|
|
;
|
|
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
;
|
|
J085B:
|
|
CALL @ATBLN
|
|
LD B,40 ; 40 characters per line
|
|
JR NC,J082B ; the starting point is line
|
|
DEC H ; o line vys
|
|
J0863: LD B,80 ; 80 characters per line
|
|
J0865: LD L,0
|
|
CALL @?ACUR ; decode the address from the position
|
|
POP DE ; address I / O buf
|
|
PUSH DE
|
|
J086C: LD A,(HL) ; we transfer characters to the I / O buffer
|
|
CALL @?DACN
|
|
LD (DE),A
|
|
INC HL
|
|
INC DE
|
|
DJNZ J086C
|
|
EX DE,HL
|
|
J0876: LD (HL),CR ; the spaces at the end will replace CR
|
|
DEC HL
|
|
LD A,(HL)
|
|
CP SPACE
|
|
JR Z,J0876
|
|
J087E: CALL LETNL ; new line and end of GETL
|
|
POP DE
|
|
POP HL
|
|
POP BC
|
|
POP AF
|
|
RET
|
|
;
|
|
N07U14: DB 0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
;
|
|
; Send the character string to the CRT terminated CR
|
|
; control characters (C0-CF)
|
|
;
|
|
; input: DE = string address
|
|
;
|
|
MSG:
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
MSGLOP:
|
|
LD A,(DE) ; character from the buffer
|
|
CP CR ; is it CR?
|
|
JR Z,J08A7 ; it's CR
|
|
CALL PRNTC ; it's not CR
|
|
INC DE ; to the next sign
|
|
JR MSGLOP ; and again
|
|
;
|
|
; Send the character string to the CRT, terminated CR
|
|
; control characters are converted to display code
|
|
; and save to VRAM
|
|
;
|
|
; input: DE = string address
|
|
;
|
|
RST18:
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
J08A4: LD A,(DE)
|
|
CP CR
|
|
J08A7: JP Z,J0EE6 ; POP and RET
|
|
CALL @?ADCN
|
|
CALL @PRNTA
|
|
INC DE
|
|
JR J08A4
|
|
;
|
|
J08B3: LD DE,QKBDS ; close to GETKD
|
|
JR J08FA
|
|
;
|
|
J08B8: LD A,0CBH
|
|
OR A
|
|
JR J08D6
|
|
;
|
|
; Returns the code of the just pressed key in ASCII code,
|
|
; if no was pressed, it returns 0
|
|
; (call GETKD and then? DACN)
|
|
;
|
|
; output: key in "ASCII" code
|
|
;
|
|
GETKY:
|
|
CALL @GETKD
|
|
SUB NOKEY
|
|
RET Z
|
|
ADD A,NOKEY
|
|
JP @?DACN
|
|
;
|
|
DB 0,0
|
|
;
|
|
; Returns the currently pressed key in the display code to A reg.
|
|
; (this routine has a delay of 7 millisecondsQ)
|
|
;
|
|
; SHIFT + BREAK = CD
|
|
; rear key = F0
|
|
; common key = code from tablesQ KBD ..
|
|
;
|
|
; mod SHIFT CTRL table
|
|
;
|
|
; ALPHA no no KBD base table
|
|
; ALPHA yes - KBDS shifted charactersQ
|
|
; --- no yesQ KBDC control characters
|
|
; GRAPH no noQ KBDG graphics
|
|
; GRAPH yes -Q KBDGS shifted graphic characters
|
|
;
|
|
@GETKD:
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
CALL @WGKEY ; key pressed
|
|
LD A,B ; "shift" keys
|
|
RLCA ; the key was pressed
|
|
JR C,J08DA ; Yes
|
|
LD A,NOKEY ; no, it returns code
|
|
J08D6: POP HL ; rear keys
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
; something pressed
|
|
J08DA: LD DE,QKBD
|
|
LD A,B
|
|
CP 88H ; was it a break?
|
|
JR Z,J08B8 ; Yes
|
|
LD H,0
|
|
LD L,C
|
|
BIT 5,A
|
|
JR NZ,J08F7 ; driving sign
|
|
LD A,(CONMOD)
|
|
RRCA
|
|
JP C,J08FE ; graphically mod + shift
|
|
LD A,B
|
|
RLA
|
|
RLA
|
|
JR C,J08B3 ; shift
|
|
JR J08FA ; ordinary character
|
|
J08F7: LD DE,QKBDC
|
|
J08FA: ADD HL,DE ; index the table
|
|
J08FB: LD A,(HL) ; sign here
|
|
JR J08D6 ; and the end
|
|
J08FE: BIT 6,B
|
|
JR Z,J0909
|
|
LD DE,QKBDGS
|
|
ADD HL,DE
|
|
SCF
|
|
JR J08FB
|
|
J0909: LD DE,QKBDG
|
|
JR J08FA
|
|
;
|
|
; New line on CRT
|
|
; no AF
|
|
;
|
|
LETNL:
|
|
XOR A
|
|
LD (CSRH),A
|
|
LD A,CRD
|
|
JR J0959
|
|
;
|
|
DB 0,0
|
|
;
|
|
; New line on CRT, if CSRH PM 0,
|
|
; i.e. if the cursor is not on the edge of the line
|
|
;
|
|
IFNL?:
|
|
LD A,(CSRH) ; logical cursor position
|
|
OR A
|
|
RET Z ; we are at the beginning of the line
|
|
JR LETNL ; business CR
|
|
;
|
|
DB 0
|
|
;
|
|
;
|
|
; Mezara on display
|
|
; no AF
|
|
;
|
|
PRNTS:
|
|
LD A,SPACE
|
|
JR PRNTC
|
|
;
|
|
; Tab on CRT, then NULL
|
|
; tabs by 10 characters
|
|
;
|
|
; no AF
|
|
;
|
|
TAB:
|
|
CALL @PRNTS
|
|
LD A,(CSRH)
|
|
OR A
|
|
RET Z ; at the beginning of the line
|
|
J092C: SUB 10 ; module 10 = 0?
|
|
JR C,TAB ; Yes
|
|
JR NZ,J092C ; no, another space
|
|
NOP
|
|
NOP
|
|
NOP
|
|
;
|
|
; Character output to CRT
|
|
; (via PRNTA or? DPCT)
|
|
;
|
|
; input: A = output character
|
|
; output: AF
|
|
;
|
|
PRNTC:
|
|
CP CR
|
|
JR Z,LETNL ; CR is done differently
|
|
PUSH BC
|
|
LD C,A
|
|
LD B,A
|
|
CALL FPRNTC ; own routine
|
|
LD A,B
|
|
POP BC
|
|
RET
|
|
;
|
|
MSGOK: DB "OK!"
|
|
DB CR
|
|
;
|
|
; PRNTC without registry hiding
|
|
;
|
|
FPRNTC: LD A,C
|
|
CALL @?ADCN ; to display
|
|
LD C,A
|
|
CP NOKEY
|
|
RET Z ; it's nothing
|
|
AND NOKEY
|
|
CP 0C0H ; rizeni?
|
|
LD A,C
|
|
JR NZ,@PRNTA ; No
|
|
CP 0C7H ; really driving?
|
|
JR NC,@PRNTA ; No
|
|
J0959: CALL @?DPCT ; it's driving
|
|
CP 0C3H ; C right?
|
|
JR Z,@ICSRH
|
|
CP 0C5H ; home?
|
|
JR Z,J0967
|
|
CP 0C6H ; clear?
|
|
RET NZ
|
|
J0967: XOR A ; at clear a home
|
|
J0968: LD (CSRH),A
|
|
RET
|
|
;
|
|
; Character from A in the display code directly to VRAM and
|
|
; move CSRH
|
|
;
|
|
; input: A = character in the display code
|
|
; output: AF
|
|
;
|
|
@PRNTA:
|
|
CALL @AVRAM
|
|
@ICSRH:
|
|
LD A,(CSRH) ; CSRH increment
|
|
INC A
|
|
CP 50H
|
|
JR C,J0968
|
|
SUB 50H
|
|
JR J0968
|
|
;
|
|
J097B: LD A,(AKCHAR) ; piece from BLIKC
|
|
JR J09EF
|
|
;
|
|
J0980: BIT 5,A ; it's a piece of BRKEY
|
|
JR Z,J0986
|
|
OR A ; common characters
|
|
RET
|
|
J0986: LD A,20H ; CTRL
|
|
OR A
|
|
SCF
|
|
RET
|
|
;
|
|
SFNAME: DB "FILENAME? "
|
|
DB CR
|
|
;
|
|
; Delay approx. 7 milliseconds
|
|
;
|
|
; output: AF
|
|
;
|
|
@D7000:
|
|
PUSH BC
|
|
LD B,21
|
|
J0999: CALL @D331
|
|
DJNZ J0999
|
|
POP BC
|
|
RET
|
|
;
|
|
SLOAD: DB "LOADING "
|
|
DB CR
|
|
;
|
|
; Delay approx. 459 microseconds
|
|
;
|
|
; output: AF
|
|
;
|
|
@D459:
|
|
LD A,73H
|
|
J09AB: DEC A
|
|
JP NZ,J09AB
|
|
RET
|
|
;
|
|
DB 0,0,0
|
|
;
|
|
;
|
|
; Flash with the cursor and wait for the keyboard
|
|
;
|
|
@??KEY:
|
|
PUSH HL
|
|
CALL @CURON ; deploy cursor
|
|
J09B7: CALL @?KBDC ; wait for the keyboard to release
|
|
JR NZ,J09B7
|
|
J09BC: CALL @?KBDC ; wait for the key to be pressed
|
|
JR Z,J09BC
|
|
LD H,A ; keys in the display
|
|
CALL @D7000
|
|
CALL @GETKD ; after 7 ms again
|
|
PUSH AF
|
|
CP H
|
|
POP HL
|
|
JR NZ,J09BC ; it's not the same, the key oscillates
|
|
PUSH HL
|
|
POP AF
|
|
CALL @CUROF ; remove cursor
|
|
POP HL
|
|
RET
|
|
;
|
|
; Fill 2 kB of memory with zero
|
|
;
|
|
@FILL0:
|
|
XOR A
|
|
;
|
|
; Fill 2 kB of memory with a constant from A
|
|
;
|
|
; input: HL = memory full address
|
|
; output: HL = HL + 800h
|
|
; BC = 0
|
|
; A = 0
|
|
;
|
|
@FILLA:
|
|
LD BC,800H
|
|
PUSH DE
|
|
LD D,A
|
|
J09DA: LD (HL),D
|
|
INC HL
|
|
DEC BC
|
|
LD A,B
|
|
OR C
|
|
JR NZ,J09DA
|
|
POP DE
|
|
RET
|
|
;
|
|
; Flashes with the cursor according to the 6th bit of C port 8255
|
|
; (there is a cursor flicker frequency)
|
|
;
|
|
; Save to VRAM at the cursor position
|
|
; (CURCH) if 6.bit C was equal to one
|
|
; (AKCHAR) ------ "----- zero
|
|
;
|
|
@BLIKC:
|
|
PUSH AF
|
|
PUSH HL
|
|
LD A,(MPORTC) ; cursor bit
|
|
RLCA
|
|
RLCA
|
|
JR C,J097B ; save the normal character
|
|
LD A,(CURCH) ; save the cursor character
|
|
J09EF: CALL @?POINT
|
|
LD (HL),A
|
|
POP HL
|
|
POP AF
|
|
RET
|
|
;
|
|
DB 0,0,0,0,0,0,0,0,0
|
|
;
|
|
BLIKC:
|
|
JR @BLIKC
|
|
;
|
|
; Enroll in CMT: record "SHORT",
|
|
; which represents the value 0
|
|
;
|
|
; HIGH ------- ---
|
|
; Q Q Q
|
|
; LOW --- --------
|
|
; ^ ^ ^ ^
|
|
; 0 240 ^ 278 + 240
|
|
; ^ (data is in microseconds)
|
|
; READ POINT: 379
|
|
;
|
|
@MG0:
|
|
PUSH AF
|
|
LD A,00000011B ; high on CMT
|
|
LD (MCWR55),A
|
|
CALL @D111
|
|
CALL @D111
|
|
LD A,00000010B ; low on CMT
|
|
LD (MCWR55),A
|
|
CALL @D111
|
|
CALL @D111
|
|
POP AF
|
|
RET
|
|
;
|
|
; Enroll in CMT: entry "LONG",
|
|
; which represents the value 1
|
|
;
|
|
;
|
|
; HIGH ------------- ---
|
|
; Q ^Q Q
|
|
; LOW --- ^ --------------
|
|
; ^ ^ ^ ^
|
|
; 0 ^ 470 494 + 470
|
|
; ^ (data is in microseconds)
|
|
; READ POINT: 379
|
|
;
|
|
@MG1:
|
|
PUSH AF
|
|
LD A,00000011B ; high on CMT
|
|
LD (MCWR55),A
|
|
CALL @D459
|
|
LD A,00000010B ; low on CMT
|
|
LD (MCWR55),A
|
|
CALL @D459
|
|
POP AF
|
|
RET
|
|
;
|
|
DB 0,0,0,0,0
|
|
;
|
|
; Tests the state of the SHIFT, CTRL, and BREAK keys
|
|
;
|
|
; output: A = see following table
|
|
; Z = 1 ... SHIFT + BREAK
|
|
; CY = 1 ... SHIFT or CTRL
|
|
;
|
|
;
|
|
; CTRL SHIFT BREAK CY ZA
|
|
; yes no - 1 0 20H control characters
|
|
; no no no 0 0 7FH common characters
|
|
; no no yes 0 0 3FH ESC
|
|
; - yes no 1 0 40H shift characters
|
|
; - yes yes 0 1 0 SHIFT + BREAK
|
|
;
|
|
BRKEY:
|
|
LD A,11111000B
|
|
LD (MKBOUT),A ; key strobe
|
|
NOP
|
|
LD A,(MKBDIN) ; key input
|
|
OR A
|
|
RRA ; shift bit to CY
|
|
JP C,J0980 ; there was no shift
|
|
RLA
|
|
RLA ; break bit to CY
|
|
JR NC,J0A48 ; it was a break
|
|
LD A,40H ; return code shift
|
|
SCF
|
|
RET
|
|
J0A48: XOR A ; SHIFT + BREAK
|
|
RET
|
|
;
|
|
; Delay approx. 331 milliseconds
|
|
;
|
|
; output: AF
|
|
;
|
|
@D331:
|
|
LD A,82
|
|
JP J0762
|
|
;
|
|
DB 0
|
|
;
|
|
; Returns the hardware code of the currently pressed key
|
|
;
|
|
; output: B = code of the "shift" keys, see the following
|
|
; table.
|
|
; if the key is pressed, it is set
|
|
; 7 bit B register
|
|
;
|
|
; C = key code
|
|
; LINE * 8 + 7-COLUMN
|
|
; LINE and COLUMN are determined from the table
|
|
; physical connection of the keyboard.
|
|
; The subroutine does not test the last column (F1-F5),
|
|
; the penultimate column only affects the B register
|
|
; If the key has not been pressed, it is not
|
|
; C register changed.
|
|
;
|
|
; CTRL SHIFT BREAK BC
|
|
;
|
|
; - yes yes 88H unchanged
|
|
; yes no - 20H key code
|
|
; - yes no 40H "
|
|
; no no no 0H "
|
|
;
|
|
;
|
|
; 0 1 2 3 4 5 6 7 8 9
|
|
; + ------------------------------------------------- - +
|
|
; Q Q
|
|
; 7Q blank YQIA 1 \ inst break F1Q
|
|
; Q Q
|
|
; 6Q graph ZRJB 2 ^ del ctrl F2Q
|
|
; Q Q
|
|
; 5Q pound @ SKC 3 - right F3Q
|
|
; Q Q
|
|
; 4Q alpha FTLD 4 sp down F4Q
|
|
; Q Q
|
|
; 3Q tab] UME 5 O left F5Q
|
|
; Q Q
|
|
; 2Q ; VNF 6 9 upQ
|
|
; Q Q
|
|
; 1Q : WOG 7,? Q
|
|
; Q Q
|
|
; 0Q cr XPH 8. / shiftQ
|
|
; Q Q
|
|
; + ------------------------------------------------- - +
|
|
;
|
|
@KBDIN:
|
|
PUSH DE
|
|
PUSH HL
|
|
XOR A
|
|
LD B,11111000B ; this will start strobing
|
|
LD D,A ; 0 -M D
|
|
CALL BRKEY
|
|
JR NZ,J0A5F ; there was no break
|
|
LD D,88H ; code break
|
|
JR J0A73 ; POP and RET
|
|
J0A5F: JR NC,KBDTST ; unhifted
|
|
LD D,A ; shifted, hide
|
|
JR KBDTST ; and let's go
|
|
J0A64: SET 7,D ; a sign that she was a keyboard
|
|
KBDTST: DEC B ; next column tested
|
|
LD A,B
|
|
LD (MKBOUT),A
|
|
CP 0EFH ; koncime?
|
|
JR NZ,J0A77 ; No
|
|
CP 0F8H ; NONSENSE Q THIS CONDITION
|
|
JR Z,KBDTST ; IT WILL NEVER BE FULFILLED
|
|
J0A73: LD B,D
|
|
POP HL
|
|
POP DE
|
|
RET
|
|
J0A77: LD A,(MKBDIN)
|
|
CPL
|
|
OR A ; is there something in that column?
|
|
JR Z,KBDTST ; it does not look like that,
|
|
LD E,A ; we will still need it
|
|
LD H,8
|
|
LD A,B
|
|
AND 00001111B
|
|
RLCA ; multiply 8
|
|
RLCA
|
|
RLCA
|
|
LD C,A
|
|
LD A,E
|
|
J0A89: DEC H ; we are looking for the right bit
|
|
RRCA
|
|
JR NC,J0A89
|
|
LD A,H
|
|
ADD A,C
|
|
LD C,A
|
|
JR J0A64 ; POP and RET
|
|
;
|
|
; "ASCII to display" conversion table
|
|
;
|
|
QADCN:
|
|
DB NOKEY,NOKEY,NOKEY,0F3H,NOKEY,0F5H,NOKEY,NOKEY
|
|
DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY
|
|
DB NOKEY,0C1H,0C2H,0C3H,0C4H,0C5H,0C6H,NOKEY
|
|
DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY
|
|
DB 000H,061H,062H,063H,064H,065H,066H,067H
|
|
DB 068H,069H,06BH,06AH,02FH,02AH,02EH,02DH
|
|
DB 020H,021H,022H,023H,024H,025H,026H,027H
|
|
DB 028H,029H,04FH,02CH,051H,02BH,057H,049H
|
|
DB 055H,001H,002H,003H,004H,005H,006H,007H
|
|
DB 008H,009H,00AH,00BH,00CH,00DH,00EH,00FH
|
|
DB 010H,011H,012H,013H,014H,015H,016H,017H
|
|
DB 018H,019H,01AH,052H,059H,054H,050H,045H
|
|
DB 0C7H,0C8H,0C9H,0CAH,0CBH,0CCH,0CDH,0CEH
|
|
DB 0CFH,0DFH,0E7H,0E8H,0E5H,0E9H,0ECH,0EDH
|
|
DB 0D0H,0D1H,0D2H,0D3H,0D4H,0D5H,0D6H,0D7H
|
|
DB 0D8H,0D9H,0DAH,0DBH,0DCH,0DDH,0DEH,0C0H
|
|
DB 080H,0BDH,09DH,0B1H,0B5H,0B9H,0B4H,09EH
|
|
DB 0B2H,0B6H,0BAH,0BEH,09FH,0B3H,0B7H,0BBH
|
|
DB 0BFH,0A3H,085H,0A4H,0A5H,0A6H,094H,087H
|
|
DB 088H,09CH,082H,098H,084H,092H,090H,083H
|
|
DB 091H,081H,09AH,097H,093H,095H,089H,0A1H
|
|
DB 0AFH,08BH,086H,096H,0A2H,0ABH,0AAH,08AH
|
|
DB 08EH,0B0H,0ADH,08DH,0A7H,0A8H,0A9H,08FH
|
|
DB 08CH,0AEH,0ACH,09BH,0A0H,099H,0BCH,0B8H
|
|
DB 040H,03BH,03AH,070H,03CH,071H,05AH,03DH
|
|
DB 043H,056H,03FH,01EH,04AH,01CH,05DH,03EH
|
|
DB 05CH,01FH,05FH,05EH,037H,07BH,07FH,036H
|
|
DB 07AH,07EH,033H,04BH,04CH,01DH,06CH,05BH
|
|
DB 078H,041H,035H,034H,074H,030H,038H,075H
|
|
DB 039H,04DH,06FH,06EH,032H,077H,076H,072H
|
|
DB 073H,047H,07CH,053H,031H,04EH,06DH,048H
|
|
DB 046H,07DH,044H,01BH,058H,079H,042H,060H
|
|
|
|
;
|
|
; Physically place the cursor on the screen. Save the code to
|
|
; variable CURCH = FE ... graphically cursor
|
|
; FF ... alphanumeric cursor
|
|
; The sign that he covered is put to AKCHAR, there you have it
|
|
; they pick up the BLIKC and CUROF routines
|
|
;
|
|
; output: HL = E000H
|
|
; A = FFH
|
|
;
|
|
@CURON:
|
|
LD HL,CURCH
|
|
LD (HL),0EFH ; alphanumeric cursor
|
|
LD A,(CONMOD)
|
|
RRCA
|
|
JR C,J0BA0 ; graphically mod
|
|
RRCA ; do I display the cursor?
|
|
JR NC,J0BA2 ; No
|
|
J0BA0: LD (HL),0FFH ; graphically cursor
|
|
J0BA2: LD A,(HL) ; cursor character here
|
|
PUSH AF
|
|
CALL @?POINT ; cursor address
|
|
LD A,(HL) ; what was there
|
|
LD (AKCHAR),A ; is hiding for CUROF
|
|
POP AF ; a nas cursor
|
|
LD (HL),A ; will be stored there
|
|
XOR A
|
|
LD HL,MKBOUT
|
|
LD (HL),A
|
|
CPL
|
|
LD (HL),A
|
|
RET
|
|
;
|
|
DB 36H,43H,18H,0E9H
|
|
;
|
|
; Character conversion from "ASCII" code to display code
|
|
;
|
|
; input: A - character in "ASCII" code
|
|
; output: A - character in the display code
|
|
;
|
|
@?ADCN:
|
|
PUSH BC
|
|
PUSH HL
|
|
LD HL,QADCN ; asci table -M display
|
|
LD C,A
|
|
LD B,0
|
|
ADD HL,BC ; index it
|
|
LD A,(HL) ; pull out the display code
|
|
JR J0BE0 ; POP and RET
|
|
;
|
|
SV10A: DB "V1.0A"
|
|
DB CR
|
|
;
|
|
DB 0,0,0
|
|
;
|
|
; Convert a character from DISPLAY to an "ASCII" code
|
|
;
|
|
; input: A - character in the display code
|
|
; output: A - character in ASCII code
|
|
;
|
|
@?DACN:
|
|
PUSH BC
|
|
PUSH HL
|
|
PUSH DE
|
|
LD HL,QADCN ; ASCII table -M display
|
|
LD D,H
|
|
LD E,L ; and to DE
|
|
LD BC,256 ; the length of this table
|
|
CPIR ; looking for the sign outside
|
|
JR Z,J0BE3 ; found
|
|
LD A,NOKEY ; not found, returns NOKEY
|
|
J0BDF: POP DE
|
|
J0BE0: POP HL
|
|
POP BC
|
|
RET
|
|
J0BE3: OR A ; found, reset CY
|
|
DEC HL ; address back
|
|
SBC HL,DE ;
|
|
LD A,L ; calculate the index from the address
|
|
JR J0BDF ; POP and RET
|
|
;
|
|
; Keyboard tables
|
|
;
|
|
; 5 conversion tables from keyboard hardware code to
|
|
; display code, all tables are 64 characters long,
|
|
; only CTRL has only 63 characters for unknown reasons.
|
|
;
|
|
;
|
|
; Normal keys (without SHIFT, CTRL in alphanumeric mode)
|
|
;
|
|
QKBD: DB 0BFH,0CAH,058H,0C9H,NOKEY,02CH,04FH,0CDH
|
|
DB 019H,01AH,055H,052H,054H,NOKEY,NOKEY,NOKEY
|
|
DB 011H,012H,013H,014H,015H,016H,017H,018H
|
|
DB 009H,00AH,00BH,00CH,00DH,00EH,00FH,010H
|
|
DB 001H,002H,003H,004H,005H,006H,007H,008H
|
|
DB 021H,022H,023H,024H,025H,026H,027H,028H
|
|
DB 059H,050H,02AH,000H,020H,029H,02FH,02EH
|
|
DB 0C8H,0C7H,0C2H,0C1H,0C3H,0C4H,049H,02DH
|
|
;
|
|
; Shift keys
|
|
;
|
|
QKBDS: DB 0BFH,0CAH,01BH,0C9H,NOKEY,06AH,06BH,0CDH
|
|
DB 099H,09AH,0A4H,0BCH,040H,NOKEY,NOKEY,NOKEY
|
|
DB 091H,092H,093H,094H,095H,096H,097H,098H
|
|
DB 089H,08AH,08BH,08CH,08DH,08EH,08FH,090H
|
|
DB 081H,082H,083H,084H,085H,086H,087H,088H
|
|
DB 061H,062H,063H,064H,065H,066H,067H,068H
|
|
DB 080H,0A5H,02BH,000H,060H,069H,051H,057H
|
|
DB 0C6H,0C5H,0C2H,0C1H,0C3H,0C4H,05AH,045H
|
|
;
|
|
; Normal keys in graphics mode
|
|
;
|
|
QKBDG: DB 0BFH,NOKEY,0E5H,0C9H,NOKEY,042H,0B6H,0CDH
|
|
DB 075H,076H,0B2H,0D8H,04EH,NOKEY,NOKEY,NOKEY
|
|
DB 03CH,030H,044H,071H,079H,0DAH,038H,06DH
|
|
DB 07DH,05CH,05BH,0B4H,01CH,032H,0B0H,0D6H
|
|
DB 053H,06FH,0DEH,047H,034H,04AH,04BH,072H
|
|
DB 037H,03EH,07FH,07BH,03AH,05EH,01FH,0BDH
|
|
DB 0D4H,09EH,0D2H,000H,09CH,0A1H,0CAH,0B8H
|
|
DB 0C8H,0C7H,0C2H,0C1H,0C3H,0C4H,0BAH,0DBH
|
|
;
|
|
; CTRL characters
|
|
;
|
|
QKBDC: DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY
|
|
DB NOKEY,05AH,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY
|
|
DB 0C1H,0C2H,0C3H,0C4H,0C5H,0C6H,NOKEY,NOKEY
|
|
DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY
|
|
DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY
|
|
DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY
|
|
DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY
|
|
DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY
|
|
;
|
|
; Shift graphics
|
|
;
|
|
QKBDGS: DB 0BFH,NOKEY,0CFH,0C9H,NOKEY,0B5H,04DH,0CDH
|
|
DB 035H,077H,0D7H,0B3H,0B7H,NOKEY,NOKEY,NOKEY
|
|
DB 07CH,070H,041H,031H,039H,0A6H,078H,0DDH
|
|
DB 03DH,05DH,06CH,056H,01DH,033H,0D5H,0B1H
|
|
DB 046H,06EH,0D9H,048H,074H,043H,04CH,073H
|
|
DB 03FH,036H,07EH,03BH,07AH,01EH,05FH,0A2H
|
|
DB 0D3H,09FH,0D1H,000H,09DH,0A3H,0D0H,0B9H
|
|
DB 0C6H,0C5H,0C2H,0C1H,0C3H,0C4H,0BBH,0BEH
|
|
FDUMP:
|
|
CALL FHLHEX ; address from
|
|
CALL @IC4DE ;
|
|
PUSH HL ; hide
|
|
CALL @HLHEX ; address kam
|
|
POP DE ; pull the address from where
|
|
JR C,J0D88 ; incorrect entry
|
|
J0D36: EX DE,HL ; DE ... end, HL ... beginning
|
|
J0D37: LD B,8 ; number of apartments per row
|
|
LD C,23 ; shifted HEXA and ASCII text
|
|
CALL @?NLHL ; address from the beginning of the line to the CRT
|
|
J0D3E: CALL @MHEX ; byte below (HL)
|
|
INC HL ; next byte
|
|
PUSH AF ;
|
|
LD A,(CURSOR) ; column
|
|
ADD A,C ; the cursor at points to ASCII
|
|
LD (CURSOR),A ; column
|
|
POP AF
|
|
CP SPACE ; gap?
|
|
JR NC,J0D51
|
|
LD A,'.' ; flats P32 replace with a dot
|
|
J0D51: CALL @?ADCN ; to the display code
|
|
CALL @PRNTA ; and send
|
|
LD A,(CURSOR)
|
|
INC C ; the cursor returns
|
|
SUB C
|
|
LD (CURSOR),A ; and saves
|
|
DEC C ; edit cursor
|
|
DEC C
|
|
DEC C
|
|
PUSH HL
|
|
SBC HL,DE ; the end?
|
|
POP HL
|
|
JR Z,J0D85 ; yes, jump to the monitor
|
|
LD A,11111000B
|
|
LD (MKBOUT),A
|
|
NOP
|
|
LD A,(MKBDIN)
|
|
CP 11111110B ; suspension request?
|
|
JR NZ,J0D78
|
|
CALL @?BLNK ; suspend listing
|
|
J0D78: DJNZ J0D3E ; another byte on the line
|
|
J0D7A: CALL @GETKD ; test suspended again
|
|
OR A
|
|
JR Z,J0D7A
|
|
CALL BRKEY
|
|
JR NZ,J0D37 ; there was no break, another line
|
|
J0D85: JP FPRMPT
|
|
J0D88: LD HL,160
|
|
ADD HL,DE ; default end address
|
|
JR J0D36 ; and I continue
|
|
;
|
|
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
;
|
|
; Wait for the beginning of the frame dimming pulse
|
|
;
|
|
@?BLNK:
|
|
PUSH AF
|
|
J0DA7: LD A,(MPORTC)
|
|
RLCA
|
|
JR NC,J0DA7 ; wait for high
|
|
J0DAD: LD A,(MPORTC)
|
|
RLCA
|
|
JR C,J0DAD ; wait for low
|
|
POP AF
|
|
RET
|
|
;
|
|
; Saves the character at the cursor position in the VRAM, and executes
|
|
; cursor right. When saving a character to the last column,
|
|
; adjust line end attributes.
|
|
;
|
|
; input: A - character in the display code
|
|
;
|
|
@AVRAM:
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
J0DB9:
|
|
CALL @?POINT ; cursor address
|
|
LD (HL),A ; save character
|
|
LD HL,(CURSOR)
|
|
LD A,L
|
|
CP 39
|
|
JR NZ,J0DD0 ; we are not at the end of the line
|
|
CALL @ATBLN ; attributes
|
|
JR C,J0DD0 ; the current line is already ongoing
|
|
EX DE,HL
|
|
LD (HL),1 ; the next will be continued
|
|
INC HL
|
|
LD (HL),0 ; and no more
|
|
J0DD0: LD A,0C3H ; cursor right
|
|
JR J0DE0 ; • DPCT without saving the registry
|
|
;
|
|
; Query the set input mode
|
|
;
|
|
; output: A - 0CAH ... graphic mode setting character
|
|
; Z = 1 ... graphically mod
|
|
; 0 ... alphanumeric mod
|
|
;
|
|
@?GMOD:
|
|
LD A,(CONMOD)
|
|
CP 1
|
|
LD A,0CAH
|
|
RET
|
|
;
|
|
; Execution of control characters C0 - CF on CRT
|
|
; All other codes are ignored
|
|
; The meaning of the individual codes is described in
|
|
; tableQ ADISP.
|
|
;
|
|
; input: A = control code C0-CF
|
|
;
|
|
@?DPCT:
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
J0DE0: LD B,A ; control code i to B
|
|
AND 11110000B
|
|
CP 0C0H ; is it really control code?
|
|
JR NZ,EXIT1 ; no
|
|
XOR B ; character without upper four bits
|
|
RLCA ; * 2
|
|
LD C,A ; index into the table
|
|
LD B,0
|
|
LD HL,QADISP ; service address table
|
|
ADD HL,BC ; index table
|
|
LD E,(HL) ; service address to HL
|
|
INC HL
|
|
LD D,(HL)
|
|
LD HL,(CURSOR) ; cursor position to DE
|
|
EX DE,HL
|
|
JP (HL) ; sell control services
|
|
;
|
|
; Cursor o line niz
|
|
; If it is already on the 24th line, it rolls
|
|
;
|
|
CDOWN:
|
|
EX DE,HL
|
|
LD A,H
|
|
CP 24 ; the last line ?
|
|
JR Z,J0E23 ; yes, scroll
|
|
INC H ; o line dolu
|
|
EXITC:
|
|
LD (CURSOR),HL
|
|
EXIT1:
|
|
JP EXIT
|
|
;
|
|
; Cursor one line up
|
|
; If it is already on the 0th line, nothing happens
|
|
;
|
|
CUP:
|
|
EX DE,HL
|
|
LD A,H
|
|
OR A
|
|
JR Z,EXIT1 ; 0.line
|
|
DEC H ; on the previous line
|
|
J0E0B: JR EXITC
|
|
;
|
|
; Cursor one character to the right
|
|
;
|
|
CRIGHT:
|
|
EX DE,HL
|
|
LD A,L
|
|
CP 39 ; last column?
|
|
JR NC,J0E16 ; Yes
|
|
INC L ; no, raise the column
|
|
JR EXITC ; return
|
|
J0E16: LD L,0 ; the column was the last
|
|
INC H ; on another line
|
|
LD A,H ;
|
|
CP 25 ; on the last line?
|
|
JR C,EXITC ; no, everything is OK
|
|
LD H,24 ; yes, he will stay there
|
|
LD (CURSOR),HL
|
|
J0E23: JR SCROLL ; and rolls off
|
|
;
|
|
; Cursor one character to the left
|
|
;
|
|
CLEFT:
|
|
EX DE,HL
|
|
LD A,L
|
|
OR A
|
|
JR Z,J0E2D ; I'm at the beginning of the line
|
|
DEC L ; shrink
|
|
JR EXITC ; return
|
|
J0E2D: LD L,39 ; I'll be at the end of the line
|
|
DEC H ; and line vys
|
|
JP P,J0E0B ; return - nothing happened
|
|
LD H,0 ; column zero
|
|
LD (CURSOR),HL
|
|
JR EXIT1
|
|
;
|
|
; Clear the screen
|
|
;
|
|
CLEAR:
|
|
LD HL,QATBLN
|
|
LD B,27
|
|
CALL @F0B ; delete row attributes
|
|
LD HL,ADRCRT ; reset VRAM data
|
|
CALL @FILL0
|
|
LD A,IMPATB ; delete VRAM attributes
|
|
CALL @FILLA ; and then a home was made
|
|
;
|
|
; Cursor left up
|
|
;
|
|
HOME:
|
|
LD HL,0
|
|
JR EXITC
|
|
;
|
|
DB 0,0,0,0,0,0,0,0
|
|
;
|
|
; New line on CRT
|
|
;
|
|
CRLF:
|
|
CALL @ATBLN
|
|
RRCA ; attribute of the next row?
|
|
JR NC,J0E16 ; is a continuation, skip it
|
|
LD L,0 ; Column 0
|
|
INC H
|
|
CP 24
|
|
JR Z,J0E6A ; end of screen, scroll
|
|
INC H
|
|
JR EXITC
|
|
;
|
|
J0E6A:
|
|
LD (CURSOR),HL
|
|
;
|
|
; Scrolls the CRT up one logical line
|
|
;
|
|
SCROLL:
|
|
LD BC,960 ; length
|
|
LD DE,ADRCRT
|
|
LD HL,ADRCRT+40
|
|
PUSH BC
|
|
LDIR ; scrolled VRAM data
|
|
POP BC
|
|
PUSH DE
|
|
LD DE,ADRATB
|
|
LD HL,ADRATB+40
|
|
LDIR ; scrolling VRAM attributes
|
|
LD B,40
|
|
EX DE,HL
|
|
LD A,IMPATB
|
|
CALL @FAB ; deleting the last row of VRAM
|
|
POP HL
|
|
LD B,40
|
|
CALL @F0B ; deleting the last row of VRAM
|
|
LD BC,26
|
|
LD DE,QATBLN
|
|
LD HL,QATBLN+1
|
|
LDIR ; line end attribute scrolling
|
|
LD (HL),0
|
|
LD A,(QATBLN) ; attribute 0. radku
|
|
OR A
|
|
JR Z,EXIT ; not continued
|
|
LD HL,CURSOR+1 ; is continued, scrolls again
|
|
DEC (HL) ; cursor one line up
|
|
JR SCROLL ; and again
|
|
;
|
|
; CRT Service Address Table (C0-CF)
|
|
;
|
|
QADISP: DW SCROLL ; C0 = Scroll
|
|
DW CDOWN ; C1 = Cursor down
|
|
DW CUP ; C2 = Cursor up
|
|
DW CRIGHT ; C3 = Cursor right
|
|
DW CLEFT ; C4 = Cursor left
|
|
DW HOME ; C5 = homeM
|
|
DW CLEAR ; C6 = clr
|
|
DW DELETE ; C7 = del
|
|
DW INSERT ; C8 = ins
|
|
DW ALPHA ; C9 = alph
|
|
DW GRAPH ; CA = graph
|
|
DW EXIT ; CB = not used
|
|
DW EXIT ; CC = not used
|
|
DW CRLF ; CD = cr
|
|
DW EXIT ; CE = not used
|
|
DW EXIT ; CF = not used
|
|
;
|
|
J0ECA: SET 3,H ; it's a piece from INSERT
|
|
LD A,(HL) ; copies characters in VRAM-attributes
|
|
INC HL
|
|
LD (HL),A
|
|
DEC HL
|
|
RES 3,H ; and in VRAM data
|
|
LDD
|
|
LD A,C
|
|
OR B
|
|
JR NZ,J0ECA ; loop insert
|
|
EX DE,HL
|
|
LD (HL),0 ; under the cursor delete
|
|
SET 3,H
|
|
LD (HL),IMPATB ; and delete the attribute as well
|
|
JR EXIT
|
|
;
|
|
; Set alphanumeric mod
|
|
;
|
|
ALPHA:
|
|
XOR A
|
|
J0EE2: LD (CONMOD),A
|
|
;
|
|
EXIT: POP HL
|
|
J0EE6: POP DE
|
|
POP BC
|
|
POP AF
|
|
RET
|
|
;
|
|
DB 0,0,0,0
|
|
;
|
|
; Graphically sets the character, if it has already been set, the character
|
|
; save to CRT
|
|
;
|
|
GRAPH:
|
|
CALL @?GMOD ; it is set ?
|
|
JP Z,J0DB9 ; Yes
|
|
LD A,1
|
|
JR J0EE2 ; jump to AVRAM without storage
|
|
;
|
|
; Delete the character to the left of the cursor
|
|
;
|
|
DELETE:
|
|
EX DE,HL
|
|
LD A,H
|
|
OR L
|
|
JR Z,EXIT ; We're home
|
|
LD A,L
|
|
OR A
|
|
JR NZ,J0F0E ; the cursor is not at the beginning of the line
|
|
CALL @ATBLN ; the cursor is at the beginning of the line
|
|
JR C,J0F0E ; line is a continuation, normally lubricated
|
|
CALL @?POINT
|
|
DEC HL
|
|
LD (HL),0 ; to the end of the previous one
|
|
JR J0F33
|
|
;
|
|
J0F0E: CALL @ATBLN
|
|
RRCA ; the row attribute to CY
|
|
LD A,40 ; simple line
|
|
JR NC,J0F17
|
|
RLCA ; continuation line
|
|
J0F17: SUB L ; the number of characters until the end of the line
|
|
LD B,A ; as a repeater
|
|
CALL @?POINT
|
|
J0F1C: ; shift B flat to the left
|
|
LD A,(HL) ; and VRAM data
|
|
DEC HL
|
|
LD (HL),A
|
|
INC HL
|
|
SET 3,H ; and in VRAM attributes
|
|
LD A,(HL)
|
|
DEC HL
|
|
LD (HL),A
|
|
RES 3,H
|
|
INC HL
|
|
INC HL
|
|
DJNZ J0F1C ; the last character has not been moved yet
|
|
DEC HL
|
|
LD (HL),0 ; delete the last character in the VRAM
|
|
SET 3,H ; also in VRAM attributes
|
|
LD HL,IMPATB ; HL MA APARTMENT IN BRACES
|
|
J0F33: LD A,0C4H ; cursor left
|
|
JP J0DE0 ; for hiding the registry? DPCT
|
|
;
|
|
; Insert a character in place of the cursor
|
|
;
|
|
INSERT:
|
|
CALL @ATBLN
|
|
RRCA ; the row attribute to CY
|
|
LD L,39 ; simple length
|
|
LD A,L
|
|
JR NC,J0F42 ;
|
|
INC H ; line is double
|
|
J0F42: CALL @?ACUR ; line end address
|
|
PUSH HL
|
|
LD HL,(CURSOR) ; cursor position
|
|
JR NC,J0F4D
|
|
LD A,79 ; double line length
|
|
J0F4D:
|
|
SUB L ; the character remains until the end of the line
|
|
LD B,0
|
|
LD C,A ; BC is the number of characters to the end of the line
|
|
POP DE ; reset line end address
|
|
JR Z,EXIT ; we are on the last character
|
|
LD A,(DE) ; last character
|
|
OR A
|
|
JR NZ,EXIT ; it is not a space, INSERT cannot
|
|
LD H,D
|
|
LD L,E
|
|
DEC HL ; penultimate address to HL
|
|
JP J0ECA
|
|
;
|
|
; SAVE monitor display
|
|
;
|
|
FSAVE:
|
|
CALL FHLHEX ; enter the address in the HL
|
|
LD (BEGIN),HL ; this will be the boot address
|
|
LD B,H ; and will also be in BC
|
|
LD C,L
|
|
CALL @IC4DE ; to another address
|
|
CALL FHLHEX ; I'm with her
|
|
SBC HL,BC ; it is the end address
|
|
INC HL
|
|
LD (FSIZE),HL ; to the header
|
|
CALL @IC4DE ; and one more address
|
|
CALL FHLHEX
|
|
LD (ENTRY),HL ; start address
|
|
CALL @IFNL? ; novy line
|
|
LD DE,SFNAME ; query file name
|
|
RST 18H
|
|
CALL FGETL ; read the file name
|
|
CALL @IC4DE ; DE = DE + 8
|
|
CALL @IC4DE
|
|
LD HL,FNAME ; address in the file name header
|
|
J0F8E: INC DE ; copy the name to the header
|
|
LD A,(DE)
|
|
LD (HL),A
|
|
INC HL
|
|
CP CR ; we end when there is CR
|
|
JR NZ,J0F8E
|
|
LD A,1 ; type is always 1 = ORDER NO
|
|
LD (HEAD),A
|
|
CALL WHEAD ; write the header
|
|
JP C,FCMTER ; error
|
|
CALL WDATA ; record that
|
|
JP C,FCMTER ; error
|
|
CALL @IFNL?
|
|
LD DE,MSGOK ; Write the message OKQ
|
|
RST 18H
|
|
JP FPRMPT ; to the monitor
|
|
;
|
|
; Return the cursor address to the VRAM
|
|
;
|
|
; output: HL = cursor address
|
|
;
|
|
@?POINT:
|
|
LD HL,(CURSOR)
|
|
@?ACUR: ; this input assumes a position in HL
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
POP BC ; position is in BC
|
|
LD DE,40 ; length of work
|
|
LD HL,ADRCRT-40 ; before the CRT address
|
|
J0FBF: ADD HL,DE ; * 40
|
|
DEC B
|
|
JP P,J0FBF
|
|
LD B,0
|
|
ADD HL,BC ; add a column
|
|
POP DE
|
|
POP BC
|
|
POP AF
|
|
RET
|
|
;
|
|
FVERIF: ; File verification
|
|
CALL VERIF ; perform verification
|
|
JP C,FCMTER ; error or break
|
|
LD DE,MSGOK ; List OK!
|
|
RST 18H
|
|
JP FPRMPT ; to the monitor
|
|
;
|
|
; Zero memory full ( see @ FAB )
|
|
;
|
|
@F0B: XOR A
|
|
JR @FAB
|
|
;
|
|
; Full FF memory ( see @ FAB )
|
|
;
|
|
@FFFB: LD A,0FFH
|
|
;
|
|
; Full memory constant
|
|
;
|
|
; Input: HL - address
|
|
; A - the value by which it is fulfilled
|
|
; B - number of apartments
|
|
;
|
|
; Output: HL = HL + B
|
|
; A = constant by which it was filled
|
|
;
|
|
@FAB: LD (HL),A
|
|
INC HL
|
|
DJNZ @FAB
|
|
RET
|
|
;
|
|
; Waiting for 100 zeros on CMT (think bit zeros)
|
|
;
|
|
; output: CY = 1 ... break
|
|
; CY = 0 ... zeros found
|
|
;
|
|
@RINTR:
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD BC,MKBDIN ; registers for W0TO1
|
|
LD DE,MPORTC
|
|
J0FEB: LD H,100
|
|
J0FED: CALL W0TO1 ; wait for the leading edge
|
|
JR C,J0FFD ; break
|
|
CALL @D331 ; waiting for READ POINT
|
|
LD A,(DE) ; honor 8255 gate C
|
|
AND 00100000B ; test read CMT bit
|
|
JR NZ,J0FEB ; the one does not have to be there
|
|
DEC H ; a mame dalsi zero
|
|
JR NZ,J0FED ; there are not 100 of them yet
|
|
J0FFD: JP POPX2
|
|
;
|