ed: make scratchpad memory only

The dual scraptchpad thing doesn't work. Things become very
complicated when it's time to write that back to the file. We
overwrite our contents and end up with garbage.
This commit is contained in:
Virgil Dupras 2019-07-21 08:47:42 -04:00
parent 942d2a952d
commit 1a5a1b9861
3 changed files with 40 additions and 105 deletions

View File

@ -1,29 +1,19 @@
; buf - manage line buffer
;
; Lines in edited file aren't loaded in memory, their offsets is referenced to
; in this buffer.
;
; About scratchpad and offsets. There are two scratchpads: file and memory.
; The file one is the contents of the active blkdev. The second one is
; in-memory, for edits. We differentiate between the two with a
; "scatchpad mask". When the high bits of the offset match the mask, then we
; know that this offset is from the scratchpad.
;
; *** Consts ***
;
; Maximum number of lines allowed in the buffer.
.equ BUF_MAXLINES 0x800
; Size of our scratchpad
.equ BUF_PADMAXLEN 0x1000
; Scratchpad mask (only applies on high byte)
.equ BUF_SCRATCHPAD_MASK 0b11110000
; *** Variables ***
; Number of lines currently in the buffer
.equ BUF_LINECNT BUF_RAMSTART
; List of words pointing to scratchpad offsets
; List of pointers to strings in scratchpad
.equ BUF_LINES BUF_LINECNT+2
; Points to the end of the scratchpad
; Points to the end of the scratchpad, that is, one byte after the last written
; char in it.
.equ BUF_PADEND BUF_LINES+BUF_MAXLINES*2
; The in-memory scratchpad
.equ BUF_PAD BUF_PADEND+2
@ -35,20 +25,34 @@
; On initialization, we read the whole contents of target blkdev and add lines
; as we go.
bufInit:
ld hl, BUF_PAD
ld (BUF_PADEND), hl
ld ix, BUF_LINES
ld hl, BUF_PAD ; running pointer to end of pad
ld de, BUF_PAD ; points to beginning of current line
ld ix, BUF_LINES ; points to current line index
ld bc, 0 ; line count
.loop:
call ioTell ; --> HL
call ioGetC
jr nz, .loopend
ld (ix), l
or a ; null? hum, weird. same as LF
jr z, .lineend
cp 0x0a
jr z, .lineend
ld (hl), a
inc hl
jr .loop
.lineend:
; We've just finished reading a line, writing each char in the pad.
; Null terminate it.
xor a
ld (hl), a
inc hl
; Now, let's register its pointer in BUF_LINES
ld (ix), e
inc ix
ld (ix), h
ld (ix), d
inc ix
inc bc
call ioGetLine
ld (BUF_PADEND), hl
ld de, (BUF_PADEND)
jr .loop
.loopend:
ld (BUF_LINECNT), bc
@ -65,45 +69,20 @@ bufLineAddr:
pop de
ret
; Read line number specified in HL and loads the I/O buffer with it.
; Like ioGetLine, sets HL to line buffer pointer.
; Read line number specified in HL and make HL point to its contents.
; Sets Z on success, unset if out of bounds.
bufGetLine:
push de
push de ; --> lvl 1
ld de, (BUF_LINECNT)
call cpHLDE
jr nc, .outOfBounds ; HL > (BUF_LINECNT)
pop de ; <-- lvl 1
jp nc, unsetZ ; HL > (BUF_LINECNT)
call bufLineAddr
; HL now points to seek offset in memory
ld e, (hl)
inc hl
ld d, (hl)
; DE has seek offset
ex de, hl
pop de
; is it a scratchpad offset?
ld a, h
and BUF_SCRATCHPAD_MASK
cp BUF_SCRATCHPAD_MASK
jr z, .fromScratchpad
; not from scratchpad
cp a ; ensure Z
jp ioGetLine ; preserves AF
.fromScratchpad:
; remove scratchpad mask
ld a, BUF_SCRATCHPAD_MASK
xor 0xff
and h
ld h, a
; HL is now a mask-less offset to BUF_PAD
push de ; --> lvl 1
ld de, BUF_PAD
add hl, de
pop de ; <-- lvl 1
; HL now points to an item in BUF_LINES.
call intoHL
; Now, HL points to our contents
cp a ; ensure Z
ret
.outOfBounds:
pop de
jp unsetZ
; Given line indexes in HL and DE where HL < DE < CNT, move all lines between
; DE and CNT by an offset of DE-HL. Also, adjust BUF_LINECNT by DE-HL.
@ -150,7 +129,7 @@ bufDelLines:
; Insert string where DE points to memory scratchpad, then insert that line
; at index HL, offsetting all lines by 2 bytes.
bufInsertLine:
push de ; --> lvl 1, scratchpad offset
push de ; --> lvl 1, scratchpad ptr
push hl ; --> lvl 2, insert index
; The logic below is mostly copy-pasted from bufDelLines, but with a
; LDDR logic (to avoid overwriting). I learned, with some pain involved,
@ -187,22 +166,15 @@ bufInsertLine:
ld (hl), d
ret
; copy string that HL points to to scratchpad and return its seek offset, in HL.
; copy string that HL points to to scratchpad and return its pointer in
; scratchpad, in HL.
bufScratchpadAdd:
push de
ld de, (BUF_PADEND)
push de ; --> lvl 1
call strcpyM
inc de ; pad end is last char + 1
ld (BUF_PADEND), de
pop hl ; <-- lvl 1
; we have a memory offset in HL, but it's not what we want! we want a
; seek offset stamped with the "scratchpad mask"
ld de, BUF_PAD
scf \ ccf
sbc hl, de
ld a, h
or BUF_SCRATCHPAD_MASK
ld h, a
; now we're good...
pop de
ret

