CPU-Z80-Disassembler

 view release on metacpan or  search on metacpan

t/data/zx81.asm  view on Meta::CPAN

; ===========================================================
; An Assembly Listing of the Operating System of the ZX81 ROM
; ===========================================================
; -------------------------
; Last updated: 13-DEC-2004
; -------------------------
;
; Work in progress.
; This file will cross-assemble an original version of the "Improved"
; ZX81 ROM.  The file can be modified to change the behaviour of the ROM
; when used in emulators although there is no spare space available.
;
; The documentation is incomplete and if you can find a copy
; of "The Complete Spectrum ROM Disassembly" then many routines
; such as POINTERS and most of the mathematical routines are
; similar and often identical.
;
; I've used the labels from the above book in this file and also
; some from the more elusive Complete ZX81 ROM Disassembly
; by the same publishers, Melbourne House.



; ================
; ZX-81 MEMORY MAP
; ================


; +------------------+-- Top of memory
; | Reserved area    |
; +------------------+-- (RAMTOP)
; | GOSUB stack      |
; +------------------+-- (ERR_SP)
; | Machine stack    |
; +------------------+-- SP
; | Spare memory     |
; +------------------+-- (STKEND)
; | Calculator stack |
; +------------------+-- (STKBOT)
; | Edit line        |
; +------------------+-- (E_LINE)
; | User variables   |
; +------------------+-- (VARS)
; | Screen           |
; +------------------+-- (D_FILE)
; | User program     |
; +------------------+-- 407Dh (16509d)
; | System variables |
; +------------------+-- 4000h (16384d)


; ======================
; ZX-81 SYSTEM VARIABLES
; ======================

ERR_NR        equ $4000         ; N1   Current report code minus one
FLAGS         equ $4001         ; N1   Various flags
ERR_SP        equ $4002         ; N2   Address of top of GOSUB stack
RAMTOP        equ $4004         ; N2   Address of reserved area (not wiped out by NEW)
MODE          equ $4006         ; N1   Current cursor mode
PPC           equ $4007         ; N2   Line number of line being executed
VERSN         equ $4009         ; N1   First system variable to be SAVEd
E_PPC         equ $400A         ; N2   Line number of line with cursor
D_FILE        equ $400C         ; N2   Address of start of display file
DF_CC         equ $400E         ; N2   Address of print position within display file
VARS          equ $4010         ; N2   Address of start of variables area
DEST          equ $4012         ; N2   Address of variable being assigned
E_LINE        equ $4014         ; N2   Address of start of edit line
CH_ADD        equ $4016         ; N2   Address of the next character to interpret
X_PTR         equ $4018         ; N2   Address of char. preceding syntax error marker
STKBOT        equ $401A         ; N2   Address of calculator stack
STKEND        equ $401C         ; N2   Address of end of calculator stack
BERG          equ $401E         ; N1   Used by floating point calculator
MEM           equ $401F         ; N2   Address of start of calculator's memory area
SPARE1        equ $4021         ; N1   One spare byte
DF_SZ         equ $4022         ; N2   Number of lines in lower part of screen
S_TOP         equ $4023         ; N2   Line number of line at top of screen
LAST_K        equ $4025         ; N2   Keyboard scan taken after the last TV frame
DB_ST         equ $4027         ; N1   Debounce status of keyboard
MARGIN        equ $4028         ; N1   Number of blank lines above or below picture
NXTLIN        equ $4029         ; N2   Address of next program line to be executed
OLDPPC        equ $402B         ; N2   Line number to which CONT/CONTINUE jumps
FLAGX         equ $402D         ; N1   Various flags
STRLEN        equ $402E         ; N2   Information concerning assigning of strings
T_ADDR        equ $4030         ; N2   Address of next item in syntax table
SEED          equ $4032         ; N2   Seed for random number generator
FRAMES        equ $4034         ; N2   Updated once for every TV frame displayed
COORDS        equ $4036         ; N2   Coordinates of last point PLOTed
PR_CC         equ $4038         ; N1   Address of LPRINT position (high part assumed $40)
S_POSN        equ $4039         ; N2   Coordinates of print position
CDFLAG        equ $403B         ; N1   Flags relating to FAST/SLOW mode
PRBUFF        equ $403C         ; N21h Buffer to store LPRINT output
MEMBOT        equ $405D         ; N1E  Area which may be used for calculator memory
SPARE2        equ $407B         ; N2   Two spare bytes
PROG          equ $407D         ; Start of BASIC program

IY0           equ ERR_NR

        org $0000



;*****************************************
;** Part 1. RESTART ROUTINES AND TABLES **
;*****************************************

; -----------
; THE 'START'
; -----------
; All Z80 chips start at location zero.
; At start-up the Interrupt Mode is 0, ZX computers use Interrupt Mode 1.
; Interrupts are disabled .

;; START

