Spectrum 128 ROM 0 - Incomplete disassembly
; *** SPECTRUM 128 ROM 0 DISASSEMBLY ***
; The Spectrum ROMs are copyright Amstrad, who have kindly given permission \
; to publish ROM disassemblies.
; ** General notes **
;
; (5B66) flags;
; bit 4 for LOAD, bit 5 for SAVE, bit 6 for MERGE, bit 7 for VERIFY
; bit 3 indicates RAMdisk or not
;
; (5b8d-5d91): last value printed by calculator
;
; page 7:
; EC00-02, 03-05 are flags of some sort
; EC06-07 is two-word store
; (EC08;EC09) seems to be the last line number entered
;
; EC0C: current menu index
;
; EC0D flags:
; bit 0 : ?
; Forcibly setting it seems to ignore all keys apart from DELETE
; (which clears it) and ENTER (which doesn't)
; bit 1 : set when a menu is displayed
; bit 2 : ?
; bit 3 : set when the current line has been altered
; bits 4 and 5 set during calculator; bit 4 reset when returning to main menu
; bit 6 : set when editing area is the lower screen
; bit 7 : set during editing (when waiting for editing keypress?)
;
; EC0E starts at 00, goes to 04 when entering calc mode,
; goes to FF when aborting Tape Loader,
; set to 07 in some other Tape Loader scenario
;
; EC13 is the temporary store for P-FLAG
;
; EC15 holds the number of editing lines: 20 for the main screen, 1 for the
; lower screen.
; EC16... holds the currently editing stuff;
; 32 * chars + 3 * flags
; characters on the screen but not editable (eg indent chars after line wrap)
; are zero
; first flag byte:
; on first line, seems to be 09 until full, then goes to 03
; 1001 0011
; on subsequent lines, seems to be 08 until full, then goes to 02
; 1000 0010
; bit 0 = first line flag?
; F6EA holds the jump table for the current menu
; F6EC holds the text information for the current menu
; F6EE,F6EF,F6F0 holds the cursor position - row, column, alternate column.
;
; Line being edited has a temporary copy (???) made at f6f8?
;
; FC9A,B holds the line at the top of the screen, or 0 for the first line
;
; FD81 contains some flag bits used when tokenizing a BASIC line. Bits 0 and 1
; relate to quote marks in the line; bit 2 is used to indicate the presence of
; REM.
;
; FD84 contains more flag bits used when entering a BASIC line. As far as I can see
; bit 0 is set when the last character was a keyword; bit 1 is set when the last
; character was a space.
;
; FD89 holds "<" or ">", if this was the previously examined character
; during tokenization of a BASIC line.
;
; AY-3-8912 registers
; Register Function Range
; 0 Channel A fine pitch 8-bit (0-255)
; 1 Channel A course pitch 4-bit (0-15)
; 2 Channel B fine pitch 8-bit (0-255)
; 3 Channel B course pitch 4-bit (0-15)
; 4 Channel C fine pitch 8-bit (0-255)
; 5 Channel C course pitch 4-bit (0-15)
; 6 Noise pitch 5-bit (0-31)
; 7 Mixer 8-bit
; 8 Channel A volume 4-bit (0-15)
; 9 Channel B volume 4-bit (0-15)
; 10 Channel C volume 4-bit (0-15)
; 11 Envelope fine duration 8-bit (0-255)
; 12 Envelope course duration 8-bit (0-255)
; 13 Envelope shape 4-bit (0-15)
; 14 I/O port A 8-bit (0-255)
; RAMdisk format:
; Files start at 1C000 and build upwards
; Catalogue entries start at 7EBFF and build downwards
; Directory stack doesn't go below 7C000
; Start address at +0A,+0B,+0C
; Length at +0D,+0E,+0F
; End addresss at +10,+11,+12
; ROM 1 subroutines
EXPT_EXP .equ $1c8c
STK_FETCH .equ $2bf1
CLS .equ $0d6b
CLS_LOWER .equ $0d6e
TEST_SCREEN .equ $3c04
; ** The restart and initialisation routines **
L0000 di ; Reset the machine.
ld bc,$692b ;
L0004 dec bc ;
ld a,b ;
or c ;
jr nz,L0004 ; (There is no RST 8).
jp L00c7 ; to the main reset routine
.byte 00,00,00,00 ; spare bytes
; RST 10,18 and 20 call the equivalent subroutines in ROM 1, via RST 28.
L0010 rst 28h ;
L0011 .word $0010 ;
L0013 ret ;
L0014 .byte 00,00,00,00 ; spare bytes
L0018 rst 28h ;
.word $0018 ;
ret ;
.byte 00,00,00,00 ; spare bytes
L0020 rst 28h ;
L0021 .word $0020 ;
L0023 ret ;
.byte 00,00,00,00 ; spare bytes
; RST 28 calls a routine in ROM 1 (or alternatively a routine in RAM while \
; ROM 1 is paged in). Call as follows: RST 28 / .word address
L0028 ex (sp),hl ; Get the address after the RST 28 into HL,
; saving HL on the stack.
push af ;
ld a,(hl) ;
L002b inc hl ; Point HL to the byte after
inc hl ; the required address.
ld ($5b5a),hl ; Store this in RETADDR.
L0030 dec hl ;
ld h,(hl) ;
L0032 ld l,a ; HL=subroutine to call.
pop af ; Restore AF.
jp L005c ; Jump ahead to continue.
L0037 .byte 0 ; Spare byte.
; Interrupt routine
L0038 push hl ; e5
ld hl,$0048 ; 21 48 00
L003c push hl ; e5
ld hl,$5b00 ; 21 00 5b
L0040 push hl ; e5
ld hl,$0038 ; 21 38 00
push hl ; e5
jp $5b00 ; c3 00 5b
L0048 pop hl ; e1
ret ; c9
L004a ld bc,$7ffd ; 01 fd 7f
xor a ; af
di ; f3
out (c),a ; ed 79
ld ($5b5c),a ; 32 5c 5b
ei ; fb
dec a ; 3d
ld (iy+$00),a ; fd 77 00
jp L0321 ; c3 21 03
L005c ld ($5b58),hl ; 22 58 5b
ld hl,$5b14 ; 21 14 5b
ex (sp),hl ; e3
push hl ; e5
L0064 ld hl,($5b58) ; NB There is no NMI code [AOwen]
ex (sp),hl ; e3
jp $5b00 ; c3 00 5b
; The following code will end up at 5b00
L006b push af ; (5b00)
push bc ; (5b01)
ld bc,$7ffd ; (5b02)
ld a,($5b5c) ; (5b05)
xor $10 ; (5b08)
di ; (5b0a)
ld ($5b5c),a ; (5b0b)
out (c),a ; (5b0e)
ei ; (5b10)
pop bc ;
pop af ;
ret ;
call $5b00 ;
L0082 push hl ;
ld hl,($5b5a) ;
ex (sp),hl ;
ret ;
di ;
ld a,($5b5c) ;
and $ef ; (5b21)
ld ($5b5c),a ;
ld bc,$7ffd ;
out (c),a ;
L0096 ei ;
jp L00c3 ;
ld hl,$06d8 ; (5b2f)
jr L00a2 ;
ld hl,$07ca ;
L00a2 ex af,af' ;
ld bc,$7ffd ;
ld a,($5b5c) ;
push af ;
and $ef ;
di ;
ld ($5b5c),a ;
out (c),a ;
jp L05e6 ;
ex af,af' ;
pop af ;
ld bc,$7ffd ;
di ;
ld ($5b5c),a ;
out (c),a ;
ei ;
ex af,af' ;
ret ;
L00c3 ld hl,($5b8b) ; 2a 8b 5b
jp (hl) ; e9
; Continuation of the RESET routine
L00c7 ld b,$08 ; 06 08
L00c9 ld a,b ; 78
exx ; d9
dec a ; 3d
ld bc,$7ffd ; Switch RAM page
L00cf out (c),a ;
ld hl,$c000 ;
ld de,$c001 ;
ld bc,$3fff ;
ld a,$ff ;
ld (hl),a ; Store FF into RAM
cp (hl) ; Check RAM integrity
jr nz,L0131 ; Fatal error
xor a ;
ld (hl),a ;
cp (hl) ;
jr nz,L0131 ;
ldir ; Clear the whole page
exx ;
djnz L00c9 ; Keep looping through pages
ld ($5b88),a ; 32 88 5b
ld c,$fd ; 0e fd
ld d,$ff ; 16 ff
ld e,$bf ; 1e bf
ld b,d ; 42
ld a,$0e ; 3e 0e
out (c),a ; ed 79
ld b,e ; 43
ld a,$ff ; 3e ff
out (c),a ; ed 79
jr L0137 ; 18 38
.byte $00 ; spare byte
; Jump table. For descriptions of 118..12a, see
; http://groups.google.com/groups?selm=bbbede39.0310140525.5b1e5a78%40posting.google.com
L0100 jp L17af ; c3 af 17
L0103 jp L1838 ; c3 38 18
L0106 jp L1ecf ; c3 cf 1e
L0109 jp L1f04 ; c3 04 1f
L010c jp L004a ; c3 4a 00
L010f jp L03a2 ; c3 a2 03
L0112 jp L182a ; c3 2a 18
L0115 jp L18a8 ; c3 a8 18
L0118 jp L012d ; Keypad scan
L011b jp L0a05 ; Play music strings
L011e jp L11a3 ; Send to MIDI
L0121 jp L06d8 ; RS232 input
L0124 jp L07ca ; RS232 output (1)
L0127 jp L08a3 ; RS232 output (2)
L012a jp L08f0 ; COPY (screen dump) routine
L012d rst 28h ; Call keypad routine in BASIC ROM.
.word $3b01 ; BUG: The address should be $3c01. Credit: Paul Farrow.
ret
; Fatal RAM error
L0131 exx ;
ld a,b ; Indicate which RAM page failed by
out ($fe),a ; setting the border colour
L0135 jr L0135 ; Infinite loop
; Next bit by Geoff Wearmouth.
; Reset routine continued
; complete setting up sound chip registers.
L0137 ld b,d ; 42
ld a,$07 ; 3e 07
out (c),a ; ed 79
ld b,e ; 43
ld a,$ff ; 3e ff
out (c),a ; ed 79
; Now copy the paging mechanism.
ld de,$5b00 ; The destination is the start of the old ZX buffer.
ld hl,$006b ; The source is in this ROM.
ld bc,$0058 ; There are eighty eight bytes to copy.
ldir ; Copy the block of bytes.
ld a,$cf ; Load A with the code for the Z80 instruction 'RST 08'.
ld ($5b5d),a ; Insert into New System Variable RAMRST.
ld sp,$5bff ; Set the stack pointer to last location of old buffer.
ld a,$04 ; page in logical page 4
call L1c64 ; (physical page 7)
ld ix,$ebec ; "end of catalogue" marker in RAMdisk
ld ($5b83),ix ; SF_NEXT
ld (ix+$0a),$00 ;
ld (ix+$0b),$c0 ;
ld (ix+$0c),$00 ;
ld hl,$2bec ;
ld a,$01 ; AHL = free space in RAMdisk
ld ($5b85),hl ;
ld ($5b87),a ;
ld a,$05 ; page in logical page 5
call L1c64 ; (physical page 0)
ld hl,$ffff ; Load HL with known last working byte - 65535.
ld ($5cb4),hl ; Set P-RAMT standard System Variable.
ld de,$3eaf ; Set DE to address of the last bitmap of 'U' in the
; Main ROM.
ld bc,$00a8 ; There are 21 User Defined Graphics to copy.
ex de,hl ; Swap so destination is $FFFF.
rst 28h ;
.word $1661 ; calling this address (LDDR/RET) in the Main ROM
; cleverly copies the 21 characters to the end of RAM.
ex de,hl ; Transfer DE to HL.
inc hl ; Increment to address first byte of UDG 'A'.
ld ($5c7b),hl ; Update standard System Variable UDG.
dec hl ; decrement HL.
ld bc,$0040 ; set values zero and 64.
ld ($5c38),bc ; Update standard System Variables RASP and PIP.
ld ($5cb2),hl ; Update standard System Variable RAMTOP - the last
; byte of the BASIC system area. Any machine code and
; graphics above this address are protected from NEW.
; entry point for NEW with Interrupts disabled and physical page zero occupying
; the upper RAM region $C000 - $FFFF - the normal BASIC memory configuration.
L019d ld hl,$3c00 ; Set HL to where, in theory character zero would be.
ld ($5c36),hl ; Update standard System Variable CHARS.
ld hl,($5cb2) ; Load HL with value of System Variable RAMTOP.
inc hl ; Address next location.
ld sp,hl ; Set the Stack Pointer.
im 1 ; Select Interrupt Mode 1.
ld iy,$5c3a ; Set the IY register to address the Standard System
; Variables and many of the new System Variables and
; even those of Interface 1 in some cases.
set 4,(iy+$01) ; Update FLAGS - signal 128K mode
; Note. This bit was unused and therefore never set
; by 48K BASIC.
ei ; With a stack and the IY register set, Interrupts can
; be enabled.
ld hl,$000b ; Set HL to eleven.
ld ($5b5f),hl ; Update new System Variable BAUD - the RS232 bit
; period. A value of eleven is equivalent to 9600 baud.
xor a ; Clear accumulator.
ld ($5b61),a ; Set new System Variable SERFL to zero.
ld ($5b63),a ; Set new System Variable COL to zero.
ld ($5b65),a ; Set new System Variable TVPARS to zero.
ld hl,$ec00 ; Should write to page 7 [AOwen]
ld ($ff24),hl ;
; Note. this is dangerously close to the machine stack. \
; The 1985 Sinclair Research ESPAGNOL source code says that this instruction \
; will write to the [previously cleared] Main BASIC RAM during initialization \
; but that a different page of RAM will be present during NEW. \
; Stuff and Nonsense! Assemblers and other languages will be corrupted by the \
; BASIC NEW command.
ld a,$50 ; Set printer width to a default of eighty.
ld ($5b64),a ; Update new System Variable WIDTH for 80 columns.
ld hl,$000a ; set HL to ten.
ld ($5b94),hl ; Store in spare locations between STRIP2
L01d4 ld ($5b96),hl ; and the temporary stack TSTACK.
ld hl,$5cb6 ; Load HL with address following System Variables.
ld ($5c4f),hl ; Set standard System Variable CHANS.
ld de,$0589 ; Point to Initial Channel Information in this ROM.
; Note. this is similar to that in Main ROM but
; channel 'P' has input and output addresses in the
; new $5Bxx region.
ld bc,$0015 ; There are 21 bytes to copy.
ex de,hl ; Switch pointer so destination is CHANS.
ldir ; Copy the block of bytes.
ex de,hl ; Transfer DE to HL.
dec hl ; Decrement to point to $80 end-marker.
ld ($5c57),hl ; Update standard System Variable DATADD to this
; resting address.
inc hl ; Bump address.
ld ($5c53),hl ; Set standard System Variable PROG.
ld ($5c4b),hl ; Set standard System Variable VARS.
ld (hl),$80 ; Insert the Variables end-marker.
inc hl ; Increment the address.
ld ($5c59),hl ; Set standard System Variable ELINE.
ld (hl),$0d ; Insert a carriage return.
inc hl ; Increment address.
ld (hl),$80 ; Insert the $80 end-marker.
inc hl ; increment address.
ld ($5c61),hl ; Set the standard System Variable WORKSP.
ld ($5c63),hl ; Set the standard System Variable STKBOT.
ld ($5c65),hl ; Set the standard System Variable STKEND.
ld a,$38 ; Set colour attribute to black ink on white paper.
ld ($5c8d),a ; Set the standard System Variable ATTR_P.
ld ($5c8f),a ; Set the standard System Variable MASK_P.
ld ($5c48),a ; Set the standard System Variable BORDCR.
xor a ; Clear the accumulator.
ld ($ec13),a ; and zero a byte in the upper page of RAM.
; Note $EC13 is the temporary store for P-FLAG in Page 7 of RAM.
; Again Main RAM has been corrupted.
ld a,$07 ; Load the accumulator with colour for white.
out ($fe),a ; Output to Port $FE changing border to white.
ld hl,$0523 ; The values five and thirty five.
ld ($5c09),hl ; Set the standard System Variables REPDEL and REPPER
dec (iy-$3a) ; Set KSTATE-0 to $FF
dec (iy-$36) ; Set KSTATE-4 to $FF
ld hl,$059e ; Set source to Initial Stream Data in this ROM.
; Note. this is identical to that is Main ROM.
ld de,$5c10 ; Set destination to standard System Variable STRMS-FD
ld bc,$000e ; There are fourteen bytes to copy.
ldir ; Block copy the bytes.
res 1,(iy+$01) ; Update FLAGS - signal printer not is use.
ld (iy+$00),$ff ; Set standard System Variable ERR_NR to $FF (OK-1).
ld (iy+$31),$02 ; Set standard Sytem Variable DF_SZ to two lines.
rst 28h
.word CLS
rst 28h
.word TEST_SCREEN
ld de,$0561 ; Sinclair copyright message
call L057d ; print a message terminated by having bit 7 set.
ld (iy+$31),$02 ; Set standard System Variable DF_SZ to two lines.
set 5,(iy+$02) ; Update TV-FLAG - signal lower screen will require
; clearing.
ld hl,$5bff ; Set HL to location of temporary stack
ld ($5b81),hl ; Store in STRIP1.
call L1f45 ; switch RAM to Page 7
ld a,$38 ; set colours to black ink on white paper.
ld ($ec11),a ; 32 11 ec
ld ($ec0f),a ; 32 0f ec
; Note this is where $EC13 and $FF24 should be set!!!!
call L2584 ;
call L1f20 ;
jp L259f ; to menu ........
L026b ld hl,$5b66 ; 21 66 5b
set 0,(hl) ; cb c6
ld (iy+$00),$ff ; '0 OK' status
ld (iy+$31),$02 ; fd 36 31 02
ld hl,$5b1d ; 21 1d 5b
push hl ; e5
ld ($5c3d),sp ; ed 73 3d 5c
ld hl,$02ba ; 21 ba 02
ld ($5b8b),hl ; 22 8b 5b
call L228e ; Point to start of BASIC command
call L22cb ; cd cb 22
jp z,L21f8 ; ca f8 21
cp $28 ; '('
jp z,L21f8 ; ca f8 21
cp $2d ; '-'
jp z,L21f8 ; ca f8 21
cp $2b ; '+'
jp z,L21f8 ; ca f8 21
call L22e0 ; cd e0 22
jp z,L21f8 ; ca f8 21
call L1f45 ; cd 45 1f
ld a,($ec0e) ; 3a 0e ec
call L1f20 ; cd 20 1f
cp $04 ; Calculator mode?
jp nz,L17af ; c2 af 17
call L2297 ; cd 97 22
jp z,L17af ; ca af 17
pop hl ; e1
ret ; c9
L02ba bit 7,(iy+$00) ; fd cb 00 7e
jr nz,L02c1 ; 20 01
L02c0 ret ; c9
L02c1 ld hl,($5c59) ; 2a 59 5c
ld ($5c5d),hl ; 22 5d 5c
rst 28h ; ef
.word $19fb ; E-LINE-NO
ld a,b ; 78
or c ; b1
jp nz,L03f7 ; c2 f7 03
rst 18h ; df
cp $0d ; fe 0d
ret z ; c8
call L21ef ; cd ef 21
bit 6,(iy+$02) ; fd cb 02 76
jr nz,L02df ; 20 03
rst 28h ; ef
.word CLS_LOWER
L02df res 6,(iy+$02) ; fd cb 02 b6
call L1f45 ; cd 45 1f
ld hl,$ec0d ;
bit 6,(hl) ; Test for editing in lower-screen area
jr nz,L02f4 ; 20 07
inc hl ; 23
ld a,(hl) ; 7e
cp $00 ; fe 00
call z,L3881 ; cc 81 38
L02f4 call L1f20 ; cd 20 1f
ld hl,$5c3c ; 21 3c 5c
res 3,(hl) ; cb 9e
ld a,$19 ; 3e 19
sub (iy+$4f) ; fd 96 4f
ld ($5c8c),a ; 32 8c 5c
set 7,(iy+$01) ; fd cb 01 fe
ld (iy+$0a),$01 ; fd 36 0a 01
ld hl,$3e00 ; 21 00 3e
push hl ; e5
ld hl,$5b1d ; 21 1d 5b
push hl ; e5
ld ($5c3d),sp ; ed 73 3d 5c
ld hl,$0321 ; 21 21 03
ld ($5b8b),hl ; 22 8b 5b
jp L1838 ; c3 38 18
L0321 ld sp,($5cb2) ; ed 7b b2 5c
inc sp ; 33
ld hl,$5bff ; 21 ff 5b
ld ($5b81),hl ; 22 81 5b
halt ; 76
res 5,(iy+$01) ; fd cb 01 ae
ld hl,$5b66 ; 21 66 5b
bit 2,(hl) ; cb 56
jr z,L034a ; 28 12
call L1f45 ; cd 45 1f
ld ix,($5b83) ; SF_NEXT
ld bc,$0014 ; 01 14 00
add ix,bc ; dd 09
call L1d56 ; cd 56 1d
call L1f20 ; cd 20 1f
L034a ld a,($5c3a) ; 3a 3a 5c
inc a ; 3c
L034e push af ; f5
ld hl,$0000 ; 21 00 00
ld (iy+$37),h ; fd 74 37
ld (iy+$26),h ; fd 74 26
ld ($5c0b),hl ; 22 0b 5c
ld hl,$0001 ; 21 01 00
ld ($5c16),hl ; 22 16 5c
rst 28h ; ef
.word $16b0 ; SET-MIN "Clears editing area and areas after it"
res 5,(iy+$37)
rst 28h ; ef
.word CLS_LOWER
set 5,(iy+$02) ; fd cb 02 ee
pop af ; f1
ld b,a ; 47
cp $0a ; Is it a digit?
jr c,L037f ; If so jump ahead to print it
cp $1d ; Is it one of the old errors (A-R)?
jr c,L037d ; If so jump ahead to add 7 and print
add a,$14 ; Otherwise add 20
jr L037f ; and jump ahead to print
; [Could have saved two bytes by having add $0c instead
; of these two instructions]
L037d add a,$07 ;
L037f rst 28h ;
.word $15ef ; OUT-CODE
ld a,$20 ; Print a space
rst 10h ;
ld a,b ; Restore the error code
cp $1d ;
jr c,L039c ; Old error message
sub $1d ;
ld b,$00 ;
ld c,a ;
ld hl,L046c ; start of new error messages
add hl,bc ;
add hl,bc ;
ld e,(hl) ;
inc hl ; get start of requested error
ld d,(hl) ; message in DE
call L057d ; print error message
jr L03a2 ; jump ahead
L039c ld de,$1391 ; Position of the error messages in ROM 1
rst 28h ;
.word $0c0a ; PO-MSG, message printing
L03a2 xor a ; af
ld de,$1536 ; 11 36 15
rst 28h ; ef
.word $0c0a ; PO-MSG; print a comma followed by a space
ld bc,($5c45) ; PPC, current line number
rst 28h ; ef
.word $1a1b ; OUT-NUM-1
ld a,$3a ; ":"
rst 10h ;
ld c,(iy+$0d) ; SUBPPC
ld b,$00 ;
rst 28h ;
.word $1a1b ; OUT-NUM-1
rst 28h ;
.word $1097 ; CLEAR-SP ; tidy up
ld a,($5c3a) ; ERR NR
inc a
jr z,L03df ; Jump ahead for 0 OK
cp $09 ;
jr z,L03cc ; Jump for A Invalid argument
cp $15 ;
jr nz,L03cf ; Jump unless M Ramtop no good
L03cc inc (iy+$0d) ; SUBPPC
L03cf ld bc,$0003 ; 01 03 00
ld de,$5c70 ; 11 70 5c
ld hl,$5c44 ; 21 44 5c
bit 7,(hl) ; cb 7e
jr z,L03dd ; 28 01
add hl,bc ; 09
L03dd lddr ; ed b8
L03df ld (iy+$0a),$ff ; fd 36 0a ff
res 3,(iy+$01) ; fd cb 01 9e
ld hl,$5b66 ; 21 66 5b
res 0,(hl) ; cb 86
jp L25cb ; c3 cb 25
L03ef ld a,$10 ; 3e 10
ld bc,$0000 ; 01 00 00
jp L034e ; c3 4e 03
L03f7 ld ($5c49),bc ; ed 43 49 5c
call L1f45 ; cd 45 1f
ld a,b ; 78
or c ; b1
jr z,L040a ; 28 08
ld ($5c49),bc ; ed 43 49 5c
ld ($ec08),bc ; ed 43 08 ec
L040a call L1f20 ; cd 20 1f
ld hl,($5c5d) ; 2a 5d 5c
ex de,hl ; eb
ld hl,$03ef ; 21 ef 03
push hl ; e5
ld hl,($5c61) ; 2a 61 5c
scf ; 37
sbc hl,de ; ed 52
push hl ; e5
ld h,b ; 60
ld l,c ; 69
rst 28h ; ef
.word $196e ; LINE-ADDR
jr nz,L0429 ; 20 06
rst 28h ; ef
.word $19b8 ; NEXT-ONE
rst 28h ; ef
.word $19e8 ; RECLAIM-2
L0429 pop bc ; c1
ld a,c ; 79
dec a ; 3d
or b ; b0
jr nz,L0442 ; 20 13
call L1f45 ; cd 45 1f
push hl ; e5
ld hl,($5c49) ; 2a 49 5c
call L334a ; cd 4a 33
ld ($5c49),hl ; 22 49 5c
pop hl ; e1
call L1f20 ; cd 20 1f
jr L046a ; 18 28
L0442 push bc ; c5
inc bc ; 03
inc bc ; 03
inc bc ; 03
inc bc ; 03
dec hl ; 2b
ld de,($5c53) ; ed 5b 53 5c
push de ; d5
rst 28h ; ef
.word $1655 ; MAKE-ROOM
pop hl
ld ($5c53),hl ; 22 53 5c
pop bc ; c1
push bc ; c5
inc de ; 13
ld hl,($5c61) ; 2a 61 5c
dec hl ; 2b
dec hl ; 2b
lddr ; ed b8
ld hl,($5c49) ; 2a 49 5c
ex de,hl ; eb
pop bc ; c1
ld (hl),b ; 70
dec hl ; 2b
ld (hl),c ; 71
dec hl ; 2b
ld (hl),e ; 73
dec hl ; 2b
ld (hl),d ; 72
L046a pop af ; f1
ret ; c9
; Pointers into the new error message table
L046c .word $048c, $0497, $04a6, $04b0, $04c1
.word $04d4, $04e0, $04e0, $04f3, $0501
.word $0512, $0523, $0531, $0542, $054e, $0561
L048c .text "MERGE erro"
.byte 'r'+$80
.text "Wrong file typ"
.byte 'e'+$80
.text "CODE erro"
.byte 'r'+$80
.text "Too many bracket"
.byte 's'+$80
.text "File already exist"
.byte 's'+$80
.text "Invalid nam"
.byte 'e'+$80
.text "File does not exis"
.byte 't'+$80
.text "Invalid devic"
.byte 'e'+$80
.text "Invalid baud rat"
.byte 'e'+$80
.text "Invalid note nam"
.byte 'e'+$80
.text "Number too bi"
.byte 'g'+$80
.text "Note out of rang"
.byte 'e'+$80
.text "Out of rang"
.byte 'e'+$80
.text "Too many tied note"
.byte 's'+$80
L0561 .byte $7f ; copyright sign
.text " 1986 Sinclair Research Lt"
.byte 'd'+$80
; Print a message which is terminated by having bit 7 set
L057d ld a,(de) ;
and $7f ;
push de ;
rst 10h ;
pop de ;
ld a,(de) ;
inc de ;
add a,a ;
jr nc,L057d ;
ret ;
; 21-byte table used at 01dd (channel information)
L0589 .byte $f4,$09,$a8,$10,$4b,$f4,$09,$c4
.byte $15,$53,$81,$0f,$c4,$15,$52,$34
.byte $5b,$2f,$5b,$50,$80
; 14-byte table used at L0226 (stream information)
L059e .byte $01,$00,$06,$00,$0b,$00,$01,$00
.byte $01,$00,$06,$00,$10,$00
; Cause error report
L05ac pop hl ; e1
ld bc,$7ffd ; 01 fd 7f
xor a ; af
di ; f3
ld ($5b5c),a ; 32 5c 5b
out (c),a ; ed 79
ei ; fb
ld sp,($5c3d) ; ed 7b 3d 5c
ld a,(hl) ; 7e
ld ($5b5e),a ; 32 5e 5b
inc a ; 3c
cp $1e ; fe 1e
jr nc,L05c8 ; 30 03
rst 28h ; ef
.word $5b5d
L05c8 dec a ; 3d
ld (iy+$00),a ; fd 77 00
ld hl,($5c5d) ; 2a 5d 5c
ld ($5c5f),hl ; 22 5f 5c
rst 28h ; ef
.word $16c5 ; SET-STK
ret
; Check for BREAK
L05d6 ld a,$7f ; 3e 7f
in a,($fe) ; db fe
rra ; 1f
ret c ; d8
ld a,$fe ; 3e fe
in a,($fe) ; db fe
rra ; 1f
ret c ; d8
call L05ac ; cd ac 05
.byte $14 ; "L Break into program"
L05e6 ei ; fb
ex af,af' ; 08
ld de,$5b4a ; 11 4a 5b
push de ; d5
res 3,(iy+$02) ; fd cb 02 9e
push hl ; e5
ld hl,($5c3d) ; ERR SP
ld e,(hl) ;
inc hl ;
ld d,(hl) ; DE = current error address
and a ;
ld hl,$107f ; HL= ED-ERROR
sbc hl,de ;
jr nz,L0637 ;
pop hl ;
ld sp,($5c3d) ;
pop de ;
pop de ;
ld ($5c3d),de ;
L060a push hl ;
ld de,$0610 ; Address to return to
push de ; Stack address
jp (hl) ; Jump to ... ?
L0610 jr c,L061b ; 38 09
jr z,L0618 ; 28 04
L0614 call L05ac ;
.byte $07 ; "8 End of file"
L0618 pop hl ; e1
jr L060a ; 18 ef
L061b cp $0d ; fe 0d
jr z,L062d ; 28 0e
ld hl,($5b5a) ; 2a 5a 5b
push hl ; e5
rst 28h ; ef
add a,l ; 85
rrca ; 0f
pop hl ; e1
ld ($5b5a),hl ; 22 5a 5b
pop hl ; e1
jr L060a ; 18 dd
L062d pop hl ; e1
ld a,($5b5c) ; 3a 5c 5b
or $10 ; f6 10
push af ; f5
jp $5b4a ; c3 4a 5b
L0637 pop hl ; e1
ld de,$063d ; Continuation address
push de ; Stack address
jp (hl) ;
L063d ret c ;
ret z ;
jr L0614 ; Report "8 End of file"
; FORMAT routine
L0641 rst 28h ; [Could just RST 18]
.word $0018
rst 28h ; Get an expression
.word EXPT_EXP
bit 7,(iy+$01) ;
jr z,L0661 ; Jump ahead if syntax checking
rst 28h ;
.word STK_FETCH
ld a,c ;
dec a ;
or b ;
jr z,L0659 ; Jump ahead if string is 1 character long
call L05ac ; Otherwise, error
.byte $24 ; "i Invalid device"
L0659 ld a,(de) ; Get character
and $df ; Convert to upper case
cp $50 ; Is it channel "P"?
jp nz,L1912 ; Error "C Nonsense in BASIC" if not
L0661 ld hl,($5c5d) ; (CH ADD), next character
ld a,(hl) ;
cp $3b ; Next character must be ";"
jp nz,L1912 ; Otherwise error C
rst 28h ; Skip past the ; character
.word $0020 ; [Could just do RST 20]
rst 28h ; Get a numeric expression from the line
.word $1c82 ; EXPT-1NUM
bit 7,(iy+$01) ; Jump ahead if syntax checking
jr z,L067d ;
rst 28h ; Get the result as an integer
.word $1e99 ; FIND-INT2
ld ($5b71),bc ; Store the result in the system variables
L067d rst 28h ; [Could just do RST 18]
.word $0018 ; Get the next character in the BASIC line;
cp $0d ; should be ENTER...
jr z,L0689 ;
cp $3a ; or ":",
jp nz,L1912 ; otherwise error C
L0689 call L18a1 ; Check for end of line
ld bc,($5b71) ; Get the baud rate
ld a,b ; Is it zero?
or c ;
jr nz,L0698 ;
call L05ac ; If so, then report error
.byte $25 ; "j invalid baud rate"
L0698 ld hl,L06b8 ; Table of known baud rates
L069b ld e,(hl) ;
inc hl ;
ld d,(hl) ;
inc hl ;
ex de,hl ; HL = known baud rate
ld a,h ; If we have reached the last item in the table without
cp $25 ; using a baud rate, then use this one (9600)
jr nc,L06af ;
and a ;
sbc hl,bc ; Use this baud rate?
jr nc,L06af ;
ex de,hl ;
inc hl ; Skip past the internal value used
inc hl ; for the baud rate
jr L069b ;
L06af ex de,hl ; HL points to internal representation
ld e,(hl) ;
inc hl ;
ld d,(hl) ; DE holds internal representation (T states/26 according to +3 manual)
ld ($5b5f),de ; Store new value in BAUD SYS_VAR
ret ; Finish
; BAUD_RATE_TABLE
L06b8 .word $0032,$0aa5
.word $006e,$04d4
.word $012c,$01c3
.word $0258,$00e0
.word $04b0,$006e
.word $0960,$0036
.word $12c0,$0019
.word $2580,$000b
; RS232 input
L06d8 ld hl,$5b61 ; hl= SERFL SYS_VAR keeps second char that can be received
ld a,(hl) ; Is the second-character received flag set,
and a ; i.e. have we already received data?
jr z,L06e5 ; Jump ahead if not.
ld (hl),$00 ; Otherwise clear the flag
inc hl ;
ld a,(hl) ; and return the data which we received earlier.
scf ; Set carry flag to indicate success
ret ;
; BAUD system variable: 23391 ,$5b5f
; Value = (3500000/(25.7*BaudRate))-3
;REC-BYTE routine that handles the receiving of a byte
L06e5 call L05d6 ; Check for BREAK
di
exx
ld de,($5b5f) ;Get BAUD
ld hl,($5b5f)
srl h ; 0 -> 76543210 -> C Halve the value
rr l ; C -> 76543210 -> C
; HL=1/2 BAUD
or a
ld b,$fa ;waiting time for start bit
exx
ld c,$fd
ld d,$ff
ld e,$bf
ld b,d
ld a,$0e
out (c),a ;selects register 14, port I/O of AY
in a,(c)
or $f0 ;%11110000
and $fb ;%11111011
;result=%1111x0xx
ld b,e
out (c),a ; Make CTS (Clear To Send)
ld h,a
L070e ld b,d
in a,(c)
and $80 ;%10000000 ;bit 7- RS232 pin 5 (TXD in)
jr z,L071e ;First test for START BIT - test if it's zero
L0715 exx
dec b
exx
jr nz,L070e
xor a
push af ;(*) Save the zero failure flag
jr L0757 ; time out waiting for START BIT
L071e in a,(c) ;2. Second test - test again to see if it's zero - START BIT
and $80
jr nz,L0715
in a,(c)
and $80 ;3. third test - test again to see if it's zero - START BIT
jr nz,L0715
; ---
; The branch is executed when TXdata was high for 3 tests.
exx
ld bc,$fffd
ld a,$80 ;A stays with START BIT
ex af,af'
L0731 add hl,de ; HL=BAUD +1/2 BAUD
nop ; (4) timing value
nop
nop
nop
;BD-DELAY
L0736 dec hl ; ( 6) Delay for 26 * BAUD
ld a,h ; ( 4)
or l ; ( 4)
jr nz,L0736 ; (12) back to BD-DELAY
in a,(c) ; Read a BIT
and $80
jp z,L074b
ex af,af' ;received one 1
scf ;set carry
rra ; C->76543210->C
jr c,L0754 ;When we reach START BIT it ends
ex af,af'
jp L0731 ;Go read next bit
L074b ex af,af' ;received one 0
or a ;clear carry
rra ; C->76543210->C
jr c,L0754 ;When we reach START BIT it ends
ex af,af'
jp L0731 ;Go read next bit
; After looping eight times, the start bit will pass through and A will
; contain a received byte.
L0754 scf ; signal success.
push af ; (*) push success flag
exx
; The success and failure (TIME OUT START BIT) paths converge here
L0757 ld a,h
or $04
;result=%1111x1xx
ld b,e ;e=$bf
out (c),a ;reset CTS line
exx
ld h,d
ld l,e ; HL = (BAUD)
ld bc,$0007
or a
sbc hl,bc ; HL = (BAUD) - 7
L0766 dec hl ;Delay for stop bit
ld a,h
or l
jr nz,L0766
;hl=0
ld bc,$fffd
add hl,de
add hl,de
add hl,de ;HL = 3 * BAUD
; The device at the other end of the cable may send a second byte even though
; CTS is low. So now repeat the procedure to read another byte
L0771 in a,(c) ;test START BIT
and $80
jr z,L077f
dec hl
ld a,h
or l
jr nz,L0771
pop af ; restore byte and flags
ei ; (either 0 and NC or received byte and carry).
ret
L077f in a,(c) ;performs again 3 tests to START BIT
and $80
jr nz,L0771
in a,(c)
and $80
jr nz,L0771
; A second byte is on its way and is received exactly as before.
ld h,d
ld l,e
ld bc,$0002
srl h
rr l
or a
sbc hl,bc
ld bc,$fffd
ld a,$80
ex af,af'
L079d nop
nop
nop
nop
add hl,de
L07a2 dec hl
ld a,h
or l
jr nz,L07a2
in a,(c)
and $80
jp z,L07b7
ex af,af'
scf
rra
jr c,L07c0
ex af,af'
jp L079d
L07b7 ex af,af'
or a
rra
jr c,L07c0
ex af,af'
jp L079d
L07c0 ld hl,$5b61 ; SERFL: second char ;flag e data
ld (hl),$01
inc hl
ld (hl),a
pop af
ei
ret
; The following has something to do with the LPRINT CHR$ 16; CHR$ 1; "ABC" bug
; (getting here from 063C)
L07ca push af ; A = character to print
ld a,($5b65) ; TVPARS, #parameters expected
or a ;
jr z,L07e0 ;
dec a ;
ld ($5b65),a ;
jr nz,L07db ; Jump ahead if we have not processed all parameters
pop af ;
jp L0872 ; Otherwise...
L07db pop af ;
ld ($5c0f),a ; TVDATA + 1
ret ;
L07e0 pop af ;
cp $a3 ; "SPECTRUM"
jr c,L07f2 ;
ld hl,($5b5a) ; Save RETADDR temporarily
push hl ;
rst 28h ;
.word $0b52 ; PO-T&UDG
pop hl ;
ld ($5b5a),hl ;
scf ;
ret ;
L07f2 ld hl,$5c3b ; FLAGS
res 0,(hl) ;
cp $20 ;
jr nz,L07fd ;
set 0,(hl) ;
L07fd cp $7f ;
jr c,L0803 ; 38 02
ld a,$3f ; 3e 3f
L0803 cp $20 ; fe 20
jr c,L081e ; 38 17
L0807 push af ; f5
ld hl,$5b63 ; COL, column number
inc (hl) ; 34
ld a,($5b64) ; WIDTH
cp (hl) ; be
jr nc,L081a ; 30 08
call L0822 ; cd 22 08
ld a,$01 ; 3e 01
ld ($5b63),a ; 32 63 5b
L081a pop af ; f1
jp L08a3 ; c3 a3 08
L081e cp $0d ; fe 0d
jr nz,L0830 ; 20 0e
L0822 xor a ; af
ld ($5b63),a ; 32 63 5b
ld a,$0d ; 3e 0d
call L08a3 ; cd a3 08
ld a,$0a ; 3e 0a
jp L08a3 ; c3 a3 08
L0830 cp $06 ; fe 06
jr nz,L0853 ; 20 1f
ld bc,($5b63) ; ed 4b 63 5b
ld e,$00 ; 1e 00
L083a inc e ; 1c
inc c ; 0c
ld a,c ; 79
cp b ; b8
jr z,L0848 ; 28 08
L0840 sub $08 ; d6 08
jr z,L0848 ; 28 04
jr nc,L0840 ; 30 fa
jr L083a ; 18 f2
L0848 push de ; d5
ld a,$20 ; 3e 20
call L07ca ; cd ca 07
pop de ; d1
dec e ; 1d
ret z ; c8
jr L0848 ; 18 f5
L0853 cp $16 ; AT
jr z,L0860 ;
cp $17 ; TAB
jr z,L0860 ;
cp $10 ; fe 10
ret c ; d8
jr L0869 ; 18 09
L0860 ld ($5c0e),a ; 32 0e 5c
ld a,$02 ; 3e 02
ld ($5b65),a ; TV_PARS
ret ; c9
L0869 ld ($5c0e),a ;
ld a,$02 ; Should be 1
ld ($5b65),a ;
ret ;
L0872 ld d,a ; D = character to print
ld a,($5c0e) ; TV DATA
cp $16 ;
jr z,L0882 ;
cp $17 ;
ccf ;
ret nz ;
ld a,($5c0f) ; TV DATA + 1
ld d,a ;
L0882 ld a,($5b64) ; WIDTH
cp d ; ba
jr z,L088a ; 28 02
jr nc,L0890 ; 30 06
L088a ld b,a ; 47
ld a,d ; 7a
sub b ; 90
ld d,a ; 57
jr L0882 ; 18 f2
L0890 ld a,d ; 7a
or a ; b7
jp z,L0822 ; ca 22 08
L0895 ld a,($5b63) ; 3a 63 5b
cp d ; ba
ret z ; c8
push de ; d5
ld a,$20 ; 3e 20
call L07ca ; cd ca 07
pop de ; d1
jr L0895 ; 18 f2
; Talk to printer ;OUTPUT SERVICE RS232
L08a3 push af ;A=value to send
ld c,$fd
ld d,$ff
ld e,$bf
ld b,d ;FFFD = Address of the
ld a,$0e ;command register do AY
out (c),a ;chose reg 14 do AY <=> porta I/O
L08af call L05d6 ; Check for BREAK
in a,(c) ;Read status of data register
and $40 ; test DTR - %01000000
jr nz,L08af
ld hl,($5b5f) ;HL = SYS_VAR BAUD
ld de,$0002
or a
sbc hl,de
ex de,hl ;DE=BAUD-2
pop af
cpl ; Invert the bits in the character. (RS232 logic is inverted)
scf ;Carry is used to send START BIT
ld b,$0b ;B= bits= 1 start + 8 data + 2 stop
di
;SEND BITS RS232
L08c8 push bc
push af
ld a,$fe
ld h,d
ld l,e
L08ce ld bc,$bffd ;AY data register
jp nc,L08da ;jp nc,Send_one
;Send_zero
and $f7
out (c),a
jr L08e0
;Send_one
L08da or $08
out (c),a
jr L08e0 ;??????
;Delay Loop BD-DEL Wait 26 * BAUD cycles
L08e0 dec hl ; ( 6)
ld a,h ; ( 4)
or l ; ( 4)
jr nz,L08e0 ; (12)
nop
nop
nop
pop af
pop bc
or a ;clear carry
rra ;C->7xxxxxx0->C
djnz L08c8 ;loops B bits
ei
ret
; COPY routine (continuation)
L08f0 ld hl,$5b72 ; 21 72 5b
ld (hl),$2b ; 36 2b
L08f5 ld hl,L0979 ; Point to data table
call L095f ; Send data to printer (?)
call L0915 ; cd 15 09
ld hl,$0980 ; Point to data table
call L095f ; Send data to printer (?)
ld hl,$5b72 ; 21 72 5b
xor a ; af
cp (hl) ; be
jr z,L090e ; 28 03
dec (hl) ; 35
jr L08f5 ; 18 e7
L090e ld hl,L0982 ; 21 82 09
call L095f ; cd 5f 09
ret ; c9
L0915 ld hl,$5b71 ; 21 71 5b
ld (hl),$ff ; 36 ff
L091a call L0926 ; cd 26 09
ld hl,$5b71 ; 21 71 5b
xor a ; af
cp (hl) ; be
ret z ; c8
dec (hl) ; 35
jr L091a ; 18 f4
L0926 ld de,$c000 ; 11 00 c0
ld bc,($5b71) ; ed 4b 71 5b
scf ; 37
rl b ; cb 10
scf ; 37
rl b ; cb 10
ld a,c ; 79
cpl ; 2f
ld c,a ; 4f
xor a ; af
push af ; f5
push de ; d5
push bc ; c5
L093a call L096d ; Test whether pixel (B,C) is set
pop bc ; c1
pop de ; d1
ld e,$00 ; 1e 00
jr z,L0944 ; 28 01
ld e,d ; 5a
L0944 pop af ; f1
or e ; b3
push af ; f5
dec b ; 05
srl d ; cb 3a
srl d ; cb 3a
push de ; d5
push bc ; c5
jr nc,L093a ; 30 ea
pop bc ; c1
pop de ; d1
pop af ; f1
ld b,$03 ; 06 03
L0955 push bc ; c5
push af ; f5
call L08a3 ; cd a3 08
pop af ; f1
pop bc ; c1
djnz L0955 ; 10 f7
ret ; c9
L095f ld b,(hl) ; Get number of bytes
inc hl ;
L0961 ld a,(hl) ; Retrieve value
push hl ;
push bc ;
call L08a3 ; Send to printer?
pop bc ; c1
pop hl ; e1
inc hl ; 23
djnz L0961 ; 10 f5
ret ; c9
; Test whether the pixel (B,C) is set or not
; If the pixel is reset, returns with A=0
; If the pixel is set, returns with A>0
; (actually the value of the bit corresponding to the pixel within the byte)
L096d rst 28h ; Get address of (B,C) pixel into HL/A
.word $22aa ; PIXEL-ADDR
ld b,a ; B=pixel position within byte (0-7)
inc b ;
xor a ;
scf ; Set bit to be rotated into A
L0974 rra ; Rotate...
djnz L0974 ; ... and repeat
and (hl) ; Isolate this pixel from A
ret ;
; Some data used in COPY
L0979 .byte $06,$1b,$31,$1b,$4c,$00,$03
; Some more data
L0980 .byte $01,$0a
; A bit more data
L0982 .byte $02,$1b,$32
; ** THE PLAY SUBROUTINES **
; Reserve and intialise space for PLAY data. B = the number of strings
; in the PLAY command. There is a block of $003c bytes allocated (IY
; points to this) plus $0037 bytes for each string used
; (IX is used to point to the current channel).
;
; IY data block:
; (IY+$00, IY+$01) points to data for channel 0
; (IY+$02, IY+$03) points to data for channel 1
; ...
; (IY+$10) gets initialised to 0ffh and RLed for each string;
; i.e. it ends up with the least-significant 'n' bits reset
; if there are n strings provided to the PLAY command
; ...
; (IY+$27;$28) holds the tempo
; (IY+$29) effect value
; (IY+$2B...$37) (for 13d bytes) gets initialised to values from L0a31
; When referring to a channel, the following values are used:
; (ix+$01) = MIDI channel
; (ix+$02) = index of string within PLAY command
; (ix+$03) = 12 * current octave number
; (ix+$04) = current volume
; (ix+$06,$07) = current position in string
; (ix+$08,$09) = 1 after end position
; (ix+$0a) = flags (only lowest bit used?)
; (ix+$0b) = current bracket nesting level
; (ix+$0e,$0f) = stored bracket return positions
; (ix+$10,$11) = stored bracket return positions
; (ix+$12,$13) = stored bracket return positions
; (ix+$14,$15) = stored bracket return positions
; (ix+$16) = ??? initialised to FF
; (ix+$17) = ??? initialised to 00
; (ix+$18) = ??? initialised to 00
; ... ?
; (ix+$21) = counter of tied notes
L0985 di
push bc
ld de,$0037 ; Calculate HL = $003C + $0037 * B
ld hl,$003c ;
L098d add hl,de ;
djnz L098d ;
ld c,l ;
ld b,h ; BC = space required
rst 28h ;
.word $0030 ; Make BC bytes of space in the workspace.
di ;
push de ;
pop iy ; IY = first new byte
push hl ;
pop ix ; IX = last new byte
ld (iy+$10),$ff ; Initial value meaning 'zero strings'
; Loop over each string to be played
L09a0 ld bc,$ffc9 ; $-37
add ix,bc ; IX points to start of space for last channel
ld (ix+$03),$3c ; Default octave is 4
ld (ix+$01),$ff ;
ld (ix+$04),$0f ; Default volume is 15
ld (ix+$05),$05 ;
ld (ix+$21),$00 ;
ld (ix+$0a),$00 ;
ld (ix+$0b),$00 ; Initial bracket nesting level
ld (ix+$16),$ff ;
ld (ix+$17),$00 ;
ld (ix+$18),$00 ;
rst 28h ; Get the details of the string from the stack
.word STK_FETCH
di ;
ld (ix+$06),e ; Store the start of the string as
ld (ix+$07),d ; the current position
ld (ix+$0c),e ;
ld (ix+$0d),d ;
ex de,hl ;
add hl,bc ;
ld (ix+$08),l ; Store the address of the character just
ld (ix+$09),h ; after the string
pop bc ; Restore B=current string index
push bc ; and save it again
dec b ;
ld c,b ;
ld b,$00 ;
sla c ; BC=string index*2
push iy ;
pop hl ;
add hl,bc ; HL
push ix ;
pop bc ; BC=pointer to data for this channel
ld (hl),c ; Store point
inc hl ;
ld (hl),b ;
or a ;
rl (iy+$10) ; Rotate one zero-bit into the least significant bit of
; (iy+$10). Once this loop is over, this byte is one
; zero bit for each string parameter to the PLAY command.
pop bc ; Restore B=current string index
dec b ; Decrement string index
push bc ; and save it for future use
ld (ix+$02),b ; Set index of string
jr nz,L09a0 ; Jump back while more channels
pop bc ;
L0a05 ld (iy+$27),$1a ; Initialise tempo
ld (iy+$28),$0b ;
push iy ;
pop hl ;
ld bc,$002b ;
add hl,bc ;
ex de,hl ; DE=main data area + $2b bytes
ld hl,L0a31 ; data area in ROM
ld bc,$000d ;
ldir ; Copy 13 bytes
ld d,$07 ; Set sound chip register 07 to $f8
ld e,$f8 ; ("Mixer")
call L0e7c ;
ld d,$0b ; Set register $0b to $ff
ld e,$ff ; ("Envelope fine duration")
call L0e7c ;
inc d ; Set register $0c to $ff
call L0e7c ; ("Envelope coarse duration")
jr L0a7d ; Jump forwards
; 13 bytes of data (initial PLAY data)
L0a31 .byte $ef,$a4,$01,$05,$34,$df,$75,$f4
.byte $38,$75,$05,$38,$c9
; Test for BREAK (returns with carry clear if BREAK is pressed)
L0a3e ld a,$7f ;
in a,($fe) ;
rra ;
ret c ; Return with C set if SPACE not pressed
ld a,$fe ;
in a,($fe) ;
rra ;
ret ; Return with C set if CAPS not pressed
L0a4a ld bc,$0011 ; 01 11 00
jr L0a52 ; 18 03
; Set up some PLAY data ??
L0a4f ld bc,$0000 ; 01 00 00
L0a52 push iy ; fd e5
pop hl ; e1
add hl,bc ; 09
ld (iy+$23),l ; fd 75 23
ld (iy+$24),h ; fd 74 24
ld a,(iy+$10) ; fd 7e 10
ld (iy+$22),a ; fd 77 22
ld (iy+$21),$01 ; fd 36 21 01
ret ; c9
; Get IX (channel data pointer) from the bytes at (HL, HL+1)
L0a67 ld e,(hl) ;
inc hl ;
ld d,(hl) ;
push de ;
pop ix ;
ret ;
; Increase the pointer at (iy+$23;iy+$24) by two
; (??? What is this pointer?)
L0a6e ld l,(iy+$23) ; fd 6e 23
ld h,(iy+$24) ; fd 66 24
inc hl ; 23
inc hl ; 23
ld (iy+$23),l ; fd 75 23
ld (iy+$24),h ; fd 74 24
ret ; c9
; Continuation of the PLAY code
L0a7d call L0a4f ; Set up some data (leaves with HL=IY)
L0a80 rr (iy+$22) ; fd cb 22 1e
jr c,L0a8c ; 38 06
call L0a67 ; Get IX from (HL;HL+1)
call L0b5c ; Process the PLAY string for this channel
L0a8c sla (iy+$21) ; fd cb 21 26
jr c,L0a97 ; 38 05
call L0a6e ; cd 6e 0a
jr L0a80 ; 18 e9
L0a97 call L0f91 ; cd 91 0f
push de ; d5
call L0f42 ; cd 42 0f
pop de ; d1
L0a9f ld a,(iy+$10) ;
cp $ff ; $ff means nothing to PLAY
jr nz,L0aab ; 20 05
call L0e93 ; cd 93 0e
ei ; fb
ret ; c9
L0aab dec de ; 1b
call L0f76 ; cd 76 0f
call L0fc1 ; cd c1 0f
call L0f91 ; cd 91 0f
jr L0a9f ; 18 e8
; Recognised characters in PLAY commands
L0ab7 .text "HZYXWUVMT)(NO!"
; Get the current character from the PLAY string and increment the pointer
L0ac5 call L0ee3 ; Get the current character
ret c ; Return if error condition
inc (ix+$06) ; Increment the low byte of the pointer
ret nz ;
inc (ix+$07) ; ... and the high byte if necessary
ret ;
; Return A=number of semitones above C for the next note in the string,
; or A=$80 for a rest
L0ad1 push hl ; Save HL
ld c,$00 ; Default is for a 'natural' note; ie no adjustment
L0ad4 call L0ac5 ; Get the current character from the PLAY string
jr c,L0ae1 ; Jump if error condition
cp $26 ; "&" (rest)
jr nz,L0aec ; Jump ahead if not
ld a,$80 ;
L0adf pop hl ; Restore HL
ret ; and return
L0ae1 ld a,(iy+$21) ; fd 7e 21
or (iy+$10) ; fd b6 10
ld (iy+$10),a ; fd 77 10
jr L0adf ; 18 f3
L0aec cp $23 ; "#" (sharpen)
jr nz,L0af3 ;
inc c ; +1 semitone
jr L0ad4 ;
L0af3 cp $24 ; "$" (flatten)
jr nz,L0afa ;
dec c ; -1 semitone
jr L0ad4 ;
L0afa bit 5,a ;
jr nz,L0b04 ; Jump ahead if lower case
push af ;
ld a,$0c ; Increase A by an octave
add a,c ; by adding 12 semitones to C
ld c,a ;
pop af ;
L0b04 and $df ; Make sure upper-case
sub $41 ; Convert "A" -> 0, "G"->6
jp c,L0f22 ; jump if error
cp $07 ;
jp nc,L0f22 ; jump if error
push bc ;
ld b,$00 ;
ld c,a ; BC represents the note, 0="a", 6="g"
ld hl,L0df9 ; Lookup table
add hl,bc ; HL=pointer to look up table
ld a,(hl) ; Get A=number of semitones above the note C
pop bc ; Restore BC
add a,c ; Adjust for sharp/flat
pop hl ; Restore HL
ret ;
; Get a numeric value from a PLAY string into BC
L0b1d push hl ;
push de ;
ld l,(ix+$06) ; Get the pointer into
ld h,(ix+$07) ; the PLAY string
ld de,$0000 ; Initialise result to 0
L0b28 ld a,(hl) ;
cp $30 ; Is character numeric?
jr c,L0b45 ;
cp $3a ;
jr nc,L0b45 ;
inc hl ; Got a numeric digit
push hl ;
call L0b50 ; Multiply result so far by 10
sub $30 ; Convert ASCII digit to numeric value
ld h,$00 ;
ld l,a ;
add hl,de ; Increase result so far by the value
jr c,L0b42 ; Error on overflow
ex de,hl ; Result into DE
pop hl ; Retrieve pointer into string
jr L0b28 ; Loop back
L0b42 jp L0f1a ; Jump to generate error "l number too big"
L0b45 ld (ix+$06),l ; Update pointer into
ld (ix+$07),h ; PLAY string
push de ; Result into BC
pop bc ;
pop de ; Restore DE, HL
pop hl ;
ret ;
; Multiply DE by 10
L0b50 ld hl,$0000 ; Do HL=10*DE
ld b,$0a ;
L0b55 add hl,de ;
jr c,L0b42 ; Error if overflow
djnz L0b55 ;
ex de,hl ; Result into DE
ret ;
L0b5c call L0a3e ; Test for BREAK
jr c,L0b69 ; Jump ahead if not pressed
call L0e93 ; Reset sound registers
ei ;
call L05ac ; Generate error
.byte $14 ; "L Break into program"
L0b69 call L0ac5 ; get next character from PLAY string
jp c,L0da2 ; jump if error
call L0df0 ; Test for a recognised PLAY control character
ld b,$00 ;
sla c ; Double the return value
ld hl,L0dca ; Start of lookup table
add hl,bc ; HL points to address for this commmand code
ld e,(hl) ;
inc hl ;
ld d,(hl) ;
ex de,hl ; HL holds address for this command code
call L0b84 ; Call this code
jr L0b5c ; Loop back
ret ; Finish
L0b84 jp (hl) ;
; "!" (comment) command for PLAY
L0b85 call L0ac5 ; get next character from PLAY string
jp c,L0da1 ; error condition
cp $21 ; "!", end-of-comment character
ret z ;
jr L0b85 ;
; "O" (octave) command for PLAY
L0b90 call L0b1d ; Get a numeric value from the string
ld a,c ; There is no check on the high value
cp $09 ; of the value, so O256 works
jp nc,L0f12 ; Error for 9 and above
sla a ; Multiply A by 12
sla a ;
ld b,a ;
sla a ;
add a,b ;
ld (ix+$03),a ; ... and store it
ret ;
; "N" (separator) command for PLAY
L0ba5 ret ; Nothing to do
; "(" command for PLAY
L0ba6 ld a,(ix+$0b) ; Current level of bracket nesting
inc a ;
cp $05 ;
jp z,L0f2a ; "Too many brackets" error
ld (ix+$0b),a ; Store new nesting level
ld de,$000c ;
call L0c27 ; Fetch HL = IX + L000C + 2*A
ld a,(ix+$06) ; Store current position
ld (hl),a ;
inc hl ;
ld a,(ix+$07) ;
ld (hl),a ;
ret ;
; ")" command for PLAY
L0bc2 ld a,(ix+$16) ; dd 7e 16
ld de,$0017 ; 11 17 00
or a ; b7
jp m,L0bf0 ; jump if negative (80..ff)
call L0c27 ; Fetch HL = IX + L0017 + 2*A
ld a,(ix+$06) ; Current position (low byte)
cp (hl) ;
jr nz,L0bf0 ;
inc hl ;
ld a,(ix+$07) ; Current position (high byte)
cp (hl) ; be
jr nz,L0bf0 ; 20 14
dec (ix+$16) ; dd 35 16
ld a,(ix+$16) ; dd 7e 16
or a ; b7
ret p ; f0
bit 0,(ix+$0a) ; dd cb 0a 46
ret z ; c8
ld (ix+$16),$00 ; dd 36 16 00
xor a ; af
jr L0c0b ; 18 1b
L0bf0 ld a,(ix+$16) ; dd 7e 16
inc a ; 3c
cp $05 ; fe 05
jp z,L0f2a ; "d too many brackets"
ld (ix+$16),a ; dd 77 16
call L0c27 ; cd 27 0c
ld a,(ix+$06) ; dd 7e 06
ld (hl),a ; 77
inc hl ; 23
ld a,(ix+$07) ; dd 7e 07
ld (hl),a ; 77
ld a,(ix+$0b) ; Level of bracket nesting
L0c0b ld de,$000c ;
call L0c27 ; HL = IX + L000c + 2*A
ld a,(hl) ; Retrieve low byte of stored position
ld (ix+$06),a ; and set the current position
inc hl ;
ld a,(hl) ; Same for the high byte
ld (ix+$07),a ;
dec (ix+$0b) ; Decrement level of bracket nesting
ret p ; f0
ld (ix+$0b),$00 ; dd 36 0b 00
set 0,(ix+$0a) ; dd cb 0a c6
ret ; c9
; Get HL = IX + DE + 2*A
L0c27 push ix ; dd e5
pop hl ; e1
add hl,de ; 19
ld b,$00 ; 06 00
ld c,a ; 4f
sla c ; cb 21
add hl,bc ; 09
ret ; c9
; "T" (tempo) command for PLAY
L0c32 call L0b1d ; Get numeric value into BC
ld a,b ;
or a ;
jp nz,L0f12 ; Error if 256 or above
ld a,c ;
cp $3c ;
jp c,L0f12 ; Error if 59 or below
cp $f1 ;
jp nc,L0f12 ; Jump if 241 or above
ld a,(ix+$02) ; Index of current string
or a ;
ret nz ; T commands have to be specified in string 0
ld b,$00 ; [B is already zero]
push bc ;
pop hl ;
add hl,hl ;
add hl,hl ; HL = tempo * 4
push hl ;
pop bc ; BC = tempo * 4
push iy ;
rst 28h ;
.word $2d2b ; STACK-BC
di ;
pop iy ;
push iy ;
push iy ;
pop hl ; HL = IY
ld bc,$002b ;
add hl,bc ; HL = IY + $002B
ld iy,$5c3a ; Restore IY
push hl ;
ld hl,L0c76 ;
ld ($5b5a),hl ; RETADDR
ld hl,$5b14 ;
ex (sp),hl ;
push hl ;
jp $5b00 ; Eh?
L0c76 di ;
rst 28h ;
.word $2da2 ; FP-TO-BC
di ;
pop iy ;
ld (iy+$27),c ; Store tempo
L0c80 ld (iy+$28),b ;
ret ;
; "M" (channel) command for play
L0c84 call L0b1d ; Get numeric value into BC
ld a,c ; A=(low byte of) value
cp $40 ;
jp nc,L0f12 ; Error n out of range
cpl ;
ld e,a ;
ld d,$07 ; Register 7
call L0e7c ; Value E
ret ;
; V command for PLAY
L0c95 call L0b1d ; Get numeric value
ld a,c ;
cp $10 ; Test against 16
jp nc,L0f12 ; Error for 16 and above
ld (ix+$04),a ; Store volume
ld e,(ix+$02) ; Get index of string
ld a,$08 ;
add a,e ; A = number of string + 8
ld d,a ; D = register to write to
ld e,c ; E = value to write = volume
call L0e7c ; set register
ret ;
; "U" (use volume effect) command for PLAY
L0cad ld e,(ix+$02) ; Get index of string
ld a,$08 ;
add a,e ;
ld d,a ; Register (8+index)
ld e,$1f ;
ld (ix+$04),e ; Store volume of 15
ret ;
; "W" (volume effect specifier) command for PLAY
L0cba call L0b1d ; Get numeric value into BC
ld a,c ; (Discard high byte)
cp $08 ;
jp nc,L0f12 ; Error n out of range
ld b,$00 ;
ld hl,L0de8 ; Lookup table
add hl,bc ; HL points to the value in the table
ld a,(hl) ;
ld (iy+$29),a ; Store new effect value
ret ;
; "X" (duration of volume effect) command for PLAY
L0cce call L0b1d ; Get numeric value into BC
ld d,$0b ;
ld e,c ;
call L0e7c ; Set register 0B to the low byte of the value
inc d ;
ld e,b ;
call L0e7c ; Set register 0C to the high byte of the value
ret ;
; "Y" (MIDI channel) command for PLAY
L0cdd call L0b1d ; Get numeric parameter
ld a,c ;
dec a ; (No check on high byte)
jp m,L0f12 ; Error
cp $10 ;
jp nc,L0f12 ; Error
ld (ix+$01),a ; Store MIDI channel
ret ;
; "Z" (MIDI programming code) command for PLAY
L0cee call L0b1d ; Get numeric value
ld a,c ; A=(low byte of) value
call L11a3 ;
ret ;
; "H" (stop) command for PLAY
L0cf6 ld (iy+$10),$ff ; Indicate 'nothing left to play'
ret ;
; any other command for PLAY (a..g, A..G, 1..12, &, _)
L0cfb call L0e19 ; Test for digit
jp c,L0d81 ; Jump if not digit
call L0dac ; Get HL = IX + L0022
call L0db4 ; Store HL
xor a ;
ld (ix+$21),a ;
call L0ec8 ; Get the previous character
call L0b1d ; Get numeric value
ld a,c ;
or a ;
jp z,L0f12 ; Error if zero
cp $0d ;
jp nc,L0f12 ; Error if 13 or above
cp $0a ;
jr c,L0d32 ; Jump if 1..9
call L0e00 ; Otherwise it's a triplet semi-quaver (10),
; triplet quaver (11) or triplet crotchet (12).
; Look up length (into DE) from table
call L0d74 ; Increment the counter of tied notes
ld (hl),e ; Store the duration value
inc hl ; into (IX+$22, IX+$23)
ld (hl),d ;
L0d28 call L0d74 ; Increment the counter of tied notes
inc hl ;
ld (hl),e ; 73
inc hl ; 23
ld (hl),d ; 72
inc hl ; 23
jr L0d38 ; Jump ahead
L0d32 ld (ix+$05),c ; C=1..9 for the duration of note
call L0e00 ; DE=duration of this note (from lookup table)
L0d38 call L0d74 ; Increment counter of tied notes
L0d3b call L0ee3 ; Get character from this PLAY string
cp $5f ; Is it "_" (indicating a tied note)?
jr nz,L0d6e ; Jump ahead if not
call L0ac5 ; Get next character from the PLAY string
call L0b1d ; then get numeric value
ld a,c ; Fetch the value into A
cp $0a ; Compare with 10d
jr c,L0d5f ; Jump ahead for 1..9 (semiquaver .. semibreve)
L0d4d push hl ; e5
push de ; d5
call L0e00 ; cd 00 0e
pop hl ; e1
add hl,de ; 19
ld c,e ; 4b
ld b,d ; 42
ex de,hl ; eb
pop hl ; e1
ld (hl),e ; 73
inc hl ; 23
ld (hl),d ; 72
ld e,c ; 59
ld d,b ; 50
jr L0d28 ; 18 c9
L0d5f ld (ix+$05),c ; dd 71 05
push hl ; e5
push de ; d5
call L0e00 ; cd 00 0e
pop hl ; e1
add hl,de ; 19
ex de,hl ; eb
pop hl ; e1
L0d6b jp L0d3b ; c3 3b 0d
L0d6e ld (hl),e ; 73
inc hl ; 23
ld (hl),d ; 72
jp L0d9c ; c3 9c 0d
L0d74 ld a,(ix+$21) ; Increment counter of tied notes
inc a ;
cp $0b ;
jp z,L0f3a ; Error "o too many tied notes"
ld (ix+$21),a ; Store incremented counter
ret ;
L0d81 call L0ec8 ; Get the previous character from the string
ld (ix+$21),$01 ;
call L0dac ; Get HL=IX+L0022
call L0db4 ; Store HL
ld c,(ix+$05) ; C = ?
push hl ; [Not necessary]
call L0e00 ; Look up the C'th element of a table
pop hl ; [Not necessary]
ld (hl),e ; 73
inc hl ; 23
ld (hl),d ; 72
jp L0d9c ; c3 9c 0d
L0d9c pop hl ;
inc hl ;
inc hl ;
push hl ;
ret ;
; error
L0da1 pop hl ; e1
L0da2 ld a,(iy+$21) ; fd 7e 21
or (iy+$10) ; fd b6 10
ld (iy+$10),a ; fd 77 10
ret ; c9
; GET HL = IX+$0022 (point to information for next PLAY parameter)
L0dac push ix ; dd e5
pop hl ; e1
ld bc,$0022 ; 01 22 00
add hl,bc ; 09
ret ; c9
; Store HL in (IY + $0011 + 2 * (IX+$02))
L0db4 push hl ; e5
push iy ; fd e5
pop hl ; e1
ld bc,$0011 ; 01 11 00
add hl,bc ; 09
ld b,$00 ; 06 00
ld c,(ix+$02) ; = index of string
sla c ; cb 21
add hl,bc ; HL = IY + $0011 + 2 * (IX+$02)
pop de ; d1
ld (hl),e ; 73
inc hl ; 23
ld (hl),d ; 72
ex de,hl ; eb
ret ; c9
; Addresses for PLAY commands
L0dca .word L0cfb, L0b85, L0b90, L0ba5 ; ! O N
.word L0ba6, L0bc2, L0c32, L0c84 ; ( ) T M
.word L0c95, L0cad, L0cba, L0cce ; V U W X
.word L0cdd, L0cee, L0cf6 ; Y Z H
; Lookup table when using the "W" command in PLAY
L0de8 .byte $00,$04,$0b,$0d
.byte $08,$0c,$0e,$0a
; Test for command characters in PLAY
L0df0 ld bc,$000f ; Number of characters in lookup table
ld hl,L0ab7 ; Start of lookup table
cpir ; Test for character
ret ;
; Data table for PLAY
; Each entry is equivalent to a note of the scale, A...G
; and is the number of semitones above (the note) C
L0df9 .byte $09, $0b, $00, $02, $04, $05, $07
; Get the C'th entry in the table from 0E0C into E
L0e00 push hl ;
ld b,$00 ;
ld hl,$0e0c ;
add hl,bc ;
ld d,$00 ;
ld e,(hl) ;
pop hl ;
ret ;
L0e0c .byte $80,$06,$09,$0c,$12,$18,$24,$30
.byte $48,$60,$04,$08,$10
; Test for a digit; returns with C flag false for a digit
L0e19 cp $30 ; '0' or less?
ret c
cp $3a ; More than '9'?
ccf ;
ret ;
; Play the note A at the current octave
; (A = 0 corresponds to C; A=2 corresponds to D etc.)
L0e20 ld c,a ;
ld a,(ix+$03) ; Octave number * 12
add a,c ;
cp $80 ; fe 80
jp nc,L0f32 ; d2 32 0f
ld c,a ; C = note value
ld a,(ix+$02) ; dd 7e 02
or a ; b7
jr nz,L0e3f ; 20 0e
ld a,c ; 79
cpl ; 2f
and $7f ; e6 7f
srl a ; cb 3f
srl a ; cb 3f
ld d,$06 ; 16 06
ld e,a ; 5f
call L0e7c ;
L0e3f ld (ix+$00),c ; dd 71 00
ld a,(ix+$02) ; dd 7e 02
cp $03 ; fe 03
ret nc ; d0
ld hl,$1096 ; Start of lookup table
ld b,$00 ;
ld a,c ;
sub $15 ;
jr nc,L0e57 ;
ld de,$0fbf ; If 0..$14, use values 0f,bf [the lowest note]
jr L0e5e ;
L0e57 ld c,a ; If $15+...
sla c ;
add hl,bc ; Lookup DE from 1096 + 2 * C
ld e,(hl) ;
inc hl ;
ld d,(hl) ;
L0e5e ex de,hl ; HL = value looked up
ld d,(ix+$02) ; index of string in PLAY command
sla d ; D = 2 * index
ld e,l ; E = 1st byte looked up
call L0e7c ; Set register D to value E
inc d ; Next register
ld e,h ; 2nd byte looked up
call L0e7c ; Set register D to value E
bit 4,(ix+$04) ; dd cb 04 66
ret z ;
ld d,$0d ; Register 13
ld a,(iy+$29) ; Effect value
ld e,a ;
call L0e7c ; Set register
ret ;
; Set sound chip register D to value E
L0e7c push bc ;
ld bc,$fffd ;
out (c),d ;
ld bc,$bffd ;
out (c),e ;
pop bc ;
ret ;
L0e89 push bc ; c5
ld bc,$fffd ; 01 fd ff
out (c),a ; ed 79
in a,(c) ; ed 78
pop bc ; c1
ret ; c9
; Set sound chip register 7 to FF and 8,9,10 to 0
; (resets the registers to their default state)
L0e93 ld d,$07 ; 16 07
ld e,$ff ; 1e ff
call L0e7c ; cd 7c 0e
ld d,$08 ; 16 08
ld e,$00 ; 1e 00
call L0e7c ; cd 7c 0e
inc d ; 14
call L0e7c ; cd 7c 0e
inc d ; 14
call L0e7c ; cd 7c 0e
call L0a4f ; cd 4f 0a
L0eac rr (iy+$22) ; fd cb 22 1e
jr c,L0eb8 ; 38 06
call L0a67 ; cd 67 0a
call L118d ; cd 8d 11
L0eb8 sla (iy+$21) ; fd cb 21 26
jr c,L0ec3 ; 38 05
call L0a6e ; cd 6e 0a
jr L0eac ; 18 e9
L0ec3 ld iy,$5c3a ; fd 21 3a 5c
ret ; c9
; Get the previous character from the PLAY string (excluding SPACE/ENTER)
L0ec8 push hl ;
push de ;
ld l,(ix+$06) ; HL points to PLAY string
ld h,(ix+$07) ;
L0ed0 dec hl ; Point to previous character
ld a,(hl) ;
cp $20 ;
jr z,L0ed0 ; Back again if SPACE...
cp $0d ;
jr z,L0ed0 ; ... or ENTER
ld (ix+$06),l ; Store decremented pointer
ld (ix+$07),h ;
pop de ;
pop hl ;
ret ;
; Get the current character from the PLAY string (skipping SPACE and ENTER)
L0ee3 push hl ;
push de ;
push bc ;
ld l,(ix+$06) ; Get pointer to PLAY string
ld h,(ix+$07) ;
L0eec ld a,h ;
cp (ix+$09) ; Reached end-of-string high byte?
jr nz,L0efb ;
ld a,l ;
cp (ix+$08) ; Reached end-of-string low byte?
jr nz,L0efb ;
scf ; Indicate error
jr L0f05 ;
L0efb ld a,(hl) ; Get character
cp $20 ;
jr z,L0f09 ; Jump ahead to get next character for SPACE...
cp $0d ;
jr z,L0f09 ; ... or for an ENTER character
or a ; Otherwise with Z reset
; (apart from CHR$ 0)
L0f05 pop bc ;
pop de ;
pop hl ;
ret ;
L0f09 inc hl ; 23
ld (ix+$06),l ; dd 75 06
ld (ix+$07),h ; dd 74 07
jr L0eec ; 18 da
L0f12 call L0e93 ; Reset sound registers
ei ;
call L05ac ; Generate error
.byte $29 ; "n Out of range"
L0f1a call L0e93 ; Reset sound chip registers
ei ;
call L05ac ; Generate error
.byte $27 ; "l Number too big"
L0f22 call L0e93 ; Reset sound registers
ei ;
call L05ac ; Generate error
.byte $26 ; "k Invalid note name"
L0f2a call L0e93 ; Reset sound registers
ei ;
call L05ac ; Generate error
.byte $1f ; "d Too many brackets"
L0f32 call L0e93 ; Reset sound registers
ei ;
call L05ac ; Generate error
.byte $28 ; "m Note out of range"
L0f3a call L0e93 ; Reset sound registers
ei ;
call L05ac ; Generate error
.byte $2a ; "o Too many tied notes"
L0f42 call L0a4f ; ??
L0f45 rr (iy+$22) ; fd cb 22 1e
jr c,L0f6c ; 38 21
call L0a67 ; cd 67 0a
call L0ad1 ; Get the next note in the string
cp $80 ; Is it a rest?
jr z,L0f6c ; Jump ahead if so
call L0e20 ; Otherwise play the note
ld a,(ix+$02) ; Get string index (channel)
cp $03 ; Only set volume for channels 0-2
jr nc,L0f69 ;
ld d,$08 ; Find register number
add a,d ;
ld d,a ; D = register = 8 + string index
ld e,(ix+$04) ; Current volume
call L0e7c ; Output volume control
L0f69 call L116e ; cd 6e 11
L0f6c sla (iy+$21) ; fd cb 21 26
ret c ; d8
call L0a6e ; cd 6e 0a
jr L0f45 ; 18 cf
; Wait (during the PLAY command). The duration of the \
; pause is based on the current tempo and the \
; value in DE.
L0f76 push hl ; Save HL
ld l,(iy+$27) ; Get tempo
ld h,(iy+$28) ;
ld bc,$0064 ; BC=100d
or a ;
sbc hl,bc ; HL=tempo-100d
push hl ;
pop bc ; BC=tempo-100d
pop hl ; Restore HL
L0f86 dec bc ; Wait for 'tempo-100' loops
ld a,b ;
or c ;
jr nz,L0f86 ;
dec de ; Repeat 'DE' times
ld a,d ;
or e ;
jr nz,L0f76 ;
ret ;
L0f91 ld de,$ffff ; 11 ff ff
call L0a4a ; cd 4a 0a
L0f97 rr (iy+$22) ; fd cb 22 1e
jr c,L0faf ; 38 12
push de ; d5
ld e,(hl) ; 5e
inc hl ; 23
ld d,(hl) ; 56
ex de,hl ; eb
ld e,(hl) ; 5e
inc hl ; 23
ld d,(hl) ; 56
push de ; d5
pop hl ; e1
pop bc ; c1
or a ; b7
sbc hl,bc ; ed 42
jr c,L0faf ; 38 02
push bc ; c5
pop de ; d1
L0faf sla (iy+$21) ; fd cb 21 26
jr c,L0fba ; 38 05
call L0a6e ; cd 6e 0a
jr L0f97 ; 18 dd
L0fba ld (iy+$25),e ; fd 73 25
ld (iy+$26),d ; fd 72 26
ret ; c9
L0fc1 xor a ; af
ld (iy+$2a),a ; fd 77 2a
call L0a4f ; cd 4f 0a
L0fc8 rr (iy+$22) ; fd cb 22 1e
jp c,L105a ; da 5a 10
call L0a67 ; cd 67 0a
push iy ; fd e5
pop hl ; e1
ld bc,$0011 ; 01 11 00
add hl,bc ; 09
ld b,$00 ; 06 00
ld c,(ix+$02) ; dd 4e 02
sla c ; cb 21
add hl,bc ; 09
ld e,(hl) ; 5e
inc hl ; 23
ld d,(hl) ; 56
ex de,hl ; eb
push hl ; e5
ld e,(hl) ; 5e
inc hl ; 23
ld d,(hl) ; 56
ex de,hl ; eb
ld e,(iy+$25) ; fd 5e 25
ld d,(iy+$26) ; fd 56 26
or a ; b7
sbc hl,de ; ed 52
ex de,hl ; eb
pop hl ; e1
jr z,L0ffc ; 28 05
ld (hl),e ; 73
inc hl ; 23
ld (hl),d ; 72
jr L105a ; 18 5e
L0ffc ld a,(ix+$02) ; dd 7e 02
cp $03 ; fe 03
jr nc,L100c ; 30 09
ld d,$08 ; 16 08
add a,d ; 82
ld d,a ; 57
ld e,$00 ; 1e 00
call L0e7c ; cd 7c 0e
L100c call L118d ; cd 8d 11
push ix ; dd e5
pop hl ; e1
ld bc,$0021 ; 01 21 00
add hl,bc ; 09
dec (hl) ; 35
jr nz,L1026 ; 20 0d
call L0b5c ; cd 5c 0b
ld a,(iy+$21) ; fd 7e 21
and (iy+$10) ; fd a6 10
jr nz,L105a ; 20 36
jr L103d ; 18 17
L1026 push iy ; fd e5
pop hl ; e1
ld bc,$0011 ; 01 11 00
add hl,bc ; 09
ld b,$00 ; 06 00
ld c,(ix+$02) ; dd 4e 02
sla c ; cb 21
add hl,bc ; 09
ld e,(hl) ; 5e
inc hl ; 23
ld d,(hl) ; 56
inc de ; 13
inc de ; 13
ld (hl),d ; 72
dec hl ; 2b
ld (hl),e ; 73
L103d call L0ad1 ; cd d1 0a
ld c,a ; 4f
ld a,(iy+$21) ; fd 7e 21
and (iy+$10) ; fd a6 10
jr nz,L105a ; 20 11
ld a,c ; 79
cp $80 ; fe 80
jr z,L105a ; 28 0c
call L0e20 ; cd 20 0e
ld a,(iy+$21) ; fd 7e 21
or (iy+$2a) ; fd b6 2a
ld (iy+$2a),a ; fd 77 2a
L105a sla (iy+$21) ; fd cb 21 26
jr c,L1066 ; 38 06
call L0a6e ; cd 6e 0a
jp L0fc8 ; c3 c8 0f
L1066 ld de,$0001 ; 11 01 00
call L0f76 ; cd 76 0f
call L0a4f ; cd 4f 0a
L106f rr (iy+$2a) ; fd cb 2a 1e
jr nc,L108c ; 30 17
call L0a67 ; cd 67 0a
ld a,(ix+$02) ; String index (channel)
cp $03 ; Only set volume
jr nc,L1089 ; for channels 0-2
L107f ld d,$08 ; Get register number
add a,d ; = 8 + channel
ld d,a ;
ld e,(ix+$04) ; Current volume
call L0e7c ; Set register
L1089 call L116e ; cd 6e 11
L108c sla (iy+$21) ; fd cb 21 26
ret c ; d8
call L0a6e ; cd 6e 0a
jr L106f ; 18 d9
; Lookup table for PLAY; each pair of bytes gives the values of the
; registers for a given note
L1096 .byte $bf,$0f,$dc,$0e,$07,$0e,$3d,$0d,$7f,$0c,$cc,$0b,$22,$0b,$82,$0a
.byte $eb,$09,$5d,$09,$d6,$08,$57,$08,$df,$07,$6e,$07,$03,$07,$9f,$06
.byte $40,$06,$e6,$05,$91,$05,$41,$05,$f6,$04,$ae,$04,$6b,$04,$2c,$04
.byte $f0,$03,$b7,$03,$82,$03,$4f,$03,$20,$03,$f3,$02,$c8,$02,$a1,$02
.byte $7b,$02,$57,$02,$36,$02,$16,$02,$f8,$01,$dc,$01,$c1,$01,$a8,$01
.byte $90,$01,$79,$01,$64,$01,$50,$01,$3d,$01,$2c,$01,$1b,$01,$0b,$01
.byte $fc,$00,$ee,$00,$e0,$00,$d4,$00,$c8,$00,$bd,$00,$b2,$00,$a8,$00
.byte $9f,$00,$96,$00,$8d,$00,$85,$00,$7e,$00,$77,$00,$70,$00,$6a,$00
.byte $64,$00,$5e,$00,$59,$00,$54,$00,$4f,$00,$4b,$00,$47,$00,$43,$00
.byte $3f,$00,$3b,$00,$38,$00,$35,$00,$32,$00,$2f,$00,$2d,$00,$2a,$00
.byte $28,$00,$25,$00,$23,$00,$21,$00,$1f,$00,$1e,$00,$1c,$00,$1a,$00
.byte $19,$00,$18,$00,$16,$00,$15,$00,$14,$00,$13,$00,$12,$00,$11,$00
.byte $10,$00,$0f,$00,$0e,$00,$0d,$00,$0c,$00,$0c,$00,$0b,$00,$0b,$00
.byte $0a,$00,$09,$00,$09,$00,$08,$00
L116e ld a,(ix+$01) ; dd 7e 01
or a ; b7
ret m ; f8
or $90 ; f6 90
call L11a3 ; cd a3 11
ld a,(ix+$00) ; dd 7e 00
call L11a3 ; cd a3 11
ld a,(ix+$04) ; dd 7e 04
res 4,a ; cb a7
sla a ; cb 27
sla a ; cb 27
sla a ; cb 27
call L11a3 ; cd a3 11
ret ; c9
L118d ld a,(ix+$01) ; dd 7e 01
or a ; b7
ret m ; f8
or $80 ; f6 80
call L11a3 ; cd a3 11
ld a,(ix+$00) ; dd 7e 00
call L11a3 ; cd a3 11
ld a,$40 ; 3e 40
call L11a3 ; cd a3 11
ret ; c9
L11a3 ld l,a ; 6f
ld bc,$fffd ; 01 fd ff
ld a,$0e ; 3e 0e
out (c),a ; ed 79
ld bc,$bffd ; 01 fd bf
ld a,$fa ; 3e fa
out (c),a ; ed 79
ld e,$03 ; 1e 03
L11b4 dec e ; 1d
jr nz,L11b4 ; 20 fd
nop ; 00
nop ; 00
nop ; 00
nop ; 00
ld a,l ; 7d
ld d,$08 ; 16 08
L11be rra ; 1f
ld l,a ; 6f
jp nc,L11c9 ; d2 c9 11
ld a,$fe ; 3e fe
out (c),a ; ed 79
jr L11cf ; 18 06
L11c9 ld a,$fa ; 3e fa
out (c),a ; ed 79
jr L11cf ; 18 00
L11cf ld e,$02 ; 1e 02
L11d1 dec e ; 1d
jr nz,L11d1 ; 20 fd
nop ; 00
add a,$00 ; c6 00
ld a,l ; 7d
dec d ; 15
jr nz,L11be ; 20 e3
nop ; 00
nop ; 00
add a,$00 ; c6 00
nop ; 00
nop ; 00
ld a,$fe ; 3e fe
out (c),a ; ed 79
ld e,$06 ; 1e 06
L11e7 dec e ; 1d
jr nz,L11e7 ; 20 fd
ret ; c9
; ** THE TAPE AND RAMDISK OPERATIONS **
; SAVE
L11eb ld hl,$5b66
set 5,(hl) ; Indicate SAVE
jr L1205
; LOAD
L11f2 ld hl,$5b66
set 4,(hl) ; Indicate LOAD
jr L1205
; VERIFY
L11f9 ld hl,$5b66
set 7,(hl) ; Indicate VERIFY
jr L1205
; MERGE
L1200 ld hl,$5b66
set 6,(hl) ; Indicate MERGE
L1205 ld hl,$5b66 ;
res 3,(hl) ; Reset RAMdisk flag
rst 18h ; Get current character
cp $21 ; "!"
jp nz,L13be ;
ld hl,$5b66 ;
set 3,(hl) ; Set RAMdisk flag
rst 20h ; Move on to next character
jp L13be ;
L1219 call L05ac ;
.byte $0b ; "C Nonsense in BASIC"
; RAMDisk operation.
; The information relating to the file is copied into memory in 5B66... \
; to ensure that it is available once other RAM pages are switched in
L121d ld ($5b74),hl ;
ld a,(ix+$00) ; File type
ld ($5b71),a ;
ld l,(ix+$0b) ; HL=length
ld h,(ix+$0c) ;
ld ($5b72),hl ;
ld l,(ix+$0d) ; HL=start address
ld h,(ix+$0e) ;
L1235 ld ($5b78),hl ;
ld l,(ix+$0f) ;
ld h,(ix+$10) ;
ld ($5b76),hl ;
or a ; Test file type
jr z,L124e ; Jump ahead for a BASIC file
cp $03 ;
jr z,L124e ; Jump ahead for a CODE file
ld a,(ix+$0e) ;
ld ($5b76),a ;
L124e push ix ; IX points to file header
pop hl ; Retrieve into HL
inc hl ; HL points to filename
ld de,$5b67 ; Copy to 5B67
ld bc,$000a ;
ldir ;
ld hl,$5b66 ;
bit 5,(hl) ; Set for SAVE
jp nz,L1bad ; Jump ahead if SAVE
ld hl,$5b71 ; Copy the expected details to 5b7a
ld de,$5b7a ;
ld bc,$0007 ;
ldir ;
call L1c2e ; Load header to 5b71
ld a,($5b7a) ; Check that file types match
ld b,a ;
ld a,($5b71) ;
cp b ;
jr nz,L1280 ; Error b if not
cp $03 ; Check for type 3 (CODE)
jr z,L1290 ;
jr c,L1284 ; Only file types 00-02 are OK
L1280 call L05ac ;
.byte $1d ; "b Wrong file type"
L1284 ld a,($5b66) ;
bit 6,a ; Set for MERGE
jr nz,L12c5 ; Jump for MERGE
bit 7,a ; Set for VERIFY
jp z,L12db ;
L1290 ld a,($5b66) ; Flags
bit 6,a ; Set for MERGE
jr z,L129b ; Jump if not MERGE
call L05ac ;
.byte $1c ; "a MERGE error"
L129b ld hl,($5b7b) ; Length requested
ld de,($5b72) ; Length of actual file (don't know when this was set up?)
ld a,h ;
or l ;
jr z,L12ae ; Jump ahead if requested length is 0 (= not specified?)
sbc hl,de ;
jr nc,L12ae ; Jump ahead if requested length is OK
call L05ac ;
.byte $1e ; "c CODE error"
L12ae ld hl,($5b7d)
ld a,h ; 7c
or l ; b5
jr nz,L12b8 ; 20 03
ld hl,($5b74) ; 2a 74 5b
L12b8 ld a,($5b71) ; 3a 71 5b
and a ; a7
jr nz,L12c1 ; 20 03
ld hl,($5c53) ; 2a 53 5c
L12c1 call L137e ; cd 7e 13
ret ; c9
L12c5 ld bc,($5b72) ; ed 4b 72 5b
push bc ; c5
inc bc ; 03
rst 28h ; ef
.word $0030
ld (hl),$80 ; 36 80
ex de,hl ; eb
pop de ; d1
push hl ; e5
call L137e ; cd 7e 13
pop hl ; e1
rst 28h ; ef
.word $08ce ; ME-CONTRL + ?
ret ; c9
L12db ld de,($5b72) ; DE = length
ld hl,($5b7d) ; 2a 7d 5b
push hl ; e5
ld a,h ; 7c
or l ; b5
jr nz,L12ed ; 20 06
inc de ; 13
inc de ; 13
inc de ; 13
ex de,hl ; eb
jr L12f6 ; 18 09
L12ed ld hl,($5b7b) ; 2a 7b 5b
ex de,hl ; eb
scf ; 37
sbc hl,de ; ed 52
jr c,L12ff ; 38 09
L12f6 ld de,$0005 ; 11 05 00
add hl,de ; 19
ld b,h ; 44
ld c,l ; 4d
rst 28h ; ef
.word $1f05 ; TEST-ROOM
L12ff pop hl ; e1
ld a,($5b71) ; 3a 71 5b
L1303 and a ; a7
jr z,L1335 ; 28 2f
ld a,h ; 7c
or l ; b5
jr z,L1315 ; 28 0b
dec hl ; 2b
ld b,(hl) ; 46
dec hl ; 2b
ld c,(hl) ; 4e
dec hl ; 2b
inc bc ; 03
inc bc ; 03
inc bc ; 03
rst 28h ; ef
.word $19e8 ; RECLAIM-2
L1315 ld hl,($5c59) ; 2a 59 5c
dec hl ; 2b
ld bc,($5b72) ; ed 4b 72 5b
push bc ; c5
inc bc ; 03
inc bc ; 03
inc bc ; 03
ld a,($5b7f) ; 3a 7f 5b
push af ; f5
rst 28h ; ef
.word $1655 ; MAKE-ROOM
inc hl
pop af ; f1
ld (hl),a ; 77
pop de ; d1
inc hl ; 23
ld (hl),e ; 73
inc hl ; 23
ld (hl),d ; 72
inc hl ; 23
L1331 call L137e ; cd 7e 13
ret ; c9
L1335 ld hl,$5b66 ; 21 66 5b
res 1,(hl) ; cb 8e
ld de,($5c53) ; ed 5b 53 5c
ld hl,($5c59) ; 2a 59 5c
dec hl ; 2b
rst 28h ; ef
.word $19e5 ; RECLAIM
ld bc,($5b72) ; ed 4b 72 5b
ld hl,($5c53) ; 2a 53 5c
rst 28h ; ef
.word $1655 ; MAKE-ROOM
inc hl
ld bc,($5b76) ; ed 4b 76 5b
add hl,bc ; 09
ld ($5c4b),hl ; 22 4b 5c
ld a,($5b79) ; 3a 79 5b
ld h,a ; 67
and $c0 ; e6 c0
jr nz,L1370 ; 20 10
ld a,($5b78) ; 3a 78 5b
ld l,a ; 6f
ld ($5c42),hl ; 22 42 5c
ld (iy+$0a),$00 ; fd 36 0a 00
ld hl,$5b66 ; 21 66 5b
set 1,(hl) ; cb ce
L1370 ld hl,($5c53) ; 2a 53 5c
ld de,($5b72) ; ed 5b 72 5b
dec hl ; 2b
ld ($5c57),hl ; 22 57 5c
inc hl ; 23
jr L1331 ; 18 b3
L137e ld a,d ; 7a
or e ; b3
ret z ; c8
call L1c4b ; Load bytes
ret ; c9
L1385 rst 28h ; Expecting an expression on the BASIC line
.word EXPT_EXP
bit 7,(iy+$01) ; Return early if syntax-checking
ret z ;
push af ; Get the item off the calculator stack
rst 28h ;
.word STK_FETCH
pop af ;
ret ;
; Called to check a filename for validity and to copy it into a buffer
; starting at 5B67
L1393 rst 20h ; Advance the pointer into the BASIC line
call L1385 ; Get expression from BASIC line
ret z ; Return if syntax checking
push af ;
ld a,c ; Check for zero length
or b ;
jr z,L13ba ; Error f if so
ld hl,$000a ; Check for length > 10
sbc hl,bc ;
jr c,L13ba ; Error f if so
push de ; Stack the filename start...
push bc ; ... and length
ld hl,$5b67 ; HL points to where we will store the filename
ld b,$0a ; Fill it with 10 spaces
ld a,$20 ;
L13ad ld (hl),a ;
inc hl ;
djnz L13ad ;
pop bc ; Restore filename length...
pop hl ; ... and start
ld de,$5b67 ; DE points to where we will store the filename
ldir ; Perform the copy
pop af ; Restore flags
ret ;
L13ba call L05ac ; cd ac 05
.byte $21 ; "f Invalid name"
; SAVE, LOAD, MERGE, VERIFY
L13be rst 28h
.word EXPT_EXP
bit 7,(iy+$01) ;
jr z,L1407 ; Jump ahead if checking syntax
ld bc,$0011 ; Size of header, 17d bytes
ld a,($5c74) ; Effectively the BASIC command
and a ; Is it SAVE?
jr z,L13d2 ; Jump ahead if so
ld c,$22 ; Otherwise need 34d bytes
L13d2 rst 28h ;
.word $0030 ; Create memory in workspace
push de ; Get start of the created memory into IX
pop ix ;
ld b,$0b ; Clear the filename
ld a,$20 ; ' '
L13dc ld (de),a ;
inc de ;
djnz L13dc ;
ld (ix+$01),$ff ;
rst 28h ; Get value from calculator stack
.word STK_FETCH
ld hl,$fff6 ; = -10
dec bc ; 0b
add hl,bc ; 09
inc bc ; 03
jr nc,L1400 ; 30 11
ld a,($5c74) ; Indicates which BASIC command
and a ; Is it SAVE?
jr nz,L13f9 ; Jump ahead if not
call L05ac ; Error report
.byte $0e ; "F Invalid filename"
L13f9 ld a,b
or c ; b1
jr z,L1407 ; 28 0a
ld bc,$000a ; 01 0a 00
L1400 push ix ; dd e5
pop hl ; e1
inc hl ; 23
ex de,hl ; eb
ldir ; ed b0
L1407 rst 18h ; Get character from BASIC line
cp $e4 ; "DATA"
jr nz,L145f ; Jump if not DATA
ld a,($5c74) ; Check the BASIC command
cp $03 ; Is it MERGE?
jp z,L1219 ; "C Nonsense in BASIC" if so
rst 20h ; Get next character from BASIC line
rst 28h ;
.word $28b2 ; LOOK_VARS
jr nc,L142f
ld hl,$0000 ; 21 00 00
bit 6,(iy+$01) ; fd cb 01 76
jr z,L1425 ; 28 02
set 7,c ; cb f9
L1425 ld a,($5c74) ; 3a 74 5c
dec a ; 3d
jr z,L1444 ; 28 19
call L05ac ; Error report
.byte $01 ; "2 Variable not found"
L142f jp nz,L1219 ; "C Nonsense in BASIC"
bit 7,(iy+$01) ; fd cb 01 7e
jr z,L1451 ; 28 19
ld c,(hl) ; 4e
inc hl ; 23
ld a,(hl) ; 7e
ld (ix+$0b),a ; dd 77 0b
inc hl ; 23
ld a,(hl) ; 7e
ld (ix+$0c),a ; dd 77 0c
inc hl ; 23
L1444 ld (ix+$0e),c ; dd 71 0e
ld a,$01 ; 3e 01
bit 6,c ; cb 71
jr z,L144e ; 28 01
inc a ; 3c
L144e ld (ix+$00),a ; dd 77 00
L1451 ex de,hl ; eb
rst 20h ; e7
cp $29 ; fe 29
jr nz,L142f ; 20 d8
rst 20h ; e7
call L18a1 ; cd a1 18
ex de,hl ; eb
jp L1519 ; c3 19 15
L145f cp $aa ; 'SCREEN$' ?
jr nz,L1482 ; Jump ahead if not
ld a,($5c74) ; Check the BASIC command
cp $03 ; Is it MERGE?
jp z,L1219 ; "C Nonsense in BASIC" if so
rst 20h ; Advance pointer into BASIC line
call L18a1 ; Ensure end of statement
ld (ix+$0b),$00 ; Set up length...
ld (ix+$0c),$1b ;
ld hl,$4000 ; ... and start of CODE block
ld (ix+$0d),l ;
ld (ix+$0e),h ;
jr L14cf ;
L1482 cp $af ; 'CODE'?
jr nz,L14d5 ; Jump ahead if not
ld a,($5c74) ; Check the BASIC command
cp $03 ; Is it MERGE?
jp z,L1219 ; "C Nonsense in BASIC" if so
rst 20h ;
rst 28h ;
.word $2048 ; PR-ST-END
jr nz,L14a0
ld a,($5c74) ; 3a 74 5c
and a ; a7
jp z,L1219 ; "C Nonsense in BASIC"
rst 28h ; ef
.word $1ce6 ; USE-ZERO
jr L14af ; 18 0f
L14a0 rst 28h ; ef
.word $1c82 ; EXPT-1NUM
rst 18h ; df
cp $2c ; fe 2c
jr z,L14b4 ; 28 0c
ld a,($5c74) ; 3a 74 5c
and a ; a7
jp z,L1219 ; "C Nonsense in BASIC"
L14af rst 28h ; ef
.word $1ce6 ; USE-ZERO
jr L14b8 ; 18 04
L14b4 rst 20h ; e7
rst 28h ; ef
.word $1c82 ; EXPT-1NUM
L14b8 call L18a1 ; cd a1 18
rst 28h ;
.word $1e99 ; FIND-INT2
ld (ix+$0b),c ; Store the length of the CODE block
ld (ix+$0c),b ;
rst 28h ;
.word $1e99 ; FIND-INT2
ld (ix+$0d),c ; Store the start address of the CODE block
ld (ix+$0e),b ;
ld h,b ; 60
ld l,c ; 69
L14cf ld (ix+$00),$03 ; Store file type = 03 (CODE)
jr L1519 ;
L14d5 cp $ca ; 'LINE'?
jr z,L14e2 ; Jump ahead if so
call L18a1 ; Check for end of statement
ld (ix+$0e),$80 ; Indicate no LINE number
jr L14f9 ;
L14e2 ld a,($5c74) ; Check the BASIC command
and a ; Is it SAVE?
jp nz,L1219 ; "C Nonsense in BASIC" if not
rst 20h ; Advance pointer into BASIC line
rst 28h ; Get LINE number onto calculator stack
.word $1c82 ; EXPT-1NUM
call L18a1 ; Ensure end-of-statement
rst 28h ; Retrieve LINE number from calculator stack
.word $1e99 ; FIND-INT2
ld (ix+$0d),c ; Store LINE number
ld (ix+$0e),b ;
L14f9 ld (ix+$00),$00 ; Store file type = 00
ld hl,($5c59) ; 2a 59 5c
L1500 ld de,($5c53) ; ed 5b 53 5c
scf ; 37
sbc hl,de ; ed 52
ld (ix+$0b),l ; dd 75 0b
ld (ix+$0c),h ; dd 74 0c
ld hl,($5c4b) ; 2a 4b 5c
sbc hl,de ; ed 52
ld (ix+$0f),l ; dd 75 0f
ld (ix+$10),h ; dd 74 10
ex de,hl ; eb
L1519 ld a,($5b66) ; Flags byte
bit 3,a ; RAMdisk bit
jp nz,L121d ; Jump if the operation is on the RAMdisk
ld a,($5c74) ; Otherwise get the BASIC command
and a ; Test for SAVE
jr nz,L152b ; Jump ahead if not
rst 28h ;
.word $0970 ; SA-CONTROL
ret ;
L152b rst 28h ;
.word $0761 ; SA-ALL + ?
ret ;
; called when a line is entered?
L152f ld hl,$eef5 ;
res 0,(hl) ; flag ?
set 1,(hl) ; flag ?
L1536 ld hl,($5c49) ; E PPC - current line number
ld a,h ;
or l ;
jr nz,L1540 ; Jump ahead if not zero
ld ($ec06),hl ; Store in ???
L1540 ld a,($f9db) ;
push af ;
ld hl,($fc9a) ; First line on screen (or 0)
call L334a ; Get address of line number in BASIC,
; or 0 if no such line
ld ($f9d7),hl ;
call L3222 ; copy some bytes
call L30d6 ; around
pop af ;
L1554 or a ; b7
jr z,L1563 ; 28 0c
push af ; f5
call L30df ; cd df 30
ex de,hl ; eb
call L326a ; cd 6a 32
pop af ; f1
dec a ; 3d
jr L1554 ; 18 f1
L1563 ld c,$00 ; first line on screen
call L30b4 ; DE = start of editing line C
ld b,c ; currently indexed editing line
ld a,($ec15) ;
ld c,a ; C=#editing lines on screen
push bc ;
push de ;
L156f call L30df ; cd df 30
ld a,($eef5) ; 3a f5 ee
bit 1,a ; cb 4f
jr z,L1596 ; 28 1d
push de ; d5
push hl ; e5
ld de,$0020 ; 11 20 00
add hl,de ; 19
bit 0,(hl) ; cb 46
jr z,L1594 ; 28 11
inc hl ;
ld d,(hl) ; Get line number into DE
inc hl ;
ld e,(hl) ;
or a ;
ld hl,($5c49) ; E PPC, number of current line
sbc hl,de ;
jr nz,L1594 ; Jump ahead unless this is the current line
ld hl,$eef5 ;
set 0,(hl) ;
L1594 pop hl ; e1
pop de ; d1
L1596 push bc ; c5
push hl ; e5
ld bc,$0023 ; 01 23 00
ldir ; [ this is where the IF n1>n2 corruption initally
; occurs ]
pop hl ; e1
pop bc ; c1
push de ; d5
push bc ; c5
ex de,hl ; eb
ld hl,$eef5 ; 21 f5 ee
bit 0,(hl) ; cb 46
jr z,L15d3 ; 28 2a
ld b,$00 ; 06 00
L15ab ld hl,($ec06) ; 2a 06 ec
ld a,h ; 7c
or l ; b5
jr z,L15c0 ; 28 0e
push hl ; e5
call L2e41 ; cd 41 2e
pop hl ; e1
jr nc,L15cb ; 30 12
dec hl ; 2b
inc b ; 04
ld ($ec06),hl ; 22 06 ec
jr L15ab ; 18 eb
L15c0 call L2e41 ; cd 41 2e
call nc,L2e63 ; d4 63 2e
ld hl,$eef5 ; 21 f5 ee
ld (hl),$00 ; 36 00
L15cb ld a,b ; 78
pop bc ; c1
push bc ; c5
ld c,b ; 48
ld b,a ; 47
call L2a11 ; cd 11 2a
L15d3 pop bc ; c1
pop de ; d1
ld a,c ; 79
inc b ; 04
cp b ; b8
jr nc,L156f ; 30 95
ld a,($eef5) ; 3a f5 ee
bit 1,a ; cb 4f
jr z,L1602 ; 28 21
bit 0,a ; cb 47
jr nz,L1602 ; 20 1d
ld hl,($5c49) ; 2a 49 5c current line number
ld a,h ; 7c
or l ; b5
jr z,L15f4 ; 28 08
ld ($fc9a),hl ; 22 9a fc
L15ef call L3222 ; cd 22 32
jr L15fd ; 18 09
L15f4 ld ($fc9a),hl ; 22 9a fc
call L3352 ; cd 52 33
ld ($5c49),hl ; 22 49 5c
L15fd pop de ; d1
pop bc ; c1
jp L1536 ; c3 36 15
L1602 pop de ; d1
pop bc ; c1
cp a ; Set Z flag
L1605 push af ; f5
ld a,c ; 79
ld c,b ; 48
call L30b4 ; Get address of start of line in editing area
ex de,hl ; ... into HL
L160c push af ;
call L3604 ;
pop af ;
ld de,$0023 ; next line
add hl,de ;
L1615 inc c ;
cp c ;
jr nc,L160c ;
pop af ;
ret z ;
call L2a07 ; cd 07 2a
L161e call L2b78 ; cd 78 2b
ld hl,($ec06) ; 2a 06 ec
dec hl ; 2b
ld a,h ; 7c
or l ; b5
ld ($ec06),hl ; 22 06 ec
jr nz,L161e ; 20 f2
jp L2a11 ; c3 11 2a
ret ; c9
L1630 ld b,$00 ;
ld a,($ec15) ;
ld d,a ; D=#editing lines available
jp L3b5e ;
L1639 ld b,$00 ; 06 00
push hl ; e5
ld c,b ; 48
call L30b4 ; DE = start of editing line C
call L326a ; cd 6a 32
pop hl ; e1
ret nc ; d0
call L30df ; cd df 30
L1648 push bc ; c5
push hl ; e5
ld hl,$0023 ; 21 23 00
add hl,de ; 19
ld a,($ec15) ; 3a 15 ec
ld c,a ; 4f
cp b ; b8
jr z,L1663 ; 28 0e
L1655 push bc ; c5
L1656 push bc ; c5
ld bc,$0023 ; 01 23 00
ldir ; ed b0
pop bc ; c1
ld a,c ; 79
inc b ; 04
cp b ; b8
jr nz,L1656 ; 20 f4
pop bc ; c1
L1663 pop hl ; e1
L1664 call L3618 ; cd 18 36
ld bc,$0023 ; 01 23 00
ldir ; ed b0
scf ; 37
pop bc ; c1
ret ; c9
L166f ld b,$00 ; 06 00
call L322b ; cd 2b 32
ret nc ; d0
L1675 push bc ; c5
push hl ; e5
ld a,($ec15) ; 3a 15 ec
ld c,a ; 4f
call L30b4 ; DE = start of editing line C
call L311e ; cd 1e 31
jr nc,L16a9 ; 30 26
dec de ; 1b
ld hl,$0023 ; 21 23 00
add hl,de ; 19
ex de,hl ; eb
push bc ;