View File

@ -32,7 +32,7 @@ ioInit:
ld ix, IO_FILE_HDL
jp fsPutC
.blkdev:
.dw .fsGetC, .fsPutC
.dw .fsGetC, unsetZ
ioGetC:
push ix
@ -61,34 +61,3 @@ ioTell:
call _blkTell
pop ix
ret
; Given an offset HL, read the line in IO_LINE, without LF and null terminates
; it. Make HL point to IO_LINE.
ioGetLine:
push af
push de
push bc
ld de, 0 ; limit ourselves to 16-bit for now
xor a ; absolute seek
call ioSeek
ld hl, IO_LINE
ld b, IO_MAXLEN
.loop:
call ioGetC
jr nz, .loopend
or a ; null? hum, weird. same as LF
jr z, .loopend
cp 0x0a
jr z, .loopend
ld (hl), a
inc hl
djnz .loop
.loopend:
; null-terminate the string
xor a
ld (hl), a
ld hl, IO_LINE
pop bc
pop de
pop af
ret

View File

@ -15,16 +15,10 @@
;
; That doubly linked list on the z80 would use 7 bytes per line (prev, next,
; offset, len), which is a bit much. Moreover, there's that whole "scratchpad
; being loaded in memory" thing that's a bit iffy. We sacrifice speed for
; memory usage.
; being loaded in memory" thing that's a bit iffy.
;
; So here's what we do. First, we have two scratchpads. The first one is the
; file being read itself. The second one is memory, for modifications we
; make to the file. When reading the file, we note the offset at which it ends.
; All offsets under this limit refer to the first scratchpad. Other offsets
; refer to the second.
;
; Then, our line list is just an array of 16-bit offsets. This means that we
; We sacrifice speed for memory usage by making that linked list into a simple
; array of pointers to line contents in scratchpad. This means that we
; don't have an easy access to line length and we have to move a lot of memory
; around whenever we add or delete lines. Hopefully, "LDIR" will be our friend
; here...