START:
        out ($FD), a            ; Turn off the NMI generator if this ROM is
                                ; running in ZX81 hardware. This does nothing
                                ; if this ROM is running within an upgraded
                                ; ZX80.
        ld bc, $7FFF            ; Set BC to the top of possible RAM.
                                ; The higher unpopulated addresses are used for
                                ; video generation.
        jp RAM_CHECK            ; Jump forward to RAM-CHECK.
                                ; 

; -------------------
; THE 'ERROR' RESTART
; -------------------
; The error restart deals immediately with an error. ZX computers execute the
; same code in runtime as when checking syntax. If the error occurred while
; running a program then a brief report is produced. If the error occurred
; while entering a BASIC line or in input etc., then the error marker indicates
; the exact point at which the error lies.

;; ERROR-1

ERROR_1:
        ld hl, (CH_ADD)         ; fetch character address from CH_ADD.
        ld (X_PTR), hl          ; and set the error pointer X_PTR.
        jr ERROR_2              ; forward to continue at ERROR-2.
                                ; 

; -------------------------------
; THE 'PRINT A CHARACTER' RESTART
; -------------------------------
; This restart prints the character in the accumulator using the alternate
; register set so there is no requirement to save the main registers.
; There is sufficient room available to separate a space (zero) from other
; characters as leading spaces need not be considered with a space.

;; PRINT-A

PRINT_A:
        and a                   ; test for zero - space.
        jp nz, PRINT_CH         ; jump forward if not to PRINT-CH.
                                ; 
        jp PRINT_SP             ; jump forward to PRINT-SP.
                                ; 
                                ; ---
                                ; 

        defb $FF                ; unused location.
                                ; 
; ---------------------------------
; THE 'COLLECT A CHARACTER' RESTART
; ---------------------------------
; The character addressed by the system variable CH_ADD is fetched and if it
; is a non-space, non-cursor character it is returned else CH_ADD is
; incremented and the new addressed character tested until it is not a space.

;; GET-CHAR

GET_CHAR:
        ld hl, (CH_ADD)         ; set HL to character address CH_ADD.
        ld a, (hl)              ; fetch addressed character to A.
                                ; 
;; TEST-SP

TEST_SP:
        and a                   ; test for space.
        ret nz                  ; return if not a space
                                ; 
        nop                     ; else trickle through
        nop                     ; to the next routine.
                                ; 
; ------------------------------------
; THE 'COLLECT NEXT CHARACTER' RESTART
; ------------------------------------
; The character address in incremented and the new addressed character is
; returned if not a space, or cursor, else the process is repeated.

;; NEXT-CHAR

NEXT_CHAR:
        call CH_ADD_1           ; routine CH-ADD+1 gets next immediate
                                ; character.
        jr TEST_SP              ; back to TEST-SP.
                                ; 

; ---

        defb $FF, $FF, $FF      ; unused locations.
                                ; 
; ---------------------------------------
; THE 'FLOATING POINT CALCULATOR' RESTART
; ---------------------------------------
; this restart jumps to the recursive floating-point calculator.
; the ZX81's internal, FORTH-like, stack-based language.
;
; In the five remaining bytes there is, appropriately, enough room for the
; end-calc literal - the instruction which exits the calculator.

;; FP-CALC

FP_CALC:
        jp CALCULATE            ; jump immediately to the CALCULATE routine.
                                ; 

; ---

;; end-calc

end_calc:
        pop af                  ; drop the calculator return address RE-ENTRY
        exx                     ; switch to the other set.
                                ; 
        ex (sp), hl             ; transfer H'L' to machine stack for the
                                ; return address.
                                ; when exiting recursion then the previous
                                ; pointer is transferred to H'L'.
                                ; 
        exx                     ; back to main set.
        ret                     ; return.
                                ; 
                                ; 

; -----------------------------
; THE 'MAKE BC SPACES'  RESTART
; -----------------------------
; This restart is used eight times to create, in workspace, the number of
; spaces passed in the BC register.

;; BC-SPACES

BC_SPACES:
        push bc                 ; push number of spaces on stack.
        ld hl, (E_LINE)         ; fetch edit line location from E_LINE.
        push hl                 ; save this value on stack.
        jp RESERVE              ; jump forward to continue at RESERVE.
                                ; 

t/data/zx81.asm  view on Meta::CPAN

                                ; with interrupts disabled.
                                ; 
        set 3, c                ; (8)  Load the scan line counter with eight.
                                ; Note. LD C,$08 is 7 clock cycles which
                                ; is way too fast.
                                ; 
; ->

;; WAIT-INT

