|
|
@@ -1,97 +1,117 @@ |
|
|
|
; *** Consts *** |
|
|
|
; maximum number of lines (line number maximum, however, is always 0xffff) |
|
|
|
.equ BUF_MAXLINES 0x100 |
|
|
|
; Size of the string pool |
|
|
|
.equ BUF_POOLSIZE 0x1000 |
|
|
|
|
|
|
|
; *** Variables *** |
|
|
|
; A pointer to free space in the pool. |
|
|
|
.equ BUF_FREE BUF_RAMSTART |
|
|
|
; The line pool. Each line consists of a two bytes binary number followed by |
|
|
|
; a one byte length followed by the command string, which doesn't include its |
|
|
|
; line number (example "10 print 123" becomes "print 123"), but which is null |
|
|
|
; terminated. The one byte length includes null termination. For example, if |
|
|
|
; we have a line record starting at 0x1000 and that its length field indicates |
|
|
|
; 0x42, this means that the next line starts at 0x1045 (0x42+2+1). |
|
|
|
.equ BUF_POOL @+2 |
|
|
|
; A pointer to the first free line |
|
|
|
.equ BUF_LFREE BUF_RAMSTART |
|
|
|
; A pointer to the first free byte in the pool |
|
|
|
.equ BUF_PFREE @+2 |
|
|
|
; The line index. Each record consists of 4 bytes: 2 for line number, |
|
|
|
; 2 for pointer to string in pool. Kept in order of line numbers. |
|
|
|
.equ BUF_LINES @+2 |
|
|
|
; The line pool. A list of null terminated strings. BUF_LINES records point |
|
|
|
; to those strings. |
|
|
|
.equ BUF_POOL @+BUF_MAXLINES*4 |
|
|
|
.equ BUF_RAMEND @+BUF_POOLSIZE |
|
|
|
|
|
|
|
bufInit: |
|
|
|
ld hl, BUF_LINES |
|
|
|
ld (BUF_LFREE), hl |
|
|
|
ld hl, BUF_POOL |
|
|
|
ld (BUF_FREE), hl |
|
|
|
ld (BUF_PFREE), hl |
|
|
|
ret |
|
|
|
|
|
|
|
; Add line at (HL) with line number DE to the pool. The string at (HL) should |
|
|
|
; Add line at (HL) with line number DE to the buffer. The string at (HL) should |
|
|
|
; not contain the line number prefix or the whitespace between the line number |
|
|
|
; and the comment. |
|
|
|
; Note that an empty string is *not* an error. It will be saved as a line. |
|
|
|
; Don't send strings that are more than 0xfe in length. It won't work well. |
|
|
|
; Z for success. |
|
|
|
; The only error condition that is handled is when there is not enough space |
|
|
|
; left in the pool to add a string of (HL)'s size. In that case, nothing will |
|
|
|
; be done and Z will be unset. |
|
|
|
; |
|
|
|
; DESTROYED REGISTER: DE. Too much pushpopping around to keep it. Not worth it. |
|
|
|
; Error conditions are: |
|
|
|
; * not enough space in the pool |
|
|
|
; * not enough space in the line index |
|
|
|
bufAdd: |
|
|
|
push hl ; --> lvl 1 |
|
|
|
push de ; --> lvl 2 |
|
|
|
; First step: see if we're within the pool's bounds |
|
|
|
exx ; preserve HL and DE |
|
|
|
; First step: do we have index space? |
|
|
|
ld hl, (BUF_LFREE) |
|
|
|
ld de, BUF_POOL |
|
|
|
or a ; reset carry |
|
|
|
sbc hl, de |
|
|
|
exx ; restore |
|
|
|
; no carry? HL >= BUF_POOL, error. Z already unset |
|
|
|
ret nc |
|
|
|
; Second step: see if we're within the pool's bounds |
|
|
|
call strlen |
|
|
|
inc a ; strlen doesn't include line termination |
|
|
|
ld hl, (BUF_FREE) |
|
|
|
exx ; preserve HL and DE |
|
|
|
ld hl, (BUF_PFREE) |
|
|
|
call addHL |
|
|
|
; add overhead (3b) |
|
|
|
inc hl \ inc hl \ inc hl |
|
|
|
ld de, BUF_RAMEND |
|
|
|
sbc hl, de |
|
|
|
exx ; restore |
|
|
|
; no carry? HL >= BUF_RAMEND, error. Z already unset |
|
|
|
jr nc, .error |
|
|
|
; We have enough space, proceed |
|
|
|
ld hl, (BUF_FREE) |
|
|
|
pop de ; <-- lvl 2 |
|
|
|
ret nc |
|
|
|
; We have enough space. |
|
|
|
; Third step: set line index data |
|
|
|
push de ; --> lvl 1 |
|
|
|
push hl ; --> lvl 2 |
|
|
|
ld hl, (BUF_LFREE) |
|
|
|
ld (hl), e |
|
|
|
inc hl |
|
|
|
ld (hl), d |
|
|
|
inc hl |
|
|
|
ld de, (BUF_PFREE) |
|
|
|
ld (hl), e |
|
|
|
inc hl |
|
|
|
ld (hl), d |
|
|
|
inc hl |
|
|
|
; A has been untouched since that strlen call. Let's use it as-is. |
|
|
|
ld (hl), a |
|
|
|
inc hl ; HL now points to dest for our string. |
|
|
|
ex de, hl |
|
|
|
pop hl \ push hl ; <--> lvl 1. recall orig, but also preserve |
|
|
|
ld (BUF_LFREE), hl |
|
|
|
pop hl \ push hl ; <-- lvl 2, restore and preserve |
|
|
|
|
|
|
|
; Fourth step: copy string to pool |
|
|
|
ld de, (BUF_PFREE) |
|
|
|
call strcpyM |
|
|
|
; Copying done. Let's update the free zone marker. |
|
|
|
ld (BUF_FREE), de |
|
|
|
xor a ; set Z |
|
|
|
pop hl ; <-- lvl 1 |
|
|
|
ret |
|
|
|
.error: |
|
|
|
pop de |
|
|
|
pop hl |
|
|
|
ld (BUF_PFREE), de |
|
|
|
pop hl ; <-- lvl 2 |
|
|
|
pop de ; <-- lvl 1 |
|
|
|
ret |
|
|
|
|
|
|
|
; Set IX to point to the first valid line we have in the pool. |
|
|
|
; Error if the pool is empty. |
|
|
|
; Z for success. |
|
|
|
; Set IX to point to the beginning of the pool. |
|
|
|
; Z set if (IX) is a valid line, unset if the pool is empty. |
|
|
|
bufFirst: |
|
|
|
ld a, (BUF_POOL+2) |
|
|
|
or a |
|
|
|
jp z, unsetZ |
|
|
|
ld ix, BUF_POOL |
|
|
|
xor a ; set Z |
|
|
|
ret |
|
|
|
ld ix, BUF_LINES |
|
|
|
jp bufEOF |
|
|
|
|
|
|
|
; Given a valid line record in IX, move IX to the next valid line. |
|
|
|
; Given a valid line record in IX, move IX to the next line. |
|
|
|
; This routine doesn't check that IX is valid. Ensure IX validity before |
|
|
|
; calling. This routine also doesn't check that the next line is within the |
|
|
|
; bounds of the pool because this check is done during bufAdd. |
|
|
|
; The only possible error is if there is no next line. |
|
|
|
; Z for success. |
|
|
|
; calling. |
|
|
|
bufNext: |
|
|
|
push de ; --> lvl 1 |
|
|
|
ld d, 0 |
|
|
|
ld e, (ix+2) |
|
|
|
add ix, de |
|
|
|
inc ix \ inc ix \ inc ix |
|
|
|
pop de ; <-- lvl 1 |
|
|
|
ld a, (ix+2) |
|
|
|
or a |
|
|
|
jp z, unsetZ |
|
|
|
xor a ; set Z |
|
|
|
inc ix \ inc ix \ inc ix \ inc ix |
|
|
|
jp bufEOF |
|
|
|
|
|
|
|
; Returns whether line index at IX is past the end of file, that is, |
|
|
|
; whether IX == (BUF_LFREE) |
|
|
|
; Z is set when not EOF, unset when EOF. |
|
|
|
bufEOF: |
|
|
|
push hl |
|
|
|
push de |
|
|
|
push ix \ pop hl |
|
|
|
ld de, (BUF_LFREE) |
|
|
|
sbc hl, de |
|
|
|
jr z, .empty |
|
|
|
cp a ; ensure Z |
|
|
|
.end: |
|
|
|
pop de |
|
|
|
pop hl |
|
|
|
ret |
|
|
|
.empty: |
|
|
|
call unsetZ |
|
|
|
jr .end |
|
|
|
|
|
|
|
; Given a line index in (IX), set HL to its associated string pointer. |
|
|
|
bufStr: |
|
|
|
ld l, (ix+2) |
|
|
|
ld h, (ix+3) |
|
|
|
ret |