From 1a5a1b9861670b34c1c81e04e3b9063c46e55dc2 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Sun, 21 Jul 2019 08:47:42 -0400 Subject: [PATCH] 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. --- apps/ed/buf.asm | 100 ++++++++++++++++++++----------------------------------- apps/ed/io.asm | 33 +----------------- apps/ed/main.asm | 12 ++----- 3 files changed, 40 insertions(+), 105 deletions(-) diff --git a/apps/ed/buf.asm b/apps/ed/buf.asm index f5226e1..64cb39d 100644 --- a/apps/ed/buf.asm +++ b/apps/ed/buf.asm @@ -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 diff --git a/apps/ed/io.asm b/apps/ed/io.asm index eecd5ec..e96737b 100644 --- a/apps/ed/io.asm +++ b/apps/ed/io.asm @@ -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 diff --git a/apps/ed/main.asm b/apps/ed/main.asm index 5e8acad..1f197ff 100644 --- a/apps/ed/main.asm +++ b/apps/ed/main.asm @@ -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...