WAIT_INT:
        ld r, a                 ; (9) Load R with initial rising value $DD.
                                ; 
        ei                      ; (4) Enable Interrupts.  [ R is now $DE ].
                                ; 
        jp (hl)                 ; (4) jump to the echo display file in upper
                                ; memory and execute characters $00 - $3F
                                ; as NOP instructions.  The video hardware
                                ; is able to read these characters and,
                                ; with the I register is able to convert
                                ; the character bitmaps in this ROM into a
                                ; line of bytes. Eventually the NEWLINE/HALT
                                ; will be encountered before R reaches $FF.
                                ; It is however the transition from $FF to
                                ; $80 that triggers the next interrupt.
                                ; [ The Refresh register is now $DF ]
                                ; 

; ---

;; SCAN-LINE

SCAN_LINE:
        pop de                  ; (10) discard the address after NEWLINE as the
                                ; same text line has to be done again
                                ; eight times.
                                ; 
        ret z                   ; (5)  Harmless Nonsensical Timing.
                                ; (condition never met)
                                ; 
        jr WAIT_INT             ; (12) back to WAIT-INT
                                ; 

;   Note. that a computer with less than 4K or RAM will have a collapsed
;   display file and the above mechanism deals with both types of display.
;
;   With a full display, the 32 characters in the line are treated as NOPS
;   and the Refresh register rises from $E0 to $FF and, at the next instruction
;   - HALT, the interrupt occurs.
;   With a collapsed display and an initial NEWLINE/HALT, it is the NOPs
;   generated by the HALT that cause the Refresh value to rise from $E0 to $FF,
;   triggering an Interrupt on the next transition.
;   This works happily for all display lines between these extremes and the
;   generation of the 32 character, 1 pixel high, line will always take 128
;   clock cycles.

; ---------------------------------
; THE 'INCREMENT CH-ADD' SUBROUTINE
; ---------------------------------
; This is the subroutine that increments the character address system variable
; and returns if it is not the cursor character. The ZX81 has an actual
; character at the cursor position rather than a pointer system variable
; as is the case with prior and subsequent ZX computers.

;; CH-ADD+1

CH_ADD_1:
        ld hl, (CH_ADD)         ; fetch character address to CH_ADD.
                                ; 
;; TEMP-PTR1

TEMP_PTR1:
        inc hl                  ; address next immediate location.
                                ; 
;; TEMP-PTR2

TEMP_PTR2:
        ld (CH_ADD), hl         ; update system variable CH_ADD.
                                ; 
        ld a, (hl)              ; fetch the character.
        cp $7F                  ; compare to cursor character.
        ret nz                  ; return if not the cursor.
                                ; 
        jr TEMP_PTR1            ; back for next character to TEMP-PTR1.
                                ; 

; --------------------
; THE 'ERROR-2' BRANCH
; --------------------
; This is a continuation of the error restart.
; If the error occurred in runtime then the error stack pointer will probably
; lead to an error report being printed unless it occurred during input.
; If the error occurred when checking syntax then the error stack pointer
; will be an editing routine and the position of the error will be shown
; when the lower screen is reprinted.

;; ERROR-2

ERROR_2:
        pop hl                  ; pop the return address which points to the
                                ; DEFB, error code, after the RST 08.
        ld l, (hl)              ; load L with the error code. HL is not needed
                                ; anymore.
                                ; 
;; ERROR-3

ERROR_3:
        ld (iy+ERR_NR-IY0), l   ; place error code in system variable ERR_NR
        ld sp, (ERR_SP)         ; set the stack pointer from ERR_SP
        call SLOW_FAST          ; routine SLOW/FAST selects slow mode.
        jp SET_MIN              ; exit to address on stack via routine SET-MIN.
                                ; 

; ---

        defb $FF                ; unused.
                                ; 
; ------------------------------------
; THE 'NON MASKABLE INTERRUPT' ROUTINE
; ------------------------------------
;   Jim Westwood's technical dodge using Non-Maskable Interrupts solved the
;   flicker problem of the ZX80 and gave the ZX81 a multi-tasking SLOW mode
;   with a steady display.  Note that the AF' register is reserved for this
;   function and its interaction with the display routines.  When counting
;   TV lines, the NMI makes no use of the main registers.
;   The circuitry for the NMI generator is contained within the SCL (Sinclair
;   Computer Logic) chip.
;   ( It takes 32 clock cycles while incrementing towards zero ).

;; NMI

NMI:
        ex af, af'              ; (4) switch in the NMI's copy of the
                                ; accumulator.
        inc a                   ; (4) increment.
        jp m, NMI_RET           ; (10/10) jump, if minus, to NMI-RET as this is
                                ; part of a test to see if the NMI
                                ; generation is working or an intermediate
                                ; value for the ascending negated blank
                                ; line counter.
                                ; 
        jr z, NMI_CONT          ; (12) forward to NMI-CONT

t/data/zx81.asm  view on Meta::CPAN

        defb $29                ; D
        defb $2B                ; F
        defb $2C                ; G
        defb $36                ; Q
        defb $3C                ; W
        defb $2A                ; E
        defb $37                ; R
        defb $39                ; T
        defb $1D                ; 1
        defb $1E                ; 2
        defb $1F                ; 3
        defb $20                ; 4
        defb $21                ; 5
        defb $1C                ; 0
        defb $25                ; 9
        defb $24                ; 8
        defb $23                ; 7
        defb $22                ; 6
        defb $35                ; P
        defb $34                ; O
        defb $2E                ; I
        defb $3A                ; U
        defb $3E                ; Y
        defb $76                ; NEWLINE
        defb $31                ; L
        defb $30                ; K
        defb $2F                ; J
        defb $2D                ; H
        defb $00                ; SPACE
        defb $1B                ; .
        defb $32                ; M
        defb $33                ; N
        defb $27                ; B
                                ; 
; -----------------------------
; THE 'SHIFTED' CHARACTER CODES
; -----------------------------


;; K-SHIFT

K_SHIFT:
        defb $0E                ; :
        defb $19                ; 
        defb $0F                ; ?
        defb $18                ; /
        defb $E3                ; STOP
        defb $E1                ; LPRINT
        defb $E4                ; SLOW
        defb $E5                ; FAST
        defb $E2                ; LLIST
        defb $C0                ; ""
        defb $D9                ; OR
        defb $E0                ; STEP
        defb $DB                ; <=
        defb $DD                ; <>
        defb $75                ; EDIT
        defb $DA                ; AND
        defb $DE                ; THEN
        defb $DF                ; TO
        defb $72                ; cursor-left
        defb $77                ; RUBOUT
        defb $74                ; GRAPHICS
        defb $73                ; cursor-right
        defb $70                ; cursor-up
        defb $71                ; cursor-down
        defb $0B                ; "
        defb $11                ; )
        defb $10                ; (
        defb $0D                ; $
        defb $DC                ; >=
        defb $79                ; FUNCTION
        defb $14                ; =
        defb $15                ; +
        defb $16                ; -
        defb $D8                ; **
        defb $0C                ; ukp
        defb $1A                ; ,
        defb $12                ; >
        defb $13                ; <
        defb $17                ; *
                                ; 
; ------------------------------
; THE 'FUNCTION' CHARACTER CODES
; ------------------------------


;; K-FUNCT

K_FUNCT:
        defb $CD                ; LN
        defb $CE                ; EXP
        defb $C1                ; AT
        defb $78                ; KL
        defb $CA                ; ASN
        defb $CB                ; ACS
        defb $CC                ; ATN
        defb $D1                ; SGN
        defb $D2                ; ABS
        defb $C7                ; SIN
        defb $C8                ; COS
        defb $C9                ; TAN
        defb $CF                ; INT
        defb $40                ; RND
        defb $78                ; KL
        defb $78                ; KL
        defb $78                ; KL
        defb $78                ; KL
        defb $78                ; KL
        defb $78                ; KL
        defb $78                ; KL
        defb $78                ; KL
        defb $78                ; KL
        defb $78                ; KL
        defb $C2                ; TAB
        defb $D3                ; PEEK
        defb $C4                ; CODE
        defb $D6                ; CHR$
        defb $D5                ; STR$
        defb $78                ; KL
        defb $D4                ; USR
        defb $C6                ; LEN
        defb $C5                ; VAL
        defb $D0                ; SQR
        defb $78                ; KL
        defb $78                ; KL

t/data/zx81.asm  view on Meta::CPAN

                                ; 
; ----------------------------
; THE 'INITIALIZATION' ROUTINE
; ----------------------------
;
;

;; INITIAL

INITIAL:
        ld hl, (RAMTOP)         ; fetch system variable RAMTOP.
        dec hl                  ; point to last system byte.
        ld (hl), $3E            ; make GO SUB end-marker $3E - too high for
                                ; high order byte of line number.
                                ; (was $3F on ZX80)
        dec hl                  ; point to unimportant low-order byte.
        ld sp, hl               ; and initialize the stack-pointer to this
                                ; location.
        dec hl                  ; point to first location on the machine stack
        dec hl                  ; which will be filled by next CALL/PUSH.
        ld (ERR_SP), hl         ; set the error stack pointer ERR_SP to
                                ; the base of the now empty machine stack.
                                ; 
; Now set the I register so that the video hardware knows where to find the
; character set. This ROM only uses the character set when printing to
; the ZX Printer. The TV picture is formed by the external video hardware.
; Consider also, that this 8K ROM can be retro-fitted to the ZX80 instead of
; its original 4K ROM so the video hardware could be on the ZX80.

        ld a, $1E               ; address for this ROM is $1E00.
        ld i, a                 ; set I register from A.
        im 1                    ; select Z80 Interrupt Mode 1.
                                ; 
        ld iy, ERR_NR           ; set IY to the start of RAM so that the
                                ; system variables can be indexed.
        ld (iy+CDFLAG-IY0), $40 ; set CDFLAG 0100 0000. Bit 6 indicates
                                ; Compute nad Display required.
                                ; 
        ld hl, PROG             ; The first location after System Variables -
                                ; 16509 decimal.
        ld (D_FILE), hl         ; set system variable D_FILE to this value.
        ld b, $19               ; prepare minimal screen of 24 NEWLINEs
                                ; following an initial NEWLINE.
                                ; 
;; LINE

LINE:
        ld (hl), $76            ; insert NEWLINE (HALT instruction)
        inc hl                  ; point to next location.
        djnz LINE               ; loop back for all twenty five to LINE
                                ; 
        ld (VARS), hl           ; set system variable VARS to next location
                                ; 
        call CLEAR              ; routine CLEAR sets $80 end-marker and the
                                ; dynamic memory pointers E_LINE, STKBOT and
                                ; STKEND.
                                ; 
;; N/L-ONLY

N_L_ONLY:
        call CURSOR_IN          ; routine CURSOR-IN inserts the cursor and
                                ; end-marker in the Edit Line also setting
                                ; size of lower display to two lines.
                                ; 
        call SLOW_FAST          ; routine SLOW/FAST selects COMPUTE and DISPLAY
                                ; 
; ---------------------------
; THE 'BASIC LISTING' SECTION
; ---------------------------
;
;

;; UPPER

UPPER:
        call CLS                ; routine CLS
        ld hl, (E_PPC)          ; sv E_PPC_lo
        ld de, (S_TOP)          ; sv S_TOP_lo
        and a                   ; 
        sbc hl, de              ; 
        ex de, hl               ; 
        jr nc, ADDR_TOP         ; to ADDR-TOP
                                ; 
        add hl, de              ; 
        ld (S_TOP), hl          ; sv S_TOP_lo
                                ; 
;; ADDR-TOP

ADDR_TOP:
        call LINE_ADDR          ; routine LINE-ADDR
        jr z, LIST_TOP          ; to LIST-TOP
                                ; 
        ex de, hl               ; 
;; LIST-TOP

LIST_TOP:
        call LIST_PROG          ; routine LIST-PROG
        dec (iy+BERG-IY0)       ; sv BERG
        jr nz, LOWER            ; to LOWER
                                ; 
        ld hl, (E_PPC)          ; sv E_PPC_lo
        call LINE_ADDR          ; routine LINE-ADDR
        ld hl, (CH_ADD)         ; sv CH_ADD_lo
        scf                     ; Set Carry Flag
        sbc hl, de              ; 
        ld hl, S_TOP            ; sv S_TOP_lo
        jr nc, INC_LINE         ; to INC-LINE
                                ; 
        ex de, hl               ; 
        ld a, (hl)              ; 
        inc hl                  ; 
        ldi                     ; 
        ld (de), a              ; 
        jr UPPER                ; to UPPER
                                ; 

; ---

;; DOWN-KEY

DOWN_KEY:
        ld hl, E_PPC            ; sv E_PPC_lo
                                ; 
;; INC-LINE

INC_LINE:
        ld e, (hl)              ; 
        inc hl                  ; 
        ld d, (hl)              ; 
        push hl                 ; 
        ex de, hl               ; 
        inc hl                  ; 
        call LINE_ADDR          ; routine LINE-ADDR
        call LINE_NO            ; routine LINE-NO
        pop hl                  ; 
;; KEY-INPUT

KEY_INPUT:
        bit 5, (iy+FLAGX-IY0)   ; sv FLAGX
        jr nz, LOWER            ; forward to LOWER
                                ; 
        ld (hl), d              ; 
        dec hl                  ; 
        ld (hl), e              ; 
        jr UPPER                ; to UPPER
                                ; 

; ----------------------------
; THE 'EDIT LINE COPY' SECTION
; ----------------------------
; This routine sets the edit line to just the cursor when
; 1) There is not enough memory to edit a BASIC line.
; 2) The edit key is used during input.
; The entry point LOWER


;; EDIT-INP

EDIT_INP:
        call CURSOR_IN          ; routine CURSOR-IN sets cursor only edit line.
                                ; 
; ->

;; LOWER

LOWER:
        ld hl, (E_LINE)         ; fetch edit line start from E_LINE.
                                ; 
;; EACH-CHAR

EACH_CHAR:
        ld a, (hl)              ; fetch a character from edit line.
        cp $7E                  ; compare to the number marker.
        jr nz, END_LINE         ; forward if not to END-LINE
                                ; 
        ld bc, $0006            ; else six invisible bytes to be removed.
        call RECLAIM_2          ; routine RECLAIM-2
        jr EACH_CHAR            ; back to EACH-CHAR
                                ; 

; ---

;; END-LINE

END_LINE:
        cp $76                  ; 
        inc hl                  ; 
        jr nz, EACH_CHAR        ; to EACH-CHAR
                                ; 
;; EDIT-LINE

EDIT_LINE:
        call CURSOR             ; routine CURSOR sets cursor K or L.
                                ; 
;; EDIT-ROOM

EDIT_ROOM:
        call LINE_ENDS          ; routine LINE-ENDS
        ld hl, (E_LINE)         ; sv E_LINE_lo
        ld (iy+ERR_NR-IY0), $FF ; sv ERR_NR
        call COPY_LINE          ; routine COPY-LINE
        bit 7, (iy+ERR_NR-IY0)  ; sv ERR_NR
        jr nz, DISPLAY_6        ; to DISPLAY-6
                                ; 
        ld a, (DF_SZ)           ; sv DF_SZ
        cp $18                  ; 
        jr nc, DISPLAY_6        ; to DISPLAY-6
                                ; 
        inc a                   ; 
        ld (DF_SZ), a           ; sv DF_SZ
        ld b, a                 ; 
        ld c, $01               ; 
        call LOC_ADDR           ; routine LOC-ADDR
        ld d, h                 ; 
        ld e, l                 ; 
        ld a, (hl)              ; 
;; FREE-LINE

FREE_LINE:
        dec hl                  ; 
        cp (hl)                 ; 
        jr nz, FREE_LINE        ; to FREE-LINE
                                ; 
        inc hl                  ; 
        ex de, hl               ; 
        ld a, ($4005)           ; sv RAMTOP_hi
        cp $4D                  ; 
        call c, RECLAIM_1       ; routine RECLAIM-1
        jr EDIT_ROOM            ; to EDIT-ROOM
                                ; 

; --------------------------
; THE 'WAIT FOR KEY' SECTION
; --------------------------
;
;

;; DISPLAY-6

DISPLAY_6:
        ld hl, START            ; 
        ld (X_PTR), hl          ; sv X_PTR_lo
                                ; 
        ld hl, CDFLAG           ; system variable CDFLAG
        bit 7, (hl)             ; 
        call z, DISPLAY_1       ; routine DISPLAY-1
                                ; 
;; SLOW-DISP

SLOW_DISP:
        bit 0, (hl)             ; 
        jr z, SLOW_DISP         ; to SLOW-DISP
                                ; 

t/data/zx81.asm  view on Meta::CPAN

; --------------------------
;
;

;; FUNCTION

FUNCTION:
        ld a, e                 ; 
        and $07                 ; 
        ld (MODE), a            ; sv MODE
        jr ENDED_2              ; back to ENDED-2
                                ; 

; ------------------------------------
; THE 'COLLECT LINE NUMBER' SUBROUTINE
; ------------------------------------
;
;

;; ZERO-DE

ZERO_DE:
        ex de, hl               ; 
        ld de, $04C2            ; $04C2 - a location addressing two zeros.
                                ; 
; ->

;; LINE-NO

LINE_NO:
        ld a, (hl)              ; 
        and $C0                 ; 
        jr nz, ZERO_DE          ; to ZERO-DE
                                ; 
        ld d, (hl)              ; 
        inc hl                  ; 
        ld e, (hl)              ; 
        ret                     ; 

; ----------------------
; THE 'EDIT KEY' ROUTINE
; ----------------------
;
;

;; EDIT-KEY

EDIT_KEY:
        call LINE_ENDS          ; routine LINE-ENDS clears lower display.
                                ; 
        ld hl, EDIT_INP         ; Address: EDIT-INP
        push hl                 ; ** is pushed as an error looping address.
                                ; 
        bit 5, (iy+FLAGX-IY0)   ; test FLAGX
        ret nz                  ; indirect jump if in input mode
                                ; to L046F, EDIT-INP (begin again).
                                ; 
;

        ld hl, (E_LINE)         ; fetch E_LINE
        ld (DF_CC), hl          ; and use to update the screen cursor DF_CC
                                ; 
; so now RST $10 will print the line numbers to the edit line instead of screen.
; first make sure that no newline/out of screen can occur while sprinting the
; line numbers to the edit line.

        ld hl, $1821            ; prepare line 0, column 0.
        ld (S_POSN), hl         ; update S_POSN with these dummy values.
                                ; 
        ld hl, (E_PPC)          ; fetch current line from E_PPC may be a
                                ; non-existent line e.g. last line deleted.
        call LINE_ADDR          ; routine LINE-ADDR gets address or that of
                                ; the following line.
        call LINE_NO            ; routine LINE-NO gets line number if any in DE
                                ; leaving HL pointing at second low byte.
                                ; 
        ld a, d                 ; test the line number for zero.
        or e                    ; 
        ret z                   ; return if no line number - no program to edit.
                                ; 
        dec hl                  ; point to high byte.
        call OUT_NO             ; routine OUT-NO writes number to edit line.
                                ; 
        inc hl                  ; point to length bytes.
        ld c, (hl)              ; low byte to C.
        inc hl                  ; 
        ld b, (hl)              ; high byte to B.
                                ; 
        inc hl                  ; point to first character in line.
        ld de, (DF_CC)          ; fetch display file cursor DF_CC
                                ; 
        ld a, $7F               ; prepare the cursor character.
        ld (de), a              ; and insert in edit line.
        inc de                  ; increment intended destination.
                                ; 
        push hl                 ; * save start of BASIC.
                                ; 
        ld hl, $001D            ; set an overhead of 29 bytes.
        add hl, de              ; add in the address of cursor.
        add hl, bc              ; add the length of the line.
        sbc hl, sp              ; subtract the stack pointer.
                                ; 
        pop hl                  ; * restore pointer to start of BASIC.
                                ; 
        ret nc                  ; return if not enough room to L046F EDIT-INP.
                                ; the edit key appears not to work.
                                ; 
        ldir                    ; else copy bytes from program to edit line.
                                ; Note. hidden floating point forms are also
                                ; copied to edit line.
                                ; 
        ex de, hl               ; transfer free location pointer to HL
                                ; 
        pop de                  ; ** remove address EDIT-INP from stack.
                                ; 
        call SET_STK_B          ; routine SET-STK-B sets STKEND from HL.
                                ; 
        jr ENDED_2              ; back to ENDED-2 and after 3 more jumps
                                ; to L0472, LOWER.
                                ; Note. The LOWER routine removes the hidden
                                ; floating-point numbers from the edit line.
                                ; 

; -------------------------
; THE 'NEWLINE KEY' ROUTINE
; -------------------------
;
;

;; N/L-KEY

N_L_KEY:
        call LINE_ENDS          ; routine LINE-ENDS
                                ; 
        ld hl, LOWER            ; prepare address: LOWER
                                ; 
        bit 5, (iy+FLAGX-IY0)   ; sv FLAGX
        jr nz, NOW_SCAN         ; to NOW-SCAN
                                ; 
        ld hl, (E_LINE)         ; sv E_LINE_lo
        ld a, (hl)              ; 
        cp $FF                  ; 
        jr z, STK_UPPER         ; to STK-UPPER
                                ; 
        call CLEAR_PRB          ; routine CLEAR-PRB
        call CLS                ; routine CLS
                                ; 
;; STK-UPPER

STK_UPPER:
        ld hl, UPPER            ; Address: UPPER
                                ; 
;; NOW-SCAN

NOW_SCAN:
        push hl                 ; push routine address (LOWER or UPPER).
        call LINE_SCAN          ; routine LINE-SCAN
        pop hl                  ; 
        call CURSOR             ; routine CURSOR

t/data/zx81.asm  view on Meta::CPAN

        rst $10                 ; PRINT-A
        inc hl                  ; 
        inc hl                  ; 
;; COPY-LINE

COPY_LINE:
        ld (CH_ADD), hl         ; sv CH_ADD_lo
        set 0, (iy+FLAGS-IY0)   ; sv FLAGS  - Suppress leading space
                                ; 
;; MORE-LINE

MORE_LINE:
        ld bc, (X_PTR)          ; sv X_PTR_lo
        ld hl, (CH_ADD)         ; sv CH_ADD_lo
        and a                   ; 
        sbc hl, bc              ; 
        jr nz, TEST_NUM         ; to TEST-NUM
                                ; 
        ld a, $B8               ; 
        rst $10                 ; PRINT-A
                                ; 
;; TEST-NUM

TEST_NUM:
        ld hl, (CH_ADD)         ; sv CH_ADD_lo
        ld a, (hl)              ; 
        inc hl                  ; 
        call NUMBER             ; routine NUMBER
        ld (CH_ADD), hl         ; sv CH_ADD_lo
        jr z, MORE_LINE         ; to MORE-LINE
                                ; 
        cp $7F                  ; 
        jr z, OUT_CURS          ; to OUT-CURS
                                ; 
        cp $76                  ; 
        jr z, OUT_CH            ; to OUT-CH
                                ; 
        bit 6, a                ; 
        jr z, NOT_TOKEN         ; to NOT-TOKEN
                                ; 
        call TOKENS             ; routine TOKENS
        jr MORE_LINE            ; to MORE-LINE
                                ; 

; ---


;; NOT-TOKEN

NOT_TOKEN:
        rst $10                 ; PRINT-A
        jr MORE_LINE            ; to MORE-LINE
                                ; 

; ---

;; OUT-CURS

OUT_CURS:
        ld a, (MODE)            ; Fetch value of system variable MODE
        ld b, $AB               ; Prepare an inverse [F] for function cursor.
                                ; 
        and a                   ; Test for zero -
        jr nz, FLAGS_2          ; forward if not to FLAGS-2
                                ; 
        ld a, (FLAGS)           ; Fetch system variable FLAGS.
        ld b, $B0               ; Prepare an inverse [K] for keyword cursor.
                                ; 
;; FLAGS-2

FLAGS_2:
        rra                     ; 00000?00 -> 000000?0
        rra                     ; 000000?0 -> 0000000?
        and $01                 ; 0000000?    0000000x
                                ; 
        add a, b                ; Possibly [F] -> [G]  or  [K] -> [L]
                                ; 
        call PRINT_SP           ; routine PRINT-SP prints character
        jr MORE_LINE            ; back to MORE-LINE
                                ; 

; -----------------------
; THE 'NUMBER' SUBROUTINE
; -----------------------
;
;

;; NUMBER

NUMBER:
        cp $7E                  ; 
        ret nz                  ; 
        inc hl                  ; 
        inc hl                  ; 
        inc hl                  ; 
        inc hl                  ; 
        inc hl                  ; 
        ret                     ; 

; --------------------------------
; THE 'KEYBOARD DECODE' SUBROUTINE
; --------------------------------
;
;

;; DECODE

DECODE:
        ld d, $00               ; 
        sra b                   ; 
        sbc a, a                ; 
        or $26                  ; 
        ld l, $05               ; 
        sub l                   ; 
;; KEY-LINE

KEY_LINE:
        add a, l                ; 
        scf                     ; Set Carry Flag
        rr c                    ; 
        jr c, KEY_LINE          ; to KEY-LINE
                                ; 
        inc c                   ; 
        ret nz                  ; 
        ld c, b                 ; 
        dec l                   ; 
        ld l, $01               ; 

t/data/zx81.asm  view on Meta::CPAN

RESERVE:
        ld hl, (STKBOT)         ; address STKBOT
        dec hl                  ; now last byte of workspace
        call MAKE_ROOM          ; routine MAKE-ROOM
        inc hl                  ; 
        inc hl                  ; 
        pop bc                  ; 
        ld (E_LINE), bc         ; sv E_LINE_lo
        pop bc                  ; 
        ex de, hl               ; 
        inc hl                  ; 
        ret                     ; 

; ---------------------------
; THE 'CLEAR' COMMAND ROUTINE
; ---------------------------
;
;

;; CLEAR

CLEAR:
        ld hl, (VARS)           ; sv VARS_lo
        ld (hl), $80            ; 
        inc hl                  ; 
        ld (E_LINE), hl         ; sv E_LINE_lo
                                ; 
; -----------------------
; THE 'X-TEMP' SUBROUTINE
; -----------------------
;
;

;; X-TEMP

X_TEMP:
        ld hl, (E_LINE)         ; sv E_LINE_lo
                                ; 
; ----------------------
; THE 'SET-STK' ROUTINES
; ----------------------
;
;

;; SET-STK-B

SET_STK_B:
        ld (STKBOT), hl         ; sv STKBOT
                                ; 
;

;; SET-STK-E

SET_STK_E:
        ld (STKEND), hl         ; sv STKEND
        ret                     ; 

; -----------------------
; THE 'CURSOR-IN' ROUTINE
; -----------------------
; This routine is called to set the edit line to the minimum cursor/newline
; and to set STKEND, the start of free space, at the next position.

;; CURSOR-IN

CURSOR_IN:
        ld hl, (E_LINE)         ; fetch start of edit line from E_LINE
        ld (hl), $7F            ; insert cursor character
                                ; 
        inc hl                  ; point to next location.
        ld (hl), $76            ; insert NEWLINE character
        inc hl                  ; point to next free location.
                                ; 
        ld (iy+DF_SZ-IY0), $02  ; set lower screen display file size DF_SZ
                                ; 
        jr SET_STK_B            ; exit via SET-STK-B above
                                ; 

; ------------------------
; THE 'SET-MIN' SUBROUTINE
; ------------------------
;
;

;; SET-MIN

SET_MIN:
        ld hl, MEMBOT           ; normal location of calculator's memory area
        ld (MEM), hl            ; update system variable MEM
        ld hl, (STKBOT)         ; fetch STKBOT
        jr SET_STK_E            ; back to SET-STK-E
                                ; 
                                ; 

; ------------------------------------
; THE 'RECLAIM THE END-MARKER' ROUTINE
; ------------------------------------

;; REC-V80

REC_V80:
        ld de, (E_LINE)         ; sv E_LINE_lo
        jp RECLAIM_1            ; to RECLAIM-1
                                ; 

; ----------------------
; THE 'ALPHA' SUBROUTINE
; ----------------------

;; ALPHA

ALPHA:
        cp $26                  ; 
        jr ALPHA_2              ; skip forward to ALPHA-2
                                ; 
                                ; 

; -------------------------
; THE 'ALPHANUM' SUBROUTINE
; -------------------------

;; ALPHANUM

ALPHANUM:
        cp $1C                  ; 
;; ALPHA-2

ALPHA_2:



( run in 2.550 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )