From cfe2fc4a987607e36f3633d58c119308293e163c Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 28 Nov 2019 13:20:43 -0800 Subject: [PATCH 001/149] Simpler INTERP entry --- src/vmsrc/c64/plvmc64.s | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/vmsrc/c64/plvmc64.s b/src/vmsrc/c64/plvmc64.s index 6681817..859ffe8 100644 --- a/src/vmsrc/c64/plvmc64.s +++ b/src/vmsrc/c64/plvmc64.s @@ -27,13 +27,10 @@ SEGBEGIN JMP VMINIT ;* SYSTEM INTERPRETER ENTRYPOINT ;* INTERP PLA - CLC - ADC #$01 STA IPL PLA - ADC #$00 STA IPH - LDY #$00 + LDY #$01 JMP FETCHOP ;* ;* ENTER INTO USER BYTECODE INTERPRETER From 02b3b88862b897c29c62d9fb0638ac9a97857e94 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 28 Nov 2019 13:21:23 -0800 Subject: [PATCH 002/149] Simpler INTERP entry --- src/vmsrc/apple/plvm01.s | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/vmsrc/apple/plvm01.s b/src/vmsrc/apple/plvm01.s index c7e70ec..1c99324 100644 --- a/src/vmsrc/apple/plvm01.s +++ b/src/vmsrc/apple/plvm01.s @@ -27,13 +27,10 @@ SEGBEGIN JMP VMINIT ;* SYSTEM INTERPRETER ENTRYPOINT ;* INTERP PLA - CLC - ADC #$01 STA IPL PLA - ADC #$00 STA IPH - LDY #$00 + LDY #$01 JMP FETCHOP ;* ;* ENTER INTO USER BYTECODE INTERPRETER From 27eca20a047e00812a828be857bb76d6be9d93de Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 28 Nov 2019 13:22:06 -0800 Subject: [PATCH 003/149] Simpler DINTERP entry --- src/vmsrc/apple/plvm02.s | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/vmsrc/apple/plvm02.s b/src/vmsrc/apple/plvm02.s index 9781c0f..dbf9d48 100755 --- a/src/vmsrc/apple/plvm02.s +++ b/src/vmsrc/apple/plvm02.s @@ -149,13 +149,10 @@ OPTBL !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 ;* DIRECTLY ENTER INTO BYTECODE INTERPRETER ;* DINTRP PLA - CLC - ADC #$01 STA IPL PLA - ADC #$00 STA IPH - LDY #$00 + LDY #$01 JMP FETCHOP ;* ;* INDIRECTLY ENTER INTO BYTECODE INTERPRETER From acf2aaacfe58251113960a9a7004678b035f6b09 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 28 Nov 2019 13:23:53 -0800 Subject: [PATCH 004/149] Simpler INTERP entry --- src/vmsrc/apple/plvm03.s | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/vmsrc/apple/plvm03.s b/src/vmsrc/apple/plvm03.s index 63f782d..809711f 100755 --- a/src/vmsrc/apple/plvm03.s +++ b/src/vmsrc/apple/plvm03.s @@ -160,14 +160,12 @@ OPTBL !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 ;* SYSTEM INTERPRETER ENTRYPOINT ;* INTERP PLA - CLC - ADC #$01 STA IPL PLA - ADC #$00 STA IPH LDY #$00 STY IPX + INY JMP FETCHOP ;* ;* ENTER INTO USER BYTECODE INTERPRETER From 50f2ac669c433d9432e8b70c7525549c1ed079fb Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 28 Nov 2019 13:27:11 -0800 Subject: [PATCH 005/149] Simpler DINTERP entry --- src/vmsrc/apple/plvm802.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vmsrc/apple/plvm802.s b/src/vmsrc/apple/plvm802.s index 7c06a2a..065e3b5 100644 --- a/src/vmsrc/apple/plvm802.s +++ b/src/vmsrc/apple/plvm802.s @@ -283,17 +283,17 @@ DINTRP PHP XCE +ACCMEM16 ; 16 BIT A/M PLA - INC STA IP STX ESP TSX STX HWSP LDX #>OPTBL !IF DEBUG { + INC IP JMP SETDBG } ELSE { STX OPPAGE - LDY #$00 + LDY #$01 JMP FETCHOP } !AS From 2fe4b9ed52df48dadb91ef62477e9f65d2f18fae Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 28 Nov 2019 13:28:04 -0800 Subject: [PATCH 006/149] Simpler DINTERP entry --- src/vmsrc/apple/plvmjit02.s | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/vmsrc/apple/plvmjit02.s b/src/vmsrc/apple/plvmjit02.s index 54c2820..a104f2f 100755 --- a/src/vmsrc/apple/plvmjit02.s +++ b/src/vmsrc/apple/plvmjit02.s @@ -223,13 +223,10 @@ OPTBL !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 ;* DIRECTLY ENTER INTO BYTECODE INTERPRETER ;* DINTRP PLA - CLC - ADC #$01 STA IPL PLA - ADC #$00 STA IPH - LDY #$00 + LDY #$01 LDA #>OPTBL STA OPPAGE JMP FETCHOP From 1242b538247b0129ea60e9281dd74abd1d48c27b Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sun, 1 Dec 2019 15:24:18 -0800 Subject: [PATCH 007/149] Back out some of the DINTRP optimizations. Dependecy on Y being szero in ENTER --- src/vmsrc/apple/plvm02.s | 5 ++++- src/vmsrc/apple/plvm03.s | 4 +++- src/vmsrc/apple/plvm802.s | 6 +++--- src/vmsrc/apple/plvmjit02.s | 5 ++++- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/vmsrc/apple/plvm02.s b/src/vmsrc/apple/plvm02.s index dbf9d48..9781c0f 100755 --- a/src/vmsrc/apple/plvm02.s +++ b/src/vmsrc/apple/plvm02.s @@ -149,10 +149,13 @@ OPTBL !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 ;* DIRECTLY ENTER INTO BYTECODE INTERPRETER ;* DINTRP PLA + CLC + ADC #$01 STA IPL PLA + ADC #$00 STA IPH - LDY #$01 + LDY #$00 JMP FETCHOP ;* ;* INDIRECTLY ENTER INTO BYTECODE INTERPRETER diff --git a/src/vmsrc/apple/plvm03.s b/src/vmsrc/apple/plvm03.s index 809711f..d00c54e 100755 --- a/src/vmsrc/apple/plvm03.s +++ b/src/vmsrc/apple/plvm03.s @@ -160,12 +160,14 @@ OPTBL !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 ;* SYSTEM INTERPRETER ENTRYPOINT ;* INTERP PLA + CLC + ADC #$01 STA IPL PLA + ADC #$00 STA IPH LDY #$00 STY IPX - INY JMP FETCHOP ;* ;* ENTER INTO USER BYTECODE INTERPRETER diff --git a/src/vmsrc/apple/plvm802.s b/src/vmsrc/apple/plvm802.s index 065e3b5..baf41b6 100644 --- a/src/vmsrc/apple/plvm802.s +++ b/src/vmsrc/apple/plvm802.s @@ -283,17 +283,17 @@ DINTRP PHP XCE +ACCMEM16 ; 16 BIT A/M PLA + INC STA IP STX ESP TSX STX HWSP LDX #>OPTBL !IF DEBUG { - INC IP - JMP SETDBG + BRA SETDBG } ELSE { STX OPPAGE - LDY #$01 + LDY #$00 JMP FETCHOP } !AS diff --git a/src/vmsrc/apple/plvmjit02.s b/src/vmsrc/apple/plvmjit02.s index a104f2f..54c2820 100755 --- a/src/vmsrc/apple/plvmjit02.s +++ b/src/vmsrc/apple/plvmjit02.s @@ -223,10 +223,13 @@ OPTBL !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 ;* DIRECTLY ENTER INTO BYTECODE INTERPRETER ;* DINTRP PLA + CLC + ADC #$01 STA IPL PLA + ADC #$00 STA IPH - LDY #$01 + LDY #$00 LDA #>OPTBL STA OPPAGE JMP FETCHOP From 8f85445700c96b191874b5134272fb800ec48645 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 1 Dec 2019 15:36:48 -0800 Subject: [PATCH 008/149] Back out DINTRP opt as ENTER requires Y being zero --- src/vmsrc/c64/plvmc64.s | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vmsrc/c64/plvmc64.s b/src/vmsrc/c64/plvmc64.s index 859ffe8..6681817 100644 --- a/src/vmsrc/c64/plvmc64.s +++ b/src/vmsrc/c64/plvmc64.s @@ -27,10 +27,13 @@ SEGBEGIN JMP VMINIT ;* SYSTEM INTERPRETER ENTRYPOINT ;* INTERP PLA + CLC + ADC #$01 STA IPL PLA + ADC #$00 STA IPH - LDY #$01 + LDY #$00 JMP FETCHOP ;* ;* ENTER INTO USER BYTECODE INTERPRETER From db6bc55df3102c103278b6deb8a6354a8b7c174f Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 1 Dec 2019 15:39:21 -0800 Subject: [PATCH 009/149] Back out DINTRP opt as ENTER needs Y to bee zero --- src/vmsrc/apple/plvm01.s | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vmsrc/apple/plvm01.s b/src/vmsrc/apple/plvm01.s index 1c99324..73645fe 100644 --- a/src/vmsrc/apple/plvm01.s +++ b/src/vmsrc/apple/plvm01.s @@ -27,8 +27,11 @@ SEGBEGIN JMP VMINIT ;* SYSTEM INTERPRETER ENTRYPOINT ;* INTERP PLA + CLC + ADC #$01 STA IPL PLA + ADC #$00 STA IPH LDY #$01 JMP FETCHOP From 1a9ab9629b1b52107eadaafafa4276df5c7d27d6 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sun, 1 Dec 2019 15:48:41 -0800 Subject: [PATCH 010/149] Copy FP modules --- src/mkrel | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mkrel b/src/mkrel index e1ad102..a458b86 100755 --- a/src/mkrel +++ b/src/mkrel @@ -30,11 +30,11 @@ cp rel/apple/JIT#FE1000 prodos/sys/JIT.REL cp rel/apple/JIT16#FE1000 prodos/sys/JIT16.REL cp rel/apple/JITUNE#FE1000 prodos/sys/JITUNE.REL cp rel/LZ4#FE1000 prodos/sys/LZ4.REL -#cp rel/FPSTR#FE1000 prodos/sys/FPSTR.REL -#cp rel/FPU#FE1000 prodos/sys/FPU.REL -#cp rel/SANE#FE1000 prodos/sys/SANE.REL -#cp ../sysfiles/FP6502.CODE#060000 prodos/sys/FP6502.CODE.BIN -#cp ../sysfiles/ELEMS.CODE#060000 prodos/sys/ELEMS.CODE.BIN +cp rel/FPSTR#FE1000 prodos/sys/FPSTR.REL +cp rel/FPU#FE1000 prodos/sys/FPU.REL +cp rel/SANE#FE1000 prodos/sys/SANE.REL +cp ../sysfiles/FP6502.CODE#060000 prodos/sys/FP6502.CODE.BIN +cp ../sysfiles/ELEMS.CODE#060000 prodos/sys/ELEMS.CODE.BIN rm -rf prodos/fpsos mkdir prodos/fpsos From 7f6f9e7bbd9d23ab66c2d0066fe82c65411c5687 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Fri, 6 Dec 2019 10:23:38 -0800 Subject: [PATCH 011/149] Fix directory creation ops --- src/libsrc/apple/fileio.pla | 5 +++-- src/samplesrc/tftpd.pla | 12 ++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/libsrc/apple/fileio.pla b/src/libsrc/apple/fileio.pla index db299a2..9f5e6db 100644 --- a/src/libsrc/apple/fileio.pla +++ b/src/libsrc/apple/fileio.pla @@ -271,7 +271,7 @@ def a2create(path, type, aux) params.3 = $C3 params.4 = type params:5 = aux - params.7 = $1 + params.7 = type == $0F ?? $0D :: $01 params:8 = 0 params:10 = 0 perr = syscall($C0, @params) @@ -284,9 +284,10 @@ def a3create(path, type, aux) params.0 = 3 params:1 = path params:3 = @options - params.5 = 3 + params.5 = 4 options.0 = type options:1 = aux + options.3 = type == $0F ?? $0D :: $01 perr = syscall($C0, @params) return perr end diff --git a/src/samplesrc/tftpd.pla b/src/samplesrc/tftpd.pla index 2e8a9b4..c9143d1 100644 --- a/src/samplesrc/tftpd.pla +++ b/src/samplesrc/tftpd.pla @@ -260,6 +260,7 @@ def writeUDP(ipsrc, portsrc, data, len, param) end def servUDP(ipsrc, portsrc, data, len, param) byte info[24] + byte l, prefix[48] when *data is RRQ // Read request @@ -317,6 +318,17 @@ def servUDP(ipsrc, portsrc, data, len, param) // Extract filename // netscii, type, aux = mkProName(data + 2, @filename) + // + // Scan filename prefix and create + // + prefix[1] = filename[1] + for l = 2 to filename[0] + if filename[l] == '/' + prefix[0] = l-1 + fileio:create(@prefix, $0F, $0000) + fin + prefix[l] = filename[l] + next fileio:destroy(@filename) if fileio:create(@filename, type, aux) puts("Create file error: "); putb(perr); putln From 1dc0d252f815402f2295bdab85b05aac04701b4d Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Fri, 6 Dec 2019 18:14:08 -0800 Subject: [PATCH 012/149] Fix is_hw test for 16 bit JIT --- src/libsrc/apple/jit16.pla | 2 +- src/libsrc/jit16core.pla | 8 ++------ src/libsrc/jitcore.pla | 7 ++----- src/tftpbld | 1 + 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/libsrc/apple/jit16.pla b/src/libsrc/apple/jit16.pla index cea991c..5ddf942 100644 --- a/src/libsrc/apple/jit16.pla +++ b/src/libsrc/apple/jit16.pla @@ -50,7 +50,7 @@ end // Identify hardware addresses for certain byte sized access operations // def is_hwaddr(addr) - return addr >= $C000 and addr < $C100 + return isuge(addr, $C000) and isult(addr, $C100) end include "libsrc/jit16core.pla" // diff --git a/src/libsrc/jit16core.pla b/src/libsrc/jit16core.pla index bb867c3..eb73f13 100644 --- a/src/libsrc/jit16core.pla +++ b/src/libsrc/jit16core.pla @@ -11,6 +11,7 @@ def compiler(defptr)#0 byte opcode, j, A_IS_TOS, X_IS_IFP //puts("JIT compiler invoked for :$"); puth(defptr=>bytecodeaddr); putln + defptr=>interpaddr = indirectentry // assume compile will fail addrxlate = heapmark // heapalloc(512 + defptr->bytecodesize) //if not addrxlate if isult(heapavail, 512 + defptr->bytecodesize) // 256 * sizeof(word) address xlate @@ -18,7 +19,6 @@ def compiler(defptr)#0 // Not enough heap available // //puts("Not enough free heap\n") - defptr=>interpaddr = indirectentry return fin // @@ -159,7 +159,6 @@ def compiler(defptr)#0 codeptr->3 = $C0 // NATV CODE codeptr = codeptr + 4 i = 0 - fin while isule(codeptr, codemax) //putc('$'); puth(codeptr); putc(':') @@ -1319,10 +1318,7 @@ def compiler(defptr)#0 fin loop // - // If we got here. we ran out of code buffer space. Overwrite interpreter - // entrypoint with standard bytecode interpreter - // - defptr=>interpaddr = indirectentry + // If we got here we ran out of code buffer space. // // Free working bufffers // diff --git a/src/libsrc/jitcore.pla b/src/libsrc/jitcore.pla index be2bcea..5286233 100644 --- a/src/libsrc/jitcore.pla +++ b/src/libsrc/jitcore.pla @@ -29,6 +29,7 @@ def compiler(defptr)#0 byte opcode, j, A_IS_TOSL //puts("JIT compiler invoked for :$"); puth(defptr=>bytecodeaddr); putln + defptr=>interpaddr = indirectentry // assume compile will fail addrxlate = heapmark // heapalloc(512 + defptr->bytecodesize) //if not addrxlate if isult(heapavail, 512 + defptr->bytecodesize) // 256 * sizeof(word) address xlate @@ -36,7 +37,6 @@ def compiler(defptr)#0 // Not enough heap available // //puts("Not enough free heap\n") - defptr=>interpaddr = indirectentry return fin // @@ -1545,10 +1545,7 @@ def compiler(defptr)#0 fin loop // - // If we got here. we ran out of code buffer space. Overwrite interpreter - // entrypoint with standard bytecode interpreter - // - defptr=>interpaddr = indirectentry + // If we got here we ran out of code buffer space. // // Free working bufffers // diff --git a/src/tftpbld b/src/tftpbld index 4acd1b0..7aa59dc 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -31,3 +31,4 @@ echo "BLD/INC/TESTLIB.PLH"; atftp $1 --put -l inc/testlib.plh -r $2/BLD/INC/TES echo "BLD/MOUSETEST.PLA"; atftp $1 --put -l samplesrc/mousetest.pla -r $2/BLD/MOUSETEST.PLA#040000 echo "BLD/HTTPD.PLA"; atftp $1 --put -l samplesrc/httpd.pla -r $2/BLD/HTTPD.PLA#040000 echo "BLD/LZ4CAT.PLA"; atftp $1 --put -l samplesrc/lz4cat.pla -r $2/BLD/LZ4CAT.PLA#040000 +echo "BLD/ROD.PLA"; atftp $1 --put -l samplesrc/rod.pla -r $2/BLD/ROD.PLA#040000 From e2d1fb3ba48ffd4f6b1c8ee801d488e7e82adfdf Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sat, 7 Dec 2019 13:42:03 -0800 Subject: [PATCH 013/149] Add online volume call and more tftp scripts --- src/inc/fileio.plh | 1 + src/libsrc/apple/fileio.pla | 58 +++++++++++++++++++++++++++++++++++-- src/samplesrc/tftpd.pla | 19 +++++++++++- src/tftpbld | 1 + src/tftpdemos | 3 ++ src/tftprel | 6 ++++ src/tftpsane | 8 +++++ src/tftpsys | 3 -- 8 files changed, 93 insertions(+), 6 deletions(-) create mode 100755 src/tftprel create mode 100755 src/tftpsane diff --git a/src/inc/fileio.plh b/src/inc/fileio.plh index 699a514..9b88405 100644 --- a/src/inc/fileio.plh +++ b/src/inc/fileio.plh @@ -46,6 +46,7 @@ import fileio word create word destroy word newline + word online word readblock word writeblock end diff --git a/src/libsrc/apple/fileio.pla b/src/libsrc/apple/fileio.pla index 9f5e6db..f006ff5 100644 --- a/src/libsrc/apple/fileio.pla +++ b/src/libsrc/apple/fileio.pla @@ -35,19 +35,20 @@ struc t_fileio word create word destroy word newline + word online word readblock word writeblock end predef a2getpfx(path), a23setpfx(path), a2getfileinfo(path, fileinfo), a23geteof(refnum), a2iobufs(iobufs), a2open(path), a2close(refnum) predef a23read(refnum, buf, len), a2write(refnum, buf, len), a2create(path, type, aux), a23destroy(path) -predef a2newline(refnum, emask, nlchar), a2readblock(unit, buf, block), a2writeblock(unit, buf, block) +predef a2newline(refnum, emask, nlchar), a2online(unit, buf), a2readblock(unit, buf, block), a2writeblock(unit, buf, block) // // Exported function table. // word fileio[] word = @a2getpfx, @a23setpfx, @a2getfileinfo, @a23geteof, @a2iobufs, @a2open, @a2close word = @a23read, @a2write, @a2create, @a23destroy -word = @a2newline, @a2readblock, @a2writeblock +word = @a2newline, @a2online, @a2readblock, @a2writeblock // // SOS/ProDOS error code // @@ -325,6 +326,57 @@ def a3newline(refnum, emask, nlchar) perr = syscall($C9, @params) return perr end +def a1online(unit, buf) + perr = $27 // IOERR + return perr +end +def a2online(unit, buf) + byte params[4] + + params.0 = 2 + params.1 = unit + params:2 = buf + perr = syscall($C5, @params) + return perr +end +def a3volume(unit, volname) + byte devname[17] + byte info[11] + byte params[9] + + ^volname = 0 + params.0 = 4 + params.1 = unit + params:2 = @devname + params:4 = @info + params.6 = 11 + if syscall($85, @params) == 0 + params.0 = 4 + params:1 = @devname + params:3 = volname + params:5 = 0 + params:7 = 0 + return syscall($C5, @params) + fin + return -1 +end +def a3online(unit, buf) + byte info[11] + byte volname[17] + byte i + + if unit == 0 + for i = $01 to $0F + if a3volume(i, buf) == 0 + ^buf = ^buf | (i << 4) + fin + buf = buf + 16 + next + else + return a3volume(unit, buf) + fin + return 0 +end def a13readblock(unit, buf, block) perr = $27 // IOERR return perr @@ -366,6 +418,7 @@ when MACHID & MACHID_MODEL fileio:write = @a3write fileio:create = @a3create fileio:newline = @a3newline + fileio:online = @a3online fileio:readblock = @a13readblock fileio:writeblock = @a13writeblock break @@ -382,6 +435,7 @@ when MACHID & MACHID_MODEL fileio:create = @a1create fileio:destroy = @a1destroy fileio:newline = @a1newline + fileio:online = @a1online fileio:readblock = @a13readblock fileio:writeblock = @a13writeblock break diff --git a/src/samplesrc/tftpd.pla b/src/samplesrc/tftpd.pla index c9143d1..90a63a4 100644 --- a/src/samplesrc/tftpd.pla +++ b/src/samplesrc/tftpd.pla @@ -354,10 +354,26 @@ def servUDP(ipsrc, portsrc, data, len, param) return 0 end +def volumes#0 + word strbuf + byte i + + strbuf = heapmark() + fileio:online(0, strbuf) + for i = 0 to 15 + ^strbuf = ^strbuf & $0F + if ^strbuf + putc('/'); puts(strbuf); putln() + fin + strbuf = strbuf + 16 + next +end + +puts("TFTP Server Version 2.0 Dev\n") if !iNet:initIP() return -1 fin -puts("TFTP Server Version 2.0 Dev\n") +puts("Online volumes:\n"); volumes() portTFTP = iNet:openUDP(TFTP_PORT, @servUDP, 0) // // Alloc aligned file/io buffers @@ -370,6 +386,7 @@ buff=>datOp = $0300 // Data op repeat iNet:serviceIP() until conio:keypressed() +getc // eat keypress done Experpts from: RFC 1350, TFTP Revision 2, July 1992 diff --git a/src/tftpbld b/src/tftpbld index 7aa59dc..026b02a 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -32,3 +32,4 @@ echo "BLD/MOUSETEST.PLA"; atftp $1 --put -l samplesrc/mousetest.pla -r $2/BLD/MO echo "BLD/HTTPD.PLA"; atftp $1 --put -l samplesrc/httpd.pla -r $2/BLD/HTTPD.PLA#040000 echo "BLD/LZ4CAT.PLA"; atftp $1 --put -l samplesrc/lz4cat.pla -r $2/BLD/LZ4CAT.PLA#040000 echo "BLD/ROD.PLA"; atftp $1 --put -l samplesrc/rod.pla -r $2/BLD/ROD.PLA#040000 +echo "BLD/RPNCALC.PLA"; atftp $1 --put -l samplesrc/rpncalc.pla -r $2/BLD/RPNCALC.PLA#040000 diff --git a/src/tftpdemos b/src/tftpdemos index c6fe200..1d6ea37 100755 --- a/src/tftpdemos +++ b/src/tftpdemos @@ -1,4 +1,7 @@ #!/bin/bash # Net demos +echo "RPNCALC"; atftp $1 --put -l rel/RPNCALC#FE1000 -r $2/DEMOS/RPNCALC#FE1000 echo "NET/TFTPD"; atftp $1 --put -l rel/TFTPD#FE1000 -r $2/DEMOS/NET/TFTPD#FE1000 +echo "NET/HTTPD"; atftp $1 --put -l rel/HTTPD#FE1000 -r $2/DEMOS/NET/HTTPD#FE1000 + atftp $1 --put -l samplesrc/index.html -r $2/DEMOS/NET/INDEX.HTML#040000 diff --git a/src/tftprel b/src/tftprel new file mode 100755 index 0000000..3fbd73f --- /dev/null +++ b/src/tftprel @@ -0,0 +1,6 @@ +#!/bin/bash + +./tftpsys $1 $2 +./tftpsane $1 $2 +./tftpbld $1 $2 +./tftpdemos $1 $2 diff --git a/src/tftpsane b/src/tftpsane new file mode 100755 index 0000000..d60dbd9 --- /dev/null +++ b/src/tftpsane @@ -0,0 +1,8 @@ +#!/bin/bash + +# SANE libraries +echo "SYS/SANE"; atftp $1 --put -l rel/SANE#FE1000 -r $2/SYS/SANE#FE1000 +echo "SYS/FPSTR"; atftp $1 --put -l rel/FPSTR#FE1000 -r $2/SYS/FPSTR#FE1000 +echo "SYS/FPU"; atftp $1 --put -l rel/FPU#FE1000 -r $2/SYS/FPU#FE1000 +echo "SYS/FP6502.CODE"; atftp $1 --put -l ../sysfiles/FP6502.CODE#060000 -r $2/SYS/FP6502.CODE#060000 +echo "SYS/ELEMS.CODE"; atftp $1 --put -l ../sysfiles/ELEMS.CODE#060000 -r $2/SYS/ELEMS.CODE#060000 diff --git a/src/tftpsys b/src/tftpsys index e4db851..5306130 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -17,13 +17,10 @@ echo "SYS/ED"; atftp $1 --put -l rel/ED#FE1000 -r $2/SYS/ED#FE1000 echo "SYS/ETHERIP"; atftp $1 --put -l rel/ETHERIP#FE1000 -r $2/SYS/ETHERIP#FE1000 echo "SYS/MOUSE"; atftp $1 --put -l rel/apple/MOUSE#FE1000 -r $2/SYS/MOUSE#FE1000 echo "SYS/FIBER"; atftp $1 --put -l rel/FIBER#FE1000 -r $2/SYS/FIBER#FE1000 -echo "SYS/FPSTR"; atftp $1 --put -l rel/FPSTR#FE1000 -r $2/SYS/FPSTR#FE1000 -echo "SYS/FPU"; atftp $1 --put -l rel/FPU#FE1000 -r $2/SYS/FPU#FE1000 echo "SYS/INET"; atftp $1 --put -l rel/INET#FE1000 -r $2/SYS/INET#FE1000 echo "SYS/LONGJUMP"; atftp $1 --put -l rel/LONGJMP#FE1000 -r $2/SYS/LONGJMP#FE1000 echo "SYS/LZ4"; atftp $1 --put -l rel/LZ4#FE1000 -r $2/SYS/LZ4#FE1000 echo "SYS/MEMMGR"; atftp $1 --put -l rel/MEMMGR#FE1000 -r $2/SYS/MEMMGR#FE1000 -echo "SYS/SANE"; atftp $1 --put -l rel/SANE#FE1000 -r $2/SYS/SANE#FE1000 echo "SYS/CONIO"; atftp $1 --put -l rel/apple/CONIO#FE1000 -r $2/SYS/CONIO#FE1000 echo "SYS/DGR"; atftp $1 --put -l rel/apple/DGR#FE1000 -r $2/SYS/DGR#FE1000 echo "SYS/FILEIO"; atftp $1 --put -l rel/apple/FILEIO#FE1000 -r $2/SYS/FILEIO#FE1000 From 517b60d86f5553516d6233ad603b369067a94c1a Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sat, 7 Dec 2019 17:03:31 -0800 Subject: [PATCH 014/149] TFTP full release to physical Apple II --- src/makefile | 2 +- src/tftpbld | 38 ++++++++++++++++++++++++++++++++------ src/tftpdemos | 34 ++++++++++++++++++++++++++++++---- src/tftpsys | 2 +- 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/makefile b/src/makefile index bf3c631..9699cf1 100755 --- a/src/makefile +++ b/src/makefile @@ -17,7 +17,7 @@ JIT = rel/apple/JIT\#FE1000 JIT16 = rel/apple/JIT16\#FE1000 JITUNE = rel/apple/JITUNE\#FE1000 SOS = rel/apple/SOS\#FE1000 -ROD = rel/ROD\#FE1000 +ROD = rel/apple/ROD\#FE1000 SIEVE = rel/SIEVE\#FE1000 PRIMEGAP = rel/PRIMEGAP\#FE1000 ARGS = rel/ARGS\#FE1000 diff --git a/src/tftpbld b/src/tftpbld index 026b02a..d4af11b 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -27,9 +27,35 @@ echo "BLD/INC/SNDSEQ.PLH"; atftp $1 --put -l inc/sndseq.plh -r $2/BLD/INC/SND echo "BLD/INC/SPIPORT.PLH"; atftp $1 --put -l inc/spiport.plh -r $2/BLD/INC/SPIPORT.PLH#040000 echo "BLD/INC/TESTLIB.PLH"; atftp $1 --put -l inc/testlib.plh -r $2/BLD/INC/TESTLIB.PLH#040000 -# Sample source -echo "BLD/MOUSETEST.PLA"; atftp $1 --put -l samplesrc/mousetest.pla -r $2/BLD/MOUSETEST.PLA#040000 -echo "BLD/HTTPD.PLA"; atftp $1 --put -l samplesrc/httpd.pla -r $2/BLD/HTTPD.PLA#040000 -echo "BLD/LZ4CAT.PLA"; atftp $1 --put -l samplesrc/lz4cat.pla -r $2/BLD/LZ4CAT.PLA#040000 -echo "BLD/ROD.PLA"; atftp $1 --put -l samplesrc/rod.pla -r $2/BLD/ROD.PLA#040000 -echo "BLD/RPNCALC.PLA"; atftp $1 --put -l samplesrc/rpncalc.pla -r $2/BLD/RPNCALC.PLA#040000 +# Sample sources +echo "BLD/SAMPLES/HELLO.PLA"; atftp $1 --put -l samplesrc/hello.pla -r $2/BLD/SAMPLES/HELLO.PLA#040000 +echo "BLD/SAMPLES/TESTLIB.PLA"; atftp $1 --put -l samplesrc/testlib.pla -r $2/BLD/SAMPLES/TESTLIB.PLA#040000 +echo "BLD/SAMPLES/TEST.PLA"; atftp $1 --put -l samplesrc/test.pla -r $2/BLD/SAMPLES/TEST.PLA#040000 +echo "BLD/SAMPLES/FIBERTEST.PLA"; atftp $1 --put -l samplesrc/fibertest.pla -r $2/BLD/SAMPLES/FIBERTEST.PLA#040000 +echo "BLD/SAMPLES/MOUSETEST.PLA"; atftp $1 --put -l samplesrc/mousetest.pla -r $2/BLD/SAMPLES/MOUSETEST.PLA#040000 +echo "BLD/SAMPLES/ROD.PLA"; atftp $1 --put -l samplesrc/rod.pla -r $2/BLD/SAMPLES/ROD.PLA#040000 +echo "BLD/SAMPLES/DGRTEST.PLA"; atftp $1 --put -l samplesrc/dgrtest.pla -r $2/BLD/SAMPLES/DGRTEST.PLA#040000 +echo "BLD/SAMPLES/HGR1TEST.PLA"; atftp $1 --put -l samplesrc/hgr1test.pla -r $2/BLD/SAMPLES/HGR1TEST.PLA#040000 +echo "BLD/SAMPLES/PLAYSEQ.PLA"; atftp $1 --put -l samplesrc/playseq.pla -r $2/BLD/SAMPLES/PLAYSEQ.PLA#040000 +echo "BLD/SAMPLES/RPNCALC.PLA"; atftp $1 --put -l samplesrc/rpncalc.pla -r $2/BLD/SAMPLES/RPNCALC.PLA#040000 +echo "BLD/SAMPLES/SIEVE.PLA"; atftp $1 --put -l samplesrc/sieve.pla -r $2/BLD/SAMPLES/SIEVE.PLA#040000 + +# Examples from video series +echo "BLD/EXAMPLES/EX.1.PLA"; atftp $1 --put -l samplesrc/examples/ex.1.pla -r $2/BLD/EXAMPLES/EX.1.PLA#040000 +echo "BLD/EXAMPLES/EX.2.PLA"; atftp $1 --put -l samplesrc/examples/ex.2.pla -r $2/BLD/EXAMPLES/EX.2.PLA#040000 +echo "BLD/EXAMPLES/EX.3.PLA"; atftp $1 --put -l samplesrc/examples/ex.3.pla -r $2/BLD/EXAMPLES/EX.3.PLA#040000 +echo "BLD/EXAMPLES/EX.4.PLA"; atftp $1 --put -l samplesrc/examples/ex.4.pla -r $2/BLD/EXAMPLES/EX.4.PLA#040000 +echo "BLD/EXAMPLES/EX.5.PLA"; atftp $1 --put -l samplesrc/examples/ex.5.pla -r $2/BLD/EXAMPLES/EX.5.PLA#040000 +echo "BLD/EXAMPLES/EX.6.PLA"; atftp $1 --put -l samplesrc/examples/ex.6.pla -r $2/BLD/EXAMPLES/EX.6.PLA#040000 +echo "BLD/EXAMPLES/EX.7.PLA"; atftp $1 --put -l samplesrc/examples/ex.7.pla -r $2/BLD/EXAMPLES/EX.7.PLA#040000 +echo "BLD/EXAMPLES/EX.8.PLA"; atftp $1 --put -l samplesrc/examples/ex.8.pla -r $2/BLD/EXAMPLES/EX.8.PLA#040000 +echo "BLD/EXAMPLES/EX.9.PLA"; atftp $1 --put -l samplesrc/examples/ex.9.pla -r $2/BLD/EXAMPLES/EX.9.PLA#040000 +echo "BLD/EXAMPLES/EX.10.PLA"; atftp $1 --put -l samplesrc/examples/ex.10.pla -r $2/BLD/EXAMPLES/EX.10.PLA#040000 +echo "BLD/EXAMPLES/EX.11.PLA"; atftp $1 --put -l samplesrc/examples/ex.11.pla -r $2/BLD/EXAMPLES/EX.11.PLA#040000 +echo "BLD/EXAMPLES/EX.12.PLA"; atftp $1 --put -l samplesrc/examples/ex.12.pla -r $2/BLD/EXAMPLES/EX.12.PLA#040000 +echo "BLD/EXAMPLES/EX.13.PLA"; atftp $1 --put -l samplesrc/examples/ex.13.pla -r $2/BLD/EXAMPLES/EX.13.PLA#040000 +echo "BLD/EXAMPLES/EX.14.PLA"; atftp $1 --put -l samplesrc/examples/ex.14.pla -r $2/BLD/EXAMPLES/EX.14.PLA#040000 +echo "BLD/EXAMPLES/EX.15.PLA"; atftp $1 --put -l samplesrc/examples/ex.15.pla -r $2/BLD/EXAMPLES/EX.15.PLA#040000 +echo "BLD/EXAMPLES/EX.16.PLA"; atftp $1 --put -l samplesrc/examples/ex.16.pla -r $2/BLD/EXAMPLES/EX.16.PLA#040000 +echo "BLD/EXAMPLES/EX.17.PLA"; atftp $1 --put -l samplesrc/examples/ex.17.pla -r $2/BLD/EXAMPLES/EX.17.PLA#040000 + diff --git a/src/tftpdemos b/src/tftpdemos index 1d6ea37..5a9bca3 100755 --- a/src/tftpdemos +++ b/src/tftpdemos @@ -1,7 +1,33 @@ #!/bin/bash +# Demos +echo "DEMOS/RPNCALC"; atftp $1 --put -l rel/RPNCALC#FE1000 -r $2/DEMOS/RPNCALC#FE1000 +echo "DEMOS/LZ4CAT"; atftp $1 --put -l rel/LZ4CAT#FE1000 -r $2/DEMOS/LZ4CAT#FE1000 +echo "DEMOS/SIEVE"; atftp $1 --put -l rel/SIEVE#FE1000 -r $2/DEMOS/SIEVE#FE1000 +echo "DEMOS/ROD"; atftp $1 --put -l rel/apple/ROD#FE1000 -r $2/DEMOS/ROD#FE1000 +echo "DEMOS/DGRTEST"; atftp $1 --put -l rel/apple/DGRTEST#FE1000 -r $2/DEMOS/DGRTEST#FE1000 + +# Music demo +echo "DEMOS/MUSIC/PLAYSEQ"; atftp $1 --put -l rel/apple/PLAYSEQ#FE1000 -r $2/DEMOS/MUSIC/PLAYSEQ#FE1000 + atftp $1 --put -l mockingboard/ultima3.seq -r $2/DEMOS/MUSIC/ULTIMA3.SEQ#060000 + atftp $1 --put -l mockingboard/startrek.seq -r $2/DEMOS/MUSIC/STARTREK.SEQ#060000 +# Rogue demo +echo "DEMOS/ROGUE/ROGUE"; atftp $1 --put -l rel/ROGUE#FE1000 -r $2/DEMOS/ROGUE/ROGUE#FE1000 +echo "DEMOS/ROGUE/ROGUEMAP"; atftp $1 --put -l rel/ROGUEMAP#FE1000 -r $2/DEMOS/ROGUE/ROGUEMAP#FE1000 +echo "DEMOS/ROGUE/ROGUECOMBAT"; atftp $1 --put -l rel/ROGUECOMBAT#FE1000 -r $2/DEMOS/ROGUE/ROGUECOMBAT#FE1000 + atftp $1 --put -l samplesrc/LEVEL0#040000 -r $2/DEMOS/ROGUE/LEVEL0#040000 + atftp $1 --put -l samplesrc/LEVEL1#040000 -r $2/DEMOS/ROGUE/LEVEL1#040000 + +# Arduino+SD card demos +echo "DEMOS/SDUTILS/SPIPORT"; atftp $1 --put -l rel/apple/SPIPORT#FE1000 -r $2/DEMOS/SDUTILS/SPIPORT#FE1000 +echo "DEMOS/SDUTILS/SDFAT"; atftp $1 --put -l rel/apple/SDFAT#FE1000 -r $2/DEMOS/SDUTILS/SDFAT#FE1000 +echo "DEMOS/SDUTILS/FATCAT"; atftp $1 --put -l rel/apple/FATCAT#FE1000 -r $2/DEMOS/SDUTILS/FATCAT#FE1000 +echo "DEMOS/SDUTILS/FATGET"; atftp $1 --put -l rel/apple/FATGET#FE1000 -r $2/DEMOS/SDUTILS/FATGET#FE1000 +echo "DEMOS/SDUTILS/FATPUT"; atftp $1 --put -l rel/apple/FATPUT#FE1000 -r $2/DEMOS/SDUTILS/FATPUT#FE1000 +echo "DEMOS/SDUTILS/FATREADDSK"; atftp $1 --put -l rel/apple/FATREADDSK#FE1000 -r $2/DEMOS/SDUTILS/FATREADDSK#FE1000 +echo "DEMOS/SDUTILS/FATWRITEDSK"; atftp $1 --put -l rel/apple/FATWRITEDSK#FE1000 -r $2/DEMOS/SDUTILS/FATWRITEDSK#FE1000 + # Net demos -echo "RPNCALC"; atftp $1 --put -l rel/RPNCALC#FE1000 -r $2/DEMOS/RPNCALC#FE1000 -echo "NET/TFTPD"; atftp $1 --put -l rel/TFTPD#FE1000 -r $2/DEMOS/NET/TFTPD#FE1000 -echo "NET/HTTPD"; atftp $1 --put -l rel/HTTPD#FE1000 -r $2/DEMOS/NET/HTTPD#FE1000 - atftp $1 --put -l samplesrc/index.html -r $2/DEMOS/NET/INDEX.HTML#040000 +echo "DEMOS/NET/TFTPD"; atftp $1 --put -l rel/TFTPD#FE1000 -r $2/DEMOS/NET/TFTPD#FE1000 +echo "DEMOS/NET/HTTPD"; atftp $1 --put -l rel/HTTPD#FE1000 -r $2/DEMOS/NET/HTTPD#FE1000 + atftp $1 --put -l samplesrc/index.html -r $2/DEMOS/NET/INDEX.HTML#040000 diff --git a/src/tftpsys b/src/tftpsys index 5306130..57a7079 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -26,8 +26,8 @@ echo "SYS/DGR"; atftp $1 --put -l rel/apple/DGR#FE1000 -r $2/SYS/DGR#FE1000 echo "SYS/FILEIO"; atftp $1 --put -l rel/apple/FILEIO#FE1000 -r $2/SYS/FILEIO#FE1000 echo "SYS/GRAFIX"; atftp $1 --put -l rel/apple/GRAFIX#FE1000 -r $2/SYS/GRAFIX#FE1000 echo "SYS/JOYBUZZ"; atftp $1 --put -l rel/apple/JOYBUZZ#FE1000 -r $2/SYS/JOYBUZZ#FE1000 +echo "SYS/SNDSEQ"; atftp $1 --put -l rel/apple/SNDSEQ#FE1000 -r $2/SYS/SNDSEQ#FE1000 echo "SYS/MON"; atftp $1 --put -l rel/apple/MON#FE1000 -r $2/SYS/MON#FE1000 echo "SYS/PORTIO"; atftp $1 --put -l rel/apple/PORTIO#FE1000 -r $2/SYS/PORTIO#FE1000 -echo "SYS/SPIPORT"; atftp $1 --put -l rel/apple/SPIPORT#FE1000 -r $2/SYS/SPIPORT#FE1000 echo "SYS/UTHERNET2";atftp $1 --put -l rel/apple/UTHERNET2#FE1000 -r $2/SYS/UTHERNET2#FE1000 echo "SYS/UTHERNET"; atftp $1 --put -l rel/apple/UTHERNET#FE1000 -r $2/SYS/UTHERNET#FE1000 From 0df8f864e7114e12d1ab0468709bf419302044ad Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sat, 7 Dec 2019 17:06:54 -0800 Subject: [PATCH 015/149] Add autorun TFTPD floppy image --- images/apple/TFTPD.PO | Bin 0 -> 143360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/apple/TFTPD.PO diff --git a/images/apple/TFTPD.PO b/images/apple/TFTPD.PO new file mode 100644 index 0000000000000000000000000000000000000000..6c00083c0da352082798e00ee1bf227ebf6efc53 GIT binary patch literal 143360 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 Date: Sat, 7 Dec 2019 18:00:12 -0800 Subject: [PATCH 016/149] Make mkrel and tftprel consistent --- src/mkrel | 206 ++++++++++++++++++++++++++++------------------------ src/tftpbld | 5 ++ 2 files changed, 118 insertions(+), 93 deletions(-) diff --git a/src/mkrel b/src/mkrel index a458b86..77422c3 100755 --- a/src/mkrel +++ b/src/mkrel @@ -1,84 +1,84 @@ -cp rel/apple/CMD#061000 prodos/CMD.BIN -cp rel/apple/CMD128#061000 prodos/CMD128.BIN +cp rel/apple/CMD#061000 prodos/CMD.BIN +cp rel/apple/CMD128#061000 prodos/CMD128.BIN cp rel/apple/PLASMA.SYSTEM#FF2000 prodos/PLASMA.SYSTEM.SYS -cp rel/apple/PLVM.128#FF2000 prodos/PLVM.128.SYS -cp rel/apple/PLVM16#FF2000 prodos/PLVM16.SYS -cp ../doc/Editor.md prodos/EDITOR.README.TXT +cp rel/apple/PLVM.128#FF2000 prodos/PLVM.128.SYS +cp rel/apple/PLVM16#FF2000 prodos/PLVM16.SYS +cp ../doc/Editor.md prodos/EDITOR.README.TXT rm -rf prodos/sys mkdir prodos/sys -cp rel/apple/FILEIO#FE1000 prodos/sys/FILEIO.REL -cp rel/apple/CONIO#FE1000 prodos/sys/CONIO.REL -cp rel/apple/DGR#FE1000 prodos/sys/DGR.REL -cp rel/ARGS#FE1000 prodos/sys/ARGS.REL -cp rel/ED#FE1000 prodos/sys/ED.REL -cp rel/FIBER#FE1000 prodos/sys/FIBER.REL -cp rel/LONGJMP#FE1000 prodos/sys/LONGJMP.REL -cp rel/MEMMGR#FE1000 prodos/sys/MEMMGR.REL -cp rel/INET#FE1000 prodos/sys/INET.REL -cp rel/DHCP#FE1000 prodos/sys/DHCP.REL -cp rel/ETHERIP#FE1000 prodos/sys/ETHERIP.REL -cp rel/apple/MOUSE#FE1000 prodos/sys/MOUSE.REL -cp rel/apple/UTHERNET2#FE1000 prodos/sys/UTHERNET2.REL -cp rel/apple/UTHERNET#FE1000 prodos/sys/UTHERNET.REL -cp rel/apple/PORTIO#FE1000 prodos/sys/PORTIO.REL -cp rel/apple/JOYBUZZ#FE1000 prodos/sys/JOYBUZZ.REL -cp rel/apple/SDFAT#FE1000 prodos/sys/SDFAT.REL -cp rel/apple/SPIPORT#FE1000 prodos/sys/SPIPORT.REL -cp rel/apple/SNDSEQ#FE1000 prodos/sys/SNDSEQ.REL -cp rel/apple/JIT#FE1000 prodos/sys/JIT.REL -cp rel/apple/JIT16#FE1000 prodos/sys/JIT16.REL -cp rel/apple/JITUNE#FE1000 prodos/sys/JITUNE.REL -cp rel/LZ4#FE1000 prodos/sys/LZ4.REL -cp rel/FPSTR#FE1000 prodos/sys/FPSTR.REL -cp rel/FPU#FE1000 prodos/sys/FPU.REL -cp rel/SANE#FE1000 prodos/sys/SANE.REL +cp rel/apple/FILEIO#FE1000 prodos/sys/FILEIO.REL +cp rel/apple/CONIO#FE1000 prodos/sys/CONIO.REL +cp rel/apple/DGR#FE1000 prodos/sys/DGR.REL +cp rel/ARGS#FE1000 prodos/sys/ARGS.REL +cp rel/ED#FE1000 prodos/sys/ED.REL +cp rel/FIBER#FE1000 prodos/sys/FIBER.REL +cp rel/LONGJMP#FE1000 prodos/sys/LONGJMP.REL +cp rel/MEMMGR#FE1000 prodos/sys/MEMMGR.REL +cp rel/INET#FE1000 prodos/sys/INET.REL +cp rel/DHCP#FE1000 prodos/sys/DHCP.REL +cp rel/ETHERIP#FE1000 prodos/sys/ETHERIP.REL +cp rel/apple/MOUSE#FE1000 prodos/sys/MOUSE.REL +cp rel/apple/UTHERNET2#FE1000 prodos/sys/UTHERNET2.REL +cp rel/apple/UTHERNET#FE1000 prodos/sys/UTHERNET.REL +cp rel/apple/PORTIO#FE1000 prodos/sys/PORTIO.REL +cp rel/apple/JOYBUZZ#FE1000 prodos/sys/JOYBUZZ.REL +cp rel/apple/SDFAT#FE1000 prodos/sys/SDFAT.REL +cp rel/apple/SNDSEQ#FE1000 prodos/sys/SNDSEQ.REL +cp rel/apple/JIT#FE1000 prodos/sys/JIT.REL +cp rel/apple/JIT16#FE1000 prodos/sys/JIT16.REL +cp rel/apple/JITUNE#FE1000 prodos/sys/JITUNE.REL +cp rel/LZ4#FE1000 prodos/sys/LZ4.REL +cp rel/FPSTR#FE1000 prodos/sys/FPSTR.REL +cp rel/FPU#FE1000 prodos/sys/FPU.REL +cp rel/SANE#FE1000 prodos/sys/SANE.REL cp ../sysfiles/FP6502.CODE#060000 prodos/sys/FP6502.CODE.BIN -cp ../sysfiles/ELEMS.CODE#060000 prodos/sys/ELEMS.CODE.BIN +cp ../sysfiles/ELEMS.CODE#060000 prodos/sys/ELEMS.CODE.BIN rm -rf prodos/fpsos mkdir prodos/fpsos cp rel/apple/SOS.INTERP#050000 prodos/fpsos/SOS.INTERP.\$05 -cp rel/apple/SOS.CMD#FE1000 prodos/fpsos/SOS.CMD.REL +cp rel/apple/SOS.CMD#FE1000 prodos/fpsos/SOS.CMD.REL mkdir prodos/fpsos/sys -cp rel/apple/SOS#FE1000 prodos/fpsos/sys/SOS.REL -cp rel/apple/GRAFIX#FE1000 prodos/fpsos/sys/GRAFIX.REL -cp rel/FPSTR#FE1000 prodos/fpsos/sys/FPSTR.REL -cp rel/FPU#FE1000 prodos/fpsos/sys/FPU.REL -cp rel/SANE#FE1000 prodos/fpsos/sys/SANE.REL +cp rel/apple/SOS#FE1000 prodos/fpsos/sys/SOS.REL +cp rel/apple/GRAFIX#FE1000 prodos/fpsos/sys/GRAFIX.REL +cp rel/FPSTR#FE1000 prodos/fpsos/sys/FPSTR.REL +cp rel/FPU#FE1000 prodos/fpsos/sys/FPU.REL +cp rel/SANE#FE1000 prodos/fpsos/sys/SANE.REL cp ../sysfiles/FP6502.CODE#060000 prodos/fpsos/sys/FP6502.CODE.BIN -cp ../sysfiles/ELEMS.CODE#060000 prodos/fpsos/sys/ELEMS.CODE.BIN +cp ../sysfiles/ELEMS.CODE#060000 prodos/fpsos/sys/ELEMS.CODE.BIN rm -rf prodos/demos mkdir prodos/demos cp rel/apple/DGRTEST#FE1000 prodos/demos/DGRTEST.REL -cp rel/RPNCALC#FE1000 prodos/demos/RPNCALC.REL -cp rel/LZ4CAT#FE1000 prodos/demos/LZ4CAT.REL -cp rel/ROD#FE1000 prodos/demos/ROD.REL -cp rel/PRIMEGAP#FE1000 prodos/demos/PRIMEGAP.REL +cp rel/apple/ROD#FE1000 prodos/demos/ROD.REL +cp rel/RPNCALC#FE1000 prodos/demos/RPNCALC.REL +cp rel/LZ4CAT#FE1000 prodos/demos/LZ4CAT.REL +cp rel/PRIMEGAP#FE1000 prodos/demos/PRIMEGAP.REL mkdir prodos/demos/rogue -cp rel/ROGUE#FE1000 prodos/demos/rogue/ROGUE.REL -cp rel/ROGUECOMBAT#FE1000 prodos/demos/rogue/ROGUECOMBAT.REL -cp rel/ROGUEMAP#FE1000 prodos/demos/rogue/ROGUEMAP.REL +cp rel/ROGUE#FE1000 prodos/demos/rogue/ROGUE.REL +cp rel/ROGUECOMBAT#FE1000 prodos/demos/rogue/ROGUECOMBAT.REL +cp rel/ROGUEMAP#FE1000 prodos/demos/rogue/ROGUEMAP.REL cp samplesrc/LEVEL0#040000 prodos/demos/rogue/LEVEL0.TXT cp samplesrc/LEVEL1#040000 prodos/demos/rogue/LEVEL1.TXT mkdir prodos/demos/sdutils -cp rel/apple/FATCAT#FE1000 prodos/demos/sdutils/FATCAT.REL -cp rel/apple/FATGET#FE1000 prodos/demos/sdutils/FATGET.REL -cp rel/apple/FATPUT#FE1000 prodos/demos/sdutils/FATPUT.REL -cp rel/apple/FATREADDSK#FE1000 prodos/demos/sdutils/FATREADDSK.REL +cp rel/apple/SPIPORT#FE1000 prodos/demos/sdutils/SPIPORT.REL +cp rel/apple/FATCAT#FE1000 prodos/demos/sdutils/FATCAT.REL +cp rel/apple/FATGET#FE1000 prodos/demos/sdutils/FATGET.REL +cp rel/apple/FATPUT#FE1000 prodos/demos/sdutils/FATPUT.REL +cp rel/apple/FATREADDSK#FE1000 prodos/demos/sdutils/FATREADDSK.REL cp rel/apple/FATWRITEDSK#FE1000 prodos/demos/sdutils/FATWRITEDSK.REL mkdir prodos/demos/apple3 -cp rel/apple/GFXDEMO#FE1000 prodos/demos/apple3/GFXDEMO.REL +cp rel/apple/GFXDEMO#FE1000 prodos/demos/apple3/GFXDEMO.REL cp samplesrc/APPLE3.PIX#060000 prodos/demos/apple3/APPLE3.PIX.BIN mkdir prodos/demos/net -cp rel/TFTPD#FE1000 prodos/demos/net/TFTPD.REL -cp rel/HTTPD#FE1000 prodos/demos/net/HTTPD.REL +cp rel/TFTPD#FE1000 prodos/demos/net/TFTPD.REL +cp rel/HTTPD#FE1000 prodos/demos/net/HTTPD.REL cp samplesrc/index.html prodos/demos/net/INDEX.HTML.TXT mkdir prodos/demos/music @@ -88,46 +88,66 @@ cp mockingboard/startrek.seq prodos/demos/music/STARTREK.SEQ.BIN rm -rf prodos/bld mkdir prodos/bld -cp rel/PLASM#FE1000 prodos/bld/PLASM.REL -cp rel/CODEOPT#FE1000 prodos/bld/CODEOPT.REL -cp samplesrc/dgrtest.pla prodos/bld/DGRTEST.PLA.TXT -cp samplesrc/hello.pla prodos/bld/HELLO.PLA.TXT -cp samplesrc/hgr1test.pla prodos/bld/HGR1TEST.PLA.TXT -cp samplesrc/fibertest.pla prodos/bld/FIBERTEST.PLA.TXT -cp samplesrc/mousetest.pla prodos/bld/MOUSETEST.PLA.TXT -cp samplesrc/mon.pla prodos/bld/MON.PLA.TXT -cp samplesrc/memtest.pla prodos/bld/MEMTEST.PLA.TXT -cp samplesrc/rod.pla prodos/bld/ROD.PLA.TXT -cp samplesrc/sieve.pla prodos/bld/SIEVE.PLA.TXT -cp samplesrc/test.pla prodos/bld/TEST.PLA.TXT -cp samplesrc/testlib.pla prodos/bld/TESTLIB.PLA.TXT -cp samplesrc/playseq.pla prodos/bld/PLAYSEQ.PLA.TXT -cp samplesrc/rpncalc.pla prodos/bld/RPNCALC.PLA.TXT -cp samplesrc/httpd.pla prodos/bld/HTTPD.PLA.TXT -cp samplesrc/fatcat.pla prodos/bld/FATCAT.PLA.TXT -cp samplesrc/gfxdemo.pla prodos/bld/GFXDEMO.PLA.TXT -cp samplesrc/lz4cat.pla prodos/bld/LZ4CAT.PLA.TXT +cp rel/PLASM#FE1000 prodos/bld/PLASM.REL +cp rel/CODEOPT#FE1000 prodos/bld/CODEOPT.REL + +mkdir prodos/bld/samples +cp samplesrc/hello.pla prodos/bld/samples/HELLO.PLA.TXT +cp samplesrc/dgrtest.pla prodos/bld/samples/DGRTEST.PLA.TXT +cp samplesrc/hgr1test.pla prodos/bld/samples/HGR1TEST.PLA.TXT +cp samplesrc/fibertest.pla prodos/bld/samples/FIBERTEST.PLA.TXT +cp samplesrc/mousetest.pla prodos/bld/samples/MOUSETEST.PLA.TXT +cp samplesrc/mon.pla prodos/bld/samples/MON.PLA.TXT +cp samplesrc/memtest.pla prodos/bld/samples/MEMTEST.PLA.TXT +cp samplesrc/rod.pla prodos/bld/samples/ROD.PLA.TXT +cp samplesrc/sieve.pla prodos/bld/samples/SIEVE.PLA.TXT +cp samplesrc/test.pla prodos/bld/samples/TEST.PLA.TXT +cp samplesrc/testlib.pla prodos/bld/samples/TESTLIB.PLA.TXT +cp samplesrc/playseq.pla prodos/bld/samples/PLAYSEQ.PLA.TXT +cp samplesrc/rpncalc.pla prodos/bld/samples/RPNCALC.PLA.TXT +cp samplesrc/fatcat.pla prodos/bld/samples/FATCAT.PLA.TXT +cp samplesrc/gfxdemo.pla prodos/bld/samples/GFXDEMO.PLA.TXT +cp samplesrc/lz4cat.pla prodos/bld/samples/Z4CAT.PLA.TXT + +mkdir prodos/bld/examples +cp samplesrc/examples/ex.1.pla prodos/bld/examples/EX.1.PLA.TXT +cp samplesrc/examples/ex.2.pla prodos/bld/examples/EX.2.PLA.TXT +cp samplesrc/examples/ex.3.pla prodos/bld/examples/EX.3.PLA.TXT +cp samplesrc/examples/ex.4.pla prodos/bld/examples/EX.4.PLA.TXT +cp samplesrc/examples/ex.5.pla prodos/bld/examples/EX.5.PLA.TXT +cp samplesrc/examples/ex.6.pla prodos/bld/examples/EX.6.PLA.TXT +cp samplesrc/examples/ex.7.pla prodos/bld/examples/EX.7.PLA.TXT +cp samplesrc/examples/ex.8.pla prodos/bld/examples/EX.8.PLA.TXT +cp samplesrc/examples/ex.9.pla prodos/bld/examples/EX.9.PLA.TXT +cp samplesrc/examples/ex.10.pla prodos/bld/examples/EX.10.PLA.TXT +cp samplesrc/examples/ex.11.pla prodos/bld/examples/EX.11.PLA.TXT +cp samplesrc/examples/ex.12.pla prodos/bld/examples/EX.12.PLA.TXT +cp samplesrc/examples/ex.13.pla prodos/bld/examples/EX.13.PLA.TXT +cp samplesrc/examples/ex.14.pla prodos/bld/examples/EX.14.PLA.TXT +cp samplesrc/examples/ex.15.pla prodos/bld/examples/EX.15.PLA.TXT +cp samplesrc/examples/ex.16.pla prodos/bld/examples/EX.16.PLA.TXT +cp samplesrc/examples/ex.17.pla prodos/bld/examples/EX.17.PLA.TXT mkdir prodos/bld/inc -cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT -cp inc/cmdsys.plh prodos/bld/inc/CMDSYS.PLH.TXT -cp inc/conio.plh prodos/bld/inc/CONIO.PLH.TXT -cp inc/dgr.plh prodos/bld/inc/DGR.PLH.TXT -cp inc/fiber.plh prodos/bld/inc/FIBER.PLH.TXT -cp inc/fileio.plh prodos/bld/inc/FILEIO.PLH.TXT -cp inc/fpstr.plh prodos/bld/inc/FPSTR.PLH.TXT -cp inc/fpu.plh prodos/bld/inc/FPU.PLH.TXT -cp inc/mouse.plh prodos/bld/inc/MOUSE.PLH.TXT -cp inc/inet.plh prodos/bld/inc/INET.PLH.TXT -cp inc/longjmp.plh prodos/bld/inc/LONGJMP.PLH.TXT -cp inc/memmgr.plh prodos/bld/inc/MEMMGR.PLH.TXT -cp inc/sane.plh prodos/bld/inc/SANE.PLH.TXT -cp inc/joybuzz.plh prodos/bld/inc/JOYBUZZ.PLH.TXT -cp inc/portio.plh prodos/bld/inc/PORTIO.PLH.TXT -cp inc/sdfat.plh prodos/bld/inc/SDFAT.PLH.TXT -cp inc/sndseq.plh prodos/bld/inc/SNDSEQ.PLH.TXT -cp inc/spiport.plh prodos/bld/inc/SPIPORT.PLH.TXT -cp inc/testlib.plh prodos/bld/inc/TESTLIB.PLH.TXT -cp inc/grafix.plh prodos/bld/inc/GRAFIX.PLH.TXT -cp inc/lz4.plh prodos/bld/inc/LZ4.PLH.TXT +cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT +cp inc/cmdsys.plh prodos/bld/inc/CMDSYS.PLH.TXT +cp inc/conio.plh prodos/bld/inc/CONIO.PLH.TXT +cp inc/dgr.plh prodos/bld/inc/DGR.PLH.TXT +cp inc/fiber.plh prodos/bld/inc/FIBER.PLH.TXT +cp inc/fileio.plh prodos/bld/inc/FILEIO.PLH.TXT +cp inc/fpstr.plh prodos/bld/inc/FPSTR.PLH.TXT +cp inc/fpu.plh prodos/bld/inc/FPU.PLH.TXT +cp inc/mouse.plh prodos/bld/inc/MOUSE.PLH.TXT +cp inc/inet.plh prodos/bld/inc/INET.PLH.TXT +cp inc/longjmp.plh prodos/bld/inc/LONGJMP.PLH.TXT +cp inc/memmgr.plh prodos/bld/inc/MEMMGR.PLH.TXT +cp inc/sane.plh prodos/bld/inc/SANE.PLH.TXT +cp inc/joybuzz.plh prodos/bld/inc/JOYBUZZ.PLH.TXT +cp inc/portio.plh prodos/bld/inc/PORTIO.PLH.TXT +cp inc/sdfat.plh prodos/bld/inc/SDFAT.PLH.TXT +cp inc/sndseq.plh prodos/bld/inc/SNDSEQ.PLH.TXT +cp inc/spiport.plh prodos/bld/inc/SPIPORT.PLH.TXT +cp inc/testlib.plh prodos/bld/inc/TESTLIB.PLH.TXT +cp inc/grafix.plh prodos/bld/inc/GRAFIX.PLH.TXT +cp inc/lz4.plh prodos/bld/inc/LZ4.PLH.TXT cp vmsrc/apple/plvmzp.inc prodos/bld/inc/PLVMZP.INC.TXT diff --git a/src/tftpbld b/src/tftpbld index d4af11b..e5d03d3 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -39,6 +39,11 @@ echo "BLD/SAMPLES/HGR1TEST.PLA"; atftp $1 --put -l samplesrc/hgr1test.pla -r $ echo "BLD/SAMPLES/PLAYSEQ.PLA"; atftp $1 --put -l samplesrc/playseq.pla -r $2/BLD/SAMPLES/PLAYSEQ.PLA#040000 echo "BLD/SAMPLES/RPNCALC.PLA"; atftp $1 --put -l samplesrc/rpncalc.pla -r $2/BLD/SAMPLES/RPNCALC.PLA#040000 echo "BLD/SAMPLES/SIEVE.PLA"; atftp $1 --put -l samplesrc/sieve.pla -r $2/BLD/SAMPLES/SIEVE.PLA#040000 +echo "BLD/SAMPLES/MON.PLA"; atftp $1 --put -l samplesrc/mon.pla -r $2/BLD/SAMPLES/MON.PLA#040000 +echo "BLD/SAMPLES/MEMTEST.PLA"; atftp $1 --put -l samplesrc/memtest.pla -r $2/BLD/SAMPLES/MEMTEST.PLA#040000 +echo "BLD/SAMPLES/FATCAT.PLA"; atftp $1 --put -l samplesrc/fatcat.pla -r $2/BLD/SAMPLES/FATCAT.PLA#040000 +echo "BLD/SAMPLES/GFXDEMO.PLA"; atftp $1 --put -l samplesrc/gfxdemo.pla -r $2/BLD/SAMPLES/GFXDEMO.PLA#040000 +echo "BLD/SAMPLES/LZ4CAT.PLA"; atftp $1 --put -l samplesrc/lz4cat.pla -r $2/BLD/SAMPLES/LZ4CAT.PLA#040000 # Examples from video series echo "BLD/EXAMPLES/EX.1.PLA"; atftp $1 --put -l samplesrc/examples/ex.1.pla -r $2/BLD/EXAMPLES/EX.1.PLA#040000 From 30cdd22211d8cd5483c1c617c513c6165e406e97 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 7 Dec 2019 19:34:12 -0800 Subject: [PATCH 017/149] Update images --- images/apple/PLASMA-BLD2.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA-DEM2.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA-FPSOS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA-SYS2.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA.2mg | Bin 819264 -> 819264 bytes src/mkrel | 2 +- src/tftpsys | 1 - 7 files changed, 1 insertion(+), 2 deletions(-) diff --git a/images/apple/PLASMA-BLD2.PO b/images/apple/PLASMA-BLD2.PO index 5c06ff0ee3ee32325f2a64f29beae9b5bd2b0687..e12a48fe5b27125803f391ed0d0d12c294631a44 100644 GIT binary patch literal 143360 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 literal 143360 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 diff --git a/images/apple/PLASMA-DEM2.PO b/images/apple/PLASMA-DEM2.PO index de3ceeb01db011c52d787f2adf60a5157ea6323a..b008aff4b0c169b57f82fc4cc8ac1f5476597cc4 100644 GIT binary patch delta 4869 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 I!k>8l4;zHe=l}o! delta 44229 zcmbrn34Bw<-ta%?HcN>R6f1g5Nn=|}TT6&ol@Jt{ zDhH;tE_m& z)Z&5}7tC;%P8FgvRm6$`@#5Z_gjE;&CA)CdgPJq&_PDZ=NLcckGD@gIXyTjfoVc*y zh-6jdxysI)S}=6jh_Gy@Nr@L9TgCEhYholk#0Hm^Omsw^7RoXq<6L>7kee>5GchW>v+2@l%ge&U`1q{hBOFvh8{*tfV4&)tZ>p>NSc* zSQAkvIa(d(jA=6pCYQTQr@QocVm2vB;-5Xm-Pt{2b*;B$pAoN$9HQw?8hSiT;wH+( z8KLRXsN&sKz03~nm+Ui=ca1jt%t~O@Q;8E-btImvNoK-#U~Z( z>B*zSsqWGl?y|t-agp$}g~B9a)Dwd{b!zEUDcU7=C9xL8oFq2gRX)DBYOJ8C(7kdnmB!ERJ7V^s>nYqCyMo*FnL_*^lmwAgHS}B za-vx7^l4FXQa9U4YMBYKz;RhOP;WZjnRjfnC=~b1J}J2I(@ILGx!e)KWAD?#ZcaE+ ztmo8e<=rVI)=y9_?s(uM%MzL-Rno?jx(7}u$YRmEY+CumDN|itVx_2afjD04V$n;_(m+It;3gn<>mSIu zX1J$EiA_Z8%i~j*Tr8Zj_o#5u6pc!$O-8xtCn=XPxxBP10i+?IokMWtCk5BDtYUa~ zoG4d@SkXz!4VpS_=8V#AL9Luv>1U2>D#ap`x;=GbcOox?Im4vHB%DSRk z=raDMt}9w?QKwGpw%!~cKV#;3=g+#J;= zZ3oRLp+kwvqbl-f?n!y%oG`hpbn>(=Ijx%Zzy5??hpe1YUNWQf+-|WNBF)ev4RrTT z)CW3ThJbFlIuRqDjXf^$RGW@|K`d6aHKYea0@2}unUi`)sW znO#xJ0=$e^zd0$^OxcX0!qXNI+=`Q8?LB4M1>(@k=?Ma z=v7UfGq=0Y-qK7S?#o1y#=qXQEL5Cf zk~QN1D8^x!PYlzuMy%UO3z_r$Jr|v76u2*f76( zz9BNdslL|d7>2{NbGqCDj+*K@p6ceX%p8x0KrX5F{l!~bU;UTb25)2DAjjM}_4P&= zb8D*SUh42RHan_n8|E}$;gDkU^%&<@`yAsN8+_FbzQOJ*nyMXh=FV+w_S809Qh$Z? zJl|JaU+?fWdKyPM8W;GQ7Wf=hbLJ1O)`Mu6GYi{>I=^}{UV2> zskz!)yU-AD$Umug)dH{AkQpjvq}60n>=^ARbfED9nW0jt6Y@j%;&8OCy5-i}Lb12s zapzrszx$qWv1_Y}vb2Dw+FRqBS5H7$lgmp=XBA9xPc6$bqM`sUax`9A<7t+0%x#=U zP7+U~u%c3nvtB#8oaQ!qjKZ9NQq&N~@P!Kr0n2iIrt6%}#$H1~vQGs{nmeK-xm=a|sApur%!$%WBXQ6R)HdbSHZ}R02Ms7pk_}U~Sx0S>ZkCO&mJkbN-5sV|NfGJG@HBYL zg|!zAI$PSz&C4yw9i+=NpssF+5)9~)N!1M=Jz~#-c}+5=`FV5#`HuSPhDiK+AM!`> zBSS|!G+K))>D$mjx26%+I&$ch9ivC{87->TH-w6(DLn${=?LrTt!>anbbX^WqZK#* z&zebPMoYE3R5~uNaEOk4ZnvI+<6|_+grcLLc6b*w%$0?v7rrc>`Mzd~aaf*bzAxV~ zzj^LZ{d1U+%k!$|&273ux;ajD;1cBOFZb;M}wIYBad^Y)1gUr=EH?oxPDm zVdG}4+`?QvyQ=HwS9j&7p<7h6jvCoR1dn@vgjx0)G@rePd&j?u*Qgu8C4MfDV74 z0%F~&{x1=A$;up+%_fq2&Hn1hh6Yyer~;C zV4^ig&(3^D)12lx^9*f_&Pd988y3vVcT_hw>j~?cSjZ&F$xFBGh>K*JX*s%;-kU6F zuFuzJ7dV`6^lYds>k3`3i>7|O+F=*{V&tG>jHA1L4jCdlFQbd-(t1#+W0u-8Wn8t- zSIy+C+L1f4)SW9W(*lGc^i?txBVD7kI5kPvy7t^t59}aJG<2=XA>1Ddt=*YSf&LH6!Mbb$@sCB(5&1xi`WYI4S zb__RcQz$2Fq#F(MG{e$HAlMHcW8~BjBZQ2Uh_#-lLv`6clZ^n1BGW%~ojjigUCRvF z;i+w|p6hF5&a6-H8yfW*;kcyMU)?a)F_St_+u*5QSRjX1J-Cd}X;Tzi=R+B<^tvAKnNajR}LI4>5!4&-9txoiQ%o(Xlj&$43EyDv8lQtN(U+KBNM3((#6PKJ!(B$jhbWxCF@~0 zG&~tHbLQ*bm~c-!N0-W&EFFwW8IBP(s~f%a6|&6_iqtqnzn zk=L?j$$_aTe5;R;;g|+de9;a@-e)+wib!7_P(H>~JZ$Km9){(+i!>r1xf*eX#kvOZ zqKI?&s!sy5!ctwuncS1S3dg0-1S1O)qiRJ;J$X=fX6YumQY?}t*&Cv=G|I(PByp5Q z#EKOK{ZMw{X^v^rPqH-HVxKO3>}j&VjV2_gp1KD;tD|K4hih0-^kh{px$c_P=j8m2 zWQfe?aFXRL-B7tt?n&hlkv}dLqu9IKYPaTn(OeFf4k}%ExvWphYv!>=J~0Vd(MgD! zPyhc-#h<78go%4N)&E!3B`WKCkx04WpeHm^{`zWC@1MGJBmYmcGb;OyHBDF*vV?%- zeu3=q<$9M5gYNx;f`Wo@-bea7Yu5i5M`?p6TpRPE$55kP$nG=WSeKuWnU_K&e z6V!6OMx5wX&x$`<7|Kp-ZhdW}^fSgu$q6)+a99u&j50DIm3v2Qx5&n3Wb8nr+m`lS zYioLJeH1vp+s-)i&+|wYZ`Yb#&*dna(05bW$XUJKq$M+(lYtuDuC72@=;t$(MAhNY z=K~fww9BPZ$T>yH4E)a#%H4^sxVY(_Tt+7Tk!$yMk?gbO6j#s2?m4b34a0kQ;$A2x zo%u;gbZMvP9%>tEeUn{z#|aG{nj~W|axnDi26I35BIs?yMMaHn@-EB^55a@NQ`qAA z`o_7AIrX)d$Sol$I;6JIAt&j^4xR2>-l8gd4NdIJHL^K}c%Gc>=Q~E^J6MTy&xdR0 zRy!uUqy;nIrs_GyvbcNlnK!+9&@?%W%0!kp(+<2*b>`|Mk$u|BA246Z5zAyU(Zw2ge!~GY9W44trc&F&RMCP z8)KSYIwSbd-&ZR4DnmBiw`J?L?K|$@x$A-54?gtpBYPfw?C~d_-22qi&pi9w^Dn&k z(#x;B`r7MnbiDc2+wZ*l-aq!~A+uR~PUzddG5s*ie5mKG%1kAv!_H$T=Y@RK?U%*^ z^`azs^NzgXU#G%ng-)qH#yaTY+;3Ima5d$ z+ecZ-GDJaK()n|m8<-=F#LX)MbLXX1sEE{Uwk=z<*;e7|!>!wCm^PxsMqAzM;S3o^hImzSWRIv? z;M)%G_P8oEWBoa zoY(9=BXrrFO7Hl?=`OM{q0)UgblaWEfWSpPU42N)D77p}s0eCqB;tjp8|^*4aTQ5* zPut4Pl;q*`*%YLEQ*W6Fqp6@;?_6Qchnal!!m4Kgvc^rOZOzh77q#&rjX1CE6}v zMCq)L@~SK0Y>2Wk0=p{O<1E8&(Q$T$&*_HG=VXFnOi6&lMG>5zFe6Y}TG+v;HKTwi9duy`39R zu_X3t8=H$bO5c+h|*{ z)*%{H+S(qq$}6(1g2sliL95zn!Slw?JN;^5#0TLR4MuNUC6!}nZZxu{iuhTYsC&#- zu89hbt6vo@kJ)4&r<7$27hh+ghpMxmSN`8lX{pi;>6U6;U8w&(%D}jA?QQuaH1!^( zXVmSydz8%hNbiDk>pe=JK=-|kzRQ`9dQJ3Rs%+uQ^p42X@`=sWi#k*(?JKQ!-iDLW zMM;iVUQLe75!{KP*aHezzH1`BqJs3W;D%y{$^p9Mr zsjhq+P}hAVaORp8Z%Y(1L$z(1@MvW* zf{IlUGs{d9av#a`s_LCB`)su3eVO!9H}!Qt8Y*0^czW%z)qH4k|J1iZD=$D3`p}1M zbx&Xu`ed~-FxkvdaJ*f9AS}>V_WX(}J6NwS1x7QkE>7E8Xeo z*fqNbk+)$p_oO(}Yi@bk<~36VWEb1B?mgR1bIW@&{$(vs*knMKo$8{!HgvkSuEQ8> zRt98WUty6cQ@vVASuY{|srchzue7>WFS>Z$TEn`+JS)*0os1~W%~G>2oh>p-t;riN zuQAl4?sRqQ6!;^hbe$6Q+$O8N8Xf-P{#_A!wJ{d2*=zB}V{7D0d7P-Z#J+6dCH9KM zS&1<+D)%k@8sf|Hgg2i0Fv?O+_R?9Ay_z?kmWws2S-hbe*D47!$$~^0nsaf>%QkYl z$kjIE!>aRTtEv1Qi7FiqxW-(3fkK?2BKvF%${W zvPI4}4C4dRDD57UL#|=BquaRCM(Idrs)inI%N`?g%e9N%k)}oeveC9E#+JRIOV=s= z1G+5^jMElPCO#)p5xZ&?9betEvT(*&xymXfivyFaW>nf`3qO`?>o(l_Su}B`oQ6G=(R@RNwn+>Ncom$ZL>+h`-(=X@u8>Ml>W;2P_GS2Hka_-#T%4UyYDs|ckgY`C4b`Xl=0~e!f$cq()zi?39m)Y z{Ve*W{75I^j%!nf5k%P2t!>c(ernt$wd(;6ZdW{+O=%v@8`A{KXhICav0WO5#a?Mw zUQn7st2QbtXM61{7JBVb*+90e%vs`B$&K>QI?13Wueu^H_S$+gb$f|ET4^5hgW-WI zHeapw$JKpq^Cx(8fd}8S`IBf`{*=1ULV-<6Kl?TtvxGd+Ktj?^AkY|H~HX z-K{JRs1X+TtXw`;=lbP9Exd{Di$h=Cr}Pf&vsXH^vzLgvefDK7`|MmQorROO#7T=v z=UG#jB6x-6PI$+mb(5+##-20s_W*G$J$3ulGgN+h(WPRVseG7}HefFFztNWbP zh40%*>cS7~HSY)PavrtV%o*E?WBHDzb_|#sx zOpmfVS&^!pHLko~R*XtH92zPguUCSKD`^^%oh&q21GsH+G4I&korSIgOrxdH=s-4e z>E{d=BjI^^8Y-P*q{}~|T?pgxs4&)r!_WoyMGHoP7%YQ$HrjR7O4C2LT7b1HiDu^G#2^%E^UkwWe^uit&cGAOmIy#I<=z1dG zjdmgQ$D%?Hg@YI=L;v^$!97ue4Pn8ta_#zLMzo|`)Vyz3v&^#GLh1J_BLg4U$1Lvl zOJ0Q=JaTd^`{DVXRLVN?$c^MwEJS*cQ}1a_N1JOoJUp(PYivA z$6OIx_l4c4(Us1#CGaHHJ1I6j&MFMiMkmc8#2Y%(`^O28;{m*^zDOuoF?s zTl92nKcTt1dB|+nSpwyd$b7i`(;Abjkk z;F3yx1?yp@GNp`M@kl3k*hydC*R_Qs4#ykF@!FnfW7enUTxWZ*4GpxM+jIkx%UarO zOegq)c^gW!9jAout;+CJX?UruP~;+c`%qt;FV?R~gT-g|s~(FwZi`uX;?!|^B4j`4 z71OJkYIsAFA5fMLV+IrJF_(}SPb{@b^_V>tcgxUSL`l!f5I** zyHc}+7Iim8zx&9JclWf=o4b{sOr5^mt+*~|8R}pi6e9%E9-H6fQGC+u{%Tm+L>Zv0 z9!{I6m(3$5+qOfk%pN2I%NZ`sUX%Ocp>jLXT`<)BflQ8J?^cI~{`R0U^t7fl25iI8 zYa)UPayGbqD2qx>20h&=hY7D}b`6z{&`|HE2bD7hq>m)Uq;CiM$Xwcz_3utHQLrA$ zWM1sI)OkYF9#Z<}6UYqVO+&{0e72trJiU`AJJVbjvJ4vK&~r%M(-!Z1NO6$zM;}s# zB$2mfr7O~-4=KZPj%NAOy_OYBVTVhvR(9lsGtX;v-#kE8cxR5+D%>B0rajE20YzXH zICcBEk2#5KkmCpVWxHiAMt_m%x`kFuYRvw0nU1c~PBS86BBSaW%1tS+pe^pqig*_l zthwn4ysU9D-I-H}Fs#A=f9R`+m4d+CZ0^x0Sf1aVE`=PvSedIw75Dz(errR9H=Wh} zNfF1hRcvR0@3qRRXOYWq=6ZN^uFLKz@~rNAhj)#XUaK!g&bdCayN3)RPc)X}-gIY` zR5QJwtEbE-wJd>lESH&VI(aS2n7*bv&vWk#?S4cln3B$1QcwDpEM_P@r0;w1-4F@H z^`Wfi&W|F^AgwzVDd$gj^_PB@5Z>TDiqk?i8KM7WkJ7(f7x)t`WU%|P85&$BVe!Z3 z*=52K!fBDJ+vSuu-D{^1QAft`>Kw*l39#m1Pu0 zrIAg&rBz9E`A~31xsb>-y(Unf&Xi)IQI9Ecx)L&XySz0UA+eR59!ZJEEMt`xPoqOc z=B#8z_*CID%kIMBG5caL)AzXJPWPGo!ec6%EXM$ciE zJw$9JE0l{JbRGIOKAneWAb!;qKE0pOC1fA+`D2QMZAsTjQeN6Woyk{v)p z(q}SsIB};J=9wSPX_g;V<+QsL;mKL%%aJi|$@;j{lOy-U<=x}s%Er?N(Yke+6}}wZ z55@1vDgU<9m02VRdBwsb_L?8K{9we<(QW*p)0bDsGZaq_F?)p(H+>cszTlV+y^s zS2@Ldq=(B&6ZnDG?4Ul=8~o5`_j zWj}VA?E8CVB6cM6#OOkA>}5Coe~ascSgzE=UYb2HDquN^92Y%t9?5jkJY}@{ja2A5 zz3Y_eblnxJC&8|{Pp1u})qQ98CrX=^@9cGl?f!UgTFYTOwo-Nb{|D7kx*U%M+3ftE zm@hYWsUagkKbd>TW3Kr(3)zMLCiBRK>akx9Rqd9~`#a;57Pe;glx=@HGmz33<`z4R(f1sN$T zh-;lGy8i0*CDU2NQp}%cT%5w6^M~0x>CcPBNKU5v`ChWWahc_6a{4#Io8v5!%PMP; ztV#+$ZSiLlV`$KG%5=s?Z?-pYPkytvkJl+LIm`Sx-aeE;BtP}+bj?GxJ~dz4op)v> z@LR?7^oBmN3&@nUKgXNrb-MTU68=nYA32+p-v6)#F7K+uJhGNb2AI#8RPj^iO(MB- znYg<%pV_0FY1^I4vwu3~%`8h7GUrc>%9|&btwx#XIqN#4aK}8-knXD5t`3EEDDCw= ztK0rzg~IS#@?A;7Im~Sd1)o>a^DMn;zOHX`z z2|f9|()S`tB7xgwK9g{7&d?<%Fygr%&2;fI*GSul!?-zvM{IJSD04&t`jcTqFGHTY zT0&>Npj;BrXU)R>_}LAbYzR^#*X8ou71M~2~kc<{0TC~Em@y-IxC4O z!R_wP!h}$>g)CUsTYA{uB=`BJQ1D%MFZ6Tepvz+YaiRWY3b}Nv+c&_rGl}Oce47GQ zlLWz4q|EBa`qpM7o|(mmp`w?RbP8&RwK7laur{s#zSCzdlxd|sxHieM(X!Uk`|4|$ zVAr}p@6{u@mFlw_?#Jhr>dz29t4z~-;f(GhGuj%R(b8*%E)(rH^usjn&>i~&sUbKt`-nCtT}(xWmK9PIB} zthisB;A)8qyF^ww9w8c=YZe(oFfw0TGEOd1EL3Hwny85P>Iv$~+uQu?Jeb^f1Y~t& zb|w2fpGhXFJBz5+;WepXO=^*?^G;@UT-|S!8u@jk)Agmks(ml}Mp;vZLcnr@Y$Qtf zG*#d0b8gHY9G0U$(3bf$sTN@bsES|e)3WYWd)SGUa+=7CiC!s77d=PBaJ?SVZdb~7 zyO`dVl}C*Gzx`!f)R)_ag4La_$>DELjN^$rOL^Qiy-?nmT<97cGQFx4UP!X+0&62T(yLw`Ee><`KM_uFNi=X(kqSd@$rug&|8+v%bS2L{W(YxK$sh{piwlh{ zNOkvfxCR>8-4J$d_NX~O+8;P#Z$ijwNd31z%a&zV9kDyDlX#|GkP&KsjUNFY=^fV}h`v1xbeDjEIs4NAp?g5J0)e=OE~GskqByf!mm((5PI1miW)qbhiz zs(NGP)F9TqJS$wgoK{)6e(LlneEmbP)H-g0AxLmd?~}S6Ipeq^Yq(&@9r6YWlFJ0Y zVr>E&igH-p_;aUEEo8)%OH8qPAl8)Y!)g`9#`YpL1G9TyU&9h*)_*KLuwK*_iwVbW z6&D}7O^i8qk0?4u=4o`!4)%Hk<#nM$=6dsxva3Wy(KjXsSiyzwWU-bX?R4Lp5pk|N z2Unh@wtQxj$&(F&l*%%>J&W%b9k<%ilV!{dr1H8L#Yj?^`&h zW&cGK#D-5PsWXf7#3cDG(0cnAWnsO&rarW}gUykNsmt&t{WynZvo6M2#Tg4}?<(#J zuAB}_x@u9b1G-$#54&2TTv_Gve|{&rp-+pUcG+cuX90#)VO?n;+9^fk?1(t=wM1?Z zl@mRl)7I=@^I(Ua%a%mx^1u$BITws8Kh%j;S+qOPws9|rDK3~c(=C11G}*Vr$NEom~c9d_q2p32wRjhk@HWvMb^chR88_i`V`#Z z6e@FLbqq9vI+QSA5?l-|upK^tox_Cs6)3~WE!Yonr<2Pgh5C5lY*N7~T5psJ^|c8? z{g&q-Z%h_y<`lk{eU4DerixaRrnaVN@vYgKy)|Dm1&3&&b(p5Lo~fz9k(ftoF|8$< z7MzHA3ieZxIad=w4ti?+3x4adyBb!(W_SYLf-fQPJ0B@AT5A@Z4&~s1tKk-ChduCm zj23(|Mg-r1_hUrsM=||_pK<+y>sMU=6Eh%qlxw`1@XT7!ZWh5z=m)33sW1eF!3a1T z#+pSSIMFOx8}Q)6q6Kb-J77CJ0zbmf@H=p5Qc#0r$bdd@3b1Sm=D{!+87o?gVr{|k zm?yzGFbyt%Ik^2bRtv7cyb5lM4T#{K819DEupTzTeXtw$z*F!N9>2!px0sK>G0-d` zm;^l_0~~M~OoLf)6|8_eU^TP@tFGW9@CtkYp9J{$9*#mMXmKK#2sY>ey`T>`zzM_P zOc(_vFd6t}Uhq7)5UQXK8o>{X;2O9AR>G}tC#;2b2=Kj_;DhieJPj|y8}JVN2fl-! zAU0kEQ=l(oK`sn|;cyld!vr`7X22}C2&#cjEZ7K_!&MN38(~E}<-ZEUU9cK9z*g7^ z55Z&bB)kAG!)x#^dWVCQ$y% zFx&!n0&|7nR@e=X!V~Z+ybYg1Y@!GzKnmo-sW1el0AFbf&VVNH!4(jMzrxLM3v7T* zz*k>`55k@RA5Xx`@DA*Q58)g54t|18FeMQ=q(NUe1qQ-k7y%w=06$y-SHtzN3m%3? z;R$#F-hqF?7ZCW0kHhdioS#eaL+6&m0e49kbbks-4t<1ri_`Y>);$Art!ANub>x2=aBD)?9l^uo%k{n8^KfyFGY5<_eet z)o>%U!YyzQtb;b#4BOyQ_y9OWFz5iLOu>4%9Ug|yK})0eg!ADVSeHimzk%T}xO-6k zupDNli`Mn&JzAek?-4wZPHKS}Q1E;B1w>CO67+*pARo?zQBd5I;_2BxSc$m-F5~{r zp8Z=l^t85a>6skdj@?e!2cHG_NXihcGc!_Jt1_&uwHe7lUk2?LmSVp)qknKW=0_o} zmuMZ{tAFd+y;6b`dePZH16>tr#gu7u4tcR_z19riK@CZBxPr}pi z9J~UrGye;|g@Jiq@Kg92z6Iud!T&-hsJ&4N;vf|qkO%oN1Wto9pa`bGG&m1tgBO}$ z0bB)3U>V#7cfs1;l>dDg9)dma1Uv;V!|U)4?1K+rKYRt>!OzgAj|ldMEXaXDa0Z+O zV_*VIhB9CWJLra4a3TB!s-YpkM>AXjSHohs0an88um+xk7vWXtfVbfv@IHJD`{5vb z1>eE15Yw0D2Z@jZsn849a1G|cP#6w@5qyk+DKHiIwoq^uc;FJK2OnGxS3(e$!%Dan z?t*sM4BO!$*aJ_%v(N!=15@|lC$Jw5!Z+}9U&{YC3`##nH%Nta=nVrP2b@p{qhKtQ zz!W$SE`W={15Gd=7Q$k<2Cj$Ya0mPy*1#s%0z2Trew6>y7@mWdp#%0oYJcW*&>Q+g z77T8hf5&1i0_~VL!&cY-qSPko-9qxl&@DMx=&%ulED!g$@fZB=SJ@^<7ftp2yfo-r0 z9)ZW;Nq8B4fU^cr8KD%;h4Y~XE`tCphn27j?t|aJl1(JVF7S z0i`errox3#1@mArTo23OUf2w*j)PyoVfYb_fhm{q9)>X%4eo+1unS&*SK)2=8h(M8d?En{ zWJ4~T3I#9}PKOZ?DBz&r2}9Du{{J^Tp2LEK;hgV8VrTyP;&f*0zb z39g1Ea2>3Ihv5Zy2R6V8LeB+pkPJ4+fIg4~ zgP{;kgAp(aCPM>U4L8Fr5Q015Uf2Me1AJ_QUGNAz22a9s@FKhd@4-LeL--hehTkBz zkm)sKz-TCgS>T1s;Yzpxw!&lZBD@Lz0@F|tv_l||kF#JDjD-?7AN~T3un-o(61V|Y z!EJB{+ymR;0eB2vg4f|a_$Pb_hv6v14x?2;56FbRkTs0*&%;mvL*evcqIJ};Iot)SVI6FSJ@7a@2N|c4{cr}1gb6SW+;9O@K_fK76>v3N11nCW{BOZ< zA8dn1;R$#KUOi2;zIj?o@LkON;3L=%U&7b$Bm4^N>jgDPf>h`W!{JOA4J9xcX26AT z1uTWXLTiAJ+hHB-f~TPa-i6VpGpmIXC0LLdWj zVF-+X@h|~gFbgh%sxvA7It=q+5d>j9Y=zzM1iS$6!$)uk{tZ8Xc?8W7k|7QHLl)#h zKAZ_7VKPjEIZz7?a5*f2r6VZ+6&TjQCfEUw!c*`p?1K;B0Q>~Mg83{Wh2GE~a$y*p z4rjr5D1&KG1C6i{u7vC0Mz|gBf{p+m`(QsDfG^=|I1E3*?_e59gkXan&<}FKIa0Ka z8>s~+V4e(RFayqmi{VmefcfBu7FYty;WoGf0&Do#0GnV7?0`q%X?Px9g4dt}_Q8Jm z8oq^};5X=mq_a^DGNCUFfE+jt&VZ3{5zGM(Tm}ozru?tQa09G@dtfbWf~~LvcEcWc z9G-)>;9YnhK7vo-OZWkf!mnT&MKJ;IrwH016NW)4OoLij2v?4x{1;Ct*R<}olHCSVuvjM0LZaC0d%z~yii1mGID5uxQ{dIWF9d?(xuYoHzb`>@}I`C)hz zo`hGhe|=29;G3A=fe+wc*nK)CHTVVBL%97LyZ^wCV<`XsV)-kM>R4tiW7!fLn;J~P zoC@jC2l~Sx7y_rk888aj3CK>t?81Eh*#5!UT>rv#E_St;8!`JZUk)vBHFitJCI^>t zy@C6i#s(OhG5if~!}4w%S94uAHY>OZyDgZvkL}<3!dNZ%GWV}>|K`}3)_2C5g8#t$ zJ`sG(^&r=;xgO?v1i7E#H|WGpE$ZLer-)7IBGH;vq_qw#GPRE8zKHwr7Az)Uad~LO zf0V~J`lLT zIGbM=)DCmd|5GQtf&sCK6K0i^2BvlesC|!I{s}JxK#rFoMC+&h$O{2xob*DFzWOT| zx&^iWqFm<*NAr&ogJw)FJx{(3A)JPQ_6xBVour+U7e5^L@{`|%S&WT4F-v-eU%{Yf z8z094CPnc7OZJ)iTL^fc%bC3VBwLC_WTaTo6eo@*BbGQKA~zy=)T(o{FK;iZP}KO( zKL6st!9!nu_3y94MHbs$bg`1I{^#59eM)aTo7B!wkxBi%y=am=XX;s1jZ?K4bF78e%d9##`)GU7 z3u>yC$a`i&#SZnihl)N>)s(=6%KonR>KMsdaN;{;`tTMQOKvLJ7?o~uEL~B=JefZ! zk(UFdSbHdG^7RW*a>sfi_JXWg$BCs+ne3ifUMhH7iSc(V1G#Tc3a)4Pg$Z3^y=1H> z1(#hiX}s~ao^WWr6;1S!HS4%o2kLJqiG)Sr^$#GoRy#>`Tk_awlzZtU z<+4gkx@BZ=#RTUwf{O}m&`kHF(&@Y#Wtbs-YzD7EdPr8(XyqOn^R=p)+l!8=nklnS zU+M|<$7G5%^>dtJ+$5M{)vRpH$J&chO{O8sHF;Lq+170FdFnH-J^S`QXNU>brPem< zS5}+tueMHGwSA@ipZ1}t(^BtAeLgjGS-NS6GB~s*-PD`QYX{F;!nR3=LP)KK-|*JnaZo|j=HRi6FQ!uM?Wnwqo8X-o#IQ@2!Q)O+jS#w^nw)C*( zTx)CTWzBid*3#RWGs@o5*P64--g1gHM@wxPV9lAA+LCL{xh1t_kTvJA)Rt4Nt}2mp zw(fnAwI$V>bGIJI=hl{@5L8eA6yN9F*EJ(3&&xq;M1X z+KOoF+$-jGirMPfR-sOSDp&+d;cjSy7vOXF3d}a4+TdFFD{zdD%F{2k6Gqwj_6zX9 zN*#FvA1h%Oyb1pVjj!7bf}t=GrolY81@3{zfW|YVpXsbX>jfeqI9rI;1zZ<$y@hK? zFh$0^8}q|l_X>OP8Ll63{|VPlkBBo8DjH~dtzT@|C6rWR zDvtAu#MUc?we|YY`6Z^gNgwq`N%#tWd+3D{Q!^8_2`1GvYRp)p3!Q9=O(_~TzNB=* z#7UE!1OY0W!n-jFTd3f3h=tk*JvA3S*kH(uk_C3x(5C0_6a0AAx2JxVG$#yhII zrYMKj03y;zT*GT zOe*Z5e`J|%d}z#Jld2@kbC(uezVM2cE3dkGQD9Z^v7e~js`60D_oicMsp0lhVXynl zRHg|rJEtsE9;=->g`Zcno+jd3U9_p0w5d5FGsyVZdX2EPCabpAE4ALOk7}u{zsL3t zZjWa>DV0r`G}gK4y@Sa-Q0L)$Yi~HSXXwQeQv2{?5+g`LlT9<3gw(B+3a)*3H(!IMMjB;zzSZ&QF zhgYv%7b>2hP%1X*r&3D{@Zv~ExqG^7IF46(u1?t`o;cre+u=J7r{7@xac$Xk2bLd7 zUmlyjJT86t{`BRarf(8UKU@0ArqxULFa31WoTcVXj-|1y#kCe};_f%MT3+n<`9SP} zxD9bHJ=}44ZRee9t!4hULoYtk*}3#+y;$A4_U1MBu1Q!^x@Ov%E7x4RCNOr*(`(*b z^U0dSYmTkSTDyJClC^W!malzi?bYkk{; zX&XjtP&edkxMafx8yYtJbA#IUo%<0v#w*^IqNIdf3xoA zbv@SStZ!MreEogvA6s9OQL8NdzNS_zJ+fLXJJK(`>^o7j^kB`>L#s{qA6$MU{f7Gw zE6bm;{I+2CUTX~Z2fkcYdCj2E{V%J- zFXp!FTj6+Y^@J~X95GBA4&K_a;n1ynH+)(6X~b=%Nrn?~F@IV30xmywbf`b=#jqR0 zdwbvO(2W~6cORllVg8`k&CueP)uF5Yea*6vzemhPtBzhfH1zYUYTB@&8xB7A$&OR+ zKltYN9T^+-OVSM;Mb>h~LUkE2y;fa#{aMN_q1Q8FGFCls{Y9biy6d{!Y$U#g?Ap>-BI=K8@u=Z_#}4A z3-7Ro3a`IiY7>cT!@&g|OTXW6Xu;m4N6HS9nalgO?cTe*U)!OM#24@Xo;&&3uT6TI zwBbmtn1ptd9G#st6no9mBQ;CEU#*13yrWLJxU%fp-3~?eclO;vSPB>qW=tz9wThI& zp~Frae)<__jyS7WA059(#%#Rh&pfqw{G`bxv8+vbH)xrrf4FA4$H(wdR<7|mLw-zN zwJ5nt5vx8)9u|l#p2=%uXO@d~ZCAA2-)7$UNZTnJpJ=;m>oaZlZhfh3@7CAb4s3n9 zZN|2JZ40-3)V6W!XKk6=4z``L`S-T(xAkbheVe)c(QW(d{>G zJly8n{!`n^?IrDh-87}WYLlz|@0-qR_ivirzH8H*_HCOsx82(&#AWS*J&Mr%O{R?V zR%jd7ipt#`5A0o@v2j_ijpX(6o*QNQSBqOaZrNLD+1;`9;O@Ok58*QD&;uQZcE34k zcgLaYzSvxo=QtoNOU>8CUTdjY8rSy4CbQuuuX5F~lyRY&ChgLTcX#yI`|atnpV<9$ zMs4NNxZQ7M)CTBOcE7pQy!)x8u|MrKIuGqY+=1BlIy%04Z*Rvpn*DH>T2vYLhCqQjr%R%THiEx^n5XX#}D^gCcSvSWn;}DnE|>gl{6yD0n4{3@jH%g zQmZXXEh}F?5Vzyy192VStSU>ZQp~Hir!5LBUOmgKFeWuQBa4#7z8L2VEKJNB7yjPP zI@0VwCSGxJ_5&*%Q=Wxor0R=hDJf;H`n}!ZiR0gyQk0cl)>AkYL(chpBn*DW>nt(C zikD#}sZPyUj(Rx;Ay)A9S$~4_Iaa26a1}{XC{960k5F(HMPzvy)=DlZrI5yfd{Jva z!@DM3l1+GLMdpi@r^>Jtix>Vx=gTahjAXGAlwyei6X`lm&MB9IMo5WLBq2(|Cqs&J zUehI!ASKL7B=1nwd2J-wD5+;%iiRo{RACLtPxUpkU4;}waVmMeXE#jr}XQie~Z zh<9HW*xDT{XGA3m=U_tg@BWxFP(ygYAj@;%Vd- z44h8a9*Kh=7$0n}OqRCpd$)3lc+9yOot#=9XCNg_tt1e`B775(@+j^Z+q{Ag!-jdV z3{W#trYV>?9{eDUL|t^SoieD}R2IYUlsF&UD2R9tq~O4B0YSf zh=rZxK;BpxE}y^N*Pxd7;y$l3=k#{BZ##A?w{yjXqgU0k3;77-k(*Q;4nU~%oAc)I zGkbYfsOnD?z5;f6I9Ng}@m6t^Xi;|ABH{JaebJuY@f;tJ3&EzuB9q@k?Eei&NE5-Yh+5@S}fCmR1HQ zW^p*MDi6-`@_SvYkwT5L)(&yrmQ;%D%Wx-d4|p>OqahO+&EJO`v+D2XP4xDWy=K3L zJipWHtdu|hb~*{p>H5CY>rBKlxr{w%P8hIg&Q8^7=~MG%yVI_^zuLkv2034~bE`Iy zR4TubU@Q_Be%bEHb_P^mfj9eNfm)SnLxAIw=$tvpC{cEdq*W~{>n%J5-n_&rZ=#x) zY?&vSj!iA33C;pIpJ4y?#?|FYR{_op>rITURwoz^r?kJo2gR|0UNh{0276tmK4V>sD+b2J5 z<_Iez5VAF&6HpSjlPe~fD-U;i3gkH<+42+($j~&mX;V$7p8ig~z%A~dw^0-9UMpWy zC3$Q{%ESeZY(KBTuGb8&-6|V~z2XyDoeLO9>jyhCMvN4Rp22wubixVlXSbB+iM#|F z3l@Fc|G2L_T@=JPMvrj}k#>Ffa1Nn8(Ue@zbQTK2t0<76CDEx@mdElVzjoQNQm;6Y ziQ>@$q9Tbg)Z~%<7`ru86h4c}?w5Uz%=9>qiQnnVn*nO2Pm_jh3^CF$P_6POZ~%ZI zR&VyijA*9Qh^wrRE&B@xMh>5CU2Znj8n|KaZW3}f6ACR;T+n4)vGwElTBzP0b z&+4S3qk5AA#ympyq4Zsel}<-VcA0#K1w#=%pzJqkDFIQLOt-~pWmrV|ecgvXhB&5V z%gP@XqU}V&!v3VNx`HyoF)=xjo7;hR<{!|78e-HX9e^0ElcjODl z1h(wGJ>(#f+Hz1fP~Iz2^JSntnPwSov6b%LTMJzWkonwoYj6FI7di2$zL%c{U(CIvBULygQvS@&PJxfkjhl4l47D$9P7LAl?5 zzjU!v(uGLyBL$fGmVW>c*_HB`|d)wX(L6!uW$?0u}P$@P`2p)vcp|?ti2$n zboz8X$u-B?DHPck=%Ulkk=bzXR;k1#_hoY9+~dyNMwXJjGH_Dk`tq2V%`!fhho+jg zt|(cJdq{sR4qH!H9}Tf3V-6LsG5@lz$Q~amTBP*}&3;RZ3&iszGb#7osWWFx9xoSU z#$U>lY$4+EO?GZv_yO7($xkSGuIap9cw%v6AN1Hhwh$Mb@Ob$N_>Jz?39uz|M^3?-07}z7Q0>Q9s6Ceh(HoMjfKV*;{R#yTBD;VvT%2GP0b`E zp@#&67_dQ@gpdr$0%ipXGmro=33*2aBFR9aAkQQS99)M9^3X*|3%jlEii^lb*9Q_G zYFr{9Pi19AbUjCO5l|FXP$v6T_dJq;tntVG3+G(!SGR6GyZTP5>UI?e+r`-8 zf)2ZYK1xJkF<%Dlpce1naW|@l@_i=gUARK;LuX-OUiNT9jaQCAtz(yrM5!MX7fdW` zx4_vm^9nWIb2ekgJ(!#CP9h13k`U9ec6`gaRLfe9)q4HuNWylJBn~ahE6vGw4!6Va zfakz=VM#XK8f+Q%;nQMvh$$td&f?PI>|DPd+apE^slCJ1;{6^Bfx7rUM6YiNYyS>? zb;A4m5wt?|IvZ%4XxaIeal4Y{Y&2t8P+u)vMSJylFLc)uM%sA|Yn(l_ydv_wckJU- z>_d)z1hKK|=ykk86Nu3?6PiX7ZP-+XCqkeug70IDsBm|RVRhA*O6IfW^8RjN& zOdJZeTZ?l_v$INaxvuYXsI^?7#&gTTN=YcYlh7;U%l_?#$}uq+dd1n!EPrl-?-bPD z4$sc3j-at(ljC))rT+7Hu&qswHz<`p`SdeLup+82I=@A!*YQ4mT@?Fj7x&YN54PAGy>(U=FN~VO3k~6_kG7TNDkr8_K z+jHNcj>dj*ljAA;k=)n9m(-Wwv)z_>Z{9QPdy&D1hHdsr;jw!Rb)#%ukzu|~vf-NuSc?_I_oq-JVnH$@Jd zEePe4sh~{L?rmlRwC&Aoh<2)(4fI-HW-@WBPqTiWXBl?I1 z5oS@3GRboc^5f9^4E!=az{bbbs${0B6%=Rgug04#YG1SDQOxk>10^HgZcb1q;5%qI zJE(ckD?ofP;--S8gJytg%(ub&3JP=037&-zECIe33B5@0ra400X_nM?5k8HK&LQps z^e%x5mKcv@!B(V2P@^pgYA?(6!hsKt?42x2oR`Q{8}%CN$G7;XR`VKr1H+L~#=T%f zqB$$fmoUCWt!k6$1g<~p?{#cv39>$TN(kP=h{R;W+Svo~#^W{1o}Wa3cWx{fc%A7|JIpMy~0Lf9LaNo;v=d%}bw z@Q-GZ2tnd|QSF9)KrJnxCD42r;Zb2fUzsEch31rH=ZAjg3Q3IMyEZ(#!C|J~cLz${ zA6_c&3~nAAW+IJsjx%21T@;cmGqa5MZ-7D!o0`wXd1jg9O@;tAGo1_WFw^LQqT&)` zKXl4e{yYDj=7^@z+T<0cbKbEt&0=3m#q`Q5*9?6VERfT3!?bN-3pZ8ft9 zZBnioo>Lnn8J<$`+sMw#&M(0dc9!ug$jT+FASl6|JK5Oa8$6+~q_o}6t?y2W3Oi^} zO$WVU!3%F3nf9w-cI9-;Tq5p*T?)1H=o66La6Z@V3RQ*lSAAHHcq zebIr>NDA)<=K=KSIxcumqG}rTW<}DUMC)%AEOCGplC~5U@m-Jje#a zWV=pI5?p=$*ndMqWhg9%g)L#>{u|te`V?XtD(mTx7yL3%0req4R38wCXBD;xm%{_% z9`IW58gLhQIXL>=GXZ=Y=vojCC{cS0q9+#E3XcSsknw1XVNpcGq7cqWI%Mmq>UKXKD~k;}YhYy6XD6QKAru^C-WR+jiPWN{NwhWz zrx3wwv%ytvmlQ<-jsk`>iMm|n2wIF_+!`c-Sa9U+YlAb8C?qRMm?&DY2B>#77-@jS z4UoK?A6kq<Bd>%Wfe;CWkYX*$rAZWL zTUD+FGve3ktky_M8g$M>uC+FIwOnhn$wEWrTAeMx|2pJJJ1t1}H?l|8ESfhXsVc=a zWQ@O(Mn@PmLk*|kN0?2+>VF*X4Z-EIeJt~~xZ+mX7Ru!|uUtNor?f|;rzy$GuW|3E zo)LU|Rs~w9#|^`E??&A6h86d(T%|dq#7j+%Tr+OMBrduppls_C7?G99yEhbP3TO?F zD=ZOgNe0Rh{KFQ`$hKjIY@}ctZlIxpEyF+q;Dsve!C4<~wmF1-ZOetjZEJ*&;DmId zEqQF9JVM>JmN?sLYdN8|gF3Jsk4v)DQkG=V$Ai%qFIvmf()b|a0K+JagCtg)mS&Hv zN>N-X%8XFkdFFPKVsr)7A9XOuf=}Kasbna_6t}{!o99VlnBEQcXl1m5sKH9RmC2BNMMfnr8k7<`Gm6sLDu+d*u)M&SYsP<(wvhZY~EE}1>G+swNU5B_}!WhQu ztG{lwc6sKkd*;rcnWSW-D8q+@caytAKNc{uD!>jbWyX=uO7tNi!RN=3mo0rE48wZ3;3%#_- z`k+AAZy$nTYS@cln1zKcA$!721kXFD3&YnTY-wi)ZR@D~}ceIwSz10wAaZ|3of}3q;s^ml&5KyO!2h z^Xr1^>Z|6}kK)nBljO*rpheHd)zI!}J(<5x?37o&?;BhWtN_|g zrNw30(KvF{&L%kXO0vUqx;ZnDs`H%Ou5n$-Dzhtut(?q*=N^DHox$(b&|^@cURgJ zdS;zu^9vtWyIc%Q!$&{pXP#B~qiUB;@Et-foj)dlTL%15xe$)LUeL!fj-Xp@708RA zW>5>xz&i*!4*Cj2d*j>22thp>A$i`6zz0{ruSQ7fa}m_j1iTseF<>05rK-?b44pdQ z`H)vbUIknMTmoDGoC}?F=%fMKLHLFp7`!Y45k{@fy|A6cm9 z1K@+ee+PaWc!x#uY=O=u;3pto5BWOa-vWDpe*?S}I@6&u75G-j^C8ax&ITS0oB=%C z4W)P}#UjuX5hg^mVLJXJrs>~eihdgSE6nrvVJhDW+yeREAjkP=>Neme;LX5KLT3eZ z+`!8qUkLf#z;^;y0OJ5QwG28pL1!dzI^>Cvy9Xf94}n+&dII-=(pfBAoWjDyNhV>D zf_jbu9|mp(ZUNqf1&l4w*#!Iq1bDH}Epx#lU5Zs6|-#$OTRVP619t+Chj{ z5Kds!t;PeyA_AAk>gU&)z(s_AG7+3*L1#ViIum9!COrQY2)GegiikSk`M|S)X8=zJ zz8$y>xCn{!fhPiwhkOih2Jmp;RNzG58-V)(#{{Q59E*19tH3XS z|Je=jAT_BCh`0}e#R$&_zY9DM@@&YR2#-RTA3Hb{yeH)FxKt^^mnBI(kGbX<@I#VG z-767wH^Ms*eja=?_N0A-G{g(h^r@}T8uOW2u}jf z2G1mt+cO$q1O(~e$>8vRR~7Jn;M^y^CvX(F1({G3{G%wTUyDTjQl#n$-~%G@?1c~g zZV-Iy)n^g61#ueU8i4UdmuCs&IIdS+06ZIdHJ~ccR1tpmr2vJXTu?S>3@8JXhD3dl z=o%!Ffun#ez*vt`zr*zQtU%RwF*SZtU}_`ie$X<^FZS(vdv|M=G1(oDgvOj#pX` Date: Sat, 7 Dec 2019 19:49:03 -0800 Subject: [PATCH 018/149] Update documentation --- README.md | 3 + doc/Version 2.0.md | 200 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 doc/Version 2.0.md diff --git a/README.md b/README.md index 99e8d19..a7c3e0d 100755 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +# 12/7/2019 PLASMA 2.0 Developer Preview Available! +[Download and read the Release Notes](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md) + # 4/29/2018 PLASMA 1.2 Available! [Download and read the Release Notes](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%201.2.md) diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md new file mode 100644 index 0000000..96a1a10 --- /dev/null +++ b/doc/Version 2.0.md @@ -0,0 +1,200 @@ +# PLASMA Version 2.0 Developer Preview + +Welcome to PLASMA: the Grand Unifying Platform for the Apple 1, ][, and ///. + +Download the four disk images (three if you don't plan to boot an Apple ///): + +[PLASMA 2.0 DP 800K Full System](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA.2mg?raw=true) + +[PLASMA 2.0 DP System and ProDOS Boot](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA-SYS2.PO?raw=true) + +[PLASMA 2.0 DP Build Tools](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA-BLD2.PO?raw=true) + +[PLASMA 2.0 DP Demos](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA-DEM2.PO?raw=true) + +[PLASMA 2.0 DP Apple /// SOS Boot ](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA-SOS2.PO?raw=true) + +PLASMA can be run from floppies, System in Drive 1, and Build or Demos in Drive 2. Mass storage is the recommended installation that looks like (replacing HARDISK with your volume name of choice): + +System Files => /HARDISK/PLASMA/ + +Build Files => /HARDISK/PLASMA/BLD/ + +Demo Files => /HARDISK/PLASMA/DEMOS/ + +Use the System Utilities to copy the floppy images into the above mentioned directories. + +## Apple 1 + +The Apple 1 is a very constrained system compared to the ][ and ///. It is required to have the CFFA1 disk adapter installed to provide file storage and a full 32K od RAM. To get the files onto the CF card required the use of [CiderPress](http://a2ciderpress.com) and they must be placed in one directory. Most PLASMA programs won't work on the Apple 1 due to limited filesystem support, video/graphics capabilities, and lack of audio output. It does, however, make a good place to start when porting PLASMA to a new platform. + +## Apple ][ + +To boot directly into PLASMA, you will need to put the system files in the root prefix of the boot device and make sure PLASMA.SYSTEM is the first SYSTEM file in the directory. Otherwise, start PLASMA.SYSTEM from your program launcher of choice. All Apple ][ models with 64K and two floppy drives are supported up to a maxed out IIGS with accelerator and hard drive. + +#### 65802/65816 Support + +PLASMA can utilize the 16 bit features of the 65802 and 65816 processors to improve performance of the PLASMA VM operation. This is transparent to the programmer/user and doesn't make any additional memory or capabilities available to PLASMA. Launch `PLASMA16.SYSTEM` to use the 16 bit PLASMA VM. If you don't have the right CPU, it will print a message and restart. + +## Apple /// + +The Apple /// gets the environment it always wanted: The ability to navigate the filesystem with a command line interface. The Apple /// always boots from the floppy drive, even if a hard disk is installed. The PLASMA.SOS floppy should be updated with the SOS.DRIVER configured for your machine. Once booted, type `S /HARDISK/PLASMA` (or your install directory of choice) to change to, and set, the system directory. This can be automated by creating an `AUTORUN` file on the boot floppy with the above command in it. + +## PLASMA Command Line Shell + +PLASMA incorporates a very basic command line shell to facilitate navigating the filesystem and executing both SYSTEM/SOS programs and PLASMA modules. It has a few built-in commands: + +| Command | Operation | +|:----------------------------:|-------------------------| +| C [PREFIX] | Catalog prefix +| P \ | change to Prefix +| / | change to parent prefix +| V | show online Volumes +| S \ | set System prefix* +| +SOS \ [PREFIX] | launch SOS interpreter* +| -\ [PARAMS] | launch SYSTEM program** +| +\ [PARAMS] | exec PLASMA module +``` +[Optional parameters] + +* Apple /// only +** Apple ][ only +``` + +The shell is very brief with error messages. It is meant solely as a way to run programs that accept command line parameters and take up as little memory as possible. It does, however, provide a rich runtime for PLASMA modules. + +## Included Modules + +PLASMA comes with many library modules used by the tools, demos and sample code. The PLASMA system volume must remain in place for the duration of PLASMAs run otherwise it won't be able to find CMD or the system libraries. Probably the most useful included module is the editor. It is used for editing PLASMA source file, assembly source files, or any text file. Execute it with: +``` ++ED [TEXT FILE] +``` + +## Compiler Modules + +The build disk includes sample source, include files for the system modules, and the PLASMA compiler+optimizer modules. The compiler is invoked with: +``` ++PLASM [-[W][O[2]] [OUTPUT FILE] +``` +Compiler warnings are enabled with `-W`. The optional optimizer is enabled with `-O` and extra optimizations are enabled with `-O2`. The source code for a few sample programs are included. The big one, `RPNCALC.PLA`, is the sample RPN calculator that uses many of PLASMA's advanced features. The self-hosted compiler is the same compiler as the cross-compiler, just transcribed from C to PLASMA (yes, the self-hosted PLASMA compiler is written in PLASMA). It requires patience when compiling: it is a fairly large and extensive program. + +## Demos + +There are some demo programs included for your perusal. Check out `ROGUE` for some diversion. You can find the documentation here: https://github.com/dschmenk/PLASMA/blob/master/doc/Rogue%20Instructions.md. A music sequencer to play through a MockingBoard if it is detected, or the built-in speaker if not. A minimal Web server if you have an Uthernet2 card (required). Bug reports appreciated. + +## Source Code + +Most sample source code is included from the project. They build without alteration and should be a good starting point for further explorations. The header files for the included library modules are in the INC directory. + +## Video Playlist + +There is a [YouTube playlist](https://www.youtube.com/playlist?list=PLlPKgUMQbJ79VJvZRfv1CJQf4SP2Gw3yU) created for learning PLASMA. It is a WIP, with updates every week or so + +## Issues + +- All the modules and runtime are written mostly in PLASMA; the compiler and editor as well. This means that there may be some startup delay as the PLASMA module loader reads in the module dependencies and performs dynamic linking. But a 1 MHz, 8 bit CPU interpreting bytecodes is never going to match a modern computer. As noted earlier, an accelerator and mass storage are your (and PLASMA's) friend. + +- All the project modules are included. They have been tested, with the exception of the Uthernet2 driver. I seem to have misplaced mine. If someone can try the Web Server demo in /PLASMA.DEMOS/NET and leave feedback would be very appreciated. + +- The Apple /// may not always report errors properly or at all. + +- The documentation is sparse and incomplete. Yep, could use your help... + +# Changed in PLASMA for 2.0 DP + +1. Expanded bytecode for more efficient size/performance of programs + +2. Just-In-Time Compiler for native code performance (6502 and 65816) for frequently called routines + +# Changes in PLASMA for 1.2 + +1. Add TFTPD TFTP server + +2. Fix Uthernet 1 driver + +3. Add mouse module + +4. Fix IRQ issues for interrupt driven mouse driver + +# Changes in PLASMA for 1.1 + +1. All known bugs are fixed + +2. PLASM compiler received a little performance boost with an assembly language helper for ID/keyword lexical scanner + +# Changes in PLASMA for 1.0 + +If you have been programming in PLASMA before, the 1.0 version has some major and minor changes that you should be aware of: + +1. Case is no longer significant. Imported symbols were always upper case. Now, all symbols are treated as if they were upper case. You may find that some symbols clash with previously defined symbols of different case. Hey, we didn't need lower case in 1977 and we don't need it now. You kids, get off my lawn! + +2. Modules are now first class citizens. Translation: importing a module adds a symbol with the module name. You can simply refer to a module's address with it's name. This is how a module's API table is accessed (instead of adding a variable of the same name in the IMPORT section). + +3. Bytecode changes means previously compiled modules will crash. Rebuild. + +4. `BYTE` and `WORD` have aliases that may improve readability of the code. `CHAR` (character) and `RES` (reserve) are synonyms for `BYTE`. `VAR` (variable) is a synonym for `WORD`. These aliases add no functionality. They are simply syntactic sugar to add context to the source code, but may cause problems if you've previously used the same names for identifiers. + +5. When declaring variables, a base size can come after the type, and an array size can folllow the identifier. For instance: +``` +res[10] a, b, c +``` +will reserve three variables of 10 bytes each. Additionally: +``` +res[10] v[5], w[3] +``` +will reserve a total of 80 bytes (10 * 5 + 10 * 3). This would be useful when combined with a structure definition. One could: +``` +res[t_record] patients[20] +``` +to reserve an array of 20 patient records. + +6. Ternary operator. Just like C and descendants, `??` and `::` allow for an if-then-else inside an expression: +``` +puts(truth == TRUE ?? "TRUE" :: "FALSE") +``` + +7. Multiple value assignements. Multiple values can be returned from functions and listed on variable assignments: +``` +def func#3 // Return 3 values + return 10, 20, 30 +end + +a, b, c = 1, 2, 3 +c, d, f = func() +x, y = y, x // Swap x and y +``` + +8. `DROP` allows for explicit dropping of values. In the above `func()` example, if the middle value was the only one desired, the others can be ignored with: +``` +drop, h, drop = func() +``` + +9. The compiler tracks parameter and return counts for functions. If the above `func()` were used without assigning all the return values, they would be dropped: +``` +a = func() // Two values silently dropped +``` +To generate compiler warning for this issue, and a few others, use the `-W` option when compiling. + +10. Lambda (Anonymous) Functions. The ability to code a quick function in-line can be very powerful when used properly. Look here, https://en.wikipedia.org/wiki/Anonymous_function, for more information. + +11. SANE (Standard Apple Numerics Environment) Floating Point Library. An extensive library (two, actually) of extended floating point (80 bit IEEE precision) functionality is suported. A wrapper library has been written to greatly simplify the interface to SANE. Look at the `RPNCALC.PLA` source code as an example. + +12. Library Documentation. Preliminary documentation is available on the Wiki: https://github.com/dschmenk/PLASMA/wiki + +13. Significant effort has gone into VM tuning and speeding up module loading/dynamic linking. + +14. The VM zero page usage has changed. If you write assembly language routines, you will need to rebuild. + +# Thanks + +I wish to thank the people who have contributed the the PLASMA project. They have greatly improved the development of the language and documentation: + +- Martin Haye: PLASMA programmer extraordinaire. Mr. Lawless Legends has requested many of the crucial features that set PLASMA apart. +- Steve F (ZornsLemma): Has taken the optimizer to new levels and his work on porting PLASMA to the Beeb are amazing: http://stardot.org.uk/forums/viewtopic.php?f=55&t=12306&sid=5a503c593f0698ebc31e590ac61b09fc +- Peter Ferrie: Assembly optimizer extraordinaire. He has made significant improvements into the code footprint in PLASMA so all the functionality can exist in just a few bytes. +- David Schmidt (DaveX): His help in documentation have made it much more accessible and professional. Of course any errors are all his. Just kidding, they're mine ;-) +- Andy Werner (6502.org): Catching the grammatical errors that I ain't no good at. +- John Brooks: Apple II Guru par excellence. His insights got 10% performance increase out of the VM. + +Dave Schmenk +http://schmenk.is-a-geek.com From df77781c177913ac86669daecd56baac65ed1c4e Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 7 Dec 2019 19:56:14 -0800 Subject: [PATCH 019/149] Automatic configuration --- doc/Version 2.0.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index 96a1a10..f72d8bb 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -34,7 +34,7 @@ To boot directly into PLASMA, you will need to put the system files in the root #### 65802/65816 Support -PLASMA can utilize the 16 bit features of the 65802 and 65816 processors to improve performance of the PLASMA VM operation. This is transparent to the programmer/user and doesn't make any additional memory or capabilities available to PLASMA. Launch `PLASMA16.SYSTEM` to use the 16 bit PLASMA VM. If you don't have the right CPU, it will print a message and restart. +PLASMA can utilize the 16 bit features of the 65802 and 65816 processors to improve performance of the PLASMA VM operation. This is transparent to the programmer/user and doesn't make any additional memory or capabilities available to PLASMA. PLASMA will automatically run the most optimal VM for your configuration. ## Apple /// @@ -106,6 +106,8 @@ There is a [YouTube playlist](https://www.youtube.com/playlist?list=PLlPKgUMQbJ7 2. Just-In-Time Compiler for native code performance (6502 and 65816) for frequently called routines +3. Automatically identify and run most opimal VM for configuration + # Changes in PLASMA for 1.2 1. Add TFTPD TFTP server From 6305c74b6585cb1cfc75f1d3f64bee6ced0ac798 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 7 Dec 2019 19:59:55 -0800 Subject: [PATCH 020/149] Update issues --- doc/Version 2.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index f72d8bb..f578973 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -94,7 +94,7 @@ There is a [YouTube playlist](https://www.youtube.com/playlist?list=PLlPKgUMQbJ7 - All the modules and runtime are written mostly in PLASMA; the compiler and editor as well. This means that there may be some startup delay as the PLASMA module loader reads in the module dependencies and performs dynamic linking. But a 1 MHz, 8 bit CPU interpreting bytecodes is never going to match a modern computer. As noted earlier, an accelerator and mass storage are your (and PLASMA's) friend. -- All the project modules are included. They have been tested, with the exception of the Uthernet2 driver. I seem to have misplaced mine. If someone can try the Web Server demo in /PLASMA.DEMOS/NET and leave feedback would be very appreciated. +- All the project modules are included. They have been lightly tested. - The Apple /// may not always report errors properly or at all. From 5088e67de5dcb17e214b5629f6a7d04ba88a83f4 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sun, 8 Dec 2019 12:33:52 -0800 Subject: [PATCH 021/149] Update image name for 800K full install --- doc/Version 2.0.md | 2 +- images/apple/{PLASMA.2mg => PLASMA2.2mg} | Bin 2 files changed, 1 insertion(+), 1 deletion(-) rename images/apple/{PLASMA.2mg => PLASMA2.2mg} (100%) diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index f578973..218d981 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -4,7 +4,7 @@ Welcome to PLASMA: the Grand Unifying Platform for the Apple 1, ][, and ///. Download the four disk images (three if you don't plan to boot an Apple ///): -[PLASMA 2.0 DP 800K Full System](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA.2mg?raw=true) +[PLASMA 2.0 DP 800K Full System](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2.2mg?raw=true) [PLASMA 2.0 DP System and ProDOS Boot](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA-SYS2.PO?raw=true) diff --git a/images/apple/PLASMA.2mg b/images/apple/PLASMA2.2mg similarity index 100% rename from images/apple/PLASMA.2mg rename to images/apple/PLASMA2.2mg From 987a546bf6bd37b0802b99334607ba481e303a89 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 8 Dec 2019 13:37:47 -0800 Subject: [PATCH 022/149] Add SANE floating point file copy directions --- doc/Version 2.0.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index 218d981..08cb2a3 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -12,7 +12,7 @@ Download the four disk images (three if you don't plan to boot an Apple ///): [PLASMA 2.0 DP Demos](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA-DEM2.PO?raw=true) -[PLASMA 2.0 DP Apple /// SOS Boot ](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA-SOS2.PO?raw=true) +[PLASMA 2.0 DP Apple /// SOS Boot and SANE floating point modules](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA-SOS2.PO?raw=true) PLASMA can be run from floppies, System in Drive 1, and Build or Demos in Drive 2. Mass storage is the recommended installation that looks like (replacing HARDISK with your volume name of choice): @@ -22,6 +22,8 @@ Build Files => /HARDISK/PLASMA/BLD/ Demo Files => /HARDISK/PLASMA/DEMOS/ +SANE files => /HARDISK/PLASMA/SYS + Use the System Utilities to copy the floppy images into the above mentioned directories. ## Apple 1 From 1a230ab165b0707b79a963ea7ce01529c394e3a4 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 8 Dec 2019 14:23:12 -0800 Subject: [PATCH 023/149] typo --- doc/Version 2.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index 08cb2a3..fa4d4d3 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -108,7 +108,7 @@ There is a [YouTube playlist](https://www.youtube.com/playlist?list=PLlPKgUMQbJ7 2. Just-In-Time Compiler for native code performance (6502 and 65816) for frequently called routines -3. Automatically identify and run most opimal VM for configuration +3. Automatically identify and run most optimal VM for configuration # Changes in PLASMA for 1.2 From fb989e22e43bbe09fe9193e70a41d8c014732d87 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sun, 8 Dec 2019 16:48:23 -0800 Subject: [PATCH 024/149] profile jit16 default values --- src/libsrc/apple/jit16.pla | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsrc/apple/jit16.pla b/src/libsrc/apple/jit16.pla index 5ddf942..4325a1f 100644 --- a/src/libsrc/apple/jit16.pla +++ b/src/libsrc/apple/jit16.pla @@ -60,7 +60,7 @@ if *jitcomp return 0 fin *jitcomp = @compiler -cmdsys.jitcount = 44 +cmdsys.jitcount = 12 cmdsys.jitsize = 96 puts("16-bit VM/JITC enabled\n") return modkeep From d91ca59b523f2dd57af9c2c8c325f335f33398b5 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sun, 8 Dec 2019 17:06:20 -0800 Subject: [PATCH 025/149] Additional jit16 tuning --- src/libsrc/apple/jit16.pla | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsrc/apple/jit16.pla b/src/libsrc/apple/jit16.pla index 4325a1f..bad2f66 100644 --- a/src/libsrc/apple/jit16.pla +++ b/src/libsrc/apple/jit16.pla @@ -60,7 +60,7 @@ if *jitcomp return 0 fin *jitcomp = @compiler -cmdsys.jitcount = 12 +cmdsys.jitcount = 36 cmdsys.jitsize = 96 puts("16-bit VM/JITC enabled\n") return modkeep From f5236f2a1d9d75f77d433931cafeddcb5acfcf55 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sun, 8 Dec 2019 17:13:43 -0800 Subject: [PATCH 026/149] More profiling? --- src/libsrc/apple/jit16.pla | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsrc/apple/jit16.pla b/src/libsrc/apple/jit16.pla index bad2f66..34e9fc2 100644 --- a/src/libsrc/apple/jit16.pla +++ b/src/libsrc/apple/jit16.pla @@ -60,7 +60,7 @@ if *jitcomp return 0 fin *jitcomp = @compiler -cmdsys.jitcount = 36 +cmdsys.jitcount = 32 cmdsys.jitsize = 96 puts("16-bit VM/JITC enabled\n") return modkeep From 8364f5c63139a1d6a512321975cf18ea9c358a18 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Thu, 12 Dec 2019 01:13:05 -0800 Subject: [PATCH 027/149] Fix premature restore of jitcodeptr in modexec --- src/libsrc/apple/jit.pla | 2 +- src/libsrc/jit16core.pla | 15 ++++----------- src/libsrc/jitcore.pla | 15 ++++----------- src/vmsrc/apple/cmdjit.pla | 9 ++++++--- 4 files changed, 15 insertions(+), 26 deletions(-) diff --git a/src/libsrc/apple/jit.pla b/src/libsrc/apple/jit.pla index 263d645..f0bd2e9 100644 --- a/src/libsrc/apple/jit.pla +++ b/src/libsrc/apple/jit.pla @@ -49,7 +49,7 @@ if *jitcomp return 0 fin *jitcomp = @compiler -cmdsys.jitcount = 44 +cmdsys.jitcount = 36 cmdsys.jitsize = 96 puts("JITC enabled\n") return modkeep diff --git a/src/libsrc/jit16core.pla b/src/libsrc/jit16core.pla index eb73f13..c036841 100644 --- a/src/libsrc/jit16core.pla +++ b/src/libsrc/jit16core.pla @@ -10,10 +10,8 @@ def compiler(defptr)#0 word codeptr, isdata[], addrxlate, bytecode, i, case, dest byte opcode, j, A_IS_TOS, X_IS_IFP - //puts("JIT compiler invoked for :$"); puth(defptr=>bytecodeaddr); putln defptr=>interpaddr = indirectentry // assume compile will fail addrxlate = heapmark // heapalloc(512 + defptr->bytecodesize) - //if not addrxlate if isult(heapavail, 512 + defptr->bytecodesize) // 256 * sizeof(word) address xlate // // Not enough heap available @@ -26,7 +24,8 @@ def compiler(defptr)#0 // bytecode = addrxlate + 512 // def bytecode defcpy(bytecode, defptr) - //puts("Addr Xlate: $"); puth(addrxlate); putln + //puts("JITC:$"); puth(defptr=>bytecodeaddr); puts("=>$"); puth(bytecode) + //puts(",$"); puth(defptr->bytecodesize); putln // // Find all branch targets and optimization fences. Tag the opcode with the LSB set // @@ -1308,11 +1307,8 @@ def compiler(defptr)#0 defptr->interpjsr = $4C // JMP defptr=>interpaddr = *jitcodeptr *jitcodeptr = codeptr - // - // Free working bufffers - // - //heaprelease(addrxlate) - //puts("Done compiling: $"); puth(defptr=>interpaddr); putln + //puts("Done compiling: $"); puth(defptr=>interpaddr) + //puts("->$"); puth(*jitcodeptr); putln //getc return fin @@ -1320,9 +1316,6 @@ def compiler(defptr)#0 // // If we got here we ran out of code buffer space. // - // Free working bufffers - // - //heaprelease(addrxlate) //puts("Ran out of code buffer\n") //getc end diff --git a/src/libsrc/jitcore.pla b/src/libsrc/jitcore.pla index 5286233..29f301d 100644 --- a/src/libsrc/jitcore.pla +++ b/src/libsrc/jitcore.pla @@ -28,10 +28,8 @@ def compiler(defptr)#0 word codeptr, isdata[], addrxlate, bytecode, i, case, dest, VX, VY byte opcode, j, A_IS_TOSL - //puts("JIT compiler invoked for :$"); puth(defptr=>bytecodeaddr); putln defptr=>interpaddr = indirectentry // assume compile will fail addrxlate = heapmark // heapalloc(512 + defptr->bytecodesize) - //if not addrxlate if isult(heapavail, 512 + defptr->bytecodesize) // 256 * sizeof(word) address xlate // // Not enough heap available @@ -44,7 +42,8 @@ def compiler(defptr)#0 // bytecode = addrxlate + 512 // def bytecode defcpy(bytecode, defptr) - //puts("Addr Xlate: $"); puth(addrxlate); putln + //puts("JITC:$"); puth(defptr=>bytecodeaddr); puts("=>$"); puth(bytecode) + //puts(",$"); puth(defptr->bytecodesize); putln // // Find all branch targets and optimization fences. Tag the opcode with the LSB set // @@ -1535,11 +1534,8 @@ def compiler(defptr)#0 defptr->interpjsr = $4C // JMP defptr=>interpaddr = *jitcodeptr *jitcodeptr = codeptr - // - // Free working bufffers - // - //heaprelease(addrxlate) - //puts("Done compiling: $"); puth(defptr=>interpaddr); putln + //puts("Done compiling: $"); puth(defptr=>interpaddr) + //puts("->$"); puth(*jitcodeptr); putln //getc return fin @@ -1547,9 +1543,6 @@ def compiler(defptr)#0 // // If we got here we ran out of code buffer space. // - // Free working bufffers - // - //heaprelease(addrxlate) //puts("Ran out of code buffer\n") //getc end diff --git a/src/vmsrc/apple/cmdjit.pla b/src/vmsrc/apple/cmdjit.pla index c3af10c..1f64fc9 100755 --- a/src/vmsrc/apple/cmdjit.pla +++ b/src/vmsrc/apple/cmdjit.pla @@ -39,6 +39,7 @@ end // // JIT compiler constants // +const jitcbuf = $AF00 const jitcomp = $03E2 const jitcodeptr = $03E4 const jitmod = $02F0 @@ -1343,6 +1344,10 @@ def resetmemfiles()#0 memset($BF58, 0, 24) ^$BF58 = $CF ^$BF6F = $01 + // + // Reset JIT code pointer + // + *jitcodeptr = jitcbuf perr = terr // Restore perr end def execsys(sysfile)#0 @@ -1372,7 +1377,7 @@ def execsys(sysfile)#0 end def execmod(modfile)#1 byte moddci[17] - word saveheap, savexheap, savesym, saveflags, savejit + word saveheap, savexheap, savesym, saveflags perr = 1 if stodci(modfile, @moddci) @@ -1380,12 +1385,10 @@ def execmod(modfile)#1 savexheap = xheap savesym = lastsym saveflags = systemflags - savejit = *jitcodeptr if loadmod(@moddci) < modkeep lastsym = savesym xheap = savexheap heap = saveheap - *jitcodeptr = savejit fin ^lastsym = 0 systemflags = saveflags From f90e339b01cabc8f7ea19aef39feb39df63c9ae0 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 12 Dec 2019 09:56:05 -0800 Subject: [PATCH 028/149] Update Apple /// JIT and images to DP 1a --- images/apple/PLASMA-FPSOS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA-SYS2.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes src/libsrc/dhcp.pla | 1 + src/vmsrc/apple/cmdjit.pla | 11 +++++++---- src/vmsrc/apple/soscmd.pla | 5 ++++- src/vmsrc/apple/sossys.pla | 5 ++--- 7 files changed, 14 insertions(+), 8 deletions(-) diff --git a/images/apple/PLASMA-FPSOS.PO b/images/apple/PLASMA-FPSOS.PO index 0f338f32174de5eeee35781e0412923f148a4d01..8c590863e5e82ab4066903a4970b883eeb2437da 100644 GIT binary patch delta 353 zcmZp8z|ru4V?!T{z;jiG9(7$#WroKLV8-NmEOr7D#Zd*D->__d!@?+H&b?WgDV2fI zUx1IHe>=Ag<0KW4YYb`5A)!Vg3=BanAm%ZHfH~7QCNOF<7EHgJz$nKUIQ>roqlAG4 zLrAkhfDwZZ!-T3Y3xEo>jiOuwlo;5w8Q%WaXITB;nW6Z907LozV1|AF!x%14w@YO7 zVC0?Np2#T6sIYx$B4aY6r?N7`L=R<_iQYgu5Qt-e>?CE5i8(+zUzxeF1SnPxWY;LO zPizFT+mwYHCnz&C&IIE5K)eVjwhD;XPY+CHTsbX;k%zH)J8ueO01u<(_P7GZSKOwO zj7$|@R;Dp%FopQ7^@(7}id__d!@?+H&b?NdDV2f2 zUx1IHb33;U<0KW43k+$_A)!Vg3=BbaAm%ZHfN9e=CNOFNMf1 Z$kl0*RbLiNudQJ;W0c;$rH0XIGXPDJZ#n<~ diff --git a/images/apple/PLASMA-SYS2.PO b/images/apple/PLASMA-SYS2.PO index 822026472a2a8e20f26e549ba50e42cbae0dc360..2a16a395e33b0cdf5b4b173a08a285a587b66861 100755 GIT binary patch delta 364 zcmZp8z|ru4V}k>WfU^L@9~A~3WroKL0zK-woSOq!Hgd8s8~FHbX60iR@Rw#}st^`P zW6)p3#N%yMGK}0 zS49dk096&FNmhjmW(W&Rh?1V1D5q$2ks;$hqt7k|H8BC5|BNB^;szi}MmA)ta8NP> zh}|R|Pyu3S9Se~ZH3-O=?kK^e{;fq_k%;rV}EhFkyj8CL#xW|;6lfMM$YFoq+Oh2^bz4F1O`Twn%aHLuB0@+%ob zHnS-FVVo?$#Ii~0eg`io96$lW0Afsjvnm5sWOL%`B^->5o7uM9uw_))eE;K3FH{BF SkJ>Q$SurYX7b$0avjYH&=WC7t delta 324 zcmZp8z|ru4V}k>WfV%)guZo0_GQ(pAfp&Fs!Oa0I8#!6n4Sa$&v+^+uM9MNURR{~D zF=#M_Gz*6RwIBOp~s9!ps0vUyvqQ6)u<|EHEKTc5=9!BKv8EjQ@;2TPD}biHgNC==^64 zX_5{o0x`6Xg-D7T1f)%OlweX)0x|6wLQJItEWxT8WCIMqjQ27jjB*Ac!LpOzE|;Gy zEN{+Z_CH490y7A!`ArU!U&$D^N#PIUCZ+owydeL9JjwuKOn$Q}165>m;_4+Fj0~IE gw%o8~)Y*Lh<4rGA1>29>F#1_B>TDM&XMD2*05YCl=l}o! diff --git a/images/apple/PLASMA2.2mg b/images/apple/PLASMA2.2mg index 58c7e54a7bcb5ecbc0a78e8a55ebafba44a30c30..45da330e7fef648b7021de2ae93402b733df3dff 100644 GIT binary patch delta 315 zcmX@mV056tXhQ>wfU^L@9~A~3WroKL0zK-S?3*XBY~a!4%Rg>|@Q46)9LIoE0rtCYlv5SSFqoE?6cBl#7+n zVNh`M5oAacuZkB;6RnCCOcSn(6l4IZDoB&83Kz@}7MKtvJ$a#At5BP4fB}Qff5wpa zG9m181|h++({*cD14m!XL(o1}x1EO6?9xjN2WQnAlG8_NeP} zf*j8PVoVQy&D0MR;$(*kak6iJ|C%XGgpqNp8}kikMwRXIF3fZE(UhDhX6~NMsL&q5 e&H}`&K+Fcj>_E%`#GF9P1;pIjL)dxVQ~&^mMpT^u delta 310 zcmX@mV056tXhQ>wfV%)guZo0_GQ(pAfp&Fs!Oas`HgfW?8~6mtGcYj#0pn(0zI^`a zH>y}9C*PJWj+A9&st^`PW6)ppy1{s#*ijn6)%`3S`{srCR`OMm?mBIgqZ=Tz93DqDqJu_SYSew?Buy}t-KAg z0R{{@{~1Hx%Y-ma)|XFX^qV|QekEhvW(S2ojLi;8?G8$e+Z~jc*iQ0-oC|U{1Bfv_ z_%%~Ms?hfLubIL`7#X&@G2d`z)Y&fY!aPSGP05L3=I+UiI_)9sEI`Z(#B4y!4#XTl R%n8I?K+L^8gq`P21psE_Rn`Ci diff --git a/src/libsrc/dhcp.pla b/src/libsrc/dhcp.pla index 2bc94d6..843bb36 100644 --- a/src/libsrc/dhcp.pla +++ b/src/libsrc/dhcp.pla @@ -3,6 +3,7 @@ // include "inc/cmdsys.plh" include "inc/inet.plh" +sysflags nojitc // No need to JITC this temp loaded module // // Needed to init subnet // diff --git a/src/vmsrc/apple/cmdjit.pla b/src/vmsrc/apple/cmdjit.pla index 1f64fc9..d85bb22 100755 --- a/src/vmsrc/apple/cmdjit.pla +++ b/src/vmsrc/apple/cmdjit.pla @@ -1344,10 +1344,6 @@ def resetmemfiles()#0 memset($BF58, 0, 24) ^$BF58 = $CF ^$BF6F = $01 - // - // Reset JIT code pointer - // - *jitcodeptr = jitcbuf perr = terr // Restore perr end def execsys(sysfile)#0 @@ -1428,6 +1424,13 @@ def docmds#0 execsys(getlnbuf) break is '+' + // + // Set JIT code pointer + // + *jitcodeptr = jitcbuf + // + // Exec module + // execmod(striptrail(getlnbuf)) // // Clean up diff --git a/src/vmsrc/apple/soscmd.pla b/src/vmsrc/apple/soscmd.pla index 6150543..694fd90 100755 --- a/src/vmsrc/apple/soscmd.pla +++ b/src/vmsrc/apple/soscmd.pla @@ -1,4 +1,5 @@ include "inc/cmdsys.plh" +sysflags nojitc // Keep JITC from compiling itself // // JIT compiler values // @@ -16,6 +17,7 @@ end // // Private addresses // +const jitcbuf = $9000 const codemax = $A000 const cmdparser = $A0F0 const jitcomp = $A0F2 @@ -291,6 +293,7 @@ def shell#1 volumes break is '+' + *jitcodeptr = jitcbuf //cmdsys:modexec(striptrail(cmdptr)) return striptrail(cmdptr) //cmdsys:syswrite(cmdsys.refcons, @textmode, 3) @@ -323,6 +326,6 @@ end directentry = *sinterp indirectentry = *xinterp *jitcomp = @compiler -cmdsys.jitcount = 44 +cmdsys.jitcount = 32 cmdsys.jitsize = 96 done diff --git a/src/vmsrc/apple/sossys.pla b/src/vmsrc/apple/sossys.pla index de840da..af01f8f 100755 --- a/src/vmsrc/apple/sossys.pla +++ b/src/vmsrc/apple/sossys.pla @@ -38,6 +38,7 @@ end // // JIT compiler values // +const jitcbuf = $9000 const jitcomp = $A0F2 const jitcodeptr = $A0F4 const codemax = $A000 @@ -1242,18 +1243,16 @@ def loadmod(mod)#1 end def execmod(modfile)#1 byte moddci[17] - word saveheap, savesym, saveflags, savejit + word saveheap, savesym, saveflags perr = 1 if stodci(modfile, @moddci) saveheap = heap savesym = lastsym saveflags = systemflags - savejit = *jitcodeptr if loadmod(@moddci) < modkeep lastsym = savesym heap = saveheap - *jitcodeptr = savejit while modid modid-- seg_release(modseg[modid]) From 8e124ca05bf130c96c4d8a8f37e77e323504b8ae Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 12 Dec 2019 09:59:41 -0800 Subject: [PATCH 029/149] Update docs for DP 1a --- README.md | 2 +- doc/Version 2.0.md | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a7c3e0d..97cb42b 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 12/7/2019 PLASMA 2.0 Developer Preview Available! +# 12/12/2019 PLASMA 2.0 Developer Preview 1a Available! [Download and read the Release Notes](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md) # 4/29/2018 PLASMA 1.2 Available! diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index fa4d4d3..3ae359c 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -1,4 +1,4 @@ -# PLASMA Version 2.0 Developer Preview +# PLASMA Version 2.0 Developer Preview 1a Welcome to PLASMA: the Grand Unifying Platform for the Apple 1, ][, and ///. @@ -102,7 +102,11 @@ There is a [YouTube playlist](https://www.youtube.com/playlist?list=PLlPKgUMQbJ7 - The documentation is sparse and incomplete. Yep, could use your help... -# Changed in PLASMA for 2.0 DP +# Changed in PLASMA for 2.0 DP 1a + +1. Fix interaction with JIT compiler and module load/unload + +# Changes in PLASMA for 2.0 DP 1 1. Expanded bytecode for more efficient size/performance of programs From bbf0a0f666cc8c2a39066821680bb4d77ff636fe Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Thu, 12 Dec 2019 11:22:46 -0800 Subject: [PATCH 030/149] Make image names a little more sensical --- doc/Version 2.0.md | 8 ++++---- images/apple/{PLASMA-BLD2.PO => PLASMA2-BLD.PO} | Bin images/apple/{PLASMA-DEM2.PO => PLASMA2-DEM.PO} | Bin images/apple/{PLASMA-FPSOS.PO => PLASMA2-FPSOS.PO} | Bin images/apple/{PLASMA-SYS2.PO => PLASMA2.SYS.PO} | Bin 5 files changed, 4 insertions(+), 4 deletions(-) rename images/apple/{PLASMA-BLD2.PO => PLASMA2-BLD.PO} (100%) rename images/apple/{PLASMA-DEM2.PO => PLASMA2-DEM.PO} (100%) rename images/apple/{PLASMA-FPSOS.PO => PLASMA2-FPSOS.PO} (100%) rename images/apple/{PLASMA-SYS2.PO => PLASMA2.SYS.PO} (100%) diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index 3ae359c..e2e7a4e 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -6,13 +6,13 @@ Download the four disk images (three if you don't plan to boot an Apple ///): [PLASMA 2.0 DP 800K Full System](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2.2mg?raw=true) -[PLASMA 2.0 DP System and ProDOS Boot](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA-SYS2.PO?raw=true) +[PLASMA 2.0 DP System and ProDOS Boot](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-SYS.PO?raw=true) -[PLASMA 2.0 DP Build Tools](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA-BLD2.PO?raw=true) +[PLASMA 2.0 DP Build Tools](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-BLD.PO?raw=true) -[PLASMA 2.0 DP Demos](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA-DEM2.PO?raw=true) +[PLASMA 2.0 DP Demos](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-DEM.PO?raw=true) -[PLASMA 2.0 DP Apple /// SOS Boot and SANE floating point modules](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA-SOS2.PO?raw=true) +[PLASMA 2.0 DP Apple /// SOS Boot and SANE floating point modules](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-FPSOS.PO?raw=true) PLASMA can be run from floppies, System in Drive 1, and Build or Demos in Drive 2. Mass storage is the recommended installation that looks like (replacing HARDISK with your volume name of choice): diff --git a/images/apple/PLASMA-BLD2.PO b/images/apple/PLASMA2-BLD.PO similarity index 100% rename from images/apple/PLASMA-BLD2.PO rename to images/apple/PLASMA2-BLD.PO diff --git a/images/apple/PLASMA-DEM2.PO b/images/apple/PLASMA2-DEM.PO similarity index 100% rename from images/apple/PLASMA-DEM2.PO rename to images/apple/PLASMA2-DEM.PO diff --git a/images/apple/PLASMA-FPSOS.PO b/images/apple/PLASMA2-FPSOS.PO similarity index 100% rename from images/apple/PLASMA-FPSOS.PO rename to images/apple/PLASMA2-FPSOS.PO diff --git a/images/apple/PLASMA-SYS2.PO b/images/apple/PLASMA2.SYS.PO similarity index 100% rename from images/apple/PLASMA-SYS2.PO rename to images/apple/PLASMA2.SYS.PO From 18102a319ae9830ee6d70d9f8c2bb0133bddc4a2 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Thu, 12 Dec 2019 11:24:00 -0800 Subject: [PATCH 031/149] Botched filename --- images/apple/{PLASMA2.SYS.PO => PLASMA2-SYS.PO} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename images/apple/{PLASMA2.SYS.PO => PLASMA2-SYS.PO} (100%) diff --git a/images/apple/PLASMA2.SYS.PO b/images/apple/PLASMA2-SYS.PO similarity index 100% rename from images/apple/PLASMA2.SYS.PO rename to images/apple/PLASMA2-SYS.PO From f67e58011a3eb2f8c64fcdcddb8bf6b63c4d94c7 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Fri, 13 Dec 2019 13:30:54 -0800 Subject: [PATCH 032/149] Auto-indent for editor --- src/toolsrc/ed.pla | 92 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 24 deletions(-) diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index 22c9884..7e895a7 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -196,16 +196,32 @@ def strpoolalloc(size) puts("OUT OF MEMORY!") return 0 end - -def strstripcpy(dststr, srcstr)#0 +def striplead(strptr, chr)#0 + byte striplen + + for striplen = 1 to ^strptr + if ^(strptr + striplen) <> chr + break + fin + next + if striplen > 1 + ^strptr = ^strptr - (striplen - 1) + memcpy(strptr + 1, strptr + striplen, ^strptr) + fin +end +def striptail(strptr, chr)#0 byte strlen - strlen = ^srcstr - while ^(srcstr + strlen) == $8D or ^(srcstr + strlen) == $A0 - strlen-- - loop - ^dststr = strlen - memcpy(dststr + 1, srcstr + 1, strlen) + for strlen = ^strptr downto 1 + if ^(strptr + strlen) <> $8D and ^(strptr + strlen) <> chr + break + fin + next + ^strptr = strlen +end +def strstripcpy(dststr, srcstr)#0 + memcpy(dststr, srcstr, ^srcstr + 1) + striptail(dststr, $80 | ' ') end def delstr(strptr)#0 byte mask, ofst @@ -799,13 +815,17 @@ def pasteline#0 fin end def joinline#0 - byte joinstr[80], joinlen + byte joinstr[80], joinlen, stripjoin[80] if cursrow < numlines - 1 strstripcpy(@joinstr, strlinbuf=>[cursrow]) - joinlen = joinstr + ^(strlinbuf=>[cursrow + 1]) + joinstr++ + joinstr[joinstr] = $80 | ' ' // add trailing space + memcpy(@stripjoin, strlinbuf=>[cursrow + 1], ^(strlinbuf=>[cursrow + 1]) + 1) + striplead(@stripjoin, $80 | ' '); + joinlen = joinstr + stripjoin if joinlen < 80 - memcpy(@joinstr + joinstr + 1, strlinbuf=>[cursrow + 1] + 1, ^(strlinbuf=>[cursrow + 1])) + memcpy(@joinstr + joinstr + 1, @stripjoin + 1, stripjoin) joinstr = joinlen delstr(strlinbuf=>[cursrow]) strlinbuf=>[cursrow] = newstr(@joinstr) @@ -820,27 +840,57 @@ def joinline#0 fin end def splitline#0 - byte splitstr[80], splitlen + byte splitstr[80], splitlen, i if openline(cursrow + 1) if curscol splitlen = ^(strlinbuf=>[cursrow]) if curscol < splitlen - 1 - memcpy(@splitstr + 1, strlinbuf=>[cursrow] + curscol + 1, splitlen - curscol) splitstr = splitlen - curscol + memcpy(@splitstr + 1, strlinbuf=>[cursrow] + curscol + 1, splitstr) + striplead(@splitstr, $80 | ' ') + for i = 1 to curscol - 1 + if ^(strlinbuf=>[cursrow] + i) <> $80 | ' ' + break + fin + memcpy(@splitstr + 2, @splitstr + 1, splitstr) + splitstr[1] = $80 | ' ' + splitstr++ + next strlinbuf=>[cursrow + 1] = newstr(@splitstr) - memcpy(@splitstr + 1, strlinbuf=>[cursrow] + 1, curscol) splitstr = curscol + memcpy(@splitstr + 1, strlinbuf=>[cursrow] + 1, splitstr) delstr(strlinbuf=>[cursrow]) strlinbuf=>[cursrow] = newstr(@splitstr) + curscol = i - 1 + if curscol > 39 + cursx = curscol - 39 + scrnleft = 39 + else + cursx = curscol + scrnleft = 0 + fin + else + if splitlen > 0 + for curscol = 1 to splitlen - 1 + if ^(strlinbuf=>[cursrow] + curscol) <> $80 | ' ' + break + fin + next + curscol-- + if curscol > 39 + cursx = curscol - 39 + scrnleft = 39 + else + cursx = curscol + scrnleft = 0 + fin + fin fin - else + else strlinbuf=>[cursrow + 1] = strlinbuf=>[cursrow] strlinbuf=>[cursrow] = @nullstr fin - curscol = 0 - cursx = 0 - scrnleft = 0 redraw cursdown fin @@ -1089,12 +1139,6 @@ def prfiles(optpath) putln return 0 end -def striplead(strptr, chr)#0 - while ^strptr and ^(strptr + 1) == chr - memcpy(strptr + 1, strptr + 2, ^strptr) - ^strptr-- - loop -end def parsecmd(strptr) byte cmd From 203b88a9798db0f86ec464c41bcd29cf5625278b Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 13 Dec 2019 19:48:11 -0800 Subject: [PATCH 033/149] Edit with auto-indent --- images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes src/samplesrc/hgr1test.pla | 66 ++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/images/apple/PLASMA2-SYS.PO b/images/apple/PLASMA2-SYS.PO index 2a16a395e33b0cdf5b4b173a08a285a587b66861..d3b1bed34995391b65879603d76ece670197d2f9 100755 GIT binary patch delta 4639 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 diff --git a/images/apple/PLASMA2.2mg b/images/apple/PLASMA2.2mg index 45da330e7fef648b7021de2ae93402b733df3dff..78d3ffc80793d3f848250143f437f2af1e5f8aa8 100644 GIT binary patch delta 4687 zcma*rdvp}l9l-HBGrJ^^*X(3Bn+JJ7=q4^gQshtpQG^&oSDeH_VhACGWeMS7%88t4 zk<9=F(Iq&btfE2^6A=?*@ZbrhLZJsLN33XVwG=HyMQg>kSVbZIP9iDxum17b`Q1Ce z`a4H+~3f43`*Ec(*o@S@K@dI_|FtIT&M#~lNiN2s`(pg!l zjz8>?7YONsdbL>cv!1{V<%E`Ref6dU`U*b%zFjcLpgKl4 z7!Z=jRz)Zf68>f*ODlJjIi!&2jHSbOvpOX(*1lrIkbCM%l_w>sJL)zRpL8-h(NOLf z)SaB~Fgkj+8Olo8)s<4aORZ^9jqg0hODPpbS2S;yk{LVD3d~Z9)&5rPPE`~IMhS9S zXDK6m{k>(9@T+2pFxtIs=X>i#VYx(N?IyLUI8bQko}H!S<^E6Z*@4`eR=a3l;<&QQ z6BF&4<5MryB+suG2d=U!HkK*=q=AZkiL0Z(DO2u_`zpowBsK6|ui;9IPP#++hxAo6 zt6Zt(V3sS#bA0Ldw5xiS@J&p!1CLM|#mBw(i4S`ZinG1G4bi&UJg!jGU7-{^+r7qc zZ**>jQXq9iH&rO9;o)9Z*SMfol(mR~dwf>pi`vK313T4fL)U^LQqP*?i*8YuUqU~5 zk?qw3LEoz7m#}K5TtU%YvP8GwNmawQny?&r#NXr*Sht_w21aszo>nyy6kImn zewR+UINc;Sj}%Mn+1q#3T~g(5w%=^8$d~h_zFdEEJwc>CEZR==)|V7snq=SIE~mt0 z7wE74V=?3M8&a1COPW@)uz5uRO)zRgUc(Mr4K1o3Z?|a)yJ0YG-jZ85Ft-fBnErZI z)lC1#>9O%X>TPIM3++4jf2t0>^pvU9KXLX>f8FIQy>ZrCUK)+5R0`x*vZ7a4D%rBG zMenFo45=&HRjH(TJ3KnmZc&?<<7K-j`u9quY5eBoe3{AB8C@wg_D$UsP(@9%z18w% zgOOf)WQ392?~b1gZ=c(LsXxqBvZgcozk}GJ`Y?ObZyu4(VuVV0fq%I6;AyIDB2;u*7M1rVsixgj%Y8+23v_~1|vPugiHnM(? z#NF%l5*tuoCK;d)bQ-?B8*8y!7gam%M%(W3cEv9u}rzplB=KctEO0aZ zYo&&bs(wrur*i|D!nmmU0%}NN5jcwel*)?_**QBIRuvc`E=w?CJe2tH{CdtC&krxu zSK0MtaeE<~-X0Psg7SpIdZ9-r2bEagwhX=8zFb2@Em!QzdVaj@=-8PvjOj+;h9WK> zT^3YAE+d0Sb4}xn7~#K_ts6)M27RzMu+Ob_x4M z;TZ@yOA|aPA&1a`i`bkj_rrOs6lvxLb)!iDwd*DI#pnrlXRMpyDzY5-%oR zM!cMO1@6Hrtj0Rrk0xwItV5Uya3LKz7>%*G8rNf*Ls;`1nzh)GZQbq2HXCVg;P?>d zqK>dITL_-QE_9+Bd(cDTA%|?f%<)YIoTTpz{)ta<4&UN?^g?k8E5Vs z8>E?wXxG!;M!SvnbF_P~4+n4a(~##TIv z$FT#gcnV$EjTf*N2XPoLHPS5OynRJKKL;Tg}4giFcH_r3#%wz zGp7;Xira8IW}_1GurQwWuO(Q9daQzpb=ZIiHc{wd3Oz#n7`CGY?bwA*?8YAK!yz2T zt9TuM!3X#VpW#dDou{6ZAgr{6ux92Ya5u=ql_p)85@pUa^6Nt(Hsjytg&ci~=`Sc~_8XCen9kdM(AiwT&FV(=5jEJYbA5kxJ*b$qNqBi7&n zG{M5dcodIg2U_tIIPbe)?c+m>lE!XT8{NG&J!0W zJ1iqvwiaPaa<;WCImz0dte9QNVPUqw&hlH{ruL%XMUC#6RLUfr+Hca z0lwT&#RDT{R%~0v+ljeW#3(r_uMvu*ce5BD0ke>tufzSLVh%!(vSjJ^_8SK-Ydf_M~jRh+K)>^1+TM8 z6zkPOWL@jrUR1k&q&c9&o8nqmwF( zZs>s_7>+r3UKQqY&Tk-YB7R4WG2SEIg^%bTP&MOY+E3I3^BD0-;&W<(af$QS@GWj~ z>=xsM6o!<-43jZNByluir3jdD(qY8Y>Bz|x;&kFJ=!$IQq8Iw09|q!0Y{O3M#UY%+ zIb6Us+@PM*<}^FnQp_w{igAxkn7wHqvI*m16k>!eAdF&y(J03_RFgQxrW#Mt)-fQ+ zu|;?h%ke7KVIvyxI(gf;$OqU@{&9|-#u;3~6v-Y(2Edy1KDSIyo5f(Pu1 zIfTwgdpo0ylP}pF=Bsw6v6bY%(7#1LGR$ctgbCxWFkub}bC|>Fm(j1rL_CJ6m;nQ` zF$eQdj|EtW#dsMj(SX1vKAP|b-o-BL#z#1aBRGn`;{;CQEWX5Le2we4f&ZWdYB+a_ zNJJwJ9gvJPWZ-V(gbVAz@v=i;FrA^`w~+B$j6f+WP=)b$0#or6{s05BQHK|>3@fn? z8_|d+yo2rdEB0bP4&ew+<5IW?7~c^53pa5K_6TN=SU3@fcqAejzd{f6MIQ1o5Ps+= zMky*V4%L{5X%WJ-BBIQfB2vu;;w{7)pCqA{P5`s;EasseCKh7}mSYvxVgoj#3C(yL+pq)IaT6_EJTk^%#Kf>~ z5QlgqA{`mHH^9dO@L?E6#t5?{#%WX%S7Rb3V;XAld(6Z$n1|=E01L4gORy5_u^E5H z7Hq{QIEgQD71y~|;071_fsPu>tA|L$z>Nf?BMaHcMNjm@gBXaR7=|K@LJ3Myfoe>} zEYzVMi(>hfjddEUh#O*A|Fs00(1;y)A0J>34&Y;af)luiukbbgjhnaysR^^4rkGAm z7#?&$64KBG-H?lW(GL${2!?6=5gI`-8e=gYk6{L$#%$DKF6yxW3$YkWz^`nh0h`c- zX1tAUcprPP4ST_qkqzoYM#Y6#QmH$bEs1_D-Z}eQ_L5fv8Lse z<|e1pIP4VWWm@6l3&kbOyInRTn>N=KXZCSPGtVWBhv`q^_!QcyE}L2F3O548vs`h; zT*l4E^H_)_Sc%nGhmB}N6W(;O{<{eFU>^?RFh0ZQ6ujt4F~Z!u^N58T3E+PrBMYP4 z!W`pP&2qOiE8VGPjoW5ENn7iVFlQ6jxur3eyanVfbSuVk;#I^A?j&=qJK5Oa&f_)V z;1=-H(R|zOGTx)z>9!fWIQAj-;}AZ@XE=^i_yXtLR@7Irn^pLPywX(GIajI6n<8O@ T9bpJZ1R~K6QET$1M92IW)G4TK diff --git a/src/samplesrc/hgr1test.pla b/src/samplesrc/hgr1test.pla index 41efef9..97ace56 100644 --- a/src/samplesrc/hgr1test.pla +++ b/src/samplesrc/hgr1test.pla @@ -20,6 +20,54 @@ const hgr2 = $4000 const page1 = 0 const page2 = 1 word hgrpage[] = hgr1, hgr2 +byte hgradrl[] = $00,$00,$00,$00,$00,$00,$00,$00 +word = $80,$80,$80,$80,$80,$80,$80,$80 +word = $00,$00,$00,$00,$00,$00,$00,$00 +word = $80,$80,$80,$80,$80,$80,$80,$80 +word = $00,$00,$00,$00,$00,$00,$00,$00 +word = $80,$80,$80,$80,$80,$80,$80,$80 +word = $00,$00,$00,$00,$00,$00,$00,$00 +word = $80,$80,$80,$80,$80,$80,$80,$80 +word = $28,$28,$28,$28,$28,$28,$28,$28 +word = $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 +word = $28,$28,$28,$28,$28,$28,$28,$28 +word = $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 +word = $28,$28,$28,$28,$28,$28,$28,$28 +word = $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 +word = $28,$28,$28,$28,$28,$28,$28,$28 +word = $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 +word = $50,$50,$50,$50,$50,$50,$50,$50 +word = $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 +word = $50,$50,$50,$50,$50,$50,$50,$50 +word = $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 +word = $50,$50,$50,$50,$50,$50,$50,$50 +word = $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 +word = $50,$50,$50,$50,$50,$50,$50,$50 +word = $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 +byte hgradrh[] = $00,$04,$08,$0C,$10,$14,$18,$1C +word = $00,$04,$08,$0C,$10,$14,$18,$1C +word = $01,$05,$09,$0D,$11,$15,$19,$1D +word = $01,$05,$09,$0D,$11,$15,$19,$1D +word = $02,$06,$0A,$0E,$12,$16,$1A,$1E +word = $02,$06,$0A,$0E,$12,$16,$1A,$1E +word = $03,$07,$0B,$0F,$13,$17,$1B,$1F +word = $03,$07,$0B,$0F,$13,$17,$1B,$1F +word = $00,$04,$08,$0C,$10,$14,$18,$1C +word = $00,$04,$08,$0C,$10,$14,$18,$1C +word = $01,$05,$09,$0D,$11,$15,$19,$1D +word = $01,$05,$09,$0D,$11,$15,$19,$1D +word = $02,$06,$0A,$0E,$12,$16,$1A,$1E +word = $02,$06,$0A,$0E,$12,$16,$1A,$1E +word = $03,$07,$0B,$0F,$13,$17,$1B,$1F +word = $03,$07,$0B,$0F,$13,$17,$1B,$1F +word = $00,$04,$08,$0C,$10,$14,$18,$1C +word = $00,$04,$08,$0C,$10,$14,$18,$1C +word = $01,$05,$09,$0D,$11,$15,$19,$1D +word = $01,$05,$09,$0D,$11,$15,$19,$1D +word = $02,$06,$0A,$0E,$12,$16,$1A,$1E +word = $02,$06,$0A,$0E,$12,$16,$1A,$1E +word = $03,$07,$0B,$0F,$13,$17,$1B,$1F +word = $03,$07,$0B,$0F,$13,$17,$1B,$1F word hgrscan[] = $0000,$0400,$0800,$0C00,$1000,$1400,$1800,$1C00 word = $0080,$0480,$0880,$0C80,$1080,$1480,$1880,$1C80 word = $0100,$0500,$0900,$0D00,$1100,$1500,$1900,$1D00 @@ -45,11 +93,29 @@ word = $02D0,$06D0,$0AD0,$0ED0,$12D0,$16D0,$1AD0,$1ED0 word = $0350,$0750,$0B50,$0F50,$1350,$1750,$1B50,$1F50 word = $03D0,$07D0,$0BD0,$0FD0,$13D0,$17D0,$1BD0,$1FD0 word hcolor[] = $0000,$552A,$2A55,$7F7F,$8080,$D5AA,$AAD5,$FFFF + +word ball0[9] = $0000, $1800, $3C00, $7E00, $7E00, $3C00, $1800, $0000 + +def hgrBLT(page, x, y, w, h, pSrc)#0 + word pDst + byte i + + repeat + pDst = hgrscan[y] | page + x + for i = 0 to w - 1 + pDst->[i] = pSrc->[i] + next + pSrc = pSrc + w + y++ + h-- + until not h +end memset(hgr1, 0, $2000) // Clear HGR page 1 ^showpage1 ^showfull ^showhires ^showgraphics +hgrBlt(hgrpage[0], 20, 100, 2, 8, @ball0) getc ^showpage1 ^showtext From 27129fe152f6c7110377d41c91bbfe8484e621b8 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sat, 14 Dec 2019 17:42:39 -0800 Subject: [PATCH 034/149] Upgrade editor to programmers editor --- src/tftpsys | 1 + src/toolsrc/ed.pla | 631 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 485 insertions(+), 147 deletions(-) diff --git a/src/tftpsys b/src/tftpsys index d652e52..78b1609 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -14,6 +14,7 @@ echo "SYS/JITUNE"; atftp $1 --put -l rel/apple/JITUNE#FE1000 -r $2/SYS/JITUNE echo "SYS/ARGS"; atftp $1 --put -l rel/ARGS#FE1000 -r $2/SYS/ARGS#FE1000 echo "SYS/DHCP"; atftp $1 --put -l rel/DHCP#FE1000 -r $2/SYS/DHCP#FE1000 echo "SYS/ED"; atftp $1 --put -l rel/ED#FE1000 -r $2/SYS/ED#FE1000 +echo "SYS/TFTPD"; atftp $1 --put -l rel/TFTPD#FE1000 -r $2/SYS/TFTPD#FE1000 echo "SYS/ETHERIP"; atftp $1 --put -l rel/ETHERIP#FE1000 -r $2/SYS/ETHERIP#FE1000 echo "SYS/MOUSE"; atftp $1 --put -l rel/apple/MOUSE#FE1000 -r $2/SYS/MOUSE#FE1000 echo "SYS/FIBER"; atftp $1 --put -l rel/FIBER#FE1000 -r $2/SYS/FIBER#FE1000 diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index 7e895a7..3e6e047 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -49,13 +49,15 @@ const keyctrlu = $95 const keyctrlv = $96 const keyctrlw = $97 const keyctrlx = $98 +const keyctrly = $99 const keyctrlz = $9A const keydelete = $FF // // Data and text buffer constants // -const MAXLINES = 1500 +const MAXLINES = 999 const MAXLINESSIZE = MAXLINES+24 +const MAXCLIPLINES = 256 const MAXLNLEN = 79 const MAXSTRPLSIZE = $8000 //const STRPLMAPSIZE = 224 // $E0 = 28K is memory@16 bytes per bit map, 128 bytes per 8 bit map, 1K bytes per 8 byte map @@ -64,28 +66,31 @@ const changed = 1 const insmode = 2 const showcurs = 4 const uppercase = 8 +const selection = 16 const shiftlock = 128 // // Text screen row address array // -word txtscrn = $0400,$0480,$0500,$0580,$0600,$0680,$0700,$0780 -word = $0428,$04A8,$0528,$05A8,$0628,$06A8,$0728,$07A8 -word = $0450,$04D0,$0550,$05D0,$0650,$06D0,$0750,$07D0 +const scrnwidth = 35 +word txtscrn = $0404,$0484,$0504,$0584,$0604,$0684,$0704,$0784 +word = $042C,$04AC,$052C,$05AC,$062C,$06AC,$072C,$07AC +word = $0454,$04D4,$0554,$05D4,$0654,$06D4,$0754,$07D4 // // Editor variables // byte nullstr = "" +byte[80] findstr = "" byte[64] filename = "UNTITLED" byte exit = FALSE byte flags = 0 byte flash = 0 word numlines = 0 -word cutbuf = 0 +word numcliplines = 0 word arg word strplsize = MAXSTRPLSIZE -word strpool, strplmapsize, strlinbuf, strpoolmap +word strpool, strplmapsize, txtlinbuf, cliplinbuf, strpoolmap byte cursx, cursy, scrnleft, curscol, underchr, curschr -word keyin, cursrow, scrntop, cursptr +word keyin, cursrow, selrow, scrntop, cursptr byte a3echo = $80 byte a3noecho = $00 // @@ -117,17 +122,17 @@ STHILP LDA (SRC),Y BNE STHILP + RTS end -asm cpyln(srcstr, dststr)#0 - LDA ESTKL,X - STA DSTL - LDA ESTKH,X - STA DSTH - INX +asm lncpy(dststr, srcstr)#0 LDA ESTKL,X STA SRCL LDA ESTKH,X STA SRCH INX + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + INX LDY #$00 LDA (SRC),Y TAY @@ -148,7 +153,43 @@ CPLNLP LDA (SRC),Y ++ STA (DST),Y RTS end - +asm lnupcpy(dststr, srcstr)#0 + LDA ESTKL,X + STA SRCL + LDA ESTKH,X + STA SRCH + INX + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + INX + LDY #$00 + LDA (SRC),Y + TAY + LDA #$00 + INY + STA (DST),Y + DEY + BEQ +++ +CPUPLP LDA (SRC),Y + CMP #$20 + BCS + + ADC #$60 ++ AND #$7F + CMP #$7B + BCS ++ + CMP #$61 + BCC ++ + SEC + SBC #$20 +++ STA (DST),Y + DEY + BNE CPUPLP + LDA (SRC),Y ++++ STA (DST),Y + RTS +end def bell#0 putc($07) end @@ -257,7 +298,8 @@ def inittxtbuf#0 word i if not strpool - strlinbuf = heapalloc(MAXLINESSIZE*2) + txtlinbuf = heapalloc(MAXLINESSIZE*2) + cliplinbuf = heapalloc(MAXCLIPLINES*2) while isult(heapavail, strplsize) strplsize = strplsize - 4096 loop @@ -267,9 +309,17 @@ def inittxtbuf#0 strplmapsize = strplsize / 128 strpoolmap = heapalloc(strplmapsize) strpool = heapalloc(strplsize) + memset(txtlinbuf, @nullstr, MAXLINESSIZE*2) + memset(cliplinbuf, @nullstr, MAXCLIPLINES*2) + memset(strpoolmap, 0, strplmapsize) + else + for i = 0 to MAXLINESSIZE-1 + if txtlinbuf=>[i] <> @nullstr + delstr(txtlinbuf=>[i]) + txtlinbuf=>[i] = @nullstr + fin + next fin - memset(strlinbuf, @nullstr, MAXLINESSIZE*2) - memset(strpoolmap, 0, strplmapsize) numlines = 1 cursrow = 0 curscol = 0 @@ -277,7 +327,7 @@ def inittxtbuf#0 cursy = 0 scrnleft = 0 scrntop = 0 - cutbuf = 0 + flags = flags & ~selection end // // Case conversion/printing routines @@ -315,7 +365,7 @@ def txtupper#0 flags = flags | uppercase for i = numlines - 1 downto 0 - strupper(strlinbuf=>[i]) + strupper(txtlinbuf=>[i]) next end def txtlower#0 @@ -323,9 +373,23 @@ def txtlower#0 flags = flags & ~uppercase for i = numlines - 1 downto 0 - strlower(strlinbuf=>[i]) + strlower(txtlinbuf=>[i]) next end +def strtonum(strptr) + word num, i + byte c + + num = 0 + for i = 1 to ^strptr + c = ^(strptr + i) & $7F + if c < '0' and c > '9' + break + fin + num = num * 10 + c - '0' + next + return num +end def nametostr(namestr, len, strptr)#0 ^strptr = len memcpy(strptr + 1, namestr, len) @@ -345,7 +409,7 @@ def readtxt(filename, startline)#0 if txtbuf sethibit(@txtbuf) if flags & uppercase; strupper(@txtbuf); fin - strlinbuf=>[numlines] = newstr(@txtbuf) + txtlinbuf=>[numlines] = newstr(@txtbuf) numlines++ fin if !(numlines & $0F); putc('.'); fin @@ -354,8 +418,8 @@ def readtxt(filename, startline)#0 // // Make sure there is a blank line at the end of the buffer // - if numlines < MAXLINES and strlinbuf=>[numlines - 1] <> @nullstr - strlinbuf=>[numlines] = @nullstr + if numlines < MAXLINES and txtlinbuf=>[numlines - 1] <> @nullstr + txtlinbuf=>[numlines] = @nullstr numlines++ fin fin @@ -374,12 +438,12 @@ def writetxt(filename)#0 // // Remove blank lines at end of text. // - while numlines > 1 and strlinbuf=>[numlines - 1] == @nullstr; numlines--; loop + while numlines > 1 and txtlinbuf=>[numlines - 1] == @nullstr; numlines--; loop // // Write all the text line to the file. // for i = 0 to numlines - 1 - cpyln(strlinbuf=>[i], @txtbuf) + lncpy(@txtbuf, txtlinbuf=>[i]) txtbuf++; txtbuf[txtbuf] = $0D // Add CR to end of line fileio:write(refnum, @txtbuf + 1, txtbuf) if !(i & $0F); putc('.'); fin @@ -406,57 +470,137 @@ def drawrow(row, ofst, strptr)#0 else numchars = ^strptr - ofst fin - if numchars >= 40 - numchars = 40 + if numchars >= 36 + numchars = 36 else - memset(scrnptr + numchars, $A0A0, 40 - numchars) + memset(scrnptr + numchars, $A0A0, 36 - numchars) fin memcpy(scrnptr, strptr + ofst + 1, numchars) end +def drawgutter(scrnrow, ofst)#0 + byte row, hilite, ofstch, huns, tens, ones + word scrnptr, scrnrow + + // + // Draw line numbers and gutter hilites + // + ofstch = ofst ?? $80 | '<' :: $80 | ' ' + huns, tens = divmod(scrnrow + 1, 100) + tens, ones = divmod(tens, 10) + for row = 0 to 23 + scrnptr = txtscrn[row] - 4 + if scrnrow < numlines + if flags & selection and (scrnrow >= selrow and scrnrow <= cursrow) or (scrnrow >= cursrow and scrnrow <= selrow) + hilite = $00 + elsif scrnrow == cursrow + hilite = $00 + else + hilite = $80 + fin + if huns + ^scrnptr = hilite + '0' + huns + ^(scrnptr+1) = hilite + '0' + tens + ^(scrnptr+2) = hilite + '0' + ones + ones++ + if ones > 9 + ones = 0 + tens++ + if tens > 9 + tens = 0 + huns++ + fin + fin + elsif tens + ^scrnptr = hilite + ' ' + ^(scrnptr+1) = hilite + '0' + tens + ^(scrnptr+2) = hilite + '0' + ones + ones++ + if ones > 9 + ones = 0 + tens++ + if tens > 9 + tens = 0 + huns = 1 + fin + fin + elsif ones + ^scrnptr = hilite + ' ' + ^(scrnptr+1) = hilite + ' ' + ^(scrnptr+2) = hilite + '0' + ones + ones++ + if ones > 9 + ones = 0 + tens = 1 + fin + fin + ^(scrnptr+3) = ofstch + else + *scrnptr = $A0A0 + *(scrnptr+2) = $A0A0 + fin + scrnrow++ + next +end def drawscrn(toprow, ofst)#0 byte row, numchars word strptr, scrnptr + + drawgutter(toprow, ofst) + // + // Draw text + // if ofst for row = 0 to 23 - strptr = strlinbuf=>[toprow + row] + strptr = txtlinbuf=>[toprow + row] scrnptr = txtscrn[row] if ofst >= ^strptr numchars = 0 else numchars = ^strptr - ofst fin - if numchars >= 40 - numchars = 40 + if numchars >= 36 + numchars = 36 else - memset(scrnptr + numchars, $A0A0, 40 - numchars) + memset(scrnptr + numchars, $A0A0, 36 - numchars) fin memcpy(scrnptr, strptr + ofst + 1, numchars) next else for row = 0 to 23 - strptr = strlinbuf=>[toprow + row] + strptr = txtlinbuf=>[toprow + row] scrnptr = txtscrn[row] numchars = ^strptr - if numchars >= 40 - numchars = 40 + if numchars >= 36 + numchars = 36 else - memset(scrnptr + numchars, $A0A0, 40 - numchars) + memset(scrnptr + numchars, $A0A0, 36 - numchars) fin memcpy(scrnptr, strptr + 1, numchars) next fin end def cursoff#0 + word scrnptr + if flags & showcurs - ^cursptr = underchr + ^cursptr = underchr + scrnptr = txtscrn[cursy] - 4 + *scrnptr = *scrnptr | $8080 + ^(scrnptr+2) = ^(scrnptr+2) | $80 flags = flags & ~showcurs + fin end def curson#0 + word scrnptr + if !(flags & showcurs) cursptr = txtscrn[cursy] + cursx underchr = ^cursptr ^cursptr = curschr + scrnptr = txtscrn[cursy] - 4 + *scrnptr = *scrnptr & $7F7F + ^(scrnptr+2) = ^(scrnptr+2) & $7F flags = flags | showcurs fin end @@ -509,6 +653,9 @@ def cursup#0 cursrow-- if cursy > 0 cursy-- + if flags & selection + drawgutter(scrntop, scrnleft) + fin else scrntop = cursrow drawscrn(scrntop, scrnleft) @@ -529,6 +676,9 @@ def cursdown#0 cursrow++ if cursy < 23 cursy++ + if flags & selection + drawgutter(scrntop, scrnleft) + fin else scrntop = cursrow - 23 drawscrn(scrntop, scrnleft) @@ -564,13 +714,13 @@ def pgleft#0 next end def cursright#0 - if curscol < 80 + if curscol < MAXLNLEN cursoff curscol++ - if cursx < 39 + if cursx < scrnwidth cursx++ else - scrnleft = curscol - 39 + scrnleft = curscol - scrnwidth drawscrn(scrntop, scrnleft) fin curson @@ -583,6 +733,79 @@ def pgright#0 cursright next end +def curshpos(hpos)#0 + cursoff + curscol = hpos + if curscol > scrnwidth + cursx = curscol - scrnwidth + scrnleft = scrnwidth + else + cursx = curscol + scrnleft = 0 + fin + curson +end +def cursvpos(vpos)#0 + cursrow = vpos + if cursrow > numlines - 1 + cursrow = numlines - 1 + fin + if numlines > 23 and cursrow > 12 + cursy = 12 + scrntop = cursrow - 12 + else + cursy = cursrow + scrntop = 0 + fin + redraw +end +// +// Find string in text +// +def findline(strptr)#1 + byte upstr[80], scan, i + + if ^strptr >= findstr + lnupcpy(@upstr, strptr) + for scan = 1 to upstr - findstr + 1 + if upstr[scan] == findstr[1] + for i = 2 to findstr + if upstr[scan + i - 1] <> findstr[i] + break + fin + next + if i > findstr + curshpos(scan - 1) + return TRUE + fin + fin + next + fin + return FALSE +end +def findtxt#0 + word f + + // + // Search from current pos to end + // + for f = cursrow + 1 to numlines - 1 + if findline(txtlinbuf=>[f]) + cursvpos(f) + return + fin + next + // + // Search from beginning to current pos + // + for f = 0 to cursrow + if findline(txtlinbuf=>[f]) + cursvpos(f) + return + fin + next + bell +end // // Keyboard routines // @@ -661,9 +884,9 @@ def keyin3 is $80 | '5' key = keyctrld; break // Del is $80 | '.' - key = keyctrlb; break // Ins + key = keyctrlc; break // Copy is $80 | '0' - key = keyctrlv; break // Copy + key = keyctrlv; break // Paste is $80 | '-' key = keyctrlx; break // Cut wend @@ -773,7 +996,7 @@ def printtxt(slot)#0 scrncsw = *csw *csw = $C000 | (slot << 8) for i = 0 to numlines - 1 - cpyln(strlinbuf=>[i], @txtbuf) + lncpy(@txtbuf, txtlinbuf=>[i]) puts(@txtbuf) putln next @@ -781,8 +1004,8 @@ def printtxt(slot)#0 end def openline(row) if numlines < MAXLINES - memcpy(@strlinbuf=>[row + 1], @strlinbuf=>[row], (numlines - row) * 2) - strlinbuf=>[row] = @nullstr + memcpy(@txtlinbuf=>[row + 1], @txtlinbuf=>[row], (numlines - row) * 2) + txtlinbuf=>[row] = @nullstr numlines++ flags = flags | changed return TRUE @@ -790,48 +1013,152 @@ def openline(row) bell return FALSE end -def cutline#0 - delstr(cutbuf) - cutbuf = strlinbuf=>[cursrow] - memcpy(@strlinbuf=>[cursrow], @strlinbuf=>[cursrow + 1], (numlines - cursrow) * 2) - if numlines > 1 - numlines-- - fin - flags = flags | changed - if cursrow == numlines - cursup - fin - redraw +def freesel#0 + word i + + for i = 0 to numcliplines - 1 + if cliplinbuf=>[i] <> @nullstr + delstr(cliplinbuf=>[i]) + cliplinbuf=>[i] = @nullstr + fin + next + numcliplines = 0 end -def pasteline#0 - if cutbuf and numlines < MAXLINES - memcpy(@strlinbuf=>[cursrow + 1], @strlinbuf=>[cursrow], (numlines - cursrow) * 2) - strlinbuf=>[cursrow] = newstr(cutbuf) - numlines++ +def selrange#2 + word first, last + + if flags & selection + if cursrow > selrow + first, last = selrow, cursrow + else + first, last = cursrow, selrow + fin + else + first = cursrow + last = first + fin + return first, last +end +def beginsel#0 + flags = flags ^ selection + selrow = cursrow + drawgutter(scrntop, scrnleft) +end +def copysel#0 + word firstsel, lastsel + + freesel + firstsel, lastsel = selrange + for numcliplines = 0 to lastsel - firstsel + cliplinbuf=>[numcliplines] = newstr(txtlinbuf=>[firstsel + numcliplines]) + next + flags = flags & ~selection + drawgutter(scrntop, scrnleft) +end +def cutsel#0 + word firstsel, lastsel + + freesel + firstsel, lastsel = selrange + if lastsel - firstsel < MAXCLIPLINES + for numcliplines = 0 to lastsel - firstsel + cliplinbuf=>[numcliplines] = txtlinbuf=>[firstsel + numcliplines] + next + memcpy(@txtlinbuf=>[firstsel], @txtlinbuf=>[lastsel + 1], (numlines - lastsel + 1) * 2) + numlines = numlines - numcliplines + cursrow = firstsel + if cursrow >= numlines + cursrow = numlines - 1 + fin + if cursrow < scrntop + scrntop = cursrow + fin + cursy = cursrow - scrntop + flags = flags | changed + flags = flags & ~selection + redraw + else + bell + fin +end +def pastesel#0 + word p + + if numcliplines and numcliplines + numlines < MAXLINES + memcpy(@txtlinbuf=>[cursrow + numcliplines], @txtlinbuf=>[cursrow], (numlines - cursrow) * 2) + for p = 0 to numcliplines - 1 + txtlinbuf=>[cursrow + p] = newstr(cliplinbuf=>[p]) + next + numlines = numlines + numcliplines flags = flags | changed redraw else bell fin end +def indentsel#0 + byte indentstr[80], l + word firstsel, lastsel, i + + freesel + firstsel, lastsel = selrange + for i = firstsel to lastsel + l = ^(txtlinbuf=>[i]) + if l < MAXLNLEN - 2 + memcpy(@indentstr + 3, txtlinbuf=>[i] + 1, l) + indentstr[0] = l + 2 + indentstr[1] = $A0 + indentstr[2] = $A0 + delstr(txtlinbuf=>[i]) + txtlinbuf=>[i] = newstr(@indentstr) + flags = flags | changed + fin + next + redraw +end +def undentsel#0 + byte undentstr[80], l + word firstsel, lastsel, i + + freesel + firstsel, lastsel = selrange + for i = firstsel to lastsel + l = ^(txtlinbuf=>[i]) + if l + memcpy(@undentstr + 1, txtlinbuf=>[i] + 1, l) + if undentstr[1] == $A0 + memcpy(@undentstr + 1, @undentstr + 2, l - 1) + l-- + if l and undentstr[1] == $A0 + memcpy(@undentstr + 1, @undentstr + 2, l - 1) + l-- + fin + undentstr[0] = l + delstr(txtlinbuf=>[i]) + txtlinbuf=>[i] = newstr(@undentstr) + flags = flags | changed + fin + fin + next + redraw +end def joinline#0 byte joinstr[80], joinlen, stripjoin[80] if cursrow < numlines - 1 - strstripcpy(@joinstr, strlinbuf=>[cursrow]) - joinstr++ - joinstr[joinstr] = $80 | ' ' // add trailing space - memcpy(@stripjoin, strlinbuf=>[cursrow + 1], ^(strlinbuf=>[cursrow + 1]) + 1) + strstripcpy(@joinstr, txtlinbuf=>[cursrow]) + memcpy(@stripjoin, txtlinbuf=>[cursrow + 1], ^(txtlinbuf=>[cursrow + 1]) + 1) striplead(@stripjoin, $80 | ' '); joinlen = joinstr + stripjoin if joinlen < 80 + curshpos(joinstr) memcpy(@joinstr + joinstr + 1, @stripjoin + 1, stripjoin) joinstr = joinlen - delstr(strlinbuf=>[cursrow]) - strlinbuf=>[cursrow] = newstr(@joinstr) - delstr(strlinbuf=>[cursrow + 1]) + delstr(txtlinbuf=>[cursrow]) + txtlinbuf=>[cursrow] = newstr(@joinstr) + delstr(txtlinbuf=>[cursrow + 1]) numlines-- - memcpy(@strlinbuf=>[cursrow + 1], @strlinbuf=>[cursrow + 2], (numlines - cursrow) * 2) + memcpy(@txtlinbuf=>[cursrow + 1], @txtlinbuf=>[cursrow + 2], (numlines - cursrow) * 2) flags = flags | changed redraw else @@ -844,52 +1171,38 @@ def splitline#0 if openline(cursrow + 1) if curscol - splitlen = ^(strlinbuf=>[cursrow]) + splitlen = ^(txtlinbuf=>[cursrow]) if curscol < splitlen - 1 splitstr = splitlen - curscol - memcpy(@splitstr + 1, strlinbuf=>[cursrow] + curscol + 1, splitstr) + memcpy(@splitstr + 1, txtlinbuf=>[cursrow] + curscol + 1, splitstr) striplead(@splitstr, $80 | ' ') - for i = 1 to curscol - 1 - if ^(strlinbuf=>[cursrow] + i) <> $80 | ' ' + for i = 1 to curscol + if ^(txtlinbuf=>[cursrow] + i) <> $80 | ' ' break fin memcpy(@splitstr + 2, @splitstr + 1, splitstr) splitstr[1] = $80 | ' ' splitstr++ next - strlinbuf=>[cursrow + 1] = newstr(@splitstr) + txtlinbuf=>[cursrow + 1] = newstr(@splitstr) splitstr = curscol - memcpy(@splitstr + 1, strlinbuf=>[cursrow] + 1, splitstr) - delstr(strlinbuf=>[cursrow]) - strlinbuf=>[cursrow] = newstr(@splitstr) - curscol = i - 1 - if curscol > 39 - cursx = curscol - 39 - scrnleft = 39 - else - cursx = curscol - scrnleft = 0 - fin + memcpy(@splitstr + 1, txtlinbuf=>[cursrow] + 1, splitstr) + delstr(txtlinbuf=>[cursrow]) + txtlinbuf=>[cursrow] = newstr(@splitstr) + curshpos(i - 1) else if splitlen > 0 for curscol = 1 to splitlen - 1 - if ^(strlinbuf=>[cursrow] + curscol) <> $80 | ' ' + if ^(txtlinbuf=>[cursrow] + curscol) <> $80 | ' ' break fin - next - curscol-- - if curscol > 39 - cursx = curscol - 39 - scrnleft = 39 - else - cursx = curscol - scrnleft = 0 - fin + next + curshpos(curscol - 1) fin fin else - strlinbuf=>[cursrow + 1] = strlinbuf=>[cursrow] - strlinbuf=>[cursrow] = @nullstr + txtlinbuf=>[cursrow + 1] = txtlinbuf=>[cursrow] + txtlinbuf=>[cursrow] = @nullstr fin redraw cursdown @@ -908,9 +1221,9 @@ def editline(key) if (editkey(key)) flags = flags | changed memset(@editstr, $A0A0, 80) - strstripcpy(@editstr, strlinbuf=>[cursrow]) - undoline = strlinbuf=>[cursrow] - strlinbuf=>[cursrow] = @editstr + strstripcpy(@editstr, txtlinbuf=>[cursrow]) + undoline = txtlinbuf=>[cursrow] + txtlinbuf=>[cursrow] = @editstr repeat if key >= keyspace if key == keydelete @@ -919,20 +1232,11 @@ def editline(key) memcpy(@editstr[curscol], @editstr[curscol + 1], editstr - curscol) editstr-- fin - curscol-- - cursoff - if cursx > 0 - cursx-- - drawrow(cursy, scrnleft, @editstr) - else - scrnleft-- - drawscrn(scrntop, scrnleft) - fin + curshpos(curscol - 1) curson fin elsif curscol < MAXLNLEN - curscol++ - cursx++ + curshpos(curscol + 1) if flags & insmode if editstr < MAXLNLEN or editstr.MAXLNLEN == $A0 editstr++ @@ -942,8 +1246,7 @@ def editline(key) memcpy(@editstr[curscol + 1], @editstr[curscol], editstr - curscol) fin else - curscol-- - cursx-- + curshpos(curscol - 1) key = editstr[curscol] bell fin @@ -954,11 +1257,11 @@ def editline(key) fin editstr[curscol] = caseconv(key) cursoff - if cursx <= 39 + if cursx <= scrnwidth drawrow(cursy, scrnleft, @editstr) else scrnleft++ - cursx = 39 + cursx = scrnwidth drawscrn(scrntop, scrnleft) fin curson @@ -983,9 +1286,9 @@ def editline(key) key = keyin() until not editkey(key) if editstr - strlinbuf=>[cursrow] = newstr(@editstr) + txtlinbuf=>[cursrow] = newstr(@editstr) else - strlinbuf=>[cursrow] = @nullstr + txtlinbuf=>[cursrow] = @nullstr fin delstr(undoline) fin @@ -1017,14 +1320,25 @@ def editmode#0 curshome; break is keyctrle cursend; break + is keyctrlb + beginsel; break + is keyctrlc + copysel; break is keyctrlx - cutline; break + cutsel; break is keyctrlv - pasteline; break + pastesel; break is keyctrlf - if numlines < MAXLINES and cursrow == numlines - 1 - strlinbuf=>[numlines] = @nullstr - numlines++ + if cursrow == (numlines - 1) + if numlines < MAXLINES + numlines++ + cursdown + flags = flags | changed + drawgutter(scrntop, scrnleft) + else + bell + fin + break fin cursdown is keyctrlo @@ -1043,11 +1357,19 @@ def editmode#0 is keyctrlt joinline; break is keyctrli - keyin = @tabkeyin - editline(keyspace) - setkeyin + if flags & selection + if flags & insmode + indentsel + else + undentsel + fin + else + keyin = @tabkeyin + editline(keyspace) + setkeyin + fin break - is keyctrlb + is keyctrly if flags & insmode flags = flags & ~insmode curschr = ' ' @@ -1056,14 +1378,6 @@ def editmode#0 curschr = '+' fin break - is keyctrlc - if flags & uppercase - txtlower - else - txtupper - fin - redraw - break is keyescape if MACHID == $F2 // Apple 3 dev_control(cmdsys.devcons, 11, @a3echo) @@ -1167,7 +1481,7 @@ def chkchng end def cmdmode#0 byte slot - word cmdptr + word cmdptr, line clrscrn puts("PLASMA Editor, Version 2.0 Dev\n") @@ -1175,11 +1489,26 @@ def cmdmode#0 puts(@filename) cmdptr = gets($BA) when toupper(parsecmd(cmdptr)) - is 'A' + is 'F' // Find string + if ^cmdptr + lnupcpy(@findstr, cmdptr) + fin + findtxt + return + is 'G' // Goto line # + line = strtonum(cmdptr) + if line + curshpos(0) + cursvpos(line - 1) + fin + is 'E' // Edit mode + is 0 + return + is 'A' // Append file readtxt(cmdptr, numlines) flags = flags | changed break - is 'R' + is 'R' // Read file if chkchng inittxtbuf strstripcpy(@filename, cmdptr) @@ -1187,7 +1516,7 @@ def cmdmode#0 flags = flags & ~changed fin break - is 'W' + is 'W' // Write file if ^cmdptr strstripcpy(@filename, cmdptr) fin @@ -1195,11 +1524,11 @@ def cmdmode#0 //if flags & changed; fin flags = flags & ~changed break - is 'C' + is 'C' // Catalog prfiles(cmdptr); break - is 'P' + is 'P' // Prefix fileio:setpfx(cmdptr); break - is 'H' + is 'H' // Hardcopy if ^cmdptr slot = cmdptr.1 - '0' else @@ -1207,17 +1536,25 @@ def cmdmode#0 fin printtxt(slot) break - is 'Q' + is 'Q' // Quit exit = chkchng - is 'E' - is 0 - return - is 'N' + if not exit + return + fin + break + is 'N' if chkchng inittxtbuf strstripcpy(@filename, "UNTITLED") fin break + is 'T' // Toggle upper/lower case display + if flags & uppercase + txtlower + else + txtupper + fin + break otherwise bell putc('?') From c7f48765b2fe96877765846c906672640a53545f Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sat, 14 Dec 2019 17:58:35 -0800 Subject: [PATCH 035/149] Return to editor when toggling lower-case chip support --- src/toolsrc/ed.pla | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index 3e6e047..1c553e1 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -1495,6 +1495,13 @@ def cmdmode#0 fin findtxt return + is 'T' // Toggle upper/lower case display + if flags & uppercase + txtlower + else + txtupper + fin + return is 'G' // Goto line # line = strtonum(cmdptr) if line @@ -1548,13 +1555,6 @@ def cmdmode#0 strstripcpy(@filename, "UNTITLED") fin break - is 'T' // Toggle upper/lower case display - if flags & uppercase - txtlower - else - txtupper - fin - break otherwise bell putc('?') From a902bc4c971332192d133e3b274a1b8bb2500606 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 14 Dec 2019 18:42:56 -0800 Subject: [PATCH 036/149] DP 1ED (editor!) release --- README.md | 2 +- doc/Editor.md | 10 +++++++--- doc/Version 2.0.md | 6 +++++- images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes src/mkrel | 3 +++ 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 97cb42b..1538bbe 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 12/12/2019 PLASMA 2.0 Developer Preview 1a Available! +# 12/14/2019 PLASMA 2.0 Developer Preview 1ED Available! [Download and read the Release Notes](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md) # 4/29/2018 PLASMA 1.2 Available! diff --git a/doc/Editor.md b/doc/Editor.md index 4d0b5f0..b687385 100644 --- a/doc/Editor.md +++ b/doc/Editor.md @@ -52,13 +52,17 @@ EDIT COMMANDS: CTRL-Q = JUMP BEGIN CTRL-E = JUMP END CTRL-D = DELETE CHAR - CTRL-X = DELETE/CUT LINE - CTRL-V = COPY DELETED LINE + CTRL-B = BEGIN SELECTION + CTRL-C = COPY SELECTION INTO CLIPBOARD + CTRL-X = CUT SELECTION INTO CLIPBOARD + CTRL-V = PASTE CLIPBOARD CTRL-O = OPEN NEW LINE CTRL-F = OPEN A FOLLOWING NEW LINE CTRL-T = JOIN LINES - CTRL-B = TOGGLE INSERT/OVERWRITE + CTRL-Y = TOGGLE INSERT/OVERWRITE TAB/CTRL-I = INSERT SPACES TO NEXT TAB + = INDENT SELECTION IF INSERT MODE + = UNDENT SELECTION IF OVERWITE MODE ESCAPE = SWITCH TO COMMAND MODE DELETE = DELETE CHAR LEFT diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index e2e7a4e..6a60943 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -1,4 +1,4 @@ -# PLASMA Version 2.0 Developer Preview 1a +# PLASMA Version 2.0 Developer Preview 1ED Welcome to PLASMA: the Grand Unifying Platform for the Apple 1, ][, and ///. @@ -102,6 +102,10 @@ There is a [YouTube playlist](https://www.youtube.com/playlist?list=PLlPKgUMQbJ7 - The documentation is sparse and incomplete. Yep, could use your help... +# Changed in PLASMA for 2.0 DP 1ED + +1. Greatly improved code editor + # Changed in PLASMA for 2.0 DP 1a 1. Fix interaction with JIT compiler and module load/unload diff --git a/images/apple/PLASMA2-SYS.PO b/images/apple/PLASMA2-SYS.PO index d3b1bed34995391b65879603d76ece670197d2f9..32b3892edba676ce323df7545fe7e29b9bc7ec48 100755 GIT binary patch delta 12835 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 delta 10321 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 diff --git a/src/mkrel b/src/mkrel index fea68a8..b9c750e 100755 --- a/src/mkrel +++ b/src/mkrel @@ -28,11 +28,14 @@ cp rel/apple/JIT#FE1000 prodos/sys/JIT.REL cp rel/apple/JIT16#FE1000 prodos/sys/JIT16.REL cp rel/apple/JITUNE#FE1000 prodos/sys/JITUNE.REL cp rel/LZ4#FE1000 prodos/sys/LZ4.REL +cp rel/TFTPD#FE1000 prodos/sys/TFTPD.REL cp rel/FPSTR#FE1000 prodos/sys/FPSTR.REL cp rel/FPU#FE1000 prodos/sys/FPU.REL cp rel/SANE#FE1000 prodos/sys/SANE.REL cp ../sysfiles/FP6502.CODE#060000 prodos/sys/FP6502.CODE.BIN cp ../sysfiles/ELEMS.CODE#060000 prodos/sys/ELEMS.CODE.BIN +cp rel/apple/SOS#FE1000 prodos/sys/SOS.REL +cp rel/apple/GRAFIX#FE1000 prodos/sys/GRAFIX.REL rm -rf prodos/fpsos mkdir prodos/fpsos From 72ddf025e35b20d6f9620739fbe1c087e2e7f131 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 14 Dec 2019 19:25:01 -0800 Subject: [PATCH 037/149] Update editor docs --- doc/Editor.md | 3 +++ images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes 3 files changed, 3 insertions(+) diff --git a/doc/Editor.md b/doc/Editor.md index b687385..4936168 100644 --- a/doc/Editor.md +++ b/doc/Editor.md @@ -146,5 +146,8 @@ COMMAND MODE: P = SET PREFIX H [SLOT] = HARDCOPY TO DEVICE IN SLOT (DEFAULT 1) N = CLEAR TEXT IN MEMORY + T = TOGGLE LOWER-CASE SUPPORT (APPLE ][) + G = GO TO LINE # + F [STRING] = FIND STRING E = EDIT MODE 'RETURN' = EDIT MODE diff --git a/images/apple/PLASMA2-SYS.PO b/images/apple/PLASMA2-SYS.PO index 32b3892edba676ce323df7545fe7e29b9bc7ec48..53b786add7f90d073eeca74c6a3b1420f7e86c11 100755 GIT binary patch delta 172 zcmZp8z|ru4V?!XTz!821dlf4_WroKL41MY%!p(`S+Y?zCx9zSEQ9uH=3L*aP?mn&x zKK|jZLAuV4!LACyp#cH@K_LnnjsXEcnb>GeUXTuV1sfkvKUX`jZd(O+f1p+ckcfgZ rSl&$`IyfZA)6YE?sKQpk&C}0C0U`jFb_MHGP?#=%kTGl7A;vra)}AVK delta 48 zcmZp8z|ru4V?!XTfGGeUXTuV1sfkvKUX`jZd(O+f1p+c zkcfgZSl&$`IyfZA)6YE?sKQpk&C}0C0U`jFb_MHGP?)^9T5o#qOD4N^r&mls%nZaV aK+FonY(UHo#2i4(3B+96onCSOn+gEbw?Cf% delta 94 zcmX@mV056tXhRmOfG Date: Sun, 15 Dec 2019 13:24:26 -0800 Subject: [PATCH 038/149] Fix some editor redraw issues --- doc/Editor.md | 31 ++--- images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes src/toolsrc/ed.pla | 262 ++++++++++++++++++++++-------------- 4 files changed, 175 insertions(+), 118 deletions(-) diff --git a/doc/Editor.md b/doc/Editor.md index 4936168..5ec5e87 100644 --- a/doc/Editor.md +++ b/doc/Editor.md @@ -2,8 +2,8 @@ WELCOME TO THE PLASMA EDITOR! ============================= FIRST THINGS FIRST: -TO NAVIGATE, USE THE ARROW KEYS. ON THE -APPLE ][: +TO NAVIGATE, USE THE ARROW KEYS. ON +THE APPLE ][: CTRL-K = UP CTRL-J = DOWN. @@ -18,22 +18,23 @@ TO JUMP AROUND THE TEXT FILE USE: CTRL-Q = JUMP BEGINNING CTRL-E = JUMP END -THE 'ESCAPE' KEY WILL PUT YOU IN COMMAND -MODE. FROM THERE YOU CAN EXIT BY -ENTERING 'Q' AND 'RETURN'. YOU CAN ALSO -RETURN TO THE EDITOR BY JUST PRESSING -'RETURN'. +THE 'ESCAPE' KEY WILL PUT YOU IN +COMMAND MODE. FROM THERE YOU CAN +EXIT BY ENTERING 'Q' AND 'RETURN'. +YOU CAN ALSO RETURN TO THE EDITOR BY +JUST PRESSING 'RETURN'. ------- THE PLASMA EDITOR IS A SIMPLE TEXT EDITOR FOR ENTERING AND MANIPULATING -TEXT AND SOURCE CODE FILES. THE EDITOR -ONLY SUPPORTS 40 COLUMN TEXT ALTHOUGH -LINES CAN BE UP TO 79 CHARACTERS LONG. -THE SCREEN WILL SCROLL HORIZONTALLY -AS THE CURSOR MOVES. THERE IS 16K OF -MEMORY FOR THE TEXT BUFFER. +TEXT AND SOURCE CODE FILES. THE +EDITOR ONLY SUPPORTS 40 COLUMN TEXT +ALTHOUGH LINES CAN BE UP TO 79 +CHARACTERS LONG. THE SCREEN WILL +SCROLL HORIZONTALLY AS THE CURSOR +MOVES. THERE IS 16K OF MEMORY FOR +THE TEXT BUFFER. IT HAS TWO MODES, COMMAND AND EDIT. @@ -82,7 +83,7 @@ EDIT COMMANDS: APPLE ][, UPPER AND LOWER CASE ENTRY WORKS AS EXPECTED. - CTRL-C = FORCE LOWER-CASE CHARS + ESC T = FORCE LOWER-CASE CHARS If you have a lower-case character generator installed, you can force @@ -128,7 +129,7 @@ EDIT COMMANDS: OA-7 = JUMP BEGIN OA-1 = JUMP END OA-5 = DELETE CHAR - OA-- = DELETE/CUT LINE + OA-- = DELETE/CUT LI OA-0 = COPY DELETED LINE OA-ENTER = OPEN NEW LINE OA-. = TOGGLE INSERT/OVERWRITE diff --git a/images/apple/PLASMA2-SYS.PO b/images/apple/PLASMA2-SYS.PO index 53b786add7f90d073eeca74c6a3b1420f7e86c11..71302a9a62bc706e8ecc8f3f6afb0d454477fb64 100755 GIT binary patch delta 7419 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 Lr?sVjmt+11hjyy< diff --git a/images/apple/PLASMA2.2mg b/images/apple/PLASMA2.2mg index 85b5a121eeb6eb0573fff770092729118a4b6118..069da3093b42f1c0690792d56d5e02d6805fe1fc 100644 GIT binary patch delta 11239 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 diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index 1c553e1..b3509f9 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -72,6 +72,7 @@ const shiftlock = 128 // Text screen row address array // const scrnwidth = 35 +const scrnheight = 23 word txtscrn = $0404,$0484,$0504,$0584,$0604,$0684,$0704,$0784 word = $042C,$04AC,$052C,$05AC,$062C,$06AC,$072C,$07AC word = $0454,$04D4,$0554,$05D4,$0654,$06D4,$0754,$07D4 @@ -89,7 +90,8 @@ word numcliplines = 0 word arg word strplsize = MAXSTRPLSIZE word strpool, strplmapsize, txtlinbuf, cliplinbuf, strpoolmap -byte cursx, cursy, scrnleft, curscol, underchr, curschr +word cursx, cursy, scrnleft, curscol +byte underchr, curschr word keyin, cursrow, selrow, scrntop, cursptr byte a3echo = $80 byte a3noecho = $00 @@ -262,7 +264,7 @@ def striptail(strptr, chr)#0 end def strstripcpy(dststr, srcstr)#0 memcpy(dststr, srcstr, ^srcstr + 1) - striptail(dststr, $80 | ' ') + striptail(dststr, keyspace) end def delstr(strptr)#0 byte mask, ofst @@ -280,7 +282,7 @@ def newstr(strptr) word newptr strlen = ^strptr - while ^(strptr + strlen) == $8D or ^(strptr + strlen) == $A0 + while ^(strptr + strlen) == keyenter or ^(strptr + strlen) == keyspace strlen-- loop if strlen == 0 @@ -484,7 +486,8 @@ def drawgutter(scrnrow, ofst)#0 // // Draw line numbers and gutter hilites // - ofstch = ofst ?? $80 | '<' :: $80 | ' ' + //ofstch = ofst ?? $80 | '<' :: keyspace + ofstch = ofst ?? '<' :: ' ' huns, tens = divmod(scrnrow + 1, 100) tens, ones = divmod(tens, 10) for row = 0 to 23 @@ -619,6 +622,44 @@ def redraw#0 drawscrn(scrntop, scrnleft) curson end +def curshpos(hpos)#1 + byte needredraw + + needredraw = TRUE + if hpos < 0; hpos = 0; fin + if hpos > MAXLNLEN; hpos = MAXLNLEN; fin + curscol = hpos + cursx = curscol - scrnleft + if cursx > scrnwidth + cursx = scrnwidth + scrnleft = curscol - scrnwidth + elsif cursx < 0 + cursx = 0 + scrnleft = curscol + else + needredraw = FALSE + fin + return needredraw +end +def cursvpos(vpos)#1 + byte needredraw + + needredraw = TRUE + if vpos < 0; vpos = 0; fin + if vpos > numlines - 1; vpos = numlines - 1; fin + cursrow = vpos + cursy = cursrow - scrntop + if cursy > scrnheight + cursy = scrnheight + scrntop = cursrow - scrnheight + elsif cursy < 0 + cursy = 0 + scrntop = cursrow + else + needredraw = FALSE + fin + return needredraw +end def curshome#0 cursoff cursrow = 0 @@ -664,11 +705,15 @@ def cursup#0 fin end def pgup#0 - byte i - - for i = 0 to pgjmp - cursup - next + cursoff + if cursvpos(cursrow - pgjmp) + drawscrn(scrntop, scrnleft) + else + if flags & selection + drawgutter(scrntop, scrnleft) + fin + fin + curson end def cursdown#0 if cursrow < numlines - 1 @@ -687,11 +732,15 @@ def cursdown#0 fin end def pgdown#0 - byte i - - for i = 0 to pgjmp - cursdown - next + cursoff + if cursvpos(cursrow + pgjmp) + drawscrn(scrntop, scrnleft) + else + if flags & selection + drawgutter(scrntop, scrnleft) + fin + fin + curson end def cursleft#0 if curscol > 0 @@ -707,11 +756,15 @@ def cursleft#0 fin end def pgleft#0 - byte i - - for i = 0 to 7 - cursleft - next + cursoff + if curshpos(curscol - 8) + drawscrn(scrntop, scrnleft) + else + if flags & selection + drawgutter(scrntop, scrnleft) + fin + fin + curson end def cursright#0 if curscol < MAXLNLEN @@ -727,43 +780,21 @@ def cursright#0 fin end def pgright#0 - byte i - - for i = 0 to 7 - cursright - next -end -def curshpos(hpos)#0 - cursoff - curscol = hpos - if curscol > scrnwidth - cursx = curscol - scrnwidth - scrnleft = scrnwidth - else - cursx = curscol - scrnleft = 0 - fin - curson -end -def cursvpos(vpos)#0 - cursrow = vpos - if cursrow > numlines - 1 - cursrow = numlines - 1 - fin - if numlines > 23 and cursrow > 12 - cursy = 12 - scrntop = cursrow - 12 - else - cursy = cursrow - scrntop = 0 - fin - redraw + cursoff + if curshpos(curscol + 8) + drawscrn(scrntop, scrnleft) + else + if flags & selection + drawgutter(scrntop, scrnleft) + fin + fin + curson end // // Find string in text // def findline(strptr)#1 - byte upstr[80], scan, i + byte upstr[MAXLNLEN+1], scan, i if ^strptr >= findstr lnupcpy(@upstr, strptr) @@ -990,7 +1021,7 @@ end // Printer routines // def printtxt(slot)#0 - byte txtbuf[80] + byte txtbuf[MAXLNLEN+1] word i, scrncsw scrncsw = *csw @@ -1002,17 +1033,6 @@ def printtxt(slot)#0 next *csw = scrncsw end -def openline(row) - if numlines < MAXLINES - memcpy(@txtlinbuf=>[row + 1], @txtlinbuf=>[row], (numlines - row) * 2) - txtlinbuf=>[row] = @nullstr - numlines++ - flags = flags | changed - return TRUE - fin - bell - return FALSE -end def freesel#0 word i @@ -1097,7 +1117,7 @@ def pastesel#0 fin end def indentsel#0 - byte indentstr[80], l + byte indentstr[MAXLNLEN+1], l word firstsel, lastsel, i freesel @@ -1107,8 +1127,8 @@ def indentsel#0 if l < MAXLNLEN - 2 memcpy(@indentstr + 3, txtlinbuf=>[i] + 1, l) indentstr[0] = l + 2 - indentstr[1] = $A0 - indentstr[2] = $A0 + indentstr[1] = keyspace + indentstr[2] = keyspace delstr(txtlinbuf=>[i]) txtlinbuf=>[i] = newstr(@indentstr) flags = flags | changed @@ -1117,7 +1137,7 @@ def indentsel#0 redraw end def undentsel#0 - byte undentstr[80], l + byte undentstr[MAXLNLEN+1], l word firstsel, lastsel, i freesel @@ -1126,10 +1146,10 @@ def undentsel#0 l = ^(txtlinbuf=>[i]) if l memcpy(@undentstr + 1, txtlinbuf=>[i] + 1, l) - if undentstr[1] == $A0 + if undentstr[1] == keyspace memcpy(@undentstr + 1, @undentstr + 2, l - 1) l-- - if l and undentstr[1] == $A0 + if l and undentstr[1] == keyspace memcpy(@undentstr + 1, @undentstr + 2, l - 1) l-- fin @@ -1142,15 +1162,36 @@ def undentsel#0 next redraw end +def autoindent(strptr)#0 + byte i + + for i = 1 to ^strptr + if ^(strptr + i) <> keyspace + break + fin + next + curshpos(i - 1) +end +def openline(row) + if numlines < MAXLINES + memcpy(@txtlinbuf=>[row + 1], @txtlinbuf=>[row], (numlines - row) * 2) + txtlinbuf=>[row] = @nullstr + numlines++ + flags = flags | changed + return TRUE + fin + bell + return FALSE +end def joinline#0 - byte joinstr[80], joinlen, stripjoin[80] + byte joinstr[MAXLNLEN+1], joinlen, stripjoin[MAXLNLEN+1] if cursrow < numlines - 1 strstripcpy(@joinstr, txtlinbuf=>[cursrow]) memcpy(@stripjoin, txtlinbuf=>[cursrow + 1], ^(txtlinbuf=>[cursrow + 1]) + 1) - striplead(@stripjoin, $80 | ' '); + striplead(@stripjoin, keyspace); joinlen = joinstr + stripjoin - if joinlen < 80 + if joinlen <= MAXLNLEN curshpos(joinstr) memcpy(@joinstr + joinstr + 1, @stripjoin + 1, stripjoin) joinstr = joinlen @@ -1160,14 +1201,13 @@ def joinline#0 numlines-- memcpy(@txtlinbuf=>[cursrow + 1], @txtlinbuf=>[cursrow + 2], (numlines - cursrow) * 2) flags = flags | changed - redraw - else - bell + return fin fin + bell end def splitline#0 - byte splitstr[80], splitlen, i + byte splitstr[MAXLNLEN+1], splitlen, i if openline(cursrow + 1) if curscol @@ -1175,13 +1215,13 @@ def splitline#0 if curscol < splitlen - 1 splitstr = splitlen - curscol memcpy(@splitstr + 1, txtlinbuf=>[cursrow] + curscol + 1, splitstr) - striplead(@splitstr, $80 | ' ') + striplead(@splitstr, keyspace) for i = 1 to curscol - if ^(txtlinbuf=>[cursrow] + i) <> $80 | ' ' + if ^(txtlinbuf=>[cursrow] + i) <> keyspace break fin memcpy(@splitstr + 2, @splitstr + 1, splitstr) - splitstr[1] = $80 | ' ' + splitstr[1] = keyspace splitstr++ next txtlinbuf=>[cursrow + 1] = newstr(@splitstr) @@ -1193,7 +1233,7 @@ def splitline#0 else if splitlen > 0 for curscol = 1 to splitlen - 1 - if ^(txtlinbuf=>[cursrow] + curscol) <> $80 | ' ' + if ^(txtlinbuf=>[cursrow] + curscol) <> keyspace break fin next @@ -1204,8 +1244,6 @@ def splitline#0 txtlinbuf=>[cursrow + 1] = txtlinbuf=>[cursrow] txtlinbuf=>[cursrow] = @nullstr fin - redraw - cursdown fin end def editkey(key) @@ -1215,12 +1253,13 @@ def editkey(key) return FALSE end def editline(key) - byte editstr[80] + byte editstr[MAXLNLEN+1], localchange, need word undoline + localchange = FALSE if (editkey(key)) - flags = flags | changed - memset(@editstr, $A0A0, 80) + localchange = TRUE + memset(@editstr + 1, $A0A0, MAXLNLEN) strstripcpy(@editstr, txtlinbuf=>[cursrow]) undoline = txtlinbuf=>[cursrow] txtlinbuf=>[cursrow] = @editstr @@ -1232,13 +1271,18 @@ def editline(key) memcpy(@editstr[curscol], @editstr[curscol + 1], editstr - curscol) editstr-- fin - curshpos(curscol - 1) + cursoff + if curshpos(curscol - 1) + drawscrn(scrntop, scrnleft) + else + drawrow(cursy, scrnleft, @editstr) + fin curson fin elsif curscol < MAXLNLEN - curshpos(curscol + 1) + curscol++ if flags & insmode - if editstr < MAXLNLEN or editstr.MAXLNLEN == $A0 + if editstr < MAXLNLEN or editstr.MAXLNLEN == keyspace editstr++ if curscol >= editstr editstr = curscol @@ -1246,7 +1290,7 @@ def editline(key) memcpy(@editstr[curscol + 1], @editstr[curscol], editstr - curscol) fin else - curshpos(curscol - 1) + curscol-- key = editstr[curscol] bell fin @@ -1257,12 +1301,10 @@ def editline(key) fin editstr[curscol] = caseconv(key) cursoff - if cursx <= scrnwidth - drawrow(cursy, scrnleft, @editstr) - else - scrnleft++ - cursx = scrnwidth + if curshpos(curscol) drawscrn(scrntop, scrnleft) + else + drawrow(cursy, scrnleft, @editstr) fin curson else @@ -1282,15 +1324,21 @@ def editline(key) cursoff drawrow(cursy, scrnleft, @editstr) curson + localchange = FALSE fin key = keyin() until not editkey(key) - if editstr - txtlinbuf=>[cursrow] = newstr(@editstr) - else - txtlinbuf=>[cursrow] = @nullstr - fin - delstr(undoline) + if localchange + flags = flags | changed + delstr(undoline) + if editstr + txtlinbuf=>[cursrow] = newstr(@editstr) + else + txtlinbuf=>[cursrow] = @nullstr + fin + else + txtlinbuf=>[cursrow] = undoline + fin fin return key end @@ -1343,6 +1391,11 @@ def editmode#0 cursdown is keyctrlo openline(cursrow) + if cursrow + autoindent(txtlinbuf=>[cursrow - 1]) + else + curshpos(0) + fin redraw break is keyenter @@ -1350,12 +1403,15 @@ def editmode#0 splitline else openline(cursrow + 1) - cursdown - redraw fin + autoindent(txtlinbuf=>[cursrow]) + cursvpos(cursrow + 1) + redraw break is keyctrlt - joinline; break + joinline + redraw + break is keyctrli if flags & selection if flags & insmode From 9011b1cc647edfc5b3eec9d38631279193c34bef Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sun, 15 Dec 2019 16:33:09 -0800 Subject: [PATCH 039/149] Add more compiler stats --- src/toolsrc/codegen.pla | 1 - src/toolsrc/parse.pla | 18 +++++++++++++++--- src/toolsrc/plasm.pla | 6 +----- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/toolsrc/codegen.pla b/src/toolsrc/codegen.pla index 8ad0fb7..002fbe6 100644 --- a/src/toolsrc/codegen.pla +++ b/src/toolsrc/codegen.pla @@ -585,7 +585,6 @@ def init_idglobal#0 codebuff = heapalloc(codebufsz) codeptr = codebuff lastglobal = idglobal_tbl - puts("Data+Code buffer size = "); puti(codebufsz); putln end def new_idlocal(nameptr, len, type, size)#0 if idmatch(nameptr, len, @idlocal_tbl, locals); exit_err(ERR_DUP|ERR_ID); fin diff --git a/src/toolsrc/parse.pla b/src/toolsrc/parse.pla index 5f44cf2..1e63a36 100644 --- a/src/toolsrc/parse.pla +++ b/src/toolsrc/parse.pla @@ -1211,9 +1211,8 @@ def parse_lambda return func_tag end def parse_defs - byte idlen, cfnparms, cfnvals - word type, idstr, func_tag, idptr - + byte idlen, cfnparms, cfnvals, defstr[17] + word type, idstr, func_tag, idptr, defcodeptr type = FUNC_TYPE when token is CONST_TKN @@ -1256,6 +1255,11 @@ def parse_defs func_tag = new_tag(WORD_FIXUP) new_idfunc(idstr, idlen, type, func_tag, cfnparms, infuncvals) fin + // + // Print def name + // + nametostr(idstr, idlen > 16 ?? 16 :: idlen, @defstr); puts(@defstr); putc(':') + defcodeptr = codeptr emit_tag(func_tag) new_dfd(func_tag) while parse_vars(LOCAL_TYPE); nextln; loop @@ -1276,20 +1280,26 @@ def parse_defs emit_lambdafunc(lambda_tag[cfnvals], lambda_cparms[cfnvals], lambda_seq[cfnvals]) new_dfd(lambda_tag[cfnvals]) next + puti(codeptr - defcodeptr); puts(@bytesln) + wend return token == EOL_TKN ?? TRUE :: FALSE end def parse_module#0 init_idglobal init_idlocal + puts("Data+Code buffer size = "); puti(codebufsz); putln if nextln // // Compile module // + puts("\nDATA:"); while parse_mods; nextln; loop while parse_vars(GLOBAL_TYPE); nextln; loop emit_codeseg + puti(codeptr - codebuff); puts(@bytesln) while parse_defs; nextln; loop + puts("INIT:") entrypoint = codeptr prevstmnt = 0 init_idlocal @@ -1301,6 +1311,8 @@ def parse_module#0 emit_const(0) emit_leave fin + puti(codeptr - entrypoint); puts(@bytesln) + puts("\nTotal bytes compiled: "); puti(codeptr - codebuff); putln if token <> DONE_TKN; parse_warn("Missing DONE\n"); fin //dumpsym(idglobal_tbl, globals) fin diff --git a/src/toolsrc/plasm.pla b/src/toolsrc/plasm.pla index c6ab52c..675a7b5 100755 --- a/src/toolsrc/plasm.pla +++ b/src/toolsrc/plasm.pla @@ -307,6 +307,7 @@ byte lambda_cnt, lambda_num byte[LAMBDANUM] lambda_cparms word[LAMBDANUM] lambda_seq, lambda_tag predef parse_constexpr#3, parse_expr(codeseq)#2, parse_lambda +byte bytesln = " bytes\n" // // Arg pointer // @@ -444,10 +445,6 @@ end // // Handy functions // -def puth(hex)#0 - putc('$') - call($F941, hex >> 8, hex, 0, 0) -end def nametostr(namestr, len, strptr)#0 ^strptr = len memcpy(strptr + 1, namestr, len) @@ -583,7 +580,6 @@ if srcfile and relfile // parse_module fileio:close(srcref) - puts("\nBytes compiled: "); puti(codeptr - codebuff); putln // // Write REL file // From 454ecb29a80c380632cc663d38a0fd45eb2a90b0 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Mon, 16 Dec 2019 08:25:58 -0800 Subject: [PATCH 040/149] Improve indent/undent and toggle gutter view. Additional compiler stats --- README.md | 2 +- doc/Editor.md | 17 ++-- doc/Version 2.0.md | 6 +- images/apple/PLASMA2-BLD.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes src/toolsrc/ed.pla | 195 ++++++++++++++++++++++-------------- 7 files changed, 132 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index 1538bbe..74aa20c 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 12/14/2019 PLASMA 2.0 Developer Preview 1ED Available! +# 12/16/2019 PLASMA 2.0 Developer Preview 1 E+C Available! [Download and read the Release Notes](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md) # 4/29/2018 PLASMA 1.2 Available! diff --git a/doc/Editor.md b/doc/Editor.md index 5ec5e87..115fbb9 100644 --- a/doc/Editor.md +++ b/doc/Editor.md @@ -83,7 +83,7 @@ EDIT COMMANDS: APPLE ][, UPPER AND LOWER CASE ENTRY WORKS AS EXPECTED. - ESC T = FORCE LOWER-CASE CHARS + ESC T C = FORCE LOWER-CASE CHARS If you have a lower-case character generator installed, you can force @@ -98,11 +98,12 @@ EDIT COMMANDS: The 'SOLID-APPLE' key will modify theese keys: - SA-RETURN = OPEN LINE + SA-RETURN = OPEN FOLLOWING LINE SA-LEFT ARROW = JUMP LEFT SA-RIGHT ARROW = JUMP RIGHT SA-UP ARROR = JUMP UP SA-DOWN ARROW = JUMP DOWN + SA-TAB = DETAB Apple /// FEATURES: ------------------- @@ -111,11 +112,12 @@ EDIT COMMANDS: these keys: OA-\ = DELETE CHAR LEFT - OA-RETURN = OPEN LINE + OA-RETURN = OPEN FOLLOWING LINE OA-LEFT ARROW = JUMP LEFT OA-RIGHT ARROW = JUMP RIGHT OA-UP ARROR = JUMP UP OA-DOWN ARROW = JUMP DOWN + OA-TAB = DETAB On the keypad, 'OPEN-APPLE' allows the keys for navigation and misc: @@ -129,9 +131,9 @@ EDIT COMMANDS: OA-7 = JUMP BEGIN OA-1 = JUMP END OA-5 = DELETE CHAR - OA-- = DELETE/CUT LI - OA-0 = COPY DELETED LINE - OA-ENTER = OPEN NEW LINE + OA-- = CUT SELECTION INTO CLIPBOARD + OA-0 = PASTE CLIPBOARD + OA-ENTER = OPEN FOLLOWING LINE OA-. = TOGGLE INSERT/OVERWRITE COMMAND MODE: @@ -147,7 +149,8 @@ COMMAND MODE: P = SET PREFIX H [SLOT] = HARDCOPY TO DEVICE IN SLOT (DEFAULT 1) N = CLEAR TEXT IN MEMORY - T = TOGGLE LOWER-CASE SUPPORT (APPLE ][) + T G = TOGGLE GUTTER VIEW + T C = TOGGLE LOWER-CASE SUPPORT (APPLE ][) G = GO TO LINE # F [STRING] = FIND STRING E = EDIT MODE diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index 6a60943..2fd0945 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -1,4 +1,4 @@ -# PLASMA Version 2.0 Developer Preview 1ED +# PLASMA Version 2.0 Developer Preview 1 E+C Welcome to PLASMA: the Grand Unifying Platform for the Apple 1, ][, and ///. @@ -102,9 +102,9 @@ There is a [YouTube playlist](https://www.youtube.com/playlist?list=PLlPKgUMQbJ7 - The documentation is sparse and incomplete. Yep, could use your help... -# Changed in PLASMA for 2.0 DP 1ED +# Changed in PLASMA for 2.0 DP 1 E+C -1. Greatly improved code editor +1. Greatly improved code editor and additional compiler stats # Changed in PLASMA for 2.0 DP 1a diff --git a/images/apple/PLASMA2-BLD.PO b/images/apple/PLASMA2-BLD.PO index e12a48fe5b27125803f391ed0d0d12c294631a44..12ea5b6e22dca593d319b33c5d94621e85e49edb 100644 GIT binary patch delta 13990 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 delta 14005 zcmbW;349Y}{`m1{rqi^P9!Ywaw&@Xi#6k~lTH107rIuJCLIq^m7@$Z6HUt)rFnFMV zVAjeYmoDG|0t+4>F06o}yDEZ<;wp#eiXe+9xTtv0|K~}{CA+WR|Mz>nd}qG%%=OH3 z%`;P+bu@C;(a4PpH1nGy#hm=8_+0T%5eyz(p{2!Km2&THZOd*=DQ_FStXjQIh#%r7 zh=1R(CEBcX4S&?Enha;6@X>CO6&`I&lW9K5+I(MIww+9JT7{?W z7}rVT`ZOiiKRnr)E5Zc)O1ghy!o_um_u~GSQhZmWXewE9%m}79-*|ESEU8B?zsJmBSR@oSEPiF zyNeXRhZ4NdU6FRH8?d%N@z9ziRQCN*W?U_wI1Ep3;A*I2=!2ag|V(S6-8{`kIuduSt3Knv}KI zq^!G`a^t14-f%IgK^Ao5eoL)cI2uSK8OmBku^C%4l|k)ke*G!3F^vZ;lQDnhL5oLpS7pICi`XE;(?-5csiVF7Y)VP_ z_N19xEaS&nE5c@Nh!!%?HfX}F)rJeQ*APD3L`Aqxr+HL$$;|y0Dsg`rt@?os*Jk5W zo6;D6CZkEK>&Ut3QZHBlg_%uJwFSZxMd4LM){%c&%|yeIqqO6419FrP4et;ouN(a&Qj@31 zd&x5XLyF<@y;6~luUfdhN;6A&qq4M!xOu~st7IomOkkhqP511#I9h_O-I>KT=H@DX zWtS0USFZ1LI*|*|Ce~OQcUuMqJ4EkbF*ZJ9`O6y1R5r|?xyC~4kOj{G;;J-i^C*i- zW3^qevuIuW(ym;0d96$P;M#B62lv!NYwJU6d)g~y?Af|4EAPtVZV#<34qf5pJjG36 zWaKmcRvN8|!}66kNz5!zRx9(2*9w%wEdE%?Fg$O|fkLIbq8u>du2XKZ49)jMx|Zhq zOg>qD(XJ6&rd_8*E6RW^vx}6mO1o`^GY?rC_gfdt+%FgN$2jtHs0K}=h*~-*3zTif zf{scRo#EY%ic?jZ4O=NWZ#L>nm7e6_;ZiQvY`jsb6l)A2&BpmsC5QC%GNnI@v1Lkb zc(bF#HOZJ;#*<)@@p74x&4!Q5lp+=pos=3D^_@7&L}OkjB|U0wskeN4ln!Hbl9a9rYQ)^>ZiI#(!XStdaRIm__~{ z?W{D#tS_tG(n5Oubio;8y99Gr+C_1s)?_wmw7Vv?B9@`REzFm0+}lNQ=1eQiYKR;j zE`(QUyw&0hb1PmMyN;FBUN2OFX5))4iY<9WscbQ>!cx}(dHuX%%SLsK>lY)vt5Vi! zVuJJHHcuF*8Bq6ai)(EueP81Qj(Ue^JY@BVsm@Z-_z&y&53Q~mL+`3|Rk|53cU5{9 zvdd86N#MM$opv9OR@p~1ZZ5%j3*Dw7OEy-yZsc?eK9L7>Q_7VZV|F*CEbnZNFUb?R zz!&N4EcZ3@+!T%ikJ&Xh*V&dZ&tn#@1IEYQ6ubZOzRxkNt}cSp61mE2d<@E=OXpt9UpM3K z?n<72F^}L{xua`wlH57V8zBqnd&PC6v(Ma=;z@FCPr4=pQ5BK0{xnap0wd)B=)6H@ z-LcA^EDFr7C7pw%Mw3qPn7!fD2xaYZ6jLS|1EMF%F;-?bDbtxO%So+mOPMkbCGf!T zM9%j`vd1vjdZW6B(y^vn&yr9M*5!l?XQDiM1xGhsJc;v=Y;BIi7h7S%<*Ug3d`V85 zJZ3iMd%1_=h$K&;v!Cpt*y4jbT%8Ley{FPHi+gC>nr)d&D|hTk@>pGG<(1{hZtkgc z{-5`HuBTFZJ;j_r2?y)L*+<@TWNioeT%s)ni!YQT^6EBi3}4_i39qJl!#z=>zi;+M z(RA2Oi5a=&O8d+Cca|$z{$T!l%TrcgS+Y(ZVzOX^g*_%z4DDpnRpn2`gvy;eO9<99 z?WUXDEhlv3w7fr)n#~4~@ZwmGWjWcL& zH8^a@<`NuWr`dhNxmn0Iu-9J2C4$?{vddmN$%g;0lS~Po6wqgOAb?Zr$)T{=rG z&(SNgBCq&~%uA%a7Fl(+UWMJJwdPp;Z#kxus|~Tk9g6Vg32*-R(^hXGoy4co>$NT= z1*VscH+v~XBOJxfIN{D);LRf`Z!AUb&a3;T#hE5JWWkKn*70An_}ZE$;cN z?Z%o)rFSd?P#9Ap*-jW}j6Ho6yXSPG(=6O!3%p?-Ei~?E?l84q-B&Hal8O!fn%P$C ziIwFgCsN z@+8bWX(d%=-THsXI+?EHz(TuEyDDQc8xLK|hP(jzlch)JB#Ppyo@g@RJZuVPFe#Xu zV9tX1xs*#f;_33VYi?YgzxmhamnZz+mVL0)lP=aRxwx1;XP#;N7uN3Tj4voW$}Z)a zvTMz)d{`U^_8s~3xcDT_Y|50wMJAI3uP_ewR-&`y6vyG%E_anJFrhW8rmLEy`Pa?F zDDR^eU(K2_9Rb^=*Lsk@uX7| zj+L@F3hlDiQYaR;U>cChWQV~xN_etd(^BO_F3UA1)tM4XW_ZsMuE$dujb*St^_oWU zhyPS*!Kc*T}kty`MXLiKe`#tK_AR{pDu-Ec8u zze%OHhouJFA+_97*0OU|=ddeVVX)TI9Myc;@D+p>4&lrDj}2_#f3Jto?WDPOrpi&n zX;P?|`mcm1&rxlsC77#e2~0psN_=*%XuQ}@sb{$M*gXZW6ixM{dmM6+H{X}%Nv963 zDo^JmvX(ynxYe;Fr>&6rZAzCNIZd|VJWqkg;o6@nd}*F^IWdxl|Hppx@TC^XHxiji zKU0%1ReaYnPsFy&7t33Um zLVE|F(ZOM9pF(ev>A{iba{9{(wc)EQa>fWpnXI6qo~p0NQ=|>#LE$NqEmPLp_|L7i zBZYh-(6DKq?y$xa)_!v8Rl@0wJ_D5Yqp6X$4DIv1VZ!xPN^p+>oW!*`&Dr;Ir)Wd? zR0{9lve(pRg-($0-yRCVy5uuJSgNsmfHEP&QA{Svn>5)SWImkJnoL@oL`qa9@nfz~w2We9gLE$)t_B zO|?8Zcrjw)ue`qk6Jghy<*dBUt4+Nbvd85IL3Hl zJZ)V=Y)qXwsa?qWF}I%D6XUASranU#Vr^HZGf#MoMFW{G4Y4)E4bSA&$U?SW8>kfX zI{58CCFhnaZX(`m4NaP_yaz{#>Prz`v&_PQ*85MF_iw)P{^g-5*WCW(K}wGGGn*&v z`4nGT=pKv~UNTn?QtYJ5lsT71Df0F4ASI3B3U<<&pIDrKmTzC7Az!}g$|2tuDX*={ z^w9V&(>cH=ykS1RTDVodiF{^r&Qe^b2RLW)#k9!G2Ni0ypRCm)zDWkFFjAgD@3Ss4 zIDMPlN6u3tX)La>Jo!aKlqZ<3+f71qhKa~UK3*onLU+upLyjWeu&eKvzD54z3yWaF z94XuR5@tIrUElN%-Tb#L&M$f8F+QkKY&Bf}S$l`z8_)qe9Y~w+)wn=OXxA@;lafns z$+9^Hx2&=!h=TAdUzRvu&^u)ePzWgs#Ows!%wOWwr1DfY}bx#;Z?I{9J6vbx6!Tj zHjekD56ir);9S-x3N*SI6M9!_ma~26+gVfV)~Rka?;Gojr>&FOiMJ5B z*SAK_4N4(%Mj`L!=WLJQ(`j2__Q~q4->L|Tq@k_6&Brc{-kvbp(IQ{4Jp?BteCB1| zz{HwQ59-Vl)~p$yTgjm>TsBrgX@!cZ`{iO%=JUZK_$?t=O#c5~P8YYVvL}kX6V|J% zo)`acw{Y==t_|NiJZ+c+&Ej)$u)&8uGPdcijd3e|HZWmm(>;6)!*?Iq8}fOB z7ZE(j?+IHZgQ?5_f}a~n=fs{c1`~y2XjYyG`LK&{J($zlTpVWETE1&>D|`_ZGmcxY zdSnWUKvv>iEX$_%Z9E1Peabb*Qf0DZ}pS%s%nXwW6_) z@upK5;O`SZpM=If@nalic8mP_T&d0&XC*X4NZx{}1s(jY|+} zF6bR9wX0f^gjxw5d_7XP<0N8|g<6W?*a2G#fBeBy2ul@eA1$eKVUUBgBGju{-~~QC)5WrSjQREFr`?CT^M2$>Yexu-y$_j zsKZd7O(wAyKO-+ks1IU2&Z06`sB?4uLOnoGXeYPWiCfzXbxfX6=ivZ`<_mQxMig*& zg+kqiW`|Ijv#32V3BQzZj#8oa#RyEpS{%UoGNB&B&z&f(&O$u`t&32*^(6L}3-v^W zP`~NVoerSr2NDnBLN#PyFekr31TKWBfha91VAHIDd@W3OXd=)-(*k9hs&^sou7wAx zG)?bA+@JJ;>{F`=eF*Cfni?2K+6*kfQ`m|<_#FNp_=yVF0vRa5Al!->ScsK)34aUM z^moFAz84>ai@-m^ZTexBM_C?Y`DJ*newJmpiSwB>J;o&TM5H1ed2pZuI-x6inuK5P zV-kT09B>B-(=Zp!Sc@0&4gQTE@Dp0lCPL`(NJctr$VCTqi4cME2#a1x+!q5-0~bcJ z?fwW&e~5Si0ug?pKSr<^OYsC&;c0BdOW20jIq*0K{)_lD&Z7m9kwP~k9_`Q(H5iKN zcnHl{ij`P{7x4xT;GmzMuW%MWq6HCcgdPnu5|E5`XpaskLpM~R9|qw@48thghDJ=m z?{N?A#XLNM$FLkL;a|hgCTzxb?8aNzi!X5sXP`z2JqjtvKn@%zMrTx@HwK^%Lopm< za2pt(^r@JRyKo;KilY7(5G=w{Jc(zq9?xS7UcoNx#$T}yAL0{yhGRI1vp5$e0!eK( zJ*_R7L;<>^2KBfJBXJuhFI=a*ziH`eP9I zdzL;CcfgCga6jf^A)dr)tidL{+uLM*IEMmG3Y0D2*cP=Zcz)PGNcUg(X%xCLV{5mPZ8_u>IOgg?N*ay*6g*n(|% z6|dn9?7=>~k0baR;bx&*kcez_HBLOL(Bp5~eqhJ_=(n0k`80OoxsK@DLuxBQUT8 zEATA*&+)Sn+pr67;BR;b`>-De@DUE-6MTkaWa3LQc#8OIoW(iP&ReYdFT}zs^e~vv z2GNLv6^Tf(a)VZ@U$+tDSmX2x606XM^&6~Ky`K0cjKmn+hxu5D$FTx`#8X&<%{YLc z&@Nu+*JB(W#S8cZEhtN%%5e`?BvAiv5uC)3MCu<8!kHujPb4JEXh3GkdAzmp&Kfash(t;ehcvg+|K%A$+p0g$>zW_$+7xc($-@?4*U6uOc4QR zN?c%6iaFp;iPi5&q5onQ>C01W`bOf-&{9R9IMo*Dni{9~PGzvcO&ATPTY3}j15+-2 zF8eM>wdn@&GCafjMvmRWv9GcI4)(#%d`v%#f8l#5Y19+ip*=dG4{9+CZcM@ycySNr zVKJ8B2|SDEumPL!BDUZaY{w3~fxj{T)AtZC&(ja#IQ|9ZeEPTe5x+ob$K4|q?U0Ln zIM5NLC`W(P;6~hx-(VspV><4}90afk%iB@^PZKBz zBXBDwq6xplowx_H@gSOEU>R2989awgnbiMwf*sh6x3M3wHs*9lLK-rV1v~Olf-dNV zKDZvWxDmrK3S%)2O_%~N?uL&0Fb|LV`B`ccfhTQh;LkQqf0gxJ*p0v9ZMN;R+4T2` z|AC`8j(?GU&Zg==5Q{7kuxDv{K^7%NTti$(d?Q?}-<%b%-@aXEVyp`>zbrQUXkMU3Zg613^D%gM*u?4SSH@-&aTpA;)QHy%~7Pn(29>hE> zz|;61VRlAVq#zr1l=%7SjwDTCtZs-RW zZpI8eiw)R>7jYbZk;j23L@BD#7XvX2qc9$KVm9Vr37!IP$NEv6#5XvP3uu#1l_D1% z&=u9_iyQGV;_#-BoYgFyrKei;1yhN#AN&qv+)qt<1cs}Z{h$B zBd(A}hK}fhn{X#)V-+?RQvZJ=IE3RkjW7rO9$6?wZ#dD2N%%c<%*Denumn$H7v91i ze1xMogL4qqF#$yqGSD7f{rvPqf7IX>j71~vgxr2V9>HT+hG(!5Td)m#@IFr9EBqTV zMLa2yhpy<2{uqc_3_(5o!}uA2+b|vX;7{0zgE)nAxPXWbyp$pyNyvZ$LogZ>F$H%) z#~jQ<04uNx&)`LTgcBX8|8oSQBSnL@NJJVkU`GK;&>g){jlrnLaE!ul;lTt<#_!<6 zo$zBmHem<;j*oE!pLeAGza}_~bNCT0(28lrFe4G|kcn*MgKs~2G0MO*3{A~32fHsCIc)hDq&6Hj0RwqYk;$J;oF zBlrS6I#K+%8Mj~@CSw|A;$A$0N3jGeI#K_t3I2qa@DBFk5I(`@_^Oi#ob42+e@A>C z7oc@!T7?)SAsu`$*W05bI-?RdVK_$PHZ;PEyTG?V{b@fx&*6D&#p`$<|HK)5htXY_ z$>KKLfoZr44`3mdU^&)d6EecX0rp z-~@ic1+?i-?vaRmI8cl(s77B5#0?mZThNHfn2otuh{fHh|5XG}<4@Ryx9}bg;WHe= zdHjrs9?biZj(ilO0@WCZp%{h+xG@Qn@em%t<5-4guoheW{A|M+oQKwviy#UyFe4e6 zu%j4d=!z-~#NeJH@Y|l6K90B%li+n2Y!C&w? z{))Z$I}YP0KF29&y?BL(7449T0(3-Y^h7W8#TYbU3cR@6&yS9|Scu246i?tOJd1Vs z6JEe(?8I)ojrZ{(KE|0|B9Kz41=>|+1Trf#_3TPY0N0@_%F(-$Z%CDifnmhA!tds1 z9EtZ=YWjo3^RW<%u^dlgHP*7vhRQ^JGx4AC7wp1cNq>j*_lZBkAsodi(!VAXXNk|@ zXS9%}R>kY4DiLT?m8nNpQU7sO453IRF`bRM#CgPp#3jU?(G9&&jT$)N!p#`PzT?<; zBJmXB8C5p@ZkDrH-bdP8;zx)dBVLT9SV7vVDn8*=`9)w23G1*CFJKEB|H8(dEMKq6 z(cdC%5AnV#Ti`?$e*<9sH0x)p!UN~3!t@`Af8qk7S_C4iZF&q#Gs}c(9?{4^7HPTF zwm`3HO|K^ITdf5KREGsdn@RW$32qX`k+9fU)}$1gUfcOjtvPDT>rG09!vAEp{OQTc Gj{gUQsYOBn diff --git a/images/apple/PLASMA2-SYS.PO b/images/apple/PLASMA2-SYS.PO index 71302a9a62bc706e8ecc8f3f6afb0d454477fb64..6b77b064223b88a743eeb574e17e2150ff717127 100755 GIT binary patch delta 10002 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 bZw>rg1OL{*zcui04gCMrz?#C0Y~}v|Ks5{7 diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index b3509f9..633d200 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -51,6 +51,8 @@ const keyctrlw = $97 const keyctrlx = $98 const keyctrly = $99 const keyctrlz = $9A +const keytab = keyctrli +const keydetab = $9D const keydelete = $FF // // Data and text buffer constants @@ -64,18 +66,21 @@ const MAXSTRPLSIZE = $8000 const pgjmp = 16 const changed = 1 const insmode = 2 -const showcurs = 4 +const gutter = 4 const uppercase = 8 const selection = 16 +const showcurs = 32 const shiftlock = 128 // // Text screen row address array // -const scrnwidth = 35 -const scrnheight = 23 -word txtscrn = $0404,$0484,$0504,$0584,$0604,$0684,$0704,$0784 -word = $042C,$04AC,$052C,$05AC,$062C,$06AC,$072C,$07AC -word = $0454,$04D4,$0554,$05D4,$0654,$06D4,$0754,$07D4 +const scrnheight = 24 +const scrnbottom = 23 +word scrnwidth = 36 +word scrnright = 35 +word txtscrn = $0400,$0480,$0500,$0580,$0600,$0680,$0700,$0780 +word = $0428,$04A8,$0528,$05A8,$0628,$06A8,$0728,$07A8 +word = $0450,$04D0,$0550,$05D0,$0650,$06D0,$0750,$07D0 // // Editor variables // @@ -466,16 +471,16 @@ def drawrow(row, ofst, strptr)#0 byte numchars word scrnptr - scrnptr = txtscrn[row] + scrnptr = txtscrn[row] + (flags & gutter) if ofst >= ^strptr numchars = 0 else numchars = ^strptr - ofst fin - if numchars >= 36 - numchars = 36 + if numchars >= scrnwidth + numchars = scrnwidth else - memset(scrnptr + numchars, $A0A0, 36 - numchars) + memset(scrnptr + numchars, $A0A0, scrnwidth - numchars) fin memcpy(scrnptr, strptr + ofst + 1, numchars) end @@ -491,7 +496,7 @@ def drawgutter(scrnrow, ofst)#0 huns, tens = divmod(scrnrow + 1, 100) tens, ones = divmod(tens, 10) for row = 0 to 23 - scrnptr = txtscrn[row] - 4 + scrnptr = txtscrn[row] if scrnrow < numlines if flags & selection and (scrnrow >= selrow and scrnrow <= cursrow) or (scrnrow >= cursrow and scrnrow <= selrow) hilite = $00 @@ -545,38 +550,41 @@ def drawgutter(scrnrow, ofst)#0 next end def drawscrn(toprow, ofst)#0 - byte row, numchars + byte row, numchars, lofst word strptr, scrnptr - drawgutter(toprow, ofst) + lofst = flags & gutter + if lofst + drawgutter(toprow, ofst) + fin // // Draw text // if ofst for row = 0 to 23 strptr = txtlinbuf=>[toprow + row] - scrnptr = txtscrn[row] + scrnptr = txtscrn[row] + lofst if ofst >= ^strptr numchars = 0 else numchars = ^strptr - ofst fin - if numchars >= 36 - numchars = 36 + if numchars >= scrnwidth + numchars = scrnwidth else - memset(scrnptr + numchars, $A0A0, 36 - numchars) + memset(scrnptr + numchars, $A0A0, scrnwidth - numchars) fin memcpy(scrnptr, strptr + ofst + 1, numchars) next else for row = 0 to 23 strptr = txtlinbuf=>[toprow + row] - scrnptr = txtscrn[row] + scrnptr = txtscrn[row] + lofst numchars = ^strptr - if numchars >= 36 - numchars = 36 + if numchars >= scrnwidth + numchars = scrnwidth else - memset(scrnptr + numchars, $A0A0, 36 - numchars) + memset(scrnptr + numchars, $A0A0, scrnwidth - numchars) fin memcpy(scrnptr, strptr + 1, numchars) next @@ -587,23 +595,29 @@ def cursoff#0 if flags & showcurs ^cursptr = underchr - scrnptr = txtscrn[cursy] - 4 - *scrnptr = *scrnptr | $8080 - ^(scrnptr+2) = ^(scrnptr+2) | $80 + if flags & gutter + scrnptr = txtscrn[cursy] + *scrnptr = *scrnptr | $8080 + ^(scrnptr+2) = ^(scrnptr+2) | $80 + fin flags = flags & ~showcurs fin end def curson#0 + byte lofst word scrnptr if !(flags & showcurs) - cursptr = txtscrn[cursy] + cursx + lofst = flags & gutter + if lofst + scrnptr = txtscrn[cursy] + *scrnptr = *scrnptr & $7F7F + ^(scrnptr+2) = ^(scrnptr+2) & $7F + fin + cursptr = txtscrn[cursy] + lofst + cursx underchr = ^cursptr ^cursptr = curschr - scrnptr = txtscrn[cursy] - 4 - *scrnptr = *scrnptr & $7F7F - ^(scrnptr+2) = ^(scrnptr+2) & $7F flags = flags | showcurs fin end @@ -630,9 +644,9 @@ def curshpos(hpos)#1 if hpos > MAXLNLEN; hpos = MAXLNLEN; fin curscol = hpos cursx = curscol - scrnleft - if cursx > scrnwidth - cursx = scrnwidth - scrnleft = curscol - scrnwidth + if cursx > scrnright + cursx = scrnright + scrnleft = curscol - scrnright elsif cursx < 0 cursx = 0 scrnleft = curscol @@ -649,9 +663,9 @@ def cursvpos(vpos)#1 if vpos > numlines - 1; vpos = numlines - 1; fin cursrow = vpos cursy = cursrow - scrntop - if cursy > scrnheight - cursy = scrnheight - scrntop = cursrow - scrnheight + if cursy > scrnbottom + cursy = scrnbottom + scrntop = cursrow - scrnbottom elsif cursy < 0 cursy = 0 scrntop = cursrow @@ -770,10 +784,10 @@ def cursright#0 if curscol < MAXLNLEN cursoff curscol++ - if cursx < scrnwidth + if cursx < scrnright cursx++ else - scrnleft = curscol - scrnwidth + scrnleft = curscol - scrnright drawscrn(scrntop, scrnleft) fin curson @@ -793,12 +807,12 @@ end // // Find string in text // -def findline(strptr)#1 +def findline(strptr, start)#1 byte upstr[MAXLNLEN+1], scan, i if ^strptr >= findstr lnupcpy(@upstr, strptr) - for scan = 1 to upstr - findstr + 1 + for scan = start to upstr - findstr + 1 if upstr[scan] == findstr[1] for i = 2 to findstr if upstr[scan + i - 1] <> findstr[i] @@ -820,8 +834,11 @@ def findtxt#0 // // Search from current pos to end // + if findline(txtlinbuf=>[cursrow], curscol + 2) + return + fin for f = cursrow + 1 to numlines - 1 - if findline(txtlinbuf=>[f]) + if findline(txtlinbuf=>[f], 1) cursvpos(f) return fin @@ -830,7 +847,7 @@ def findtxt#0 // Search from beginning to current pos // for f = 0 to cursrow - if findline(txtlinbuf=>[f]) + if findline(txtlinbuf=>[f], 1) cursvpos(f) return fin @@ -891,7 +908,9 @@ def keyin3 key = keyctrlz; break is keyenter key = keyctrlf; break - is $80 | '\\' + is keytab + key = keydetab; break + is $80 | '\\' key = keydelete; break // Delete // // Map OA+keypad @@ -943,6 +962,8 @@ def keyin2e key = keyctrlz; break is keyenter key = keyctrlf; break + is keytab + key = keydetab; break wend fin return key @@ -981,6 +1002,11 @@ def keyin2 key = keydelete fin break + is keyarrowright + if ^pushbttn3 < 128 + key = keytab + fin + break otherwise if key >= $C0 and flags < shiftlock if ^pushbttn3 < 128 @@ -1014,9 +1040,6 @@ def setkeyin#0 keyin = @keyin2 wend end -def tabkeyin - return curscol < MAXLNLEN and curscol & $01 ?? keyspace :: 0 -end // // Printer routines // @@ -1266,19 +1289,19 @@ def editline(key) repeat if key >= keyspace if key == keydelete - if curscol > 0 - if curscol <= editstr - memcpy(@editstr[curscol], @editstr[curscol + 1], editstr - curscol) - editstr-- - fin + if curscol > 0 + if curscol <= editstr + memcpy(@editstr[curscol], @editstr[curscol + 1], editstr - curscol) + editstr-- + fin cursoff - if curshpos(curscol - 1) + if curshpos(curscol - 1) drawscrn(scrntop, scrnleft) else drawrow(cursy, scrnleft, @editstr) fin - curson - fin + curson + fin elsif curscol < MAXLNLEN curscol++ if flags & insmode @@ -1412,27 +1435,29 @@ def editmode#0 joinline redraw break - is keyctrli - if flags & selection - if flags & insmode - indentsel - else - undentsel - fin - else - keyin = @tabkeyin - editline(keyspace) - setkeyin - fin + is keytab + if flags & insmode + indentsel + else + undentsel + fin + if not (flags & selection) + cursoff + autoindent(txtlinbuf=>[cursrow]) + curson + fin + break + is keydetab + undentsel + if not (flags & selection) + cursoff + autoindent(txtlinbuf=>[cursrow]) + curson + fin break is keyctrly - if flags & insmode - flags = flags & ~insmode - curschr = ' ' - else - flags = flags | insmode - curschr = '+' - fin + flags = flags ^ insmode + curschr = flags & insmode ?? '+' :: ' ' break is keyescape if MACHID == $F2 // Apple 3 @@ -1552,11 +1577,27 @@ def cmdmode#0 findtxt return is 'T' // Toggle upper/lower case display - if flags & uppercase - txtlower - else - txtupper - fin + if ^cmdptr + when toupper(^(cmdptr + 1)) + is 'G' // Gutter view + flags = flags ^ gutter + if flags & gutter + scrnwidth = 36 + scrnright = 35 + else + scrnwidth = 40 + scrnright = 39 + fin + break + is 'C' // Lower case chip (Apple ][/][+ only) + if flags & uppercase + txtlower + else + txtupper + fin + break + wend + fin return is 'G' // Goto line # line = strtonum(cmdptr) @@ -1640,7 +1681,7 @@ if ^arg readtxt(@filename, 0) fin curschr = '+' -flags = flags | insmode +flags = flags | insmode | gutter drawscrn(scrntop, scrnleft) curson editmode From 6cabe160c4878d3fc477046a1e6d6409b03eb634 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Mon, 16 Dec 2019 09:03:34 -0800 Subject: [PATCH 041/149] Fix empty line TABbing --- src/toolsrc/ed.pla | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index 633d200..df651e2 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -1147,7 +1147,7 @@ def indentsel#0 firstsel, lastsel = selrange for i = firstsel to lastsel l = ^(txtlinbuf=>[i]) - if l < MAXLNLEN - 2 + if l and l < MAXLNLEN - 2 memcpy(@indentstr + 3, txtlinbuf=>[i] + 1, l) indentstr[0] = l + 2 indentstr[1] = keyspace @@ -1443,7 +1443,11 @@ def editmode#0 fin if not (flags & selection) cursoff - autoindent(txtlinbuf=>[cursrow]) + if not ^(txtlinbuf=>[cursrow]) + curshpos((curscol + 2) & $FE) + else + autoindent(txtlinbuf=>[cursrow]) + fin curson fin break From e1e16ef36d6a5bfc62e4c9f8d33183a9df17d67a Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Mon, 16 Dec 2019 10:05:07 -0800 Subject: [PATCH 042/149] Better blank line detab --- src/toolsrc/ed.pla | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index df651e2..6b5fb86 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -1455,7 +1455,11 @@ def editmode#0 undentsel if not (flags & selection) cursoff - autoindent(txtlinbuf=>[cursrow]) + if not ^(txtlinbuf=>[cursrow]) + curshpos((curscol - 2) & $FFFE) + else + autoindent(txtlinbuf=>[cursrow]) + fin curson fin break From f937e8265e1074ffa4ebd97deda4076baed4e83f Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Mon, 16 Dec 2019 10:09:56 -0800 Subject: [PATCH 043/149] Update images with edit tab/detab fixes --- images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/images/apple/PLASMA2-SYS.PO b/images/apple/PLASMA2-SYS.PO index 6b77b064223b88a743eeb574e17e2150ff717127..4125505b65e99dce5f44b38409f31b8d34f813e9 100755 GIT binary patch delta 2267 zcmZ9~eQZ=!8prYH+)iz61!g*L?cBM2p)DvCBf(hEx+P+Hi3KlsRjh!#HITv*y9PHX zo9W$(@}kHI!hi%}-4#p3EvDL$M$u43iVC725~-HuEp@Hh6=emz^;>qMiGO_V`JHp0 z=bV!})6kXK(3QFC#&qA>p;u~Cs-T(D)Svxc%t5{CS<0&5wr!2m!?i+vGU2|qFvUg_4yksDt#;BK5Qv<3^sX%H#P>oV5k{TCMyBRk` z)bweUL#FOgj$_&Z!`W}z*@km#+)g)~rnudwoK2?vqjG|A`#a?PredS<%!jbP3u&^36xyVP#q91NLcgi z9H+b3&Jb}*W7j+3m_1u9IO(r2sx!sOD7CYMq9-nQedFJw0{zvOR~r9UJyJP$m-M#{ z`>m~au$?Z>%;Nri{FBSXxjnCj)B3w-P4-LOCI2X+!s|cJzN-Hk|KHYmGS5EqTi><) zeZRJG-%I|RjG5lkzwb-xC?B&Yc_6Bar`LLam8D*zJmM{vh2CSb+*=`|y_FK_TP0=Q zYAN!bl#jiqq{-7#<*k#Oy{DzuTQ8=!LGJXDlILw?eUr@Xdq#rZW?9m=MGE>Bbor}0 ze@;!zRXdcbPkxuDwyNgjx|pg`4aws%HEd9G*|IMGWS`We+cU*!PUe{Eb2UEMYpSl{ zGmFLOMxaEDyOB{UMr4Q>l^B1u7!AY3s4o+v89ga4t_~Qjg-Sh^>?ly>t=rYBzC?ad z^w40AJ1QvdA21f

I5?eeLz06`vo2oA}{s+2`+cNj|^+ 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 WjRB1TjRB1TjRB1Tje-B~4E$eI=yh2D literal 0 HcmV?d00001 diff --git a/images/apple/PLASMA2-SYS.PO b/images/apple/PLASMA2-SYS.PO index 31fa6f58fd1027c717ae9f18be0fc0f102cebeac..03da6f5df895c7c12e7fd9af4594152f9f6660ec 100755 GIT binary patch delta 30137 zcmc(|3w%@M{rLZ!lQd1QoTM!+^cHSuDNrKVtb0~A9W+5n}ZD+m!f1ctR@R6>+G zw*eAs4fD3jD2h`DNWt4?5vrglg~D_?H#di%^MX3SEB(EnlceRceYfB5`+vRum3PkP zxnIw7p1UjFH?Mf#ym^SxA16#AL+PrTStZW+>k}&s0+WaG^7;%C9|-NCyit8rVK13d zdf~{T9*d?p5idq-V)ft*Ys6YVtmRcYi%ScqIHUHADI!61rid#B7bZ(orn{k zCX3O7)uf)}HqDM%w$+qnYSL7r;(um9;$IZM5ci4?&dJi728msHNg|S^h?znaYTl5E zm9Db!Jy8*-7Yd^&jM1Z@=ao!ZtVnUyjOw){#OcLC5jQC3T1zdioLD6YKl*oi3HDx< zq4v`YQWs*y;F1dW%%~lnrD%${-t)XmpIk9>{Ir^ysJ+w6Wm?Zm!;lGOpiPI}c!+Ilu z`p-)1P-0i*t}OFJ(s6nv75lQdb0cRjJv$Mne=cIg7WoRC<(qv%naf#L5sjNTeGk6< z_-x;-6qsDf$2pBuzN zlQ*u`HB0b2u20jqnU`KvU`1|86bsD-HqS!qhOfKp%?@wEnuY{#+-74#+=fthy~!c! z4el5r&`c;VZCa4^veMEtJbN&|Q?n;4|7dzBJEN>3+iP%@39lHwLiPC59bVyCl=Y-l z%onx-*OgDki8_OA_-CJ8>B_{8rzLBCjLj=*S50yyh~Xwg=|(#JN7E14K_#Qh~eV5zP}rWcPpNMWO;tbc6ch9zRIai8<*>wX(>$Q_2%uijVyH7O5G!yYIBik8tF&T9c~rAFs_Al0@Faz_ElR)8uq{ge(8Mju zMO8LZF@<;}O{pk#7TRnRDl4YQI1*VI>5}4do3pyiV;es+$yx4kR+2DV-qbuBPHeQ8 zo@tfkd4)Yzi(OR}Nuf8kDCr}J8#&>wbXHa2CaK4+%#QMk8H7=6O-<{Yp3$#=W)?N; zq~iDV_%o$qx|0m6m{wjo+~#t6@~V-TuNnCV|ztgaZ=^9a!(nh z;w+zDR#{O#g(&MW^;A^2s+=C%v?^yQMV2&vTA8aNdzU_cU^&sxYai^leohGKEsFsFXfXFnVbSB}i zbIN#^vr;#VmMo5=uFI-yRb~DuWv=2%Sw~7L%1fMX>QRL(ibz#(7gv=OyKLdlj?6xf zZANjGtd~iHYGMKC_ zn^^Ajm)fe_&XTeTWrX9JnIsc(R{CX`j~VS4DU(-1x$@0Qno;JNM1V3NnwUykiL0W@ z>6&SqQtT<2q-VCCglL4$hzHr}8E%_UT*a?*0)hI=D6S+Ki1e+vMAja?Ac!i}P!>Jy zp~p#qQD0@jg2IGNiVTGKmC4FX?IZ(|#?RE<`SrBvFF*+| z1A1gJ^|y@t!MqD4xKDoZ2b>E(`6Mz^%0Dk*RLOlMv+?o@(l<>W-AZ4y~N-bw5$ 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 I;wxnT51Q6vvj6}9 delta 117802 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 vmsrc/apple/cmdjit.a acme --setpc 8192 -o $(CMDJIT) vmsrc/apple/cmdjitstub.s -$(SOSCMD): vmsrc/apple/soscmd.pla libsrc/jitcore.pla $(PLVM03) $(PLASM) +$(SOSCMD): vmsrc/apple/soscmd.pla $(PLVM03) $(PLASM) ./$(PLASM) -AMOW < vmsrc/apple/soscmd.pla > vmsrc/apple/soscmd.a acme --setpc 4094 -o $(SOSCMD) vmsrc/apple/soscmd.a +$(SOSCMDJIT): vmsrc/apple/soscmdjit.pla libsrc/jitcore.pla $(PLVMJIT03) $(PLASM) + ./$(PLASM) -AMOW < vmsrc/apple/soscmdjit.pla > vmsrc/apple/soscmdjit.a + acme --setpc 4094 -o $(SOSCMDJIT) vmsrc/apple/soscmdjit.a + $(PLVM02): vmsrc/apple/plvm02.s acme -o $(PLVM02) -l vmsrc/apple/plvm02.sym vmsrc/apple/plvm02.s @@ -199,6 +205,11 @@ vmsrc/apple/sossys.a: vmsrc/apple/sossys.pla $(PLASM) $(PLVM03): vmsrc/apple/plvm03.s vmsrc/apple/sossys.a acme -o $(PLVM03) -l vmsrc/apple/plvm03.sym vmsrc/apple/plvm03.s +vmsrc/apple/sossysjit.a: vmsrc/apple/sossysjit.pla $(PLASM) + ./$(PLASM) -AOW < vmsrc/apple/sossysjit.pla > vmsrc/apple/sossysjit.a + +$(PLVMJIT03): vmsrc/apple/plvmjit03.s vmsrc/apple/sossysjit.a + acme -o $(PLVMJIT03) -l vmsrc/apple/plvmjit03.sym vmsrc/apple/plvmjit03.s # # Sample code # diff --git a/src/mkrel b/src/mkrel index 3854133..cb084a0 100755 --- a/src/mkrel +++ b/src/mkrel @@ -50,8 +50,12 @@ cp rel/apple/GRAFIX#FE1000 prodos/sys/GRAFIX.REL rm -rf prodos/fpsos mkdir prodos/fpsos +cp ../sysfiles/SOS.KERNEL#0C0000 prodos/fpsos/SOS.KERNEL.\$0C +cp ../sysfiles/SOS.DRIVER#0C0000 prodos/fpsos/SOS.DRIVER.\$0C cp rel/apple/SOS.INTERP#050000 prodos/fpsos/SOS.INTERP.\$05 cp rel/apple/SOS.CMD#FE1000 prodos/fpsos/SOS.CMD.REL +cp rel/apple/SOS.INTERPJIT#050000 prodos/fpsos/SOS.INTERPJIT.\$05 +cp rel/apple/SOS.CMDJIT#FE1000 prodos/fpsos/SOS.CMDJIT.REL mkdir prodos/fpsos/sys cp rel/apple/SOS#FE1000 prodos/fpsos/sys/SOS.REL @@ -127,24 +131,24 @@ cp samplesrc/fatcat.pla prodos/bld/samples/FATCAT.PLA.TXT cp samplesrc/gfxdemo.pla prodos/bld/samples/GFXDEMO.PLA.TXT cp samplesrc/lz4cat.pla prodos/bld/samples/Z4CAT.PLA.TXT -mkdir prodos/bld/examples -cp samplesrc/examples/ex.1.pla prodos/bld/examples/EX.1.PLA.TXT -cp samplesrc/examples/ex.2.pla prodos/bld/examples/EX.2.PLA.TXT -cp samplesrc/examples/ex.3.pla prodos/bld/examples/EX.3.PLA.TXT -cp samplesrc/examples/ex.4.pla prodos/bld/examples/EX.4.PLA.TXT -cp samplesrc/examples/ex.5.pla prodos/bld/examples/EX.5.PLA.TXT -cp samplesrc/examples/ex.6.pla prodos/bld/examples/EX.6.PLA.TXT -cp samplesrc/examples/ex.7.pla prodos/bld/examples/EX.7.PLA.TXT -cp samplesrc/examples/ex.8.pla prodos/bld/examples/EX.8.PLA.TXT -cp samplesrc/examples/ex.9.pla prodos/bld/examples/EX.9.PLA.TXT -cp samplesrc/examples/ex.10.pla prodos/bld/examples/EX.10.PLA.TXT -cp samplesrc/examples/ex.11.pla prodos/bld/examples/EX.11.PLA.TXT -cp samplesrc/examples/ex.12.pla prodos/bld/examples/EX.12.PLA.TXT -cp samplesrc/examples/ex.13.pla prodos/bld/examples/EX.13.PLA.TXT -cp samplesrc/examples/ex.14.pla prodos/bld/examples/EX.14.PLA.TXT -cp samplesrc/examples/ex.15.pla prodos/bld/examples/EX.15.PLA.TXT -cp samplesrc/examples/ex.16.pla prodos/bld/examples/EX.16.PLA.TXT -cp samplesrc/examples/ex.17.pla prodos/bld/examples/EX.17.PLA.TXT +#mkdir prodos/bld/examples +#cp samplesrc/examples/ex.1.pla prodos/bld/examples/EX.1.PLA.TXT +#cp samplesrc/examples/ex.2.pla prodos/bld/examples/EX.2.PLA.TXT +#cp samplesrc/examples/ex.3.pla prodos/bld/examples/EX.3.PLA.TXT +#cp samplesrc/examples/ex.4.pla prodos/bld/examples/EX.4.PLA.TXT +#cp samplesrc/examples/ex.5.pla prodos/bld/examples/EX.5.PLA.TXT +#cp samplesrc/examples/ex.6.pla prodos/bld/examples/EX.6.PLA.TXT +#cp samplesrc/examples/ex.7.pla prodos/bld/examples/EX.7.PLA.TXT +#cp samplesrc/examples/ex.8.pla prodos/bld/examples/EX.8.PLA.TXT +#cp samplesrc/examples/ex.9.pla prodos/bld/examples/EX.9.PLA.TXT +#cp samplesrc/examples/ex.10.pla prodos/bld/examples/EX.10.PLA.TXT +#cp samplesrc/examples/ex.11.pla prodos/bld/examples/EX.11.PLA.TXT +#cp samplesrc/examples/ex.12.pla prodos/bld/examples/EX.12.PLA.TXT +#cp samplesrc/examples/ex.13.pla prodos/bld/examples/EX.13.PLA.TXT +#cp samplesrc/examples/ex.14.pla prodos/bld/examples/EX.14.PLA.TXT +#cp samplesrc/examples/ex.15.pla prodos/bld/examples/EX.15.PLA.TXT +#cp samplesrc/examples/ex.16.pla prodos/bld/examples/EX.16.PLA.TXT +#cp samplesrc/examples/ex.17.pla prodos/bld/examples/EX.17.PLA.TXT mkdir prodos/bld/inc cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index a0ae85a..f45658f 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -1600,7 +1600,7 @@ def cmdmode#0 word cmdptr, line clrscrn - puts("PLASMA Editor, Version 2.0 Dev\n") + puts("PLASMA Editor, Version 2.0 DP2\n") while not exit puts(@filename) cmdptr = gets($BA) diff --git a/src/toolsrc/plasm.pla b/src/toolsrc/plasm.pla index 675a7b5..d8feba6 100755 --- a/src/toolsrc/plasm.pla +++ b/src/toolsrc/plasm.pla @@ -507,7 +507,7 @@ include "toolsrc/parse.pla" // // Look at command line arguments and compile module // -puts("PLASMA Compiler, Version 2.0 Dev\n") +puts("PLASMA Compiler, Version 2.0 DP2\n") arg = argNext(argFirst) if ^arg and ^(arg + 1) == '-' opt = arg + 2 diff --git a/src/vmsrc/apple/a1cmd.pla b/src/vmsrc/apple/a1cmd.pla index b93c896..0feef38 100755 --- a/src/vmsrc/apple/a1cmd.pla +++ b/src/vmsrc/apple/a1cmd.pla @@ -40,7 +40,7 @@ predef sext(a)#1, divmod(a,b)#2, execmod(modfile)#1 // // Exported CMDSYS table // -word version = $0110 // 01.10 +word version = $0200 // 02.00 word syspath word syscmdln word = @execmod @@ -52,7 +52,7 @@ byte perr, refauto // String pool. // byte autorun[] = "AUTORUN" -byte verstr[] = "\nPLASMA " +byte verstr[] = "\nPLASMA DP2" byte freestr[] = "MEM FREE:$" byte errorstr[] = "ERR:$" byte prompt[] = "PLASMA" diff --git a/src/vmsrc/apple/cmd.pla b/src/vmsrc/apple/cmd.pla index af1df5a..45c50f0 100755 --- a/src/vmsrc/apple/cmd.pla +++ b/src/vmsrc/apple/cmd.pla @@ -1383,7 +1383,7 @@ heap = @lastdef // // Print PLASMA version // -prstr("PLASMA 2.0 Dev 64K\n")//; prbyte(version.1); cout('.'); prbyte(version.0); crout +prstr("PLASMA 2.0 DP2 64K\n")//; prbyte(version.1); cout('.'); prbyte(version.0); crout // // Init symbol table. // diff --git a/src/vmsrc/apple/cmdjit.pla b/src/vmsrc/apple/cmdjit.pla index 0aeba58..6f40545 100755 --- a/src/vmsrc/apple/cmdjit.pla +++ b/src/vmsrc/apple/cmdjit.pla @@ -1460,7 +1460,7 @@ heap = @lastdef // // Print PLASMA version // -prstr("PLASMA 2.0 Dev 128K\n")//; prbyte(version.1); cout('.'); prbyte(version.0); crout +prstr("PLASMA 2.0 DP2 128K\n")//; prbyte(version.1); cout('.'); prbyte(version.0); crout // // Init symbol table. // diff --git a/src/vmsrc/apple/plvm03.s b/src/vmsrc/apple/plvm03.s index db24f80..e0a8d42 100755 --- a/src/vmsrc/apple/plvm03.s +++ b/src/vmsrc/apple/plvm03.s @@ -81,13 +81,9 @@ SEGSTART = $2000 CMP #$B8 BNE - LDA #$00 ; INIT JIT, FRAME & POOL POINTERS - STA JITCOMP - STA JITCOMP+1 - STA JITCODE STA PPL STA IFPL - LDA #$90 ; RESERVE 4K FOR JITCODE - STA JITCODE+1 + LDA #$A0 ; TOP OF RAM FOR FRAME POINER STA PPH STA IFPH LDX #$FF ; INIT STACK POINTER diff --git a/src/vmsrc/apple/plvmjit03.s b/src/vmsrc/apple/plvmjit03.s new file mode 100755 index 0000000..f33a56a --- /dev/null +++ b/src/vmsrc/apple/plvmjit03.s @@ -0,0 +1,1436 @@ +;********************************************************** +;* +;* APPLE /// PLASMA INTERPETER +;* +;* SYSTEM ROUTINES AND LOCATIONS +;* +;********************************************************** +; +; HARDWARE REGISTERS +; +MEMBANK = $FFEF + !SOURCE "vmsrc/plvmzp.inc" +DVSIGN = TMP+2 +DROP = $EF +NEXTOP = $F0 +FETCHOP = NEXTOP+1 +IP = FETCHOP+1 +IPL = IP +IPH = IPL+1 +OPIDX = FETCHOP+6 +OPPAGE = OPIDX+1 +; +; XPAGE ADDRESSES +; +XPAGE = $1600 +DROPX = XPAGE+DROP +IFPX = XPAGE+IFPH +PPX = XPAGE+PPH +IPX = XPAGE+IPH +JMPTMPX = XPAGE+JMPTMP +TMPX = XPAGE+TMPH +SRCX = XPAGE+SRCH +DSTX = XPAGE+DSTH +;* +;* SOS +;* + !MACRO SOS .CMD, .LIST { + BRK + !BYTE .CMD + !WORD .LIST + } +;* +;* INTERPRETER HEADER+INITIALIZATION +;* +SEGSTART = $2000 + *= SEGSTART-$0E + !TEXT "SOS NTRP" + !WORD $0000 + !WORD SEGSTART + !WORD SEGEND-SEGSTART + + LDY #$0F ; INSTALL PAGE 0 FETCHOP ROUTINE + LDA #$00 +- LDX PAGE0,Y + STX DROP,Y + STA DROPX,Y + DEY + BPL - + LDX #$4C ; SET JMPTMP OPCODE + STX JMPTMP + STA TMPX ; CLEAR ALL EXTENDED POINTERS + STA SRCX + STA DSTX + STA PPX + STA IFPX + LDA #VMCORE + STA SRCH + LDY #$00 + STY DSTL + LDA #$A0 + STA DSTH +- LDA (SRC),Y + STA (DST),Y + INY + BNE - + INC SRCH + INC DSTH + LDA DSTH + CMP #$B8 + BNE - + LDA #$00 ; INIT JIT, FRAME & POOL POINTERS + STA JITCOMP + STA JITCOMP+1 + STA JITCODE + STA PPL + STA IFPL + LDA #$90 ; RESERVE 4K FOR JITCODE + STA JITCODE+1 + STA PPH + STA IFPH + LDX #$FF ; INIT STACK POINTER + TXS + LDX #ESTKSZ/2 ; INIT EVAL STACK INDEX + JMP SOSCMD +;PRHEX PHA +; LSR +; LSR +; LSR +; LSR +; CLC +; ADC #'0' +; CMP #':' +; BCC + +; ADC #6 +;+ STA $480 +; PLA +; AND #$0F +; ADC #'0' +; CMP #':' +; BCC + +; ADC #6 +;+ STA $481 ;$880 +;FAIL STA $0480 +; RTS +;SEGREQ !BYTE 4 +; !WORD $2000 +; !WORD $9F00 +; !BYTE $10 +; !BYTE $00 +PAGE0 = * + !PSEUDOPC DROP { +;* +;* INTERP BYTECODE INNER LOOP +;* + INX ; DROP + INY ; NEXTOP + LDA $FFFF,Y ; FETCHOP @ $F1, IP MAPS OVER $FFFF @ $F2 + STA OPIDX + JMP (OPTBL) +} +VMCORE = * + !PSEUDOPC $A000 { +TEMPBUF !FILL $F0 +CMDPARS !WORD 0 ; $A0F0 +JITCOMP !WORD 0 ; $A0F2 +JITCODE !WORD 0 ; $A0F4 +SENTRY !WORD INTERP ; $A0F6 +XENTRY !WORD XINTERP ; $A0F8 +JENTRY !WORD JITINTRP ; $A0FA +;* +;* OPCODE TABLE +;* + !ALIGN 255,0 +OPTBL !WORD ZERO,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E + !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 10 12 14 16 18 1A 1C 1E + !WORD MINUS1,BREQ,BRNE,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E + !WORD DROP,DROP2,DUP,DIVMOD,ADDI,SUBI,ANDI,ORI ; 30 32 34 36 38 3A 3C 3E + !WORD ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E + !WORD BRNCH,SEL,CALL,ICAL,ENTER,LEAVE,RET,CFFB ; 50 52 54 56 58 5A 5C 5E + !WORD LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E + !WORD SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E + !WORD LNOT,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 80 82 84 86 88 8A 8C 8E + !WORD NEG,COMP,BAND,IOR,XOR,SHL,SHR,IDXW ; 90 92 94 96 98 9A 9C 9E + !WORD BRGT,BRLT,INCBRLE,ADDBRLE,DECBRGE,SUBBRGE,BRAND,BROR ; A0 A2 A4 A6 A8 AA AC AE + !WORD ADDLB,ADDLW,ADDAB,ADDAW,IDXLB,IDXLW,IDXAB,IDXAW ; B0 B2 B4 B6 B8 BA BC BE + !WORD NATV ; C0 +;* +;* SYSTEM INTERPRETER ENTRYPOINT +;* +INTERP PLA + CLC + ADC #$01 + STA IPL + PLA + ADC #$00 + STA IPH + LDY #$00 + STY IPX + JMP FETCHOP +;* +;* ENTER INTO USER BYTECODE INTERPRETER +;* +XINTERP PLA + STA TMPL + PLA + STA TMPH +- LDY #$03 + LDA (TMP),Y + STA IPX + DEY + LDA (TMP),Y + STA IPH + DEY + LDA (TMP),Y + STA IPL + DEY + JMP FETCHOP +;* +;* JIT PROFILING ENTRY INTO INTERPRETER +;* +JITINTRP PLA + STA TMPL + PLA + STA TMPH + LDY #$04 + LDA (TMP),Y ; DEC JIT COUNT + SEC + SBC #$01 + STA (TMP),Y + BNE - ; INTERP BYTECODE + LDA JITCOMP ; CALL JIT COMPILER + STA SRCL + LDA JITCOMP+1 + STA SRCH + INY ; LDY #$05 + LDA (SRC),Y + STA IPX + DEY + LDA (SRC),Y + STA IPH + DEY + LDA (SRC),Y + STA IPL + DEX ; ADD PARAMETER TO DEF ENTRY + LDA TMPL + SEC + SBC #$02 ; POINT TO DEF ENTRY + PHA ; AND SAVE IT FOR LATER + STA ESTKL,X + LDA TMPH + SBC #$00 + PHA + STA ESTKH,X + LDY #$00 + JSR FETCHOP ; CALL JIT COMPILER + PLA + STA TMPH + PLA + STA TMPL + JMP (TMP) ; RE-CALL ORIGINAL DEF ENTRY +;* +;* INTERNAL DIVIDE ALGORITHM +;* +_NEG LDA #$00 + SEC + SBC ESTKL,X + STA ESTKL,X + LDA #$00 + SBC ESTKH,X + STA ESTKH,X + RTS +_DIV STY IPY + LDY #$11 ; #BITS+1 + LDA #$00 + STA TMPL ; REMNDRL + STA TMPH ; REMNDRH + STA DVSIGN + LDA ESTKH+1,X + BPL + + INX + JSR _NEG + DEX + LDA #$81 + STA DVSIGN ++ ORA ESTKL+1,X ; DVDNDL + BEQ _DIVEX + LDA ESTKH,X + BPL _DIV1 + JSR _NEG + INC DVSIGN +_DIV1 ASL ESTKL+1,X ; DVDNDL + ROL ESTKH+1,X ; DVDNDH + DEY + BCC _DIV1 +_DIVLP ROL TMPL ; REMNDRL + ROL TMPH ; REMNDRH + LDA TMPL ; REMNDRL + CMP ESTKL,X ; DVSRL + LDA TMPH ; REMNDRH + SBC ESTKH,X ; DVSRH + BCC + + STA TMPH ; REMNDRH + LDA TMPL ; REMNDRL + SBC ESTKL,X ; DVSRL + STA TMPL ; REMNDRL + SEC ++ ROL ESTKL+1,X ; DVDNDL + ROL ESTKH+1,X ; DVDNDH + DEY + BNE _DIVLP +_DIVEX INX + LDY IPY + RTS +;* +;* MUL TOS-1 BY TOS +;* +MUL STY IPY + LDY #$10 + LDA ESTKL+1,X + EOR #$FF + STA TMPL + LDA ESTKH+1,X + EOR #$FF + STA TMPH + LDA #$00 + STA ESTKL+1,X ; PRODL +; STA ESTKH+1,X ; PRODH +_MULLP LSR TMPH ; MULTPLRH + ROR TMPL ; MULTPLRL + BCS + + STA ESTKH+1,X ; PRODH + LDA ESTKL,X ; MULTPLNDL + ADC ESTKL+1,X ; PRODL + STA ESTKL+1,X + LDA ESTKH,X ; MULTPLNDH + ADC ESTKH+1,X ; PRODH ++ ASL ESTKL,X ; MULTPLNDL + ROL ESTKH,X ; MULTPLNDH + DEY + BNE _MULLP + STA ESTKH+1,X ; PRODH + LDY IPY + JMP DROP +;* +;* NEGATE TOS +;* +NEG JSR _NEG + JMP NEXTOP +;* +;* DIV TOS-1 BY TOS +;* +DIV JSR _DIV + LSR DVSIGN ; SIGN(RESULT) = (SIGN(DIVIDEND) + SIGN(DIVISOR)) & 1 + BCS NEG + JMP NEXTOP +;* +;* MOD TOS-1 BY TOS +;* +MOD JSR _DIV + LDA TMPL ; REMNDRL + STA ESTKL,X + LDA TMPH ; REMNDRH + STA ESTKH,X + LDA DVSIGN ; REMAINDER IS SIGN OF DIVIDEND + BMI NEG + JMP NEXTOP +;* +;* DIVMOD TOS-1 BY TOS +;* +DIVMOD JSR _DIV + LSR DVSIGN ; SIGN(RESULT) = (SIGN(DIVIDEND) + SIGN(DIVISOR)) & 1 + BCC + + JSR _NEG ++ DEX + LDA TMPL ; REMNDRL + STA ESTKL,X + LDA TMPH ; REMNDRH + STA ESTKH,X + ASL DVSIGN ; REMAINDER IS SIGN OF DIVIDEND + BMI NEG + JMP NEXTOP +;* +;* INCREMENT TOS +;* +INCR INC ESTKL,X + BNE + + INC ESTKH,X ++ JMP NEXTOP +;* +;* DECREMENT TOS +;* +DECR LDA ESTKL,X + BNE + + DEC ESTKH,X ++ DEC ESTKL,X + JMP NEXTOP +;* +;* ADD TOS TO TOS-1 +;* +ADD LDA ESTKL,X + CLC + ADC ESTKL+1,X + STA ESTKL+1,X + LDA ESTKH,X + ADC ESTKH+1,X + STA ESTKH+1,X + JMP DROP +;* +;* SUB TOS FROM TOS-1 +;* +SUB LDA ESTKL+1,X + SEC + SBC ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + SBC ESTKH,X + STA ESTKH+1,X + JMP DROP +; +;* +;* SHIFT TOS LEFT BY 1, ADD TO TOS-1 +;* +IDXW LDA ESTKL,X + ASL + ROL ESTKH,X + CLC + ADC ESTKL+1,X + STA ESTKL+1,X + LDA ESTKH,X + ADC ESTKH+1,X + STA ESTKH+1,X + JMP DROP +;* +;* BITWISE COMPLIMENT TOS +;* +COMP LDA #$FF + EOR ESTKL,X + STA ESTKL,X + LDA #$FF + EOR ESTKH,X + STA ESTKH,X + JMP NEXTOP +;* +;* BITWISE AND TOS TO TOS-1 +;* +BAND LDA ESTKL+1,X + AND ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + AND ESTKH,X + STA ESTKH+1,X + JMP DROP +;* +;* INCLUSIVE OR TOS TO TOS-1 +;* +IOR LDA ESTKL+1,X + ORA ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + ORA ESTKH,X + STA ESTKH+1,X + JMP DROP +;* +;* EXLUSIVE OR TOS TO TOS-1 +;* +XOR LDA ESTKL+1,X + EOR ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + EOR ESTKH,X + STA ESTKH+1,X + JMP DROP +;* +;* SHIFT TOS-1 LEFT BY TOS +;* +SHL STY IPY + LDA ESTKL,X + CMP #$08 + BCC + + LDY ESTKL+1,X + STY ESTKH+1,X + LDY #$00 + STY ESTKL+1,X + SBC #$08 ++ TAY + BEQ + + LDA ESTKL+1,X +- ASL + ROL ESTKH+1,X + DEY + BNE - + STA ESTKL+1,X ++ LDY IPY + JMP DROP +;* +;* SHIFT TOS-1 RIGHT BY TOS +;* +SHR STY IPY + LDA ESTKL,X + CMP #$08 + BCC ++ + LDY ESTKH+1,X + STY ESTKL+1,X + CPY #$80 + LDY #$00 + BCC + + DEY ++ STY ESTKH+1,X + SEC + SBC #$08 +++ TAY + BEQ + + LDA ESTKH+1,X +- CMP #$80 + ROR + ROR ESTKL+1,X + DEY + BNE - + STA ESTKH+1,X ++ LDY IPY + JMP DROP +;* +;* DUPLICATE TOS +;* +DUP DEX + LDA ESTKL+1,X + STA ESTKL,X + LDA ESTKH+1,X + STA ESTKH,X + JMP NEXTOP +;* +;* ADD IMMEDIATE TO TOS +;* +ADDI INY ;+INC_IP + LDA (IP),Y + CLC + ADC ESTKL,X + STA ESTKL,X + BCC + + INC ESTKH,X ++ JMP NEXTOP +;* +;* SUB IMMEDIATE FROM TOS +;* +SUBI INY ;+INC_IP + LDA ESTKL,X + SEC + SBC (IP),Y + STA ESTKL,X + BCS + + DEC ESTKH,X ++ JMP NEXTOP +;* +;* AND IMMEDIATE TO TOS +;* +ANDI INY ;+INC_IP + LDA (IP),Y + AND ESTKL,X + STA ESTKL,X + LDA #$00 + STA ESTKH,X + JMP NEXTOP +;* +;* IOR IMMEDIATE TO TOS +;* +ORI INY ;+INC_IP + LDA (IP),Y + ORA ESTKL,X + STA ESTKL,X + JMP NEXTOP +;* +;* LOGICAL NOT +;* +LNOT LDA ESTKL,X + ORA ESTKH,X + BEQ + + LDA #$00 + STA ESTKL,X + STA ESTKH,X + JMP NEXTOP +;* +;* CONSTANT -1, ZERO, NYBBLE, BYTE, $FF BYTE, WORD (BELOW) +;* +MINUS1 DEX ++ LDA #$FF + STA ESTKL,X + STA ESTKH,X + JMP NEXTOP +ZERO DEX + STA ESTKL,X + STA ESTKH,X + JMP NEXTOP +CN DEX + LSR ; A = CONST * 2 + STA ESTKL,X + LDA #$00 + STA ESTKH,X + JMP NEXTOP +CFFB LDA #$FF + DEX + STA ESTKH,X + INY ;+INC_IP + LDA (IP),Y + STA ESTKL,X + JMP NEXTOP +CB LDA #$00 + DEX + STA ESTKH,X + INY ;+INC_IP + LDA (IP),Y + STA ESTKL,X + JMP NEXTOP +;* +;* LOAD ADDRESS & LOAD CONSTANT WORD (SAME THING, WITH OR WITHOUT FIXUP) +;* +- TYA ; RENORMALIZE IP + CLC + ADC IPL + STA IPL + BCC + + INC IPH ++ LDY #$FF +LA INY ;+INC_IP + BMI - + DEX + LDA (IP),Y + STA ESTKL,X + INY + LDA (IP),Y + STA ESTKH,X + JMP NEXTOP +CW DEX + INY ;+INC_IP + LDA (IP),Y + STA ESTKL,X + INY + LDA (IP),Y + STA ESTKH,X + JMP NEXTOP +;* +;* CONSTANT STRING +;* +CS DEX + ;INY ;+INC_IP + TYA ; NORMALIZE IP + SEC + ADC IPL + STA IPL + LDA #$00 + TAY + ADC IPH + STA IPH + LDA PPL ; SCAN POOL FOR STRING ALREADY THERE + STA TMPL + LDA PPH + STA TMPH +_CMPPS ;LDA TMPH ; CHECK FOR END OF POOL + CMP IFPH + BCC _CMPS ; CHECK FOR MATCHING STRING + BNE _CPYS ; BEYOND END OF POOL, COPY STRING OVER + LDA TMPL + CMP IFPL + BCS _CPYS ; AT OR BEYOND END OF POOL, COPY STRING OVER +_CMPS LDA (TMP),Y ; COMPARE STRINGS FROM AUX MEM TO STRINGS IN MAIN MEM + CMP (IP),Y ; COMPARE STRING LENGTHS + BNE _CNXTS1 + TAY +_CMPCS LDA (TMP),Y ; COMPARE STRING CHARS FROM END + CMP (IP),Y + BNE _CNXTS + DEY + BNE _CMPCS + LDA TMPL ; MATCH - SAVE EXISTING ADDR ON ESTK AND MOVE ON + STA ESTKL,X + LDA TMPH + STA ESTKH,X + BNE _CEXS +_CNXTS LDY #$00 + LDA (TMP),Y +_CNXTS1 SEC + ADC TMPL + STA TMPL + LDA #$00 + ADC TMPH + STA TMPH + BNE _CMPPS +_CPYS LDA (IP),Y ; COPY STRING FROM AUX TO MAIN MEM POOL + TAY ; MAKE ROOM IN POOL AND SAVE ADDR ON ESTK + EOR #$FF + CLC + ADC PPL + STA PPL + STA ESTKL,X + LDA #$FF + ADC PPH + STA PPH + STA ESTKH,X ; COPY STRING FROM AUX MEM BYTECODE TO MAIN MEM POOL +_CPYS1 LDA (IP),Y ; ALTRD IS ON, NO NEED TO CHANGE IT HERE + STA (PP),Y ; ALTWR IS OFF, NO NEED TO CHANGE IT HERE + DEY + CPY #$FF + BNE _CPYS1 + INY +_CEXS LDA (IP),Y ; SKIP TO NEXT OP ADDR AFTER STRING + TAY + JMP NEXTOP +;* +;* LOAD VALUE FROM ADDRESS TAG +;* +LB LDA ESTKL,X + STA ESTKH-1,X + LDA (ESTKH-1,X) + STA ESTKL,X + LDA #$00 + STA ESTKH,X + JMP NEXTOP +LW LDA ESTKL,X + STA ESTKH-1,X + LDA (ESTKH-1,X) + STA ESTKL,X + INC ESTKH-1,X + BNE + + INC ESTKH,X ++ LDA (ESTKH-1,X) + STA ESTKH,X + JMP NEXTOP +;* +;* LOAD ADDRESS OF LOCAL FRAME OFFSET +;* +- TYA ; RENORMALIZE IP + CLC + ADC IPL + STA IPL + BCC + + INC IPH ++ LDY #$FF +LLA INY ;+INC_IP + BMI - + LDA (IP),Y + DEX + CLC + ADC IFPL + STA ESTKL,X + LDA #$00 + ADC IFPH + STA ESTKH,X + JMP NEXTOP +;* +;* LOAD VALUE FROM LOCAL FRAME OFFSET +;* +LLB INY ;+INC_IP + LDA (IP),Y + STY IPY + TAY + DEX + LDA (IFP),Y + STA ESTKL,X + LDA #$00 + STA ESTKH,X + LDY IPY + JMP NEXTOP +LLW INY ;+INC_IP + LDA (IP),Y + STY IPY + TAY + DEX + LDA (IFP),Y + STA ESTKL,X + INY + LDA (IFP),Y + STA ESTKH,X + LDY IPY + JMP NEXTOP +;* +;* ADD VALUE FROM LOCAL FRAME OFFSET +;* +ADDLB INY ;+INC_IP + LDA (IP),Y + STY IPY + TAY + LDA (IFP),Y + CLC + ADC ESTKL,X + STA ESTKL,X + BCC + + INC ESTKH,X ++ LDY IPY + JMP NEXTOP +ADDLW INY ;+INC_IP + LDA (IP),Y + STY IPY + TAY + LDA (IFP),Y + CLC + ADC ESTKL,X + STA ESTKL,X + INY + LDA (IFP),Y + ADC ESTKH,X + STA ESTKH,X + LDY IPY + JMP NEXTOP +;* +;* INDEX VALUE FROM LOCAL FRAME OFFSET +;* +IDXLB INY ;+INC_IP + LDA (IP),Y + STY IPY + TAY + LDA (IFP),Y + LDY #$00 + ASL + BCC + + INY + CLC ++ ADC ESTKL,X + STA ESTKL,X + TYA + ADC ESTKH,X + STA ESTKH,X + LDY IPY + JMP NEXTOP +IDXLW INY ;+INC_IP + LDA (IP),Y + STY IPY + TAY + LDA (IFP),Y + ASL + STA TMPL + INY + LDA (IFP),Y + ROL + STA TMPH + LDA TMPL + CLC + ADC ESTKL,X + STA ESTKL,X + LDA TMPH + ADC ESTKH,X + STA ESTKH,X + LDY IPY + JMP NEXTOP +;* +;* LOAD VALUE FROM ABSOLUTE ADDRESS +;* +LAB INY ;+INC_IP + LDA (IP),Y + STA ESTKH-2,X + INY ;+INC_IP + LDA (IP),Y + STA ESTKH-1,X + LDA (ESTKH-2,X) + DEX + STA ESTKL,X + LDA #$00 + STA ESTKH,X + JMP NEXTOP +LAW INY ;+INC_IP + LDA (IP),Y + STA TMPL + INY ;+INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA (TMP),Y + DEX + STA ESTKL,X + INY + LDA (TMP),Y + STA ESTKH,X + LDY IPY + JMP NEXTOP +;* +;* ADD VALUE FROM ABSOLUTE ADDRESS +;* +ADDAB INY ;+INC_IP + LDA (IP),Y + STA ESTKH-2,X + INY ;+INC_IP + LDA (IP),Y + STA ESTKH-1,X + LDA (ESTKH-2,X) + CLC + ADC ESTKL,X + STA ESTKL,X + BCC + + INC ESTKH,X ++ JMP NEXTOP +ADDAW INY ;+INC_IP + LDA (IP),Y + STA SRCL + INY ;+INC_IP + LDA (IP),Y + STA SRCH + STY IPY + LDY #$00 + LDA (SRC),Y + CLC + ADC ESTKL,X + STA ESTKL,X + INY + LDA (SRC),Y + ADC ESTKH,X + STA ESTKH,X + LDY IPY + JMP NEXTOP +;* +;* INDEX VALUE FROM ABSOLUTE ADDRESS +;* +IDXAB INY ;+INC_IP + LDA (IP),Y + STA ESTKH-2,X + INY ;+INC_IP + LDA (IP),Y + STA ESTKH-1,X + LDA (ESTKH-2,X) + STY IPY + LDY #$00 + ASL + BCC + + INY + CLC ++ ADC ESTKL,X + STA ESTKL,X + TYA + ADC ESTKH,X + STA ESTKH,X + LDY IPY + JMP NEXTOP +IDXAW INY ;+INC_IP + LDA (IP),Y + STA SRCL + INY ;+INC_IP + LDA (IP),Y + STA SRCH + STY IPY + LDY #$00 + LDA (SRC),Y + ASL + STA TMPL + INY + LDA (SRC),Y + ROL + STA TMPH + LDA TMPL + CLC + ADC ESTKL,X + STA ESTKL,X + LDA TMPH + ADC ESTKH,X + STA ESTKH,X + LDY IPY + JMP NEXTOP +;* +;* STORE VALUE TO ADDRESS +;* +SB LDA ESTKL,X + STA ESTKH-1,X + LDA ESTKL+1,X + STA (ESTKH-1,X) + INX + JMP DROP +SW LDA ESTKL,X + STA ESTKH-1,X + LDA ESTKL+1,X + STA (ESTKH-1,X) + LDA ESTKH+1,X + INC ESTKH-1,X + BNE + + INC ESTKH,X ++ STA (ESTKH-1,X) +;* +;* DROP TOS, TOS-1 +;* +DROP2 INX + JMP DROP +;* +;* STORE VALUE TO LOCAL FRAME OFFSET +;* +SLB INY ;+INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + LDY IPY + BMI FIXDROP + JMP DROP +SLW INY ;+INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + INY + LDA ESTKH,X + STA (IFP),Y + LDY IPY + BMI FIXDROP + JMP DROP +FIXDROP TYA + LDY #$00 + CLC + ADC IPL + STA IPL + BCC + + INC IPH ++ JMP DROP +;* +;* STORE VALUE TO LOCAL FRAME OFFSET WITHOUT POPPING STACK +;* +DLB INY ;+INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + LDA #$00 + STA ESTKH,X + LDY IPY + JMP NEXTOP +DLW INY ;+INC_IP + LDA (IP),Y + STY IPY + TAY + LDA ESTKL,X + STA (IFP),Y + INY + LDA ESTKH,X + STA (IFP),Y + LDY IPY + JMP NEXTOP +;* +;* STORE VALUE TO ABSOLUTE ADDRESS +;* +- TYA ; RENORMALIZE IP + CLC + ADC IPL + STA IPL + BCC + + INC IPH ++ LDY #$FF +SAB INY ;+INC_IP + BMI - + LDA (IP),Y + STA ESTKH-2,X + INY ;+INC_IP + LDA (IP),Y + STA ESTKH-1,X + LDA ESTKL,X + STA (ESTKH-2,X) + JMP DROP +SAW INY ;+INC_IP + LDA (IP),Y + STA TMPL + INY ;+INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL,X + STA (TMP),Y + INY + LDA ESTKH,X + STA (TMP),Y + LDY IPY + BMI FIXDROP + JMP DROP +;* +;* STORE VALUE TO ABSOLUTE ADDRESS WITHOUT POPPING STACK +;* +DAB INY ;+INC_IP + LDA (IP),Y + STA ESTKH-2,X + INY ;+INC_IP + LDA (IP),Y + STA ESTKH-1,X + LDA ESTKL,X + STA (ESTKH-2,X) + LDA #$00 + STA ESTKH,X + JMP NEXTOP +DAW INY ;+INC_IP + LDA (IP),Y + STA TMPL + INY ;+INC_IP + LDA (IP),Y + STA TMPH + STY IPY + LDY #$00 + LDA ESTKL,X + STA (TMP),Y + INY + LDA ESTKH,X + STA (TMP),Y + LDY IPY + JMP NEXTOP +;* +;* COMPARES +;* +ISEQ LDA ESTKL,X + CMP ESTKL+1,X + BNE ISFLS + LDA ESTKH,X + CMP ESTKH+1,X + BNE ISFLS +ISTRU LDA #$FF + STA ESTKL+1,X + STA ESTKH+1,X + JMP DROP +ISNE LDA ESTKL,X + CMP ESTKL+1,X + BNE ISTRU + LDA ESTKH,X + CMP ESTKH+1,X + BNE ISTRU +ISFLS LDA #$00 + STA ESTKL+1,X + STA ESTKH+1,X + JMP DROP +ISGE LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + BVS + + BPL ISTRU + BMI ISFLS ++ +- BPL ISFLS + BMI ISTRU +ISLE LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + BVS - + BPL ISTRU + BMI ISFLS +ISGT LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + BVS + + BMI ISTRU + BPL ISFLS ++ +- BMI ISFLS + BPL ISTRU +ISLT LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + BVS - + BMI ISTRU + BPL ISFLS +;* +;* BRANCHES +;* +SEL INX + TYA ; FLATTEN IP + SEC + ADC IPL + STA TMPL + LDA #$00 + TAY + ADC IPH + STA TMPH ; ADD CASEBLOCK OFFSET + LDA IPX ; COPY XBYTE FROM IP + STA TMPX + LDA (TMP),Y + ;CLC ; BETTER NOT CARRY OUT OF IP+Y + ADC TMPL + STA IPL + INY + LDA (TMP),Y + ADC TMPH + STA IPH + DEY + STY TMPX ; CLEAR TMPX + LDA (IP),Y + STA TMPL ; CASE COUNT + INC IPL + BNE CASELP + INC IPH +CASELP LDA ESTKL-1,X + CMP (IP),Y + BEQ + + LDA ESTKH-1,X + INY + SBC (IP),Y + BMI CASEEND +- INY + INY + DEC TMPL + BEQ FIXNEXT + INY + BNE CASELP + INC IPH + BNE CASELP ++ LDA ESTKH-1,X + INY + SBC (IP),Y + BEQ BRNCH + BPL - +CASEEND LDA #$00 + STA TMPH + DEC TMPL + LDA TMPL + ASL ; SKIP REMAINING CASES + ROL TMPH + ASL + ROL TMPH +; CLC + ADC IPL + STA IPL + LDA TMPH + ADC IPH + STA IPH + INY + INY +FIXNEXT TYA + LDY #$00 + SEC + ADC IPL + STA IPL + BCC + + INC IPH ++ JMP FETCHOP +BRAND LDA ESTKL,X + ORA ESTKH,X + BEQ BRNCH + INX ; DROP LEFT HALF OF AND + BNE NOBRNCH +BROR LDA ESTKL,X + ORA ESTKH,X + BNE BRNCH + INX ; DROP LEFT HALF OF OR + BNE NOBRNCH +BREQ INX + INX + LDA ESTKL-2,X + CMP ESTKL-1,X + BNE NOBRNCH + LDA ESTKH-2,X + CMP ESTKH-1,X + BEQ BRNCH + BNE NOBRNCH +BRNE INX + INX + LDA ESTKL-2,X + CMP ESTKL-1,X + BNE BRNCH + LDA ESTKH-2,X + CMP ESTKH-1,X + BNE BRNCH + BEQ NOBRNCH +BRTRU INX + LDA ESTKH-1,X + ORA ESTKL-1,X + BNE BRNCH +NOBRNCH INY ;+INC_IP + INY ;+INC_IP + BMI FIXNEXT + JMP NEXTOP +BRFLS INX + LDA ESTKH-1,X + ORA ESTKL-1,X + BNE NOBRNCH +BRNCH TYA ; FLATTEN IP + SEC + ADC IPL + STA TMPL + LDA #$00 + TAY + ADC IPH + STA TMPH ; ADD BRANCH OFFSET + LDA IPX ; COPY XBYTE FROM IP + STA TMPX + LDA (TMP),Y + ;CLC ; BETTER NOT CARRY OUT OF IP+Y + ADC TMPL + STA IPL + INY + LDA (TMP),Y + ADC TMPH + STA IPH + DEY + STY TMPX ; CLEAR TMPX + JMP FETCHOP +;* +;* FOR LOOPS PUT TERMINAL VALUE AT ESTK+1 AND CURRENT COUNT ON ESTK +;* +BRGT LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + BVS ++ +- BPL NOBRNCH + BMI BRNCH +BRLT LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + BVS ++ + BPL NOBRNCH + BMI BRNCH +DECBRGE DEC ESTKL,X + LDA ESTKL,X + CMP #$FF + BNE + + DEC ESTKH,X +_BRGE LDA ESTKL,X ++ CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + BVS - + BPL BRNCH + BMI NOBRNCH +INCBRLE INC ESTKL,X + BNE _BRLE + INC ESTKH,X +_BRLE LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + BVS - +++ BPL BRNCH + BMI NOBRNCH +SUBBRGE LDA ESTKL+1,X + SEC + SBC ESTKL,X + STA ESTKL+1,X + LDA ESTKH+1,X + SBC ESTKH,X + STA ESTKH+1,X + INX + BNE _BRGE +ADDBRLE LDA ESTKL,X + CLC + ADC ESTKL+1,X + STA ESTKL+1,X + LDA ESTKH,X + ADC ESTKH+1,X + STA ESTKH+1,X + INX + BNE _BRLE +;* +;* INDIRECT CALL TO ADDRESS (NATIVE CODE) +;* +ICAL LDA ESTKL,X + STA ICALADR+1 + LDA ESTKH,X + STA ICALADR+2 + INX + TYA + SEC + ADC IPL + PHA + LDA IPH + ADC #$00 + PHA + LDA IPX + PHA +ICALADR JSR $FFFF + PLA + STA IPX + PLA + STA IPH + PLA + STA IPL + LDY #$00 + JMP FETCHOP +;* +;* CALL INTO ABSOLUTE ADDRESS (NATIVE CODE) +;* +CALL INY ;+INC_IP + LDA (IP),Y + STA CALLADR+1 + INY ;+INC_IP + LDA (IP),Y + STA CALLADR+2 +_CALL TYA + SEC + ADC IPL + PHA + LDA IPH + ADC #$00 + PHA + LDA IPX + PHA +CALLADR JSR $FFFF + PLA + STA IPX + PLA + STA IPH + PLA + STA IPL + LDY #$00 + JMP FETCHOP +;* +;* ENTER FUNCTION WITH FRAME SIZE AND PARAM COUNT +;* +ENTER LDA IFPH + PHA ; SAVE ON STACK FOR LEAVE + LDA IFPL + PHA + INY + LDA (IP),Y + EOR #$FF + SEC + ADC PPL + STA PPL + STA IFPL + LDA #$FF + ADC PPH + STA PPH + STA IFPH + INY + LDA (IP),Y + BEQ + + ASL + TAY +- LDA ESTKH,X + DEY + STA (IFP),Y + LDA ESTKL,X + INX + DEY + STA (IFP),Y + BNE - ++ LDY #$03 + JMP FETCHOP +;* +;* LEAVE FUNCTION +;* +LEAVE INY ;+INC_IP + LDA (IP),Y + CLC + ADC IFPL + STA PPL + LDA #$00 + ADC IFPH + STA PPH + PLA ; RESTORE PREVIOUS FRAME + STA IFPL + PLA + STA IFPH +RET RTS +;* +;* RETURN TO NATIVE CODE +;* +NATV TYA ; FLATTEN IP + SEC + ADC IPL + STA IPL + BCS + + JMP (IP) ++ INC IPH + JMP (IP) +SOSCMD = * + !SOURCE "vmsrc/apple/sossysjit.a" + +} +SEGEND = * diff --git a/src/vmsrc/apple/soscmd.pla b/src/vmsrc/apple/soscmd.pla index eef4d83..e9f3ca2 100755 --- a/src/vmsrc/apple/soscmd.pla +++ b/src/vmsrc/apple/soscmd.pla @@ -17,14 +17,9 @@ end // // Private addresses // -const jitcbuf = $9000 -const codemax = $A000 const cmdparser = $A0F0 -const jitcomp = $A0F2 -const jitcodeptr = $A0F4 const sinterp = $A0F6 const xinterp = $A0F8 -const jitinterp = $A0FA const estkh8 = $C000 const estkh = $00C0 const estkl8 = $D000 @@ -36,49 +31,6 @@ const tmpl8 = $E700 const tmph8 = $E800 word directentry, indirectentry // -// COPY FROM EXT MEM TO MAIN MEM. -// -asm defcpy(dst, defentry)#0 - !SOURCE "vmsrc/plvmzp.inc" -XPAGE = $1600 -SRCX = XPAGE+SRCH -DSTX = XPAGE+DSTH - - LDA ESTKL+1,X - STA DSTL - LDA ESTKH+1,X - STA DSTH - LDA ESTKL,X - STA TMPL - LDA ESTKH,X - STA TMPH - LDY #$05 - LDA (TMP),Y - STA SRCX - DEY - LDA (TMP),Y - STA SRCH - DEY - LDA (TMP),Y - STA SRCL - LDY #$07 - LDA (TMP),Y - TAY - DEY - BEQ + -- LDA (SRC),Y - STA (DST),Y - DEY - BNE - -+ LDA (SRC),Y - STA (DST),Y - STY SRCX - INX - INX - RTS -end -include "libsrc/jitcore.pla" -// // SOS routines // FILE I/O // @@ -291,8 +243,7 @@ def shell#1 volumes break is '+' - *jitcodeptr = jitcbuf - //cmdsys:modexec(striptrail(cmdptr)) + //cmdsys:modexec(striptrail(cmdptr)) return striptrail(cmdptr) //cmdsys:syswrite(cmdsys.refcons, @textmode, 3) break @@ -317,13 +268,7 @@ end // // Save pointer to command line handler // -*cmdparser = @shell -// -// Install JIT compiler -// +*cmdparser = @shell directentry = *sinterp indirectentry = *xinterp -*jitcomp = @compiler -cmdsys.jitcount = 32 -cmdsys.jitsize = 96 done diff --git a/src/vmsrc/apple/soscmdjit.pla b/src/vmsrc/apple/soscmdjit.pla new file mode 100755 index 0000000..eef4d83 --- /dev/null +++ b/src/vmsrc/apple/soscmdjit.pla @@ -0,0 +1,329 @@ +include "inc/cmdsys.plh" +sysflags nojitc // Keep JITC from compiling itself +// +// JIT compiler values +// +// +// Indirect interpreter DEFinition entrypoint +// +struc t_defentry + byte interpjsr + word interpaddr + word bytecodeaddr + byte bytecodexbyte + byte callcount + byte bytecodesize +end +// +// Private addresses +// +const jitcbuf = $9000 +const codemax = $A000 +const cmdparser = $A0F0 +const jitcomp = $A0F2 +const jitcodeptr = $A0F4 +const sinterp = $A0F6 +const xinterp = $A0F8 +const jitinterp = $A0FA +const estkh8 = $C000 +const estkh = $00C0 +const estkl8 = $D000 +const estkl = $00D0 +const ifpl8 = $E000 +const ifph8 = $E100 +const jmptmp = $00E6 +const tmpl8 = $E700 +const tmph8 = $E800 +word directentry, indirectentry +// +// COPY FROM EXT MEM TO MAIN MEM. +// +asm defcpy(dst, defentry)#0 + !SOURCE "vmsrc/plvmzp.inc" +XPAGE = $1600 +SRCX = XPAGE+SRCH +DSTX = XPAGE+DSTH + + LDA ESTKL+1,X + STA DSTL + LDA ESTKH+1,X + STA DSTH + LDA ESTKL,X + STA TMPL + LDA ESTKH,X + STA TMPH + LDY #$05 + LDA (TMP),Y + STA SRCX + DEY + LDA (TMP),Y + STA SRCH + DEY + LDA (TMP),Y + STA SRCL + LDY #$07 + LDA (TMP),Y + TAY + DEY + BEQ + +- LDA (SRC),Y + STA (DST),Y + DEY + BNE - ++ LDA (SRC),Y + STA (DST),Y + STY SRCX + INX + INX + RTS +end +include "libsrc/jitcore.pla" +// +// SOS routines +// FILE I/O +// +def getpfx(path)#1 + byte params[4] + + ^path = 0 + params.0 = 2 + params:1 = path + params.3 = 128 + syscall($C7, @params) + return path +end +def setpfx(path)#1 + byte params[6] + byte fileinfo[2] + + params.0 = 3 + params:1 = path + params:3 = @fileinfo + params.5 = 2 + if not syscall($C4, @params) and (fileinfo.1 == $00 or fileinfo.1 == $0F) // Make sure it's a directory + params.0 = 1 + params:1 = path + syscall($C6, @params) + else + getpfx(path) // Get current path + fin + return path +end +def dev_info(devnum, name, list, listlen)#1 + byte params[7] + + params.0 = 4 + params.1 = devnum + params:2 = name + params:4 = list + params.6 = listlen + return syscall($85, @params) +end +def volume(devname, volname)#1 + byte params[9] + + params.0 = 4 + params:1 = devname + params:3 = volname + params:5 = 0 + params:7 = 0 + return syscall($C5, @params) +end +// +// Command mode +// +def volumes()#0 + byte info[11] + byte devname[17] + byte volname[17] + byte i + + for i = $01 to $18 + if dev_info(i, @devname, @info, 11) == 0 + puts(@devname) + if volume(@devname, @volname) == 0 + puts(" => /") + puts(@volname) + putc('/') + fin + putln + fin + next +end +def catalog(path)#0 + byte refnum + byte firstblk + byte entrylen, entriesblk + byte i, type, len + word entry, filecnt, catptr + + if !^path + getpfx(path) + fin + refnum = cmdsys:sysopen(path) + if not refnum + return + fin + catptr = heapmark + firstblk = 1 + repeat + if cmdsys:sysread(refnum, catptr, 512) == 512 + entry = catptr + 4 + if firstblk + entrylen = catptr->$23 + entriesblk = catptr->$24 + filecnt = catptr=>$25 + entry = entry + entrylen + fin + for i = firstblk to entriesblk + if ^entry + ^entry = ^entry & $0F + puts(entry) + type = ' ' + when entry->$10 + is $0F // Is it a directory? + type = '/' + break + is $FF // SYSTEM file + type = '-' + break + is $FE // REL file + type = '+' + wend + putc(type) + for len = ^entry to 18 + putc(' ') + next + filecnt-- + fin + entry = entry + entrylen + next + firstblk = 0 + else + filecnt = 0 + fin + until filecnt == 0 + cmdsys:sysclose(refnum) + putln() +end +def stripchars(strptr)#1 + while ^strptr and ^(strptr + 1) > ' ' + memcpy(strptr + 1, strptr + 2, ^strptr) + ^strptr-- + loop + return ^strptr +end +def stripspaces(strptr)#0 + while ^strptr and ^(strptr + ^strptr) <= ' ' + ^strptr-- + loop + while ^strptr and ^(strptr + 1) <= ' ' + memcpy(strptr + 1, strptr + 2, ^strptr) + ^strptr-- + loop +end +def striptrail(strptr)#1 + byte i + + for i = 1 to ^strptr + if ^(strptr + i) <= ' ' + ^strptr = i - 1 + break + fin + next + return strptr +end +def parsecmd(strptr)#1 + byte cmd + + cmd = 0 + stripspaces(strptr) + if ^strptr + cmd = ^(strptr + 1) + memcpy(strptr + 1, strptr + 2, ^strptr) + ^strptr-- + fin + stripspaces(strptr) + return cmd +end +// +// Command line handler +// +def shell#1 + byte textmode[3] + byte prefix[64] + byte err[] + word cmdptr + // + // Copy AUTORUN commmand line + // + cmdptr = strcpy(heapmark, cmdsys:cmdline) + // + // Handle commands. + // + repeat + if ^cmdptr + when toupper(parsecmd(cmdptr)) + is 'C' + catalog(cmdptr) + break + is 'P' + if ^cmdptr and ^(cmdptr + 1) <> '/' + strcat(@prefix, cmdptr) + else + strcpy(@prefix, cmdptr) + fin + setpfx(@prefix) + break + is '/' + repeat + prefix-- + until prefix[prefix] == '/' + if prefix > 1 + setpfx(@prefix) + fin + break + is 'S' + setpfx(cmdptr) + strcat(getpfx(cmdsys:syspath), "SYS/")) + break + is 'V' + volumes + break + is '+' + *jitcodeptr = jitcbuf + //cmdsys:modexec(striptrail(cmdptr)) + return striptrail(cmdptr) + //cmdsys:syswrite(cmdsys.refcons, @textmode, 3) + break + otherwise + puts("?\n") + wend + if cmdsys.syserr + err = cmdsys.syserr + puts("ERR:$") + putb(err) + else + puts("OK") + fin + putln + fin + puts(getpfx(@prefix)) + cmdptr = gets($BA) + strcpy(cmdsys:cmdline, cmdptr) + until 0 + return 0 +end +// +// Save pointer to command line handler +// +*cmdparser = @shell +// +// Install JIT compiler +// +directentry = *sinterp +indirectentry = *xinterp +*jitcomp = @compiler +cmdsys.jitcount = 32 +cmdsys.jitsize = 96 +done diff --git a/src/vmsrc/apple/sossys.pla b/src/vmsrc/apple/sossys.pla index af01f8f..267121f 100755 --- a/src/vmsrc/apple/sossys.pla +++ b/src/vmsrc/apple/sossys.pla @@ -23,7 +23,6 @@ const modinitkeep = $4000 const instr = $A020 const cmdparser = $A0F0 const xinterp = $A0F8 -const jitinterp = $A0FA // // Indirect interpreter DEFinition entrypoint // @@ -32,17 +31,8 @@ struc t_defentry word interpaddr word bytecodeaddr byte bytecodexbyte - byte callcount - byte bytecodesize end // -// JIT compiler values -// -const jitcbuf = $9000 -const jitcomp = $A0F2 -const jitcodeptr = $A0F4 -const codemax = $A000 -// // Pedefined functions. // predef syscall(cmd,params)#1, call(addr,areg,xreg,yreg,status)#1 @@ -1027,19 +1017,10 @@ def lookupextern(esd, index)#1 fin return 0 end -def adddef(isfirst, ext, addr, deflast)#1 +def adddef(ext, addr, deflast)#1 word preventry, defentry, defsize defentry = *deflast *deflast = defentry + t_defentry - if not isfirst - preventry = defentry - t_defentry - defsize = addr - preventry=>bytecodeaddr - if defsize <= jitsize - preventry=>interpaddr = *jitinterp // JSR JITINTRP - preventry->callcount = jitcount // Set JIT countdown - preventry->bytecodesize = defsize // Set size - fin - fin defentry->interpjsr = $20 // JSR defentry=>interpaddr = *xinterp // XINTERP defentry=>bytecodeaddr = addr @@ -1048,11 +1029,11 @@ def adddef(isfirst, ext, addr, deflast)#1 return defentry end def loadmod(mod)#1 - word refnum[], deffirst, rdlen, modsize, bytecode, codefix, defofst, defcnt, init, initcode[], fixup + word refnum[], rdlen, modsize, bytecode, codefix, defofst, defcnt, init, initcode[], fixup word addr, defaddr, modaddr, modfix, modofst, modend word deftbl, deflast, codeseg word moddep, rld, esd, sym - byte lerr, defext, skipjit, fileinfo[], str[16], filename[33] + byte lerr, defext, fileinfo[], str[16], filename[33] byte header[128] lerr = 0 // @@ -1087,7 +1068,6 @@ def loadmod(mod)#1 // This is an EXTended RELocatable (data+bytecode) module. // systemflags = header.4 | systemflags - skipjit = header.5 & (nojitc >> 8) defofst = header:6 defcnt = header:8 init = header:10 @@ -1173,14 +1153,12 @@ def loadmod(mod)#1 // // Run through the DeFinition Dictionary. // - deffirst = 1 while ^rld == $02 // // This is a bytcode def entry - add it to the def directory. // - adddef(deffirst, defext, rld=>1 + defofst, @deflast) - deffirst = skipjit // Calculate JIT potential or not - rld = rld + 4 + adddef(defext, rld=>1 + defofst, @deflast) + rld = rld + 4 loop // // Run through the Re-Location Dictionary. @@ -1234,7 +1212,7 @@ def loadmod(mod)#1 // initcode = 0 if init - initcode = adddef(deffirst, defext, init + defofst, @deflast)() + initcode = adddef(defext, init + defofst, @deflast)() if initcode < 0 perr = -initcode fin @@ -1286,7 +1264,7 @@ cmdlnptr = @cmdln // Print PLASMA version // init_cons -prstr("PLASMA 2.0 Dev JITC\n")//; putb(version.1); putc('.'); putb(version.0); putln +prstr("PLASMA 2.0 DP2\n")//; putb(version.1); putc('.'); putb(version.0); putln prstr("MEM:$"); prword(availheap); crout // // Exec command line parser diff --git a/src/vmsrc/apple/sossysjit.pla b/src/vmsrc/apple/sossysjit.pla new file mode 100755 index 0000000..2e91d8d --- /dev/null +++ b/src/vmsrc/apple/sossysjit.pla @@ -0,0 +1,1309 @@ +const membank = $FFEF +const RELADDR = $1000 +// +// System flags: memory allocator screen holes. +// +const restxt1 = $0001 +const restxt2 = $0002 +const resxtxt1 = $0004 +const resxtxt2 = $0008 +const reshgr1 = $0010 +const reshgr2 = $0020 +const resxhgr1 = $0040 +const resxhgr2 = $0080 +const nojitc = $0100 +// +// Module don't free memory +// +const modkeep = $2000 +const modinitkeep = $4000 +// +// Private addresses +// +const instr = $A020 +const cmdparser = $A0F0 +const xinterp = $A0F8 +const jitinterp = $A0FA +// +// Indirect interpreter DEFinition entrypoint +// +struc t_defentry + byte interpjsr + word interpaddr + word bytecodeaddr + byte bytecodexbyte + byte callcount + byte bytecodesize +end +// +// JIT compiler values +// +const jitcbuf = $9000 +const jitcomp = $A0F2 +const jitcodeptr = $A0F4 +const codemax = $A000 +// +// Pedefined functions. +// +predef syscall(cmd,params)#1, call(addr,areg,xreg,yreg,status)#1 +predef crout()#0, cout(c)#0, prstr(s)#0, print(i)#0, prbyte(b)#0, prword(w)#0 +predef cin()#1, rdstr(p)#1, toupper(c)#1, strcpy(dst,src)#1, strcat(dst,src)#1 +predef markheap()#1, allocheap(size)#1, allocalignheap(size, pow2, freeaddr), releaseheap(newheap)#1, availheap()#1 +predef memset(addr,value,size)#0, memcpy(dst,src,size)#0 +predef uword_isgt(a,b)#1, uword_isge(a,b)#1, uword_islt(a,b)#1, uword_isle(a,b)#1, sext(a)#1, divmod(a,b)#2 +predef execmod(modfile)#1, open(path)#1, close(refnum)#1, read(refnum, buff, len)#1, write(refnum, buff, len)#1 +// +// Exported CMDSYS table +// +word version = $0200 // 02.00 +word syspath +word cmdlnptr +word = @execmod, @open, @close, @read, @write +byte perr +byte jitcount = 0 +byte jitsize = 0 +byte refcons = 0 +byte devcons = 0 +// +// String pool. +// +byte hexchar[] = '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' +// +// Exported Machine ID. +// +byte machid = $F2 // Apple ///, 80 columns +// +// Console and textmode control characters +// +byte console[] = ".CONSOLE" +byte textmode[] = 16, 0, 15 + +// +// Working input buffer overlayed with strings table +// +byte cmdln = "" +// +// SOS.CMD as DCI string +// +byte soscmd = 'S'|$80,'O'|$80,'S'|$80,'.'|$80,'C'|$80,'M'|$80,'D'|$80,'J'|$80,'I'|$80,'T' +// +// Standard Library exported functions. +// +byte sysmodstr[] = "CMDSYS" +byte machidstr[] = "MACHID" +byte sysstr[] = "SYSCALL" +byte callstr[] = "CALL" +byte putcstr[] = "PUTC" +byte putlnstr[] = "PUTLN" +byte putsstr[] = "PUTS" +byte putistr[] = "PUTI" +byte putbstr[] = "PUTB" +byte putwstr[] = "PUTH" +byte getcstr[] = "GETC" +byte getsstr[] = "GETS" +byte toupstr[] = "TOUPPER" +byte strcpystr[] = "STRCPY" +byte strcatstr[] = "STRCAT" +byte hpmarkstr[] = "HEAPMARK" +byte hpalignstr[] = "HEAPALLOCALIGN" +byte hpallocstr[] = "HEAPALLOC" +byte hprelstr[] = "HEAPRELEASE" +byte hpavlstr[] = "HEAPAVAIL" +byte memsetstr[] = "MEMSET" +byte memcpystr[] = "MEMCPY" +byte uisgtstr[] = "ISUGT" +byte uisgestr[] = "ISUGE" +byte uisltstr[] = "ISULT" +byte uislestr[] = "ISULE" +byte sextstr[] = "SEXT" +byte divmodstr[] = "DIVMOD" +byte sysmods[] = "" // overlay sys path with exports +word exports[] = @sysmodstr, @version +word = @sysstr, @syscall +word = @callstr, @call +word = @putcstr, @cout +word = @putlnstr, @crout +word = @putsstr, @prstr +word = @putistr, @print +word = @putbstr, @prbyte +word = @putwstr, @prword +word = @getcstr, @cin +word = @getsstr, @rdstr +word = @toupstr, @toupper +word = @hpmarkstr, @markheap +word = @hpallocstr,@allocheap +word = @hpalignstr,@allocalignheap +word = @hprelstr, @releaseheap +word = @hpavlstr, @availheap +word = @memsetstr, @memset +word = @memcpystr, @memcpy +word = @strcpystr, @strcpy +word = @strcatstr, @strcat +word = @uisgtstr, @uword_isgt +word = @uisgestr, @uword_isge +word = @uisltstr, @uword_islt +word = @uislestr, @uword_isle +word = @sextstr, @sext +word = @divmodstr, @divmod +word = @machidstr, @machid +word = 0 +word sysmodsym = @exports +// +// System variables. +// +word systemflags = 0 +word heap = $2000 +byte autorun[] +byte modseg[15] +byte modid = 0 +word symtbl, lastsym +// +// CALL SOS +// SYSCALL(CMD, PARAMS) +// +asm syscall(cmd,params)#1 + LDA ESTKL,X + LDY ESTKH,X + STA PARAMS + STY PARAMS+1 + INX + LDA ESTKL,X + STA CMD + BRK +CMD !BYTE 00 +PARAMS !WORD 0000 + LDY #$00 + STA ESTKL,X + STY ESTKH,X + RTS +end +// +// CALL 6502 ROUTINE +// CALL(AREG, XREG, YREG, STATUS, ADDR) +// +asm call(addr,areg,xreg,yreg,sstatus)#1 +REGVALS = SRC + PHP + LDA ESTKL,X + STA TMPL + LDA ESTKH,X + STA TMPH + INX + LDA ESTKL,X + PHA + INX + LDY ESTKL,X + INX + LDA ESTKL+1,X + PHA + LDA ESTKL,X + INX + STX ESP + TAX + PLA + PLP + JSR JMPTMP + PHP + STA REGVALS+0 + STX REGVALS+1 + STY REGVALS+2 + PLA + STA REGVALS+3 + LDX ESP + LDA #REGVALS + STA ESTKL,X + STY ESTKH,X + PLP + RTS +end +// +// SET MEMORY TO VALUE +// MEMSET(ADDR, VALUE, SIZE) +// With optimizations from Peter Ferrie +// +asm memset(addr,value,size)#0 + LDA ESTKL+2,X + STA DSTL + LDA ESTKH+2,X + STA DSTH + LDY ESTKL,X + BEQ + + INC ESTKH,X + LDY #$00 ++ LDA ESTKH,X + BEQ SETMEX +SETMLPL CLC + LDA ESTKL+1,X +SETMLPH STA (DST),Y + DEC ESTKL,X + BEQ ++ +- INY + BEQ + +-- BCS SETMLPL + SEC + LDA ESTKH+1,X + BCS SETMLPH ++ INC DSTH + BNE -- +++ DEC ESTKH,X + BNE - +SETMEX INX + INX + INX + RTS +end +// +// COPY MEMORY +// MEMCPY(DSTADDR, SRCADDR, SIZE) +// +asm memcpy(dst,src,size)#0 + INX + INX + INX + LDA ESTKL-3,X + ORA ESTKH-3,X + BEQ CPYMEX + LDA ESTKL-2,X + CMP ESTKL-1,X + LDA ESTKH-2,X + SBC ESTKH-1,X + BCC REVCPY +; +; FORWARD COPY +; + LDA ESTKL-1,X + STA DSTL + LDA ESTKH-1,X + STA DSTH + LDA ESTKL-2,X + STA SRCL + LDA ESTKH-2,X + STA SRCH + LDY ESTKL-3,X + BEQ FORCPYLP + INC ESTKH-3,X + LDY #$00 +FORCPYLP LDA (SRC),Y + STA (DST),Y + INY + BNE + + INC DSTH + INC SRCH ++ DEC ESTKL-3,X + BNE FORCPYLP + DEC ESTKH-3,X + BNE FORCPYLP + RTS +; +; REVERSE COPY +; +REVCPY ;CLC + LDA ESTKL-3,X + ADC ESTKL-1,X + STA DSTL + LDA ESTKH-3,X + ADC ESTKH-1,X + STA DSTH + CLC + LDA ESTKL-3,X + ADC ESTKL-2,X + STA SRCL + LDA ESTKH-3,X + ADC ESTKH-2,X + STA SRCH + DEC DSTH + DEC SRCH + LDY #$FF + LDA ESTKL-3,X + BEQ REVCPYLP + INC ESTKH-3,X +REVCPYLP LDA (SRC),Y + STA (DST),Y + DEY + CPY #$FF + BNE + + DEC DSTH + DEC SRCH ++ DEC ESTKL-3,X + BNE REVCPYLP + DEC ESTKH-3,X + BNE REVCPYLP +CPYMEX RTS +end +// +// COPY FROM MAIN MEM TO EXT MEM. +// +// MEMXCPY(DSTSEG, SRC, SIZE) +// +asm memxcpy(dst,src,size)#0 + LDA ESTKL,X + ORA ESTKH,X + BEQ CPYXMEX + LDY #$00 + STY DSTL + LDA ESTKH+2,X + CLC + ADC #$60 + STA DSTH + LDA ESTKL+2,X + CLC + ADC #$7F + STA DSTX + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + INC ESTKH,X +CPYXLP LDA (SRC),Y + STA (DST),Y + INY + BNE + + INC DSTH + INC SRCH ++ DEC ESTKL,X + BNE CPYXLP + DEC ESTKH,X + BNE CPYXLP + LDA #$00 + STA DSTX +CPYXMEX INX + INX + INX + RTS +end +// +// POKE BYTE VAL INTO EXT MEM. +// +// XPOKEB(SEG, DST, BYTEVAL) +// +asm xpokeb(seg, dst, byteval)#0 + LDA ESTKL+1,X + STA DSTL + LDA ESTKH+1,X + CLC + ADC #$60 + STA DSTH + LDA ESTKL+2,X + CLC + ADC #$7F + STA DSTX + LDY #$00 + LDA ESTKL,X + STA (DST),Y + STY DSTX + INX + INX + INX + RTS +end +// +// Unsigned word comparisons. +// +asm uword_isge(a,b)#1 + LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + LDA #$FF + ADC #$00 + EOR #$FF + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS +end +asm uword_isle(a,b)#1 + LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + LDA #$FF + ADC #$00 + EOR #$FF + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS +end +asm uword_isgt(a,b)#1 + LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + LDA #$FF + ADC #$00 + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS +end +asm uword_islt(a,b)#1 + LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + LDA #$FF + ADC #$00 + STA ESTKL+1,X + STA ESTKH+1,X + INX + RTS +end +asm divmod(a,b)#2 + JSR INTERP ; CALL INTERP + !BYTE $36, $5C ; DIVMOD, RET +end +asm sext(a)#1 + LDY #$00 + LDA ESTKL,X + BPL + + DEY ++ STY ESTKH,X + RTS +end +// +// A DCI string is one that has the high bit set for every character except the last. +// More efficient than C or Pascal strings. +// +//def dcitos(dci, str) +// byte len, c +// len = 0 +// repeat +// c = (dci).[len] +// len = len + 1 +// (str).[len] = c & $7F +// until !(c & $80) +// ^str = len +// return len +//end +asm dcitos(dci, str)#1 + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + LDY #$00 +- LDA (SRC),Y + CMP #$80 + AND #$7F + INY + STA (DST),Y + BCS - + TYA + LDY #$00 + STA (DST),Y + INX + STA ESTKL,X + STY ESTKH,X + RTS +end +//def stodci(str, dci) +// byte len, c +// len = ^str +// if len == 0 +// return +// fin +// c = toupper((str).[len]) & $7F +// len = len - 1 +// (dci).[len] = c +// while len +// c = toupper((str).[len]) | $80 +// len = len - 1 +// (dci).[len] = c +// loop +// return ^str +//end +asm stodci(str, dci)#1 + LDA ESTKL,X + STA DSTL + LDA ESTKH,X + STA DSTH + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH + INX + LDY #$00 + LDA (SRC),Y + BEQ ++ + TAY + LDA (SRC),Y + JSR TOUPR + BNE + +- LDA (SRC),Y + JSR TOUPR + ORA #$80 ++ DEY + STA (DST),Y + BNE - + LDA (SRC),Y +++ STA ESTKL,X + STY ESTKH,X + RTS +end +asm toupper(c)#1 + LDA ESTKL,X +TOUPR AND #$7F + CMP #'a' + BCC + + CMP #'z'+1 + BCS + + SBC #$1F ++ STA ESTKL,X + RTS +end +// +// Lookup routines. +// +//def lookuptbl(dci, tbl) +// word match +// while ^tbl +// match = dci +// while ^tbl == ^match +// if !(^tbl & $80) +// return (tbl):1 +// fin +// tbl = tbl + 1 +// match = match + 1 +// loop +// while (^tbl & $80) +// tbl = tbl + 1 +// loop +// tbl = tbl + 3 +// loop +// return 0 +asm lookuptbl(dci, tbl)#1 + LDY #$00 + STY DSTL + LDA ESTKH,X + CLC + ADC #$60 + STA DSTH + LDA ESTKL,X + CLC + ADC #$7F + STA DSTX + LDA ESTKL+1,X + STA SRCL + LDA ESTKH+1,X + STA SRCH +- LDA (DST),Y + BEQ + + CMP (SRC),Y + BNE ++ + INY + ASL + BCS - + LDA (DST),Y + PHA + INY + LDA (DST),Y + TAY + PLA ++ INX + STA ESTKL,X + STY ESTKH,X + LDA #$00 + STA DSTX + RTS +++ LDY #$00 +-- LDA (DST),Y + INC DSTL + BEQ + +--- ASL + BCS -- + LDA #$02 + ADC DSTL + STA DSTL + BCC - + INC DSTH + BCS - ++ INC DSTH + BNE --- +end +// def lookupidx(esd, index) +// word sym +// while ^esd +// sym = esd +// esd = sym + dcitos(sym, @str) +// if esd->0 & $10 and esd->1 == index +// return sym +// fin +// esd = esd + 3 +// loop +//end +asm lookupidx(esd, index)#1 + LDA ESTKL,X + STA TMPL + INX +--- LDA ESTKH,X + STA SRCH + LDA ESTKL,X +-- STA SRCL + LDY #$00 +- LDA (SRC),Y + BPL + + INY + BNE - ++ BEQ ++ ; END OF ESD + INY + LDA (SRC),Y + INY + AND #$10 ; EXTERN FLAG? + BEQ + + LDA (SRC),Y + CMP TMPL + BEQ +++ ; MATCH ++ INY + TYA + SEC + ADC SRCL + STA ESTKL,X ; SYM PTRL + BCC -- + INC ESTKH,X ; SYM PTRH + BNE --- +++ STA ESTKL,X ; END OF ESD + STA ESTKH,X ++++ RTS +end +//def lookupdef(addr, deftbl)#1 +// while deftbl->0 == $20 +// if deftbl=>3 == addr +// return deftbl +// fin +// deftbl = deftbl + t_defentry +// loop +// return 0 +//end +asm lookupdef(addr, deftbl)#1 + LDA ESTKH,X + STA SRCH + LDA ESTKL,X + STA SRCL + INX +- LDY #$00 + LDA (SRC),Y + CMP #$20 ; JSR OPCODE? + BNE ++ + LDY #$03 + LDA (SRC),Y + CMP ESTKL,X + BNE + + INY + LDA (SRC),Y + CMP ESTKH,X + BNE + + LDA SRCL ; MATCH + STA ESTKL,X + LDA SRCH + STA ESTKH,X + RTS ++ LDA #$08 ; T_DEFENTRY + CLC + ADC SRCL + STA SRCL + BCC - + INC SRCH + BNE - +++ STY ESTKL,X + STY ESTKH,X + RTS +end +// +// Reloc internal data +// +//def reloc(modfix, modofst, bytecode, rld)#3 +// word addr, fixup +// while ^rld +// if ^rld & $10 // EXTERN reference. +// return rld, addr, fixup +// fin +// addr = rld=>1 + modfix +// fixup = *addr + modofst +// if uword_isge(fixup, bytecode) // Bytecode address. +// return rld, addr, fixup +// fin +// *addr = fixup +// rld = rld + 4 +// loop +// return rld, addr, fixup +//end +asm reloc(modfix, modofst, bytecode, rld)#3 + LDA ESTKL,X + STA SRCL + LDA ESTKH,X + STA SRCH + LDY #$00 +- LDA (SRC),Y + BEQ RLDEX ; END OF RLD + PHA + INY + LDA (SRC),Y + INY + CLC + ADC ESTKL+3,X ; ADDR=ENTRY=>1+MODFIX + STA DSTL + LDA (SRC),Y + ADC ESTKH+3,X + STA DSTH + PLA + AND #$10 ; EXTERN REF - EXIT + BNE RLDEX + TAY ; FIXUP=*ADDR+MODOFST + LDA (DST),Y + INY + CLC + ADC ESTKL+2,X + STA TMPL + LDA (DST),Y + ADC ESTKH+2,X + CMP ESTKH+1,X ; FIXUP >= BYTECODE? + BCC + + STA TMPH + BNE RLDEX ; YEP, EXIT + LDA TMPL + CMP ESTKL+1,X + BCS RLDEX ; YEP, EXIT + LDA TMPH ++ STA (DST),Y ; *ADDR=FIXUP + DEY + LDA TMPL + STA (DST),Y + LDA SRCL ; NEXT ENTRY +; CLC + ADC #$04 + STA SRCL + BCC - + INC SRCH + BNE - +RLDEX INX + LDA TMPL + STA ESTKL,X + LDA TMPH + STA ESTKH,X + LDA DSTL + STA ESTKL+1,X + LDA DSTH + STA ESTKH+1,X + LDA SRCL + STA ESTKL+2,X + LDA SRCH + STA ESTKH+2,X + RTS +end +// +// SOS routines +// FILE I/O +// +def open(path)#1 + byte params[7] + + params.0 = 4 + params:1 = path + params.3 = 0 + params:4 = 0 + params.6 = 0 + perr = syscall($C8, @params) + return params.3 +end +def close(refnum)#1 + byte params[2] + + params.0 = 1 + params.1 = refnum + perr = syscall($CC, @params) + return perr +end +def read(refnum, buff, len)#1 + byte params[8] + + params.0 = 4 + params.1 = refnum + params:2 = buff + params:4 = len + params:6 = 0 + perr = syscall($CA, @params) + return params:6 +end +def write(refnum, buff, len)#1 + byte params[6] + + params.0 = 3 + params.1 = refnum + params:2 = buff + params:4 = len + perr = syscall($CB, @params) + return perr +end +// +// CONSOLE I/O +// +def dev_control(devnum, code, list)#1 + byte params[5] + + params.0 = 3 + params.1 = devnum + params.2 = code + params:3 = list + return syscall($83, @params) +end +def dev_getnum(name)#1 + byte params[4] + + params.0 = 2 + params:1 = name + params.3 = 0 + syscall($84, @params) + return params.3 +end +def init_cons()#0 + byte nlmode[2] + + refcons = open(@console) + devcons = dev_getnum(@console) + nlmode:0 = $0D80 + //nlmode.0 = $80 + //nlmode.1 = $0D + dev_control(devcons, $02, @nlmode) + write(refcons, @textmode, 3) +end +// +// MEMORY CALLS +// +def seg_find(search, pages, id)#3 + byte params[10] + + params.0 = 6 + params.1 = search + params.2 = id + params:3 = pages + params:5 = 0 + params:7 = 0 + params.9 = 0 + perr = syscall($41, @params) + return params.9, params:5, params:7 +end +def seg_release(segnum)#1 + byte params[2] + + params.0 = 1 + params.1 = segnum + perr = syscall($45, @params) + return perr +end +// +// CONSOLE I/O +// +def cout(ch)#0 + byte nc + + nc = 1 + if ch == $0D + ch = $0A0D + nc = 2 + fin + write(refcons, @ch, nc) +end +def crout()#0 + cout($0D) +end +def cin()#1 + byte ch + read(refcons, @ch, 1) + return ch & $7F +end +def prstr(str)#0 + write(refcons, str + 1, ^str) + if str->[^str] == $0D + cout($0A) + fin +end +def print(i)#0 + if i < 0; cout('-'); i = -i; fin + if i >= 10; print(i / 10); fin + cout(i % 10 + '0') +end +def rdstr(prompt)#1 + cout(prompt) + ^instr = read(refcons, instr+1, 128) + if instr->[^instr] == $0D + ^instr-- + fin + crout + return instr +end +def prbyte(v)#0 + cout(hexchar[(v >> 4) & $0F]) + cout(hexchar[v & $0F]) +end +def prword(v)#0 + prbyte(v >> 8) + prbyte(v) +end +// +// Heap routines. +// +def availheap()#1 + byte fp + return @fp - heap +end +def allocheap(size)#1 + word addr + addr = heap + heap = heap + size + if uword_isge(heap, @addr) + heap = addr + return 0 + fin + return addr +end +def allocalignheap(size, pow2, freeaddr)#1 + word align, addr + if freeaddr + *freeaddr = heap + fin + align = (1 << pow2) - 1 + addr = (heap | align) + 1 + heap = addr + size + if uword_isge(heap, @addr) + return 0 + fin + return addr +end +def markheap()#1 + return heap +end +def releaseheap(newheap)#1 + heap = newheap + return @newheap - heap +end +// +// Symbol table routines. +// +def addsym(sym, addr)#0 + while ^sym & $80 + xpokeb(symtbl.0, lastsym, ^sym) + lastsym = lastsym + 1 + sym = sym + 1 + loop + xpokeb(symtbl.0, lastsym, ^sym) + xpokeb(symtbl.0, lastsym + 1, addr.0) + xpokeb(symtbl.0, lastsym + 2, addr.1) + xpokeb(symtbl.0, lastsym + 3, 0) + lastsym = lastsym + 3 +end +// +// String routines. +// +def strcpy(dst, src)#1 + memcpy(dst+1, src+1, ^src) + ^dst = ^src + return dst +end +def strcat(dst, src)#1 + memcpy(dst + ^dst + 1, src + 1, ^src) + ^dst = ^dst + ^src + return dst +end +// +// Module routines. +// +def lookupextern(esd, index)#1 + word sym, addr + byte str[16] + sym = lookupidx(esd, index) + if sym + addr = lookuptbl(sym, symtbl) + if !addr + perr = $81 + dcitos(sym, @str) + cout('?'); prstr(@str); crout + fin + return addr + fin + return 0 +end +def adddef(isfirst, ext, addr, deflast)#1 + word preventry, defentry, defsize + defentry = *deflast + *deflast = defentry + t_defentry + if not isfirst + preventry = defentry - t_defentry + defsize = addr - preventry=>bytecodeaddr + if defsize <= jitsize + preventry=>interpaddr = *jitinterp // JSR JITINTRP + preventry->callcount = jitcount // Set JIT countdown + preventry->bytecodesize = defsize // Set size + fin + fin + defentry->interpjsr = $20 // JSR + defentry=>interpaddr = *xinterp // XINTERP + defentry=>bytecodeaddr = addr + defentry->bytecodexbyte = ext + defentry->t_defentry = 0 + return defentry +end +def loadmod(mod)#1 + word refnum[], deffirst, rdlen, modsize, bytecode, codefix, defofst, defcnt, init, initcode[], fixup + word addr, defaddr, modaddr, modfix, modofst, modend + word deftbl, deflast, codeseg + word moddep, rld, esd, sym + byte lerr, defext, skipjit, fileinfo[], str[16], filename[33] + byte header[128] + lerr = 0 + // + // Read the RELocatable module header (first 128 bytes) + // + dcitos(mod, @filename) + refnum = open(@filename) + if !refnum and filename < 16 + // + // Try system path + // + refnum = open(strcpy(@filename,strcat(strcpy(@header, @sysmods), @filename))) + fin + if refnum + header.0 = 3 + header:1 = @filename + header:3 = @fileinfo + header.5 = 2 + if not syscall($C4, @header) and fileinfo.1 <> $FE // Make sure it's a REL module + close(refnum) + perr = $4A // Incompatible type + return -perr + fin + rdlen = read(refnum, @header, 128) + modsize = header:0 + moddep = @header.1 + defofst = modsize + RELADDR + defext = 0 + init = 0 + if rdlen > 4 and header:2 == $6502 // magic number + // + // This is an EXTended RELocatable (data+bytecode) module. + // + systemflags = header.4 | systemflags + skipjit = header.5 & (nojitc >> 8) + defofst = header:6 + defcnt = header:8 + init = header:10 + moddep = @header.12 + // + // Load module dependencies. + // + while ^moddep + if !lookuptbl(moddep, symtbl) + if refnum + close(refnum) + refnum = 0 + fin + if loadmod(moddep) < 0 + return -perr + fin + fin + moddep = moddep + dcitos(moddep, @str) + loop + // + // Init def table. + // + deftbl = allocheap(defcnt * t_defentry + 1) + deflast = deftbl + ^deflast = 0 + if !refnum + // + // Reset read pointer. + // + refnum = open(@filename) + rdlen = read(refnum, @header, 128) + fin + fin + // + // Alloc heap space for relocated module (data + bytecode). + // + moddep++ + modfix = moddep - @header.2 // Adjust to skip header + modsize = modsize - modfix + rdlen = rdlen - modfix - 2 + modaddr = allocheap(modsize) + memcpy(modaddr, moddep, rdlen) + // + // Read in remainder of module into memory for fixups. + // + addr = modaddr + repeat + addr = addr + rdlen + rdlen = read(refnum, addr, 4096) + until rdlen <= 0 + close(refnum) + // + // Add module to symbol table. + // + addsym(mod, modaddr) + // + // Apply all fixups and symbol import/export. + // + modfix = modaddr - modfix + modofst = modfix - RELADDR + modend = modaddr + modsize + bytecode = defofst + modofst + rld = modend // Re-Locatable Directory + esd = rld // Extern+Entry Symbol Directory + while ^esd // Scan to end of ESD + esd = esd + 4 + loop + esd++ + if defcnt + // + // Locate bytecode defs in allocated segment. + // + modseg[modid], codeseg, drop = seg_find($00, (rld - bytecode + 255) >> 8, modid + $12) + if perr + return -perr + fin + modid++ + defext = codeseg.0 + $7F // (codeseg.0 | $80) - 1 + defaddr = (codeseg & $FF00) + $6000 + codefix = defaddr - bytecode + defofst = defaddr - defofst + fin + // + // Run through the DeFinition Dictionary. + // + deffirst = 1 + while ^rld == $02 + // + // This is a bytcode def entry - add it to the def directory. + // + adddef(deffirst, defext, rld=>1 + defofst, @deflast) + deffirst = skipjit // Calculate JIT potential or not + rld = rld + 4 + loop + // + // Run through the Re-Location Dictionary. + // + while ^rld + rld, addr, fixup = reloc(modfix, modofst, bytecode, rld) + if ^rld + *addr = ^rld & $10 ?? *addr + lookupextern(esd, rld->3) :: lookupdef(fixup + codefix, deftbl) + rld = rld + 4 + fin + loop + // + // Run through the External/Entry Symbol Directory. + // + while ^esd + sym = esd + esd = esd + dcitos(esd, @str) + if ^esd & $08 + // + // EXPORT symbol - add it to the global symbol table. + // + addr = esd=>1 + modofst + if uword_isge(addr, bytecode) + // + // Use the def directory address for bytecode. + // + addr = lookupdef(addr + codefix, deftbl) + fin + addsym(sym, addr) + fin + esd = esd + 3 + loop + if defext + // + // Copy bytecode to code segment. + // + memxcpy(codeseg, bytecode, modsize - (bytecode - modaddr)) + fin + else + lerr = $46 + fin + if lerr + return -lerr + fin + // + // Free up end-of-module main memory. + // + releaseheap(bytecode) + // + // Call init routine if it exists. + // + initcode = 0 + if init + initcode = adddef(deffirst, defext, init + defofst, @deflast)() + if initcode < 0 + perr = -initcode + fin + fin + return initcode +end +def execmod(modfile)#1 + byte moddci[17] + word saveheap, savesym, saveflags + + perr = 1 + if stodci(modfile, @moddci) + saveheap = heap + savesym = lastsym + saveflags = systemflags + if loadmod(@moddci) < modkeep + lastsym = savesym + heap = saveheap + while modid + modid-- + seg_release(modseg[modid]) + loop + xpokeb(symtbl.0, lastsym, 0) + systemflags = saveflags + else + modid = 0 + fin + fin + return -perr +end +// +// Init 2K symbol table. +// +drop, symtbl, drop = seg_find($00, $08, $11) +lastsym = symtbl & $FF00 +xpokeb(symtbl.0, lastsym, 0) +while *sysmodsym + stodci(sysmodsym=>0, heap) + addsym(heap, sysmodsym=>2) + sysmodsym = sysmodsym + 4 +loop +// +// Clear system path and command line +// +sysmods = 0 +syspath = @sysmods +cmdlnptr = @cmdln +// +// Print PLASMA version +// +init_cons +prstr("PLASMA 2.0 DP2 JITC\n")//; putb(version.1); putc('.'); putb(version.0); putln +prstr("MEM:$"); prword(availheap); crout +// +// Exec command line parser +// +loadmod(@soscmd) +modid = 0 +autorun = open("AUTORUN") +if autorun > 0 + cmdln = read(autorun, @cmdln.1, 64) + close(autorun) +fin +// +// Call cmd line parser +// +repeat + execmod((*cmdparser)()) + write(refcons, @textmode, 3) + cmdln = 0 +until 0 +done From f5b0fb86b4d4038a38bae9991adf207b9c0a2f9a Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 28 Dec 2019 17:36:34 -0800 Subject: [PATCH 093/149] Not loading NOJIT interpreter correctly --- src/vmsrc/apple/plvm03.s | 2 +- src/vmsrc/apple/soscmd.pla | 15 --------------- src/vmsrc/apple/sossys.pla | 3 +-- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/src/vmsrc/apple/plvm03.s b/src/vmsrc/apple/plvm03.s index e0a8d42..90b9f95 100755 --- a/src/vmsrc/apple/plvm03.s +++ b/src/vmsrc/apple/plvm03.s @@ -80,7 +80,7 @@ SEGSTART = $2000 LDA DSTH CMP #$B8 BNE - - LDA #$00 ; INIT JIT, FRAME & POOL POINTERS + LDA #$00 ; INIT FRAME & POOL POINTERS STA PPL STA IFPL LDA #$A0 ; TOP OF RAM FOR FRAME POINER diff --git a/src/vmsrc/apple/soscmd.pla b/src/vmsrc/apple/soscmd.pla index e9f3ca2..12ce01e 100755 --- a/src/vmsrc/apple/soscmd.pla +++ b/src/vmsrc/apple/soscmd.pla @@ -1,19 +1,4 @@ include "inc/cmdsys.plh" -sysflags nojitc // Keep JITC from compiling itself -// -// JIT compiler values -// -// -// Indirect interpreter DEFinition entrypoint -// -struc t_defentry - byte interpjsr - word interpaddr - word bytecodeaddr - byte bytecodexbyte - byte callcount - byte bytecodesize -end // // Private addresses // diff --git a/src/vmsrc/apple/sossys.pla b/src/vmsrc/apple/sossys.pla index 267121f..12e199c 100755 --- a/src/vmsrc/apple/sossys.pla +++ b/src/vmsrc/apple/sossys.pla @@ -11,7 +11,6 @@ const reshgr1 = $0010 const reshgr2 = $0020 const resxhgr1 = $0040 const resxhgr2 = $0080 -const nojitc = $0100 // // Module don't free memory // @@ -50,7 +49,7 @@ word syspath word cmdlnptr word = @execmod, @open, @close, @read, @write byte perr -byte jitcount = 0 +byte jitcount = 0 // Keep these here for compatibility byte jitsize = 0 byte refcons = 0 byte devcons = 0 From eb076459e9bf9a621c5fd46ffa7076331512255b Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sat, 28 Dec 2019 18:48:15 -0800 Subject: [PATCH 094/149] Fix all remaining NOJIT issues (defentry size discrepancy) --- src/tftpbld | 2 +- src/vmsrc/apple/plvm03.s | 50 +++-------------------------------- src/vmsrc/apple/soscmd.pla | 16 +---------- src/vmsrc/apple/sossys.pla | 8 +++--- src/vmsrc/apple/sossysjit.pla | 4 +-- 5 files changed, 11 insertions(+), 69 deletions(-) diff --git a/src/tftpbld b/src/tftpbld index 9a53911..5d40e6c 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -47,7 +47,7 @@ echo "BLD/SAMPLES/HGRTEST.PLA"; atftp $1 --put -l samplesrc/hgrtest.pla -r $ echo "BLD/SAMPLES/PLAYSEQ.PLA"; atftp $1 --put -l samplesrc/playseq.pla -r $2/BLD/SAMPLES/PLAYSEQ.PLA#040000 echo "BLD/SAMPLES/RPNCALC.PLA"; atftp $1 --put -l samplesrc/rpncalc.pla -r $2/BLD/SAMPLES/RPNCALC.PLA#040000 echo "BLD/SAMPLES/SIEVE.PLA"; atftp $1 --put -l samplesrc/sieve.pla -r $2/BLD/SAMPLES/SIEVE.PLA#040000 -echo "BLD/SAMPLES/MON.PLA"; atftp $1 --put -l utilsrc/mon.pla -r $2/BLD/SAMPLES/MON.PLA#040000 +echo "BLD/SAMPLES/MON.PLA"; atftp $1 --put -l utilsrc/apple/mon.pla -r $2/BLD/SAMPLES/MON.PLA#040000 echo "BLD/SAMPLES/MEMTEST.PLA"; atftp $1 --put -l samplesrc/memtest.pla -r $2/BLD/SAMPLES/MEMTEST.PLA#040000 echo "BLD/SAMPLES/FATCAT.PLA"; atftp $1 --put -l samplesrc/fatcat.pla -r $2/BLD/SAMPLES/FATCAT.PLA#040000 echo "BLD/SAMPLES/GFXDEMO.PLA"; atftp $1 --put -l samplesrc/gfxdemo.pla -r $2/BLD/SAMPLES/GFXDEMO.PLA#040000 diff --git a/src/vmsrc/apple/plvm03.s b/src/vmsrc/apple/plvm03.s index 90b9f95..1c4c874 100755 --- a/src/vmsrc/apple/plvm03.s +++ b/src/vmsrc/apple/plvm03.s @@ -134,7 +134,6 @@ JITCOMP !WORD 0 ; $A0F2 JITCODE !WORD 0 ; $A0F4 SENTRY !WORD INTERP ; $A0F6 XENTRY !WORD XINTERP ; $A0F8 -JENTRY !WORD JITINTRP ; $A0FA ;* ;* OPCODE TABLE ;* @@ -156,11 +155,11 @@ OPTBL !WORD ZERO,CN,CN,CN,CN,CN,CN,CN ; 00 02 ;* SYSTEM INTERPRETER ENTRYPOINT ;* INTERP PLA - CLC - ADC #$01 + CLC + ADC #$01 STA IPL PLA - ADC #$00 + ADC #$00 STA IPH LDY #$00 STY IPX @@ -184,49 +183,6 @@ XINTERP PLA DEY JMP FETCHOP ;* -;* JIT PROFILING ENTRY INTO INTERPRETER -;* -JITINTRP PLA - STA TMPL - PLA - STA TMPH - LDY #$04 - LDA (TMP),Y ; DEC JIT COUNT - SEC - SBC #$01 - STA (TMP),Y - BNE - ; INTERP BYTECODE - LDA JITCOMP ; CALL JIT COMPILER - STA SRCL - LDA JITCOMP+1 - STA SRCH - INY ; LDY #$05 - LDA (SRC),Y - STA IPX - DEY - LDA (SRC),Y - STA IPH - DEY - LDA (SRC),Y - STA IPL - DEX ; ADD PARAMETER TO DEF ENTRY - LDA TMPL - SEC - SBC #$02 ; POINT TO DEF ENTRY - PHA ; AND SAVE IT FOR LATER - STA ESTKL,X - LDA TMPH - SBC #$00 - PHA - STA ESTKH,X - LDY #$00 - JSR FETCHOP ; CALL JIT COMPILER - PLA - STA TMPH - PLA - STA TMPL - JMP (TMP) ; RE-CALL ORIGINAL DEF ENTRY -;* ;* INTERNAL DIVIDE ALGORITHM ;* _NEG LDA #$00 diff --git a/src/vmsrc/apple/soscmd.pla b/src/vmsrc/apple/soscmd.pla index 12ce01e..f433a5d 100755 --- a/src/vmsrc/apple/soscmd.pla +++ b/src/vmsrc/apple/soscmd.pla @@ -3,18 +3,6 @@ include "inc/cmdsys.plh" // Private addresses // const cmdparser = $A0F0 -const sinterp = $A0F6 -const xinterp = $A0F8 -const estkh8 = $C000 -const estkh = $00C0 -const estkl8 = $D000 -const estkl = $00D0 -const ifpl8 = $E000 -const ifph8 = $E100 -const jmptmp = $00E6 -const tmpl8 = $E700 -const tmph8 = $E800 -word directentry, indirectentry // // SOS routines // FILE I/O @@ -253,7 +241,5 @@ end // // Save pointer to command line handler // -*cmdparser = @shell -directentry = *sinterp -indirectentry = *xinterp +*cmdparser = @shell done diff --git a/src/vmsrc/apple/sossys.pla b/src/vmsrc/apple/sossys.pla index 12e199c..30b0bf2 100755 --- a/src/vmsrc/apple/sossys.pla +++ b/src/vmsrc/apple/sossys.pla @@ -691,7 +691,7 @@ asm lookupdef(addr, deftbl)#1 LDA SRCH STA ESTKH,X RTS -+ LDA #$08 ; T_DEFENTRY ++ LDA #$06 ; T_DEFENTRY CLC ADC SRCL STA SRCL @@ -1028,7 +1028,7 @@ def adddef(ext, addr, deflast)#1 return defentry end def loadmod(mod)#1 - word refnum[], rdlen, modsize, bytecode, codefix, defofst, defcnt, init, initcode[], fixup + word refnum, rdlen, modsize, bytecode, codefix, defofst, defcnt, init, initcode[], fixup word addr, defaddr, modaddr, modfix, modofst, modend word deftbl, deflast, codeseg word moddep, rld, esd, sym @@ -1269,8 +1269,8 @@ prstr("MEM:$"); prword(availheap); crout // Exec command line parser // loadmod(@soscmd) -modid = 0 -autorun = open("AUTORUN") +modid = 0 +autorun = open("AUTORUN") if autorun > 0 cmdln = read(autorun, @cmdln.1, 64) close(autorun) diff --git a/src/vmsrc/apple/sossysjit.pla b/src/vmsrc/apple/sossysjit.pla index 2e91d8d..58d10c9 100755 --- a/src/vmsrc/apple/sossysjit.pla +++ b/src/vmsrc/apple/sossysjit.pla @@ -1292,8 +1292,8 @@ prstr("MEM:$"); prword(availheap); crout // Exec command line parser // loadmod(@soscmd) -modid = 0 -autorun = open("AUTORUN") +modid = 0 +autorun = open("AUTORUN") if autorun > 0 cmdln = read(autorun, @cmdln.1, 64) close(autorun) From 262a799a9d1d2bfacc2e628ce2ef64602861e08d Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 28 Dec 2019 18:52:58 -0800 Subject: [PATCH 095/149] Update SOS images --- images/apple/PLASMA2-FPSOS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/images/apple/PLASMA2-FPSOS.PO b/images/apple/PLASMA2-FPSOS.PO index b269e7af13333cf3400df625e20c500c0a26a66c..c88bf6e279b2cd01ef64d891c3d273a59f2acc5f 100644 GIT binary patch delta 2833 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 delta 3399 zcmZu!4|G%I6~FI$FJIC&ZPWB0Efq?M;Vq^mfMP||6loPmLq;F0>%gWZe5=tDq}10g z$C4qmbgTnUE*(rJHbKzrvee?3tm0f#i!L*IxJ@iJjs+`+Hb4ynk;;1ROhj&!1t}0pK zmCD!nK>srg@u^Ur`yH54R!b+k3QMzw-Fs>IvS|)>y+;ccUKc`$w^fyS%j4D(kMU-n z!iP!IZ7S!!r{^g5lvh@j+`W2vLYqFuX8;sV=~?0#I^U-Si>CRzslvDT7T3ZlMY@l- z0u)Wx3+Xw$)Z;!!AIW`{C!2uFwwU2)=8LZ%JM(r`JW$1cmagZrmBAY0nv52UR|GLd z0(^)Cl44Q*b(WTpY>Sff7X4q3d%ck;>7#T9u~?P;qjWB3QO52w7NoaZQDx1e!0wj5 zwD@)_7f0#5dly+;z90nnolU&R$9TVEzU}fvfG5j6CJ=c^KVGG4pb#V=Wm`&ws-ITP zM@uf>LXZwyd`|tiTG?J}^kIbW)*5FV%Z&3Zw=|Y1;x2?Ls+*@-dW8fY5dZ`3E3G|A}+~Nc1A` zZ9E6jB&00P9Er|F;XzJ_{(&RWexy-czt8c}OPn=&2eGz2K_L1k!JhT-d-NZw5KJtagZ|AexmZ7{7<;}bhZA9LJ)PeFg{zs;0 z7Ye(1zU}w8xgX_&yfOM0l>7M1wqaBpK|0QZaxRAyDrpz^H09Ph<0S=q*i3HCRlN1a zwZj8@X_PY`+y$^J|IDFX|XqkpCj z<%y8-c*L%LcIalcSzD_9Rx4AJVijs}%%iS~{a6jf)~TmsKT|Kq{OT>SP3rzwP<_0w zRoy(eN6j4ErY;#gpvr^&s$uZ2>dV@5>J_a~y*T&_HEHO$`gQLK^-S-ZYHHu8`bqCO z)z@LZ2XinZSOl}9HfQY zmGfJSZz*XSeR6iQ)^hbwz)+J^_`)Bn1&%Zk22H%FjYSgj-qLOI_3OxIo*^Io*y{ zw7#W}<~9_^oQ2)jEZRAhfob2;^mac&oly@nO;vaFcPj)#`G4M-I^`g)j))$?675qzEy&p|nf1Z##Zwn9vCl;k7 zz<;~oAz`JIM>91-JQ;lHos8hWU%H|^(@$q{SCn`AX@1G)eIdb93`_`a)ubo;LeyIT zjy7yCCWt1fq|fEJ3(JS%s+d$9Q(lvecSX)~(Bxzw-l?DC^JIUBwDuYyaHqpk;mN}T zvDSV;l`anAVbTzCgveMbPcxxSwc?$!Uo4U9g{FYxm{^NV8&{t17+>bGV1cDe{VvDK zN3I^)Rdb#Zu~vV<1E^jr3!-1Pv54RVOS_y5O~oLmF=ATYYXVm1B%9oxUqWDGuvXh0 zuGQEkIhp-jHnaQXH1Pr1=35NRmdMguh;BS7lfD3L+obLx>_8JVB;49=7E3U@c64X+ zdtaGgX7g`4rOd(5EV=LjV1*Ac;|o+# zl|!O`smWu*O>~_fvNEaqqSUSSbgyVnMJ7e4+@?O$3TP8NiA#9swz*qeE)y z^-*wCG&uuK5B8%|?;tA4gD#LQEX^}hPcLmUxpg5+{EaiqF1_6?HRtt7$>WH=0-X1C zeV%H4P~}J_&ZL};eI@7Oe)o_Q3M)Lf0n66sG!qBfmjzhgomk&Q<^9qaep)ta-V2kX ztB)kh#jeEo0AcYq%R`4?ab)Q4EWA~7VRPbZL7R!G)^&VyAh=<%R*zv|JT7Fx4O%Iw z$4cme5Z<6~)O+8XfR+m?4qf>3L-tu}c($P-jMzx5BF45FE6iLea+nX6}-{> znwx^55Qkkm2gOrM|BJzH>v6wnAWB)pSfuzO#&dbcj=%iM-(G#~#Oo*DICc8XGk^cb z*|$dDe&^ly-dD<=<_a)@*M{9^4MH#iYgXU0_PXov4*@$y!HW%f5Qv# z#kBkS4e4L=;3;2M?pZJupTG%8z^6}7;2O+@uwVizBnvz&A>YHrgR3k{T>jB(s*ncb zc|Q!Bath-!(d!%E^*Z${p~t<9k{)+CzTKm}kDJl_$IuQ^ P5>hf!N{@T7dFB5BkHJB* From 80a6b2d4b74f538dde35932eab4a2df7b9c37386 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 28 Dec 2019 20:39:43 -0800 Subject: [PATCH 096/149] Developer Preview 2 Release --- README.md | 2 +- doc/Version 2.0.md | 24 ++++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a186f62..146795e 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 12/17/2019 PLASMA 2.0 Developer Preview 1z Available! +# 12/28/2019 PLASMA 2.0 Developer Preview 2 Available! [Download and read the Release Notes](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md) # 4/29/2018 PLASMA 1.2 Available! diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index a183038..6e5994e 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -1,4 +1,4 @@ -# PLASMA Version 2.0 Developer Preview 1z +# PLASMA Version 2.0 Developer Preview 2 Welcome to PLASMA: the Grand Unifying Platform for the Apple 1, ][, and ///. @@ -102,15 +102,31 @@ There is a [YouTube playlist](https://www.youtube.com/playlist?list=PLlPKgUMQbJ7 - The documentation is sparse and incomplete. Yep, could use your help... -# Changed in PLASMA for 2.0 DP 1z +# Changes in PLASMA for 2.0 DP 2 + +1. Many file manipulaition utilities (COPY, REName, NEWDIRectory, DELete, CATalog, TYPE) + +2. New and updated graphics libraries for lo-res. double lo-res and hi-res graphics + +3. Apple /// improvements to SOS.INTERP launching with SOS utility + +3. Editor improvements + +4. A couple small compiler optimizations + +5. Needed to break out TCP/IP modules into seperate floppy image + +6. Library changes require full install + +# Changes in PLASMA for 2.0 DP 1z 1. Many fixes for the value zero - especially in 65802/65816 divide routine -# Changed in PLASMA for 2.0 DP 1 E+C +# Changes in PLASMA for 2.0 DP 1 E+C 1. Greatly improved code editor and additional compiler stats -# Changed in PLASMA for 2.0 DP 1a +# Changes in PLASMA for 2.0 DP 1a 1. Fix interaction with JIT compiler and module load/unload From 3caa4b909cd80533baf4d5d9c496bfd817f664fd Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 29 Dec 2019 06:37:54 -0800 Subject: [PATCH 097/149] More DP2 change description --- doc/Version 2.0.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index 6e5994e..618490e 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -106,17 +106,21 @@ There is a [YouTube playlist](https://www.youtube.com/playlist?list=PLlPKgUMQbJ7 1. Many file manipulaition utilities (COPY, REName, NEWDIRectory, DELete, CATalog, TYPE) -2. New and updated graphics libraries for lo-res. double lo-res and hi-res graphics +2. New and updated libraries for lo-res. double lo-res and hi-res graphics w/ sprites -3. Apple /// improvements to SOS.INTERP launching with SOS utility +3. 32 bit integer library for those times when 16 bits just isn't enough -3. Editor improvements +4. Apple /// improvements to other SOS.INTERP launching with SOS utility -4. A couple small compiler optimizations +5. Apple /// JIT VM for speed and non JIT version to free up global memory -5. Needed to break out TCP/IP modules into seperate floppy image +6. Editor improvements -6. Library changes require full install +7. A couple small compiler optimizations + +8. Needed to break out TCP/IP modules into seperate floppy image + +9. Library changes require full install # Changes in PLASMA for 2.0 DP 1z From 74f00b9764556102f06bb27bfc0343059f42f9c4 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 29 Dec 2019 06:39:17 -0800 Subject: [PATCH 098/149] Direct link to change list for DP2 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 146795e..1d1e0b4 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # 12/28/2019 PLASMA 2.0 Developer Preview 2 Available! [Download and read the Release Notes](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md) +[Change List](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md#changes-in-plasma-for-20-dp-2) # 4/29/2018 PLASMA 1.2 Available! [Download and read the Release Notes](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%201.2.md) From 3bb038b1d581b936d862f79da14ca21675d5ba9d Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 29 Dec 2019 06:39:33 -0800 Subject: [PATCH 099/149] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1d1e0b4..893a881 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # 12/28/2019 PLASMA 2.0 Developer Preview 2 Available! [Download and read the Release Notes](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md) + [Change List](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md#changes-in-plasma-for-20-dp-2) # 4/29/2018 PLASMA 1.2 Available! From c86d3349dfe294281d5fbdf34cc905e9042d2f05 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 29 Dec 2019 08:43:24 -0800 Subject: [PATCH 100/149] Update Version 2.0.md --- doc/Version 2.0.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index 618490e..aadf654 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -12,6 +12,8 @@ Download the four disk images (three if you don't plan to boot an Apple ///): [PLASMA 2.0 DP Demos](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-DEM.PO?raw=true) +[PLASMA 2.0 TCP/IP modules](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-INET.PO?raw=true) + [PLASMA 2.0 DP Apple /// SOS Boot and SANE floating point modules](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-FPSOS.PO?raw=true) PLASMA can be run from floppies, System in Drive 1, and Build or Demos in Drive 2. Mass storage is the recommended installation that looks like (replacing HARDISK with your volume name of choice): @@ -24,6 +26,8 @@ Demo Files => /HARDISK/PLASMA/DEMOS/ SANE files => /HARDISK/PLASMA/SYS +INET files => /HARDDISK/PLASMA/SYS + Use the System Utilities to copy the floppy images into the above mentioned directories. ## Apple 1 From 835b90e63600c417f7e4b61711ef1c2da65f28ba Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 29 Dec 2019 08:44:32 -0800 Subject: [PATCH 101/149] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 893a881..0b38ebf 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # 12/28/2019 PLASMA 2.0 Developer Preview 2 Available! -[Download and read the Release Notes](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md) +[Download and read the Release Notes](https://github.com/dschmenk/PLASMA/releases) [Change List](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md#changes-in-plasma-for-20-dp-2) From de29742841b5f3e023d1729b51738292f0293adc Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 29 Dec 2019 22:04:04 -0800 Subject: [PATCH 102/149] Missed JIT16 dependency --- src/makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/makefile b/src/makefile index 38cd078..2220ef1 100755 --- a/src/makefile +++ b/src/makefile @@ -102,7 +102,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT17) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc From c743ace42b72a657e3993cf249059b7b49a5b447 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Mon, 30 Dec 2019 22:34:35 -0800 Subject: [PATCH 103/149] Trying to track down file write corruption --- images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes src/toolsrc/ed.pla | 47 +++++++++++++++++++-------------------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/images/apple/PLASMA2.2mg b/images/apple/PLASMA2.2mg index 76e8995d1eb8e838098848dc1b6fffabe8a8705c..c996d54cc7f0d7e0dd8cb5058e403558159a0ace 100644 GIT binary patch delta 863 zcmZ|NUr19?90%~!ApO2!dX$zIRUOr3+uq=XcNHoOACvsd#HD z-Z~eN+4l!))1!CNaxyKmXATxfjBH^yn|7Qz-4hK(q6fog+X;_#iWre(lJ?N2T1!dW zR(8Cxsh_0b7P`P0^>STX&P5jUWusKqDj`7EIx>Z<@h&m^+IHANbZLIP`kW<|7M8!V zZ+m@}jp>MfC$P%EMrE$TP2QVdn+~!GWyXwzSP&~>L+rE4j3eIkNHVw3&n@)A|KBYn zv4vaA)l8|u1M$x8Yl$xlwq9mUC|%A!7BBbXN31iRP*S$1v4@gf+?Pn5lt@fSK5ql#>`>NOJ)-@@M9KpiYew5ldM5Jp@4`ZqvRHsDJVur5<}z{gJcy0 zWTAYnauVlM$Q3fBe%t|^d9_$B>BT6Q%wkd3x^XVhTT@n3g<>|uZB(gNYOrohGy8^y-_HPVTA=DeA=@?xx!1%4Ld$lBS2ar(S1Q!d$MqR5Y~ZY_5+t zY<6NET{EKGTYr(xp5nfLI?Y8m8M%sieT-eD^m2szsaDh+*zBu)SrB)!oy{s^_P~VF P=0seG8}ZC4ZF1LN*ego; delta 153 zcmX@mV056tXhSg1 chr break @@ -391,7 +391,7 @@ end def strtonum(strptr) word num, i byte c - + num = 0 for i = 1 to ^strptr c = ^(strptr + i) & $7F @@ -438,9 +438,8 @@ def readtxt(filename, startline)#0 putln end def writetxt(filename)#0 - word i, strptr - byte refnum, j, chr - byte txtbuf[MAXLNLEN+2] + word i + byte refnum, txtbuf[MAXLNLEN+2] fileio:destroy(filename) fileio:create(filename, $04, $00) // full access, TXT file @@ -558,7 +557,7 @@ end def drawscrn(toprow, ofst)#0 byte row, numchars, lofst word strptr, scrnptr - + lofst = flags & gutter if lofst drawgutter(toprow, ofst) @@ -598,7 +597,7 @@ def drawscrn(toprow, ofst)#0 end def cursoff#0 word scrnptr - + if flags & showcurs ^cursptr = underchr if flags & gutter @@ -607,13 +606,13 @@ def cursoff#0 ^(scrnptr+2) = ^(scrnptr+2) | $80 fin flags = flags & ~showcurs - + fin end def curson#0 byte lofst word scrnptr - + if !(flags & showcurs) lofst = flags & gutter if lofst @@ -644,7 +643,7 @@ def redraw#0 end def curshpos(hpos)#1 byte needredraw - + needredraw = TRUE if hpos < 0; hpos = 0; fin if hpos > MAXLNLEN; hpos = MAXLNLEN; fin @@ -777,7 +776,7 @@ def cursleft#0 end def pgleft#0 word i, strptr - + strptr = txtlinbuf=>[cursrow] if curscol > ^strptr i = ^strptr @@ -818,7 +817,7 @@ def cursright#0 end def pgright#0 word i, strptr - + strptr = txtlinbuf=>[cursrow] if curscol >= ^strptr i = curscol + 8 @@ -849,7 +848,7 @@ end // def findline(strptr, start)#1 byte scan, i, upstr[MAXLNLEN+1] - + if ^strptr >= findstr lnupcpy(@upstr, strptr) for scan = start to upstr - findstr + 1 @@ -1098,7 +1097,7 @@ def printtxt(slot)#0 end def freesel#0 word i - + for i = 0 to numcliplines - 1 if cliplinbuf=>[i] <> @nullstr delstr(cliplinbuf=>[i]) @@ -1109,7 +1108,7 @@ def freesel#0 end def selrange#2 word first, last - + if flags & selection if cursrow > selrow first, last = selrow, cursrow @@ -1129,7 +1128,7 @@ def beginsel#0 end def copysel#0 word firstsel, lastsel - + freesel firstsel, lastsel = selrange for numcliplines = 0 to lastsel - firstsel @@ -1140,7 +1139,7 @@ def copysel#0 end def cutsel#0 word firstsel, lastsel - + freesel firstsel, lastsel = selrange if lastsel - firstsel < MAXCLIPLINES @@ -1169,7 +1168,7 @@ def cutsel#0 end def pastesel#0 word p - + if numcliplines and numcliplines + numlines < MAXLINES memcpy(@txtlinbuf=>[cursrow + numcliplines], @txtlinbuf=>[cursrow], (numlines - cursrow) * 2) for p = 0 to numcliplines - 1 @@ -1185,7 +1184,7 @@ end def indentsel#0 byte indentstr[MAXLNLEN+1], l word firstsel, lastsel, i - + freesel firstsel, lastsel = selrange for i = firstsel to lastsel @@ -1205,7 +1204,7 @@ end def undentsel#0 byte undentstr[MAXLNLEN+1], l word firstsel, lastsel, i - + freesel firstsel, lastsel = selrange for i = firstsel to lastsel @@ -1230,12 +1229,12 @@ def undentsel#0 end def autoindent(strptr)#0 byte i - + for i = 1 to ^strptr if ^(strptr + i) <> keyspace break fin - next + next curshpos(i - 1) end def openline(row) @@ -1289,7 +1288,7 @@ def splitline#0 memcpy(@splitstr + 2, @splitstr + 1, splitstr) splitstr[1] = keyspace splitstr++ - next + next txtlinbuf=>[cursrow + 1] = newstr(@splitstr) splitstr = curscol memcpy(@splitstr + 1, txtlinbuf=>[cursrow] + 1, splitstr) @@ -1303,7 +1302,7 @@ def splitline#0 break fin next - curshpos(curscol - 1) + curshpos(curscol - 1) fin fin else From 484aefb08c3b45126c36820317e0a9bd0011955a Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Tue, 31 Dec 2019 07:53:41 -0800 Subject: [PATCH 104/149] More error reporting when writing files --- images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes src/toolsrc/ed.pla | 28 +++++++++++++++++++--------- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/images/apple/PLASMA2-SYS.PO b/images/apple/PLASMA2-SYS.PO index 03da6f5df895c7c12e7fd9af4594152f9f6660ec..f25a27a4ca1c7cb9c6712911de00a154f2892177 100755 GIT binary patch delta 5075 zcma*q3w(}cAHebJy7z3)j`ln|J)ZOIWEgF-NVJdBUS%)$bQ?zFoo!|gLvu)Y+%HPC zmu}Ic99l@uMVP~zRI&;wB?)CsN`#73iud=d`qbN}KDE!j_x->A*Wo@~*L8ok8K**L z@ViA0PqEx_lL-7Ii-yLtsGXD|AIysIc$HEi7hAiF#kCOyGBZ>ukp99VndI+WByB!Z z?>3@MXjG5!<15D}rf5Qx3&F8Xcw*()(lH~(4DXmou`H0|x3Hk1!7^9W{7Z~c(t|55 zT6QYMTB^0glpazNToES_Bg$1=ci{vROx798lD(A>1_4bNjYsGgK&1%<@9saCh zxm(uzFBMC7Xk%uuR_~7=CUY%6l`5oFbkDn8kR3TprsZ$5sZ9jQ>Ax9-E_PBKEt=h# zN9`|FYOE-)w{)`PMf{T6X5*TJX&ZQHxp`dz!+tzWHdh(e5*W6l?GFa-@V5uPX5nTt z1EUTskVI@nq48+%XR*?BjwoGbq+OHXp60d%7FgAblEym4vkvp zDD3}hDruCQPM4=f$uu7AwNY|Dr$M7-rP43ee_*uSKyk_#na%0BF;Z0uoBNeY*-vGG zT(z+3(nGW%fi;j=6|5>U-JDTV)3OiiJKbESRF^431DmSeUSj(FR7HvZ@9%%6Ql_Ud z>NU&UzifM@Qs%J$Xj}bPZ5!`PRNSx>Obkp3w?BET>~gown;FPyGn@BaEw#^`>NTkq zxzsCCd*7vAl-g{!dRA&Txzq-!t#PR*r55d0k4o(oxB9l!COOspQd{CwUzOU*B=tq9 zy^y5tkXmrE`n=Tk`V+>7My>h#pTyOb#|F9(*XGEP4xE8BM>zA6zDbE^MIRtZ; z6>F_iRWq+_mm^bS27AfCepB*7h1M%g4G(On>c(CdExV;P(7G{WcQ&?mOYMo&K({!$ zMFjd~2`xK?MZag9jB_%k8X36M&s~`{^`y|22O3-)C*x!Ppn=~uUbar*Z83@3%NgaT zEWMiszMn0>N{JHXaUvlt+^Pkt*VUGfmq(=1&F0UklG#mjGno0l?PQr8ninq8R7)8T zZPhmTtE*&r7*{F_nj6?4KUPVbGAqNMFhO=#`nB>8o*=5iYp{&C$*quU|geCYKH@SpTgf(~{(Qcv4#w*D22xS9oUZG@TAZFs;M4^0& zea(b&8Cgj}DNhnzm6Zf9AUIhldy$=xC1pAAD(6$BnRzk_m5WF6t zyj=U_B)L}l^qdf(cSA0EBOm=kgfTS4YmC5H%nUIZ_lG1J4~B#pi-?z^CL~CInzoxz zOZz>vdx!jcv^z$-&xpUkrH~-w3Uwi7#ju*aMv~cNq?!|rbaR-|-t03Ook--EgN*KG zY4oPiAal4r%q;W~cnAh+%)(e@wi=twF~&i&%{Xed=?&z+z-3&AIaKHt*pZI-Frg;Z}4) z0S00SicyLY7==pQgUOhN*?1Vfxf~W^DQd71tFa!>Vl%d4J3hck)Z;YH;R3$IWqgb4 zFh>YI98t(XJ9I)0x}i7nQ4k?~`e1@mlw%|&V=87~7UrNDkKj=}hR3lKHCTfU*o>{% zi9OhhI_$?Gyn~}Sjt^0f(-A(Qe@bu;U*j8mj~@{nDfBQzA`Uh@ zx1$TX<4*KNKMcSi3_&p}Fxtmq9I7x4I%c67^DrNauoN{|fmK+G4cLtB*oEELivu`> z!#ILtsK;r1hI9BDSK<4SgNPD(5JC`!NW>xmF7&}b6rlveQGv0TjQcPhI_}3j%*SJR z980hQ&tLR1Jpl+ zM=;I8YsC*xth@=UFzT#QKSX>O@8dWw;7f$Yu%_Vf#R$V2V=|Irg7j<>Ip~32$cKjh zD8VRHVG^c8$HSP5MR*$Puo0WE1-00Tm#`P_;wVm_9=_8YKE(xmg>P{U*CAtB4~RrM zS|JnJ=ztt_Lr?UH6~=(r7<~|N5sFcYa*V}2&@l@SV;<(mGXDz+mf%S&$J1DY_1J`3 z?8F|thBxsxj^jhr;}d*_bGX2bT;@iu63aL~MhHg~9B?BM$w-fL@>B#_xD}m{hvGP4 zjP%#}q}R8K;u`Eg9qG5?VvKrRi;L0C@r;WY#KVb1w1A3%7={W|#tUOoe2hMYcp7Hn z0X&3xScqkK3hS^Do8x&wwFEn{2d^;5eg-*A+(3MZ_$u-DxQ?I%)-A#i1q%{jhZ~7V zMmky{3+)nw(J>)L?@Zhk|3Dwyg@FldkRb%c7=a0xh8dVe$A{=>5HG+|)R5as?seh= zID{iOfsd#=L)}^8^SFd7_!ifo*!al80XLc<)5oD5Iv@vKk&8Rf2Yt~G4`Ln`z;6@A zYMa$~-WH>8r@RZV<4qi)?il$~#0@xubGShMI(@>L#^{kvg>HonJ_iRkl97g1XoL3X zf}Z$iQ(@%OaRBik3_&T%F%siYg?lj-^RWVJ@hp9xr|%Bpm#`0S;2_>^%KRTC_y8x- zfHOFU3%H6K2)7G88ga101uxRk$}WtX?b5i7I0s#ki#wsB0E1DCa*RP0reKDh`M;l_ z8uPIT%dis9U?aBUzjzTZqYiK2Al|}zIDwDwG0xyTF5(J)fN-#I(FAd53KzUS4*X%O zr=caID?G)oK1{>Q=a2YH0EL{@mcDw zIu#?*r5LxkyhdkNw9&;Cr02VYQQ?Zwr@Od8;=Pr|e ziSySklku&~tp7+X-0^y(o0W?=w=j|^w;*nV4(N;?xDzS{pa@l%hFPe_Jj{n5OWn-> z3W8NwhmF{bt=NS+9KazQ#t|Gx12=Hq?bSm)%qgsJAqlByi_soojQ1$U1W%AL*^_9@ z@tBNxrNBxQ)#okG_@icD#s}$-nA})nDg)z+=)6 zk$VU4Q9ef76T~0k49?;_zQ$EtgY*jBga|Z&6>;F7Azg8J{rfk|*4Dc$X7SdMcf0Z@ TKBu0Ru-fCZWiPpEj$Hje)FX5i delta 4955 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 I<3hRlzwupEW&i*H diff --git a/images/apple/PLASMA2.2mg b/images/apple/PLASMA2.2mg index c996d54cc7f0d7e0dd8cb5058e403558159a0ace..6b8893638ecf52a7ea09c955ece2f97f17610f6a 100644 GIT binary patch delta 5171 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 KJ|`2eE&3-2CbBjF delta 5348 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 diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index 1968c90..f4b4738 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -441,25 +441,35 @@ def writetxt(filename)#0 word i byte refnum, txtbuf[MAXLNLEN+2] - fileio:destroy(filename) - fileio:create(filename, $04, $00) // full access, TXT file - refnum = fileio:open(filename) - if refnum == 0 - return - fin // // Remove blank lines at end of text. // while numlines > 1 and txtlinbuf=>[numlines - 1] == @nullstr; numlines--; loop // - // Write all the text line to the file. + // Delete old file and re-create + // + fileio:destroy(filename) + fileio:create(filename, $04, $00) // full access, TXT file + refnum = fileio:open(filename) + if refnum == 0 + puts("\nError $"); puth(perr); puts(" opening: "); puts(filename); putln + return + fin + // + // Write all the text lines to the file. // for i = 0 to numlines - 1 lncpy(@txtbuf, txtlinbuf=>[i]) - fileio:write(refnum, @txtbuf + 1, txtbuf) + if fileio:write(refnum, @txtbuf + 1, txtbuf) <> txtbuf + puts("\nError $"); puth(perr); puts(" writing: "); puts(filename); putln + fileio:close(refnum) + return + fin if !(i & $0F); putc('.'); fin next - fileio:close(refnum) + if fileio:close(refnum) <> FILE_ERR_OK + puts("\nError $"); puth(perr); puts(" closing: "); puts(filename) + fin putln end // From 81ad97e0bd543fa4c31bc0654c31bccfb3c5e3db Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Tue, 31 Dec 2019 08:04:48 -0800 Subject: [PATCH 105/149] Fix HGRTEST.PLA sample --- images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/images/apple/PLASMA2.2mg b/images/apple/PLASMA2.2mg index 6b8893638ecf52a7ea09c955ece2f97f17610f6a..214c4397b046bdaec9432b1d21224224e50d4736 100644 GIT binary patch delta 1916 zcmah}O-~b16zvp{svTv4F>c6B#AKQlnJLhZL`b0;!9YTU7!y*HmcGK2X=gGs71%f! z7i>+M$WL(Vu3Hj+fN|$i_bgO2Y*={jdmV;Kn>Kwjciuhk-1E-+I6g=oA0$7$i8kLu zUXq$$qv_`N=00Pl)Us&t&A+MH?K;b{C32tmy8nf7RU|UhUu}O(@DUZC0yDzf9bzDB+oE`axOa$KQ81u#UIAXgR5}K6 z$l~(>`ataT!^#{xK>=Y4?L^h*z<~E7MKVhiGgCyNae+jEA_WBn0foOldR;#94C$Un zn}G!Lz0g%K*Af?+e0>!$n@2D)1GJl{)*K`=(`~?iQ}E?iuq=rqKe@W9NAI{$8<6v? zPtHH)a1W*~$U7!?l^my`yKL2Tmg;4;M}8M@3-ITT*kElN06c+xY!`R&ye#XEs|ZBU zztE^Cc!1V+i z(v{XRFxds+bwZ}PKspiAeGzDs5ZhBoDnNKWw59_{4@9Of0x!;PLNZdAg+hgqaOmgA z=fjng0c?ZVhOk|0t(**>PI{N@rnT=za~aa#d##)Koz7~3`9`lL)cV`6_41!KCtcNA kDkg6+cT;xvTsl21=|}jEbeJ29V7rd(2DY0Yb7RrcKQ4enqW}N^ delta 1635 zcmWmD4@}f$9LMqJcfTJT$dPhz+;P9V-(BItG5)0%O&I?|Kx8CDlVT%IV{;CtW%g%I zjwcGnBH07#-EbBgE2DHd=DbZMS)sL@mF4E2WszrJ7liSH1 zzKhDZf1zEoG09c&C3e|2bLfe8L*J+6>5c7 zQ$^%bRGB89`?CZo=;aRe7Y>6evbKeo|}Az z+Tydz7s)$(E-8JyxagyfQolnU#bJ!&I8KEbPU9TD!wlwe2b!P15$tfl2@gyJk%=s1 zqX5MyM!S50aN!ewAfeGMhRVD^bY&Dl1i%@GQ3sS;<@t)>7BAwt?J)7PML- zUxo;q(1C4u8Ly!W-RMCd`Y~Wdl6D!nk(`h{DfZ_zy;d8#HGCyfwn~rht(wzeAP(`d zsyX}Jd`Hw~YcCMbEYZb>DUrH7tu7Wl8CRnv=7`C*?5?W%t&v|Q;@0<;SqVtQA|xFw Ivm6`#15$m Date: Tue, 31 Dec 2019 13:19:42 -0800 Subject: [PATCH 106/149] notes on IIc VBL --- src/libsrc/apple/dgrlib.pla | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/libsrc/apple/dgrlib.pla b/src/libsrc/apple/dgrlib.pla index 0eccee4..f502a5b 100755 --- a/src/libsrc/apple/dgrlib.pla +++ b/src/libsrc/apple/dgrlib.pla @@ -494,7 +494,7 @@ asm _dgrFillTile RTS end // -// Wait for VLB - Shouldn't work on //c, but seems to. +// Wait for VLB - Only IIe/IIGS. // asm vlbWait#0 - LDA $C019 @@ -503,6 +503,30 @@ asm vlbWait#0 BPL - RTS end +// Wait for VBL on IIc is entirely different from others. +// Setup, one-time *only* if polling will be used exclusively. +// Otherwise requires restoring the mode on exit, +// and setting up per-use instead. +// [php] +// sei ; otherwise interrupt is still raised +// sta $C07F ; enable access to VBL register +// sta $C05B ; enable VBL polling +// sta $C07E ; disable access to VBL register +// +// wait for VBL: +// - bit $C019 +// bpl - +// lda $C070 ; $c019 bit 7 is sticky, reset it +// +// To allow other methods of VBL, restore access: +// - bit $C019 +// bpl - +// lda $C070 ; $c019 bit 7 is sticky, reset it +// sta $C07F ; enable access to VBL register +// sta $C05A ; disable VBL polling +// sta $C07E ; disable access to VBL register +// [plp] + // // Clear the buffer // From 397dbdbb999d099283f795f315ea3bc49374c896 Mon Sep 17 00:00:00 2001 From: Peter Ferrie Date: Tue, 31 Dec 2019 13:21:14 -0800 Subject: [PATCH 107/149] cut some bytes --- src/libsrc/apple/dgrlib.pla | 10 ++++------ src/libsrc/apple/mouse.pla | 3 +-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/libsrc/apple/dgrlib.pla b/src/libsrc/apple/dgrlib.pla index f502a5b..1937ee7 100755 --- a/src/libsrc/apple/dgrlib.pla +++ b/src/libsrc/apple/dgrlib.pla @@ -196,9 +196,8 @@ export asm dgrBLT(x, y, width, height, src)#0 CLC ADC ESTKL+2,X ; WIDTH STA SRCL - LDA SRCH - ADC #$00 - STA SRCH + BCC +++ + INC SRCH BNE +++ + AND #$FE TAY @@ -356,9 +355,8 @@ export asm dgrTile(x, y, src)#0 LDA SRCL ; SKIP TO NEXT ROW ADC #$07 ; CARRY = 1 STA SRCL - LDA SRCH - ADC #$00 - STA SRCH + BCC +++ + INC SRCH BNE +++ + AND #$FE TAY diff --git a/src/libsrc/apple/mouse.pla b/src/libsrc/apple/mouse.pla index 6d5193d..5472b8d 100644 --- a/src/libsrc/apple/mouse.pla +++ b/src/libsrc/apple/mouse.pla @@ -270,7 +270,7 @@ CHKSIG: LDY #$05 LDA (TMPTR),Y CMP #$01 BNE :+ - LDY #$0C + INY TXA ; LOOK FOR MATCHING ID CMP (TMPTR),Y BNE :+ @@ -283,7 +283,6 @@ CHKSIG: LDY #$05 LDA TMPTR+1 CMP #$C8 BCC CHKSIG - SEC RTS ;* From 438ab01254d9d05ef8d429487b6cf7c117092737 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Tue, 31 Dec 2019 17:20:20 -0800 Subject: [PATCH 108/149] Wildcard filename matching --- src/inc/match.plh | 5 + src/libsrc/apple/hgrsprite.pla | 21 ++-- src/libsrc/lines.pla | 202 +++++++++++++++++---------------- src/libsrc/match.pla | 144 +++++++++++++++++++++++ src/makefile | 7 +- src/mkrel | 2 + src/tftpbld | 1 + src/tftpsys | 1 + src/utilsrc/apple/cat.pla | 179 +++++++++++++++-------------- 9 files changed, 366 insertions(+), 196 deletions(-) create mode 100644 src/inc/match.plh create mode 100644 src/libsrc/match.pla diff --git a/src/inc/match.plh b/src/inc/match.plh new file mode 100644 index 0000000..57b61ee --- /dev/null +++ b/src/inc/match.plh @@ -0,0 +1,5 @@ +import match + predef matchName(src, exp)#1 + predef matchList(pathptr, exp)#2 + predef isWildName(exp)#1 +end diff --git a/src/libsrc/apple/hgrsprite.pla b/src/libsrc/apple/hgrsprite.pla index 5f60ee1..84f2980 100644 --- a/src/libsrc/apple/hgrsprite.pla +++ b/src/libsrc/apple/hgrsprite.pla @@ -107,8 +107,10 @@ BLTDONE INX end def spriteBLTMask(x, y, w, h, srcptr)#0 word i, j - byte c + byte pitch +// byte c + pitch = (w + 1) / 2 for j = y to y + h - 1 scanMask(x, j, w, srcptr) // for i = 0 to w - 1 @@ -120,7 +122,7 @@ def spriteBLTMask(x, y, w, h, srcptr)#0 // fin // hgrPlot(x + i, j) // next - srcptr = srcptr + (w + 1) / 2 + srcptr = srcptr + pitch next end export def spriteCompile(w, h, xcenter, ycenter, srcptr)#1 @@ -154,20 +156,11 @@ export def spriteDup(sprtsrc)#1 var sprtdup, spritesize byte i - sprtdup = heapalloc(t_sprite) - spritesize = sprtsrc=>s_size - sprtdup=>s_size = spritesize - sprtdup->s_pitch = sprtsrc->s_pitch - sprtdup->s_height = sprtsrc->s_height - sprtdup->s_height = sprtsrc->s_height - sprtdup->s_xcenter = sprtsrc->s_xcenter - sprtdup->s_ycenter = sprtsrc->s_ycenter + sprtdup = heapalloc(t_sprite) + memcpy(sprtdup, sprtsrc, t_sprite) + spritesize = sprtdup=>s_size sprtdup=>s_under[0] = heapalloc(spritesize) sprtdup=>s_under[1] = heapalloc(spritesize) - for i = 0 to 13 - sprtdup=>s_map[i] = sprtsrc=>s_map[i] - sprtdup=>s_mask[i] = sprtsrc=>s_mask[i] - next return sprtdup end export def spriteRead(filestr)#1 diff --git a/src/libsrc/lines.pla b/src/libsrc/lines.pla index eec08c9..39750b7 100644 --- a/src/libsrc/lines.pla +++ b/src/libsrc/lines.pla @@ -10,7 +10,7 @@ var err, shorterr, shortlen, longerr, longlen //def nopLin(a, b, c)#0 //end -//def majorline(majorstart, major, majorend, minor, dir, majorspan)#0 +//def majorspans(majorstart, major, majorend, minor, dir, majorspan)#0 // // // // Initial half-span step // // @@ -32,7 +32,7 @@ var err, shorterr, shortlen, longerr, longlen // // // majorspan(majorstart, majorend, minor)#0 //end -asm majorline(majorstart, major, majorend, minor, dir, majorspan)#0 +asm majorspans(majorstart, major, majorend, minor, dir, majorspan)#0 !SOURCE "vmsrc/plvmzp.inc" LDA $1000 ; ERRL CLC @@ -48,7 +48,7 @@ asm majorline(majorstart, major, majorend, minor, dir, majorspan)#0 STA $A001 STA $B001 end -asm _majorlineA +asm _majorspansA - DEX DEX DEX @@ -82,11 +82,11 @@ asm _majorlineA ADC #$00 STA ESTKH+5,X ; MAJORSTARTH end -asm _majorlineB +asm _majorspansB LDY $1001 ; ERRH BMI + end -asm _majorlineC +asm _majorspansC LDA $1000 ; ERRL CLC ADC $2000 ; SHORTERRL @@ -101,10 +101,14 @@ asm _majorlineC LDA ESTKH+4,X ; MAJORH ADC $3001 ; SHORTLENH STA ESTKH+4,X - BCC ++ + LDA ESTKL+4,X ; MAJORL + CMP ESTKL+3,X ; MAJORENDL + LDA ESTKH+4,X ; MAJORH + SBC ESTKH+3,X ; MAJORENDH + BCC - BCS ++ end -asm _majorlineD +asm _majorspansD + LDA $1000 ; ERRL CLC ADC $4000 ; LONGERRL @@ -119,16 +123,15 @@ asm _majorlineD LDA ESTKH+4,X ; MAJORH ADC $5001 ; LONGLENH STA ESTKH+4,X - -++ LDA ESTKL+4,X ; MAJORL + LDA ESTKL+4,X ; MAJORL CMP ESTKL+3,X ; MAJORENDL LDA ESTKH+4,X ; MAJORH SBC ESTKH+3,X ; MAJORENDH - BCS + + BCS ++ end -asm _majorlineE +asm _majorspansE JMP $6000 -+ DEX +++ DEX DEX DEX LDA ESTKL+8,X ; MAJORSTARTL @@ -335,6 +338,52 @@ export def setlinespans(h, v)#0 hspan = h vspan = v end +def hmajorspans(x1, y1, x2, y2, dx, dy, sy)#0 + var dy2, halflen, rem + // + // Half-span length and error + // + dy2 = dy * 2 + halflen, rem = divmod(dx, dy2) + err = dy2 - rem + // + // Long-span length = half-span length * 2 + // + longlen = (halflen + 1) * 2 + longerr = err * 2 + if longerr >= dy2 + longerr = longerr - dy2 + longlen-- + fin + // + // Short-span length = long-span length - 1 + // + shortlen = longlen - 1 + shorterr = longerr - dy2 + majorspans(x1, x1 + halflen, x2, y1, sy, hspan) +end +def vmajorspans(x1, y1, x2, y2, dx, dy, sx)#0 + var dx2, halflen, rem + + // + // Half-span length and error + // + dx2 = dx * 2 + halflen, rem = divmod(dy, dx2) + err = dx2 - rem + // + // Long-span length = half-span length * 2 + // + longlen = (halflen + 1) * 2 + longerr = err * 2 + if longerr >= dx2 + longerr = longerr - dx2 + longlen-- + fin + shortlen = longlen - 1 + shorterr = longerr - dx2 + majorspans(y1, y1 + halflen, y2, x1, sx, vspan) +end export def linespans(x1, y1, x2, y2)#0 var dx, dy, dx2, dy2, halflen, rem, sx, sy @@ -358,29 +407,9 @@ export def linespans(x1, y1, x2, y2)#0 hspan(x1, x2, y1)#0; return fin // - // Half-span length and error + // JIT optimize setup // - dy2 = dy * 2 - halflen, rem = divmod(dx, dy2) - err = dy2 - rem - // - // Long-span length = half-span length * 2 - // - longlen = (halflen + 1) * 2 - longerr = err * 2 - if longerr >= dy2 - longerr = longerr - dy2 - longlen-- - fin - // - // Short-span length = long-span length - 1 - // - shortlen = longlen - 1 - shorterr = longerr - dy2 - // - // JIT optimize inner loop - // - majorline(x1, x1 + halflen, x2, y1, sy, hspan) + hmajorspans(x1, y1, x2, y2, dx, dy, sy) else if sy < 0 x1, x2 = x2, x1 @@ -391,26 +420,9 @@ export def linespans(x1, y1, x2, y2)#0 vspan(y1, y2, x1)#0; return fin // - // Half-span length and error + // JIT optimize inner setup // - dx2 = dx * 2 - halflen, rem = divmod(dy, dx2) - err = dx2 - rem - // - // Long-span length = half-span length * 2 - // - longlen = (halflen + 1) * 2 - longerr = err * 2 - if longerr >= dx2 - longerr = longerr - dx2 - longlen-- - fin - shortlen = longlen - 1 - shorterr = longerr - dx2 - // - // JIT optimize inner loop - // - majorline(y1, y1 + halflen, y2, x1, sx, vspan) + vmajorspans(x1, y1, x2, y2, dx, dy, sx) fin end export def setlineplot(p)#0 @@ -449,46 +461,46 @@ export def line(x1, y1, x2, y2)#0 // // Assembly fixups // -majorline:1 = @err -majorline:5 = @shorterr -majorline:8 = @err -majorline:11 = @err.1 -majorline:14 = @shorterr.1 -majorline:17 = @err.1 -majorline:22 = @_majorlineA.28 -majorline:25 = @_majorlineE.31 -majorline:30 = @_majorlineA.29 -majorline:33 = @_majorlineE.32 -_majorlineB:1 = @err.1 -_majorlineC:1 = @err -_majorlineC:5 = @shorterr -_majorlineC:8 = @err -_majorlineC:12 = @shorterr.1 -_majorlineC:15 = @err.1 -_majorlineC:21 = @shortlen -_majorlineC:28 = @shortlen.1 -_majorlineD:1 = @err -_majorlineD:5 = @longerr -_majorlineD:8 = @err -_majorlineD:12 = @longerr.1 -_majorlineD:15 = @err.1 -_majorlineD:21 = @longlen -_majorlineD:28 = @longlen.1 -_majorlineE:1 = @_majorlineA -hline:16 = @err -hline:23 = @err.1 -_hlineA:1 = @jmpplot -_hlineA:4 = @err.1 -_hlineB:6 = @err -_hlineB:9 = @err -_hlineB:13 = @err.1 -_hlineB:16 = @err.1 -vline:16 = @err -vline:23 = @err.1 -_vlineA:1 = @jmpplot -_vlineA:4 = @err.1 -_vlineB:6 = @err -_vlineB:9 = @err -_vlineB:13 = @err.1 -_vlineB:16 = @err.1 +majorspans:1 = @err +majorspans:5 = @shorterr +majorspans:8 = @err +majorspans:11 = @err.1 +majorspans:14 = @shorterr.1 +majorspans:17 = @err.1 +majorspans:22 = @_majorspansA.28 +majorspans:25 = @_majorspansE.31 +majorspans:30 = @_majorspansA.29 +majorspans:33 = @_majorspansE.32 +_majorspansB:1 = @err.1 +_majorspansC:1 = @err +_majorspansC:5 = @shorterr +_majorspansC:8 = @err +_majorspansC:12 = @shorterr.1 +_majorspansC:15 = @err.1 +_majorspansC:21 = @shortlen +_majorspansC:28 = @shortlen.1 +_majorspansD:1 = @err +_majorspansD:5 = @longerr +_majorspansD:8 = @err +_majorspansD:12 = @longerr.1 +_majorspansD:15 = @err.1 +_majorspansD:21 = @longlen +_majorspansD:28 = @longlen.1 +_majorspansE:1 = @_majorspansA +hline:16 = @err +hline:23 = @err.1 +_hlineA:1 = @jmpplot +_hlineA:4 = @err.1 +_hlineB:6 = @err +_hlineB:9 = @err +_hlineB:13 = @err.1 +_hlineB:16 = @err.1 +vline:16 = @err +vline:23 = @err.1 +_vlineA:1 = @jmpplot +_vlineA:4 = @err.1 +_vlineB:6 = @err +_vlineB:9 = @err +_vlineB:13 = @err.1 +_vlineB:16 = @err.1 done diff --git a/src/libsrc/match.pla b/src/libsrc/match.pla new file mode 100644 index 0000000..5662ea4 --- /dev/null +++ b/src/libsrc/match.pla @@ -0,0 +1,144 @@ +include "inc/cmdsys.plh" +include "inc/fileio.plh" + +var dirbuf +// +// Copy string with upper case conversion +// +def cpyuprstr(dst, src)#0 + byte i, chr + + if ^src + for i = 1 to ^src + chr = src->[i] + if chr >= 'a' and chr <= 'z' + dst->[i] = chr - 'a' + 'A' + else + dst->[i] = chr + fin + next + fin + ^dst = ^src +end +// +// Match next section of source and expression +// +def matchNext(src, srcofst, exp, expofst) + if ^src >= srcofst and ^exp >= expofst + when exp->[expofst] + is '*' // Multi-char wildcard + if matchNext(src, srcofst + 1, exp, expofst + 1) + return TRUE + fin + return matchNext(src, srcofst + 1, exp, expofst) + is '?' // Single char wildcard + return matchNext(src, srcofst + 1, exp, expofst + 1) + otherwise // verbatim match + if src->[srcofst] == exp->[expofst] + return matchNext(src, srcofst + 1, exp, expofst + 1) + fin + return FALSE + wend + fin + return ^src < srcofst and ^exp < expofst // Return TRUE if at the end of both +end +// +// Start off matching process +// +export def matchName(src, exp)#1 + char matchSrc[16], matchExp[16] + + // + // Ensure valid filename lengths + // + if ^src > 15 or ^exp > 15 + return FALSE + fin + // + // Match on empty wildcard name (same as '*') + // + if not ^exp + return TRUE + fin + // + // Convert strings to upper case + // + cpyuprstr(@matchSrc, src) + cpyuprstr(@matchExp, exp) + return matchNext(@matchSrc, 1, @matchExp, 1) +end +export def matchList(pathstr, exp)#2 + byte refnum + var firstblk, entrylen, entriesblk, i, entry, filecnt, entrylist, entryptr, entrycnt + + if not dirbuf + dirbuf = heapallocalign(512, 8, 0) + fin + if pathstr->[^pathstr] <> '/' // Make sure path ends with a '/' + ^pathstr++ + pathstr->[^pathstr] = '/' + fin + entrylist = 0 + entrycnt = 0 + filecnt = 0 + firstblk = 1 + refnum = fileio:open(pathstr) + repeat + if fileio:read(refnum, dirbuf, 512) == 512 + // + // Skip block pointers + // + entry = dirbuf + 4 + if firstblk + // + // Pull out revelant details from the first block + // + entrylen = dirbuf->$23 + entriesblk = dirbuf->$24 + filecnt = dirbuf=>$25 + entry = entry + entrylen + fin + for i = firstblk to entriesblk + // + // Print directory entry details + // + ^entry = ^entry & $0F + if ^entry + // + // Match wildcard filename + // + if matchName(entry, exp) + entryptr = heapalloc(t_fileentry) + memcpy(entryptr, entry, t_fileentry) + entrycnt++ + if not entrylist + entrylist = entryptr + fin + fin + filecnt-- + fin + entry = entry + entrylen + next + firstblk = 0 + fin + until filecnt == 0 + fileio:close(refnum) + return entrylist, entrycnt +end +// +// Is this a wildcard name? +// +export def isWildName(exp)#1 + byte i + + if ^exp + for i = 1 to ^exp + if exp->[i] == '*' or exp->[i] == '?' + return TRUE + fin + next + fin + return FALSE +end +done + diff --git a/src/makefile b/src/makefile index 2220ef1..e96167e 100755 --- a/src/makefile +++ b/src/makefile @@ -29,6 +29,7 @@ TYPE = rel/apple/TYPE\#FE1000 SIEVE = rel/SIEVE\#FE1000 PRIMEGAP = rel/PRIMEGAP\#FE1000 ARGS = rel/ARGS\#FE1000 +MATCH = rel/MATCH\#FE1000 SPIPORT = rel/apple/SPIPORT\#FE1000 SDFAT = rel/apple/SDFAT\#FE1000 FATCAT = rel/apple/FATCAT\#FE1000 @@ -102,7 +103,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(MATCH) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -224,6 +225,10 @@ $(ED): toolsrc/ed.pla $(PLVM02) $(PLASM) toolsrc/ed.pla ./$(PLASM) -AMOW < toolsrc/ed.pla > toolsrc/ed.a acme --setpc 4094 -o $(ED) toolsrc/ed.a +$(MATCH): libsrc/match.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < libsrc/match.pla > libsrc/match.a + acme --setpc 4094 -o $(MATCH) libsrc/match.a + $(ARGS): libsrc/args.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/args.pla > libsrc/args.a acme --setpc 4094 -o $(ARGS) libsrc/args.a diff --git a/src/mkrel b/src/mkrel index cb084a0..3789c45 100755 --- a/src/mkrel +++ b/src/mkrel @@ -20,6 +20,7 @@ cp rel/apple/REN#FE1000 prodos/sys/REN.REL cp rel/apple/CAT#FE1000 prodos/sys/CAT.REL cp rel/apple/NEWDIR#FE1000 prodos/sys/NEWDIR.REL cp rel/apple/TYPE#FE1000 prodos/sys/TYPE.REL +cp rel/MATCH#FE1000 prodos/sys/MATCH.REL cp rel/ARGS#FE1000 prodos/sys/ARGS.REL cp rel/ED#FE1000 prodos/sys/ED.REL cp rel/FIBER#FE1000 prodos/sys/FIBER.REL @@ -152,6 +153,7 @@ cp samplesrc/lz4cat.pla prodos/bld/samples/Z4CAT.PLA.TXT mkdir prodos/bld/inc cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT +cp inc/match.plh prodos/bld/inc/MATCH.PLH.TXT cp inc/cmdsys.plh prodos/bld/inc/CMDSYS.PLH.TXT cp inc/conio.plh prodos/bld/inc/CONIO.PLH.TXT cp inc/lines.plh prodos/bld/inc/LINES.PLH.TXT diff --git a/src/tftpbld b/src/tftpbld index 5d40e6c..24e6c70 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -6,6 +6,7 @@ echo "BLD/CODEOPT"; atftp $1 --put -l rel/CODEOPT#FE1000 -r $2/BLD/CODEOPT#FE10 #Build incs echo "BLD/INC/ARGS.PLH"; atftp $1 --put -l inc/args.plh -r $2/BLD/INC/ARGS.PLH#040000 +echo "BLD/INC/MATCH.PLH"; atftp $1 --put -l inc/match.plh -r $2/BLD/INC/MATCH.PLH#040000 echo "BLD/INC/CMDSYS.PLH"; atftp $1 --put -l inc/cmdsys.plh -r $2/BLD/INC/CMDSYS.PLH#040000 echo "BLD/INC/CONIO.PLH"; atftp $1 --put -l inc/conio.plh -r $2/BLD/INC/CONIO.PLH#040000 echo "BLD/INC/LINES.PLH"; atftp $1 --put -l inc/lines.plh -r $2/BLD/INC/LINES.PLH#040000 diff --git a/src/tftpsys b/src/tftpsys index 8c986bb..c32e833 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -11,6 +11,7 @@ echo "SYS/JIT16"; atftp $1 --put -l rel/apple/JIT16#FE1000 -r $2/SYS/JIT16#F echo "SYS/JITUNE"; atftp $1 --put -l rel/apple/JITUNE#FE1000 -r $2/SYS/JITUNE#FE1000 # Core libraries +echo "SYS/MATCH"; atftp $1 --put -l rel/MATCH#FE1000 -r $2/SYS/MATCH#FE1000 echo "SYS/ARGS"; atftp $1 --put -l rel/ARGS#FE1000 -r $2/SYS/ARGS#FE1000 echo "SYS/INT32"; atftp $1 --put -l rel/INT32#FE1000 -r $2/SYS/INT32#FE1000 echo "SYS/DHCP"; atftp $1 --put -l rel/DHCP#FE1000 -r $2/SYS/DHCP#FE1000 diff --git a/src/utilsrc/apple/cat.pla b/src/utilsrc/apple/cat.pla index e5467ea..aa9a82a 100644 --- a/src/utilsrc/apple/cat.pla +++ b/src/utilsrc/apple/cat.pla @@ -1,11 +1,14 @@ include "inc/cmdsys.plh" +include "inc/longjmp.plh" include "inc/args.plh" +include "inc/match.plh" include "inc/fileio.plh" include "inc/int32.plh" -var arg, refnum, dirbuf -var page, firstblk, entrylen, entriesblk, i, entry, filecnt -char[64] path, filename +predef catalog(pathstr)#0 + +var arg, recurse, exit +char[64] path, wildname res[t_fileinfo] fileinfo res[t_fileentry] fileentry // @@ -82,91 +85,95 @@ def printentry(entryptr)#0 puts(@eofstr) putln end -// -// Check arguments and file types -// -arg = argNext(argFirst) -if ^arg - strcpy(@path, arg) - strupper(@path) -else - fileio:getpfx(@path) -fin -// -// Check if file exists -// -if fileio:getfileinfo(@path, @fileinfo) == FILE_ERR_OK +def printentries(pathstr, entries, num)#0 + byte page + page = 20 + puts(pathstr); putln puts("=NAME==========TYPE===AUX====LENGTH=\n") - // - // Check if cataloging a directory - // - if fileinfo.file_type == $0F - fileio:iobufalloc(2) // Reserve two I/O buffers - if path[path] <> '/' // Make sure path ends with a '/' - path++ - path[path] = '/' - fin - page = 21 - filecnt = 0 - firstblk = 1 - dirbuf = heapallocalign(512, 8, 0) - refnum = fileio:open(@path) - repeat - if fileio:read(refnum, dirbuf, 512) == 512 - // - // Skip block pointers - // - entry = dirbuf + 4 - if firstblk - // - // Pull out revelant details from the first block - // - entrylen = dirbuf->$23 - entriesblk = dirbuf->$24 - filecnt = dirbuf=>$25 - entry = entry + entrylen - fin - for i = firstblk to entriesblk - // - // Print directory entry details - // - ^entry = ^entry & $0F - if ^entry - printentry(entry) - filecnt-- - // - // Pause display every screenfull - // - if not page - getc - page = 22 - else - page-- - fin - fin - entry = entry + entrylen - next - firstblk = 0 + repeat + printentry(entries) + entries = entries + t_fileentry + // + // Pause display every screenfull + // + if not page + if toupper(getc()) == 'Q' + throw(exit, TRUE) fin - until filecnt == 0 - else - // - // Create file entry from file info - // - filefrompath(@fileentry, @path) - fileentry.entry_access = fileinfo.file_access - fileentry.entry_type = fileinfo.file_type - fileentry:entry_create:0 = fileinfo:create_date - fileentry:entry_create:2 = fileinfo:create_time - fileentry:entry_aux = fileinfo:aux_type - fileentry:entry_mod:0 = fileinfo:mod_date - fileentry:entry_mod:2 = fileinfo:mod_time - refnum = fileio:open(@path) - fileentry:entry_EOFL, fileentry.entry_EOFH = fileio:geteof(refnum)#2 - printentry(@fileentry) + page = 22 + else + page-- + fin + num-- + until not num +end +def catalog(pathstr)#0 + char recursepath[64] + var entrylist, entryptr, entrycnt + + entrylist, entrycnt = matchList(pathstr, @wildname) + if entrylist + printentries(pathstr, entrylist, entrycnt) + if recurse + entryptr = entrylist + repeat + if entryptr->entry_type == $0F + // + // A directory, so recurse + // + strcpy(@recursepath, pathstr) + strcat(@recursepath, entryptr) + recursepath++ + recursepath[recursepath] = '/' + if toupper(getc()) == 'Q' + throw(exit, TRUE) + fin + catalog(@recursepath) + fin + entryptr = entryptr + t_fileentry + entrycnt-- + until not entrycnt + fin + heaprelease(entrylist) + fin +end +// +// Install error exit +// +exit = heapalloc(t_except) +if not except(exit) + // + // Check arguments and file types + // + arg = argNext(argFirst) + if ^arg and arg->[1] == '-' + if ^arg > 1 and toupper(arg->[2]) == 'R' + recurse = TRUE + fin + arg = argNext(arg) + fin + recurse = TRUE + if ^arg + strcpy(@path, arg) + strupper(@path) + // + // Check if cataloging a directory + // + if fileio:getfileinfo(@path, @fileinfo) <> FILE_ERR_OK or fileinfo.file_type <> $0F + filefrompath(@wildname, @path) + fin + path = path - wildname + fin + if not path + fileio:getpfx(@path) + fin + // + // Check if directory exists + // + if fileio:getfileinfo(@path, @fileinfo) == FILE_ERR_OK + catalog(@path) + else + puts("Unable to open: "); puts(@path); putln fin - fileio:close(0) -else - puts("Unable to open: "); puts(@path); putln fin done From 7c3dfe2b2ec169f2ff14f4c48aff829a31324534 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Wed, 1 Jan 2020 13:50:57 -0800 Subject: [PATCH 109/149] Wildcard names for file utilities --- src/inc/{match.plh => matchfiles.plh} | 2 +- .../{match.pla => apple/matchfiles.pla} | 38 +-- src/makefile | 10 +- src/mkrel | 4 +- src/tftpbld | 2 +- src/tftpsys | 2 +- src/utilsrc/apple/cat.pla | 25 +- src/utilsrc/apple/copy.pla | 263 +++++++++++------- src/utilsrc/apple/del.pla | 160 +++++++++-- 9 files changed, 333 insertions(+), 173 deletions(-) rename src/inc/{match.plh => matchfiles.plh} (85%) rename src/libsrc/{match.pla => apple/matchfiles.pla} (82%) diff --git a/src/inc/match.plh b/src/inc/matchfiles.plh similarity index 85% rename from src/inc/match.plh rename to src/inc/matchfiles.plh index 57b61ee..9c571d4 100644 --- a/src/inc/match.plh +++ b/src/inc/matchfiles.plh @@ -1,4 +1,4 @@ -import match +import matchfiles predef matchName(src, exp)#1 predef matchList(pathptr, exp)#2 predef isWildName(exp)#1 diff --git a/src/libsrc/match.pla b/src/libsrc/apple/matchfiles.pla similarity index 82% rename from src/libsrc/match.pla rename to src/libsrc/apple/matchfiles.pla index 5662ea4..c14fd7a 100644 --- a/src/libsrc/match.pla +++ b/src/libsrc/apple/matchfiles.pla @@ -3,24 +3,6 @@ include "inc/fileio.plh" var dirbuf // -// Copy string with upper case conversion -// -def cpyuprstr(dst, src)#0 - byte i, chr - - if ^src - for i = 1 to ^src - chr = src->[i] - if chr >= 'a' and chr <= 'z' - dst->[i] = chr - 'a' + 'A' - else - dst->[i] = chr - fin - next - fin - ^dst = ^src -end -// // Match next section of source and expression // def matchNext(src, srcofst, exp, expofst) @@ -46,34 +28,26 @@ end // Start off matching process // export def matchName(src, exp)#1 - char matchSrc[16], matchExp[16] - - // - // Ensure valid filename lengths - // - if ^src > 15 or ^exp > 15 - return FALSE - fin // // Match on empty wildcard name (same as '*') // if not ^exp return TRUE fin - // - // Convert strings to upper case - // - cpyuprstr(@matchSrc, src) - cpyuprstr(@matchExp, exp) - return matchNext(@matchSrc, 1, @matchExp, 1) + return matchNext(src, 1, exp, 1) end export def matchList(pathstr, exp)#2 byte refnum + char[64] curpath var firstblk, entrylen, entriesblk, i, entry, filecnt, entrylist, entryptr, entrycnt if not dirbuf dirbuf = heapallocalign(512, 8, 0) fin + if not ^pathstr + fileio:getpfx(@curpath) + pathstr = @curpath + fin if pathstr->[^pathstr] <> '/' // Make sure path ends with a '/' ^pathstr++ pathstr->[^pathstr] = '/' diff --git a/src/makefile b/src/makefile index e96167e..5bda359 100755 --- a/src/makefile +++ b/src/makefile @@ -29,7 +29,7 @@ TYPE = rel/apple/TYPE\#FE1000 SIEVE = rel/SIEVE\#FE1000 PRIMEGAP = rel/PRIMEGAP\#FE1000 ARGS = rel/ARGS\#FE1000 -MATCH = rel/MATCH\#FE1000 +MATCHFILES = rel/apple/MATCHFILES\#FE1000 SPIPORT = rel/apple/SPIPORT\#FE1000 SDFAT = rel/apple/SDFAT\#FE1000 FATCAT = rel/apple/FATCAT\#FE1000 @@ -103,7 +103,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(MATCH) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(MATCHFILES) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -225,9 +225,9 @@ $(ED): toolsrc/ed.pla $(PLVM02) $(PLASM) toolsrc/ed.pla ./$(PLASM) -AMOW < toolsrc/ed.pla > toolsrc/ed.a acme --setpc 4094 -o $(ED) toolsrc/ed.a -$(MATCH): libsrc/match.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AMOW < libsrc/match.pla > libsrc/match.a - acme --setpc 4094 -o $(MATCH) libsrc/match.a +$(MATCHFILES): libsrc/apple/matchfiles.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < libsrc/apple/matchfiles.pla > libsrc/apple/matchfiles.a + acme --setpc 4094 -o $(MATCHFILES) libsrc/apple/matchfiles.a $(ARGS): libsrc/args.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/args.pla > libsrc/args.a diff --git a/src/mkrel b/src/mkrel index 3789c45..48f9f7a 100755 --- a/src/mkrel +++ b/src/mkrel @@ -20,7 +20,7 @@ cp rel/apple/REN#FE1000 prodos/sys/REN.REL cp rel/apple/CAT#FE1000 prodos/sys/CAT.REL cp rel/apple/NEWDIR#FE1000 prodos/sys/NEWDIR.REL cp rel/apple/TYPE#FE1000 prodos/sys/TYPE.REL -cp rel/MATCH#FE1000 prodos/sys/MATCH.REL +cp rel/apple/MATCHFILES#FE1000 prodos/sys/MATCHFILES.REL cp rel/ARGS#FE1000 prodos/sys/ARGS.REL cp rel/ED#FE1000 prodos/sys/ED.REL cp rel/FIBER#FE1000 prodos/sys/FIBER.REL @@ -153,7 +153,7 @@ cp samplesrc/lz4cat.pla prodos/bld/samples/Z4CAT.PLA.TXT mkdir prodos/bld/inc cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT -cp inc/match.plh prodos/bld/inc/MATCH.PLH.TXT +cp inc/matchfiles.plh prodos/bld/inc/MATCHFILES.PLH.TXT cp inc/cmdsys.plh prodos/bld/inc/CMDSYS.PLH.TXT cp inc/conio.plh prodos/bld/inc/CONIO.PLH.TXT cp inc/lines.plh prodos/bld/inc/LINES.PLH.TXT diff --git a/src/tftpbld b/src/tftpbld index 24e6c70..5676b2a 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -6,7 +6,7 @@ echo "BLD/CODEOPT"; atftp $1 --put -l rel/CODEOPT#FE1000 -r $2/BLD/CODEOPT#FE10 #Build incs echo "BLD/INC/ARGS.PLH"; atftp $1 --put -l inc/args.plh -r $2/BLD/INC/ARGS.PLH#040000 -echo "BLD/INC/MATCH.PLH"; atftp $1 --put -l inc/match.plh -r $2/BLD/INC/MATCH.PLH#040000 +echo "BLD/INC/MATCHFILES.PLH"; atftp $1 --put -l inc/matchfiles.plh -r $2/BLD/INC/MATCHFILES.PLH#040000 echo "BLD/INC/CMDSYS.PLH"; atftp $1 --put -l inc/cmdsys.plh -r $2/BLD/INC/CMDSYS.PLH#040000 echo "BLD/INC/CONIO.PLH"; atftp $1 --put -l inc/conio.plh -r $2/BLD/INC/CONIO.PLH#040000 echo "BLD/INC/LINES.PLH"; atftp $1 --put -l inc/lines.plh -r $2/BLD/INC/LINES.PLH#040000 diff --git a/src/tftpsys b/src/tftpsys index c32e833..a54c52a 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -11,7 +11,7 @@ echo "SYS/JIT16"; atftp $1 --put -l rel/apple/JIT16#FE1000 -r $2/SYS/JIT16#F echo "SYS/JITUNE"; atftp $1 --put -l rel/apple/JITUNE#FE1000 -r $2/SYS/JITUNE#FE1000 # Core libraries -echo "SYS/MATCH"; atftp $1 --put -l rel/MATCH#FE1000 -r $2/SYS/MATCH#FE1000 +echo "SYS/MATCHFILES"; atftp $1 --put -l rel/apple/MATCHFILES#FE1000 -r $2/SYS/MATCHFILES#FE1000 echo "SYS/ARGS"; atftp $1 --put -l rel/ARGS#FE1000 -r $2/SYS/ARGS#FE1000 echo "SYS/INT32"; atftp $1 --put -l rel/INT32#FE1000 -r $2/SYS/INT32#FE1000 echo "SYS/DHCP"; atftp $1 --put -l rel/DHCP#FE1000 -r $2/SYS/DHCP#FE1000 diff --git a/src/utilsrc/apple/cat.pla b/src/utilsrc/apple/cat.pla index aa9a82a..68f3860 100644 --- a/src/utilsrc/apple/cat.pla +++ b/src/utilsrc/apple/cat.pla @@ -1,7 +1,7 @@ include "inc/cmdsys.plh" include "inc/longjmp.plh" include "inc/args.plh" -include "inc/match.plh" +include "inc/matchfiles.plh" include "inc/fileio.plh" include "inc/int32.plh" @@ -28,17 +28,23 @@ def putb(b)#0 fin putc(h) end -def strupper(strptr)#0 +// +// Copy string with upper case conversion +// +def struprcpy(dst, src)#0 byte i, chr - if ^strptr - for i = 1 to ^strptr - chr = strptr->[i] + if ^src + for i = 1 to ^src + chr = src->[i] if chr >= 'a' and chr <= 'z' - strptr->[i] = chr - 'a' + 'A' + dst->[i] = chr - 'a' + 'A' + else + dst->[i] = chr fin next fin + ^dst = ^src end def filefrompath(filestr, pathstr)#0 byte i @@ -87,9 +93,10 @@ def printentry(entryptr)#0 end def printentries(pathstr, entries, num)#0 byte page - page = 20 + puts(pathstr); putln puts("=NAME==========TYPE===AUX====LENGTH=\n") + page = 20 repeat printentry(entries) entries = entries + t_fileentry @@ -152,10 +159,8 @@ if not except(exit) fin arg = argNext(arg) fin - recurse = TRUE if ^arg - strcpy(@path, arg) - strupper(@path) + struprcpy(@path, arg) // // Check if cataloging a directory // diff --git a/src/utilsrc/apple/copy.pla b/src/utilsrc/apple/copy.pla index 881faa9..feee4b1 100644 --- a/src/utilsrc/apple/copy.pla +++ b/src/utilsrc/apple/copy.pla @@ -1,14 +1,31 @@ include "inc/cmdsys.plh" +include "inc/longjmp.plh" include "inc/args.plh" include "inc/fileio.plh" +include "inc/matchfiles.plh" const MAXBUFSIZE = 16384 -var arg, srcref, dstref, copybuff, copysize, copyxfer -char[64] srcfilename, dstfilename +var arg, recurse, exit, srcfilelist, srcfileptr, srccnt +char[64] dstpath res[t_fileinfo] srcfileinfo, dstfileinfo // -// Handy string functions +// Copy string with upper case conversion // +def struprcpy(dst, src)#0 + byte i, chr + + if ^src + for i = 1 to ^src + chr = src->[i] + if chr >= 'a' and chr <= 'z' + dst->[i] = chr - 'a' + 'A' + else + dst->[i] = chr + fin + next + fin + ^dst = ^src +end def filefrompath(filestr, pathstr)#0 byte i @@ -21,126 +38,184 @@ def filefrompath(filestr, pathstr)#0 memcpy(filestr + 1, pathstr + 1 + i, ^filestr) end // -// Check destination filename +// Check destination path // -def checkdst - char[17] basefile +def chkdstpath(dstfile) // // Check if destination exists // - if fileio:getfileinfo(@dstfilename, @dstfileinfo) == FILE_ERR_OK + if fileio:getfileinfo(dstfile, @dstfileinfo) == FILE_ERR_OK // // Check if copying into a directory // if dstfileinfo.file_type == $0F - if dstfilename[dstfilename] <> '/' + if dstfile->[^dstfile] <> '/' // // Add path seperator // - dstfilename++ - dstfilename[dstfilename] = '/' + ^dstfile++ + dstfile->[^dstfile] = '/' fin - filefrompath(@basefile, @srcfilename) - strcat(@dstfilename, @basefile) - if fileio:getfileinfo(@dstfilename, @dstfileinfo) == FILE_ERR_OK - // - // Check if *that* is a directory - // - if dstfileinfo.file_type == $0F - puts("Destination is a directory filename\n") - return FALSE + return TRUE + fin + fin + return FALSE +end +def copyfiles(srcfile, dstfile)#0 + var entrylist, entry, entrycnt, srcref, dstref, copybuff, copyrel, copysize, copyxfer + char[64] srcpath + char[64] srcfilepath + char[64] dstfilepath + char[16] wildname + + copysize = MAXBUFSIZE + while isult(heapavail, copysize + 512) + copysize = copysize / 2 + loop + copyrel = heapalloc(copysize) + if copyrel + // + // Round buffer to page boundary for faster transfers + // + copybuff = (copyrel + $FF) & $FF00 + // + // Check if copying a directory + // + strcpy(@srcpath, srcfile) + wildname = 0 + if fileio:getfileinfo(@srcpath, @srcfileinfo) <> FILE_ERR_OK or srcfileinfo.file_type <> $0F + filefrompath(@wildname, @srcpath) + srcpath = srcpath - wildname + fin + entrylist, entrycnt = matchList(@srcpath, @wildname) + if not entrylist + // + // Unable to open source + // + puts("Unable to open: "); puts(@srcpath); putln + throw(exit, TRUE) + fin + entry = entrylist + while entrycnt + strcpy(@srcfilepath, @srcpath) + strcat(@srcfilepath, entry) + strcpy(@dstfilepath, dstfile) + if chkdstpath(@dstfilepath) + strcat(@dstfilepath, entry) + fin + puts(@srcfilepath); puts(" ==> "); puts(@dstfilepath); putln + // + // Check if source is a directory + // + if entry->entry_type == $0F + fileio:create(@dstfilepath, $0F, $0000) + if not chkdstpath(@dstfilepath) + puts("Unable to create: "); puts(@dstfilepath); putln + throw(exit, TRUE) + fin + if recurse + copyfiles(@srcfilepath, @dstfilepath) fin else - return TRUE - fin - fin - // - // Remove existing file - // - fileio:destroy(@dstfilename) - fin - return TRUE -end -// -// Check arguments and file types -// -arg = argNext(argFirst) -if ^arg - strcpy(@srcfilename, arg) - fileio:iobufalloc(2) // Reserve two I/O buffers - if fileio:getfileinfo(@srcfilename, @srcfileinfo) == FILE_ERR_OK - // - // Check that source isn't a directory - can't handle that yet - // - if srcfileinfo.file_type == $0F - puts("Can't copy directories (yet)\n") - return - fin - else - // - // File not found - // - puts("File not found: "); puts(@srcfilename); putln - return - fin - srcref = fileio:open(@srcfilename) - if srcref - arg = argNext(arg) - if ^arg - strcpy(@dstfilename, arg) - if checkdst() + // + // Check if destination exists + // + if fileio:getfileinfo(@dstfilepath, @dstfileinfo) == FILE_ERR_OK + fileio:destroy(@dstfilepath) + fin // // Create the destination file and open for writing // - if fileio:create(@dstfilename, srcfileinfo.file_type, srcfileinfo:aux_type) == FILE_ERR_OK - dstref = fileio:open(@dstfilename) + if fileio:create(@dstfilepath, entry->entry_type, entry=>entry_aux) == FILE_ERR_OK + srcref = fileio:open(@srcfilepath) + dstref = fileio:open(@dstfilepath) if dstref // // Let the copying begin // - copysize = MAXBUFSIZE - while isult(heapavail, copysize + 512) - copysize = copysize / 2 - loop - copybuff = heapalloc(copysize) - if copybuff - // - // Round buffer to page boundary for faster transfers - // - copybuff = (copybuff + $FF) & $FF00 + copyxfer = fileio:read(srcref, copybuff, copysize) + while copyxfer + if fileio:write(dstref, copybuff, copyxfer) <> copyxfer + puts("Error writing: "); puts(@dstfilepath); putln + throw(exit, TRUE) + fin copyxfer = fileio:read(srcref, copybuff, copysize) - while copyxfer - if fileio:write(dstref, copybuff, copyxfer) <> copyxfer - puts("Error writing: "); puts(@dstfilename); putln - break - fin - copyxfer = fileio:read(srcref, copybuff, copysize) - loop - else - puts("No memory available!\n") - fin + loop + fileio:close(dstref) else - puts("Unable to open: "); puts(@dstfilename); putln + puts("Unable to open: "); puts(@dstfilepath); putln + throw(exit, TRUE) fin + fileio:close(srcref) else - puts("Unable to create: "); puts(@dstfilename); putln + puts("Unable to create: "); puts(@dstfilepath); putln + throw(exit, TRUE) fin fin - fileio:close(0) + entry = entry + t_fileentry + entrycnt-- + loop + heaprelease(entrylist) + else + puts("No memory available!\n") + throw(exit, TRUE) + fin + heaprelease(copyrel) +end +// +// Install error exit +// +exit = heapalloc(t_except) +if not except(exit) + // + // Check arguments and file types + // + arg = argNext(argFirst) + if ^arg and arg->[1] == '-' + if ^arg > 1 and toupper(arg->[2]) == 'R' + recurse = TRUE + fin + arg = argNext(arg) + fin + if ^arg + srcfilelist = heapalloc(^arg + 1) + struprcpy(srcfilelist, arg) + srccnt++ + arg = argNext(arg) + if ^arg + struprcpy(@dstpath, arg) + arg = argNext(arg) + while ^arg + // + // Add to source list + // + srcfileptr = heapalloc(dstpath + 1) + strcpy(srcfileptr, @dstpath) + srccnt++ + // + // Set new destination + // + struprcpy(@dstpath, arg) + arg = argNext(arg) + loop + if not chkdstpath(@dstpath) and (srccnt > 1 or isWildName(srcfilelist)) + puts("Destination must be directory: "); puts(@dstpath); putln + throw(exit, TRUE) + fin + fileio:iobufalloc(2) // Reserve two I/O buffers + srcfileptr = srcfilelist + while srccnt + // + // Copy files in list + // + copyfiles(srcfileptr, @dstpath) + srcfileptr = srcfileptr + ^srcfileptr + 1 + srccnt-- + loop return fin - else - // - // Unable to open source - // - puts("Unable to open: "); puts(@srcfilename); putln - return fin - // - // Close all files - // - fileio:close(0) - return + puts("Usage: +COPY + \n") fin -puts("Usage: +COPY SRCFILE DEST\n") +fileio:close(0) done diff --git a/src/utilsrc/apple/del.pla b/src/utilsrc/apple/del.pla index 83a07f9..5501609 100644 --- a/src/utilsrc/apple/del.pla +++ b/src/utilsrc/apple/del.pla @@ -1,62 +1,168 @@ include "inc/cmdsys.plh" +include "inc/longjmp.plh" include "inc/args.plh" include "inc/fileio.plh" +include "inc/matchfiles.plh" -char[64] filename -var arg +var arg, recurse, exit, filelist, fileptr, filecnt +char[64] path +res[t_fileinfo] fileinfo +// +// Copy string with upper case conversion +// +def struprcpy(dst, src)#0 + byte i, chr + if ^src + for i = 1 to ^src + chr = src->[i] + if chr >= 'a' and chr <= 'z' + dst->[i] = chr - 'a' + 'A' + else + dst->[i] = chr + fin + next + fin + ^dst = ^src +end +def filefrompath(filestr, pathstr)#0 + byte i + + for i = ^pathstr downto 1 + if pathstr->[i] == '/' + break + fin + next + ^filestr = ^pathstr - i + memcpy(filestr + 1, pathstr + 1 + i, ^filestr) +end // // Check filename // -def checkfile - var refnum, dirbuf - res[t_fileinfo] fileinfo +def chkfile(file)#1 + var refnum, dirbuf, filecnt // // Check if file exists // - if fileio:getfileinfo(@filename, @fileinfo) == FILE_ERR_OK + if fileio:getfileinfo(file, @fileinfo) == FILE_ERR_OK // // Check if deleting a directory // if fileinfo.file_type == $0F - refnum = fileio:open(@filename) + refnum = fileio:open(file) if refnum // // Check for files inside directory // + filecnt = 0 dirbuf = heapalloc(512) if fileio:read(refnum, dirbuf, 512) == 512 fileio:close(refnum) - if dirbuf=>$25 // File count in directory - puts("Directory not empty: "); puts(@filename); putln - return FALSE - fin + filecnt = dirbuf=>$25 // File count in directory + fin + heaprelease(dirbuf) + if filecnt + puts("Directory not empty: "); puts(file); putln + return FALSE fin fin fin return TRUE fin - puts("File not found: "); puts(@filename); putln + puts("File not found: "); puts(file); putln return FALSE end -// -// Check arguments and file types -// -arg = argNext(argFirst) -if ^arg - strcpy(@filename, arg) - if checkfile() - // - // Remove existing file - // - fileio:destroy(@filename) +def delfiles(delfile)#0 + var entrylist, entry, entrycnt + char[64] delpath + char[64] delfilepath + char[16] wildname + + strcpy(@delpath, delfile) + wildname = 0 + //if fileio:getfileinfo(@delpath, @fileinfo) <> FILE_ERR_OK or fileinfo.file_type <> $0F + if delpath[delpath] <> '/' + filefrompath(@wildname, @delpath) + delpath = delpath - wildname fin // - // Close all files + // Check arguments and file types // - fileio:close(0) - return + entrylist, entrycnt = matchList(@delpath, @wildname) + if entrylist + entry = entrylist + while entrycnt + strcpy(@delfilepath, @delpath) + strcat(@delfilepath, entry) + // + // Check if file is a directory + // + if entry->entry_type == $0F + if recurse + strcat(@delfilepath, "/") + strcat(@delfilepath, @wildname) + delfiles(@delfilepath) + fin + strcpy(@delfilepath, @delpath) + strcat(@delfilepath, entry) + if chkfile(@delfilepath) + puts("Removing: "); puts(@delfilepath); putln + fileio:destroy(@delfilepath) + fin + else + puts("Removing: "); puts(@delfilepath); putln + fileio:destroy(@delfilepath) + fin + entry = entry + t_fileentry + entrycnt-- + loop + elsif not wildname + puts("Not found: "); puts(@delpath); puts("/"); puts(@wildname); putln + fin +end +// +// Install error exit +// +exit = heapalloc(t_except) +if not except(exit) + // + // Check arguments and file types + // + arg = argNext(argFirst) + if ^arg and arg->[1] == '-' + if ^arg > 1 and toupper(arg->[2]) == 'R' + recurse = TRUE + fin + arg = argNext(arg) + fin + if ^arg + filelist = heapmark() + while ^arg + // + // Add to file list + // + fileptr = heapalloc(^arg + 1) + struprcpy(fileptr, arg) + filecnt++ + arg = argNext(arg) + loop + fileptr = filelist + while filecnt + // + // Delete files in list + // + if recurse and fileio:getfileinfo(fileptr, @fileinfo) == FILE_ERR_OK and fileinfo.file_type == $0F + strcpy(@path,fileptr) + strcat(@path, "/") + delfiles(@path) + fin + delfiles(fileptr) + fileptr = fileptr + ^fileptr + 1 + filecnt-- + loop + else + puts("Usage: +DEL +\n") + fin fin -puts("Usage: +DEL FILE\n") done From ecb61ccddd667cbd72c5f342d39e50e7a8d32e3d Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Thu, 2 Jan 2020 19:49:18 -0800 Subject: [PATCH 110/149] Fix too many buffers allocated --- src/libsrc/apple/matchfiles.pla | 2 +- src/utilsrc/apple/copy.pla | 200 ++++++++++++++++++-------------- 2 files changed, 114 insertions(+), 88 deletions(-) diff --git a/src/libsrc/apple/matchfiles.pla b/src/libsrc/apple/matchfiles.pla index c14fd7a..98f69e0 100644 --- a/src/libsrc/apple/matchfiles.pla +++ b/src/libsrc/apple/matchfiles.pla @@ -74,7 +74,7 @@ export def matchList(pathstr, exp)#2 fin for i = firstblk to entriesblk // - // Print directory entry details + // Copy directory entry details // ^entry = ^entry & $0F if ^entry diff --git a/src/utilsrc/apple/copy.pla b/src/utilsrc/apple/copy.pla index feee4b1..8fda31d 100644 --- a/src/utilsrc/apple/copy.pla +++ b/src/utilsrc/apple/copy.pla @@ -5,7 +5,9 @@ include "inc/fileio.plh" include "inc/matchfiles.plh" const MAXBUFSIZE = 16384 -var arg, recurse, exit, srcfilelist, srcfileptr, srccnt +var arg, exit, srcfilelist, srcfileptr, srccnt +var copybuff, copyrel, copysize +byte recurse, dstlen char[64] dstpath res[t_fileinfo] srcfileinfo, dstfileinfo // @@ -62,105 +64,93 @@ def chkdstpath(dstfile) return FALSE end def copyfiles(srcfile, dstfile)#0 - var entrylist, entry, entrycnt, srcref, dstref, copybuff, copyrel, copysize, copyxfer + var entrylist, entry, entrycnt, srcref, dstref, copyxfer char[64] srcpath char[64] srcfilepath char[64] dstfilepath char[16] wildname - copysize = MAXBUFSIZE - while isult(heapavail, copysize + 512) - copysize = copysize / 2 - loop - copyrel = heapalloc(copysize) - if copyrel + // + // Check if copying a directory + // + strcpy(@srcpath, srcfile) + wildname = 0 + if fileio:getfileinfo(@srcpath, @srcfileinfo) <> FILE_ERR_OK or srcfileinfo.file_type <> $0F + filefrompath(@wildname, @srcpath) + srcpath = srcpath - wildname + fin + entrylist, entrycnt = matchList(@srcpath, @wildname) +// if not entrylist // - // Round buffer to page boundary for faster transfers + // Unable to open source // - copybuff = (copyrel + $FF) & $FF00 - // - // Check if copying a directory - // - strcpy(@srcpath, srcfile) - wildname = 0 - if fileio:getfileinfo(@srcpath, @srcfileinfo) <> FILE_ERR_OK or srcfileinfo.file_type <> $0F - filefrompath(@wildname, @srcpath) - srcpath = srcpath - wildname +// puts("Unable to open: "); puts(wildname ?? @wildname :: @srcpath); putln +// throw(exit, TRUE) +// fin + entry = entrylist + while entrycnt + strcpy(@srcfilepath, @srcpath) + strcat(@srcfilepath, entry) + strcpy(@dstfilepath, dstfile) + if chkdstpath(@dstfilepath) + strcat(@dstfilepath, entry) fin - entrylist, entrycnt = matchList(@srcpath, @wildname) - if not entrylist + puts(@srcfilepath); puts(" ==> "); puts(@dstfilepath); putln + if entry->entry_type == $0F // - // Unable to open source + // Source is a directory // - puts("Unable to open: "); puts(@srcpath); putln - throw(exit, TRUE) - fin - entry = entrylist - while entrycnt - strcpy(@srcfilepath, @srcpath) - strcat(@srcfilepath, entry) - strcpy(@dstfilepath, dstfile) - if chkdstpath(@dstfilepath) - strcat(@dstfilepath, entry) + fileio:create(@dstfilepath, $0F, $0000) + if not chkdstpath(@dstfilepath) + puts("Unable to create directory: "); puts(@dstfilepath); putln + throw(exit, TRUE) fin - puts(@srcfilepath); puts(" ==> "); puts(@dstfilepath); putln + if recurse + copyfiles(@srcfilepath, @dstfilepath) + fin + else // - // Check if source is a directory + // Check if destination file exists // - if entry->entry_type == $0F - fileio:create(@dstfilepath, $0F, $0000) - if not chkdstpath(@dstfilepath) - puts("Unable to create: "); puts(@dstfilepath); putln - throw(exit, TRUE) - fin - if recurse - copyfiles(@srcfilepath, @dstfilepath) - fin - else - // - // Check if destination exists - // - if fileio:getfileinfo(@dstfilepath, @dstfileinfo) == FILE_ERR_OK - fileio:destroy(@dstfilepath) - fin - // - // Create the destination file and open for writing - // - if fileio:create(@dstfilepath, entry->entry_type, entry=>entry_aux) == FILE_ERR_OK - srcref = fileio:open(@srcfilepath) - dstref = fileio:open(@dstfilepath) - if dstref - // - // Let the copying begin - // - copyxfer = fileio:read(srcref, copybuff, copysize) - while copyxfer - if fileio:write(dstref, copybuff, copyxfer) <> copyxfer - puts("Error writing: "); puts(@dstfilepath); putln - throw(exit, TRUE) - fin - copyxfer = fileio:read(srcref, copybuff, copysize) - loop - fileio:close(dstref) - else - puts("Unable to open: "); puts(@dstfilepath); putln + if fileio:getfileinfo(@dstfilepath, @dstfileinfo) == FILE_ERR_OK + fileio:destroy(@dstfilepath) + fin + // + // Create the destination file and open for writing + // + if fileio:create(@dstfilepath, entry->entry_type, entry=>entry_aux) <> FILE_ERR_OK + puts("Unable to create file: "); puts(@dstfilepath); putln + throw(exit, TRUE) + fin + srcref = fileio:open(@srcfilepath) + if not srcref + puts("Unable to open file: "); puts(@srcfilepath); putln + throw(exit, TRUE) + fin + dstref = fileio:open(@dstfilepath) + if not dstref + puts("Unable to open file: "); puts(@dstfilepath); putln + throw(exit, TRUE) + fin + // + // Let the copying begin + // + repeat + copyxfer = fileio:read(srcref, copybuff, copysize) + if copyxfer + if fileio:write(dstref, copybuff, copyxfer) <> copyxfer + puts("Error writing: "); puts(@dstfilepath); putln throw(exit, TRUE) fin - fileio:close(srcref) - else - puts("Unable to create: "); puts(@dstfilepath); putln - throw(exit, TRUE) fin - fin - entry = entry + t_fileentry - entrycnt-- - loop - heaprelease(entrylist) - else - puts("No memory available!\n") - throw(exit, TRUE) - fin - heaprelease(copyrel) + until copyxfer == 0 + fileio:close(dstref) + fileio:close(srcref) + fin + entry = entry + t_fileentry + entrycnt-- + loop + heaprelease(entrylist) end // // Install error exit @@ -199,19 +189,55 @@ if not except(exit) arg = argNext(arg) loop if not chkdstpath(@dstpath) and (srccnt > 1 or isWildName(srcfilelist)) - puts("Destination must be directory: "); puts(@dstpath); putln - throw(exit, TRUE) + puts("Destination must be a directory: "); puts(@dstpath); putln + return fin fileio:iobufalloc(2) // Reserve two I/O buffers + copysize = MAXBUFSIZE + while isult(heapavail, copysize + 512) + copysize = copysize / 2 + loop + copyrel = heapalloc(copysize) + if not copyrel + puts(" No available memory for copy buffer\n") + return + fin + // + // Round buffer to page boundary for faster transfers + // + copybuff = (copyrel + $FF) & $FF00 + // + // Iterate through all sources + // srcfileptr = srcfilelist while srccnt + if fileio:getfileinfo(srcfileptr, @srcfileinfo) == FILE_ERR_OK and srcfileinfo.file_type == $0F + if recurse + // + // Copy directory + // + if fileio:getfileinfo(@dstpath, @dstfileinfo) <> FILE_ERR_OK + fileio:create(@dstpath, $0F, $0000) + fin + if not chkdstpath(@dstpath) + puts("Destination must be a directory: "); puts(@dstpath); putln + return + fin + else + puts("Omitting directory without -r: "); puts(srcfileptr); putln + srcfileptr = srcfileptr + ^srcfileptr + 1 + srccnt-- + continue + fin + fin // - // Copy files in list + // Copy files // copyfiles(srcfileptr, @dstpath) srcfileptr = srcfileptr + ^srcfileptr + 1 srccnt-- loop + heaprelease(copyrel) return fin fin From c4c3f4d9b3f9a53c012e559427e5c2b7b4d07c84 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Thu, 2 Jan 2020 20:49:32 -0800 Subject: [PATCH 111/149] Avoid infinite copy recursion --- src/utilsrc/apple/copy.pla | 80 +++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 23 deletions(-) diff --git a/src/utilsrc/apple/copy.pla b/src/utilsrc/apple/copy.pla index 8fda31d..e77256d 100644 --- a/src/utilsrc/apple/copy.pla +++ b/src/utilsrc/apple/copy.pla @@ -8,14 +8,14 @@ const MAXBUFSIZE = 16384 var arg, exit, srcfilelist, srcfileptr, srccnt var copybuff, copyrel, copysize byte recurse, dstlen -char[64] dstpath +char[64] curpath, dstpath res[t_fileinfo] srcfileinfo, dstfileinfo // -// Copy string with upper case conversion +// Copy path with upper case conversion // -def struprcpy(dst, src)#0 +def pathcpy(dst, src)#0 byte i, chr - + if ^src for i = 1 to ^src chr = src->[i] @@ -28,6 +28,44 @@ def struprcpy(dst, src)#0 fin ^dst = ^src end +def abspath(abs, path)#0 + if ^path == 0 or path->[1] <> '/' + // + // Append relative path to absolute path + // + strcpy(abs, @curpath) + else + // + // Absolute path + // + ^abs = 0 + fin + strcat(abs, path) + // + // Strip trailing path seperator + // + if abs->[^abs] == '/' + ^abs-- + fin +end +def pathdiff(path1, path2)#1 + byte i, d + char[64] abs1, abs2 + + abspath(@abs1, path1) + abspath(@abs2, path2) + + if abs1 <> abs2 + return TRUE + fin + for i = 1 to abs1 + d = abs1[i] - abs2[i] + if d + return d + fin + next + return FALSE +end def filefrompath(filestr, pathstr)#0 byte i @@ -80,13 +118,6 @@ def copyfiles(srcfile, dstfile)#0 srcpath = srcpath - wildname fin entrylist, entrycnt = matchList(@srcpath, @wildname) -// if not entrylist - // - // Unable to open source - // -// puts("Unable to open: "); puts(wildname ?? @wildname :: @srcpath); putln -// throw(exit, TRUE) -// fin entry = entrylist while entrycnt strcpy(@srcfilepath, @srcpath) @@ -95,18 +126,19 @@ def copyfiles(srcfile, dstfile)#0 if chkdstpath(@dstfilepath) strcat(@dstfilepath, entry) fin - puts(@srcfilepath); puts(" ==> "); puts(@dstfilepath); putln if entry->entry_type == $0F // - // Source is a directory + // Source is a directory and not referencing the destination // - fileio:create(@dstfilepath, $0F, $0000) - if not chkdstpath(@dstfilepath) - puts("Unable to create directory: "); puts(@dstfilepath); putln - throw(exit, TRUE) - fin - if recurse - copyfiles(@srcfilepath, @dstfilepath) + if pathdiff(@srcfilepath, dstfile) + fileio:create(@dstfilepath, $0F, $0000) + if not chkdstpath(@dstfilepath) + puts("Unable to create directory: "); puts(@dstfilepath); putln + throw(exit, TRUE) + fin + if recurse + copyfiles(@srcfilepath, @dstfilepath) + fin fin else // @@ -146,6 +178,7 @@ def copyfiles(srcfile, dstfile)#0 until copyxfer == 0 fileio:close(dstref) fileio:close(srcref) + puts(@srcfilepath); puts(" ==> "); puts(@dstfilepath); putln fin entry = entry + t_fileentry entrycnt-- @@ -157,6 +190,7 @@ end // exit = heapalloc(t_except) if not except(exit) + fileio:getpfx(@curpath) // // Check arguments and file types // @@ -169,11 +203,11 @@ if not except(exit) fin if ^arg srcfilelist = heapalloc(^arg + 1) - struprcpy(srcfilelist, arg) + pathcpy(srcfilelist, arg) srccnt++ arg = argNext(arg) if ^arg - struprcpy(@dstpath, arg) + pathcpy(@dstpath, arg) arg = argNext(arg) while ^arg // @@ -185,7 +219,7 @@ if not except(exit) // // Set new destination // - struprcpy(@dstpath, arg) + pathcpy(@dstpath, arg) arg = argNext(arg) loop if not chkdstpath(@dstpath) and (srccnt > 1 or isWildName(srcfilelist)) From b2eaa867eb9ea5b67de6b563a40c1bf568589cbe Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 3 Jan 2020 07:57:26 -0800 Subject: [PATCH 112/149] Add explicit undrawList calls --- src/inc/hgrsprite.plh | 2 ++ src/libsrc/apple/hgrsprite.pla | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/inc/hgrsprite.plh b/src/inc/hgrsprite.plh index d2daed0..803e590 100644 --- a/src/inc/hgrsprite.plh +++ b/src/inc/hgrsprite.plh @@ -9,6 +9,8 @@ import hgrsprite predef spriteUnDrawXor(sprtptr)#0 predef spritePos(x, y, sprtptr)#0 predef spritePosIndex(x, y, i)#0 + predef spriteUnDrawList#0 + predef spriteUnDrawXorList#0 predef spriteDrawList#0 predef spriteDrawXorList#0 predef spriteAdd(i, sprtptr)#1 diff --git a/src/libsrc/apple/hgrsprite.pla b/src/libsrc/apple/hgrsprite.pla index 84f2980..2e11a89 100644 --- a/src/libsrc/apple/hgrsprite.pla +++ b/src/libsrc/apple/hgrsprite.pla @@ -260,6 +260,18 @@ export def spritePosIndex(x, y, i)#0 drawList[i]=>s_xpos = x - drawList[i]->s_xcenter fin end +export def spriteUnDrawList#0 + byte i + var undrawptr + + undrawptr = undrawList[drawpage] + for i = 15 downto 0 + if undrawptr=>[i] + spriteUnDraw(undrawptr=>[i]) + undrawptr=>[i] = 0 + fin + next +end export def spriteDrawList#0 byte i var undrawptr @@ -277,6 +289,18 @@ export def spriteDrawList#0 next memcpy(undrawptr, @drawList, 16*2) end +export def spriteUnDrawXorList#0 + byte i + var undrawptr + + undrawptr = undrawList[drawpage] + for i = 0 to 15 + if undrawptr=>[i] + spriteUnDrawXor(undrawptr=>[i]) + undrawptr=>[i] = 0 + fin + next +end export def spriteDrawXorList#0 byte i var undrawptr From 18543c83630a329806cf5268d181d9315e00286d Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Fri, 3 Jan 2020 14:19:38 -0800 Subject: [PATCH 113/149] Fix copy directory destination --- src/utilsrc/apple/copy.pla | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/utilsrc/apple/copy.pla b/src/utilsrc/apple/copy.pla index e77256d..d74d2be 100644 --- a/src/utilsrc/apple/copy.pla +++ b/src/utilsrc/apple/copy.pla @@ -9,6 +9,7 @@ var arg, exit, srcfilelist, srcfileptr, srccnt var copybuff, copyrel, copysize byte recurse, dstlen char[64] curpath, dstpath +char[16] srcdir res[t_fileinfo] srcfileinfo, dstfileinfo // // Copy path with upper case conversion @@ -245,11 +246,18 @@ if not except(exit) // srcfileptr = srcfilelist while srccnt + dstlen = dstpath if fileio:getfileinfo(srcfileptr, @srcfileinfo) == FILE_ERR_OK and srcfileinfo.file_type == $0F if recurse // // Copy directory // + if dstpath[dstpath] <> '/' + dstpath++ + dstpath[dstpath] = '/' + fin + filefrompath(@srcdir, srcfileptr) + strcat(@dstpath, @srcdir) if fileio:getfileinfo(@dstpath, @dstfileinfo) <> FILE_ERR_OK fileio:create(@dstpath, $0F, $0000) fin @@ -268,6 +276,7 @@ if not except(exit) // Copy files // copyfiles(srcfileptr, @dstpath) + dstpath = dstlen srcfileptr = srcfileptr + ^srcfileptr + 1 srccnt-- loop From 426b66248105f5614dd16a091b3b84c873ec332c Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Fri, 3 Jan 2020 14:24:41 -0800 Subject: [PATCH 114/149] Lose examples from TFTP BLD --- src/tftpbld | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/tftpbld b/src/tftpbld index 5676b2a..eae19c2 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -54,22 +54,3 @@ echo "BLD/SAMPLES/FATCAT.PLA"; atftp $1 --put -l samplesrc/fatcat.pla -r $ echo "BLD/SAMPLES/GFXDEMO.PLA"; atftp $1 --put -l samplesrc/gfxdemo.pla -r $2/BLD/SAMPLES/GFXDEMO.PLA#040000 echo "BLD/SAMPLES/LZ4CAT.PLA"; atftp $1 --put -l samplesrc/lz4cat.pla -r $2/BLD/SAMPLES/LZ4CAT.PLA#040000 -# Examples from video series -echo "BLD/EXAMPLES/EX.1.PLA"; atftp $1 --put -l samplesrc/examples/ex.1.pla -r $2/BLD/EXAMPLES/EX.1.PLA#040000 -echo "BLD/EXAMPLES/EX.2.PLA"; atftp $1 --put -l samplesrc/examples/ex.2.pla -r $2/BLD/EXAMPLES/EX.2.PLA#040000 -echo "BLD/EXAMPLES/EX.3.PLA"; atftp $1 --put -l samplesrc/examples/ex.3.pla -r $2/BLD/EXAMPLES/EX.3.PLA#040000 -echo "BLD/EXAMPLES/EX.4.PLA"; atftp $1 --put -l samplesrc/examples/ex.4.pla -r $2/BLD/EXAMPLES/EX.4.PLA#040000 -echo "BLD/EXAMPLES/EX.5.PLA"; atftp $1 --put -l samplesrc/examples/ex.5.pla -r $2/BLD/EXAMPLES/EX.5.PLA#040000 -echo "BLD/EXAMPLES/EX.6.PLA"; atftp $1 --put -l samplesrc/examples/ex.6.pla -r $2/BLD/EXAMPLES/EX.6.PLA#040000 -echo "BLD/EXAMPLES/EX.7.PLA"; atftp $1 --put -l samplesrc/examples/ex.7.pla -r $2/BLD/EXAMPLES/EX.7.PLA#040000 -echo "BLD/EXAMPLES/EX.8.PLA"; atftp $1 --put -l samplesrc/examples/ex.8.pla -r $2/BLD/EXAMPLES/EX.8.PLA#040000 -echo "BLD/EXAMPLES/EX.9.PLA"; atftp $1 --put -l samplesrc/examples/ex.9.pla -r $2/BLD/EXAMPLES/EX.9.PLA#040000 -echo "BLD/EXAMPLES/EX.10.PLA"; atftp $1 --put -l samplesrc/examples/ex.10.pla -r $2/BLD/EXAMPLES/EX.10.PLA#040000 -echo "BLD/EXAMPLES/EX.11.PLA"; atftp $1 --put -l samplesrc/examples/ex.11.pla -r $2/BLD/EXAMPLES/EX.11.PLA#040000 -echo "BLD/EXAMPLES/EX.12.PLA"; atftp $1 --put -l samplesrc/examples/ex.12.pla -r $2/BLD/EXAMPLES/EX.12.PLA#040000 -echo "BLD/EXAMPLES/EX.13.PLA"; atftp $1 --put -l samplesrc/examples/ex.13.pla -r $2/BLD/EXAMPLES/EX.13.PLA#040000 -echo "BLD/EXAMPLES/EX.14.PLA"; atftp $1 --put -l samplesrc/examples/ex.14.pla -r $2/BLD/EXAMPLES/EX.14.PLA#040000 -echo "BLD/EXAMPLES/EX.15.PLA"; atftp $1 --put -l samplesrc/examples/ex.15.pla -r $2/BLD/EXAMPLES/EX.15.PLA#040000 -echo "BLD/EXAMPLES/EX.16.PLA"; atftp $1 --put -l samplesrc/examples/ex.16.pla -r $2/BLD/EXAMPLES/EX.16.PLA#040000 -echo "BLD/EXAMPLES/EX.17.PLA"; atftp $1 --put -l samplesrc/examples/ex.17.pla -r $2/BLD/EXAMPLES/EX.17.PLA#040000 - From b6a7b72fe150587aa71ff01f3b690d75977a641e Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 4 Jan 2020 07:45:39 -0800 Subject: [PATCH 115/149] Set inituial mask to WHITE(7) instead of WHITE(3) to reduce artifacting in blank areas --- src/libsrc/apple/hgrsprite.pla | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsrc/apple/hgrsprite.pla b/src/libsrc/apple/hgrsprite.pla index 2e11a89..0a4342c 100644 --- a/src/libsrc/apple/hgrsprite.pla +++ b/src/libsrc/apple/hgrsprite.pla @@ -145,7 +145,7 @@ export def spriteCompile(w, h, xcenter, ycenter, srcptr)#1 hgrRect(0, w + 21, 0, h - 1) hgrBLT(i, 0, w, h, srcptr) hgrCopyDst(i > 6 ?? 1 :: 0, 0, bytewidth, h, sprtptr=>s_map[i]) - hgrColor(3) + hgrColor(7) hgrRect(0, w + 21, h, h * 2 - 1) spriteBLTMask(i, h, w, h, srcptr) hgrCopyDst(i > 6 ?? 1 :: 0, h, bytewidth, h, sprtptr=>s_mask[i]) From 41071de12fdc168efe5c58148ad64088014c069c Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sat, 4 Jan 2020 08:45:23 -0800 Subject: [PATCH 116/149] New HGR sprite shoot-em up demo --- src/samplesrc/sfm.pla | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/samplesrc/sfm.pla diff --git a/src/samplesrc/sfm.pla b/src/samplesrc/sfm.pla new file mode 100644 index 0000000..8e4dc61 --- /dev/null +++ b/src/samplesrc/sfm.pla @@ -0,0 +1 @@ +include "inc/cmdsys.plh" include "inc/hgrlib.plh" include "inc/hgrsprite.plh" include "inc/lines.plh" include "inc/joybuzz.plh" sysflags reshgr1|reshgr2 // Reserve HGR page 1 and 2 byte egg = $88,$83,$33,$33,$38,$88 byte = $88,$33,$11,$11,$33,$88 byte = $83,$31,$11,$11,$13,$38 byte = $33,$11,$11,$11,$11,$33 byte = $33,$11,$11,$11,$11,$33 byte = $33,$11,$11,$11,$11,$33 byte = $33,$11,$11,$11,$11,$33 byte = $83,$31,$11,$11,$13,$38 byte = $88,$33,$11,$11,$33,$88 byte = $88,$83,$33,$33,$38,$88 byte dummy = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte ship = $CC,$CC,$CC,$77,$CC,$CC,$CC byte = $CC,$CC,$C7,$77,$7C,$CC,$CC byte = $CC,$CC,$C7,$77,$7C,$CC,$CC byte = $CC,$CC,$C7,$77,$7C,$CC,$CC byte = $CC,$CC,$C7,$77,$7C,$CC,$CC byte = $77,$CC,$77,$66,$77,$CC,$77 byte = $77,$CC,$77,$66,$77,$CC,$77 byte = $77,$CC,$77,$66,$77,$CC,$77 byte = $77,$CC,$77,$77,$77,$CC,$77 byte = $77,$CC,$77,$77,$77,$CC,$77 byte = $77,$CC,$77,$77,$77,$CC,$77 byte = $77,$C7,$77,$77,$77,$7C,$77 byte = $77,$77,$77,$77,$77,$77,$77 byte = $77,$77,$75,$55,$57,$77,$77 byte missle = $CC,$55,$CC byte = $CC,$55,$CC byte = $CC,$55,$CC byte = $CC,$55,$CC byte = $CC,$55,$CC byte = $CC,$55,$CC byte = $C5,$55,$5C byte = $55,$55,$55 var sprtEgg, sprtShip, sprtMissle, sprtDummy def moire#0 var i setlinespans(@hgrHlin, @hgrVlin) setlineplot(@hgrXorPlot) hgrColor(7) for i = 0 to 191 step 8 linespans(0, i, 279, 191 - i) next for i = 0 to 279 step 9 linespans(i, 0, 279 - i, 191) next end def game(eggnum)#0 var[14] xegg, yegg, ixegg, iyegg var xship, xmissle byte yship, ymissle byte k, xdelta, ydelta, btn0, btn1 xship = 140 ymissle = 255 xegg[0] = 100 ixegg[0] = 1 yegg[0] = 60 iyegg[0] = -1 for k = 1 to 13 xegg[k] = ((xegg[k - 1] ^ 37) + 97) & 255 ixegg[k] = -ixegg[k - 1] yegg[k] = ((yegg[k - 1] ^ 29) + 53) & 63 iyegg[k] = -iyegg[k - 1] next repeat for k = 0 to 13 if yegg[k] <> 255 xegg[k] = xegg[k] + ixegg[k] if xegg[k] < -5 or xegg[k] > 284 ixegg[k] = -ixegg[k] fin yegg[k] = yegg[k] + iyegg[k] if yegg[k] < -5 or yegg[k] > 64 iyegg[k] = -iyegg[k] fin spritePosIndex(xegg[k], yegg[k], k+2) fin next xdelta, ydelta, btn0, btn1 = joypos(ymissle/4) xship = xship + (xdelta / 4 - 10) if xship < 0; xship = 0; fin if xship > 279; xship = 279; fin if btn0 and ymissle == 255 spriteAdd(1, sprtMissle) xmissle = xship ymissle = 172 fin if ymissle <> 255 if ymissle < 8 spriteDel(1) ymissle = 255 else ymissle = ymissle - 8 spritePosIndex(xmissle, ymissle, 1) for k = 0 to 13 if yegg[k] <> 255 if ymissle >= yegg[k] - 5 and ymissle <= yegg[k] + 5 if xmissle >= xegg[k] - 5 and xmissle <= xegg[k] + 5 // // Hit // yegg[k] = 255 ymissle = 255 spriteAdd(k + 2, spriteDup(sprtDummy)) spritePosIndex(0, 0, k + 2) spriteDel(1) fin fin fin next fin fin spritePosIndex(xship, 190, 0) spriteDrawList() spriteDrawBuf(hgrSwap()) until ^$C000 > 127 end hgrMode spriteDrawBuf(hgrDrawBuf(0)) // So we can see the compile process sprtShip = spriteCompile(14, 14, 7, 13, @ship) sprtMissle = spriteCompile( 6, 8, 3, 0, @missle) sprtEgg = spriteCompile(12, 10, 6, 5, @egg) sprtDummy = spriteCompile( 7, 8, 0, 0, @dummy) hgrColor(8) hgrClear() moire memcpy($4000, $2000, $2000) // Copy to both buffers spriteDrawBuf(hgrDrawBuf(1)) spriteAdd(0, sprtShip) spriteAdd(2, sprtEgg) spriteAdd(3, spriteDup(sprtEgg)) spriteAdd(4, spriteDup(sprtEgg)) spriteAdd(5, spriteDup(sprtEgg)) spriteAdd(6, spriteDup(sprtEgg)) spriteAdd(7, spriteDup(sprtEgg)) spriteAdd(8, spriteDup(sprtEgg)) spriteAdd(9, spriteDup(sprtEgg)) spriteAdd(10, spriteDup(sprtEgg)) spriteAdd(11, spriteDup(sprtEgg)) spriteAdd(12, spriteDup(sprtEgg)) spriteAdd(13, spriteDup(sprtEgg)) spriteAdd(14, spriteDup(sprtEgg)) spriteAdd(15, spriteDup(sprtEgg)) game(14) getc txtMode done \ No newline at end of file From c1b6741cfdde69462c7b5cfc9b40981d65cf6447 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sat, 4 Jan 2020 09:36:54 -0800 Subject: [PATCH 117/149] Fix commented out data and rect parameters --- src/inc/hgrlib.plh | 2 +- src/libsrc/apple/hgrlib.pla | 56 +++++++++++++++++----------------- src/libsrc/apple/hgrsprite.pla | 6 ++-- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/inc/hgrlib.plh b/src/inc/hgrlib.plh index 14af0ec..4e48592 100644 --- a/src/inc/hgrlib.plh +++ b/src/inc/hgrlib.plh @@ -4,7 +4,7 @@ import hgrlib predef hgrXorPlot(x, y)#0 predef hgrHLin(x1, x2, y)#0 predef hgrVLin(y1, y2, x)#0 - predef hgrRect(x1, x2, y1, y2)#0 + predef hgrRect(x1, y1, x2, y2)#0 predef hgrBLT(x, y, width, height, srcptr)#0 predef hgrCopySrc(ofst, y, w, h, srcptr)#0 predef hgrAndSrc(ofst, y, w, h, srcptr)#0 diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index 0d716c2..c447182 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -65,36 +65,36 @@ byte = $02,$06,$0A,$0E,$12,$16,$1A,$1E byte = $02,$06,$0A,$0E,$12,$16,$1A,$1E byte = $03,$07,$0B,$0F,$13,$17,$1B,$1F byte = $03,$07,$0B,$0F,$13,$17,$1B,$1F -word //hgrscan[] = $0000,$0400,$0800,$0C00,$1000,$1400,$1800,$1C00 -word // = $0080,$0480,$0880,$0C80,$1080,$1480,$1880,$1C80 -word // = $0100,$0500,$0900,$0D00,$1100,$1500,$1900,$1D00 -word // = $0180,$0580,$0980,$0D80,$1180,$1580,$1980,$1D80 -word // = $0200,$0600,$0A00,$0E00,$1200,$1600,$1A00,$1E00 -word // = $0280,$0680,$0A80,$0E80,$1280,$1680,$1A80,$1E80 -word // = $0300,$0700,$0B00,$0F00,$1300,$1700,$1B00,$1F00 -word // = $0380,$0780,$0B80,$0F80,$1380,$1780,$1B80,$1F80 -word // = $0028,$0428,$0828,$0C28,$1028,$1428,$1828,$1C28 -word // = $00A8,$04A8,$08A8,$0CA8,$10A8,$14A8,$18A8,$1CA8 -word // = $0128,$0528,$0928,$0D28,$1128,$1528,$1928,$1D28 -word // = $01A8,$05A8,$09A8,$0DA8,$11A8,$15A8,$19A8,$1DA8 -word // = $0228,$0628,$0A28,$0E28,$1228,$1628,$1A28,$1E28 -word // = $02A8,$06A8,$0AA8,$0EA8,$12A8,$16A8,$1AA8,$1EA8 -word // = $0328,$0728,$0B28,$0F28,$1328,$1728,$1B28,$1F28 -word // = $03A8,$07A8,$0BA8,$0FA8,$13A8,$17A8,$1BA8,$1FA8 -word // = $0050,$0450,$0850,$0C50,$1050,$1450,$1850,$1C50 -word // = $00D0,$04D0,$08D0,$0CD0,$10D0,$14D0,$18D0,$1CD0 -word // = $0150,$0550,$0950,$0D50,$1150,$1550,$1950,$1D50 -word // = $01D0,$05D0,$09D0,$0DD0,$11D0,$15D0,$19D0,$1DD0 -word // = $0250,$0650,$0A50,$0E50,$1250,$1650,$1A50,$1E50 -word // = $02D0,$06D0,$0AD0,$0ED0,$12D0,$16D0,$1AD0,$1ED0 -word // = $0350,$0750,$0B50,$0F50,$1350,$1750,$1B50,$1F50 -word // = $03D0,$07D0,$0BD0,$0FD0,$13D0,$17D0,$1BD0,$1FD0 -word hcolor[] = $0000,$552A,$2A55,$7F7F,$8080,$D5AA,$AAD5,$FFFF -word hmask = $8081,$8082,$8084,$8088,$8090,$80A0,$80C0 -word = $8180,$8280,$8480,$8880,$9080,$A080,$C080 +//word hgrscan[] = $0000,$0400,$0800,$0C00,$1000,$1400,$1800,$1C00 +//word = $0080,$0480,$0880,$0C80,$1080,$1480,$1880,$1C80 +//word = $0100,$0500,$0900,$0D00,$1100,$1500,$1900,$1D00 +//word = $0180,$0580,$0980,$0D80,$1180,$1580,$1980,$1D80 +//word = $0200,$0600,$0A00,$0E00,$1200,$1600,$1A00,$1E00 +//word = $0280,$0680,$0A80,$0E80,$1280,$1680,$1A80,$1E80 +//word = $0300,$0700,$0B00,$0F00,$1300,$1700,$1B00,$1F00 +//word = $0380,$0780,$0B80,$0F80,$1380,$1780,$1B80,$1F80 +//word = $0028,$0428,$0828,$0C28,$1028,$1428,$1828,$1C28 +//word = $00A8,$04A8,$08A8,$0CA8,$10A8,$14A8,$18A8,$1CA8 +//word = $0128,$0528,$0928,$0D28,$1128,$1528,$1928,$1D28 +//word = $01A8,$05A8,$09A8,$0DA8,$11A8,$15A8,$19A8,$1DA8 +//word = $0228,$0628,$0A28,$0E28,$1228,$1628,$1A28,$1E28 +//word = $02A8,$06A8,$0AA8,$0EA8,$12A8,$16A8,$1AA8,$1EA8 +//word = $0328,$0728,$0B28,$0F28,$1328,$1728,$1B28,$1F28 +//word = $03A8,$07A8,$0BA8,$0FA8,$13A8,$17A8,$1BA8,$1FA8 +//word = $0050,$0450,$0850,$0C50,$1050,$1450,$1850,$1C50 +//word = $00D0,$04D0,$08D0,$0CD0,$10D0,$14D0,$18D0,$1CD0 +//word = $0150,$0550,$0950,$0D50,$1150,$1550,$1950,$1D50 +//word = $01D0,$05D0,$09D0,$0DD0,$11D0,$15D0,$19D0,$1DD0 +//word = $0250,$0650,$0A50,$0E50,$1250,$1650,$1A50,$1E50 +//word = $02D0,$06D0,$0AD0,$0ED0,$12D0,$16D0,$1AD0,$1ED0 +//word = $0350,$0750,$0B50,$0F50,$1350,$1750,$1B50,$1F50 +//word = $03D0,$07D0,$0BD0,$0FD0,$13D0,$17D0,$1BD0,$1FD0 +//word hmask = $8081,$8082,$8084,$8088,$8090,$80A0,$80C0 +//word = $8180,$8280,$8480,$8880,$9080,$A080,$C080 byte hbmask = $81,$82,$84,$88,$90,$A0,$C0 byte hlmask = $FF,$FE,$FC,$F8,$F0,$E0,$C0 byte hrmask = $81,$83,$87,$8F,$9F,$BF,$FF +word hcolor[] = $0000,$552A,$2A55,$7F7F,$8080,$D5AA,$AAD5,$FFFF word curhclr byte drawpage = 1 word drawbuff = hgr2 @@ -893,7 +893,7 @@ BLTDONE INX INX RTS end -export def hgrRect(x1, x2, y1, y2)#0 +export def hgrRect(x1, y1, x2, y2)#0 word y if x1 == x2 diff --git a/src/libsrc/apple/hgrsprite.pla b/src/libsrc/apple/hgrsprite.pla index 0a4342c..92e3eab 100644 --- a/src/libsrc/apple/hgrsprite.pla +++ b/src/libsrc/apple/hgrsprite.pla @@ -142,12 +142,12 @@ export def spriteCompile(w, h, xcenter, ycenter, srcptr)#1 sprtptr=>s_map[i] = heapalloc(spritesize) sprtptr=>s_mask[i] = heapalloc(spritesize) hgrColor(0) - hgrRect(0, w + 21, 0, h - 1) + hgrRect(0, 0, w + 21, h - 1) hgrBLT(i, 0, w, h, srcptr) hgrCopyDst(i > 6 ?? 1 :: 0, 0, bytewidth, h, sprtptr=>s_map[i]) hgrColor(7) - hgrRect(0, w + 21, h, h * 2 - 1) - spriteBLTMask(i, h, w, h, srcptr) + hgrRect(0, h, w + 21, h * 2 - 1) + spriteBLTMask(i, h, w, h, srcptr) hgrCopyDst(i > 6 ?? 1 :: 0, h, bytewidth, h, sprtptr=>s_mask[i]) next return sprtptr From 69733fd37f2ae89a79e6da881a2243f4f599ae09 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sat, 4 Jan 2020 12:52:31 -0800 Subject: [PATCH 118/149] Fix XORing of BLT with ORing. Better COPY message and add ZIP Chip utility --- src/inc/hgrlib.plh | 1 + src/libsrc/apple/hgrlib.pla | 115 +++++++++++++++++++++-------- src/libsrc/apple/hgrsprite.pla | 14 ++-- src/makefile | 27 ++++--- src/mkrel | 1 + src/tftputil | 1 + src/utilsrc/apple/copy.pla | 129 +++++++++++++++++---------------- src/utilsrc/apple/zip.pla | 51 +++++++++++++ 8 files changed, 227 insertions(+), 112 deletions(-) create mode 100644 src/utilsrc/apple/zip.pla diff --git a/src/inc/hgrlib.plh b/src/inc/hgrlib.plh index 4e48592..b09a751 100644 --- a/src/inc/hgrlib.plh +++ b/src/inc/hgrlib.plh @@ -1,6 +1,7 @@ import hgrlib predef divmod7(x)#2 predef hgrPlot(x, y)#0 + predef hgrOrPlot(x, y)#0 predef hgrXorPlot(x, y)#0 predef hgrHLin(x1, x2, y)#0 predef hgrVLin(y1, y2, x)#0 diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index c447182..fa79ca3 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -17,6 +17,32 @@ const hgr2 = $4000 const page1 = 0 const page2 = 1 word hgrbuff[] = hgr1, hgr2 +//word hgrscan[] = $0000,$0400,$0800,$0C00,$1000,$1400,$1800,$1C00 +//word = $0080,$0480,$0880,$0C80,$1080,$1480,$1880,$1C80 +//word = $0100,$0500,$0900,$0D00,$1100,$1500,$1900,$1D00 +//word = $0180,$0580,$0980,$0D80,$1180,$1580,$1980,$1D80 +//word = $0200,$0600,$0A00,$0E00,$1200,$1600,$1A00,$1E00 +//word = $0280,$0680,$0A80,$0E80,$1280,$1680,$1A80,$1E80 +//word = $0300,$0700,$0B00,$0F00,$1300,$1700,$1B00,$1F00 +//word = $0380,$0780,$0B80,$0F80,$1380,$1780,$1B80,$1F80 +//word = $0028,$0428,$0828,$0C28,$1028,$1428,$1828,$1C28 +//word = $00A8,$04A8,$08A8,$0CA8,$10A8,$14A8,$18A8,$1CA8 +//word = $0128,$0528,$0928,$0D28,$1128,$1528,$1928,$1D28 +//word = $01A8,$05A8,$09A8,$0DA8,$11A8,$15A8,$19A8,$1DA8 +//word = $0228,$0628,$0A28,$0E28,$1228,$1628,$1A28,$1E28 +//word = $02A8,$06A8,$0AA8,$0EA8,$12A8,$16A8,$1AA8,$1EA8 +//word = $0328,$0728,$0B28,$0F28,$1328,$1728,$1B28,$1F28 +//word = $03A8,$07A8,$0BA8,$0FA8,$13A8,$17A8,$1BA8,$1FA8 +//word = $0050,$0450,$0850,$0C50,$1050,$1450,$1850,$1C50 +//word = $00D0,$04D0,$08D0,$0CD0,$10D0,$14D0,$18D0,$1CD0 +//word = $0150,$0550,$0950,$0D50,$1150,$1550,$1950,$1D50 +//word = $01D0,$05D0,$09D0,$0DD0,$11D0,$15D0,$19D0,$1DD0 +//word = $0250,$0650,$0A50,$0E50,$1250,$1650,$1A50,$1E50 +//word = $02D0,$06D0,$0AD0,$0ED0,$12D0,$16D0,$1AD0,$1ED0 +//word = $0350,$0750,$0B50,$0F50,$1350,$1750,$1B50,$1F50 +//word = $03D0,$07D0,$0BD0,$0FD0,$13D0,$17D0,$1BD0,$1FD0 +//word hmask = $8081,$8082,$8084,$8088,$8090,$80A0,$80C0 +//word = $8180,$8280,$8480,$8880,$9080,$A080,$C080 byte hgrscanl[]= $00,$00,$00,$00,$00,$00,$00,$00 byte = $80,$80,$80,$80,$80,$80,$80,$80 byte = $00,$00,$00,$00,$00,$00,$00,$00 @@ -65,32 +91,6 @@ byte = $02,$06,$0A,$0E,$12,$16,$1A,$1E byte = $02,$06,$0A,$0E,$12,$16,$1A,$1E byte = $03,$07,$0B,$0F,$13,$17,$1B,$1F byte = $03,$07,$0B,$0F,$13,$17,$1B,$1F -//word hgrscan[] = $0000,$0400,$0800,$0C00,$1000,$1400,$1800,$1C00 -//word = $0080,$0480,$0880,$0C80,$1080,$1480,$1880,$1C80 -//word = $0100,$0500,$0900,$0D00,$1100,$1500,$1900,$1D00 -//word = $0180,$0580,$0980,$0D80,$1180,$1580,$1980,$1D80 -//word = $0200,$0600,$0A00,$0E00,$1200,$1600,$1A00,$1E00 -//word = $0280,$0680,$0A80,$0E80,$1280,$1680,$1A80,$1E80 -//word = $0300,$0700,$0B00,$0F00,$1300,$1700,$1B00,$1F00 -//word = $0380,$0780,$0B80,$0F80,$1380,$1780,$1B80,$1F80 -//word = $0028,$0428,$0828,$0C28,$1028,$1428,$1828,$1C28 -//word = $00A8,$04A8,$08A8,$0CA8,$10A8,$14A8,$18A8,$1CA8 -//word = $0128,$0528,$0928,$0D28,$1128,$1528,$1928,$1D28 -//word = $01A8,$05A8,$09A8,$0DA8,$11A8,$15A8,$19A8,$1DA8 -//word = $0228,$0628,$0A28,$0E28,$1228,$1628,$1A28,$1E28 -//word = $02A8,$06A8,$0AA8,$0EA8,$12A8,$16A8,$1AA8,$1EA8 -//word = $0328,$0728,$0B28,$0F28,$1328,$1728,$1B28,$1F28 -//word = $03A8,$07A8,$0BA8,$0FA8,$13A8,$17A8,$1BA8,$1FA8 -//word = $0050,$0450,$0850,$0C50,$1050,$1450,$1850,$1C50 -//word = $00D0,$04D0,$08D0,$0CD0,$10D0,$14D0,$18D0,$1CD0 -//word = $0150,$0550,$0950,$0D50,$1150,$1550,$1950,$1D50 -//word = $01D0,$05D0,$09D0,$0DD0,$11D0,$15D0,$19D0,$1DD0 -//word = $0250,$0650,$0A50,$0E50,$1250,$1650,$1A50,$1E50 -//word = $02D0,$06D0,$0AD0,$0ED0,$12D0,$16D0,$1AD0,$1ED0 -//word = $0350,$0750,$0B50,$0F50,$1350,$1750,$1B50,$1F50 -//word = $03D0,$07D0,$0BD0,$0FD0,$13D0,$17D0,$1BD0,$1FD0 -//word hmask = $8081,$8082,$8084,$8088,$8090,$80A0,$80C0 -//word = $8180,$8280,$8480,$8880,$9080,$A080,$C080 byte hbmask = $81,$82,$84,$88,$90,$A0,$C0 byte hlmask = $FF,$FE,$FC,$F8,$F0,$E0,$C0 byte hrmask = $81,$83,$87,$8F,$9F,$BF,$FF @@ -609,6 +609,51 @@ asm _hgrXorPlotD INX RTS end +//export def hgrOrPlot(x, y)#0 +// word pixptr +// byte ofst, pixofst, pmask +// +// ofst, pixofst = divmod7(x) +// pixptr = hgrscan[y] + drawbuff + ofst +// pmask = hbmask[pixofst] +// ^pixptr = ^pixptr | (curhclr.[ofst & 1] & pmask) +//end +export asm hgrOrPlot(x, y)#0 + LDY ESTKL+0,X ; Y COORD + CPY #192 + BCS + +end +asm _hgrOrPlotA + LDA $8000,Y ; HGRSCANL + STA DSTL + LDA $1000 ; DRAWBUFFH + ORA $9000,Y ; HGRSCANH + STA DSTH + INX +end +asm _hgrOrPlotB + JSR 1000 ; DIVMOD7 + LDY ESTKL+0,X ; PIXEL OFFSET +end +asm _hgrOrPlotC + LDA $1000,Y ; HBMASK + STA TMPL + LDA ESTKL+1,X ; HORIZ OFFSET + CMP #40 + BCS + + AND #$01 + TAY +end +asm _hgrOrPlotD + LDA $2000,Y ; CURHCLR + AND TMPL + LDY ESTKL+1,X ; HORIZ OFFSET + ORA (DST),Y + STA (DST),Y ++ INX + INX + RTS +end //export def hgrHLin(x1, x2, y)#0 // word pixptr, x // byte lofst, lpixofst, lpmask @@ -801,7 +846,7 @@ asm _hgrVLinC RTS end // -// BLT scanline of pixmap +// Masked BLT scanline of pixmap // asm scanBLT(x, y, w, srcptr)#0 LDA ESTKL+0,X ; SRC PTR @@ -841,7 +886,7 @@ asm _scanBLTB JSR $D000 ; HPLOT BEQ ++ BNE ++ -+ JSR $E000 ; HPLOTX ++ JSR $E000 ; HPLOTOR ++ INC ESTKL+3,X ; X COORDL BNE + INC ESTKH+3,X ; X COORDH @@ -878,7 +923,7 @@ asm _scanBLTD JSR $D000 ; HPLOT BEQ ++ BNE ++ -+ JSR $E000 ; HPLOTX ++ JSR $E000 ; HPLOTOR ++ INC ESTKL+3,X ; X COORDL BNE + INC ESTKH+3,X ; X COORDH @@ -917,7 +962,7 @@ export def hgrBLT(x, y, w, h, srcptr)#0 // if i & 1 // hgrColor(c) // if c & $08 -// hgrXorPlot(x + i, j) +// hgrOrPlot(x + i, j) // else // hgrPlot(x + i, j) // fin @@ -1005,6 +1050,12 @@ _hgrXorPlotA:9 = @hgrscanh _hgrXorPlotB:1 = @divmod7 _hgrXorPlotC:1 = @hbmask _hgrXorPlotD:1 = @curhclr +_hgrOrPlotA:1 = @hgrscanl +_hgrOrPlotA:6 = @drawbuff.1 +_hgrOrPlotA:9 = @hgrscanh +_hgrOrPlotB:1 = @divmod7 +_hgrOrPlotC:1 = @hbmask +_hgrOrPlotD:1 = @curhclr _hgrHLinA:1 = @hgrPlot _hgrHLinB:1 = @hgrscanl _hgrHLinB:6 = @drawbuff.1 @@ -1029,8 +1080,8 @@ hgrColor:13 = @hcolor.1 hgrColor:16 = @curhclr.1 _scanBLTA:1 = @hgrColor _scanBLTB:1 = @hgrPlot -_scanBLTB:8 = @hgrXorPlot +_scanBLTB:8 = @hgrOrPlot _scanBLTC:1 = @hgrColor _scanBLTD:1 = @hgrPlot -_scanBLTD:8 = @hgrXorPlot +_scanBLTD:8 = @hgrOrPlot done diff --git a/src/libsrc/apple/hgrsprite.pla b/src/libsrc/apple/hgrsprite.pla index 92e3eab..a07b6a3 100644 --- a/src/libsrc/apple/hgrsprite.pla +++ b/src/libsrc/apple/hgrsprite.pla @@ -108,7 +108,7 @@ end def spriteBLTMask(x, y, w, h, srcptr)#0 word i, j byte pitch -// byte c + byte c pitch = (w + 1) / 2 for j = y to y + h - 1 @@ -141,14 +141,14 @@ export def spriteCompile(w, h, xcenter, ycenter, srcptr)#1 for i = 0 to 13 sprtptr=>s_map[i] = heapalloc(spritesize) sprtptr=>s_mask[i] = heapalloc(spritesize) - hgrColor(0) - hgrRect(0, 0, w + 21, h - 1) - hgrBLT(i, 0, w, h, srcptr) - hgrCopyDst(i > 6 ?? 1 :: 0, 0, bytewidth, h, sprtptr=>s_map[i]) hgrColor(7) + hgrRect(0, 0, w + 21, h - 1) + spriteBLTMask(i, 0, w, h, srcptr) + hgrCopyDst(i > 6 ?? 1 :: 0, 0, bytewidth, h, sprtptr=>s_mask[i]) + hgrColor(0) hgrRect(0, h, w + 21, h * 2 - 1) - spriteBLTMask(i, h, w, h, srcptr) - hgrCopyDst(i > 6 ?? 1 :: 0, h, bytewidth, h, sprtptr=>s_mask[i]) + hgrBLT(i, h, w, h, srcptr) + hgrCopyDst(i > 6 ?? 1 :: 0, h, bytewidth, h, sprtptr=>s_map[i]) next return sprtptr end diff --git a/src/makefile b/src/makefile index 5bda359..be94b47 100755 --- a/src/makefile +++ b/src/makefile @@ -15,6 +15,7 @@ CMDJIT = rel/apple/CMD128\#061000 PLVMZP_C64 = vmsrc/c64/plvmzp.inc PLVMC64 = rel/c64/PLASMA ED = rel/ED\#FE1000 +ZIP = rel/apple/ZIP\#FE1000 JIT = rel/apple/JIT\#FE1000 JIT16 = rel/apple/JIT16\#FE1000 JITUNE = rel/apple/JITUNE\#FE1000 @@ -103,7 +104,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(MATCHFILES) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(ZIP) $(MATCHFILES) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -437,43 +438,43 @@ $(HGRSPRITE): libsrc/apple/hgrsprite.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/hgrsprite.pla > libsrc/apple/hgrsprite.a acme --setpc 4094 -o $(HGRSPRITE) libsrc/apple/hgrsprite.a -$(HGRTEST): samplesrc/hgrtest.pla $(PLVM02) $(PLASM) +$(HGRTEST): samplesrc/hgrtest.pla $(HGRLIB) $(PLASM) ./$(PLASM) -AMOW < samplesrc/hgrtest.pla > samplesrc/hgrtest.a acme --setpc 4094 -o $(HGRTEST) samplesrc/hgrtest.a -$(GRTEST): samplesrc/grtest.pla $(PLVM02) $(PLASM) +$(GRTEST): samplesrc/grtest.pla $(GRLIB) $(PLASM) ./$(PLASM) -AMOW < samplesrc/grtest.pla > samplesrc/grtest.a acme --setpc 4094 -o $(GRTEST) samplesrc/grtest.a -$(DGRTEST): samplesrc/dgrtest.pla $(PLVM02) $(PLASM) +$(DGRTEST): samplesrc/dgrtest.pla $(DGRLIB) $(PLASM) ./$(PLASM) -AMOW < samplesrc/dgrtest.pla > samplesrc/dgrtest.a acme --setpc 4094 -o $(DGRTEST) samplesrc/dgrtest.a -$(MON): utilsrc/apple/mon.pla $(PLVM02) $(PLASM) +$(MON): utilsrc/apple/mon.pla $(PLASM) ./$(PLASM) -AMOW < utilsrc/apple/mon.pla > utilsrc/apple/mon.a acme --setpc 4094 -o $(MON) utilsrc/apple/mon.a -$(COPY): utilsrc/apple/copy.pla $(PLVM03) $(PLASM) +$(COPY): utilsrc/apple/copy.pla $(PLASM) ./$(PLASM) -AMOW < utilsrc/apple/copy.pla > utilsrc/apple/copy.a acme --setpc 4094 -o $(COPY) utilsrc/apple/copy.a -$(DEL): utilsrc/apple/del.pla $(PLVM03) $(PLASM) +$(DEL): utilsrc/apple/del.pla $(PLASM) ./$(PLASM) -AMOW < utilsrc/apple/del.pla > utilsrc/apple/del.a acme --setpc 4094 -o $(DEL) utilsrc/apple/del.a -$(REN): utilsrc/apple/ren.pla $(PLVM03) $(PLASM) +$(REN): utilsrc/apple/ren.pla $(PLASM) ./$(PLASM) -AMOW < utilsrc/apple/ren.pla > utilsrc/apple/ren.a acme --setpc 4094 -o $(REN) utilsrc/apple/ren.a -$(CAT): utilsrc/apple/cat.pla $(PLVM03) $(PLASM) +$(CAT): utilsrc/apple/cat.pla $(PLASM) ./$(PLASM) -AMOW < utilsrc/apple/cat.pla > utilsrc/apple/cat.a acme --setpc 4094 -o $(CAT) utilsrc/apple/cat.a -$(NEWDIR): utilsrc/apple/newdir.pla $(PLVM03) $(PLASM) +$(NEWDIR): utilsrc/apple/newdir.pla $(PLASM) ./$(PLASM) -AMOW < utilsrc/apple/newdir.pla > utilsrc/apple/newdir.a acme --setpc 4094 -o $(NEWDIR) utilsrc/apple/newdir.a -$(TYPE): utilsrc/apple/type.pla $(PLVM03) $(PLASM) +$(TYPE): utilsrc/apple/type.pla $(PLASM) ./$(PLASM) -AMOW < utilsrc/apple/type.pla > utilsrc/apple/type.a acme --setpc 4094 -o $(TYPE) utilsrc/apple/type.a @@ -481,6 +482,10 @@ $(SOS): utilsrc/apple/sos.pla $(PLVM03) $(PLASM) ./$(PLASM) -AMOW < utilsrc/apple/sos.pla > utilsrc/apple/sos.a acme --setpc 4094 -o $(SOS) utilsrc/apple/sos.a +$(ZIP): utilsrc/apple/zip.pla $(PLASM) + ./$(PLASM) -AMOW < utilsrc/apple/zip.pla > utilsrc/apple/zip.a + acme --setpc 4094 -o $(ZIP) utilsrc/apple/zip.a + $(JIT): libsrc/apple/jit.pla libsrc/jitcore.pla $(PLVMJIT) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/jit.pla > libsrc/apple/jit.a acme --setpc 4094 -o $(JIT) libsrc/apple/jit.a diff --git a/src/mkrel b/src/mkrel index 48f9f7a..b188559 100755 --- a/src/mkrel +++ b/src/mkrel @@ -38,6 +38,7 @@ cp rel/apple/SNDSEQ#FE1000 prodos/sys/SNDSEQ.REL cp rel/apple/JIT#FE1000 prodos/sys/JIT.REL cp rel/apple/JIT16#FE1000 prodos/sys/JIT16.REL cp rel/apple/JITUNE#FE1000 prodos/sys/JITUNE.REL +cp rel/apple/ZIP#FE1000 prodos/sys/ZIP.REL cp rel/LZ4#FE1000 prodos/sys/LZ4.REL cp rel/TFTPD#FE1000 prodos/sys/TFTPD.REL cp rel/INT32#FE1000 prodos/sys/INT32.REL diff --git a/src/tftputil b/src/tftputil index 156f93b..5728816 100755 --- a/src/tftputil +++ b/src/tftputil @@ -11,3 +11,4 @@ echo "SYS/NEWDIR"; atftp $1 --put -l rel/apple/NEWDIR#FE1000 -r $2/SYS/NEWDIR# echo "SYS/TYPE"; atftp $1 --put -l rel/apple/TYPE#FE1000 -r $2/SYS/TYPE#FE1000 echo "SYS/MON"; atftp $1 --put -l rel/apple/MON#FE1000 -r $2/SYS/MON#FE1000 echo "SYS/SOS"; atftp $1 --put -l rel/apple/SOS#FE1000 -r $2/SYS/SOS#FE1000 +echo "SYS/ZIP"; atftp $1 --put -l rel/apple/ZIP#FE1000 -r $2/SYS/ZIP#FE1000 diff --git a/src/utilsrc/apple/copy.pla b/src/utilsrc/apple/copy.pla index d74d2be..1985a32 100644 --- a/src/utilsrc/apple/copy.pla +++ b/src/utilsrc/apple/copy.pla @@ -119,72 +119,77 @@ def copyfiles(srcfile, dstfile)#0 srcpath = srcpath - wildname fin entrylist, entrycnt = matchList(@srcpath, @wildname) - entry = entrylist - while entrycnt - strcpy(@srcfilepath, @srcpath) - strcat(@srcfilepath, entry) - strcpy(@dstfilepath, dstfile) - if chkdstpath(@dstfilepath) - strcat(@dstfilepath, entry) - fin - if entry->entry_type == $0F - // - // Source is a directory and not referencing the destination - // - if pathdiff(@srcfilepath, dstfile) - fileio:create(@dstfilepath, $0F, $0000) - if not chkdstpath(@dstfilepath) - puts("Unable to create directory: "); puts(@dstfilepath); putln - throw(exit, TRUE) - fin - if recurse - copyfiles(@srcfilepath, @dstfilepath) - fin + if not entrylist + puts(srcfile); puts(" ???\n") + else + entry = entrylist + while entrycnt + strcpy(@srcfilepath, @srcpath) + strcat(@srcfilepath, entry) + strcpy(@dstfilepath, dstfile) + if chkdstpath(@dstfilepath) + strcat(@dstfilepath, entry) fin - else - // - // Check if destination file exists - // - if fileio:getfileinfo(@dstfilepath, @dstfileinfo) == FILE_ERR_OK - fileio:destroy(@dstfilepath) - fin - // - // Create the destination file and open for writing - // - if fileio:create(@dstfilepath, entry->entry_type, entry=>entry_aux) <> FILE_ERR_OK - puts("Unable to create file: "); puts(@dstfilepath); putln - throw(exit, TRUE) - fin - srcref = fileio:open(@srcfilepath) - if not srcref - puts("Unable to open file: "); puts(@srcfilepath); putln - throw(exit, TRUE) - fin - dstref = fileio:open(@dstfilepath) - if not dstref - puts("Unable to open file: "); puts(@dstfilepath); putln - throw(exit, TRUE) - fin - // - // Let the copying begin - // - repeat - copyxfer = fileio:read(srcref, copybuff, copysize) - if copyxfer - if fileio:write(dstref, copybuff, copyxfer) <> copyxfer - puts("Error writing: "); puts(@dstfilepath); putln + if entry->entry_type == $0F + // + // Source is a directory and not referencing the destination + // + if pathdiff(@srcfilepath, dstfile) + fileio:create(@dstfilepath, $0F, $0000) + if not chkdstpath(@dstfilepath) + puts("Unable to create directory: "); puts(@dstfilepath); putln throw(exit, TRUE) fin + if recurse + copyfiles(@srcfilepath, @dstfilepath) + fin fin - until copyxfer == 0 - fileio:close(dstref) - fileio:close(srcref) - puts(@srcfilepath); puts(" ==> "); puts(@dstfilepath); putln - fin - entry = entry + t_fileentry - entrycnt-- - loop - heaprelease(entrylist) + else + puts(@srcfilepath) + // + // Check if destination file exists + // + if fileio:getfileinfo(@dstfilepath, @dstfileinfo) == FILE_ERR_OK + fileio:destroy(@dstfilepath) + fin + // + // Create the destination file and open for writing + // + if fileio:create(@dstfilepath, entry->entry_type, entry=>entry_aux) <> FILE_ERR_OK + puts("\nUnable to create file: "); puts(@dstfilepath); putln + throw(exit, TRUE) + fin + srcref = fileio:open(@srcfilepath) + if not srcref + puts("\nUnable to open file: "); puts(@srcfilepath); putln + throw(exit, TRUE) + fin + dstref = fileio:open(@dstfilepath) + if not dstref + puts("\nUnable to open file: "); puts(@dstfilepath); putln + throw(exit, TRUE) + fin + // + // Let the copying begin + // + repeat + copyxfer = fileio:read(srcref, copybuff, copysize) + if copyxfer + if fileio:write(dstref, copybuff, copyxfer) <> copyxfer + puts("\nError writing: "); puts(@dstfilepath); putln + throw(exit, TRUE) + fin + fin + until copyxfer == 0 + fileio:close(dstref) + fileio:close(srcref) + puts(" ==> "); puts(@dstfilepath); putln + fin + entry = entry + t_fileentry + entrycnt-- + loop + heaprelease(entrylist) + fin end // // Install error exit diff --git a/src/utilsrc/apple/zip.pla b/src/utilsrc/apple/zip.pla new file mode 100644 index 0000000..c8a2311 --- /dev/null +++ b/src/utilsrc/apple/zip.pla @@ -0,0 +1,51 @@ +include "inc/cmdsys.plh" +include "inc/args.plh" +// +// ZIP Chip control +// +var arg, status, slots, clock, state, cache + +byte _unlock[] +byte = $A9, $5A // LDA #$5A +byte = $8D, $5A, $C0 // STA $C05A +byte = $8D, $5A, $C0 // STA $C05A +byte = $8D, $5A, $C0 // STA $C05A +byte = $8D, $5A, $C0 // STA $C05A +byte = $60 // RTS + +def unlock#0 + (@_unlock)()#0 // Unlock regs (has to be machine code) +end +def lock#0 + ^$C05A = $A5 // Lock regs +end +arg = argNext(argFirst) +if ^arg + when toupper(arg->[1]) + is 'S' // Slow to 1 MHz + unlock + ^$C05A = $00 + lock + puts("Slow speed\n") + break + is 'F' // Enable acceleration + unlock + ^$C05B = $FF + lock + puts("Fast speed\n") + break + wend +fin +unlock +status = ^$C05B +slots = ^$C05C +clock = ^$C05D +state = ^$C05E +cache = ^$C05F +lock +puts("Status: $"); puth(status); putln +puts("Slots: $"); puth(slots); putln +puts("Clock: $"); puth(clock); putln +puts("State: $"); puth(state); putln +puts("Cache: $"); puth(cache); putln +done From b006e18d263484c0635471ee6a44841bfa661102 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sat, 4 Jan 2020 16:58:51 -0800 Subject: [PATCH 119/149] Fun with the graphics libraries --- src/makefile | 7 +- src/mkrel | 2 + src/samplesrc/sfm.pla | 204 +++++++++++++++++++++++++++++++++++++++++- src/tftpbld | 1 + src/tftpdemos | 1 + 5 files changed, 213 insertions(+), 2 deletions(-) diff --git a/src/makefile b/src/makefile index be94b47..fdd4797 100755 --- a/src/makefile +++ b/src/makefile @@ -65,6 +65,7 @@ DGRLIB = rel/apple/DGRLIB\#FE1000 HGRSPRITE = rel/apple/HGRSPRITE\#FE1000 LINES = rel/LINES\#FE1000 GRAFIX = rel/apple/GRAFIX\#FE1000 +SFM = rel/apple/SFM\#FE1000 GFXDEMO = rel/apple/GFXDEMO\#FE1000 JOYBUZZ = rel/apple/JOYBUZZ\#FE1000 PORTIO = rel/apple/PORTIO\#FE1000 @@ -104,7 +105,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(ZIP) $(MATCHFILES) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(ZIP) $(MATCHFILES) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(SFM) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -258,6 +259,10 @@ $(LONGJMP): libsrc/longjmp.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/longjmp.pla > libsrc/longjmp.a acme --setpc 4094 -o $(LONGJMP) libsrc/longjmp.a +$(SFM): samplesrc/sfm.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < samplesrc/sfm.pla > samplesrc/sfm.a + acme --setpc 4094 -o $(SFM) samplesrc/sfm.a + $(ROGUE): samplesrc/rogue.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/rogue.pla > samplesrc/rogue.a acme --setpc 4094 -o $(ROGUE) samplesrc/rogue.a diff --git a/src/mkrel b/src/mkrel index b188559..aa184cf 100755 --- a/src/mkrel +++ b/src/mkrel @@ -75,6 +75,7 @@ cp rel/apple/HGRTEST#FE1000 prodos/demos/HGRTEST.REL cp rel/apple/GRTEST#FE1000 prodos/demos/GRTEST.REL cp rel/apple/DGRTEST#FE1000 prodos/demos/DGRTEST.REL cp rel/apple/HGRTEST#FE1000 prodos/demos/HGRTEST.REL +cp rel/apple/SFM#FE1000 prodos/demos/SFM.REL cp rel/apple/ROD#FE1000 prodos/demos/ROD.REL cp rel/RPNCALC#FE1000 prodos/demos/RPNCALC.REL cp rel/LZ4CAT#FE1000 prodos/demos/LZ4CAT.REL @@ -132,6 +133,7 @@ cp samplesrc/rpncalc.pla prodos/bld/samples/RPNCALC.PLA.TXT cp samplesrc/fatcat.pla prodos/bld/samples/FATCAT.PLA.TXT cp samplesrc/gfxdemo.pla prodos/bld/samples/GFXDEMO.PLA.TXT cp samplesrc/lz4cat.pla prodos/bld/samples/Z4CAT.PLA.TXT +cp samplesrc/sfm.pla prodos/bld/samples/SFM.PLA.TXT #mkdir prodos/bld/examples #cp samplesrc/examples/ex.1.pla prodos/bld/examples/EX.1.PLA.TXT diff --git a/src/samplesrc/sfm.pla b/src/samplesrc/sfm.pla index 8e4dc61..d4d35a6 100644 --- a/src/samplesrc/sfm.pla +++ b/src/samplesrc/sfm.pla @@ -1 +1,203 @@ -include "inc/cmdsys.plh" include "inc/hgrlib.plh" include "inc/hgrsprite.plh" include "inc/lines.plh" include "inc/joybuzz.plh" sysflags reshgr1|reshgr2 // Reserve HGR page 1 and 2 byte egg = $88,$83,$33,$33,$38,$88 byte = $88,$33,$11,$11,$33,$88 byte = $83,$31,$11,$11,$13,$38 byte = $33,$11,$11,$11,$11,$33 byte = $33,$11,$11,$11,$11,$33 byte = $33,$11,$11,$11,$11,$33 byte = $33,$11,$11,$11,$11,$33 byte = $83,$31,$11,$11,$13,$38 byte = $88,$33,$11,$11,$33,$88 byte = $88,$83,$33,$33,$38,$88 byte dummy = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte ship = $CC,$CC,$CC,$77,$CC,$CC,$CC byte = $CC,$CC,$C7,$77,$7C,$CC,$CC byte = $CC,$CC,$C7,$77,$7C,$CC,$CC byte = $CC,$CC,$C7,$77,$7C,$CC,$CC byte = $CC,$CC,$C7,$77,$7C,$CC,$CC byte = $77,$CC,$77,$66,$77,$CC,$77 byte = $77,$CC,$77,$66,$77,$CC,$77 byte = $77,$CC,$77,$66,$77,$CC,$77 byte = $77,$CC,$77,$77,$77,$CC,$77 byte = $77,$CC,$77,$77,$77,$CC,$77 byte = $77,$CC,$77,$77,$77,$CC,$77 byte = $77,$C7,$77,$77,$77,$7C,$77 byte = $77,$77,$77,$77,$77,$77,$77 byte = $77,$77,$75,$55,$57,$77,$77 byte missle = $CC,$55,$CC byte = $CC,$55,$CC byte = $CC,$55,$CC byte = $CC,$55,$CC byte = $CC,$55,$CC byte = $CC,$55,$CC byte = $C5,$55,$5C byte = $55,$55,$55 var sprtEgg, sprtShip, sprtMissle, sprtDummy def moire#0 var i setlinespans(@hgrHlin, @hgrVlin) setlineplot(@hgrXorPlot) hgrColor(7) for i = 0 to 191 step 8 linespans(0, i, 279, 191 - i) next for i = 0 to 279 step 9 linespans(i, 0, 279 - i, 191) next end def game(eggnum)#0 var[14] xegg, yegg, ixegg, iyegg var xship, xmissle byte yship, ymissle byte k, xdelta, ydelta, btn0, btn1 xship = 140 ymissle = 255 xegg[0] = 100 ixegg[0] = 1 yegg[0] = 60 iyegg[0] = -1 for k = 1 to 13 xegg[k] = ((xegg[k - 1] ^ 37) + 97) & 255 ixegg[k] = -ixegg[k - 1] yegg[k] = ((yegg[k - 1] ^ 29) + 53) & 63 iyegg[k] = -iyegg[k - 1] next repeat for k = 0 to 13 if yegg[k] <> 255 xegg[k] = xegg[k] + ixegg[k] if xegg[k] < -5 or xegg[k] > 284 ixegg[k] = -ixegg[k] fin yegg[k] = yegg[k] + iyegg[k] if yegg[k] < -5 or yegg[k] > 64 iyegg[k] = -iyegg[k] fin spritePosIndex(xegg[k], yegg[k], k+2) fin next xdelta, ydelta, btn0, btn1 = joypos(ymissle/4) xship = xship + (xdelta / 4 - 10) if xship < 0; xship = 0; fin if xship > 279; xship = 279; fin if btn0 and ymissle == 255 spriteAdd(1, sprtMissle) xmissle = xship ymissle = 172 fin if ymissle <> 255 if ymissle < 8 spriteDel(1) ymissle = 255 else ymissle = ymissle - 8 spritePosIndex(xmissle, ymissle, 1) for k = 0 to 13 if yegg[k] <> 255 if ymissle >= yegg[k] - 5 and ymissle <= yegg[k] + 5 if xmissle >= xegg[k] - 5 and xmissle <= xegg[k] + 5 // // Hit // yegg[k] = 255 ymissle = 255 spriteAdd(k + 2, spriteDup(sprtDummy)) spritePosIndex(0, 0, k + 2) spriteDel(1) fin fin fin next fin fin spritePosIndex(xship, 190, 0) spriteDrawList() spriteDrawBuf(hgrSwap()) until ^$C000 > 127 end hgrMode spriteDrawBuf(hgrDrawBuf(0)) // So we can see the compile process sprtShip = spriteCompile(14, 14, 7, 13, @ship) sprtMissle = spriteCompile( 6, 8, 3, 0, @missle) sprtEgg = spriteCompile(12, 10, 6, 5, @egg) sprtDummy = spriteCompile( 7, 8, 0, 0, @dummy) hgrColor(8) hgrClear() moire memcpy($4000, $2000, $2000) // Copy to both buffers spriteDrawBuf(hgrDrawBuf(1)) spriteAdd(0, sprtShip) spriteAdd(2, sprtEgg) spriteAdd(3, spriteDup(sprtEgg)) spriteAdd(4, spriteDup(sprtEgg)) spriteAdd(5, spriteDup(sprtEgg)) spriteAdd(6, spriteDup(sprtEgg)) spriteAdd(7, spriteDup(sprtEgg)) spriteAdd(8, spriteDup(sprtEgg)) spriteAdd(9, spriteDup(sprtEgg)) spriteAdd(10, spriteDup(sprtEgg)) spriteAdd(11, spriteDup(sprtEgg)) spriteAdd(12, spriteDup(sprtEgg)) spriteAdd(13, spriteDup(sprtEgg)) spriteAdd(14, spriteDup(sprtEgg)) spriteAdd(15, spriteDup(sprtEgg)) game(14) getc txtMode done \ No newline at end of file +include "inc/cmdsys.plh" +include "inc/hgrlib.plh" +include "inc/hgrsprite.plh" +include "inc/lines.plh" +include "inc/joybuzz.plh" +sysflags reshgr1|reshgr2 // Reserve HGR page 1 and 2 + +byte egg = $88,$88,$83,$33,$33,$33,$33,$38,$88,$88 +byte = $88,$83,$33,$11,$11,$11,$11,$33,$38,$88 +byte = $83,$31,$11,$11,$11,$11,$11,$11,$13,$38 +byte = $33,$11,$11,$11,$11,$11,$11,$11,$11,$33 +byte = $33,$11,$11,$11,$11,$11,$11,$11,$11,$33 +byte = $33,$11,$11,$11,$11,$11,$11,$11,$11,$33 +byte = $33,$11,$11,$11,$11,$11,$11,$11,$11,$33 +byte = $83,$31,$11,$11,$11,$11,$11,$11,$13,$38 +byte = $88,$83,$33,$11,$11,$11,$11,$33,$38,$88 +byte = $88,$88,$83,$33,$33,$33,$33,$38,$88,$88 +byte spider = $33,$88,$88,$33,$33,$33,$33,$88,$88,$33 +byte = $33,$88,$83,$32,$22,$22,$23,$38,$88,$33 +byte = $83,$38,$83,$32,$22,$22,$23,$38,$83,$38 +byte = $88,$83,$33,$22,$22,$22,$22,$33,$38,$88 +byte = $33,$88,$33,$22,$22,$22,$22,$33,$88,$33 +byte = $88,$33,$38,$33,$22,$22,$33,$83,$33,$88 +byte = $88,$88,$83,$33,$22,$22,$33,$38,$88,$88 +byte = $88,$33,$33,$33,$22,$22,$33,$33,$33,$88 +byte = $33,$88,$88,$88,$33,$33,$88,$88,$88,$33 +byte = $88,$88,$33,$33,$22,$22,$33,$33,$88,$88 +byte = $88,$33,$88,$33,$22,$22,$33,$88,$33,$88 +byte = $33,$88,$88,$83,$32,$23,$38,$88,$88,$33 +byte = $88,$88,$88,$88,$33,$33,$88,$88,$88,$88 +byte web1 = $88,$83,$38,$88 +byte = $88,$38,$83,$88 +byte = $88,$38,$83,$88 +byte = $88,$33,$33,$88 +byte = $83,$38,$83,$38 +byte = $83,$38,$83,$38 +byte = $83,$38,$83,$38 +byte = $33,$33,$33,$33 +byte web2 = $88,$33,$83,$38,$33,$88 +byte = $88,$38,$83,$38,$83,$88 +byte = $83,$38,$83,$38,$83,$38 +byte = $83,$33,$33,$33,$33,$38 +byte = $83,$38,$83,$38,$83,$38 +byte = $83,$38,$83,$38,$83,$38 +byte = $33,$88,$83,$38,$88,$33 +byte = $33,$33,$33,$33,$33,$33 +byte ship = $CC,$CC,$CC,$77,$CC,$CC,$CC +byte = $CC,$CC,$C7,$77,$7C,$CC,$CC +byte = $CC,$CC,$C7,$77,$7C,$CC,$CC +byte = $CC,$CC,$C7,$77,$7C,$CC,$CC +byte = $CC,$CC,$C7,$77,$7C,$CC,$CC +byte = $77,$CC,$77,$66,$77,$CC,$77 +byte = $77,$CC,$77,$66,$77,$CC,$77 +byte = $77,$CC,$77,$66,$77,$CC,$77 +byte = $77,$CC,$77,$77,$77,$CC,$77 +byte = $77,$CC,$77,$77,$77,$CC,$77 +byte = $77,$CC,$77,$77,$77,$CC,$77 +byte = $77,$C7,$77,$77,$77,$7C,$77 +byte = $77,$77,$75,$55,$57,$77,$77 +byte = $77,$77,$75,$55,$57,$77,$77 +byte missle = $CC,$55,$CC +byte = $CC,$55,$CC +byte = $CC,$55,$CC +byte = $CC,$55,$CC +byte = $CC,$55,$CC +byte = $CC,$55,$CC +byte = $C5,$55,$5C +byte = $55,$55,$55 +byte dummy = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +var sprtEgg, sprtSpider, sprtShip, sprtMissle, sprtDummy + +def moire#0 + var i + + setlinespans(@hgrHlin, @hgrVlin) + setlineplot(@hgrPlot) + hgrColor(7) + for i = 0 to 191 step 8 + linespans(0, i, 279, 191 - i) + next + for i = 0 to 279 step 9 + linespans(i, 0, 279 - i, 191) + next +end +def game(spdrcnt)#0 + var[14] xspdr, yspdr, ixspdr, iyspdr, hatch + var xship, xmissle + byte yship, ymissle + byte spdrnum, k, xdelta, ydelta, btn0, btn1 + + xship = 140 + ymissle = 255 + xspdr[0] = 100 + ixspdr[0] = 1 + yspdr[0] = 60 + iyspdr[0] = -1 + hatch[0] = 1 + spdrnum = spdrcnt - 1 + for k = 1 to spdrnum + spriteAdd(k + 2, spriteDup(sprtEgg)) + xspdr[k] = ((xspdr[k - 1] ^ 37) + 97) & 255 + ixspdr[k] = -ixspdr[k - 1] + yspdr[k] = ((yspdr[k - 1] ^ 29) + 53) & 63 + iyspdr[k] = -iyspdr[k - 1] + hatch[k] = hatch[k - 1] + 1 + next + repeat + for k = 0 to spdrnum + if yspdr[k] <> 255 + //xspdr[k] = xspdr[k] + ixspdr[k] + if ixspdr[k] > 0 + xspdr[k] = xspdr[k] + yspdr[k] / 8 + else + xspdr[k] = xspdr[k] - yspdr[k] / 8 + fin + if xspdr[k] < -5 or xspdr[k] > 284 + ixspdr[k] = -ixspdr[k] + fin + yspdr[k] = yspdr[k] + iyspdr[k] + if yspdr[k] < -5 + iyspdr[k] = -iyspdr[k] + if hatch[k] + hatch[k]-- + if hatch[k] == 0 + spriteAdd(k + 2, spriteDup(sprtSpider)) + fin + fin + fin + if yspdr[k] > 64 + iyspdr[k] = -iyspdr[k] + fin + spritePosIndex(xspdr[k], yspdr[k], k+2) + fin + next + xdelta, ydelta, btn0, btn1 = joypos(ymissle/4) + xship = xship + (xdelta / 4 - 10) + if xship < 0; xship = 0; fin + if xship > 279; xship = 279; fin + if btn0 and ymissle == 255 + spriteAdd(1, sprtMissle) + xmissle = xship + ymissle = 172 + fin + if ymissle <> 255 + if ymissle < 8 + spriteDel(1) + ymissle = 255 + else + ymissle = ymissle - 8 + spritePosIndex(xmissle, ymissle, 1) + for k = 0 to spdrnum + if yspdr[k] <> 255 + if ymissle >= yspdr[k] - 7 and ymissle <= yspdr[k] + 6 + if xmissle >= xspdr[k] - 10 and xmissle <= xspdr[k] + 9 + // + // Hit + // + yspdr[k] = 255 + ymissle = 255 + spriteAdd(k + 2, spriteDup(sprtDummy)) + spritePosIndex(0, 0, k + 2) + spriteDel(1) + spdrcnt-- + if not spdrcnt + return + fin + fin + fin + fin + next + fin + fin + spritePosIndex(xship, 190, 0) + spriteDrawList() + spriteDrawBuf(hgrSwap()) + until ^$C000 > 127 + getc +end + +hgrMode +spriteDrawBuf(hgrDrawBuf(0)) // So we can see the compile process +sprtShip = spriteCompile(14, 14, 7, 13, @ship) +sprtMissle = spriteCompile( 6, 8, 3, 0, @missle) +sprtEgg = spriteCompile(20, 10, 10, 5, @egg) +sprtSpider = spriteCompile(20, 13, 10, 6, @spider) +sprtDummy = spriteCompile( 7, 8, 0, 0, @dummy) +hgrColor(4) +hgrClear() +moire +memcpy($4000, $2000, $2000) // Copy to both buffers +spriteDrawBuf(hgrDrawBuf(1)) +spriteAdd(0, sprtShip) +spriteAdd(2, sprtEgg) +game(4) +txtMode +done diff --git a/src/tftpbld b/src/tftpbld index eae19c2..716af76 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -53,4 +53,5 @@ echo "BLD/SAMPLES/MEMTEST.PLA"; atftp $1 --put -l samplesrc/memtest.pla -r $ echo "BLD/SAMPLES/FATCAT.PLA"; atftp $1 --put -l samplesrc/fatcat.pla -r $2/BLD/SAMPLES/FATCAT.PLA#040000 echo "BLD/SAMPLES/GFXDEMO.PLA"; atftp $1 --put -l samplesrc/gfxdemo.pla -r $2/BLD/SAMPLES/GFXDEMO.PLA#040000 echo "BLD/SAMPLES/LZ4CAT.PLA"; atftp $1 --put -l samplesrc/lz4cat.pla -r $2/BLD/SAMPLES/LZ4CAT.PLA#040000 +echo "BLD/SAMPLES/SFM.PLA"; atftp $1 --put -l samplesrc/sfm.pla -r $2/BLD/SAMPLES/SFM.PLA#040000 diff --git a/src/tftpdemos b/src/tftpdemos index 8e010d8..bf22589 100755 --- a/src/tftpdemos +++ b/src/tftpdemos @@ -9,6 +9,7 @@ echo "DEMOS/HGRTEST"; atftp $1 --put -l rel/apple/HGRTEST#FE1000 echo "DEMOS/GRTEST"; atftp $1 --put -l rel/apple/GRTEST#FE1000 -r $2/DEMOS/GRTEST#FE1000 echo "DEMOS/INT32TEST"; atftp $1 --put -l rel/INT32TEST#FE1000 -r $2/DEMOS/INT32TEST#FE1000 echo "DEMOS/DGRTEST"; atftp $1 --put -l rel/apple/DGRTEST#FE1000 -r $2/DEMOS/DGRTEST#FE1000 +echo "DEMOS/SFM"; atftp $1 --put -l rel/apple/SFM#FE1000 -r $2/DEMOS/SFM#FE1000 # Music demo echo "DEMOS/MUSIC/PLAYSEQ"; atftp $1 --put -l rel/apple/PLAYSEQ#FE1000 -r $2/DEMOS/MUSIC/PLAYSEQ#FE1000 From 1fe619134353902a30f298f7038ce33f82c194bb Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 4 Jan 2020 19:51:39 -0800 Subject: [PATCH 120/149] More pixmaps --- src/samplesrc/sfm.pla | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/samplesrc/sfm.pla b/src/samplesrc/sfm.pla index d4d35a6..3f58f66 100644 --- a/src/samplesrc/sfm.pla +++ b/src/samplesrc/sfm.pla @@ -44,6 +44,14 @@ byte = $83,$38,$83,$38,$83,$38 byte = $83,$38,$83,$38,$83,$38 byte = $33,$88,$83,$38,$88,$33 byte = $33,$33,$33,$33,$33,$33 +byte web3 = $88,$83,$38,$88,$88,$88,$88,$83,$38,$88 +byte = $88,$83,$38,$83,$38,$83,$38,$83,$38,$88 +byte = $88,$33,$88,$33,$88,$88,$33,$88,$33,$88 +byte = $88,$33,$33,$33,$33,$33,$33,$33,$33,$88 +byte = $83,$38,$88,$33,$83,$38,$33,$88,$83,$38 +byte = $83,$38,$83,$38,$83,$38,$83,$38,$83,$38 +byte = $33,$88,$83,$38,$83,$38,$83,$38,$88,$33 +byte = $33,$38,$33,$33,$33,$33,$33,$33,$33,$33 byte ship = $CC,$CC,$CC,$77,$CC,$CC,$CC byte = $CC,$CC,$C7,$77,$7C,$CC,$CC byte = $CC,$CC,$C7,$77,$7C,$CC,$CC @@ -74,7 +82,8 @@ byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 -var sprtEgg, sprtSpider, sprtShip, sprtMissle, sprtDummy +var sprtEgg, sprtSpider, sprtWeb1, sprtWeb2, sprtWeb3 +var sprtShip, sprtMissle, sprtDummy def moire#0 var i @@ -104,7 +113,7 @@ def game(spdrcnt)#0 hatch[0] = 1 spdrnum = spdrcnt - 1 for k = 1 to spdrnum - spriteAdd(k + 2, spriteDup(sprtEgg)) + spriteAdd(k + 8, spriteDup(sprtEgg)) xspdr[k] = ((xspdr[k - 1] ^ 37) + 97) & 255 ixspdr[k] = -ixspdr[k - 1] yspdr[k] = ((yspdr[k - 1] ^ 29) + 53) & 63 @@ -122,6 +131,11 @@ def game(spdrcnt)#0 fin if xspdr[k] < -5 or xspdr[k] > 284 ixspdr[k] = -ixspdr[k] + if xspdr[k] < -5 + xspdr[k] = -5 + else + xspdr[k] = 284 + fin fin yspdr[k] = yspdr[k] + iyspdr[k] if yspdr[k] < -5 @@ -129,14 +143,14 @@ def game(spdrcnt)#0 if hatch[k] hatch[k]-- if hatch[k] == 0 - spriteAdd(k + 2, spriteDup(sprtSpider)) + spriteAdd(k + 8, spriteDup(sprtSpider)) fin fin fin if yspdr[k] > 64 iyspdr[k] = -iyspdr[k] fin - spritePosIndex(xspdr[k], yspdr[k], k+2) + spritePosIndex(xspdr[k], yspdr[k], k + 8) fin next xdelta, ydelta, btn0, btn1 = joypos(ymissle/4) @@ -164,8 +178,8 @@ def game(spdrcnt)#0 // yspdr[k] = 255 ymissle = 255 - spriteAdd(k + 2, spriteDup(sprtDummy)) - spritePosIndex(0, 0, k + 2) + spriteAdd(k + 8, spriteDup(sprtDummy)) + spritePosIndex(0, 0, k + 8) spriteDel(1) spdrcnt-- if not spdrcnt @@ -178,7 +192,8 @@ def game(spdrcnt)#0 fin fin spritePosIndex(xship, 190, 0) - spriteDrawList() +// spriteDrawList() + spriteDrawXorList() spriteDrawBuf(hgrSwap()) until ^$C000 > 127 getc @@ -190,14 +205,18 @@ sprtShip = spriteCompile(14, 14, 7, 13, @ship) sprtMissle = spriteCompile( 6, 8, 3, 0, @missle) sprtEgg = spriteCompile(20, 10, 10, 5, @egg) sprtSpider = spriteCompile(20, 13, 10, 6, @spider) +sprtWeb1 = spriteCompile( 8, 8, 4, 0, @web1) +sprtWeb2 = spriteCompile(12, 8, 6, 0, @web2) +sprtWeb3 = spriteCompile(20, 8, 10, 0, @web3) sprtDummy = spriteCompile( 7, 8, 0, 0, @dummy) -hgrColor(4) +//hgrColor(4) +hgrColor(0) hgrClear() -moire +//moire memcpy($4000, $2000, $2000) // Copy to both buffers spriteDrawBuf(hgrDrawBuf(1)) spriteAdd(0, sprtShip) -spriteAdd(2, sprtEgg) -game(4) +spriteAdd(8, sprtEgg) +game(8) txtMode done From 42888ed95a0e00d6adaf4cf8cb9fcf3a5817b124 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 5 Jan 2020 14:43:58 -0800 Subject: [PATCH 121/149] When spiders attack --- src/libsrc/apple/hgrsprite.pla | 2 +- src/samplesrc/sfm.pla | 79 +++++++++++++++++++++++----------- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/src/libsrc/apple/hgrsprite.pla b/src/libsrc/apple/hgrsprite.pla index a07b6a3..316bc9b 100644 --- a/src/libsrc/apple/hgrsprite.pla +++ b/src/libsrc/apple/hgrsprite.pla @@ -129,7 +129,7 @@ export def spriteCompile(w, h, xcenter, ycenter, srcptr)#1 var sprtptr, bytewidth, spritesize, i sprtptr = heapalloc(t_sprite) - bytewidth = (w + 7) / 7 + 1 + bytewidth = (w + 13) / 7 sprtptr->s_pitch = bytewidth spritesize = bytewidth * h sprtptr=>s_size = spritesize diff --git a/src/samplesrc/sfm.pla b/src/samplesrc/sfm.pla index 3f58f66..6b4624d 100644 --- a/src/samplesrc/sfm.pla +++ b/src/samplesrc/sfm.pla @@ -100,17 +100,18 @@ def moire#0 end def game(spdrcnt)#0 var[14] xspdr, yspdr, ixspdr, iyspdr, hatch - var xship, xmissle + var xship, xmissle, attack byte yship, ymissle byte spdrnum, k, xdelta, ydelta, btn0, btn1 - xship = 140 - ymissle = 255 + xship = 140 + ymissle = 255 xspdr[0] = 100 ixspdr[0] = 1 yspdr[0] = 60 iyspdr[0] = -1 - hatch[0] = 1 + hatch[0] = 1 + attack = -1 spdrnum = spdrcnt - 1 for k = 1 to spdrnum spriteAdd(k + 8, spriteDup(sprtEgg)) @@ -123,23 +124,9 @@ def game(spdrcnt)#0 repeat for k = 0 to spdrnum if yspdr[k] <> 255 - //xspdr[k] = xspdr[k] + ixspdr[k] - if ixspdr[k] > 0 - xspdr[k] = xspdr[k] + yspdr[k] / 8 - else - xspdr[k] = xspdr[k] - yspdr[k] / 8 - fin - if xspdr[k] < -5 or xspdr[k] > 284 - ixspdr[k] = -ixspdr[k] - if xspdr[k] < -5 - xspdr[k] = -5 - else - xspdr[k] = 284 - fin - fin yspdr[k] = yspdr[k] + iyspdr[k] if yspdr[k] < -5 - iyspdr[k] = -iyspdr[k] + iyspdr[k] = 1 if hatch[k] hatch[k]-- if hatch[k] == 0 @@ -147,8 +134,48 @@ def game(spdrcnt)#0 fin fin fin - if yspdr[k] > 64 - iyspdr[k] = -iyspdr[k] + if yspdr[k] > 64 // Attack or not? + if hatch[k] == 0 and attack < 0 + attack = k + iyspdr[k] = 8 + fin + if attack == k + if yspdr[k] > 160 + iyspdr[k] = -8 // Retreat + fin + if iyspdr[k] > 0 // Attacking + xspdr[k] = xspdr[k] + (xship - xspdr[k]) / 8 + else // Retreating + if ixspdr[k] > 0 + xspdr[k] = xspdr[k] + (160 - yspdr[k]) / 8 + else + xspdr[k] = xspdr[k] - (160 - yspdr[k]) / 8 + fin + fin + else + iyspdr[k] = -1 + fin + else + if attack == k + attack = -1 // Stop attack + iyspdr[k] = -1 + fin + fin + if attack <> k + if ixspdr[k] > 0 + xspdr[k] = xspdr[k] + yspdr[k] / 8 + else + xspdr[k] = xspdr[k] - yspdr[k] / 8 + fin + if xspdr[k] < -5 or xspdr[k] > 284 + if xspdr[k] < -5 + xspdr[k] = -5 + ixspdr[k] = 1 + else + xspdr[k] = 284 + ixspdr[k] = -1 + fin + fin fin spritePosIndex(xspdr[k], yspdr[k], k + 8) fin @@ -160,7 +187,7 @@ def game(spdrcnt)#0 if btn0 and ymissle == 255 spriteAdd(1, sprtMissle) xmissle = xship - ymissle = 172 + ymissle = 176 fin if ymissle <> 255 if ymissle < 8 @@ -172,10 +199,13 @@ def game(spdrcnt)#0 for k = 0 to spdrnum if yspdr[k] <> 255 if ymissle >= yspdr[k] - 7 and ymissle <= yspdr[k] + 6 - if xmissle >= xspdr[k] - 10 and xmissle <= xspdr[k] + 9 + if xmissle >= xspdr[k] - 10 and xmissle <= xspdr[k] + 10 // // Hit // + if attack == k // Was it attacking? + attack = -1 + fin yspdr[k] = 255 ymissle = 255 spriteAdd(k + 8, spriteDup(sprtDummy)) @@ -195,7 +225,7 @@ def game(spdrcnt)#0 // spriteDrawList() spriteDrawXorList() spriteDrawBuf(hgrSwap()) - until ^$C000 > 127 + until ^$C000 == $9B getc end @@ -209,7 +239,6 @@ sprtWeb1 = spriteCompile( 8, 8, 4, 0, @web1) sprtWeb2 = spriteCompile(12, 8, 6, 0, @web2) sprtWeb3 = spriteCompile(20, 8, 10, 0, @web3) sprtDummy = spriteCompile( 7, 8, 0, 0, @dummy) -//hgrColor(4) hgrColor(0) hgrClear() //moire From e9a13117646a00a4f9521acb3675f101764aea9f Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 5 Jan 2020 20:30:02 -0800 Subject: [PATCH 122/149] Shooting spiderwebs --- src/samplesrc/sfm.pla | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/src/samplesrc/sfm.pla b/src/samplesrc/sfm.pla index 6b4624d..d7ce814 100644 --- a/src/samplesrc/sfm.pla +++ b/src/samplesrc/sfm.pla @@ -102,7 +102,7 @@ def game(spdrcnt)#0 var[14] xspdr, yspdr, ixspdr, iyspdr, hatch var xship, xmissle, attack byte yship, ymissle - byte spdrnum, k, xdelta, ydelta, btn0, btn1 + byte spdrnum, k, xdelta, ydelta, btn0, btn1, webstate xship = 140 ymissle = 255 @@ -112,6 +112,7 @@ def game(spdrcnt)#0 iyspdr[0] = -1 hatch[0] = 1 attack = -1 + webstate = 0 spdrnum = spdrcnt - 1 for k = 1 to spdrnum spriteAdd(k + 8, spriteDup(sprtEgg)) @@ -141,11 +142,43 @@ def game(spdrcnt)#0 fin if attack == k if yspdr[k] > 160 - iyspdr[k] = -8 // Retreat + // + // Iterate through web sequence + // + when webstate + is 10 + iyspdr[k] = -8 // Retreat + yspdr[k] = 160 + spriteDel(2) + spriteDel(3) + spriteDel(4) + webstate = 0 + break + is 0 + iyspdr[k] = 0 + spriteAdd(2, sprtWeb1) + spritePosIndex(xspdr[k], 160, 2) + webstate = 1 + break + is 1 + spriteAdd(3, sprtWeb2) + spritePosIndex(xspdr[k], 168, 3) + webstate = 2 + break + is 2 + spriteAdd(4, sprtWeb3) + spritePosIndex(xspdr[k], 176, 4) + webstate = 3 + otherwise + if xship >= xspdr[k] - 10 and xship <= xspdr[k] + 10 + return + fin + webstate++ + wend fin if iyspdr[k] > 0 // Attacking xspdr[k] = xspdr[k] + (xship - xspdr[k]) / 8 - else // Retreating + elsif iyspdr[k] < 0 // Retreating if ixspdr[k] > 0 xspdr[k] = xspdr[k] + (160 - yspdr[k]) / 8 else @@ -198,7 +231,7 @@ def game(spdrcnt)#0 spritePosIndex(xmissle, ymissle, 1) for k = 0 to spdrnum if yspdr[k] <> 255 - if ymissle >= yspdr[k] - 7 and ymissle <= yspdr[k] + 6 + if ymissle >= yspdr[k] - 15 and ymissle <= yspdr[k] + 5 if xmissle >= xspdr[k] - 10 and xmissle <= xspdr[k] + 10 // // Hit From 10cc631b0aa7dcb4050d78a84a66e4812a87f3ab Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Mon, 6 Jan 2020 16:09:25 -0800 Subject: [PATCH 123/149] More or less operational game --- src/inc/hgrlib.plh | 3 + src/libsrc/apple/hgrlib.pla | 262 +++++++++++++--- src/libsrc/apple/hgrsprite.pla | 40 ++- src/samplesrc/sfm.pla | 534 +++++++++++++++++++++++++-------- src/tftpbld | 4 +- 5 files changed, 677 insertions(+), 166 deletions(-) diff --git a/src/inc/hgrlib.plh b/src/inc/hgrlib.plh index b09a751..c3f0e6f 100644 --- a/src/inc/hgrlib.plh +++ b/src/inc/hgrlib.plh @@ -5,7 +5,10 @@ import hgrlib predef hgrXorPlot(x, y)#0 predef hgrHLin(x1, x2, y)#0 predef hgrVLin(y1, y2, x)#0 + predef hgrXorHLin(x1, x2, y)#0 + predef hgrXorVLin(y1, y2, x)#0 predef hgrRect(x1, y1, x2, y2)#0 + predef hgrXorRect(x1, y1, x2, y2)#0 predef hgrBLT(x, y, width, height, srcptr)#0 predef hgrCopySrc(ofst, y, w, h, srcptr)#0 predef hgrAndSrc(ofst, y, w, h, srcptr)#0 diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index fa79ca3..9a588e5 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -543,8 +543,6 @@ end asm _hgrPlotC LDA $1000,Y ; HBMASK STA TMPL - EOR #$FF - STA TMPH LDA ESTKL+1,X ; HORIZ OFFSET CMP #40 BCS + @@ -553,12 +551,10 @@ asm _hgrPlotC end asm _hgrPlotD LDA $2000,Y ; CURHCLR - AND TMPL - STA TMPL LDY ESTKL+1,X ; HORIZ OFFSET - LDA (DST),Y - AND TMPH - ORA TMPL + EOR (DST),Y + AND TMPL + EOR (DST),Y STA (DST),Y + INX INX @@ -601,8 +597,8 @@ asm _hgrXorPlotC end asm _hgrXorPlotD LDA $2000,Y ; CURHCLR - AND TMPL LDY ESTKL+1,X ; HORIZ OFFSET + AND TMPL EOR (DST),Y STA (DST),Y + INX @@ -646,8 +642,8 @@ asm _hgrOrPlotC end asm _hgrOrPlotD LDA $2000,Y ; CURHCLR - AND TMPL LDY ESTKL+1,X ; HORIZ OFFSET + AND TMPL ORA (DST),Y STA (DST),Y + INX @@ -713,6 +709,8 @@ end asm _hgrHLinD LDA $1000,Y ; HRMASK STA TMPH + LDA ESTKL+1,X ; RIGHT HORIZ OFFSET + STA IPY ; STEAL THIS ZP FOR A MOMENT INX INX INX @@ -739,47 +737,151 @@ asm _hgrHLinG STA SRCH LDA $2001 ; CURHCLRH STA SRCL -++ TYA - CMP ESTKL-1,X ; RIGHT HORIZ OFFSET +++ CPY IPY ; RIGHT HORIZ OFFSET BNE + - LDA TMPL + LDA SRCL + EOR (DST),Y + AND TMPL AND TMPH - STA TMPL - AND SRCL + EOR (DST),Y + STA (DST),Y + INX + INX + RTS ++ LDA SRCL ; CURHCLR + EOR (DST),Y + AND TMPL + EOR (DST),Y +- STA (DST),Y + INY + CPY IPY ; RIGHT HORIZ OFFSET + LDA SRCH + BCS + + STA (DST),Y + INY + CPY IPY ; RIGHT HORIZ OFFSET + LDA SRCL + BCC - ++ EOR (DST),Y + AND TMPH + EOR (DST),Y + STA (DST),Y + INX + INX + RTS +end +//export def hgrXorHLin(x1, x2, y)#0 +// word pixptr, x +// byte lofst, lpixofst, lpmask +// byte rofst, rpixofst, rpmask +// +// if x1 == x2 +// hgrPlot(x1, y) +// else +// lofst, lpixofst = divmod7(x1) +// pixptr = hgrscan[y] + drawbuff + lofst +// rofst, rpixofst = divmod7(x2) +// lpmask = hlmask[lpixofst] +// rpmask = hrmask[rpixofst] +// if lofst == rofst +// lpmask = lpmask & rpmask +// ^pixptr = ^pixptr ^ (curhclr.[pixptr.0 & 1] & lpmask) +// else +// ^pixptr = ^pixptr ^ (curhclr.[pixptr.0 & 1] & lpmask) +// pixptr++ +// for x = lofst + 1 to rofst - 1 +// ^pixptr = ^pixptr ^ curhclr.[pixptr.0 & 1] +// pixptr++ +// next +// ^pixptr = ^pixptr ^ (curhclr.[pixptr.0 & 1] & rpmask) +// fin +// fin +//end +export asm hgrXorHLin(x1, x2, y)#0 + LDA ESTKL+1 + CMP ESTKL+2 + BNE + + LDA ESTKH+1 + CMP ESTKH+2 + BNE + +end +asm _hgrXHLinA + JSR $F000 + INX + RTS ++ LDY ESTKL+0,X ; Y COORD +end +asm _hgrXHLinB + LDA $8000,Y ; HGRSCANL + STA DSTL + LDA $1000 ; DRAWBUFFH + ORA $9000,Y ; HGRSCANH + STA DSTH + LDA ESTKL+1,X + STA ESTKL+0,X + LDA ESTKH+1,X + STA ESTKH+0,X +end +asm _hgrXHLinC + JSR 1000 ; DIVMOD7 + LDY ESTKL+0,X ; RIGHT PIXEL OFFSET +end +asm _hgrXHLinD + LDA $1000,Y ; HRMASK STA TMPH - LDA TMPL - EOR #$FF - AND (DST),Y - ORA TMPH + LDA ESTKL+1,X ; RIGHT HORIZ OFFSET + STA IPY ; STEAL THIS ZP FOR A MOMENT + INX + INX + INX +end +asm _hgrXHLinE + JSR 1000 ; DIVMOD7 + LDY ESTKL+0,X ; LEFT PIXEL OFFSET +end +asm _hgrXHLinF + LDA $1000,Y ; HLMASK + STA TMPL + LDA ESTKL+1,X ; LEFT HORIZ OFFSET + TAY + LSR + BCS + +end +asm _hgrXHLinG + LDA $2000 ; CURHCLRL + STA SRCL + LDA $2001 ; CURHCLRH + STA SRCH + BCC ++ ++ LDA $2000 ; CURHCLRL + STA SRCH + LDA $2001 ; CURHCLRH + STA SRCL +++ CPY IPY ; RIGHT HORIZ OFFSET + BNE + + LDA SRCL + AND TMPL + EOR (DST),Y STA (DST),Y INX INX RTS + LDA SRCL ; CURHCLR AND TMPL - STA ESTKL+0,X - LDA TMPL - EOR #$FF - AND (DST),Y - ORA ESTKL+0,X -- STA (DST),Y - INY - TYA - CMP ESTKL-1,X ; RIGHT HORIZ OFFSET - LDA SRCH - BCS + +- EOR (DST),Y STA (DST),Y INY - TYA - CMP ESTKL-1,X ; RIGHT HORIZ OFFSET + CPY IPY ; RIGHT HORIZ OFFSET + LDA SRCH + BCS + + EOR (DST),Y + STA (DST),Y + INY + CPY IPY ; RIGHT HORIZ OFFSET LDA SRCL BCC - + AND TMPH - STA ESTKL+0,X - LDA TMPH - EOR #$FF - AND (DST),Y - ORA ESTKL+0,X + EOR (DST),Y STA (DST),Y INX INX @@ -845,6 +947,65 @@ asm _hgrVLinC INX RTS end +//export def hgrXVlin(y1, y2, x)#0 +// word pixptr, y, ofst +// byte pixofst, pmask, cmask +// +// if y1 == y2 +// hgrXorPlot(x, y1) +// else +// ofst, pixofst = divmod7(x) +// ofst = ofst + drawbuff +// pmask = hbmask[pixofst] +// cmask = curhclr.[ofst & 1] & pmask +// pmask = ~pmask +// for y = y1 to y2 +// pixptr = hgrscan[y] + ofst +// ^pixptr = ^pixptr ^ cmask +// next +// fin +//end +export asm hgrXorVlin(y1, y2, x)#0 + JSR 1000 ; DIVMOD7 + LDY ESTKL+0,X ; PIXEL OFFSET +end +asm _hgrXVLinA + LDA $1000,Y ; HBMASK + STA TMPL + EOR #$FF + STA TMPH + LDA ESTKL+1,X ; HORIZ OFFSET + AND #$01 + TAY +end +asm _hgrXVLinB + LDA $2000,Y ; CURHCLR + AND TMPL + STA TMPL + LDY ESTKL+3,X ; Y1 COORD +end +asm _hgrXVLinC +- LDA $8000,Y ; HGRSCANL + STA DSTL + LDA $1000 ; DRAWBUFFH + ORA $9000,Y ; HGRSCANH + STA DSTH + LDY ESTKL+1,X ; HORIZ OFFSET + LDA TMPL + EOR (DST),Y + STA (DST),Y + LDY ESTKL+3,X ; Y1 COORD + TYA + INY + STY ESTKL+3,X ; Y1 COORD + CMP ESTKL+2,X ; Y2 COORD + BNE - + INX + INX + INX + INX + RTS +end // // Masked BLT scanline of pixmap // @@ -949,6 +1110,17 @@ export def hgrRect(x1, y1, x2, y2)#0 next fin end +export def hgrXorRect(x1, y1, x2, y2)#0 + word y + + if x1 == x2 + hgrXorVLin(y1, y2, x1) + else + for y = y1 to y2 + hgrXorHLin(x1, x2, y) + next + fin +end export def hgrBLT(x, y, w, h, srcptr)#0 word i, j word saveclr @@ -1068,12 +1240,30 @@ _hgrHLinG:1 = @curhclr _hgrHLinG:6 = @curhclr.1 _hgrHLinG:13 = @curhclr.1 _hgrHLinG:18 = @curhclr +_hgrXHLinA:1 = @hgrXorPlot +_hgrXHLinB:1 = @hgrscanl +_hgrXHLinB:6 = @drawbuff.1 +_hgrXHLinB:9 = @hgrscanh +_hgrXHLinC:1 = @divmod7 +_hgrXHLinD:1 = @hrmask +_hgrXHLinE:1 = @divmod7 +_hgrXHLinF:1 = @hlmask +_hgrXHLinG:1 = @curhclr +_hgrXHLinG:6 = @curhclr.1 +_hgrXHLinG:13 = @curhclr.1 +_hgrXHLinG:18 = @curhclr hgrVLin:1 = @divmod7 _hgrVLinA:1 = @hbmask _hgrVLinB:1 = @curhclr _hgrVLinC:1 = @hgrscanl _hgrVLinC:6 = @drawbuff.1 _hgrVLinC:9 = @hgrscanh +hgrXorVLin:1 = @divmod7 +_hgrXVLinA:1 = @hbmask +_hgrXVLinB:1 = @curhclr +_hgrXVLinC:1 = @hgrscanl +_hgrXVLinC:6 = @drawbuff.1 +_hgrXVLinC:9 = @hgrscanh hgrColor:7 = @hcolor hgrColor:10 = @curhclr hgrColor:13 = @hcolor.1 diff --git a/src/libsrc/apple/hgrsprite.pla b/src/libsrc/apple/hgrsprite.pla index 316bc9b..4b6c03d 100644 --- a/src/libsrc/apple/hgrsprite.pla +++ b/src/libsrc/apple/hgrsprite.pla @@ -129,6 +129,7 @@ export def spriteCompile(w, h, xcenter, ycenter, srcptr)#1 var sprtptr, bytewidth, spritesize, i sprtptr = heapalloc(t_sprite) + if not sprtptr; return 0; fin bytewidth = (w + 13) / 7 sprtptr->s_pitch = bytewidth spritesize = bytewidth * h @@ -136,11 +137,15 @@ export def spriteCompile(w, h, xcenter, ycenter, srcptr)#1 sprtptr->s_height = h sprtptr->s_xcenter = xcenter sprtptr->s_ycenter = ycenter - sprtptr=>s_under[0] = heapalloc(spritesize) - sprtptr=>s_under[1] = heapalloc(spritesize) + sprtptr=>s_under[0] = 0//heapalloc(spritesize) + sprtptr=>s_under[1] = 0//heapalloc(spritesize) for i = 0 to 13 sprtptr=>s_map[i] = heapalloc(spritesize) sprtptr=>s_mask[i] = heapalloc(spritesize) + if not sprtptr=>s_map[i] or not sprtptr=>s_mask[i] + heaprelease(sprtptr) + return 0 + fin hgrColor(7) hgrRect(0, 0, w + 21, h - 1) spriteBLTMask(i, 0, w, h, srcptr) @@ -157,27 +162,33 @@ export def spriteDup(sprtsrc)#1 byte i sprtdup = heapalloc(t_sprite) + if not sprtdup; return 0; fin memcpy(sprtdup, sprtsrc, t_sprite) - spritesize = sprtdup=>s_size - sprtdup=>s_under[0] = heapalloc(spritesize) - sprtdup=>s_under[1] = heapalloc(spritesize) + //spritesize = sprtdup=>s_size + sprtdup=>s_under[0] = 0//heapalloc(spritesize) + sprtdup=>s_under[1] = 0//heapalloc(spritesize) return sprtdup end export def spriteRead(filestr)#1 var sprtptr, spritesize byte refnum, i - sprtptr = 0 + sprtptr = heapalloc(t_sprite) + if not sprtptr; return 0; fin refnum = fileio:open(@filestr) if refnum - sprtptr = heapalloc(t_sprite) if fileio:read(refnum, sprtptr, t_sprite) == t_sprite spritesize = sprtptr=>s_size sprtptr=>s_under[0] = heapalloc(spritesize) sprtptr=>s_under[1] = heapalloc(spritesize) + if not sprtptr=>s_under[0] or not sprtptr=>s_under[1] + heaprelease(sprtptr) + fileio:close(refnum) + return 0 + fin for i = 0 to 13 - sprtptr=>s_map[i] = heapalloc(spritesize) - sprtptr=>s_mask[i] = heapalloc(spritesize) + sprtptr=>s_map[i] = 0//heapalloc(spritesize) + sprtptr=>s_mask[i] = 0//heapalloc(spritesize) fileio:read(refnum, sprtptr=>s_map[i], spritesize) fileio:read(refnum, sprtptr=>s_mask[i], spritesize) next @@ -186,6 +197,9 @@ export def spriteRead(filestr)#1 sprtptr = 0 fin fileio:close(refnum) + else + heaprelease(sprtptr) + sprtptr = 0 fin return sprtptr end @@ -223,12 +237,18 @@ export def spriteDraw(sprtptr)#0 sprtptr=>s_undery[drawpage] = y pitch = sprtptr->s_pitch height = sprtptr->s_height + if not sprtptr=>s_under[drawpage] + sprtptr=>s_under[drawpage] = heapalloc(sprtptr=>s_size) + if not sprtptr=>s_under[drawpage]; return; fin + fin hgrCopyDst(ofst, y, pitch, height, sprtptr=>s_under[drawpage]) hgrAndSrc( ofst, y, pitch, height, sprtptr=>s_mask[map]) hgrXorSrc( ofst, y, pitch, height, sprtptr=>s_map[map]) end export def spriteUnDraw(sprtptr)#0 - hgrCopySrc(sprtptr=>s_underofst[drawpage], sprtptr=>s_undery[drawpage], sprtptr->s_pitch, sprtptr->s_height, sprtptr=>s_under[drawpage]) + if sprtptr=>s_under[drawpage] + hgrCopySrc(sprtptr=>s_underofst[drawpage], sprtptr=>s_undery[drawpage], sprtptr->s_pitch, sprtptr->s_height, sprtptr=>s_under[drawpage]) + fin end export def spriteDrawXor(sprtptr)#0 byte map, pitch, height diff --git a/src/samplesrc/sfm.pla b/src/samplesrc/sfm.pla index d7ce814..33980b9 100644 --- a/src/samplesrc/sfm.pla +++ b/src/samplesrc/sfm.pla @@ -1,57 +1,120 @@ include "inc/cmdsys.plh" include "inc/hgrlib.plh" include "inc/hgrsprite.plh" -include "inc/lines.plh" include "inc/joybuzz.plh" -sysflags reshgr1|reshgr2 // Reserve HGR page 1 and 2 +sysflags reshgr1 // Reserve HGR page 1 -byte egg = $88,$88,$83,$33,$33,$33,$33,$38,$88,$88 -byte = $88,$83,$33,$11,$11,$11,$11,$33,$38,$88 -byte = $83,$31,$11,$11,$11,$11,$11,$11,$13,$38 -byte = $33,$11,$11,$11,$11,$11,$11,$11,$11,$33 -byte = $33,$11,$11,$11,$11,$11,$11,$11,$11,$33 -byte = $33,$11,$11,$11,$11,$11,$11,$11,$11,$33 -byte = $33,$11,$11,$11,$11,$11,$11,$11,$11,$33 -byte = $83,$31,$11,$11,$11,$11,$11,$11,$13,$38 -byte = $88,$83,$33,$11,$11,$11,$11,$33,$38,$88 -byte = $88,$88,$83,$33,$33,$33,$33,$38,$88,$88 -byte spider = $33,$88,$88,$33,$33,$33,$33,$88,$88,$33 -byte = $33,$88,$83,$32,$22,$22,$23,$38,$88,$33 -byte = $83,$38,$83,$32,$22,$22,$23,$38,$83,$38 -byte = $88,$83,$33,$22,$22,$22,$22,$33,$38,$88 -byte = $33,$88,$33,$22,$22,$22,$22,$33,$88,$33 -byte = $88,$33,$38,$33,$22,$22,$33,$83,$33,$88 -byte = $88,$88,$83,$33,$22,$22,$33,$38,$88,$88 -byte = $88,$33,$33,$33,$22,$22,$33,$33,$33,$88 -byte = $33,$88,$88,$88,$33,$33,$88,$88,$88,$33 -byte = $88,$88,$33,$33,$22,$22,$33,$33,$88,$88 -byte = $88,$33,$88,$33,$22,$22,$33,$88,$33,$88 -byte = $33,$88,$88,$83,$32,$23,$38,$88,$88,$33 -byte = $88,$88,$88,$88,$33,$33,$88,$88,$88,$88 -byte web1 = $88,$83,$38,$88 -byte = $88,$38,$83,$88 -byte = $88,$38,$83,$88 -byte = $88,$33,$33,$88 -byte = $83,$38,$83,$38 -byte = $83,$38,$83,$38 -byte = $83,$38,$83,$38 -byte = $33,$33,$33,$33 -byte web2 = $88,$33,$83,$38,$33,$88 -byte = $88,$38,$83,$38,$83,$88 -byte = $83,$38,$83,$38,$83,$38 -byte = $83,$33,$33,$33,$33,$38 -byte = $83,$38,$83,$38,$83,$38 -byte = $83,$38,$83,$38,$83,$38 -byte = $33,$88,$83,$38,$88,$33 -byte = $33,$33,$33,$33,$33,$33 -byte web3 = $88,$83,$38,$88,$88,$88,$88,$83,$38,$88 -byte = $88,$83,$38,$83,$38,$83,$38,$83,$38,$88 -byte = $88,$33,$88,$33,$88,$88,$33,$88,$33,$88 -byte = $88,$33,$33,$33,$33,$33,$33,$33,$33,$88 -byte = $83,$38,$88,$33,$83,$38,$33,$88,$83,$38 -byte = $83,$38,$83,$38,$83,$38,$83,$38,$83,$38 -byte = $33,$88,$83,$38,$83,$38,$83,$38,$88,$33 -byte = $33,$38,$33,$33,$33,$33,$33,$33,$33,$33 +const NUMSTARS = 32 +const SHIP_SPRTNUM = 0 +const MISSLE_SPRTNUM = 1 +const WEB_SPRTBASE = 2 +const SPIDER_SPRTEBASE = 8 +const FULL_CHARGE = 20 +const ATTACK_SPEED = 12 +const SWARM_LIMIT = 52 +const FASTMOVE_LIMIT = 120 +const WEB_LIMIT = 152 +const YSHIP = 180 + +byte egg3 = $88,$88,$83,$33,$38,$88,$88 +byte = $88,$83,$33,$11,$33,$38,$88 +byte = $83,$31,$11,$11,$11,$13,$38 +byte = $33,$11,$11,$11,$11,$11,$33 +byte = $33,$11,$11,$11,$11,$11,$33 +byte = $33,$11,$11,$11,$11,$11,$33 +byte = $33,$11,$11,$11,$11,$11,$33 +byte = $33,$11,$11,$11,$11,$11,$33 +byte = $33,$11,$11,$11,$11,$11,$33 +byte = $83,$31,$11,$11,$11,$13,$38 +byte = $88,$83,$33,$11,$33,$38,$88 +byte = $88,$88,$83,$33,$38,$88,$88 +byte egg2 = $88,$88,$83,$33,$38,$88,$88 +byte = $88,$83,$33,$11,$33,$38,$88 +byte = $83,$30,$11,$00,$11,$13,$38 +byte = $33,$11,$00,$11,$00,$11,$33 +byte = $33,$00,$11,$00,$11,$00,$33 +byte = $33,$11,$00,$11,$00,$11,$33 +byte = $33,$00,$11,$00,$11,$00,$33 +byte = $33,$11,$00,$11,$00,$11,$33 +byte = $33,$00,$11,$00,$11,$00,$33 +byte = $83,$31,$00,$11,$00,$13,$38 +byte = $88,$83,$33,$00,$33,$38,$88 +byte = $88,$88,$83,$33,$38,$88,$88 +byte egg1 = $88,$88,$83,$33,$38,$88,$88 +byte = $88,$83,$33,$00,$33,$38,$88 +byte = $83,$30,$00,$00,$00,$03,$38 +byte = $33,$00,$00,$00,$00,$00,$33 +byte = $33,$00,$00,$00,$00,$00,$33 +byte = $33,$00,$00,$00,$00,$00,$33 +byte = $33,$00,$00,$00,$00,$00,$33 +byte = $33,$00,$00,$00,$00,$00,$33 +byte = $33,$00,$00,$00,$00,$00,$33 +byte = $83,$30,$00,$00,$00,$03,$38 +byte = $88,$83,$33,$11,$33,$38,$88 +byte = $88,$88,$83,$33,$38,$88,$88 +byte spider3 = $33,$88,$88,$33,$33,$33,$33,$88,$88,$33 +byte = $33,$88,$83,$32,$22,$22,$23,$38,$88,$33 +byte = $83,$38,$83,$32,$22,$22,$23,$38,$83,$38 +byte = $88,$83,$33,$22,$22,$22,$22,$33,$38,$88 +byte = $33,$88,$33,$22,$22,$22,$22,$33,$88,$33 +byte = $88,$33,$38,$33,$22,$22,$33,$83,$33,$88 +byte = $88,$88,$83,$33,$22,$22,$33,$38,$88,$88 +byte = $88,$33,$33,$33,$22,$22,$33,$33,$33,$88 +byte = $33,$88,$88,$88,$33,$33,$88,$88,$88,$33 +byte = $88,$88,$33,$33,$22,$22,$33,$33,$88,$88 +byte = $88,$33,$88,$33,$22,$22,$33,$88,$33,$88 +byte = $33,$88,$88,$83,$32,$23,$38,$88,$88,$33 +byte = $88,$88,$88,$88,$33,$33,$88,$88,$88,$88 +byte spider2 = $33,$88,$88,$33,$33,$33,$33,$88,$88,$33 +byte = $33,$88,$83,$30,$02,$20,$03,$38,$88,$33 +byte = $83,$38,$83,$32,$20,$02,$23,$38,$83,$38 +byte = $88,$83,$33,$20,$02,$20,$02,$33,$38,$88 +byte = $33,$88,$33,$02,$20,$02,$20,$33,$88,$33 +byte = $88,$33,$38,$30,$02,$20,$03,$83,$33,$88 +byte = $88,$88,$83,$33,$20,$02,$33,$38,$88,$88 +byte = $88,$33,$33,$30,$02,$20,$03,$33,$33,$88 +byte = $33,$88,$88,$88,$33,$33,$88,$88,$88,$33 +byte = $88,$88,$33,$30,$02,$20,$03,$33,$88,$88 +byte = $88,$33,$88,$33,$20,$02,$33,$88,$33,$88 +byte = $33,$88,$88,$83,$32,$23,$38,$88,$88,$33 +byte = $88,$88,$88,$88,$33,$33,$88,$88,$88,$88 +byte spider1 = $33,$88,$88,$33,$33,$33,$33,$88,$88,$33 +byte = $33,$88,$83,$30,$00,$00,$03,$38,$88,$33 +byte = $83,$38,$83,$30,$00,$00,$03,$38,$83,$38 +byte = $88,$83,$33,$00,$00,$00,$00,$33,$38,$88 +byte = $33,$88,$33,$00,$00,$00,$00,$33,$88,$33 +byte = $88,$33,$38,$33,$00,$00,$33,$83,$33,$88 +byte = $88,$88,$83,$33,$00,$00,$33,$38,$88,$88 +byte = $88,$33,$33,$30,$00,$00,$03,$33,$33,$88 +byte = $33,$88,$88,$88,$33,$33,$88,$88,$88,$33 +byte = $88,$88,$33,$30,$00,$00,$03,$33,$88,$88 +byte = $88,$33,$88,$33,$00,$00,$33,$88,$33,$88 +byte = $33,$88,$88,$83,$30,$03,$38,$88,$88,$33 +byte = $88,$88,$88,$88,$33,$33,$88,$88,$88,$88 +byte web1 = $88,$83,$38,$88 +byte = $88,$38,$83,$88 +byte = $88,$38,$83,$88 +byte = $88,$33,$33,$88 +byte = $83,$38,$83,$38 +byte = $83,$38,$83,$38 +byte = $83,$38,$83,$38 +byte = $33,$33,$33,$33 +byte web2 = $88,$33,$83,$38,$33,$88 +byte = $88,$38,$83,$38,$83,$88 +byte = $83,$38,$83,$38,$83,$38 +byte = $83,$33,$33,$33,$33,$38 +byte = $83,$38,$83,$38,$83,$38 +byte = $83,$38,$83,$38,$83,$38 +byte = $33,$88,$83,$38,$88,$33 +byte = $33,$33,$33,$33,$33,$33 +byte web3 = $88,$83,$38,$88,$88,$88,$88,$83,$38,$88 +byte = $88,$83,$38,$83,$38,$83,$38,$83,$38,$88 +byte = $88,$33,$88,$33,$88,$88,$33,$88,$33,$88 +byte = $88,$33,$33,$33,$33,$33,$33,$33,$33,$88 +byte = $83,$38,$88,$33,$83,$38,$33,$88,$83,$38 +byte = $83,$38,$83,$38,$83,$38,$83,$38,$83,$38 +byte = $33,$88,$83,$38,$83,$38,$83,$38,$88,$33 +byte = $33,$38,$33,$33,$33,$33,$33,$33,$33,$33 byte ship = $CC,$CC,$CC,$77,$CC,$CC,$CC byte = $CC,$CC,$C7,$77,$7C,$CC,$CC byte = $CC,$CC,$C7,$77,$7C,$CC,$CC @@ -82,73 +145,130 @@ byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 byte = $88,$88,$88,$88 -var sprtEgg, sprtSpider, sprtWeb1, sprtWeb2, sprtWeb3 +var sprtEgg1, sprtEgg2, sprtEgg3 +var sprtSpider1, sprtSpider2, sprtSpider3 +var sprtWeb1, sprtWeb2, sprtWeb3 var sprtShip, sprtMissle, sprtDummy - -def moire#0 - var i - - setlinespans(@hgrHlin, @hgrVlin) - setlineplot(@hgrPlot) - hgrColor(7) - for i = 0 to 191 step 8 - linespans(0, i, 279, 191 - i) - next - for i = 0 to 279 step 9 - linespans(i, 0, 279 - i, 191) - next +var[NUMSTARS] xstar +byte[NUMSTARS] ystar +byte won, curstar +def initStars#0 + byte k + + xstar[0] = 99 + ystar[0] = 10 + hgrColor(3) + hgrXorPlot(xstar[0], ystar[0]) + for k = 1 to NUMSTARS-1 + xstar[k] = (xstar[k - 1] + 97 - k) % 280 + ystar[k] = (ystar[k - 1] + 19 + k) % YSHIP + hgrXorPlot(xstar[k], ystar[k]) + next + curstar = 0 end -def game(spdrcnt)#0 - var[14] xspdr, yspdr, ixspdr, iyspdr, hatch - var xship, xmissle, attack - byte yship, ymissle +def updateStars#0 + hgrColor(3) + hgrXorPlot(xstar[curstar], ystar[curstar]) + ystar[curstar]++ + if ystar[curstar] > YSHIP + ystar[curstar] = 0 + fin + hgrXorPlot(xstar[curstar], ystar[curstar]) + curstar++ + if curstar >= NUMSTARS; curstar = 0; fin +end +def game(spdrcnt)#1 + var[8] xspdr, yspdr, ixspdr, iyspdr, hatch + var xship, xmissle, leftxlaser, rightxlaser, attack + byte[8] life + byte lasercharge, misslecnt, ymissle, leftylaser, rightylaser, lefthit, righthit, width byte spdrnum, k, xdelta, ydelta, btn0, btn1, webstate - xship = 140 - ymissle = 255 + xship = 140 + ymissle = 255 // Not active value + misslecnt = 6 + lasercharge = FULL_CHARGE + // + // Initialize the spiders (first is special) + // xspdr[0] = 100 ixspdr[0] = 1 yspdr[0] = 60 iyspdr[0] = -1 hatch[0] = 1 + life[0] = 3 attack = -1 webstate = 0 + // + // Initialize spiders + // spdrnum = spdrcnt - 1 for k = 1 to spdrnum - spriteAdd(k + 8, spriteDup(sprtEgg)) + spriteAdd(k + SPIDER_SPRTEBASE, spriteDup(sprtEgg3)) xspdr[k] = ((xspdr[k - 1] ^ 37) + 97) & 255 ixspdr[k] = -ixspdr[k - 1] yspdr[k] = ((yspdr[k - 1] ^ 29) + 53) & 63 iyspdr[k] = -iyspdr[k - 1] - hatch[k] = hatch[k - 1] + 1 + hatch[k] = k / 2 + 1//hatch[k - 1] + 1 + life[k] = 3 next + // + // Initialize missle display + // + hgrColor(3) + hgrRect(0, YSHIP+3, 279, 191) + for k = 0 to misslecnt-1 + spritePos(k * 16 + 160, 184, sprtMissle) + spriteDrawXor(sprtMissle) + next + hgrColor(1) + hgrRect(4, YSHIP+6, FULL_CHARGE * 4 + 4, 188) + // + // Main game loop + // repeat + // + // Move living spiders + // for k = 0 to spdrnum - if yspdr[k] <> 255 + if life[k] yspdr[k] = yspdr[k] + iyspdr[k] if yspdr[k] < -5 + // + // Above screen + // iyspdr[k] = 1 if hatch[k] hatch[k]-- if hatch[k] == 0 - spriteAdd(k + 8, spriteDup(sprtSpider)) + // + // Hatch this egg into a spider + // + life[k] = 3 // Reset life + spriteAdd(k + SPIDER_SPRTEBASE, spriteDup(sprtSpider3)) fin fin fin - if yspdr[k] > 64 // Attack or not? + if yspdr[k] > SWARM_LIMIT + // + // Attack or not? + // if hatch[k] == 0 and attack < 0 attack = k - iyspdr[k] = 8 + iyspdr[k] = ATTACK_SPEED fin if attack == k - if yspdr[k] > 160 + // + // Attacking + // + if yspdr[k] > WEB_LIMIT // // Iterate through web sequence // when webstate is 10 iyspdr[k] = -8 // Retreat - yspdr[k] = 160 + yspdr[k] = WEB_LIMIT spriteDel(2) spriteDel(3) spriteDel(4) @@ -157,44 +277,64 @@ def game(spdrcnt)#0 is 0 iyspdr[k] = 0 spriteAdd(2, sprtWeb1) - spritePosIndex(xspdr[k], 160, 2) + spritePosIndex(xspdr[k], WEB_LIMIT+7, 2) webstate = 1 break is 1 spriteAdd(3, sprtWeb2) - spritePosIndex(xspdr[k], 168, 3) + spritePosIndex(xspdr[k], WEB_LIMIT+15, 3) webstate = 2 break is 2 spriteAdd(4, sprtWeb3) - spritePosIndex(xspdr[k], 176, 4) + spritePosIndex(xspdr[k], WEB_LIMIT+22, 4) webstate = 3 otherwise - if xship >= xspdr[k] - 10 and xship <= xspdr[k] + 10 - return + // + // States 3..9 just repeat this + // + if xship >= xspdr[k] - 17 and xship <= xspdr[k] + 17 + // + // Capture ship + // + return FALSE fin webstate++ wend - fin - if iyspdr[k] > 0 // Attacking - xspdr[k] = xspdr[k] + (xship - xspdr[k]) / 8 - elsif iyspdr[k] < 0 // Retreating - if ixspdr[k] > 0 - xspdr[k] = xspdr[k] + (160 - yspdr[k]) / 8 + else + if iyspdr[k] > 0 + // + // Move towards player during attack, but not too fast + // + xspdr[k] = xspdr[k] + (xship - xspdr[k]) / (yspdr[k] > FASTMOVE_LIMIT ?? 2 :: 4) else - xspdr[k] = xspdr[k] - (160 - yspdr[k]) / 8 + // + // Retreat at a progressively faster rate + // + if ixspdr[k] > 0 + xspdr[k] = xspdr[k] + (WEB_LIMIT - yspdr[k]) / 8 + else + xspdr[k] = xspdr[k] - (WEB_LIMIT - yspdr[k]) / 8 + fin fin fin else + // + // Just reverse direction towards top of screen + // iyspdr[k] = -1 fin else if attack == k - attack = -1 // Stop attack + // + // Retreated back to swarm zone so stop attack + // + attack = -1 iyspdr[k] = -1 fin - fin - if attack <> k + // + // Swarm movement + // if ixspdr[k] > 0 xspdr[k] = xspdr[k] + yspdr[k] / 8 else @@ -210,75 +350,233 @@ def game(spdrcnt)#0 fin fin fin - spritePosIndex(xspdr[k], yspdr[k], k + 8) + spritePosIndex(xspdr[k], yspdr[k], k+SPIDER_SPRTEBASE) fin next + // + // Move ship + // xdelta, ydelta, btn0, btn1 = joypos(ymissle/4) - xship = xship + (xdelta / 4 - 10) + xship = xship + ((xdelta + 4) / 8 - 5) if xship < 0; xship = 0; fin if xship > 279; xship = 279; fin - if btn0 and ymissle == 255 - spriteAdd(1, sprtMissle) + if btn0 and misslecnt and ymissle == 255 + // + // Fire missle + // xmissle = xship - ymissle = 176 + ymissle = YSHIP+8 + misslecnt-- + spritePos(misslecnt * 16 + 160, 184, sprtMissle) // Erase from armory + spriteDrawXor(sprtMissle) + spriteAdd(1, sprtMissle) fin if ymissle <> 255 if ymissle < 8 + // + // Missle off top of screen + // spriteDel(1) ymissle = 255 else ymissle = ymissle - 8 - spritePosIndex(xmissle, ymissle, 1) + spritePosIndex(xmissle, ymissle, MISSLE_SPRTNUM) for k = 0 to spdrnum - if yspdr[k] <> 255 + if life[k] + // + // Hit test will all living spiders + // if ymissle >= yspdr[k] - 15 and ymissle <= yspdr[k] + 5 - if xmissle >= xspdr[k] - 10 and xmissle <= xspdr[k] + 10 + if hatch[k] + width = 7 // Egg width + else + width = 10 // Spider width + fin + if xmissle >= xspdr[k] - width and xmissle <= xspdr[k] + width // - // Hit + // Hit & kill spider // + life[k] = 0 + spriteAdd(k+SPIDER_SPRTEBASE, spriteDup(sprtDummy)) + spritePosIndex(0, 0, k+SPIDER_SPRTEBASE) if attack == k // Was it attacking? attack = -1 + spriteDel(2) + spriteDel(3) + spriteDel(4) + webstate = 0 fin - yspdr[k] = 255 - ymissle = 255 - spriteAdd(k + 8, spriteDup(sprtDummy)) - spritePosIndex(0, 0, k + 8) - spriteDel(1) spdrcnt-- if not spdrcnt - return + return TRUE fin + // + // Remove missle + // + spriteDel(MISSLE_SPRTNUM) + ymissle = 255 fin fin fin next fin fin - spritePosIndex(xship, 190, 0) -// spriteDrawList() + if lasercharge < FULL_CHARGE + lasercharge++ + hgrColor(1) + hgrRect(4, YSHIP+6, lasercharge * 4 + 4, 188) +// hgrRect((lasercharge - 1) * 4 + 5, YSHIP+6, lasercharge * 4 + 4, 188) + fin + if btn1 and lasercharge == FULL_CHARGE + // + // Fire laser + // + hgrColor(0) + hgrRect(4, YSHIP+6, FULL_CHARGE * 4 + 4, 188) + lasercharge = 0 + leftxlaser = xship - 7 + rightxlaser = xship + 7 + leftylaser = 0 + rightylaser = 0 + lefthit = 255 + righthit = 255 + for k = 0 to spdrnum + if life[k] + // + // Hit test will all living spiders + // + if hatch[k] + width = 7 // Egg width + else + width = 10 // Spider width + fin + if leftxlaser >= xspdr[k] - width and leftxlaser <= xspdr[k] + width + if yspdr[k] > leftylaser + lefthit = k + leftylaser = yspdr[k] + fin + fin + if rightxlaser >= xspdr[k] - width and rightxlaser <= xspdr[k] + width + if yspdr[k] > rightylaser + righthit = k + rightylaser = yspdr[k] + fin + fin + fin + next + // + // Draw Laser beams + // + hgrColor(3) + for k=0 to 1 + if leftxlaser + k >= 0; hgrXorVLin(leftylaser, YSHIP+8, leftxlaser+k); fin + if rightxlaser + k < 280;hgrXorVLin(rightylaser, YSHIP+8, rightxlaser-k); fin + next + if lefthit <> 255 + // + // Hit + // + life[lefthit]-- + if not life[lefthit] + // + // Kill spider + // + spriteAdd(lefthit + SPIDER_SPRTEBASE, spriteDup(sprtDummy)) + spritePosIndex(0, 0, lefthit + SPIDER_SPRTEBASE) + if attack == lefthit // Was it attacking? + spriteDel(2) + spriteDel(3) + spriteDel(4) + webstate = 0 + attack = -1 + fin + spdrcnt-- + if not spdrcnt + return TRUE + fin + else + // + // Dim color to show life status + // + if hatch[lefthit] + spriteAdd(lefthit + SPIDER_SPRTEBASE, spriteDup(life[lefthit] == 2 ?? sprtEgg2 :: sprtEgg1)) + else + spriteAdd(lefthit + SPIDER_SPRTEBASE, spriteDup(life[lefthit] == 2 ?? sprtSpider2 :: sprtSpider1)) + fin + spritePosIndex(xspdr[lefthit], yspdr[lefthit], lefthit+SPIDER_SPRTEBASE) + fin + fin + if righthit <> 255 and life[righthit] + // + // Hit + // + life[righthit]-- + if not life[righthit] + // + // Kill spider + // + spriteAdd(righthit + SPIDER_SPRTEBASE, spriteDup(sprtDummy)) + spritePosIndex(0, 0, righthit + SPIDER_SPRTEBASE) + if attack == righthit // Was it attacking? + spriteDel(2) + spriteDel(3) + spriteDel(4) + webstate = 0 + attack = -1 + fin + spdrcnt-- + if not spdrcnt + return TRUE + fin + else + // + // Dim color to show life status + // + if hatch[righthit] + spriteAdd(righthit + SPIDER_SPRTEBASE, spriteDup(life[righthit] == 2 ?? sprtEgg2 :: sprtEgg1)) + else + spriteAdd(righthit + SPIDER_SPRTEBASE, spriteDup(life[righthit] == 2 ?? sprtSpider2 :: sprtSpider1)) + fin + spritePosIndex(xspdr[righthit], yspdr[righthit], righthit+SPIDER_SPRTEBASE) + fin + fin + // + // Undraw lasers + // + hgrColor(3) + for k=0 to 1 + if leftxlaser + k >= 0; hgrXorVLin(leftylaser, YSHIP+8, leftxlaser+k); fin + if rightxlaser + k < 280;hgrXorVLin(rightylaser, YSHIP+8, rightxlaser-k); fin + next + fin + spritePosIndex(xship, YSHIP, SHIP_SPRTNUM) spriteDrawXorList() - spriteDrawBuf(hgrSwap()) + updateStars until ^$C000 == $9B getc + return FALSE end hgrMode spriteDrawBuf(hgrDrawBuf(0)) // So we can see the compile process sprtShip = spriteCompile(14, 14, 7, 13, @ship) sprtMissle = spriteCompile( 6, 8, 3, 0, @missle) -sprtEgg = spriteCompile(20, 10, 10, 5, @egg) -sprtSpider = spriteCompile(20, 13, 10, 6, @spider) +sprtEgg3 = spriteCompile(14, 12, 7, 6, @egg3) +sprtEgg2 = spriteCompile(14, 12, 7, 6, @egg2) +sprtEgg1 = spriteCompile(14, 12, 7, 6, @egg1) +sprtSpider3= spriteCompile(20, 13, 10, 6, @spider3) +sprtSpider2= spriteCompile(20, 13, 10, 6, @spider2) +sprtSpider1= spriteCompile(20, 13, 10, 6, @spider1) sprtWeb1 = spriteCompile( 8, 8, 4, 0, @web1) sprtWeb2 = spriteCompile(12, 8, 6, 0, @web2) sprtWeb3 = spriteCompile(20, 8, 10, 0, @web3) sprtDummy = spriteCompile( 7, 8, 0, 0, @dummy) hgrColor(0) hgrClear() -//moire -memcpy($4000, $2000, $2000) // Copy to both buffers -spriteDrawBuf(hgrDrawBuf(1)) -spriteAdd(0, sprtShip) -spriteAdd(8, sprtEgg) -game(8) +spriteAdd(SHIP_SPRTNUM, sprtShip) +spriteAdd(SPIDER_SPRTEBASE, sprtEgg3) +initStars +won = game(8) txtMode +puts(won ?? "You won!\n" :: "You lost.\n") done diff --git a/src/tftpbld b/src/tftpbld index 716af76..57f2819 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -48,10 +48,10 @@ echo "BLD/SAMPLES/HGRTEST.PLA"; atftp $1 --put -l samplesrc/hgrtest.pla -r $ echo "BLD/SAMPLES/PLAYSEQ.PLA"; atftp $1 --put -l samplesrc/playseq.pla -r $2/BLD/SAMPLES/PLAYSEQ.PLA#040000 echo "BLD/SAMPLES/RPNCALC.PLA"; atftp $1 --put -l samplesrc/rpncalc.pla -r $2/BLD/SAMPLES/RPNCALC.PLA#040000 echo "BLD/SAMPLES/SIEVE.PLA"; atftp $1 --put -l samplesrc/sieve.pla -r $2/BLD/SAMPLES/SIEVE.PLA#040000 -echo "BLD/SAMPLES/MON.PLA"; atftp $1 --put -l utilsrc/apple/mon.pla -r $2/BLD/SAMPLES/MON.PLA#040000 echo "BLD/SAMPLES/MEMTEST.PLA"; atftp $1 --put -l samplesrc/memtest.pla -r $2/BLD/SAMPLES/MEMTEST.PLA#040000 echo "BLD/SAMPLES/FATCAT.PLA"; atftp $1 --put -l samplesrc/fatcat.pla -r $2/BLD/SAMPLES/FATCAT.PLA#040000 echo "BLD/SAMPLES/GFXDEMO.PLA"; atftp $1 --put -l samplesrc/gfxdemo.pla -r $2/BLD/SAMPLES/GFXDEMO.PLA#040000 echo "BLD/SAMPLES/LZ4CAT.PLA"; atftp $1 --put -l samplesrc/lz4cat.pla -r $2/BLD/SAMPLES/LZ4CAT.PLA#040000 -echo "BLD/SAMPLES/SFM.PLA"; atftp $1 --put -l samplesrc/sfm.pla -r $2/BLD/SAMPLES/SFM.PLA#040000 +echo "BLD/SAMPLES/SFM.PLA"; atftp $1 --put -l samplesrc/sfm.pla -r $2/BLD/SAMPLES/SFM.PLA#040000 +echo "BLD/SAMPLES/MON.PLA"; atftp $1 --put -l utilsrc/apple/mon.pla -r $2/BLD/SAMPLES/MON.PLA#040000 From f5416c2d823d92b32332d0f0c2e3a9fdbc389bf0 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Mon, 6 Jan 2020 20:18:40 -0800 Subject: [PATCH 124/149] Fix hgrHLin colors and tidy up game locations --- src/libsrc/apple/hgrlib.pla | 57 ++++++++++++++++++------------------- src/samplesrc/sfm.pla | 16 +++++------ 2 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index 9a588e5..11afa77 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -709,8 +709,8 @@ end asm _hgrHLinD LDA $1000,Y ; HRMASK STA TMPH - LDA ESTKL+1,X ; RIGHT HORIZ OFFSET - STA IPY ; STEAL THIS ZP FOR A MOMENT + LDY ESTKL+1,X ; RIGHT HORIZ OFFSET + STY IPY ; STEAL THIS ZP FOR A MOMENT INX INX INX @@ -722,16 +722,16 @@ end asm _hgrHLinF LDA $1000,Y ; HLMASK STA TMPL - LDA ESTKL+1,X ; LEFT HORIZ OFFSET - TAY + LDY ESTKL+1,X ; LEFT HORIZ OFFSET + TYA LSR BCS + end asm _hgrHLinG - LDA $2000 ; CURHCLRL - STA SRCL LDA $2001 ; CURHCLRH STA SRCH + LDA $2000 ; CURHCLRL + STA SRCL BCC ++ + LDA $2000 ; CURHCLRL STA SRCH @@ -739,7 +739,6 @@ asm _hgrHLinG STA SRCL ++ CPY IPY ; RIGHT HORIZ OFFSET BNE + - LDA SRCL EOR (DST),Y AND TMPL AND TMPH @@ -748,19 +747,18 @@ asm _hgrHLinG INX INX RTS -+ LDA SRCL ; CURHCLR - EOR (DST),Y ++ EOR (DST),Y AND TMPL EOR (DST),Y - STA (DST),Y + LDA SRCH INY CPY IPY ; RIGHT HORIZ OFFSET - LDA SRCH BCS + STA (DST),Y + LDA SRCL INY CPY IPY ; RIGHT HORIZ OFFSET - LDA SRCL BCC - + EOR (DST),Y AND TMPH @@ -829,8 +827,8 @@ end asm _hgrXHLinD LDA $1000,Y ; HRMASK STA TMPH - LDA ESTKL+1,X ; RIGHT HORIZ OFFSET - STA IPY ; STEAL THIS ZP FOR A MOMENT + LDY ESTKL+1,X ; RIGHT HORIZ OFFSET + STY IPY ; STEAL THIS ZP FOR A MOMENT INX INX INX @@ -842,16 +840,16 @@ end asm _hgrXHLinF LDA $1000,Y ; HLMASK STA TMPL - LDA ESTKL+1,X ; LEFT HORIZ OFFSET - TAY + LDY ESTKL+1,X ; LEFT HORIZ OFFSET + TYA LSR BCS + end asm _hgrXHLinG - LDA $2000 ; CURHCLRL - STA SRCL LDA $2001 ; CURHCLRH STA SRCH + LDA $2000 ; CURHCLRH + STA SRCL BCC ++ + LDA $2000 ; CURHCLRL STA SRCH @@ -859,26 +857,25 @@ asm _hgrXHLinG STA SRCL ++ CPY IPY ; RIGHT HORIZ OFFSET BNE + - LDA SRCL AND TMPL + AND TMPH EOR (DST),Y STA (DST),Y INX INX RTS -+ LDA SRCL ; CURHCLR - AND TMPL ++ AND TMPL - EOR (DST),Y STA (DST),Y + LDA SRCH INY CPY IPY ; RIGHT HORIZ OFFSET - LDA SRCH BCS + EOR (DST),Y STA (DST),Y + LDA SRCL INY CPY IPY ; RIGHT HORIZ OFFSET - LDA SRCL BCC - + AND TMPH EOR (DST),Y @@ -1236,10 +1233,10 @@ _hgrHLinC:1 = @divmod7 _hgrHLinD:1 = @hrmask _hgrHLinE:1 = @divmod7 _hgrHLinF:1 = @hlmask -_hgrHLinG:1 = @curhclr -_hgrHLinG:6 = @curhclr.1 -_hgrHLinG:13 = @curhclr.1 -_hgrHLinG:18 = @curhclr +_hgrHLinG:1 = @curhclr.1 +_hgrHLinG:6 = @curhclr +_hgrHLinG:13 = @curhclr +_hgrHLinG:18 = @curhclr.1 _hgrXHLinA:1 = @hgrXorPlot _hgrXHLinB:1 = @hgrscanl _hgrXHLinB:6 = @drawbuff.1 @@ -1248,10 +1245,10 @@ _hgrXHLinC:1 = @divmod7 _hgrXHLinD:1 = @hrmask _hgrXHLinE:1 = @divmod7 _hgrXHLinF:1 = @hlmask -_hgrXHLinG:1 = @curhclr -_hgrXHLinG:6 = @curhclr.1 -_hgrXHLinG:13 = @curhclr.1 -_hgrXHLinG:18 = @curhclr +_hgrXHLinG:1 = @curhclr.1 +_hgrXHLinG:6 = @curhclr +_hgrXHLinG:13 = @curhclr +_hgrXHLinG:18 = @curhclr.1 hgrVLin:1 = @divmod7 _hgrVLinA:1 = @hbmask _hgrVLinB:1 = @curhclr diff --git a/src/samplesrc/sfm.pla b/src/samplesrc/sfm.pla index 33980b9..548f54d 100644 --- a/src/samplesrc/sfm.pla +++ b/src/samplesrc/sfm.pla @@ -107,7 +107,7 @@ byte = $83,$38,$83,$38,$83,$38 byte = $83,$38,$83,$38,$83,$38 byte = $33,$88,$83,$38,$88,$33 byte = $33,$33,$33,$33,$33,$33 -byte web3 = $88,$83,$38,$88,$88,$88,$88,$83,$38,$88 +byte web3 = $88,$83,$38,$83,$38,$83,$38,$83,$38,$88 byte = $88,$83,$38,$83,$38,$83,$38,$83,$38,$88 byte = $88,$33,$88,$33,$88,$88,$33,$88,$33,$88 byte = $88,$33,$33,$33,$33,$33,$33,$33,$33,$88 @@ -365,7 +365,7 @@ def game(spdrcnt)#1 // Fire missle // xmissle = xship - ymissle = YSHIP+8 + ymissle = YSHIP-15 misslecnt-- spritePos(misslecnt * 16 + 160, 184, sprtMissle) // Erase from armory spriteDrawXor(sprtMissle) @@ -424,8 +424,7 @@ def game(spdrcnt)#1 if lasercharge < FULL_CHARGE lasercharge++ hgrColor(1) - hgrRect(4, YSHIP+6, lasercharge * 4 + 4, 188) -// hgrRect((lasercharge - 1) * 4 + 5, YSHIP+6, lasercharge * 4 + 4, 188) + hgrRect((lasercharge - 1) * 4 + 5, YSHIP+6, lasercharge * 4 + 4, 188) fin if btn1 and lasercharge == FULL_CHARGE // @@ -469,8 +468,8 @@ def game(spdrcnt)#1 // hgrColor(3) for k=0 to 1 - if leftxlaser + k >= 0; hgrXorVLin(leftylaser, YSHIP+8, leftxlaser+k); fin - if rightxlaser + k < 280;hgrXorVLin(rightylaser, YSHIP+8, rightxlaser-k); fin + if leftxlaser + k >= 0; hgrXorVLin(leftylaser, YSHIP-8, leftxlaser+k); fin + if rightxlaser + k < 280;hgrXorVLin(rightylaser, YSHIP-8, rightxlaser-k); fin next if lefthit <> 255 // @@ -545,8 +544,8 @@ def game(spdrcnt)#1 // hgrColor(3) for k=0 to 1 - if leftxlaser + k >= 0; hgrXorVLin(leftylaser, YSHIP+8, leftxlaser+k); fin - if rightxlaser + k < 280;hgrXorVLin(rightylaser, YSHIP+8, rightxlaser-k); fin + if leftxlaser + k >= 0; hgrXorVLin(leftylaser, YSHIP-8, leftxlaser+k); fin + if rightxlaser + k < 280;hgrXorVLin(rightylaser, YSHIP-8, rightxlaser-k); fin next fin spritePosIndex(xship, YSHIP, SHIP_SPRTNUM) @@ -579,4 +578,5 @@ initStars won = game(8) txtMode puts(won ?? "You won!\n" :: "You lost.\n") +puts("Available memory: "); puti(heapavail()); putln done From 09d861e5a56b98ed89cb77b96e6d05859b3a13bb Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Mon, 6 Jan 2020 22:15:59 -0800 Subject: [PATCH 125/149] Quick updates --- src/samplesrc/hgrtest.pla | 16 +--------------- src/samplesrc/sfm.pla | 38 +++++++++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index f04b3d4..70206db 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -42,6 +42,7 @@ def testblt(sprtnum)#0 jj[0] = -1 if sprtnum for k = 1 to sprtnum + spriteAdd(k, spriteDup(sprtBall)) i[k] = ((i[k - 1] ^ 37) + 97) % 270 ii[k] = -ii[k - 1] j[k] = ((j[k - 1] ^ 29) + 53) % 180 @@ -74,21 +75,6 @@ testline memcpy($4000, $2000, $2000) // Copy to both buffers spriteDrawBuf(hgrDrawBuf(1)) spriteAdd(0, sprtBall) -spriteAdd(1, spriteDup(sprtBall)) -spriteAdd(2, spriteDup(sprtBall)) -spriteAdd(3, spriteDup(sprtBall)) -spriteAdd(4, spriteDup(sprtBall)) -spriteAdd(5, spriteDup(sprtBall)) -spriteAdd(6, spriteDup(sprtBall)) -spriteAdd(7, spriteDup(sprtBall)) -spriteAdd(8, spriteDup(sprtBall)) -spriteAdd(9, spriteDup(sprtBall)) -spriteAdd(10, spriteDup(sprtBall)) -spriteAdd(11, spriteDup(sprtBall)) -spriteAdd(12, spriteDup(sprtBall)) -spriteAdd(13, spriteDup(sprtBall)) -spriteAdd(14, spriteDup(sprtBall)) -spriteAdd(15, spriteDup(sprtBall)) testblt(16) getc txtMode diff --git a/src/samplesrc/sfm.pla b/src/samplesrc/sfm.pla index 548f54d..731eba7 100644 --- a/src/samplesrc/sfm.pla +++ b/src/samplesrc/sfm.pla @@ -422,9 +422,9 @@ def game(spdrcnt)#1 fin fin if lasercharge < FULL_CHARGE - lasercharge++ - hgrColor(1) - hgrRect((lasercharge - 1) * 4 + 5, YSHIP+6, lasercharge * 4 + 4, 188) + lasercharge++ + hgrColor(1) + hgrRect((lasercharge - 1) * 4 + 5, YSHIP+6, lasercharge * 4 + 4, 188) fin if btn1 and lasercharge == FULL_CHARGE // @@ -467,10 +467,18 @@ def game(spdrcnt)#1 // Draw Laser beams // hgrColor(3) - for k=0 to 1 - if leftxlaser + k >= 0; hgrXorVLin(leftylaser, YSHIP-8, leftxlaser+k); fin - if rightxlaser + k < 280;hgrXorVLin(rightylaser, YSHIP-8, rightxlaser-k); fin - next + //for k=0 to 1 + // if leftxlaser + k >= 0; hgrXorVLin(leftylaser, YSHIP-8, leftxlaser+k); fin + // if rightxlaser + k < 280;hgrXorVLin(rightylaser, YSHIP-8, rightxlaser-k); fin + //next + if leftxlaser >= 0 + hgrXorVLin(leftylaser, YSHIP-8, leftxlaser) + hgrXorVLin(leftylaser, YSHIP-8, leftxlaser+1) + fin + if rightxlaser < 280 + hgrXorVLin(rightylaser, YSHIP-8, rightxlaser) + hgrXorVLin(rightylaser, YSHIP-8, rightxlaser-1) + fin if lefthit <> 255 // // Hit @@ -543,10 +551,18 @@ def game(spdrcnt)#1 // Undraw lasers // hgrColor(3) - for k=0 to 1 - if leftxlaser + k >= 0; hgrXorVLin(leftylaser, YSHIP-8, leftxlaser+k); fin - if rightxlaser + k < 280;hgrXorVLin(rightylaser, YSHIP-8, rightxlaser-k); fin - next + //for k=0 to 1 + // if leftxlaser + k >= 0; hgrXorVLin(leftylaser, YSHIP-8, leftxlaser+k); fin + // if rightxlaser + k < 280;hgrXorVLin(rightylaser, YSHIP-8, rightxlaser-k); fin + //next + if leftxlaser >= 0 + hgrXorVLin(leftylaser, YSHIP-8, leftxlaser) + hgrXorVLin(leftylaser, YSHIP-8, leftxlaser+1) + fin + if rightxlaser < 280 + hgrXorVLin(rightylaser, YSHIP-8, rightxlaser) + hgrXorVLin(rightylaser, YSHIP-8, rightxlaser-1) + fin fin spritePosIndex(xship, YSHIP, SHIP_SPRTNUM) spriteDrawXorList() From 0c57570d4a54b42628c93e90fdb8ff0556943fd6 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Tue, 7 Jan 2020 16:08:48 -0800 Subject: [PATCH 126/149] Pre-compile sprites and more animations and audio --- src/libsrc/apple/hgrsprite.pla | 37 ++- src/libsrc/apple/sndseq.pla | 2 +- src/makefile | 7 +- src/mkrel | 6 +- src/samplesrc/sfm.pla | 494 +++++++++++++++++---------------- src/tftpbld | 1 + src/tftpdemos | 5 +- 7 files changed, 289 insertions(+), 263 deletions(-) diff --git a/src/libsrc/apple/hgrsprite.pla b/src/libsrc/apple/hgrsprite.pla index 4b6c03d..b20656a 100644 --- a/src/libsrc/apple/hgrsprite.pla +++ b/src/libsrc/apple/hgrsprite.pla @@ -137,8 +137,8 @@ export def spriteCompile(w, h, xcenter, ycenter, srcptr)#1 sprtptr->s_height = h sprtptr->s_xcenter = xcenter sprtptr->s_ycenter = ycenter - sprtptr=>s_under[0] = 0//heapalloc(spritesize) - sprtptr=>s_under[1] = 0//heapalloc(spritesize) + sprtptr=>s_under[0] = 0 + sprtptr=>s_under[1] = 0 for i = 0 to 13 sprtptr=>s_map[i] = heapalloc(spritesize) sprtptr=>s_mask[i] = heapalloc(spritesize) @@ -158,15 +158,14 @@ export def spriteCompile(w, h, xcenter, ycenter, srcptr)#1 return sprtptr end export def spriteDup(sprtsrc)#1 - var sprtdup, spritesize + var sprtdup byte i sprtdup = heapalloc(t_sprite) if not sprtdup; return 0; fin memcpy(sprtdup, sprtsrc, t_sprite) - //spritesize = sprtdup=>s_size - sprtdup=>s_under[0] = 0//heapalloc(spritesize) - sprtdup=>s_under[1] = 0//heapalloc(spritesize) + sprtdup=>s_under[0] = 0 + sprtdup=>s_under[1] = 0 return sprtdup end export def spriteRead(filestr)#1 @@ -175,20 +174,20 @@ export def spriteRead(filestr)#1 sprtptr = heapalloc(t_sprite) if not sprtptr; return 0; fin - refnum = fileio:open(@filestr) + refnum = fileio:open(filestr) if refnum if fileio:read(refnum, sprtptr, t_sprite) == t_sprite spritesize = sprtptr=>s_size - sprtptr=>s_under[0] = heapalloc(spritesize) - sprtptr=>s_under[1] = heapalloc(spritesize) - if not sprtptr=>s_under[0] or not sprtptr=>s_under[1] - heaprelease(sprtptr) - fileio:close(refnum) - return 0 - fin + sprtptr=>s_under[0] = 0 + sprtptr=>s_under[1] = 0 for i = 0 to 13 - sprtptr=>s_map[i] = 0//heapalloc(spritesize) - sprtptr=>s_mask[i] = 0//heapalloc(spritesize) + sprtptr=>s_map[i] = heapalloc(spritesize) + sprtptr=>s_mask[i] = heapalloc(spritesize) + if not sprtptr=>s_map[i] or not sprtptr=>s_mask[i] + heaprelease(sprtptr) + fileio:close(refnum) + return 0 + fin fileio:read(refnum, sprtptr=>s_map[i], spritesize) fileio:read(refnum, sprtptr=>s_mask[i], spritesize) next @@ -207,9 +206,9 @@ export def spriteSave(filestr, sprtptr)#1 var spritesize byte refnum, i - fileio:destroy(@filestr) - if fileio:create(@filestr, $06, $0000) == FILE_ERR_OK - refnum = fileio:open(@filestr) + fileio:destroy(filestr) + if fileio:create(filestr, $06, $0000) == FILE_ERR_OK + refnum = fileio:open(filestr) if refnum if fileio:write(refnum, sprtptr, t_sprite) == t_sprite spritesize = sprtptr=>s_size diff --git a/src/libsrc/apple/sndseq.pla b/src/libsrc/apple/sndseq.pla index 152d951..b070ece 100755 --- a/src/libsrc/apple/sndseq.pla +++ b/src/libsrc/apple/sndseq.pla @@ -305,7 +305,7 @@ TONELP SBC #$01 ; 2 ;+4 = 11 (from BNE above) +++ BIT $C000 ; 4 - BMI TONEXIT ; 2 + NOP ; 2 BPL TONELP ; 3 ;--- ;+9 = 20 diff --git a/src/makefile b/src/makefile index fdd4797..743d721 100755 --- a/src/makefile +++ b/src/makefile @@ -66,6 +66,7 @@ HGRSPRITE = rel/apple/HGRSPRITE\#FE1000 LINES = rel/LINES\#FE1000 GRAFIX = rel/apple/GRAFIX\#FE1000 SFM = rel/apple/SFM\#FE1000 +SFMSPRT = rel/apple/SFMSPRT\#FE1000 GFXDEMO = rel/apple/GFXDEMO\#FE1000 JOYBUZZ = rel/apple/JOYBUZZ\#FE1000 PORTIO = rel/apple/PORTIO\#FE1000 @@ -105,7 +106,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(ZIP) $(MATCHFILES) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(SFM) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(ZIP) $(MATCHFILES) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(SFM) $(SFMSPRT) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -263,6 +264,10 @@ $(SFM): samplesrc/sfm.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/sfm.pla > samplesrc/sfm.a acme --setpc 4094 -o $(SFM) samplesrc/sfm.a +$(SFMSPRT): samplesrc/sfmsprt.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < samplesrc/sfmsprt.pla > samplesrc/sfmsprt.a + acme --setpc 4094 -o $(SFMSPRT) samplesrc/sfmsprt.a + $(ROGUE): samplesrc/rogue.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/rogue.pla > samplesrc/rogue.a acme --setpc 4094 -o $(ROGUE) samplesrc/rogue.a diff --git a/src/mkrel b/src/mkrel index aa184cf..9dfe67a 100755 --- a/src/mkrel +++ b/src/mkrel @@ -75,12 +75,15 @@ cp rel/apple/HGRTEST#FE1000 prodos/demos/HGRTEST.REL cp rel/apple/GRTEST#FE1000 prodos/demos/GRTEST.REL cp rel/apple/DGRTEST#FE1000 prodos/demos/DGRTEST.REL cp rel/apple/HGRTEST#FE1000 prodos/demos/HGRTEST.REL -cp rel/apple/SFM#FE1000 prodos/demos/SFM.REL cp rel/apple/ROD#FE1000 prodos/demos/ROD.REL cp rel/RPNCALC#FE1000 prodos/demos/RPNCALC.REL cp rel/LZ4CAT#FE1000 prodos/demos/LZ4CAT.REL cp rel/PRIMEGAP#FE1000 prodos/demos/PRIMEGAP.REL +mkdir prodos/demos/spiders +cp rel/apple/SFM#FE1000 prodos/demos/spiders/SFM.REL +cp rel/apple/SFMSPRT#FE1000 prodos/demos/spiders/SFMSPRT.REL + mkdir prodos/demos/rogue cp rel/ROGUE#FE1000 prodos/demos/rogue/ROGUE.REL cp rel/ROGUECOMBAT#FE1000 prodos/demos/rogue/ROGUECOMBAT.REL @@ -134,6 +137,7 @@ cp samplesrc/fatcat.pla prodos/bld/samples/FATCAT.PLA.TXT cp samplesrc/gfxdemo.pla prodos/bld/samples/GFXDEMO.PLA.TXT cp samplesrc/lz4cat.pla prodos/bld/samples/Z4CAT.PLA.TXT cp samplesrc/sfm.pla prodos/bld/samples/SFM.PLA.TXT +cp samplesrc/sfmsprt.pla prodos/bld/samples/SFMSPRT.PLA.TXT #mkdir prodos/bld/examples #cp samplesrc/examples/ex.1.pla prodos/bld/examples/EX.1.PLA.TXT diff --git a/src/samplesrc/sfm.pla b/src/samplesrc/sfm.pla index 731eba7..bf90a62 100644 --- a/src/samplesrc/sfm.pla +++ b/src/samplesrc/sfm.pla @@ -1,3 +1,6 @@ +// +// Ziggy Stardust and the Spiders from Mars +// include "inc/cmdsys.plh" include "inc/hgrlib.plh" include "inc/hgrsprite.plh" @@ -9,185 +12,93 @@ const SHIP_SPRTNUM = 0 const MISSLE_SPRTNUM = 1 const WEB_SPRTBASE = 2 const SPIDER_SPRTEBASE = 8 -const FULL_CHARGE = 20 +const LASER_RECHARGE = 20 +const MISSLE_RELOAD = 10 const ATTACK_SPEED = 12 const SWARM_LIMIT = 52 const FASTMOVE_LIMIT = 120 const WEB_LIMIT = 152 const YSHIP = 180 +const LASER_BUZZ = 20 +const ATTACK_BUZZ = 5 +const WEB1_BUZZ = 10 +const WEB2_BUZZ = 12 +const WEB3_BUZZ = 14 +const SPLAT_BUZZ = 40 -byte egg3 = $88,$88,$83,$33,$38,$88,$88 -byte = $88,$83,$33,$11,$33,$38,$88 -byte = $83,$31,$11,$11,$11,$13,$38 -byte = $33,$11,$11,$11,$11,$11,$33 -byte = $33,$11,$11,$11,$11,$11,$33 -byte = $33,$11,$11,$11,$11,$11,$33 -byte = $33,$11,$11,$11,$11,$11,$33 -byte = $33,$11,$11,$11,$11,$11,$33 -byte = $33,$11,$11,$11,$11,$11,$33 -byte = $83,$31,$11,$11,$11,$13,$38 -byte = $88,$83,$33,$11,$33,$38,$88 -byte = $88,$88,$83,$33,$38,$88,$88 -byte egg2 = $88,$88,$83,$33,$38,$88,$88 -byte = $88,$83,$33,$11,$33,$38,$88 -byte = $83,$30,$11,$00,$11,$13,$38 -byte = $33,$11,$00,$11,$00,$11,$33 -byte = $33,$00,$11,$00,$11,$00,$33 -byte = $33,$11,$00,$11,$00,$11,$33 -byte = $33,$00,$11,$00,$11,$00,$33 -byte = $33,$11,$00,$11,$00,$11,$33 -byte = $33,$00,$11,$00,$11,$00,$33 -byte = $83,$31,$00,$11,$00,$13,$38 -byte = $88,$83,$33,$00,$33,$38,$88 -byte = $88,$88,$83,$33,$38,$88,$88 -byte egg1 = $88,$88,$83,$33,$38,$88,$88 -byte = $88,$83,$33,$00,$33,$38,$88 -byte = $83,$30,$00,$00,$00,$03,$38 -byte = $33,$00,$00,$00,$00,$00,$33 -byte = $33,$00,$00,$00,$00,$00,$33 -byte = $33,$00,$00,$00,$00,$00,$33 -byte = $33,$00,$00,$00,$00,$00,$33 -byte = $33,$00,$00,$00,$00,$00,$33 -byte = $33,$00,$00,$00,$00,$00,$33 -byte = $83,$30,$00,$00,$00,$03,$38 -byte = $88,$83,$33,$11,$33,$38,$88 -byte = $88,$88,$83,$33,$38,$88,$88 -byte spider3 = $33,$88,$88,$33,$33,$33,$33,$88,$88,$33 -byte = $33,$88,$83,$32,$22,$22,$23,$38,$88,$33 -byte = $83,$38,$83,$32,$22,$22,$23,$38,$83,$38 -byte = $88,$83,$33,$22,$22,$22,$22,$33,$38,$88 -byte = $33,$88,$33,$22,$22,$22,$22,$33,$88,$33 -byte = $88,$33,$38,$33,$22,$22,$33,$83,$33,$88 -byte = $88,$88,$83,$33,$22,$22,$33,$38,$88,$88 -byte = $88,$33,$33,$33,$22,$22,$33,$33,$33,$88 -byte = $33,$88,$88,$88,$33,$33,$88,$88,$88,$33 -byte = $88,$88,$33,$33,$22,$22,$33,$33,$88,$88 -byte = $88,$33,$88,$33,$22,$22,$33,$88,$33,$88 -byte = $33,$88,$88,$83,$32,$23,$38,$88,$88,$33 -byte = $88,$88,$88,$88,$33,$33,$88,$88,$88,$88 -byte spider2 = $33,$88,$88,$33,$33,$33,$33,$88,$88,$33 -byte = $33,$88,$83,$30,$02,$20,$03,$38,$88,$33 -byte = $83,$38,$83,$32,$20,$02,$23,$38,$83,$38 -byte = $88,$83,$33,$20,$02,$20,$02,$33,$38,$88 -byte = $33,$88,$33,$02,$20,$02,$20,$33,$88,$33 -byte = $88,$33,$38,$30,$02,$20,$03,$83,$33,$88 -byte = $88,$88,$83,$33,$20,$02,$33,$38,$88,$88 -byte = $88,$33,$33,$30,$02,$20,$03,$33,$33,$88 -byte = $33,$88,$88,$88,$33,$33,$88,$88,$88,$33 -byte = $88,$88,$33,$30,$02,$20,$03,$33,$88,$88 -byte = $88,$33,$88,$33,$20,$02,$33,$88,$33,$88 -byte = $33,$88,$88,$83,$32,$23,$38,$88,$88,$33 -byte = $88,$88,$88,$88,$33,$33,$88,$88,$88,$88 -byte spider1 = $33,$88,$88,$33,$33,$33,$33,$88,$88,$33 -byte = $33,$88,$83,$30,$00,$00,$03,$38,$88,$33 -byte = $83,$38,$83,$30,$00,$00,$03,$38,$83,$38 -byte = $88,$83,$33,$00,$00,$00,$00,$33,$38,$88 -byte = $33,$88,$33,$00,$00,$00,$00,$33,$88,$33 -byte = $88,$33,$38,$33,$00,$00,$33,$83,$33,$88 -byte = $88,$88,$83,$33,$00,$00,$33,$38,$88,$88 -byte = $88,$33,$33,$30,$00,$00,$03,$33,$33,$88 -byte = $33,$88,$88,$88,$33,$33,$88,$88,$88,$33 -byte = $88,$88,$33,$30,$00,$00,$03,$33,$88,$88 -byte = $88,$33,$88,$33,$00,$00,$33,$88,$33,$88 -byte = $33,$88,$88,$83,$30,$03,$38,$88,$88,$33 -byte = $88,$88,$88,$88,$33,$33,$88,$88,$88,$88 -byte web1 = $88,$83,$38,$88 -byte = $88,$38,$83,$88 -byte = $88,$38,$83,$88 -byte = $88,$33,$33,$88 -byte = $83,$38,$83,$38 -byte = $83,$38,$83,$38 -byte = $83,$38,$83,$38 -byte = $33,$33,$33,$33 -byte web2 = $88,$33,$83,$38,$33,$88 -byte = $88,$38,$83,$38,$83,$88 -byte = $83,$38,$83,$38,$83,$38 -byte = $83,$33,$33,$33,$33,$38 -byte = $83,$38,$83,$38,$83,$38 -byte = $83,$38,$83,$38,$83,$38 -byte = $33,$88,$83,$38,$88,$33 -byte = $33,$33,$33,$33,$33,$33 -byte web3 = $88,$83,$38,$83,$38,$83,$38,$83,$38,$88 -byte = $88,$83,$38,$83,$38,$83,$38,$83,$38,$88 -byte = $88,$33,$88,$33,$88,$88,$33,$88,$33,$88 -byte = $88,$33,$33,$33,$33,$33,$33,$33,$33,$88 -byte = $83,$38,$88,$33,$83,$38,$33,$88,$83,$38 -byte = $83,$38,$83,$38,$83,$38,$83,$38,$83,$38 -byte = $33,$88,$83,$38,$83,$38,$83,$38,$88,$33 -byte = $33,$38,$33,$33,$33,$33,$33,$33,$33,$33 -byte ship = $CC,$CC,$CC,$77,$CC,$CC,$CC -byte = $CC,$CC,$C7,$77,$7C,$CC,$CC -byte = $CC,$CC,$C7,$77,$7C,$CC,$CC -byte = $CC,$CC,$C7,$77,$7C,$CC,$CC -byte = $CC,$CC,$C7,$77,$7C,$CC,$CC -byte = $77,$CC,$77,$66,$77,$CC,$77 -byte = $77,$CC,$77,$66,$77,$CC,$77 -byte = $77,$CC,$77,$66,$77,$CC,$77 -byte = $77,$CC,$77,$77,$77,$CC,$77 -byte = $77,$CC,$77,$77,$77,$CC,$77 -byte = $77,$CC,$77,$77,$77,$CC,$77 -byte = $77,$C7,$77,$77,$77,$7C,$77 -byte = $77,$77,$75,$55,$57,$77,$77 -byte = $77,$77,$75,$55,$57,$77,$77 -byte missle = $CC,$55,$CC -byte = $CC,$55,$CC -byte = $CC,$55,$CC -byte = $CC,$55,$CC -byte = $CC,$55,$CC -byte = $CC,$55,$CC -byte = $C5,$55,$5C -byte = $55,$55,$55 -byte dummy = $88,$88,$88,$88 -byte = $88,$88,$88,$88 -byte = $88,$88,$88,$88 -byte = $88,$88,$88,$88 -byte = $88,$88,$88,$88 -byte = $88,$88,$88,$88 -byte = $88,$88,$88,$88 -byte = $88,$88,$88,$88 -var sprtEgg1, sprtEgg2, sprtEgg3 -var sprtSpider1, sprtSpider2, sprtSpider3 +var sprtEgg1, sprtEgg2, sprtEgg3, sprtEgg +var sprtSpider1, sprtSpider2, sprtSpider3, sprtSpider +var sprtSplat1, sprtSplat2 var sprtWeb1, sprtWeb2, sprtWeb3 var sprtShip, sprtMissle, sprtDummy var[NUMSTARS] xstar byte[NUMSTARS] ystar -byte won, curstar -def initStars#0 - byte k - - xstar[0] = 99 - ystar[0] = 10 - hgrColor(3) - hgrXorPlot(xstar[0], ystar[0]) - for k = 1 to NUMSTARS-1 - xstar[k] = (xstar[k - 1] + 97 - k) % 280 - ystar[k] = (ystar[k - 1] + 19 + k) % YSHIP - hgrXorPlot(xstar[k], ystar[k]) - next - curstar = 0 -end -def updateStars#0 - hgrColor(3) - hgrXorPlot(xstar[curstar], ystar[curstar]) - ystar[curstar]++ - if ystar[curstar] > YSHIP - ystar[curstar] = 0 - fin - hgrXorPlot(xstar[curstar], ystar[curstar]) - curstar++ - if curstar >= NUMSTARS; curstar = 0; fin -end +byte curstar, buzz + +// +// Apple II speaker tone generator routine +// +//asm spkrTone(pitch, duration)#0 +byte _spkrTone[] +byte = $86, $E5 // STX ESP +byte = $B4, $C0 // LDY ESTKH,X +byte = $B5, $D0 // LDA ESTKL,X +byte = $F0, $01 // BEQ +1 +byte = $C8 // INY +byte = $85, $08 // STA DSTL +byte = $84, $09 // STY DSTH +byte = $B4, $C1 // LDY ESTKL+1,X +byte = $B5, $D1 // LDA ESTKL+1,X +byte = $F0, $01 // BEQ +1 +byte = $C8 // INY +byte = $85, $E7 // STA TMPL +byte = $84, $E8 // STY TMPH +byte = $AA // TAX +byte = $A9, $FF // LDA #$FF +byte = $08 // PHP +byte = $78 // SEI +byte = $EA // NOP +byte = $EA // NOP +byte = $B0, $00 // BCS +0 +byte = $38 // SEC +byte = $CA // DEX +byte = $D0, $18 // BNE +18 +byte = $88 // DEY +byte = $D0, $17 // BNE +17 +byte = $2C, $30, $C0 // BIT $C030 +byte = $A6, $E7 // LDX TMPL +byte = $A4, $E8 // LDY TMPH +byte = $E9, $01 // SBC #$01 +byte = $B0, $EA // BCS -EA +byte = $C6, $08 // DEC DSTL +byte = $D0, $EA // BNE -EA +byte = $C6, $09 // DEC DSTH +byte = $D0, $E6 // BNE -E6 +byte = $F0, $07 // BEQ +8 +byte = $EA // NOP +byte = $EA // NOP +byte = $EA, $EA // BIT $C000 (nope) +byte = $EA // NOP +byte = $D0, $EB // BNE -EA +byte = $28 // PLP +byte = $A6, $E5 // LDX ESP +byte = $E8 // INX +byte = $E8 // INX +byte = $60 // RTS + def game(spdrcnt)#1 var[8] xspdr, yspdr, ixspdr, iyspdr, hatch var xship, xmissle, leftxlaser, rightxlaser, attack - byte[8] life - byte lasercharge, misslecnt, ymissle, leftylaser, rightylaser, lefthit, righthit, width + byte[8] life, death + byte lasercharging, missleloading, misslecnt, ymissle + byte leftylaser, rightylaser, lefthit, righthit, sprtnum[], width byte spdrnum, k, xdelta, ydelta, btn0, btn1, webstate - xship = 140 - ymissle = 255 // Not active value - misslecnt = 6 - lasercharge = FULL_CHARGE + xship = 140 + ymissle = 255 // Not active value + misslecnt = 6 + missleloading = FALSE + lasercharging = FALSE // // Initialize the spiders (first is special) // @@ -197,6 +108,7 @@ def game(spdrcnt)#1 iyspdr[0] = -1 hatch[0] = 1 life[0] = 3 + death[0] = 0 attack = -1 webstate = 0 // @@ -211,6 +123,7 @@ def game(spdrcnt)#1 iyspdr[k] = -iyspdr[k - 1] hatch[k] = k / 2 + 1//hatch[k - 1] + 1 life[k] = 3 + death[k] = 0 next // // Initialize missle display @@ -222,7 +135,7 @@ def game(spdrcnt)#1 spriteDrawXor(sprtMissle) next hgrColor(1) - hgrRect(4, YSHIP+6, FULL_CHARGE * 4 + 4, 188) + hgrRect(4, YSHIP+6, LASER_RECHARGE * 4 + 4, 188) // // Main game loop // @@ -278,11 +191,13 @@ def game(spdrcnt)#1 iyspdr[k] = 0 spriteAdd(2, sprtWeb1) spritePosIndex(xspdr[k], WEB_LIMIT+7, 2) + buzz = WEB1_BUZZ webstate = 1 break is 1 spriteAdd(3, sprtWeb2) spritePosIndex(xspdr[k], WEB_LIMIT+15, 3) + buzz = WEB2_BUZZ webstate = 2 break is 2 @@ -299,6 +214,7 @@ def game(spdrcnt)#1 // return FALSE fin + buzz = WEB3_BUZZ webstate++ wend else @@ -306,7 +222,9 @@ def game(spdrcnt)#1 // // Move towards player during attack, but not too fast // - xspdr[k] = xspdr[k] + (xship - xspdr[k]) / (yspdr[k] > FASTMOVE_LIMIT ?? 2 :: 4) + xdelta = yspdr[k] > FASTMOVE_LIMIT ?? 2 :: 4 + xspdr[k] = xspdr[k] + (xship - xspdr[k]) / xdelta + buzz = ATTACK_BUZZ else // // Retreat at a progressively faster rate @@ -351,21 +269,47 @@ def game(spdrcnt)#1 fin fin spritePosIndex(xspdr[k], yspdr[k], k+SPIDER_SPRTEBASE) + elsif death[k] + // + // Splat sequence + // + death[k]-- + if death[k] + spriteAdd(k+SPIDER_SPRTEBASE, spriteDup(sprtSplat2)) + spritePosIndex(xspdr[k], yspdr[k], k+SPIDER_SPRTEBASE) + else + spriteAdd(k+SPIDER_SPRTEBASE, spriteDup(sprtDummy)) + spritePosIndex(0, 0, k+SPIDER_SPRTEBASE) + spdrcnt-- + if not spdrcnt + return TRUE + fin + buzz = SPLAT_BUZZ + fin fin next // // Move ship // - xdelta, ydelta, btn0, btn1 = joypos(ymissle/4) + xdelta, ydelta, btn0, btn1 = joypos(buzz) + buzz = spdrcnt * 4 xship = xship + ((xdelta + 4) / 8 - 5) if xship < 0; xship = 0; fin if xship > 279; xship = 279; fin - if btn0 and misslecnt and ymissle == 255 + spritePosIndex(xship, YSHIP, SHIP_SPRTNUM) + // + // Missle + // + if misslecnt and missleloading + missleloading-- + fin + if btn0 and not missleloading // // Fire missle // - xmissle = xship - ymissle = YSHIP-15 + xmissle = xship + ymissle = YSHIP-15 + missleloading = MISSLE_RELOAD misslecnt-- spritePos(misslecnt * 16 + 160, 184, sprtMissle) // Erase from armory spriteDrawXor(sprtMissle) @@ -396,9 +340,10 @@ def game(spdrcnt)#1 // // Hit & kill spider // - life[k] = 0 - spriteAdd(k+SPIDER_SPRTEBASE, spriteDup(sprtDummy)) - spritePosIndex(0, 0, k+SPIDER_SPRTEBASE) + life[k] = 0 + death[k] = 2 + spriteAdd(k+SPIDER_SPRTEBASE, spriteDup(sprtSplat1)) + spritePosIndex(xspdr[k], yspdr[k], k+SPIDER_SPRTEBASE) if attack == k // Was it attacking? attack = -1 spriteDel(2) @@ -406,10 +351,6 @@ def game(spdrcnt)#1 spriteDel(4) webstate = 0 fin - spdrcnt-- - if not spdrcnt - return TRUE - fin // // Remove missle // @@ -419,26 +360,30 @@ def game(spdrcnt)#1 fin fin next + buzz = ymissle/4 fin fin - if lasercharge < FULL_CHARGE - lasercharge++ + // + // Lasers + // + if lasercharging + lasercharging-- hgrColor(1) - hgrRect((lasercharge - 1) * 4 + 5, YSHIP+6, lasercharge * 4 + 4, 188) + hgrRect(81 - lasercharging*4, YSHIP+6, 84 - lasercharging*4, 188) fin - if btn1 and lasercharge == FULL_CHARGE + if btn1 and not lasercharging // // Fire laser // hgrColor(0) - hgrRect(4, YSHIP+6, FULL_CHARGE * 4 + 4, 188) - lasercharge = 0 - leftxlaser = xship - 7 - rightxlaser = xship + 7 - leftylaser = 0 - rightylaser = 0 - lefthit = 255 - righthit = 255 + hgrRect(4, YSHIP+6, LASER_RECHARGE * 4 + 4, 188) + lasercharging = LASER_RECHARGE + leftxlaser = xship - 7 + rightxlaser = xship + 7 + leftylaser = 0 + rightylaser = 0 + lefthit = 255 + righthit = 255 for k = 0 to spdrnum if life[k] // @@ -449,13 +394,13 @@ def game(spdrcnt)#1 else width = 10 // Spider width fin - if leftxlaser >= xspdr[k] - width and leftxlaser <= xspdr[k] + width + if leftxlaser >= xspdr[k]-width and leftxlaser <= xspdr[k]+width if yspdr[k] > leftylaser lefthit = k leftylaser = yspdr[k] fin fin - if rightxlaser >= xspdr[k] - width and rightxlaser <= xspdr[k] + width + if rightxlaser >= xspdr[k]-width and rightxlaser <= xspdr[k]+width if yspdr[k] > rightylaser righthit = k rightylaser = yspdr[k] @@ -467,10 +412,6 @@ def game(spdrcnt)#1 // Draw Laser beams // hgrColor(3) - //for k=0 to 1 - // if leftxlaser + k >= 0; hgrXorVLin(leftylaser, YSHIP-8, leftxlaser+k); fin - // if rightxlaser + k < 280;hgrXorVLin(rightylaser, YSHIP-8, rightxlaser-k); fin - //next if leftxlaser >= 0 hgrXorVLin(leftylaser, YSHIP-8, leftxlaser) hgrXorVLin(leftylaser, YSHIP-8, leftxlaser+1) @@ -479,7 +420,10 @@ def game(spdrcnt)#1 hgrXorVLin(rightylaser, YSHIP-8, rightxlaser) hgrXorVLin(rightylaser, YSHIP-8, rightxlaser-1) fin + buzz = LASER_BUZZ + (@_spkrTone)(15, 1)#0 if lefthit <> 255 + sprtnum = lefthit + SPIDER_SPRTEBASE // // Hit // @@ -488,8 +432,9 @@ def game(spdrcnt)#1 // // Kill spider // - spriteAdd(lefthit + SPIDER_SPRTEBASE, spriteDup(sprtDummy)) - spritePosIndex(0, 0, lefthit + SPIDER_SPRTEBASE) + death[lefthit] = 2 + spriteAdd(sprtnum, spriteDup(sprtSplat1)) + spritePosIndex(xspdr[lefthit], yspdr[lefthit], sprtnum) if attack == lefthit // Was it attacking? spriteDel(2) spriteDel(3) @@ -497,23 +442,22 @@ def game(spdrcnt)#1 webstate = 0 attack = -1 fin - spdrcnt-- - if not spdrcnt - return TRUE - fin else // // Dim color to show life status // if hatch[lefthit] - spriteAdd(lefthit + SPIDER_SPRTEBASE, spriteDup(life[lefthit] == 2 ?? sprtEgg2 :: sprtEgg1)) + sprtEgg = life[lefthit] == 2 ?? sprtEgg2 :: sprtEgg1 + spriteAdd(sprtnum, spriteDup(sprtEgg)) else - spriteAdd(lefthit + SPIDER_SPRTEBASE, spriteDup(life[lefthit] == 2 ?? sprtSpider2 :: sprtSpider1)) + sprtSpider = life[lefthit] == 2 ?? sprtSpider2 :: sprtSpider1 + spriteAdd(sprtnum, spriteDup(sprtSpider)) fin - spritePosIndex(xspdr[lefthit], yspdr[lefthit], lefthit+SPIDER_SPRTEBASE) + spritePosIndex(xspdr[lefthit], yspdr[lefthit], sprtnum) fin fin if righthit <> 255 and life[righthit] + sprtnum = righthit + SPIDER_SPRTEBASE // // Hit // @@ -522,8 +466,9 @@ def game(spdrcnt)#1 // // Kill spider // - spriteAdd(righthit + SPIDER_SPRTEBASE, spriteDup(sprtDummy)) - spritePosIndex(0, 0, righthit + SPIDER_SPRTEBASE) + death[righthit] = 2 + spriteAdd(sprtnum, spriteDup(sprtSplat1)) + spritePosIndex(xspdr[righthit], yspdr[righthit], sprtnum) if attack == righthit // Was it attacking? spriteDel(2) spriteDel(3) @@ -531,30 +476,24 @@ def game(spdrcnt)#1 webstate = 0 attack = -1 fin - spdrcnt-- - if not spdrcnt - return TRUE - fin else // // Dim color to show life status // if hatch[righthit] - spriteAdd(righthit + SPIDER_SPRTEBASE, spriteDup(life[righthit] == 2 ?? sprtEgg2 :: sprtEgg1)) + sprtEgg = life[righthit] == 2 ?? sprtEgg2 :: sprtEgg1 + spriteAdd(sprtnum, spriteDup(sprtEgg)) else - spriteAdd(righthit + SPIDER_SPRTEBASE, spriteDup(life[righthit] == 2 ?? sprtSpider2 :: sprtSpider1)) + sprtSpider = life[righthit] == 2 ?? sprtSpider2 :: sprtSpider1 + spriteAdd(sprtnum, spriteDup(sprtSpider)) fin - spritePosIndex(xspdr[righthit], yspdr[righthit], righthit+SPIDER_SPRTEBASE) + spritePosIndex(xspdr[righthit], yspdr[righthit], sprtnum) fin fin // // Undraw lasers // hgrColor(3) - //for k=0 to 1 - // if leftxlaser + k >= 0; hgrXorVLin(leftylaser, YSHIP-8, leftxlaser+k); fin - // if rightxlaser + k < 280;hgrXorVLin(rightylaser, YSHIP-8, rightxlaser-k); fin - //next if leftxlaser >= 0 hgrXorVLin(leftylaser, YSHIP-8, leftxlaser) hgrXorVLin(leftylaser, YSHIP-8, leftxlaser+1) @@ -564,35 +503,110 @@ def game(spdrcnt)#1 hgrXorVLin(rightylaser, YSHIP-8, rightxlaser-1) fin fin - spritePosIndex(xship, YSHIP, SHIP_SPRTNUM) spriteDrawXorList() - updateStars - until ^$C000 == $9B + // + // Update stars + // + hgrColor(3) + hgrXorPlot(xstar[curstar], ystar[curstar]) + ystar[curstar]++ + if ystar[curstar] > YSHIP + ystar[curstar] = 0 + fin + hgrXorPlot(xstar[curstar], ystar[curstar]) + curstar++ + if curstar >= NUMSTARS; curstar = 0; fin + until ^$C000 == $9B // ESCape key pressed getc return FALSE end - +// +// Initialization +// +puts("Loading"); +putc('.') +sprtShip = spriteRead("SHIP") +if not sprtShip + cmdsys:modexec("SFMSPRT") + sprtShip = spriteRead("SHIP") + if not sprtShip + puts("\nError: Unable to compile sprites.\n") + return -1 + fin +fin +putc('.') +sprtMissle = spriteRead("MISSLE") +putc('.') +sprtEgg3 = spriteRead("EGG3") +putc('.') +sprtEgg2 = spriteRead("EGG2") +putc('.') +sprtEgg1 = spriteRead("EGG1") +putc('.') +sprtSpider3= spriteRead("SPIDER3") +putc('.') +sprtSpider2= spriteRead("SPIDER2") +putc('.') +sprtSpider1= spriteRead("SPIDER1") +putc('.') +sprtWeb1 = spriteRead("WEB1") +putc('.') +sprtWeb2 = spriteRead("WEB2") +putc('.') +sprtWeb3 = spriteRead("WEB3") +putc('.') +sprtSplat1 = spriteRead("SPLAT1") +putc('.') +sprtSplat2 = spriteRead("SPLAT2") +putc('.') +sprtDummy = spriteRead("DUMMY") +// +// Heat up JIT compiler +// +spriteAdd(0, sprtDummy) +for curstar = 0 to 50 + putc('.') + spriteDrawXorList() +next hgrMode -spriteDrawBuf(hgrDrawBuf(0)) // So we can see the compile process -sprtShip = spriteCompile(14, 14, 7, 13, @ship) -sprtMissle = spriteCompile( 6, 8, 3, 0, @missle) -sprtEgg3 = spriteCompile(14, 12, 7, 6, @egg3) -sprtEgg2 = spriteCompile(14, 12, 7, 6, @egg2) -sprtEgg1 = spriteCompile(14, 12, 7, 6, @egg1) -sprtSpider3= spriteCompile(20, 13, 10, 6, @spider3) -sprtSpider2= spriteCompile(20, 13, 10, 6, @spider2) -sprtSpider1= spriteCompile(20, 13, 10, 6, @spider1) -sprtWeb1 = spriteCompile( 8, 8, 4, 0, @web1) -sprtWeb2 = spriteCompile(12, 8, 6, 0, @web2) -sprtWeb3 = spriteCompile(20, 8, 10, 0, @web3) -sprtDummy = spriteCompile( 7, 8, 0, 0, @dummy) -hgrColor(0) -hgrClear() +spriteDrawBuf(hgrDrawBuf(0)) // Single buffered spriteAdd(SHIP_SPRTNUM, sprtShip) spriteAdd(SPIDER_SPRTEBASE, sprtEgg3) -initStars -won = game(8) +// +// Init stars +// +xstar[0] = 99 +ystar[0] = 10 +hgrColor(3) +hgrXorPlot(xstar[0], ystar[0]) +for curstar = 1 to NUMSTARS-1 + xstar[curstar] = (xstar[curstar - 1] + 97 - curstar) % 280 + ystar[curstar] = (ystar[curstar - 1] + 19 + curstar) % YSHIP + hgrXorPlot(xstar[curstar], ystar[curstar]) +next +curstar = 0 +if game(8) + // + // Won + // + spriteDrawXorList() + (@_spkrTone)(100, 20)#0 + (@_spkrTone)(75, 20)#0 + (@_spkrTone)(15, 20)#0 + (@_spkrTone)(25, 100)#0 +else + // + // Lost + // + spriteDrawXorList() + (@_spkrTone)(100, 50)#0 + spriteDrawXor(sprtShip) + (@_spkrTone)(150, 50)#0 + spriteDrawXor(sprtShip) + (@_spkrTone)(100, 50)#0 + spriteDrawXor(sprtShip) + (@_spkrTone)(150, 50)#0 +fin txtMode -puts(won ?? "You won!\n" :: "You lost.\n") -puts("Available memory: "); puti(heapavail()); putln +puts("\nAvailable memory: "); puti(heapavail()); putln done diff --git a/src/tftpbld b/src/tftpbld index 57f2819..d781be5 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -53,5 +53,6 @@ echo "BLD/SAMPLES/FATCAT.PLA"; atftp $1 --put -l samplesrc/fatcat.pla -r $ echo "BLD/SAMPLES/GFXDEMO.PLA"; atftp $1 --put -l samplesrc/gfxdemo.pla -r $2/BLD/SAMPLES/GFXDEMO.PLA#040000 echo "BLD/SAMPLES/LZ4CAT.PLA"; atftp $1 --put -l samplesrc/lz4cat.pla -r $2/BLD/SAMPLES/LZ4CAT.PLA#040000 echo "BLD/SAMPLES/SFM.PLA"; atftp $1 --put -l samplesrc/sfm.pla -r $2/BLD/SAMPLES/SFM.PLA#040000 +echo "BLD/SAMPLES/SFMSPRT.PLA"; atftp $1 --put -l samplesrc/sfmsprt.pla -r $2/BLD/SAMPLES/SFMSPRT.PLA#040000 echo "BLD/SAMPLES/MON.PLA"; atftp $1 --put -l utilsrc/apple/mon.pla -r $2/BLD/SAMPLES/MON.PLA#040000 diff --git a/src/tftpdemos b/src/tftpdemos index bf22589..54d052c 100755 --- a/src/tftpdemos +++ b/src/tftpdemos @@ -9,7 +9,10 @@ echo "DEMOS/HGRTEST"; atftp $1 --put -l rel/apple/HGRTEST#FE1000 echo "DEMOS/GRTEST"; atftp $1 --put -l rel/apple/GRTEST#FE1000 -r $2/DEMOS/GRTEST#FE1000 echo "DEMOS/INT32TEST"; atftp $1 --put -l rel/INT32TEST#FE1000 -r $2/DEMOS/INT32TEST#FE1000 echo "DEMOS/DGRTEST"; atftp $1 --put -l rel/apple/DGRTEST#FE1000 -r $2/DEMOS/DGRTEST#FE1000 -echo "DEMOS/SFM"; atftp $1 --put -l rel/apple/SFM#FE1000 -r $2/DEMOS/SFM#FE1000 + +# Spiders from Mars +echo "DEMOS/SPIDERS/SFM"; atftp $1 --put -l rel/apple/SFM#FE1000 -r $2/DEMOS/SPIDERS/SFM#FE1000 +echo "DEMOS/SPIDERS/SFMSPRT"; atftp $1 --put -l rel/apple/SFMSPRT#FE1000 -r $2/DEMOS/SPIDERS/SFMSPRT#FE1000 # Music demo echo "DEMOS/MUSIC/PLAYSEQ"; atftp $1 --put -l rel/apple/PLAYSEQ#FE1000 -r $2/DEMOS/MUSIC/PLAYSEQ#FE1000 From b13fb204a228c5d76f31353d69678947dd53f2aa Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Tue, 7 Jan 2020 16:12:40 -0800 Subject: [PATCH 127/149] Spider sprite compiler --- src/samplesrc/sfmsprt.pla | 203 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 src/samplesrc/sfmsprt.pla diff --git a/src/samplesrc/sfmsprt.pla b/src/samplesrc/sfmsprt.pla new file mode 100644 index 0000000..4ef6b8d --- /dev/null +++ b/src/samplesrc/sfmsprt.pla @@ -0,0 +1,203 @@ +include "inc/cmdsys.plh" +include "inc/hgrlib.plh" +include "inc/hgrsprite.plh" +sysflags reshgr1 // Reserve HGR page 1 + + +byte egg3 = $88,$88,$83,$33,$38,$88,$88 +byte = $88,$83,$33,$11,$33,$38,$88 +byte = $83,$31,$11,$11,$11,$13,$38 +byte = $33,$11,$11,$11,$11,$11,$33 +byte = $33,$11,$11,$11,$11,$11,$33 +byte = $33,$11,$11,$11,$11,$11,$33 +byte = $33,$11,$11,$11,$11,$11,$33 +byte = $33,$11,$11,$11,$11,$11,$33 +byte = $33,$11,$11,$11,$11,$11,$33 +byte = $83,$31,$11,$11,$11,$13,$38 +byte = $88,$83,$33,$11,$33,$38,$88 +byte = $88,$88,$83,$33,$38,$88,$88 +byte egg2 = $88,$88,$83,$33,$38,$88,$88 +byte = $88,$83,$33,$11,$33,$38,$88 +byte = $83,$30,$11,$00,$11,$13,$38 +byte = $33,$11,$00,$11,$00,$11,$33 +byte = $33,$00,$11,$00,$11,$00,$33 +byte = $33,$11,$00,$11,$00,$11,$33 +byte = $33,$00,$11,$00,$11,$00,$33 +byte = $33,$11,$00,$11,$00,$11,$33 +byte = $33,$00,$11,$00,$11,$00,$33 +byte = $83,$31,$00,$11,$00,$13,$38 +byte = $88,$83,$33,$00,$33,$38,$88 +byte = $88,$88,$83,$33,$38,$88,$88 +byte egg1 = $88,$88,$83,$33,$38,$88,$88 +byte = $88,$83,$33,$00,$33,$38,$88 +byte = $83,$30,$00,$00,$00,$03,$38 +byte = $33,$00,$00,$00,$00,$00,$33 +byte = $33,$00,$00,$00,$00,$00,$33 +byte = $33,$00,$00,$00,$00,$00,$33 +byte = $33,$00,$00,$00,$00,$00,$33 +byte = $33,$00,$00,$00,$00,$00,$33 +byte = $33,$00,$00,$00,$00,$00,$33 +byte = $83,$30,$00,$00,$00,$03,$38 +byte = $88,$83,$33,$11,$33,$38,$88 +byte = $88,$88,$83,$33,$38,$88,$88 +byte spider3 = $33,$88,$88,$33,$33,$33,$33,$88,$88,$33 +byte = $33,$88,$83,$32,$22,$22,$23,$38,$88,$33 +byte = $83,$38,$83,$32,$22,$22,$23,$38,$83,$38 +byte = $88,$83,$33,$22,$22,$22,$22,$33,$38,$88 +byte = $33,$88,$33,$22,$22,$22,$22,$33,$88,$33 +byte = $88,$33,$38,$33,$22,$22,$33,$83,$33,$88 +byte = $88,$88,$83,$33,$22,$22,$33,$38,$88,$88 +byte = $88,$33,$33,$33,$22,$22,$33,$33,$33,$88 +byte = $33,$88,$88,$88,$33,$33,$88,$88,$88,$33 +byte = $88,$88,$33,$33,$22,$22,$33,$33,$88,$88 +byte = $88,$33,$88,$33,$22,$22,$33,$88,$33,$88 +byte = $33,$88,$88,$83,$32,$23,$38,$88,$88,$33 +byte = $88,$88,$88,$88,$33,$33,$88,$88,$88,$88 +byte spider2 = $33,$88,$88,$33,$33,$33,$33,$88,$88,$33 +byte = $33,$88,$83,$30,$02,$20,$03,$38,$88,$33 +byte = $83,$38,$83,$32,$20,$02,$23,$38,$83,$38 +byte = $88,$83,$33,$20,$02,$20,$02,$33,$38,$88 +byte = $33,$88,$33,$02,$20,$02,$20,$33,$88,$33 +byte = $88,$33,$38,$30,$02,$20,$03,$83,$33,$88 +byte = $88,$88,$83,$33,$20,$02,$33,$38,$88,$88 +byte = $88,$33,$33,$30,$02,$20,$03,$33,$33,$88 +byte = $33,$88,$88,$88,$33,$33,$88,$88,$88,$33 +byte = $88,$88,$33,$30,$02,$20,$03,$33,$88,$88 +byte = $88,$33,$88,$33,$20,$02,$33,$88,$33,$88 +byte = $33,$88,$88,$83,$32,$23,$38,$88,$88,$33 +byte = $88,$88,$88,$88,$33,$33,$88,$88,$88,$88 +byte spider1 = $33,$88,$88,$33,$33,$33,$33,$88,$88,$33 +byte = $33,$88,$83,$30,$00,$00,$03,$38,$88,$33 +byte = $83,$38,$83,$30,$00,$00,$03,$38,$83,$38 +byte = $88,$83,$33,$00,$00,$00,$00,$33,$38,$88 +byte = $33,$88,$33,$00,$00,$00,$00,$33,$88,$33 +byte = $88,$33,$38,$33,$00,$00,$33,$83,$33,$88 +byte = $88,$88,$83,$33,$00,$00,$33,$38,$88,$88 +byte = $88,$33,$33,$30,$00,$00,$03,$33,$33,$88 +byte = $33,$88,$88,$88,$33,$33,$88,$88,$88,$33 +byte = $88,$88,$33,$30,$00,$00,$03,$33,$88,$88 +byte = $88,$33,$88,$33,$00,$00,$33,$88,$33,$88 +byte = $33,$88,$88,$83,$30,$03,$38,$88,$88,$33 +byte = $88,$88,$88,$88,$33,$33,$88,$88,$88,$88 +byte web1 = $88,$83,$38,$88 +byte = $88,$38,$83,$88 +byte = $88,$38,$83,$88 +byte = $88,$33,$33,$88 +byte = $83,$38,$83,$38 +byte = $83,$38,$83,$38 +byte = $83,$38,$83,$38 +byte = $33,$33,$33,$33 +byte web2 = $88,$33,$83,$38,$33,$88 +byte = $88,$38,$83,$38,$83,$88 +byte = $83,$38,$83,$38,$83,$38 +byte = $83,$33,$33,$33,$33,$38 +byte = $83,$38,$83,$38,$83,$38 +byte = $83,$38,$83,$38,$83,$38 +byte = $33,$88,$83,$38,$88,$33 +byte = $33,$33,$33,$33,$33,$33 +byte web3 = $88,$83,$38,$83,$38,$83,$38,$83,$38,$88 +byte = $88,$83,$38,$83,$38,$83,$38,$83,$38,$88 +byte = $88,$33,$88,$33,$88,$88,$33,$88,$33,$88 +byte = $88,$33,$33,$33,$33,$33,$33,$33,$33,$88 +byte = $83,$38,$88,$33,$83,$38,$33,$88,$83,$38 +byte = $83,$38,$83,$38,$83,$38,$83,$38,$83,$38 +byte = $33,$88,$83,$38,$83,$38,$83,$38,$88,$33 +byte = $33,$38,$33,$33,$33,$33,$33,$33,$33,$33 +byte splat1 = $88,$88,$88,$22,$22,$22,$22,$88,$88,$88 +byte = $88,$88,$88,$22,$11,$11,$22,$88,$88,$88 +byte = $88,$88,$88,$22,$11,$11,$22,$88,$88,$88 +byte = $88,$82,$22,$11,$11,$11,$11,$22,$28,$88 +byte = $22,$22,$22,$11,$11,$11,$11,$22,$22,$22 +byte = $88,$22,$28,$22,$11,$11,$22,$82,$22,$88 +byte = $88,$88,$82,$22,$11,$11,$22,$28,$88,$88 +byte = $88,$22,$22,$22,$11,$11,$22,$22,$22,$88 +byte = $22,$22,$88,$88,$22,$22,$88,$88,$22,$22 +byte = $88,$88,$22,$22,$11,$11,$22,$22,$88,$88 +byte = $88,$22,$22,$22,$11,$11,$22,$22,$22,$88 +byte = $22,$22,$88,$82,$21,$12,$28,$88,$22,$22 +byte = $88,$88,$88,$88,$22,$22,$88,$88,$88,$88 +byte splat2 = $88,$88,$88,$88,$22,$22,$22,$22,$88,$88,$88,$88 +byte = $88,$88,$88,$88,$22,$11,$11,$22,$88,$88,$88,$88 +byte = $88,$88,$88,$82,$22,$11,$11,$22,$88,$88,$88,$88 +byte = $88,$88,$88,$22,$11,$11,$11,$11,$22,$88,$88,$88 +byte = $88,$88,$82,$22,$11,$18,$81,$11,$22,$28,$88,$88 +byte = $88,$22,$22,$22,$11,$88,$88,$11,$22,$22,$22,$88 +byte = $22,$28,$82,$22,$11,$88,$88,$11,$22,$28,$82,$22 +byte = $88,$88,$22,$28,$88,$88,$88,$88,$82,$22,$88,$88 +byte = $88,$88,$88,$22,$88,$88,$88,$11,$22,$88,$88,$88 +byte = $88,$88,$22,$22,$11,$88,$88,$11,$22,$22,$88,$88 +byte = $88,$22,$22,$22,$11,$18,$81,$11,$22,$22,$22,$88 +byte = $88,$88,$88,$22,$11,$18,$81,$11,$22,$88,$88,$88 +byte = $88,$88,$22,$22,$11,$11,$11,$11,$22,$22,$88,$88 +byte = $88,$22,$22,$88,$22,$11,$11,$22,$88,$22,$22,$88 +byte = $22,$28,$88,$88,$88,$22,$22,$88,$88,$88,$82,$22 +byte = $88,$88,$22,$22,$22,$11,$11,$22,$22,$22,$88,$88 +byte = $88,$88,$22,$28,$22,$11,$11,$22,$82,$22,$88,$88 +byte ship = $CC,$CC,$CC,$77,$CC,$CC,$CC +byte = $CC,$CC,$C7,$77,$7C,$CC,$CC +byte = $CC,$CC,$C7,$77,$7C,$CC,$CC +byte = $CC,$CC,$C7,$77,$7C,$CC,$CC +byte = $CC,$CC,$C7,$77,$7C,$CC,$CC +byte = $77,$CC,$77,$66,$77,$CC,$77 +byte = $77,$CC,$77,$66,$77,$CC,$77 +byte = $77,$CC,$77,$66,$77,$CC,$77 +byte = $77,$CC,$77,$77,$77,$CC,$77 +byte = $77,$CC,$77,$77,$77,$CC,$77 +byte = $77,$CC,$77,$77,$77,$CC,$77 +byte = $77,$C7,$77,$77,$77,$7C,$77 +byte = $77,$77,$75,$55,$57,$77,$77 +byte = $77,$77,$75,$55,$57,$77,$77 +byte missle = $CC,$55,$CC +byte = $CC,$55,$CC +byte = $CC,$55,$CC +byte = $CC,$55,$CC +byte = $CC,$55,$CC +byte = $CC,$55,$CC +byte = $C5,$55,$5C +byte = $55,$55,$55 +byte dummy = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +byte = $88,$88,$88,$88 +var sprtEgg1, sprtEgg2, sprtEgg3 +var sprtSpider1, sprtSpider2, sprtSpider3 +var sprtSplat1, sprtSplat2 +var sprtWeb1, sprtWeb2, sprtWeb3 +var sprtShip, sprtMissle, sprtDummy + +hgrMode +spriteDrawBuf(hgrDrawBuf(0)) // So we can see the compile process +sprtShip = spriteCompile(14, 14, 7, 13, @ship) +sprtMissle = spriteCompile( 6, 8, 3, 0, @missle) +sprtEgg3 = spriteCompile(14, 12, 7, 6, @egg3) +sprtEgg2 = spriteCompile(14, 12, 7, 6, @egg2) +sprtEgg1 = spriteCompile(14, 12, 7, 6, @egg1) +sprtSpider3= spriteCompile(20, 13, 10, 6, @spider3) +sprtSpider2= spriteCompile(20, 13, 10, 6, @spider2) +sprtSpider1= spriteCompile(20, 13, 10, 6, @spider1) +sprtWeb1 = spriteCompile( 8, 8, 4, 0, @web1) +sprtWeb2 = spriteCompile(12, 8, 6, 0, @web2) +sprtWeb3 = spriteCompile(20, 8, 10, 0, @web3) +sprtSplat1 = spriteCompile(20, 13, 10, 6, @splat1) +sprtSplat2 = spriteCompile(24, 17, 12, 8, @splat2) +sprtDummy = spriteCompile( 7, 8, 0, 0, @dummy) +txtMode +spriteSave("SHIP", sprtShip) +spriteSave("MISSLE", sprtMissle) +spriteSave("EGG3", sprtEgg3) +spriteSave("EGG2", sprtEgg2) +spriteSave("EGG1", sprtEgg1) +spriteSave("SPIDER1", sprtSpider1) +spriteSave("SPIDER2", sprtSpider2) +spriteSave("SPIDER3", sprtSpider3) +spriteSave("WEB1", sprtWeb1) +spriteSave("WEB2", sprtWeb2) +spriteSave("WEB3", sprtWeb3) +spriteSave("SPLAT1", sprtSplat1) +spriteSave("SPLAT2", sprtSplat2) +spriteSave("DUMMY", sprtDummy) +done From 360be4c709e3206861b661a1c32766c07f45f3a7 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Tue, 7 Jan 2020 17:07:26 -0800 Subject: [PATCH 128/149] Tweak sprite update and laser hit --- src/samplesrc/sfm.pla | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/samplesrc/sfm.pla b/src/samplesrc/sfm.pla index bf90a62..d719530 100644 --- a/src/samplesrc/sfm.pla +++ b/src/samplesrc/sfm.pla @@ -364,6 +364,10 @@ def game(spdrcnt)#1 fin fin // + // Update sprites + // + spriteDrawXorList() + // // Lasers // if lasercharging @@ -395,15 +399,15 @@ def game(spdrcnt)#1 width = 10 // Spider width fin if leftxlaser >= xspdr[k]-width and leftxlaser <= xspdr[k]+width - if yspdr[k] > leftylaser + if yspdr[k] + 5 > leftylaser lefthit = k - leftylaser = yspdr[k] + leftylaser = yspdr[k] + 5 fin fin if rightxlaser >= xspdr[k]-width and rightxlaser <= xspdr[k]+width - if yspdr[k] > rightylaser + if yspdr[k] + 5 > rightylaser righthit = k - rightylaser = yspdr[k] + rightylaser = yspdr[k] + 5 fin fin fin @@ -503,7 +507,6 @@ def game(spdrcnt)#1 hgrXorVLin(rightylaser, YSHIP-8, rightxlaser-1) fin fin - spriteDrawXorList() // // Update stars // From 1da0bdf6101300e40bbbf396dc011e3c0e3cfd23 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Tue, 7 Jan 2020 17:22:44 -0800 Subject: [PATCH 129/149] Tweak --- src/samplesrc/sfm.pla | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/samplesrc/sfm.pla b/src/samplesrc/sfm.pla index d719530..b0a5d2b 100644 --- a/src/samplesrc/sfm.pla +++ b/src/samplesrc/sfm.pla @@ -566,9 +566,10 @@ sprtDummy = spriteRead("DUMMY") // // Heat up JIT compiler // -spriteAdd(0, sprtDummy) for curstar = 0 to 50 putc('.') + spriteAdd(0, sprtDummy) + spritePosIndex(0, 0, 0) spriteDrawXorList() next hgrMode From 9e31fbd1dab5fa7e49f277087022dafa5a754c56 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Tue, 7 Jan 2020 18:18:18 -0800 Subject: [PATCH 130/149] Replay game --- src/samplesrc/sfm.pla | 95 ++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/src/samplesrc/sfm.pla b/src/samplesrc/sfm.pla index b0a5d2b..b47b3f3 100644 --- a/src/samplesrc/sfm.pla +++ b/src/samplesrc/sfm.pla @@ -30,7 +30,7 @@ var sprtEgg1, sprtEgg2, sprtEgg3, sprtEgg var sprtSpider1, sprtSpider2, sprtSpider3, sprtSpider var sprtSplat1, sprtSplat2 var sprtWeb1, sprtWeb2, sprtWeb3 -var sprtShip, sprtMissle, sprtDummy +var sprtShip, sprtMissle, sprtDummy, heapstart var[NUMSTARS] xstar byte[NUMSTARS] ystar byte curstar, buzz @@ -303,7 +303,7 @@ def game(spdrcnt)#1 if misslecnt and missleloading missleloading-- fin - if btn0 and not missleloading + if btn1 and not missleloading and ymissle == 255 // // Fire missle // @@ -375,7 +375,7 @@ def game(spdrcnt)#1 hgrColor(1) hgrRect(81 - lasercharging*4, YSHIP+6, 84 - lasercharging*4, 188) fin - if btn1 and not lasercharging + if btn0 and not lasercharging // // Fire laser // @@ -572,45 +572,66 @@ for curstar = 0 to 50 spritePosIndex(0, 0, 0) spriteDrawXorList() next -hgrMode -spriteDrawBuf(hgrDrawBuf(0)) // Single buffered -spriteAdd(SHIP_SPRTNUM, sprtShip) -spriteAdd(SPIDER_SPRTEBASE, sprtEgg3) -// -// Init stars -// -xstar[0] = 99 -ystar[0] = 10 -hgrColor(3) -hgrXorPlot(xstar[0], ystar[0]) -for curstar = 1 to NUMSTARS-1 +heapstart = heapmark() +//puts("\nBeginning available memory: "); puti(heapavail()); putln +repeat + hgrMode + spriteDrawBuf(hgrDrawBuf(0)) // Single buffered + spriteAdd(SHIP_SPRTNUM, sprtShip) + spriteAdd(SPIDER_SPRTEBASE, sprtEgg3) + // + // Init stars + // + xstar[0] = 99 + ystar[0] = 10 + hgrColor(3) + hgrXorPlot(xstar[0], ystar[0]) + for curstar = 1 to NUMSTARS-1 xstar[curstar] = (xstar[curstar - 1] + 97 - curstar) % 280 ystar[curstar] = (ystar[curstar - 1] + 19 + curstar) % YSHIP hgrXorPlot(xstar[curstar], ystar[curstar]) -next -curstar = 0 -if game(8) + next + curstar = 0 + if game(8) + // + // Won + // + spriteDrawXorList() + (@_spkrTone)(100, 20)#0 + (@_spkrTone)(75, 20)#0 + (@_spkrTone)(15, 20)#0 + (@_spkrTone)(25, 100)#0 + puts("\nZiggy Stardust has saved Earth!\n") + else + // + // Lost + // + spriteDrawXorList() + (@_spkrTone)(100, 50)#0 + spriteDrawXor(sprtShip) + (@_spkrTone)(150, 50)#0 + spriteDrawXor(sprtShip) + (@_spkrTone)(100, 50)#0 + spriteDrawXor(sprtShip) + (@_spkrTone)(150, 50)#0 + puts("\nEarth has been overrun") + puts("\nby the Spiders from Mars\n") + fin + txtMode // - // Won + // Clear sprite lists // + for curstar = 0 to 15 + spriteDel(curstar) + next spriteDrawXorList() - (@_spkrTone)(100, 20)#0 - (@_spkrTone)(75, 20)#0 - (@_spkrTone)(15, 20)#0 - (@_spkrTone)(25, 100)#0 -else - // - // Lost - // spriteDrawXorList() - (@_spkrTone)(100, 50)#0 - spriteDrawXor(sprtShip) - (@_spkrTone)(150, 50)#0 - spriteDrawXor(sprtShip) - (@_spkrTone)(100, 50)#0 - spriteDrawXor(sprtShip) - (@_spkrTone)(150, 50)#0 -fin -txtMode -puts("\nAvailable memory: "); puti(heapavail()); putln + // + // Reset heap + // + heaprelease(heapstart) + //puts("\nAvailable memory: "); puti(heapavail()); putln + puts("Play again (Y/N)?") +until toupper(getc) <> 'Y' +putln done From 4ee7c8c049d6221f686b909cc3f011b5b3c811ee Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Tue, 7 Jan 2020 18:51:06 -0800 Subject: [PATCH 131/149] Auto-play Spiders from Mars --- images/apple/SFM.PO | Bin 0 -> 143360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/apple/SFM.PO diff --git a/images/apple/SFM.PO b/images/apple/SFM.PO new file mode 100644 index 0000000000000000000000000000000000000000..20894c590f33b725f5ef5b7e44083ac8eabfac3f GIT binary patch literal 143360 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 E0b;+yq5uE@ literal 0 HcmV?d00001 From 6f620e194db627061f19c6ea7fa05ac34c367050 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Wed, 8 Jan 2020 05:43:26 -0800 Subject: [PATCH 132/149] Add JIT compiler to image --- images/apple/SFM.PO | Bin 143360 -> 143360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/images/apple/SFM.PO b/images/apple/SFM.PO index 20894c590f33b725f5ef5b7e44083ac8eabfac3f..96b9f2819ad42d0a36e78f8e14defa5e5919a468 100644 GIT binary patch delta 197 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 From 31f4fbfbecfdfbb4ca13f5750ae0cc548f8f60b2 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Wed, 8 Jan 2020 05:51:19 -0800 Subject: [PATCH 133/149] Slight API change --- images/apple/SFM.PO | Bin 143360 -> 143360 bytes src/inc/hgrsprite.plh | 2 +- src/libsrc/apple/hgrsprite.pla | 3 ++- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/images/apple/SFM.PO b/images/apple/SFM.PO index 96b9f2819ad42d0a36e78f8e14defa5e5919a468..097c2e75634ea4a097b9d542abb6e23c8e0a317f 100644 GIT binary patch delta 8471 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 Li#zZm_Q3xFKrPvy delta 13541 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 Date: Wed, 8 Jan 2020 12:11:55 -0800 Subject: [PATCH 134/149] HGR tile and font libraries --- src/inc/dgrlib.plh | 3 +- src/inc/grlib.plh | 3 +- src/inc/hgrfont.plh | 3 + src/inc/hgrlib.plh | 3 +- src/inc/hgrtile.plh | 13 ++ src/libsrc/apple/dgrlib.pla | 39 ++-- src/libsrc/apple/grlib.pla | 38 ++-- src/libsrc/apple/hgrfont.pla | 140 +++++++++++++ src/libsrc/apple/hgrlib.pla | 31 +-- src/libsrc/apple/hgrtile.pla | 377 +++++++++++++++++++++++++++++++++++ src/makefile | 17 +- src/mkrel | 6 + src/samplesrc/dgrtest.pla | 4 +- src/samplesrc/grtest.pla | 4 +- src/samplesrc/hgrtest.pla | 4 +- src/samplesrc/sfm.pla | 4 +- src/samplesrc/sfmsprt.pla | 4 +- src/samplesrc/tiletest.pla | 13 ++ src/tftpbld | 3 + src/tftpdemos | 1 + src/tftpsys | 2 + 21 files changed, 647 insertions(+), 65 deletions(-) create mode 100644 src/inc/hgrfont.plh create mode 100644 src/inc/hgrtile.plh create mode 100644 src/libsrc/apple/hgrfont.pla create mode 100644 src/libsrc/apple/hgrtile.pla create mode 100644 src/samplesrc/tiletest.pla diff --git a/src/inc/dgrlib.plh b/src/inc/dgrlib.plh index a378993..7904afc 100644 --- a/src/inc/dgrlib.plh +++ b/src/inc/dgrlib.plh @@ -7,8 +7,7 @@ import dgrlib predef dgrTileStr(x, y, tilestr, strlen, tilebuff)#0 predef dgrFill(x, y, tile)#0 predef dgrClear(clr)#0 - predef dgrMode#1 - predef txtMode#0 + predef dgrMode(mode)#1 predef dgrShow(page)#1 predef dgrSwap#0 predef dgrDrawBuf(page)#0 diff --git a/src/inc/grlib.plh b/src/inc/grlib.plh index fec0916..f1aa61f 100644 --- a/src/inc/grlib.plh +++ b/src/inc/grlib.plh @@ -7,8 +7,7 @@ import grlib predef grTileStr(x, y, tilestr, strlen, tilebuff)#0 predef grFill(x, y, tile)#0 predef grClear(clr)#0 - predef grMode#1 - predef txtMode#0 + predef grMode(mode)#1 predef grShow(page)#1 predef grSwap#0 predef grDrawBuf(page)#0 diff --git a/src/inc/hgrfont.plh b/src/inc/hgrfont.plh new file mode 100644 index 0000000..93c069c --- /dev/null +++ b/src/inc/hgrfont.plh @@ -0,0 +1,3 @@ +import hgrfont + predef hgrPutStr(x, y, strptr)#0 +end diff --git a/src/inc/hgrlib.plh b/src/inc/hgrlib.plh index c3f0e6f..251fcf1 100644 --- a/src/inc/hgrlib.plh +++ b/src/inc/hgrlib.plh @@ -15,8 +15,7 @@ import hgrlib predef hgrXorSrc(ofst, y, w, h, srcptr)#0 predef hgrOrSrc(ofst, y, w, h, srcptr)#0 predef hgrCopyDst(ofst, y, w, h, dstptr)#0 - predef hgrMode#1 - predef txtMode#0 + predef hgrMode(mode)#1 predef hgrClear#0 predef hgrShow(page)#1 predef hgrSwap#1 diff --git a/src/inc/hgrtile.plh b/src/inc/hgrtile.plh new file mode 100644 index 0000000..9a8bac9 --- /dev/null +++ b/src/inc/hgrtile.plh @@ -0,0 +1,13 @@ +import hgrtile + predef tileDraw(x, y, tileptr)#0 + predef tileXorDraw(x, y, tileptr)#0 + predef tileOrDraw(x, y, tileptr)#0 + predef tileAndDraw(x, y, tileptr)#0 + predef tileDrawStr(x, y, strptr, strlen, tileset)#0 + predef tileFromText(txtpage, tileset)#0 + predef tileMode(mode)#1 + predef tileClear#0 + predef tileShow(page)#1 + predef tileSwap#1 + predef tileDrawBuf(page)#1 +end diff --git a/src/libsrc/apple/dgrlib.pla b/src/libsrc/apple/dgrlib.pla index 1937ee7..69302b0 100755 --- a/src/libsrc/apple/dgrlib.pla +++ b/src/libsrc/apple/dgrlib.pla @@ -535,25 +535,25 @@ export def dgrClear(clr)#0 memset(@clrtile, clr, 32) dgrFill(0, 0, @clrtile) end -// -// Set double lores graphics, return draw buffer -// -export def dgrMode#1 - ^showlores - ^showfull - ^showgraphics - ^showpage1 - ^ena80 = 0 - ^show80 = 0 - ^an3on - drawpage = 1 - drawbuff = dgrbuff[1] - return 1 -end -// -// Set text mode -// -export def txtMode#0 +export def dgrMode(mode)#1 + if mode + // + // Set double lores graphics, return draw buffer + // + ^showlores + ^showfull + ^showgraphics + ^showpage1 + ^ena80 = 0 + ^show80 = 0 + ^an3on + drawpage = 1 + drawbuff = dgrbuff[1] + return 1 + fin + // + // Set text mode + // ^showtext ^showpage1 ^ena80 = 0 @@ -561,6 +561,7 @@ export def txtMode#0 ^mapmain = 0 ^an3off call($FC58, 0, 0, 0, 0) // home() + return 0 end // // Set display page, return other page diff --git a/src/libsrc/apple/grlib.pla b/src/libsrc/apple/grlib.pla index 1fc95dc..163f14d 100644 --- a/src/libsrc/apple/grlib.pla +++ b/src/libsrc/apple/grlib.pla @@ -420,23 +420,26 @@ end // // Set lores graphics, return draw buffer // -export def grMode#1 - ^showlores - ^showfull - ^showgraphics - ^showpage1 - ^ena80 = 0 - ^show40 = 0 - ^mapmain = 0 - ^an3off - drawpage = 1 - drawbuff = grbuff[1] - return 1 -end -// -// Set text mode -// -export def txtMode#0 +export def grMode(mode)#1 + if mode + // + // Set GR mode + // + ^showlores + ^showfull + ^showgraphics + ^showpage1 + ^ena80 = 0 + ^show40 = 0 + ^mapmain = 0 + ^an3off + drawpage = 1 + drawbuff = grbuff[1] + return 1 + fin + // + // Set text mode + // ^showtext ^showpage1 ^ena80 = 0 @@ -444,6 +447,7 @@ export def txtMode#0 ^mapmain = 0 ^an3off call($FC58, 0, 0, 0, 0) // home() + return 0 end // // Set display page, return other page diff --git a/src/libsrc/apple/hgrfont.pla b/src/libsrc/apple/hgrfont.pla new file mode 100644 index 0000000..7bb06b6 --- /dev/null +++ b/src/libsrc/apple/hgrfont.pla @@ -0,0 +1,140 @@ +include "inc/hgrtile.plh" +// +// Apple //e hires character font +// +byte hgrFont[] +byte = $1C,$22,$2A,$3A,$1A,$02,$3C,$00,$08,$14,$22,$22,$3E,$22,$22,$00 +byte = $1E,$22,$22,$1E,$22,$22,$1E,$00,$1C,$22,$02,$02,$02,$22,$1C,$00 +byte = $1E,$22,$22,$22,$22,$22,$1E,$00,$3E,$02,$02,$1E,$02,$02,$3E,$00 +byte = $3E,$02,$02,$1E,$02,$02,$02,$00,$3C,$02,$02,$02,$32,$22,$3C,$00 +byte = $22,$22,$22,$3E,$22,$22,$22,$00,$1C,$08,$08,$08,$08,$08,$1C,$00 +byte = $20,$20,$20,$20,$20,$22,$1C,$00,$22,$12,$0A,$06,$0A,$12,$22,$00 +byte = $02,$02,$02,$02,$02,$02,$3E,$00,$22,$36,$2A,$2A,$22,$22,$22,$00 +byte = $22,$22,$26,$2A,$32,$22,$22,$00,$1C,$22,$22,$22,$22,$22,$1C,$00 +byte = $1E,$22,$22,$1E,$02,$02,$02,$00,$1C,$22,$22,$22,$2A,$12,$2C,$00 +byte = $1E,$22,$22,$1E,$0A,$12,$22,$00,$1C,$22,$02,$1C,$20,$22,$1C,$00 +byte = $3E,$08,$08,$08,$08,$08,$08,$00,$22,$22,$22,$22,$22,$22,$1C,$00 +byte = $22,$22,$22,$22,$22,$14,$08,$00,$22,$22,$22,$2A,$2A,$36,$22,$00 +byte = $22,$22,$14,$08,$14,$22,$22,$00,$22,$22,$14,$08,$08,$08,$08,$00 +byte = $3E,$20,$10,$08,$04,$02,$3E,$00,$3E,$06,$06,$06,$06,$06,$3E,$00 +byte = $00,$02,$04,$08,$10,$20,$00,$00,$3E,$30,$30,$30,$30,$30,$3E,$00 +byte = $00,$00,$08,$14,$22,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7F +byte = $00,$00,$00,$00,$00,$00,$00,$00,$08,$08,$08,$08,$08,$00,$08,$00 +byte = $14,$14,$14,$00,$00,$00,$00,$00,$14,$14,$3E,$14,$3E,$14,$14,$00 +byte = $08,$3C,$0A,$1C,$28,$1E,$08,$00,$06,$26,$10,$08,$04,$32,$30,$00 +byte = $04,$0A,$0A,$04,$2A,$12,$2C,$00,$08,$08,$08,$00,$00,$00,$00,$00 +byte = $08,$04,$02,$02,$02,$04,$08,$00,$08,$10,$20,$20,$20,$10,$08,$00 +byte = $08,$2A,$1C,$08,$1C,$2A,$08,$00,$00,$08,$08,$3E,$08,$08,$00,$00 +byte = $00,$00,$00,$00,$08,$08,$04,$00,$00,$00,$00,$3E,$00,$00,$00,$00 +byte = $00,$00,$00,$00,$00,$00,$08,$00,$00,$20,$10,$08,$04,$02,$00,$00 +byte = $1C,$22,$32,$2A,$26,$22,$1C,$00,$08,$0C,$08,$08,$08,$08,$1C,$00 +byte = $1C,$22,$20,$18,$04,$02,$3E,$00,$3E,$20,$10,$18,$20,$22,$1C,$00 +byte = $10,$18,$14,$12,$3E,$10,$10,$00,$3E,$02,$1E,$20,$20,$22,$1C,$00 +byte = $38,$04,$02,$1E,$22,$22,$1C,$00,$3E,$20,$10,$08,$04,$04,$04,$00 +byte = $1C,$22,$22,$1C,$22,$22,$1C,$00,$1C,$22,$22,$3C,$20,$10,$0E,$00 +byte = $00,$00,$08,$00,$08,$00,$00,$00,$00,$00,$08,$00,$08,$08,$04,$00 +byte = $10,$08,$04,$02,$04,$08,$10,$00,$00,$00,$3E,$00,$3E,$00,$00,$00 +byte = $04,$08,$10,$20,$10,$08,$04,$00,$1C,$22,$10,$08,$08,$00,$08,$00 +byte = $1C,$22,$2A,$3A,$1A,$02,$3C,$00,$08,$14,$22,$22,$3E,$22,$22,$00 +byte = $1E,$22,$22,$1E,$22,$22,$1E,$00,$1C,$22,$02,$02,$02,$22,$1C,$00 +byte = $1E,$22,$22,$22,$22,$22,$1E,$00,$3E,$02,$02,$1E,$02,$02,$3E,$00 +byte = $3E,$02,$02,$1E,$02,$02,$02,$00,$3C,$02,$02,$02,$32,$22,$3C,$00 +byte = $22,$22,$22,$3E,$22,$22,$22,$00,$1C,$08,$08,$08,$08,$08,$1C,$00 +byte = $20,$20,$20,$20,$20,$22,$1C,$00,$22,$12,$0A,$06,$0A,$12,$22,$00 +byte = $02,$02,$02,$02,$02,$02,$3E,$00,$22,$36,$2A,$2A,$22,$22,$22,$00 +byte = $22,$22,$26,$2A,$32,$22,$22,$00,$1C,$22,$22,$22,$22,$22,$1C,$00 +byte = $1E,$22,$22,$1E,$02,$02,$02,$00,$1C,$22,$22,$22,$2A,$12,$2C,$00 +byte = $1E,$22,$22,$1E,$0A,$12,$22,$00,$1C,$22,$02,$1C,$20,$22,$1C,$00 +byte = $3E,$08,$08,$08,$08,$08,$08,$00,$22,$22,$22,$22,$22,$22,$1C,$00 +byte = $22,$22,$22,$22,$22,$14,$08,$00,$22,$22,$22,$2A,$2A,$36,$22,$00 +byte = $22,$22,$14,$08,$14,$22,$22,$00,$22,$22,$14,$08,$08,$08,$08,$00 +byte = $3E,$20,$10,$08,$04,$02,$3E,$00,$3E,$06,$06,$06,$06,$06,$3E,$00 +byte = $00,$02,$04,$08,$10,$20,$00,$00,$3E,$30,$30,$30,$30,$30,$3E,$00 +byte = $00,$00,$08,$14,$22,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7F +byte = $00,$00,$00,$00,$00,$00,$00,$00,$08,$08,$08,$08,$08,$00,$08,$00 +byte = $14,$14,$14,$00,$00,$00,$00,$00,$14,$14,$3E,$14,$3E,$14,$14,$00 +byte = $08,$3C,$0A,$1C,$28,$1E,$08,$00,$06,$26,$10,$08,$04,$32,$30,$00 +byte = $04,$0A,$0A,$04,$2A,$12,$2C,$00,$08,$08,$08,$00,$00,$00,$00,$00 +byte = $08,$04,$02,$02,$02,$04,$08,$00,$08,$10,$20,$20,$20,$10,$08,$00 +byte = $08,$2A,$1C,$08,$1C,$2A,$08,$00,$00,$08,$08,$3E,$08,$08,$00,$00 +byte = $00,$00,$00,$00,$08,$08,$04,$00,$00,$00,$00,$3E,$00,$00,$00,$00 +byte = $00,$00,$00,$00,$00,$00,$08,$00,$00,$20,$10,$08,$04,$02,$00,$00 +byte = $1C,$22,$32,$2A,$26,$22,$1C,$00,$08,$0C,$08,$08,$08,$08,$1C,$00 +byte = $1C,$22,$20,$18,$04,$02,$3E,$00,$3E,$20,$10,$18,$20,$22,$1C,$00 +byte = $10,$18,$14,$12,$3E,$10,$10,$00,$3E,$02,$1E,$20,$20,$22,$1C,$00 +byte = $38,$04,$02,$1E,$22,$22,$1C,$00,$3E,$20,$10,$08,$04,$04,$04,$00 +byte = $1C,$22,$22,$1C,$22,$22,$1C,$00,$1C,$22,$22,$3C,$20,$10,$0E,$00 +byte = $00,$00,$08,$00,$08,$00,$00,$00,$00,$00,$08,$00,$08,$08,$04,$00 +byte = $10,$08,$04,$02,$04,$08,$10,$00,$00,$00,$3E,$00,$3E,$00,$00,$00 +byte = $04,$08,$10,$20,$10,$08,$04,$00,$1C,$22,$10,$08,$08,$00,$08,$00 +byte = $1C,$22,$2A,$3A,$1A,$02,$3C,$00,$08,$14,$22,$22,$3E,$22,$22,$00 +byte = $1E,$22,$22,$1E,$22,$22,$1E,$00,$1C,$22,$02,$02,$02,$22,$1C,$00 +byte = $1E,$22,$22,$22,$22,$22,$1E,$00,$3E,$02,$02,$1E,$02,$02,$3E,$00 +byte = $3E,$02,$02,$1E,$02,$02,$02,$00,$3C,$02,$02,$02,$32,$22,$3C,$00 +byte = $22,$22,$22,$3E,$22,$22,$22,$00,$1C,$08,$08,$08,$08,$08,$1C,$00 +byte = $20,$20,$20,$20,$20,$22,$1C,$00,$22,$12,$0A,$06,$0A,$12,$22,$00 +byte = $02,$02,$02,$02,$02,$02,$3E,$00,$22,$36,$2A,$2A,$22,$22,$22,$00 +byte = $22,$22,$26,$2A,$32,$22,$22,$00,$1C,$22,$22,$22,$22,$22,$1C,$00 +byte = $1E,$22,$22,$1E,$02,$02,$02,$00,$1C,$22,$22,$22,$2A,$12,$2C,$00 +byte = $1E,$22,$22,$1E,$0A,$12,$22,$00,$1C,$22,$02,$1C,$20,$22,$1C,$00 +byte = $3E,$08,$08,$08,$08,$08,$08,$00,$22,$22,$22,$22,$22,$22,$1C,$00 +byte = $22,$22,$22,$22,$22,$14,$08,$00,$22,$22,$22,$2A,$2A,$36,$22,$00 +byte = $22,$22,$14,$08,$14,$22,$22,$00,$22,$22,$14,$08,$08,$08,$08,$00 +byte = $3E,$20,$10,$08,$04,$02,$3E,$00,$3E,$06,$06,$06,$06,$06,$3E,$00 +byte = $00,$02,$04,$08,$10,$20,$00,$00,$3E,$30,$30,$30,$30,$30,$3E,$00 +byte = $00,$00,$08,$14,$22,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7F +byte = $00,$00,$00,$00,$00,$00,$00,$00,$08,$08,$08,$08,$08,$00,$08,$00 +byte = $14,$14,$14,$00,$00,$00,$00,$00,$14,$14,$3E,$14,$3E,$14,$14,$00 +byte = $08,$3C,$0A,$1C,$28,$1E,$08,$00,$06,$26,$10,$08,$04,$32,$30,$00 +byte = $04,$0A,$0A,$04,$2A,$12,$2C,$00,$08,$08,$08,$00,$00,$00,$00,$00 +byte = $08,$04,$02,$02,$02,$04,$08,$00,$08,$10,$20,$20,$20,$10,$08,$00 +byte = $08,$2A,$1C,$08,$1C,$2A,$08,$00,$00,$08,$08,$3E,$08,$08,$00,$00 +byte = $00,$00,$00,$00,$08,$08,$04,$00,$00,$00,$00,$3E,$00,$00,$00,$00 +byte = $00,$00,$00,$00,$00,$00,$08,$00,$00,$20,$10,$08,$04,$02,$00,$00 +byte = $1C,$22,$32,$2A,$26,$22,$1C,$00,$08,$0C,$08,$08,$08,$08,$1C,$00 +byte = $1C,$22,$20,$18,$04,$02,$3E,$00,$3E,$20,$10,$18,$20,$22,$1C,$00 +byte = $10,$18,$14,$12,$3E,$10,$10,$00,$3E,$02,$1E,$20,$20,$22,$1C,$00 +byte = $38,$04,$02,$1E,$22,$22,$1C,$00,$3E,$20,$10,$08,$04,$04,$04,$00 +byte = $1C,$22,$22,$1C,$22,$22,$1C,$00,$1C,$22,$22,$3C,$20,$10,$0E,$00 +byte = $00,$00,$08,$00,$08,$00,$00,$00,$00,$00,$08,$00,$08,$08,$04,$00 +byte = $10,$08,$04,$02,$04,$08,$10,$00,$00,$00,$3E,$00,$3E,$00,$00,$00 +byte = $04,$08,$10,$20,$10,$08,$04,$00,$1C,$22,$10,$08,$08,$00,$08,$00 +byte = $1C,$22,$2A,$3A,$1A,$02,$3C,$00,$08,$14,$22,$22,$3E,$22,$22,$00 +byte = $1E,$22,$22,$1E,$22,$22,$1E,$00,$1C,$22,$02,$02,$02,$22,$1C,$00 +byte = $1E,$22,$22,$22,$22,$22,$1E,$00,$3E,$02,$02,$1E,$02,$02,$3E,$00 +byte = $3E,$02,$02,$1E,$02,$02,$02,$00,$3C,$02,$02,$02,$32,$22,$3C,$00 +byte = $22,$22,$22,$3E,$22,$22,$22,$00,$1C,$08,$08,$08,$08,$08,$1C,$00 +byte = $20,$20,$20,$20,$20,$22,$1C,$00,$22,$12,$0A,$06,$0A,$12,$22,$00 +byte = $02,$02,$02,$02,$02,$02,$3E,$00,$22,$36,$2A,$2A,$22,$22,$22,$00 +byte = $22,$22,$26,$2A,$32,$22,$22,$00,$1C,$22,$22,$22,$22,$22,$1C,$00 +byte = $1E,$22,$22,$1E,$02,$02,$02,$00,$1C,$22,$22,$22,$2A,$12,$2C,$00 +byte = $1E,$22,$22,$1E,$0A,$12,$22,$00,$1C,$22,$02,$1C,$20,$22,$1C,$00 +byte = $3E,$08,$08,$08,$08,$08,$08,$00,$22,$22,$22,$22,$22,$22,$1C,$00 +byte = $22,$22,$22,$22,$22,$14,$08,$00,$22,$22,$22,$2A,$2A,$36,$22,$00 +byte = $22,$22,$14,$08,$14,$22,$22,$00,$22,$22,$14,$08,$08,$08,$08,$00 +byte = $3E,$20,$10,$08,$04,$02,$3E,$00,$3E,$06,$06,$06,$06,$06,$3E,$00 +byte = $00,$02,$04,$08,$10,$20,$00,$00,$3E,$30,$30,$30,$30,$30,$3E,$00 +byte = $00,$00,$08,$14,$22,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7F +byte = $04,$08,$10,$00,$00,$00,$00,$00,$00,$00,$1C,$20,$3C,$22,$3C,$00 +byte = $02,$02,$1E,$22,$22,$22,$1E,$00,$00,$00,$3C,$02,$02,$02,$3C,$00 +byte = $20,$20,$3C,$22,$22,$22,$3C,$00,$00,$00,$1C,$22,$3E,$02,$3C,$00 +byte = $18,$24,$04,$1E,$04,$04,$04,$00,$00,$00,$1C,$22,$22,$3C,$20,$1C +byte = $02,$02,$1E,$22,$22,$22,$22,$00,$08,$00,$0C,$08,$08,$08,$1C,$00 +byte = $10,$00,$18,$10,$10,$10,$12,$0C,$02,$02,$22,$12,$0E,$12,$22,$00 +byte = $0C,$08,$08,$08,$08,$08,$1C,$00,$00,$00,$36,$2A,$2A,$22,$22,$00 +byte = $00,$00,$1E,$22,$22,$22,$22,$00,$00,$00,$1C,$22,$22,$22,$1C,$00 +byte = $00,$00,$1E,$22,$22,$1E,$02,$02,$00,$00,$3C,$22,$22,$3C,$20,$20 +byte = $00,$00,$3A,$06,$02,$02,$02,$00,$00,$00,$3C,$02,$1C,$20,$1E,$00 +byte = $04,$04,$1E,$04,$04,$24,$18,$00,$00,$00,$22,$22,$22,$32,$2C,$00 +byte = $00,$00,$22,$22,$22,$14,$08,$00,$00,$00,$22,$22,$2A,$2A,$36,$00 +byte = $00,$00,$22,$14,$08,$14,$22,$00,$00,$00,$22,$22,$22,$3C,$20,$1C +byte = $00,$00,$3E,$10,$08,$04,$3E,$00,$38,$0C,$0C,$06,$0C,$0C,$38,$00 +byte = $08,$08,$08,$08,$08,$08,$08,$08,$0E,$18,$18,$30,$18,$18,$0E,$00 +byte = $00,$2C,$1A,$00,$00,$00,$00,$00,$00,$2A,$14,$2A,$14,$2A,$00,$00 +// +// Print string with HGR tile library +// +export def hgrPutStr(x, y, strptr)#0 + tileDrawStr(x, y, strptr + 1, ^strptr, @hgrFont + 1024) // Offset into regular char +end +done diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index 11afa77..395fa78 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -1148,22 +1148,29 @@ export def hgrBLT(x, y, w, h, srcptr)#0 next curhclr = saveclr end -export def hgrMode#1 - memset(hgr1, 0, $2000) // Clear HGR page 1 - ^showpage1 - ^showfull - ^showhires - ^showgraphics - drawpage = 1 - drawbuff = hgrbuff[1] - return 1 -end -export def txtMode#0 +export def hgrMode(mode)#1 + if mode + // + // Set HGR mode + // + memset(hgr1, 0, $2000) // Clear HGR page 1 + ^showpage1 + ^showfull + ^showhires + ^showgraphics + drawpage = 1 + drawbuff = hgrbuff[1] + return 1 + fin + // + // Show text mode + // ^showpage1 ^showtext + return 0 end export def hgrClear#0 - memset(drawbuff, curhclr, $2000) // Clear HGR page 1 + memset(drawbuff, curhclr, drawbuff) // Clear current HGR page end // // Set display page, return other page diff --git a/src/libsrc/apple/hgrtile.pla b/src/libsrc/apple/hgrtile.pla new file mode 100644 index 0000000..df0c415 --- /dev/null +++ b/src/libsrc/apple/hgrtile.pla @@ -0,0 +1,377 @@ +include "inc/cmdsys.plh" +// +// Hardware addresses +// +const showgraphics = $C050 +const showtext = $C051 +const showfull = $C052 +const showmix = $C053 +const showpage1 = $C054 +const showpage2 = $C055 +const showlores = $C056 +const showhires = $C057 +const keyboard = $C000 +const keystrobe = $C010 +const txt1 = $0400 +const txt2 = $0800 +const hgr1 = $2000 +const hgr2 = $4000 +const page1 = 0 +const page2 = 1 + +word txtbuff[] = txt1, txt2 +word hgrbuff[] = hgr1, hgr2 +// +// Screen tile scanline addresses. +// +word[] scanaddr = $0000,$0080,$0100,$0180,$0200,$0280,$0300,$0380 +word = $0028,$00A8,$0128,$01A8,$0228,$02A8,$0328,$03A8 +word = $0050,$00D0,$0150,$01D0,$0250,$02D0,$0350,$03D0 +byte[] scanbttml = $00,$80,$00,$80,$00,$80,$00,$80 +byte = $28,$A8,$28,$A8,$28,$A8,$28,$A8 +byte = $50,$D0,$50,$D0,$50,$D0,$50,$D0 +byte[] scanbttmh = $1C,$1C,$1D,$1D,$1E,$1E,$1F,$1F +byte = $1C,$1C,$1D,$1D,$1E,$1E,$1F,$1F +byte = $1C,$1C,$1D,$1D,$1E,$1E,$1F,$1F + +byte hbmask = $81,$82,$84,$88,$90,$A0,$C0 +word hcolor[] = $0000,$552A,$2A55,$7F7F,$8080,$D5AA,$AAD5,$FFFF +byte drawpage = 0 +word drawbuff = hgr1 + +asm tileInc#0 +!SOURCE "vmsrc/plvmzp.inc" +CURSH = $24 +CURSV = $25 +GBASL = $26 +GBASH = $27 +GBASE = GBASL +TBASL = $28 +TBASH = $29 +TBASE = TBASL +TBAS2L = $2A +TBAS2H = $2B +TBAS2E = TBAS2L +end +//export def tileDraw(x, y, tileptr)#0 +// var scrnptr +// +// scrnptr = (scanaddr[y] | drawbuff) + x +// scrnptr->[$1C00] = tileptr->[7] +// scrnptr->[$1800] = tileptr->[6] +// scrnptr->[$1400] = tileptr->[5] +// scrnptr->[$1000] = tileptr->[4] +// scrnptr->[$0C00] = tileptr->[3] +// scrnptr->[$0800] = tileptr->[2] +// scrnptr->[$0400] = tileptr->[1] +// scrnptr->[$0000] = tileptr->[0] +//end +export asm tileDraw(x, y, tileptr)#0 + LDA ESTKL+0,X ; TILEPTRL + STA SRCL + LDA ESTKH+0,X ; TILEPTRH + STA SRCH + LDY ESTKL+1,X ; Y COORD + LDA ESTKL+2,X ; X COORD + CLC +end +asm _tileDraw + ADC $1000,Y ; SCANBTTML + STA ESTKL+0,X ; USE ESTK AS POINTER + LDA $3001 ; DRAWBUFFH + ADC $2000,Y ; SCANBTTMH + STA ESTKL+1,X + LDY #$07 ; DRAW BOTTOM UP + SEC +- LDA (SRC),Y + STA (ESTKL,X) + LDA ESTKL+1,X + SBC #$04 + STA ESTKL+1,X + DEY + BNE - + LDA (SRC),Y + STA (ESTKL,X) + INX + INX + INX + RTS +end +//export def tileXorDraw(x, y, tileptr)#0 +// var scrnptr +// +// scrnptr = (scanaddr[y] | drawbuff) + x +// scrnptr->[$1C00] = tileptr->[7] +// scrnptr->[$1800] = tileptr->[6] +// scrnptr->[$1400] = tileptr->[5] +// scrnptr->[$1000] = tileptr->[4] +// scrnptr->[$0C00] = tileptr->[3] +// scrnptr->[$0800] = tileptr->[2] +// scrnptr->[$0400] = tileptr->[1] +// scrnptr->[$0000] = tileptr->[0] +//end +export asm tileXorDraw(x, y, tileptr)#0 + LDA ESTKL+0,X ; TILEPTRL + STA SRCL + LDA ESTKH+0,X ; TILEPTRH + STA SRCH + LDY ESTKL+1,X ; Y COORD + LDA ESTKL+2,X ; X COORD + CLC +end +asm _tileXDraw + ADC $1000,Y ; SCANBTTML + STA ESTKL+0,X ; USE ESTK AS POINTER + LDA $3001 ; DRAWBUFFH + ADC $2000,Y ; SCANBTTMH + STA ESTKL+1,X + LDY #$07 ; DRAW BOTTOM UP + SEC +- LDA (SRC),Y + EOR (ESTKL,X) + STA (ESTKL,X) + LDA ESTKL+1,X + SBC #$04 + STA ESTKL+1,X + DEY + BNE - + LDA (SRC),Y + EOR (ESTKL,X) + STA (ESTKL,X) + INX + INX + INX + RTS +end +//export def tileOrDraw(x, y, tileptr)#0 +// var scrnptr +// +// scrnptr = (scanaddr[y] | drawbuff) + x +// scrnptr->[$1C00] = tileptr->[7] +// scrnptr->[$1800] = tileptr->[6] +// scrnptr->[$1400] = tileptr->[5] +// scrnptr->[$1000] = tileptr->[4] +// scrnptr->[$0C00] = tileptr->[3] +// scrnptr->[$0800] = tileptr->[2] +// scrnptr->[$0400] = tileptr->[1] +// scrnptr->[$0000] = tileptr->[0] +//end +export asm tileOrDraw(x, y, tileptr)#0 + LDA ESTKL+0,X ; TILEPTRL + STA SRCL + LDA ESTKH+0,X ; TILEPTRH + STA SRCH + LDY ESTKL+1,X ; Y COORD + LDA ESTKL+2,X ; X COORD + CLC +end +asm _tileODraw + ADC $1000,Y ; SCANBTTML + STA ESTKL+0,X ; USE ESTK AS POINTER + LDA $3001 ; DRAWBUFFH + ADC $2000,Y ; SCANBTTMH + STA ESTKL+1,X + LDY #$07 ; DRAW BOTTOM UP + SEC +- LDA (SRC),Y + ORA (ESTKL,X) + STA (ESTKL,X) + LDA ESTKL+1,X + SBC #$04 + STA ESTKL+1,X + DEY + BNE - + LDA (SRC),Y + ORA (ESTKL,X) + STA (ESTKL,X) + INX + INX + INX + RTS +end +//export def tileAndDraw(x, y, tileptr)#0 +// var scrnptr +// +// scrnptr = (scanaddr[y] | drawbuff) + x +// scrnptr->[$1C00] = tileptr->[7] +// scrnptr->[$1800] = tileptr->[6] +// scrnptr->[$1400] = tileptr->[5] +// scrnptr->[$1000] = tileptr->[4] +// scrnptr->[$0C00] = tileptr->[3] +// scrnptr->[$0800] = tileptr->[2] +// scrnptr->[$0400] = tileptr->[1] +// scrnptr->[$0000] = tileptr->[0] +//end +export asm tileAndDraw(x, y, tileptr)#0 + LDA ESTKL+0,X ; TILEPTRL + STA SRCL + LDA ESTKH+0,X ; TILEPTRH + STA SRCH + LDY ESTKL+1,X ; Y COORD + LDA ESTKL+2,X ; X COORD + CLC +end +asm _tileADraw + ADC $1000,Y ; SCANBTTML + STA ESTKL+0,X ; USE ESTK AS POINTER + LDA $3001 ; DRAWBUFFH + ADC $2000,Y ; SCANBTTMH + STA ESTKL+1,X + LDY #$07 ; DRAW BOTTOM UP + SEC +- LDA (SRC),Y + AND (ESTKL,X) + STA (ESTKL,X) + LDA ESTKL+1,X + SBC #$04 + STA ESTKL+1,X + DEY + BNE - + LDA (SRC),Y + AND (ESTKL,X) + STA (ESTKL,X) + INX + INX + INX + RTS +end +//export def tileDrawStr(x, y, strptr, strlen, tileset)#0 +// while strlen +// tileDraw(x, y, tileset + ^strptr * 8) +// x++ +// strptr++ +// strlen-- +// loop +//end +export asm tileDrawStr(x, y, strptr, strlen, tileset)#0 + LDA ESTKL+2,X ; STRPTRL + STA TMPL + LDA ESTKH+2,X ; STRPTRH + STA TMPH + LDY ESTKL+3,X ; Y COORD + LDA ESTKL+4,X ; X COORD + CLC +end +asm _tileDrawStr + ADC $1000,Y ; SCANBTTML + STA ESTKL+2,X ; USE ESTK AS POINTER + LDA $3001 ; DRAWBUFFH + ADC $2000,Y ; SCANBTTMH + STA ESTKL+3,X + LDA #$00 + STA ESTKH+1,X ; USE STRLENH AS COUNT +-- LDY ESTKH+1,X + LDA #$00 + STA SRCH + LDA (TMP),Y ; TILE INDEX * 8 + ASL + ROL SRCH + ASL + ROL SRCH + ASL + ROL SRCH + CLC + ADC ESTKL+0,X ; ADD TO TILESETPTR + STA SRCL + LDA SRCH + ADC ESTKH+0,X + STA SRCH + LDY #$07 ; DRAW BOTTOM UP + SEC +- LDA (SRC),Y + STA (ESTKL+2,X) + LDA ESTKL+3,X + SBC #$04 + STA ESTKL+3,X + DEY + BNE - + LDA (SRC),Y + STA (ESTKL+2,X) + DEC ESTKL+1,X ; STRLEN + BEQ + + INC ESTKL+2,X ; RESET SCREEN PTR TO NEXT TILE POS + LDA ESTKL+3,X + CLC + ADC #$1C + STA ESTKL+3,X + INC ESTKH+1,X ; COUNT++ + BNE -- ++ INX + INX + INX + INX + INX + RTS +end +export def tileFromText(txtpage, tileset)#0 + byte y + word txtptr + + txtptr = txtbuff[txtpage & 1] + for y = 0 to 23 + tileDrawStr(0, y, scanaddr[y] | txtptr, 40, tileset) + next +end +export def tileMode(mode)#1 + if mode + // + // Set HGR mode + // + memset(hgr1, 0, $2000) // Clear HGR page 1 + ^showpage1 + ^showfull + ^showhires + ^showgraphics + drawpage = 0 + drawbuff = hgr1 + return 0 + fin + // + // Show text mode + // + ^showpage1 + ^showtext + return 0 +end +export def tileClear#0 + memset(drawbuff, $0000, drawbuff) // Clear current HGR page +end +// +// Set display page, return other page +// +export def tileShow(page)#1 + page = page & 1 + ^(showpage1 + page) + return page ^ 1 +end +export def tileSwap#1 + ^(showpage1 + drawpage) + drawpage = drawpage ^ 1 + drawbuff = hgrbuff[drawpage] + return drawpage +end +export def tileDrawBuf(page)#1 + drawpage = page & 1 + drawbuff = hgrbuff[drawpage] + return drawpage +end +// +// Assembly fixups +// +_tileDraw:1 = @scanbttml +_tileDraw:6 = @drawbuff.1 +_tileDraw:9 = @scanbttmh +_tileXDraw:1 = @scanbttml +_tileXDraw:6 = @drawbuff.1 +_tileXDraw:9 = @scanbttmh +_tileODraw:1 = @scanbttml +_tileODraw:6 = @drawbuff.1 +_tileODraw:9 = @scanbttmh +_tileADraw:1 = @scanbttml +_tileADraw:6 = @drawbuff.1 +_tileADraw:9 = @scanbttmh +_tileDrawStr:1 = @scanbttml +_tileDrawStr:6 = @drawbuff.1 +_tileDrawStr:9 = @scanbttmh +done + diff --git a/src/makefile b/src/makefile index 743d721..31bf46a 100755 --- a/src/makefile +++ b/src/makefile @@ -63,6 +63,8 @@ HGRLIB = rel/apple/HGRLIB\#FE1000 GRLIB = rel/apple/GRLIB\#FE1000 DGRLIB = rel/apple/DGRLIB\#FE1000 HGRSPRITE = rel/apple/HGRSPRITE\#FE1000 +HGRTILE = rel/apple/HGRTILE\#FE1000 +HGRFONT = rel/apple/HGRFONT\#FE1000 LINES = rel/LINES\#FE1000 GRAFIX = rel/apple/GRAFIX\#FE1000 SFM = rel/apple/SFM\#FE1000 @@ -74,6 +76,7 @@ ROGUE = rel/ROGUE\#FE1000 ROGUEMAP = rel/ROGUEMAP\#FE1000 ROGUECOMBAT= rel/ROGUECOMBAT\#FE1000 MON = rel/apple/MON\#FE1000 +TILETEST = rel/apple/TILETEST\#FE1000 HGRTEST = rel/apple/HGRTEST\#FE1000 GRTEST = rel/apple/GRTEST\#FE1000 DGRTEST = rel/apple/DGRTEST\#FE1000 @@ -106,7 +109,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(ZIP) $(MATCHFILES) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(SFM) $(SFMSPRT) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(PLVMJIT03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(SOSCMDJIT) $(PLASMAPLASM) $(CODEOPT) $(ZIP) $(MATCHFILES) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(SFM) $(SFMSPRT) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRTILE) $(HGRFONT) $(HGRSPRITE) $(HGRLIB) $(TILETEST) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -444,6 +447,18 @@ $(DGRLIB): libsrc/apple/dgrlib.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/dgrlib.pla > libsrc/apple/dgrlib.a acme --setpc 4094 -o $(DGRLIB) libsrc/apple/dgrlib.a +$(TILETEST): samplesrc/tiletest.pla $(PLASM) + ./$(PLASM) -AMOW < samplesrc/tiletest.pla > samplesrc/tiletest.a + acme --setpc 4094 -o $(TILETEST) samplesrc/tiletest.a + +$(HGRTILE): libsrc/apple/hgrtile.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < libsrc/apple/hgrtile.pla > libsrc/apple/hgrtile.a + acme --setpc 4094 -o $(HGRTILE) libsrc/apple/hgrtile.a + +$(HGRFONT): libsrc/apple/hgrfont.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < libsrc/apple/hgrfont.pla > libsrc/apple/hgrfont.a + acme --setpc 4094 -o $(HGRFONT) libsrc/apple/hgrfont.a + $(HGRSPRITE): libsrc/apple/hgrsprite.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/hgrsprite.pla > libsrc/apple/hgrsprite.a acme --setpc 4094 -o $(HGRSPRITE) libsrc/apple/hgrsprite.a diff --git a/src/mkrel b/src/mkrel index 9dfe67a..5a559bf 100755 --- a/src/mkrel +++ b/src/mkrel @@ -10,6 +10,8 @@ mkdir prodos/sys cp rel/apple/FILEIO#FE1000 prodos/sys/FILEIO.REL cp rel/apple/CONIO#FE1000 prodos/sys/CONIO.REL cp rel/LINES#FE1000 prodos/sys/LINES.REL +cp rel/apple/HGRFONT#FE1000 prodos/sys/HGRFONT.REL +cp rel/apple/HGRTILE#FE1000 prodos/sys/HGRTILE.REL cp rel/apple/HGRSPRITE#FE1000 prodos/sys/HGRSPRITE.REL cp rel/apple/HGRLIB#FE1000 prodos/sys/HGRLIB.REL cp rel/apple/GRLIB#FE1000 prodos/sys/GRLIB.REL @@ -71,6 +73,7 @@ cp ../sysfiles/ELEMS.CODE#060000 prodos/fpsos/sys/ELEMS.CODE.BIN rm -rf prodos/demos mkdir prodos/demos cp rel/INT32TEST#FE1000 prodos/demos/INT32TEST.REL +cp rel/apple/TILETEST#FE1000 prodos/demos/TILETEST.REL cp rel/apple/HGRTEST#FE1000 prodos/demos/HGRTEST.REL cp rel/apple/GRTEST#FE1000 prodos/demos/GRTEST.REL cp rel/apple/DGRTEST#FE1000 prodos/demos/DGRTEST.REL @@ -124,6 +127,7 @@ cp samplesrc/int32test.pla prodos/bld/samples/INT32TEST.PLA.TXT cp samplesrc/grtest.pla prodos/bld/samples/GRTEST.PLA.TXT cp samplesrc/dgrtest.pla prodos/bld/samples/DGRTEST.PLA.TXT cp samplesrc/hgrtest.pla prodos/bld/samples/HGRTEST.PLA.TXT +cp samplesrc/tiletest.pla prodos/bld/samples/TILETEST.PLA.TXT cp samplesrc/fibertest.pla prodos/bld/samples/FIBERTEST.PLA.TXT cp samplesrc/mousetest.pla prodos/bld/samples/MOUSETEST.PLA.TXT cp samplesrc/memtest.pla prodos/bld/samples/MEMTEST.PLA.TXT @@ -164,6 +168,8 @@ cp inc/matchfiles.plh prodos/bld/inc/MATCHFILES.PLH.TXT cp inc/cmdsys.plh prodos/bld/inc/CMDSYS.PLH.TXT cp inc/conio.plh prodos/bld/inc/CONIO.PLH.TXT cp inc/lines.plh prodos/bld/inc/LINES.PLH.TXT +cp inc/hgrfont.plh prodos/bld/inc/HGRFONT.PLH.TXT +cp inc/hgrtile.plh prodos/bld/inc/HGRTILE.PLH.TXT cp inc/hgrsprite.plh prodos/bld/inc/HGRSPRITE.PLH.TXT cp inc/hgrlib.plh prodos/bld/inc/HGRLIB.PLH.TXT cp inc/grlib.plh prodos/bld/inc/GRLIB.PLH.TXT diff --git a/src/samplesrc/dgrtest.pla b/src/samplesrc/dgrtest.pla index 11ca80f..c5ead35 100644 --- a/src/samplesrc/dgrtest.pla +++ b/src/samplesrc/dgrtest.pla @@ -24,7 +24,7 @@ def dgrTest#0 byte b, l, k word i, j, ii, ij - b = dgrMode() + b = dgrMode(TRUE) dgrDrawBuf(0) for k = 15 downto 0 dgrClear(k) @@ -59,7 +59,7 @@ def dgrTest#0 fin loop ^$C010 - txtMode + dgrMode(FALSE) end dgrTest diff --git a/src/samplesrc/grtest.pla b/src/samplesrc/grtest.pla index 48ea2ff..88880a7 100644 --- a/src/samplesrc/grtest.pla +++ b/src/samplesrc/grtest.pla @@ -24,7 +24,7 @@ def grTest#0 byte b, l, k word i, j, ii, ij - b = grMode() + b = grMode(TRUE) grDrawBuf(0) for k = 15 downto 0 grClear(k) @@ -59,7 +59,7 @@ def grTest#0 fin loop ^$C010 - txtMode + grMode(FALSE) end grTest diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index 70206db..64d4080 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -66,7 +66,7 @@ def testblt(sprtnum)#0 loop end -hgrMode +hgrMode(TRUE) spriteDrawBuf(hgrDrawBuf(0)) // So we can see the compile process sprtBall = spriteCompile(10, 10, 5, 5, @ball) hgrColor(0) @@ -77,5 +77,5 @@ spriteDrawBuf(hgrDrawBuf(1)) spriteAdd(0, sprtBall) testblt(16) getc -txtMode +hgrMode(FALSE) done diff --git a/src/samplesrc/sfm.pla b/src/samplesrc/sfm.pla index b47b3f3..69396f6 100644 --- a/src/samplesrc/sfm.pla +++ b/src/samplesrc/sfm.pla @@ -575,7 +575,7 @@ next heapstart = heapmark() //puts("\nBeginning available memory: "); puti(heapavail()); putln repeat - hgrMode + hgrMode(TRUE) spriteDrawBuf(hgrDrawBuf(0)) // Single buffered spriteAdd(SHIP_SPRTNUM, sprtShip) spriteAdd(SPIDER_SPRTEBASE, sprtEgg3) @@ -617,7 +617,7 @@ repeat puts("\nEarth has been overrun") puts("\nby the Spiders from Mars\n") fin - txtMode + hgrMode(FALSE) // // Clear sprite lists // diff --git a/src/samplesrc/sfmsprt.pla b/src/samplesrc/sfmsprt.pla index 4ef6b8d..6f53a34 100644 --- a/src/samplesrc/sfmsprt.pla +++ b/src/samplesrc/sfmsprt.pla @@ -169,7 +169,7 @@ var sprtSplat1, sprtSplat2 var sprtWeb1, sprtWeb2, sprtWeb3 var sprtShip, sprtMissle, sprtDummy -hgrMode +hgrMode(TRUE) spriteDrawBuf(hgrDrawBuf(0)) // So we can see the compile process sprtShip = spriteCompile(14, 14, 7, 13, @ship) sprtMissle = spriteCompile( 6, 8, 3, 0, @missle) @@ -185,7 +185,7 @@ sprtWeb3 = spriteCompile(20, 8, 10, 0, @web3) sprtSplat1 = spriteCompile(20, 13, 10, 6, @splat1) sprtSplat2 = spriteCompile(24, 17, 12, 8, @splat2) sprtDummy = spriteCompile( 7, 8, 0, 0, @dummy) -txtMode +hgrMode(FALSE) spriteSave("SHIP", sprtShip) spriteSave("MISSLE", sprtMissle) spriteSave("EGG3", sprtEgg3) diff --git a/src/samplesrc/tiletest.pla b/src/samplesrc/tiletest.pla new file mode 100644 index 0000000..0e4ff28 --- /dev/null +++ b/src/samplesrc/tiletest.pla @@ -0,0 +1,13 @@ +include "inc/cmdsys.plh" +include "inc/hgrtile.plh" +include "inc/hgrfont.plh" +sysflags reshgr1 // Reserve HGR page 1 + +tileMode(TRUE) +hgrPutStr(5, 1, "Hello HiRes Tile Demo") +getc +tileFromText(0, @hgrFont) +getc +tileMode(FALSE) +done + diff --git a/src/tftpbld b/src/tftpbld index d781be5..8e6fe23 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -10,6 +10,8 @@ echo "BLD/INC/MATCHFILES.PLH"; atftp $1 --put -l inc/matchfiles.plh -r $2/BLD/IN echo "BLD/INC/CMDSYS.PLH"; atftp $1 --put -l inc/cmdsys.plh -r $2/BLD/INC/CMDSYS.PLH#040000 echo "BLD/INC/CONIO.PLH"; atftp $1 --put -l inc/conio.plh -r $2/BLD/INC/CONIO.PLH#040000 echo "BLD/INC/LINES.PLH"; atftp $1 --put -l inc/lines.plh -r $2/BLD/INC/LINES.PLH#040000 +echo "BLD/INC/HGRTILE.PLH"; atftp $1 --put -l inc/hgrtile.plh -r $2/BLD/INC/HGRTILE.PLH#040000 +echo "BLD/INC/HGRFONT.PLH";atftp $1 --put -l inc/hgrfont.plh -r $2/BLD/INC/HGRFONT.PLH#040000 echo "BLD/INC/HGRSPRITE.PLH";atftp $1 --put -l inc/hgrsprite.plh -r $2/BLD/INC/HGRSPRITE.PLH#040000 echo "BLD/INC/HGRLIB.PLH"; atftp $1 --put -l inc/hgrlib.plh -r $2/BLD/INC/HGRLIB.PLH#040000 echo "BLD/INC/GRLIB.PLH"; atftp $1 --put -l inc/grlib.plh -r $2/BLD/INC/GRLIB.PLH#040000 @@ -44,6 +46,7 @@ echo "BLD/SAMPLES/INT32TEST.PLA"; atftp $1 --put -l samplesrc/int32test.pla -r $ echo "BLD/SAMPLES/HGRTEST.PLA"; atftp $1 --put -l samplesrc/hgrtest.pla -r $2/BLD/SAMPLES/HGRTEST.PLA#040000 echo "BLD/SAMPLES/GRTEST.PLA"; atftp $1 --put -l samplesrc/grtest.pla -r $2/BLD/SAMPLES/GRTEST.PLA#040000 echo "BLD/SAMPLES/DGRTEST.PLA"; atftp $1 --put -l samplesrc/dgrtest.pla -r $2/BLD/SAMPLES/DGRTEST.PLA#040000 +echo "BLD/SAMPLES/TILETEST.PLA"; atftp $1 --put -l samplesrc/tiletest.pla -r $2/BLD/SAMPLES/TILETEST.PLA#040000 echo "BLD/SAMPLES/HGRTEST.PLA"; atftp $1 --put -l samplesrc/hgrtest.pla -r $2/BLD/SAMPLES/HGRTEST.PLA#040000 echo "BLD/SAMPLES/PLAYSEQ.PLA"; atftp $1 --put -l samplesrc/playseq.pla -r $2/BLD/SAMPLES/PLAYSEQ.PLA#040000 echo "BLD/SAMPLES/RPNCALC.PLA"; atftp $1 --put -l samplesrc/rpncalc.pla -r $2/BLD/SAMPLES/RPNCALC.PLA#040000 diff --git a/src/tftpdemos b/src/tftpdemos index 54d052c..9dcccf8 100755 --- a/src/tftpdemos +++ b/src/tftpdemos @@ -5,6 +5,7 @@ echo "DEMOS/RPNCALC"; atftp $1 --put -l rel/RPNCALC#FE1000 echo "DEMOS/LZ4CAT"; atftp $1 --put -l rel/LZ4CAT#FE1000 -r $2/DEMOS/LZ4CAT#FE1000 echo "DEMOS/SIEVE"; atftp $1 --put -l rel/SIEVE#FE1000 -r $2/DEMOS/SIEVE#FE1000 echo "DEMOS/ROD"; atftp $1 --put -l rel/apple/ROD#FE1000 -r $2/DEMOS/ROD#FE1000 +echo "DEMOS/TILETEST"; atftp $1 --put -l rel/apple/TILETEST#FE1000 -r $2/DEMOS/TILETEST#FE1000 echo "DEMOS/HGRTEST"; atftp $1 --put -l rel/apple/HGRTEST#FE1000 -r $2/DEMOS/HGRTEST#FE1000 echo "DEMOS/GRTEST"; atftp $1 --put -l rel/apple/GRTEST#FE1000 -r $2/DEMOS/GRTEST#FE1000 echo "DEMOS/INT32TEST"; atftp $1 --put -l rel/INT32TEST#FE1000 -r $2/DEMOS/INT32TEST#FE1000 diff --git a/src/tftpsys b/src/tftpsys index a54c52a..2b36848 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -23,6 +23,8 @@ echo "SYS/LONGJUMP"; atftp $1 --put -l rel/LONGJMP#FE1000 -r $2/SYS/LONGJMP#FE10 echo "SYS/MEMMGR"; atftp $1 --put -l rel/MEMMGR#FE1000 -r $2/SYS/MEMMGR#FE1000 echo "SYS/LZ4"; atftp $1 --put -l rel/LZ4#FE1000 -r $2/SYS/LZ4#FE1000 echo "SYS/CONIO"; atftp $1 --put -l rel/apple/CONIO#FE1000 -r $2/SYS/CONIO#FE1000 +echo "SYS/HGRTILE"; atftp $1 --put -l rel/apple/HGRTILE#FE1000 -r $2/SYS/HGRTILE#FE1000 +echo "SYS/HGRFONT"; atftp $1 --put -l rel/apple/HGRFONT#FE1000 -r $2/SYS/HGRFONT#FE1000 echo "SYS/HGRSPRITE"; atftp $1 --put -l rel/apple/HGRSPRITE#FE1000 -r $2/SYS/HGRSPRITE#FE1000 echo "SYS/LINES"; atftp $1 --put -l rel/LINES#FE1000 -r $2/SYS/LINES#FE1000 echo "SYS/HGRLIB"; atftp $1 --put -l rel/apple/HGRLIB#FE1000 -r $2/SYS/HGRLIB#FE1000 From 206e7ae3f4b5a7f15246bb821a3153844f1361f7 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Wed, 8 Jan 2020 14:30:37 -0800 Subject: [PATCH 135/149] A wee bit faster and smaller --- src/libsrc/apple/hgrtile.pla | 39 ++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/libsrc/apple/hgrtile.pla b/src/libsrc/apple/hgrtile.pla index df0c415..2bd7e45 100644 --- a/src/libsrc/apple/hgrtile.pla +++ b/src/libsrc/apple/hgrtile.pla @@ -24,9 +24,9 @@ word hgrbuff[] = hgr1, hgr2 // // Screen tile scanline addresses. // -word[] scanaddr = $0000,$0080,$0100,$0180,$0200,$0280,$0300,$0380 -word = $0028,$00A8,$0128,$01A8,$0228,$02A8,$0328,$03A8 -word = $0050,$00D0,$0150,$01D0,$0250,$02D0,$0350,$03D0 +word[] rowaddr = $0000,$0080,$0100,$0180,$0200,$0280,$0300,$0380 +word = $0028,$00A8,$0128,$01A8,$0228,$02A8,$0328,$03A8 +word = $0050,$00D0,$0150,$01D0,$0250,$02D0,$0350,$03D0 byte[] scanbttml = $00,$80,$00,$80,$00,$80,$00,$80 byte = $28,$A8,$28,$A8,$28,$A8,$28,$A8 byte = $50,$D0,$50,$D0,$50,$D0,$50,$D0 @@ -244,6 +244,8 @@ end // loop //end export asm tileDrawStr(x, y, strptr, strlen, tileset)#0 + DEC ESTKL+1,X ; STRLEN-- + BMI + LDA ESTKL+2,X ; STRPTRL STA TMPL LDA ESTKH+2,X ; STRPTRH @@ -251,6 +253,7 @@ export asm tileDrawStr(x, y, strptr, strlen, tileset)#0 LDY ESTKL+3,X ; Y COORD LDA ESTKL+4,X ; X COORD CLC + ADC ESTKL+1,X ; STRLEN end asm _tileDrawStr ADC $1000,Y ; SCANBTTML @@ -258,11 +261,11 @@ asm _tileDrawStr LDA $3001 ; DRAWBUFFH ADC $2000,Y ; SCANBTTMH STA ESTKL+3,X - LDA #$00 - STA ESTKH+1,X ; USE STRLENH AS COUNT --- LDY ESTKH+1,X - LDA #$00 - STA SRCH + LDY #$00 +; STY ESTKH+1,X ; USE STRLENH AS COUNT +-- STY SRCH +; LDY ESTKH+1,X + LDY ESTKL+1,X ; STRLEN LDA (TMP),Y ; TILE INDEX * 8 ASL ROL SRCH @@ -270,7 +273,7 @@ asm _tileDrawStr ROL SRCH ASL ROL SRCH - CLC +; CLC ADC ESTKL+0,X ; ADD TO TILESETPTR STA SRCL LDA SRCH @@ -287,15 +290,17 @@ asm _tileDrawStr BNE - LDA (SRC),Y STA (ESTKL+2,X) - DEC ESTKL+1,X ; STRLEN - BEQ + - INC ESTKL+2,X ; RESET SCREEN PTR TO NEXT TILE POS +; INC ESTKL+2,X ; RESET SCREEN PTR TO NEXT TILE POS + DEC ESTKL+2,X ; RESET SCREEN PTR TO NEXT TILE POS LDA ESTKL+3,X - CLC - ADC #$1C +; CLC +; ADC #$1C + ADC #$1B ; CARRY STILL SET FROM ABOVE STA ESTKL+3,X - INC ESTKH+1,X ; COUNT++ - BNE -- +; INC ESTKH+1,X ; COUNT++ +; BNE -- + DEC ESTKL+1,X ; STRLEN-- + BPL -- + INX INX INX @@ -309,7 +314,7 @@ export def tileFromText(txtpage, tileset)#0 txtptr = txtbuff[txtpage & 1] for y = 0 to 23 - tileDrawStr(0, y, scanaddr[y] | txtptr, 40, tileset) + tileDrawStr(0, y, rowaddr[y] | txtptr, 40, tileset) next end export def tileMode(mode)#1 From d92d5dd6cd0b1162d67424e8b5114a3097c05b34 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Wed, 8 Jan 2020 14:33:49 -0800 Subject: [PATCH 136/149] A wee'er bit faster --- src/libsrc/apple/hgrtile.pla | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libsrc/apple/hgrtile.pla b/src/libsrc/apple/hgrtile.pla index 2bd7e45..f947268 100644 --- a/src/libsrc/apple/hgrtile.pla +++ b/src/libsrc/apple/hgrtile.pla @@ -262,9 +262,7 @@ asm _tileDrawStr ADC $2000,Y ; SCANBTTMH STA ESTKL+3,X LDY #$00 -; STY ESTKH+1,X ; USE STRLENH AS COUNT -- STY SRCH -; LDY ESTKH+1,X LDY ESTKL+1,X ; STRLEN LDA (TMP),Y ; TILE INDEX * 8 ASL @@ -273,7 +271,7 @@ asm _tileDrawStr ROL SRCH ASL ROL SRCH -; CLC +; CLC ; CARRY IS CLEAR FROM ABOVE ADC ESTKL+0,X ; ADD TO TILESETPTR STA SRCL LDA SRCH @@ -290,15 +288,12 @@ asm _tileDrawStr BNE - LDA (SRC),Y STA (ESTKL+2,X) -; INC ESTKL+2,X ; RESET SCREEN PTR TO NEXT TILE POS DEC ESTKL+2,X ; RESET SCREEN PTR TO NEXT TILE POS LDA ESTKL+3,X ; CLC ; ADC #$1C ADC #$1B ; CARRY STILL SET FROM ABOVE STA ESTKL+3,X -; INC ESTKH+1,X ; COUNT++ -; BNE -- DEC ESTKL+1,X ; STRLEN-- BPL -- + INX From 5e0053569eb984bbb3c2ef355a23bc56e0a9763c Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Wed, 8 Jan 2020 17:27:08 -0800 Subject: [PATCH 137/149] Formatting (which editor keeps messing up the tabs vs spaces?) --- src/samplesrc/rogue.map.pla | 224 ++++++++++++++++++------------------ src/samplesrc/rogue.pla | 52 ++++----- 2 files changed, 138 insertions(+), 138 deletions(-) diff --git a/src/samplesrc/rogue.map.pla b/src/samplesrc/rogue.map.pla index 0ddf1a9..e9ce3bd 100644 --- a/src/samplesrc/rogue.map.pla +++ b/src/samplesrc/rogue.map.pla @@ -402,7 +402,7 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) // Update distance // occluded = 1 - dist = dist + 1 + dist = dist + 1 fin next break @@ -419,12 +419,12 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) if adjtile & OPAQUE_TILE ^(viewmap + imap - mapcols) = adjtile | VIEWED_TILE screen.[ycentr-xbeam[l]-1, xcentr+ybeam[l]] = adjtile - fin + fin fin ^(viewmap + imap) = tile | VIEWED_TILE - if tile <> PIT_TILE + if tile <> PIT_TILE screen.[ycentr-xbeam[l], xcentr+ybeam[l]] = tile & INV_TILE - fin + fin else vispix[l] = 0 fin @@ -437,24 +437,24 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) vispix[l] = 0 else vispix[l] = 1 - occluded = 0 + occluded = 0 fin - if tile & LIT_TILE + if tile & LIT_TILE ^(viewmap + imap) = tile | VIEWED_TILE screen.[ycentr-xbeam[l], xcentr+ybeam[l]] = tile & INV_TILE darkness = 0 - fin + fin else vispix[l] = 0 fin - if l == dbeam[dist] - if occluded - break - fin + if l == dbeam[dist] + if occluded + break + fin occluded = 1 - dist = dist + 1 - fin - next + dist = dist + 1 + fin + next break is 2 for l = 1 to dbeam[lightdist] @@ -464,17 +464,17 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) if tile & OPAQUE_TILE vispix[l] = 0 else - vispix[l] = 1 - adjtile = ^(map + imap + mapcols) & INV_TILE + vispix[l] = 1 + adjtile = ^(map + imap + mapcols) & INV_TILE if adjtile & OPAQUE_TILE ^(viewmap + imap + mapcols) = adjtile | VIEWED_TILE screen.[ycentr+xbeam[l]+1, xcentr+ybeam[l]] = adjtile fin - fin + fin ^(viewmap + imap) = tile | VIEWED_TILE - if tile <> PIT_TILE + if tile <> PIT_TILE screen.[ycentr+xbeam[l], xcentr+ybeam[l]] = tile & INV_TILE - fin + fin else vispix[l] = 0 fin @@ -486,25 +486,25 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) if tile & OPAQUE_TILE vispix[l] = 0 else - vispix[l] = 1 - occluded = 0 - fin - if tile & LIT_TILE + vispix[l] = 1 + occluded = 0 + fin + if tile & LIT_TILE ^(viewmap + imap) = tile | VIEWED_TILE screen.[ycentr+xbeam[l], xcentr+ybeam[l]] = tile & INV_TILE darkness = 0 - fin + fin else vispix[l] = 0 fin - if l == dbeam[dist] - if occluded - break - fin + if l == dbeam[dist] + if occluded + break + fin occluded = 1 - dist = dist + 1 - fin - next + dist = dist + 1 + fin + next break is 3 for l = 1 to dbeam[lightdist] @@ -514,17 +514,17 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) if tile & OPAQUE_TILE vispix[l] = 0 else - vispix[l] = 1 - adjtile = ^(map + imap + 1) & INV_TILE + vispix[l] = 1 + adjtile = ^(map + imap + 1) & INV_TILE if adjtile & OPAQUE_TILE ^(viewmap + imap + 1) = adjtile | VIEWED_TILE screen.[ycentr+ybeam[l], xcentr+xbeam[l]+1] = adjtile fin fin ^(viewmap + imap) = tile | VIEWED_TILE - if tile <> PIT_TILE + if tile <> PIT_TILE screen.[ycentr+ybeam[l], xcentr+xbeam[l]] = tile & INV_TILE - fin + fin else vispix[l] = 0 fin @@ -536,25 +536,25 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) if tile & OPAQUE_TILE vispix[l] = 0 else - vispix[l] = 1 - occluded = 0 - fin - if tile & LIT_TILE + vispix[l] = 1 + occluded = 0 + fin + if tile & LIT_TILE ^(viewmap + imap) = tile | VIEWED_TILE screen.[ycentr+ybeam[l], xcentr+xbeam[l]] = tile & INV_TILE darkness = 0 - fin + fin else vispix[l] = 0 fin - if l == dbeam[dist] - if occluded - break - fin + if l == dbeam[dist] + if occluded + break + fin occluded = 1 - dist = dist + 1 - fin - next + dist = dist + 1 + fin + next break is 4 for l = 1 to dbeam[lightdist] @@ -564,17 +564,17 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) if tile & OPAQUE_TILE vispix[l] = 0 else - vispix[l] = 1 - adjtile = ^(map + imap - 1) & INV_TILE + vispix[l] = 1 + adjtile = ^(map + imap - 1) & INV_TILE if adjtile & OPAQUE_TILE ^(viewmap + imap - 1) = adjtile | VIEWED_TILE screen.[ycentr+ybeam[l], xcentr-xbeam[l]-1] = adjtile fin fin ^(viewmap + imap) = tile | VIEWED_TILE - if tile <> PIT_TILE + if tile <> PIT_TILE screen.[ycentr+ybeam[l], xcentr-xbeam[l]] = tile & INV_TILE - fin + fin else vispix[l] = 0 fin @@ -586,25 +586,25 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) if tile & OPAQUE_TILE vispix[l] = 0 else - vispix[l] = 1 - occluded = 0 - fin - if tile & LIT_TILE + vispix[l] = 1 + occluded = 0 + fin + if tile & LIT_TILE ^(viewmap + imap) = tile | VIEWED_TILE screen.[ycentr+ybeam[l], xcentr-xbeam[l]] = tile & INV_TILE darkness = 0 - fin + fin else vispix[l] = 0 fin - if l == dbeam[dist] - if occluded - break - fin + if l == dbeam[dist] + if occluded + break + fin occluded = 1 - dist = dist + 1 - fin - next + dist = dist + 1 + fin + next break is 5 for l = 1 to dbeam[lightdist] @@ -614,17 +614,17 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) if tile & OPAQUE_TILE vispix[l] = 0 else - vispix[l] = 1 - adjtile = ^(map + imap + mapcols) & INV_TILE + vispix[l] = 1 + adjtile = ^(map + imap + mapcols) & INV_TILE if adjtile & OPAQUE_TILE ^(viewmap + imap + mapcols) = adjtile | VIEWED_TILE screen.[ycentr+xbeam[l]+1, xcentr-ybeam[l]] = adjtile fin fin ^(viewmap + imap) = tile | VIEWED_TILE - if tile <> PIT_TILE + if tile <> PIT_TILE screen.[ycentr+xbeam[l], xcentr-ybeam[l]] = tile & INV_TILE - fin + fin else vispix[l] = 0 fin @@ -636,26 +636,26 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) if tile & OPAQUE_TILE vispix[l] = 0 else - vispix[l] = 1 - occluded = 0 - fin - if tile & LIT_TILE + vispix[l] = 1 + occluded = 0 + fin + if tile & LIT_TILE ^(viewmap + imap) = tile | VIEWED_TILE screen.[ycentr+xbeam[l], xcentr-ybeam[l]] = tile & INV_TILE darkness = 0 - fin + fin else vispix[l] = 0 fin - if l == dbeam[dist] - if occluded - break - fin + if l == dbeam[dist] + if occluded + break + fin occluded = 1 - dist = dist + 1 - fin - next - break + dist = dist + 1 + fin + next + break is 6 for l = 1 to dbeam[lightdist] if vispix[vbeam[l]] @@ -664,17 +664,17 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) if tile & OPAQUE_TILE vispix[l] = 0 else - vispix[l] = 1 - adjtile = ^(map + imap - mapcols) & INV_TILE + vispix[l] = 1 + adjtile = ^(map + imap - mapcols) & INV_TILE if adjtile & OPAQUE_TILE ^(viewmap + imap - mapcols) = adjtile | VIEWED_TILE screen.[ycentr-xbeam[l]-1, xcentr-ybeam[l]] = adjtile fin fin ^(viewmap + imap) = tile | VIEWED_TILE - if tile <> PIT_TILE + if tile <> PIT_TILE screen.[ycentr-xbeam[l], xcentr-ybeam[l]] = tile & INV_TILE - fin + fin else vispix[l] = 0 fin @@ -686,25 +686,25 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) if tile & OPAQUE_TILE vispix[l] = 0 else - vispix[l] = 1 - occluded = 0 - fin - if tile & LIT_TILE + vispix[l] = 1 + occluded = 0 + fin + if tile & LIT_TILE ^(viewmap + imap) = tile | VIEWED_TILE screen.[ycentr-xbeam[l], xcentr-ybeam[l]] = tile & INV_TILE darkness = 0 - fin + fin else vispix[l] = 0 fin - if l == dbeam[dist] - if occluded - break - fin + if l == dbeam[dist] + if occluded + break + fin occluded = 1 - dist = dist + 1 - fin - next + dist = dist + 1 + fin + next break is 7 for l = 1 to dbeam[lightdist] @@ -714,17 +714,17 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) if tile & OPAQUE_TILE vispix[l] = 0 else - vispix[l] = 1 - adjtile = ^(map + imap - 1) & INV_TILE + vispix[l] = 1 + adjtile = ^(map + imap - 1) & INV_TILE if adjtile & OPAQUE_TILE ^(viewmap + imap - 1) = adjtile | VIEWED_TILE screen.[ycentr-ybeam[l], xcentr-xbeam[l]-1] = adjtile fin fin ^(viewmap + imap) = tile | VIEWED_TILE - if tile <> PIT_TILE + if tile <> PIT_TILE screen.[ycentr-ybeam[l], xcentr-xbeam[l]] = tile & INV_TILE - fin + fin else vispix[l] = 0 fin @@ -736,25 +736,25 @@ export def drawmap(xorg, yorg, viewfield, viewdir, lightdist, viewdist) if tile & OPAQUE_TILE vispix[l] = 0 else - vispix[l] = 1 - occluded = 0 - fin - if tile & LIT_TILE + vispix[l] = 1 + occluded = 0 + fin + if tile & LIT_TILE ^(viewmap + imap) = tile | VIEWED_TILE screen.[ycentr-ybeam[l], xcentr-xbeam[l]] = tile & INV_TILE darkness = 0 - fin + fin else vispix[l] = 0 fin - if l == dbeam[dist] - if occluded - break - fin + if l == dbeam[dist] + if occluded + break + fin occluded = 1 - dist = dist + 1 - fin - next + dist = dist + 1 + fin + next break wend next diff --git a/src/samplesrc/rogue.pla b/src/samplesrc/rogue.pla index d7f115a..add2fc1 100755 --- a/src/samplesrc/rogue.pla +++ b/src/samplesrc/rogue.pla @@ -535,47 +535,47 @@ def play is KEY_TILE player.key = 1 updtmaptile(player.xpos, player.ypos, FLOOR_TILE) - gotit - break + gotit + break is RAFT_TILE player.raft = 1 updtmaptile(player.xpos, player.ypos, FLOOR_TILE) - gotit - break + gotit + break is GOLD_TILE player.gold = player.gold + 1 updtmaptile(player.xpos, player.ypos, FLOOR_TILE) - gotit + gotit break is TORCH_TILE - if player.oil < 1000 + if player.oil < 1000 player:oil = player:oil + TORCH_OIL - if player:oil > 1000 - player:oil = 1000 - fin + if player:oil > 1000 + player:oil = 1000 + fin setmaptile(player.xpos, player.ypos, FLOOR_TILE) for yt = player.ypos - 1 to player.ypos + 1 - for xt = player.xpos - 1 to player.xpos + 1 - setmaptile(xt, yt, getmaptile(xt, yt) & MAP_TILE) - next - next - gotit - fin + for xt = player.xpos - 1 to player.xpos + 1 + setmaptile(xt, yt, getmaptile(xt, yt) & MAP_TILE) + next + next + gotit + fin break is FOOD_TILE - if player.health < 100 or player.energy < 100 + if player.health < 100 or player.energy < 100 player.health = player.health + MANA/2 - if player.health > 100 - player.health = 100 - fin + if player.health > 100 + player.health = 100 + fin player.energy = player.energy + MANA - if player.energy > 100 - player.energy = 100 - fin - updtmaptile(player.xpos, player.ypos, FLOOR_TILE) - player.fov = 1 - gotit - fin + if player.energy > 100 + player.energy = 100 + fin + updtmaptile(player.xpos, player.ypos, FLOOR_TILE) + player.fov = 1 + gotit + fin break wend break From 12f8cf8053de8126d7750c664de49d02a4cf4c5e Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 9 Jan 2020 16:45:17 -0800 Subject: [PATCH 138/149] Tile blitter improvements from Brendan (BluRry) --- src/libsrc/apple/hgrtile.pla | 144 ++++++++++++++++++++++++----------- 1 file changed, 101 insertions(+), 43 deletions(-) diff --git a/src/libsrc/apple/hgrtile.pla b/src/libsrc/apple/hgrtile.pla index f947268..a02cfab 100644 --- a/src/libsrc/apple/hgrtile.pla +++ b/src/libsrc/apple/hgrtile.pla @@ -244,8 +244,10 @@ end // loop //end export asm tileDrawStr(x, y, strptr, strlen, tileset)#0 - DEC ESTKL+1,X ; STRLEN-- - BMI + + LDA ESTKL+0,X ; TILESETPTRL + STA DSTL + LDA ESTKH+0,X ; TILESETPTRH + STA DSTH LDA ESTKL+2,X ; STRPTRL STA TMPL LDA ESTKH+2,X ; STRPTRH @@ -253,17 +255,46 @@ export asm tileDrawStr(x, y, strptr, strlen, tileset)#0 LDY ESTKL+3,X ; Y COORD LDA ESTKL+4,X ; X COORD CLC - ADC ESTKL+1,X ; STRLEN end -asm _tileDrawStr +asm _tileDSa ADC $1000,Y ; SCANBTTML - STA ESTKL+2,X ; USE ESTK AS POINTER + STA $D000 ; SELF MODIFY LOOP + STA $D001 + STA $D002 + STA $D003 + STA $D004 + STA $D005 + STA $D006 + STA $D007 +end +asm _tileDSb LDA $3001 ; DRAWBUFFH ADC $2000,Y ; SCANBTTMH - STA ESTKL+3,X + STA $D008 ; SELF MODIFY LOOP + SEC + SBC #$04 + STA $D009 + SBC #$04 + STA $D00A + SBC #$04 + STA $D00B + SBC #$04 + STA $D00C + SBC #$04 + STA $D00D + SBC #$04 + STA $D00E + SBC #$04 + STA $D00F + LDA ESTKL+1,X ; STRLEN + STX IPY + TAX ; DRAW RIGHT TO LEFT + BEQ + + DEX LDY #$00 --- STY SRCH - LDY ESTKL+1,X ; STRLEN +- STY SRCH + TXA + TAY LDA (TMP),Y ; TILE INDEX * 8 ASL ROL SRCH @@ -271,31 +302,41 @@ asm _tileDrawStr ROL SRCH ASL ROL SRCH -; CLC ; CARRY IS CLEAR FROM ABOVE - ADC ESTKL+0,X ; ADD TO TILESETPTR +; CLC ; CARRY IS CLEAR FROM ABOVE + ADC DSTL ; ADD TO TILESETPTR STA SRCL LDA SRCH - ADC ESTKH+0,X + ADC DSTH STA SRCH LDY #$07 ; DRAW BOTTOM UP - SEC -- LDA (SRC),Y - STA (ESTKL+2,X) - LDA ESTKL+3,X - SBC #$04 - STA ESTKL+3,X - DEY - BNE - +end +asm _tileDSc LDA (SRC),Y - STA (ESTKL+2,X) - DEC ESTKL+2,X ; RESET SCREEN PTR TO NEXT TILE POS - LDA ESTKL+3,X -; CLC -; ADC #$1C - ADC #$1B ; CARRY STILL SET FROM ABOVE - STA ESTKL+3,X - DEC ESTKL+1,X ; STRLEN-- - BPL -- + STA $4000,X + DEY + LDA (SRC),Y + STA $4000,X + DEY + LDA (SRC),Y + STA $4000,X + DEY + LDA (SRC),Y + STA $4000,X + DEY + LDA (SRC),Y + STA $4000,X + DEY + LDA (SRC),Y + STA $4000,X + DEY + LDA (SRC),Y + STA $4000,X + DEY + LDA (SRC),Y + STA $4000,X + DEX + BPL - + LDX IPY + INX INX INX @@ -358,20 +399,37 @@ end // // Assembly fixups // -_tileDraw:1 = @scanbttml -_tileDraw:6 = @drawbuff.1 -_tileDraw:9 = @scanbttmh -_tileXDraw:1 = @scanbttml -_tileXDraw:6 = @drawbuff.1 -_tileXDraw:9 = @scanbttmh -_tileODraw:1 = @scanbttml -_tileODraw:6 = @drawbuff.1 -_tileODraw:9 = @scanbttmh -_tileADraw:1 = @scanbttml -_tileADraw:6 = @drawbuff.1 -_tileADraw:9 = @scanbttmh -_tileDrawStr:1 = @scanbttml -_tileDrawStr:6 = @drawbuff.1 -_tileDrawStr:9 = @scanbttmh +_tileDraw:1 = @scanbttml +_tileDraw:6 = @drawbuff.1 +_tileDraw:9 = @scanbttmh +_tileXDraw:1 = @scanbttml +_tileXDraw:6 = @drawbuff.1 +_tileXDraw:9 = @scanbttmh +_tileODraw:1 = @scanbttml +_tileODraw:6 = @drawbuff.1 +_tileODraw:9 = @scanbttmh +_tileADraw:1 = @scanbttml +_tileADraw:6 = @drawbuff.1 +_tileADraw:9 = @scanbttmh +_tileDSa:1 = @scanbttml +_tileDSa:4 = @_tileDSc.3 +_tileDSa:7 = @_tileDSc.9 +_tileDSa:10 = @_tileDSc.15 +_tileDSa:13 = @_tileDSc.21 +_tileDSa:16 = @_tileDSc.27 +_tileDSa:19 = @_tileDSc.33 +_tileDSa:22 = @_tileDSc.39 +_tileDSa:25 = @_tileDSc.45 +_tileDSa:28 = @_tileDSc.51 +_tileDSb:1 = @drawbuff.1 +_tileDSb:4 = @scanbttmh +_tileDSb:7 = @_tileDSc.4 +_tileDSb:13 = @_tileDSc.10 +_tileDSb:18 = @_tileDSc.16 +_tileDSb:23 = @_tileDSc.22 +_tileDSb:28 = @_tileDSc.28 +_tileDSb:33 = @_tileDSc.34 +_tileDSb:38 = @_tileDSc.40 +_tileDSb:43 = @_tileDSc.46 done From fb3a4964c8f27b353326079b7414d41d0e73e814 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 10 Jan 2020 11:23:25 -0800 Subject: [PATCH 139/149] Match patterns with ending wildcard --- images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes src/libsrc/apple/matchfiles.pla | 14 +++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/images/apple/PLASMA2-SYS.PO b/images/apple/PLASMA2-SYS.PO index f25a27a4ca1c7cb9c6712911de00a154f2892177..189caf9c2174a76536f26e54a5b4157c61a62980 100755 GIT binary patch delta 56 xcmZp8z|ru4V?!1TF9Q%LGdyMx05LX~v#>Dop$IWeW@IXFVrye#T*k(v1pri93S|HQ delta 56 zcmZp8z|ru4V?!1TZ?B4kkTSz#27x*1lKh*?Sy&kPOjVe8;X+K48JWtP*xJ|_m$5Nv F0RXo|4SoOs diff --git a/src/libsrc/apple/matchfiles.pla b/src/libsrc/apple/matchfiles.pla index 98f69e0..69c2afe 100644 --- a/src/libsrc/apple/matchfiles.pla +++ b/src/libsrc/apple/matchfiles.pla @@ -6,17 +6,21 @@ var dirbuf // Match next section of source and expression // def matchNext(src, srcofst, exp, expofst) - if ^src >= srcofst and ^exp >= expofst + if ^exp >= expofst when exp->[expofst] is '*' // Multi-char wildcard - if matchNext(src, srcofst + 1, exp, expofst + 1) + if matchNext(src, srcofst, exp, expofst + 1) // Match zero wild chars + return TRUE + elsif ^src >= srcofst and matchNext(src, srcofst + 1, exp, expofst) // Match more wild chars return TRUE fin - return matchNext(src, srcofst + 1, exp, expofst) is '?' // Single char wildcard - return matchNext(src, srcofst + 1, exp, expofst + 1) + if ^src >= srcofst + return matchNext(src, srcofst + 1, exp, expofst + 1) + fin + return FALSE otherwise // verbatim match - if src->[srcofst] == exp->[expofst] + if ^src >= srcofst and src->[srcofst] == exp->[expofst] return matchNext(src, srcofst + 1, exp, expofst + 1) fin return FALSE From 6b1123a95b025085c129cdc3b5eb77094ed05d1a Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 10 Jan 2020 11:57:39 -0800 Subject: [PATCH 140/149] Update images --- images/apple/PLASMA2-BLD.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2-DEM.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2-FPSOS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2-INET.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes 6 files changed, 0 insertions(+), 0 deletions(-) diff --git a/images/apple/PLASMA2-BLD.PO b/images/apple/PLASMA2-BLD.PO index 2a33e3b19efa589a3192f7a81ecf0f01d5baa373..bb8a2fa03c491b4ff9760c9547416de9d2d45b7a 100644 GIT binary patch delta 28578 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 delta 29781 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 C&n8p= diff --git a/images/apple/PLASMA2-DEM.PO b/images/apple/PLASMA2-DEM.PO index 5d144ce9e5bd1bf8c2171e02f4caf3999c54b4db..b440a679b7fd39d5b66550fd44221065af6aac35 100644 GIT binary patch delta 10763 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 E0}=R(s{jB1 delta 14715 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 diff --git a/images/apple/PLASMA2-INET.PO b/images/apple/PLASMA2-INET.PO index dd75073710d8a2ee95808341bb75518414c8e919..28407c7eef5cc21d32eba6bdf2067ba0c30d29aa 100644 GIT binary patch delta 169 zcmZp8z|ru4V}mmvF9Q%LGdu=S3=ES4_@qog47dn8gGOkGhij0ZYY0dj2>yvNurO4z zfZ1?mljmV-R1I+p32*_c0~7xg7&sVWdC)Yz;gjM63BiqGpUlYgrb(bpfN_}slL7$J CwHbZ@ delta 169 zcmZp8z|ru4V}mmv?;LeWer1No3=AN~_$S7|!cfTq yR*%p)4^yLRh+9a23se`7`lrCa!4S)XrtuA*6d$UMlNp)bGzqi`FfJ2dQUCy(izI>o diff --git a/images/apple/PLASMA2-SYS.PO b/images/apple/PLASMA2-SYS.PO index 189caf9c2174a76536f26e54a5b4157c61a62980..bc5c36f2e383d29472e883a82671a4b118eaf066 100755 GIT binary patch delta 17572 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 RQ^ZQ2h_^1pgM30h_Fn}=gE;^I diff --git a/images/apple/PLASMA2.2mg b/images/apple/PLASMA2.2mg index 214c4397b046bdaec9432b1d21224224e50d4736..12cf78e8175ea1ac8aa891d6196dec925ec92c3c 100644 GIT binary patch delta 54045 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 delta 18544 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 V@ODplyC=Ne6W-ht?%uJI`G3t4>`wpy From 1f42523014758b9ef1f68ecf2555c0581763b90f Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Fri, 10 Jan 2020 13:55:05 -0800 Subject: [PATCH 141/149] Fix some Apple /// differences --- src/inc/fileio.plh | 2 +- src/libsrc/apple/fileio.pla | 2 +- src/utilsrc/apple/cat.pla | 4 ++-- src/utilsrc/apple/copy.pla | 2 +- src/utilsrc/apple/del.pla | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/inc/fileio.plh b/src/inc/fileio.plh index 04c8cc6..4226cf1 100644 --- a/src/inc/fileio.plh +++ b/src/inc/fileio.plh @@ -33,7 +33,7 @@ import fileio byte entry_minver byte entry_access word entry_aux - word entry_mod + word entry_mod[2] word entry_headptr end // diff --git a/src/libsrc/apple/fileio.pla b/src/libsrc/apple/fileio.pla index 9851bd9..0020808 100644 --- a/src/libsrc/apple/fileio.pla +++ b/src/libsrc/apple/fileio.pla @@ -298,7 +298,7 @@ def a3write(refnum, buff, len) params:2 = buff params:4 = len perr = syscall($CB, @params) - return perr + return perr ?? 0 :: len end def a1create(path, type, aux) return perr diff --git a/src/utilsrc/apple/cat.pla b/src/utilsrc/apple/cat.pla index 68f3860..e7f131e 100644 --- a/src/utilsrc/apple/cat.pla +++ b/src/utilsrc/apple/cat.pla @@ -162,9 +162,9 @@ if not except(exit) if ^arg struprcpy(@path, arg) // - // Check if cataloging a directory + // Check if cataloging a directory or volume // - if fileio:getfileinfo(@path, @fileinfo) <> FILE_ERR_OK or fileinfo.file_type <> $0F + if fileio:getfileinfo(@path, @fileinfo) <> FILE_ERR_OK or (fileinfo.storage_type & $0D <> $0D) filefrompath(@wildname, @path) fin path = path - wildname diff --git a/src/utilsrc/apple/copy.pla b/src/utilsrc/apple/copy.pla index 1985a32..8bab308 100644 --- a/src/utilsrc/apple/copy.pla +++ b/src/utilsrc/apple/copy.pla @@ -252,7 +252,7 @@ if not except(exit) srcfileptr = srcfilelist while srccnt dstlen = dstpath - if fileio:getfileinfo(srcfileptr, @srcfileinfo) == FILE_ERR_OK and srcfileinfo.file_type == $0F + if fileio:getfileinfo(srcfileptr, @srcfileinfo) == FILE_ERR_OK and (srcfileinfo.storage_type & $0D == $0D) if recurse // // Copy directory diff --git a/src/utilsrc/apple/del.pla b/src/utilsrc/apple/del.pla index 5501609..3129ed4 100644 --- a/src/utilsrc/apple/del.pla +++ b/src/utilsrc/apple/del.pla @@ -152,7 +152,7 @@ if not except(exit) // // Delete files in list // - if recurse and fileio:getfileinfo(fileptr, @fileinfo) == FILE_ERR_OK and fileinfo.file_type == $0F + if recurse and fileio:getfileinfo(fileptr, @fileinfo) == FILE_ERR_OK and (fileinfo.storage_type & $0D == $0D) strcpy(@path,fileptr) strcat(@path, "/") delfiles(@path) From ea3c73ac15a402d04a550f2649a9e2747590db19 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 10 Jan 2020 17:25:32 -0800 Subject: [PATCH 142/149] 2.0 DP3 release --- README.md | 4 ++-- doc/Version 2.0.md | 21 +++++++++++++++++++-- images/apple/PLASMA2-BLD.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2-FPSOS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2-INET.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes src/toolsrc/plasm.pla | 2 +- src/utilsrc/tftpd.pla | 2 +- src/vmsrc/apple/a1cmd.pla | 2 +- src/vmsrc/apple/cmd.pla | 2 +- src/vmsrc/apple/cmdjit.pla | 2 +- src/vmsrc/apple/sossys.pla | 2 +- src/vmsrc/apple/sossysjit.pla | 2 +- 14 files changed, 28 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 0b38ebf..fae17ef 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# 12/28/2019 PLASMA 2.0 Developer Preview 2 Available! +# 11/10/2020 PLASMA 2.0 Developer Preview 3 Available! [Download and read the Release Notes](https://github.com/dschmenk/PLASMA/releases) -[Change List](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md#changes-in-plasma-for-20-dp-2) +[Change List](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md#changes-in-plasma-for-20-dp-3) # 4/29/2018 PLASMA 1.2 Available! [Download and read the Release Notes](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%201.2.md) diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index aadf654..240fc7e 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -1,4 +1,4 @@ -# PLASMA Version 2.0 Developer Preview 2 +# PLASMA Version 2.0 Developer Preview 3 Welcome to PLASMA: the Grand Unifying Platform for the Apple 1, ][, and ///. @@ -75,6 +75,15 @@ PLASMA comes with many library modules used by the tools, demos and sample code. ``` +ED [TEXT FILE] ``` +The file manipulation utilities to copy, delete, rename, create directories, and change file type and aux type remove the need for external programs to do the same. PLASMA can now be installed with the tools included on the PLASMA2-SYS boot floppy. They are: +``` ++COPY [-R] + ++DEL [-R] ++REN ++NEWDIR ++TYPE [NEWTYPE [NEWAUX]] +``` +The ```-R``` option will operate on the directories recursively. Wildcard filenames can be specified with ```'*'``` matching zero or more characters, and ```'?'``` matching any character. ## Compiler Modules @@ -86,7 +95,7 @@ Compiler warnings are enabled with `-W`. The optional optimizer is enabled with ## Demos -There are some demo programs included for your perusal. Check out `ROGUE` for some diversion. You can find the documentation here: https://github.com/dschmenk/PLASMA/blob/master/doc/Rogue%20Instructions.md. A music sequencer to play through a MockingBoard if it is detected, or the built-in speaker if not. A minimal Web server if you have an Uthernet2 card (required). Bug reports appreciated. +There are some demo programs included for your perusal. Check out `ROGUE` for some diversion. You can find the documentation here: https://github.com/dschmenk/PLASMA/blob/master/doc/Rogue%20Instructions.md. A music sequencer to play through a MockingBoard if it is detected, or the built-in speaker if not. A minimal Web server if you have an Uthernet2 card (required). Try `SPIDERS`for some hires shoot'em-up action. Bug reports appreciated. ## Source Code @@ -106,6 +115,14 @@ There is a [YouTube playlist](https://www.youtube.com/playlist?list=PLlPKgUMQbJ7 - The documentation is sparse and incomplete. Yep, could use your help... +# Changes in PLASMA for 2.0 DP 3 + +1. File manipulation utilities fixed for Apple /// SOS vs ProDOS differences + +2. More optimizations for HiRes graphics libraries + +3. Spiders From Mars hires demo game + # Changes in PLASMA for 2.0 DP 2 1. Many file manipulaition utilities (COPY, REName, NEWDIRectory, DELete, CATalog, TYPE) diff --git a/images/apple/PLASMA2-BLD.PO b/images/apple/PLASMA2-BLD.PO index bb8a2fa03c491b4ff9760c9547416de9d2d45b7a..2b2513d17c793bc26a313a498d484b79489e98d9 100644 GIT binary patch delta 57 zcmZp8z|ru4V}mmbua<_9fHK2l1_lsgasZ1Xs>tSfEPtLd8aK~=wSD$0##C1T%t#Tx delta 57 ycmZp8z|ru4V}mmbF9Q%LGdu=S3=ES4SR7GBHqT@E^OVu3dG@RAvtKc$x&i=!whwLq diff --git a/images/apple/PLASMA2-FPSOS.PO b/images/apple/PLASMA2-FPSOS.PO index 4f48e743a4f7ec2d13c351c16c85d3a26463b978..372aff47937394e53d263e5f6c313f75d396414c 100644 GIT binary patch delta 178 zcmZp8z|ru4V}mmbua<_PfHK2l1_lsgasZ1Inn*c|qX~){CI+ow|6n~&zYy1;00t0X z&0*kW_#*~30b$e|7AdS6yOV delta 49 zcmZp8z|ru4V}lP1%N%tp{>=d_{am~ZK%mU<7(_8JY<|O+ZMivo!b;XAzh!=mj{s-J B4%7eu diff --git a/images/apple/PLASMA2-SYS.PO b/images/apple/PLASMA2-SYS.PO index bc5c36f2e383d29472e883a82671a4b118eaf066..dc0b9652fb2b5bab5cdc78891b9fdaf6989206ef 100755 GIT binary patch delta 1607 zcmZXUYiv|S7>4JYbM~;??Pc1t3l`hj%l2$3_ZGQWuB8;Et!cF-@kSugrl|%nfW;MQ zCm=#8t-~7ThtU|Lwc%1qE4x@wFlG}H3@Sk(At8upinR&~iWsPG8=?hI^5lKyn{Q`N zW@fkPg1hO0yQ|zZ^YbQ&aHTmmAwO?|$YI|zF(lyzbHTqAHe8AQuVTCI?OEX(n|Rkc zJWRZy+dAkLSL3kEq~UKEmY!H*9*MP{d#bmRmL*eR&(m2qx)C*}_ax8*J#=x7MZxgA zzAXAUyrS<>Dh+q_1u3KFY@bPiII7zy*3S|31;RNg>P@z^X|IRXof5MX#?CMQg4N9y z$*f3w(YrI+zt0eYce#DcL!EQ(9p&UIUuJ5fB6Cz$I`SSU$!BpbXT2RbW5p2iJk^XFT1n2OlFxpLgg= zW0k?wCc`VYAP*uB8BBf#KMg+vzX1OeeiP13rqWHX%tV$T7n@90!Rz49BX^iy)d4?- z`Xz7`wRo3TCb^hQbul#!J_9-1MY067#V)3w$fF9+CJeTKZF+wmZHbq^!LNfGXi(qL zeY#>C?QYMfWz-p^tu#p9TgK4A4~S80iuN|s#b|#s+0@=b+%;1yuO84wE4^ZMB-iqp zLA|+^%BWa>)k>vSB&D_lrL;E6qEGeQHY&}3kU29%{ZvuyBtx9&@O|sVbvrzC-HOY- z%xMsqsa~!3woyJs^qDrwZ5$AcJIRc%1|6U{h4DxVQy$_f8@x{`s*_B-KUcqko5UsO zOvQ0irErhR<_pyn&Q%e{bGe}&MwTJhaZ_$YUkkTX8}~~Me~V|xBgmsXAiv~Hp5m-g zUFNpB%6*CqOPPjW#^b1jks(JT#~Vp%nvp1Hz#lTw)qEpUEi|%ZDUR_GPzjy_&tkqF zpIr-YfQQiYD!d824w}IZ@CFEDewX3Mx8WZeib^lf>RJtbUqs*8lhCw_)fu z>Kb&=zG$0=FQ-{gVpE^NW-d4EJ16OrD^Yt9+&NJhf=jR&Yz5oVzgy>d`L~gHzBM&2 TSk2hV$7?I{gVCM2d}Z7}m%g9X delta 1583 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 X2kL8fjJk4wTp$m~H%DCs{g?b77txc; delta 5515 zcmZu#4RBP&9p8Ps@8yypJaR_@34}m$m#;Ixff~@zyX5YYz~#f-1w==5P!Z9lqZPqZ z3C|B8B;Y**E(qF*PC;!(+8)D0i-S|Dj@9~+>GTV|wmNOGU_+g;)v+G^zjv2+cl+*U zez*VIx4-|_{&(N*y|Kgd#tzRDbv`e0p;@expUTbDm2r@o~Tp%8sB-T09)Hz`)9l$T1nu(TxJBCVf;J@F&+ zFWr-R5*w**)a?h6vp3`mcV(0&KS7Jp?Khh$4Pi7f!nqk2_io3W=dpd9!|iBJsIxl| zZt4wnq%6=7!ic40Gp^A@9%8UJ9O=s-$(qeHo7>s0ii1q=on;qsNR5*vb@p+IL(#^U`*MB@@ibiZn`SRU^7 zhXdDVh!29Rvw2seuUZmqRW;k!*Pc}*i0%MYOAQw?)jv9ECDsOe`%MR6JbetD|DwQP zn&lO5dF}os@e>zDXuRdp{7OFM6{~vIwf5h5w;5y+m& ztff%gTn1PIn8peL(pK`$n;0y#1;%bvk z=3&n12!ujzSdj=Pv$s(gCYgp;3&PacEz#N!-7PMW;&Y=jT4oso1_k{V=g4wpF=+h7gfmD-@qFp|H7@bBisPvl`bjY2kwDETJ{{~gLD z&V8HJX0<;M%J3j@Gbu%9 z!(r?+&H)*2a)Ch687>B`<#s|Ui!Y199SF6_i;#z{ew0*R5wf4QpR<2w4>>M69NGhq zlIfzhcNf`$@kU05NHsLILu6=gb+Xh!~v%P6M%DouK?cxDjY~?1%v<_0Y?F! z0xklIW+B0Ga+s9i!487dC@EGRfp#3);{++EKzmM3?SQVj zrO0)Sym^TnshJ6aOEZ?+E3n#5$(604V&vK?Lw{s|T@q;nKEWy^>KwcvBcWy{5(WTA z0p1cMoG3wR0T$FM!1K679miDtGss^6zQ%%r1f<#os>(v4S|zlpO@g2q3q48v!XF3TROMhhSGH1&4YW1`1@BQUo(I zom46gXzR%g)kCH$SApD2=BX=5mFgo46hF*hJD?k|4zK~9ZvyUpAa4PA8;p4fq&YI6yC%IN&7UGz>fg1Ahhb+aUiMSC&SZFH`e-;C?}BOQT0IAW)lWU?04{x6v57U*pNEjpaujJjZ{oToJe_G2b zN<6IfVR|0_M{9h9&caZ9ns+;0TO{1^fOcp%J$nm39ZutZWhzF=K|w@=+yR)y&RbJc zn?Afwag+04i~osbI)HhVKE%uxZ00w1_D-?%Hd#XnD&wYOnE9?0E{|3&=B{?u`JN@4Qv;MzRiwMo;V(uOJ5S{lTlX&_Y~u?8`dQlsmD zPzER5b#R$74UB`gKjyqWaLjiv#iQQg4Vup_wyrSs8Y~vu$Y&ugxZqCMZmw0Bs$amG zd&4rxd65E!IcA*s?xt^Q z-c4fLGCqzYB6nYUe=6|Zn)f-e&0`YM3H^{KoX;Xmh;0KVA)P6&#O+R1#1#sx34|6K z1N1Mth!C`bpW*~CbC*LEarX7J_XkWO>@lPeeK5o5Fjq|#^W7q)mqV*Gx100mt{D7N zqcd16CUMd4&kE)#$$DdankTGI+42tWW&VTG_c&9rgA!lz+Ck%gB2NiRz{A`vCPW(G zQqcr^cc8D=h)Mi8xdQ#KG&erxKE!7x&0MX&EmDWcX`c}{LThrFA>CW3gl8l-{6(dG zKQ5Kl^DckPdo@5Tmx8S%&!r%dhuIJa1-ioKE{>#KWF|sYrdO$=a(}|dGe9gafFs2E z0vJfglaSOS5YI%kVBiIgCrN{Lyvn9xZRJAS76C3v zCu(d#{3ZKVZ=PbUPTTVG9<;eh9-oCaFOyx{GMA$V6;;M_Ig SvjGYLMSx;$!Z&ST<^KU9UGzQx diff --git a/src/toolsrc/plasm.pla b/src/toolsrc/plasm.pla index d8feba6..385b197 100755 --- a/src/toolsrc/plasm.pla +++ b/src/toolsrc/plasm.pla @@ -507,7 +507,7 @@ include "toolsrc/parse.pla" // // Look at command line arguments and compile module // -puts("PLASMA Compiler, Version 2.0 DP2\n") +puts("PLASMA Compiler, Version 2.0 DP3\n") arg = argNext(argFirst) if ^arg and ^(arg + 1) == '-' opt = arg + 2 diff --git a/src/utilsrc/tftpd.pla b/src/utilsrc/tftpd.pla index 90a63a4..a4a9c6d 100644 --- a/src/utilsrc/tftpd.pla +++ b/src/utilsrc/tftpd.pla @@ -369,7 +369,7 @@ def volumes#0 next end -puts("TFTP Server Version 2.0 Dev\n") +puts("TFTP Server Version 2.0 DP3\n") if !iNet:initIP() return -1 fin diff --git a/src/vmsrc/apple/a1cmd.pla b/src/vmsrc/apple/a1cmd.pla index 0feef38..5fc97b9 100755 --- a/src/vmsrc/apple/a1cmd.pla +++ b/src/vmsrc/apple/a1cmd.pla @@ -52,7 +52,7 @@ byte perr, refauto // String pool. // byte autorun[] = "AUTORUN" -byte verstr[] = "\nPLASMA DP2" +byte verstr[] = "\nPLASMA DP3" byte freestr[] = "MEM FREE:$" byte errorstr[] = "ERR:$" byte prompt[] = "PLASMA" diff --git a/src/vmsrc/apple/cmd.pla b/src/vmsrc/apple/cmd.pla index 45c50f0..13d0499 100755 --- a/src/vmsrc/apple/cmd.pla +++ b/src/vmsrc/apple/cmd.pla @@ -1383,7 +1383,7 @@ heap = @lastdef // // Print PLASMA version // -prstr("PLASMA 2.0 DP2 64K\n")//; prbyte(version.1); cout('.'); prbyte(version.0); crout +prstr("PLASMA 2.0 DP3 64K\n")//; prbyte(version.1); cout('.'); prbyte(version.0); crout // // Init symbol table. // diff --git a/src/vmsrc/apple/cmdjit.pla b/src/vmsrc/apple/cmdjit.pla index 6f40545..6545556 100755 --- a/src/vmsrc/apple/cmdjit.pla +++ b/src/vmsrc/apple/cmdjit.pla @@ -1460,7 +1460,7 @@ heap = @lastdef // // Print PLASMA version // -prstr("PLASMA 2.0 DP2 128K\n")//; prbyte(version.1); cout('.'); prbyte(version.0); crout +prstr("PLASMA 2.0 DP3 128K\n")//; prbyte(version.1); cout('.'); prbyte(version.0); crout // // Init symbol table. // diff --git a/src/vmsrc/apple/sossys.pla b/src/vmsrc/apple/sossys.pla index 30b0bf2..7a4250e 100755 --- a/src/vmsrc/apple/sossys.pla +++ b/src/vmsrc/apple/sossys.pla @@ -1263,7 +1263,7 @@ cmdlnptr = @cmdln // Print PLASMA version // init_cons -prstr("PLASMA 2.0 DP2\n")//; putb(version.1); putc('.'); putb(version.0); putln +prstr("PLASMA 2.0 DP3\n")//; putb(version.1); putc('.'); putb(version.0); putln prstr("MEM:$"); prword(availheap); crout // // Exec command line parser diff --git a/src/vmsrc/apple/sossysjit.pla b/src/vmsrc/apple/sossysjit.pla index 58d10c9..e2cdbe8 100755 --- a/src/vmsrc/apple/sossysjit.pla +++ b/src/vmsrc/apple/sossysjit.pla @@ -1286,7 +1286,7 @@ cmdlnptr = @cmdln // Print PLASMA version // init_cons -prstr("PLASMA 2.0 DP2 JITC\n")//; putb(version.1); putc('.'); putb(version.0); putln +prstr("PLASMA 2.0 DP3 JITC\n")//; putb(version.1); putc('.'); putb(version.0); putln prstr("MEM:$"); prword(availheap); crout // // Exec command line parser From 5c8fbfdcf4cc2605926b1dd30bcfe91be9e6de7c Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 10 Jan 2020 17:59:27 -0800 Subject: [PATCH 143/149] Forgot to update editor version --- images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes src/toolsrc/ed.pla | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/images/apple/PLASMA2-SYS.PO b/images/apple/PLASMA2-SYS.PO index dc0b9652fb2b5bab5cdc78891b9fdaf6989206ef..d2f04262587b4ae83b1d62f07e2e6eb509d68874 100755 GIT binary patch delta 137 zcmZp8z|ru4V}mLSBgbSl77ZpV!N~zEnv4vSt5_6Rv^1;)H_v0KWM``Xu$htRCF5o$ zzJH?2!Wfw(ghWKe#3dx9q-9pGS-WoihK-vxZ`rzS`wpP87mUlI7=<=jCBG68W{_m? n)Mo&hqs;J_0nFH5uEN-9xGjhAB?qJN_E#m0V#3Rc8214HBRDFE delta 3780 zcmZWsO^+N$8Q$3}u{l)aSV=Z^0;wH4o?Y+E*bc;&7pX{uU5kCPW zkPrx^bLD~rec*<&f!zcfh{=XH5C~r<5C|dh10r!DaL*C(yw%+^Yna1s&)Ze+$MZh# z$GrOC=~q8Ieec<|&L^u&Yn!XXGgZE})#+8=SmSG-zc_s4`1@;LKXrU&_1~T2)kpsG z_)EO~%%qM?D!Dg2*TSWOzx?6`V~MiPb3akp*zxdXhcV9Qrr^R#t}?un?F}cgcx3ju zjFmTbSmm#EKg~@z!bF~H37tDU@>UP__%1KjU@&400=-!xgqTNA&UjQpr{gAp(`IZ%iX|ZbVk{Z-%5*b@=~SHVI`y;a^zBn)(=#MM=@NDx9Ne;Zo> zWD&Cqbr-CV5%{Nw%U~w}V551sSBBUE|0C1_WPlj_Rlo=50~gwq!Xq0u_CntAmE4Vu zW4+N__FCUTf+7PFmQMirNWyz7!I`MG8<3;&<64!OT%K-2h256x9>6BSCg}2jTEP=J zV@{>iEdU-VbfM);QTSS+5KT7F3I?V|7pZh8!W^%N3IHKd`w)~7B$4n!n=!uL!na!m zDu2_;kuiP?vH@fSd_%$}KVY@iW)?cbpoe4I&9TOFbd~~+ojA4KV-1`qz$pXSMoKG> zgrK9MY*;Q(iO7<5BoZyGfPv^qDHf=eKJ)XO>~{xkI|aGpVJf?PW(w50ms$rVwrIw( z&%4dxZl9EwbR{q$0hL*Ip#e028B|mbv$F|ONRW~_s?G*6Y8-;c%E}0Bd=6$qi9;RO zJ)}C6NpFC*iN5+EdaloV+w`K8ZK|~qu|U7zHF7vX4C!47*I8==y$Bs7_(RAo7y)+F z1Bld6eJjtjF?)4u0$1P|@~kz=QxtHv$PkxGN`_>k*E69lsjDuZV*4zQyMnq%F}8N@`YauG_b+#ZLNXeXft1C_80 z8gD(S#ytc)i6McsSn-1i+YW z%PXL`#ag!URuP)TR)7cG!?h5zm;1gsFZYL+hwy80Uha!fwayfmZA6$O(k<31W`p`e zQ;q5XA>aBs93_Z;id2XzC{Igf#Ch8nZ1eq4vPfRhMFbZzbOc4w6aN{PW z!lK(!iD{FKhoLe#rY$wAnL^#*85Pba#;V&ULxaF{5LZx<@F*%Q1_78l1szF33y$O0 zuJ55DSSnK#L#Wki{qV*r=T&ydt1lgHRNp!5R_`1>Q~e#!ALIWMM;q1Z!FpwmK2a4% zpQ^rcbiVrb(bLskJpb|NsVaHv>?CYB`*rGeF}JW9fcS_C@HG3+w0#?yeBK3%fReye?zmE0EfX4xt<$F~<`sT%lv2ci7R)2f*nG&zssf|`Eu=L2fzjE#-D)EC9 zR(JW!OBETpvCCgvO7dFr#ie9aOTM|3%xlRjONk~)_17QmRHyE2RG02tsK$5r!vTk= z`tluKQssudX(DK6LJDWn4kD}s%ftqCW0^@SQ0{ftr1I}C7A`c?s0Q)GebgDKI!ALb zl-HSZXtd-Hct)e1Y;*%bFq@mh=qZ`8X`l!l9TmRn-Mvsv?tXz#tXbR(TS7btnD+Rd zoYy=tXl>95t z?}g$5H0V06(0<6F%oWiDLjxVpqRBSxY&*tm$GF1YG?g|%qJb!N*`buVEZ$)m>2qxRK)!JgL7>@SUsnzVf(uyU04FVT7BdjQBQes_e%r3kwAJOp z(^3Y&UEK>Ce_h-BnjSb{tfY|^kY3E{|G5LEFk@kbn%fxb4edr!w;+MExdLt9{b na5D3?Tt=gIt&7Y+%mT!$K+Fcj>_E%`#GF9PwO#8Xx7d0B%)u?E diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index f4b4738..e128773 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -1609,7 +1609,7 @@ def cmdmode#0 word cmdptr, line clrscrn - puts("PLASMA Editor, Version 2.0 DP2\n") + puts("PLASMA Editor, Version 2.0 DP3\n") while not exit puts(@filename) cmdptr = gets($BA) From c83ed2c494e07d75879de959cade2611585bcb0b Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Fri, 10 Jan 2020 18:50:54 -0800 Subject: [PATCH 144/149] Fix another SOS-ism --- src/utilsrc/apple/copy.pla | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utilsrc/apple/copy.pla b/src/utilsrc/apple/copy.pla index 8bab308..d6d9c6a 100644 --- a/src/utilsrc/apple/copy.pla +++ b/src/utilsrc/apple/copy.pla @@ -89,7 +89,7 @@ def chkdstpath(dstfile) // // Check if copying into a directory // - if dstfileinfo.file_type == $0F + if dstfileinfo.storage_type & $0D == $0D if dstfile->[^dstfile] <> '/' // // Add path seperator @@ -114,7 +114,7 @@ def copyfiles(srcfile, dstfile)#0 // strcpy(@srcpath, srcfile) wildname = 0 - if fileio:getfileinfo(@srcpath, @srcfileinfo) <> FILE_ERR_OK or srcfileinfo.file_type <> $0F + if fileio:getfileinfo(@srcpath, @srcfileinfo) <> FILE_ERR_OK or (srcfileinfo.storage_type & $0D <> $0D) filefrompath(@wildname, @srcpath) srcpath = srcpath - wildname fin From c8015091a54546adbae5464cf9efc9a9fea9e586 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 10 Jan 2020 18:54:28 -0800 Subject: [PATCH 145/149] Update SOS fix in images --- images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/images/apple/PLASMA2-SYS.PO b/images/apple/PLASMA2-SYS.PO index d2f04262587b4ae83b1d62f07e2e6eb509d68874..9a1f3bc42ab21bd21e929d34ced89dd12c4ce82e 100755 GIT binary patch delta 931 zcmW;HeQ3>59LMqVJLmj<_ip3v?nz9$wx4mAD7CG5*dL_!4=qAbYHHDygyt!=?vA46 z59?TrD3K;2+9k$nMmJkF)3~*w*f0!vXp35z_uP8*{d^yOr*6aBV8h$st!gdHvlDCe zlR$dr4XB&{Ngz+6UB0Nvp*6Eris|V)U3H`q{}Hu1V4_+OQVfCRvBJ% zy3OfxN?M+^IWbB_!imNg%N(;*3R@|Cvq}oHj$9+>+nrL|{WvCb>M|^AlrIncwsiGGZoqCrt^PrL>trouz#1qZAvIwwtj5=OBdQby2#XNVGf`kjj-%nbe_3LzD&Nt%{B53 z+@^2mu?})49wCVy^s?*cc7UA1YrMfQKCt`5?n|8JC(SsI{2@<}|LPngU12<=VHz@# z?eeeOA~Tab8$RY?A+)uxub-PLx7tL$#qHwW3*;|TMkZrC(Zo7{YJiW)!T zhRiuaHy`$Kl)@lhVF>T>5u@CEDxSI?(lI3I`J4i=tVyUkisC|U>GC# qjPJbh%geO00@@Y?eDOT>vbQ>{rt12z7Tw9NyPLGU?6e+o?)?K$iVPV5 delta 143 zcmV;A0C4|+;0S==2(V5B0y+`1Pz1*Z0)Ozc0Rrg(lL8L25b+8CDkv@xBLL$704gXh z5VOS&JJSmv2LfdP0PGM408z6G;`9LrCUJ9g*#QER0RsM(Cj$KjXxh>Vx9VO2789n30jSr8FQ5Pb diff --git a/images/apple/PLASMA2.2mg b/images/apple/PLASMA2.2mg index c22f563c01e21bfb3f06be17f87fbd74ed7c344d..c9106af32d71247025ce4976d731afbd6acf78c2 100644 GIT binary patch delta 1025 zcmYMve@N7K9LMp`_w(a>XZ||9yDZC_ezPgj*kS%?*&ipvhy~GT`y&X9#4utM#Bz*| z^RqFF!4{vSefJAOh{;A#)W#7M>4u=pu%rW_AZnY{Dyoqb#ju#6S?n4a7xcgEj z+*jOv&+Z4AuzBhz_v6%i+&sc#sq7Q_=Q3sId8bGTSE00BNL{P~7ho0MQ`&98R;6s0 z5;@ncQf?=U&lw)VVHQXD=o{uonU63V!#MNbnNO*dEhu4U$X8WhXQ_9&^R;%xDAUST zXyKAN~6EWo1=L|Gsh!O$$;fa2jyYsot=0mbJX_W%F@ delta 2579 zcmZWrO>Y}T7*4WH?G#3$&=Lv-rs=^+6T4|>6Qxxpk9WuRG_yOKnc3Jb;umn^4{R$W zDscd$3a!KiRUCQ*sfS+s3y^x^2Ox1lNFZ_G2G2X*bz5O+t=)HL-jC;fo_F@yy}f7m z_I~<)b>;BvlSiwMPOp@IKD^JreE9tJgD0!(*7>Uc+47p3NFAG0a&LI9g-Zqh z4V87C`?1PKj)#YvjB!3Q1s7IwmEoOib~uqG12g3^QQp{I_03AO@c}ns4HJ2;C7j;m zvA4Q=#BcK=->H6CiS};=%LJA?MViBm2*Gr>F(qb_HAc}GwH$g@8Ms7eNx6(Q6VT-i{M`k97A%3{em)mFGI(Po<^>;2*VsGW2(l1=4=0pNBQ)I~w z*V1U)6iO%I z4R&zBGdbaL37?LeA@VjOD^fIrQN!lVP>MSsAj1mamKOlT_1J;{+zzr?3 zQ6WZ>!LLjQTH5fkX)ZQ5yOrZkm8sIg5=~;0#WDw#40WSsLoQq_G#kH@i>4TN@x;#DG$Kuclb~^{L3MN zmJ01+6okBqm?=cUK?5=L02?3%g%$9@`oM*zrO3!8b-d7bJW{%eajY|#$xf3yNKj-z!tya7 zA4p_xB{&n$;|AnNf?TUIlP^{`r6O*_bq`>NAtvbZid(^la>ATSX=(sGa_GYBIf4GQ zf)-8I)d~Slj4o2?pu-%mhzbBeFm4vg_zuytW0;A;}r z{Q;}BHj^+Nx*aUru9wxBW4aVb?4?!P9ah8n5;$cb+dygM(GZMQ$cE(tN<^2eBa>)g z1q?(_YO#P;c9@^#6n~@J%vF#(>7{amPfP)=d#QC`VuNNPclbuVcw>j0m$W4?VF)U- zjfDr$0AZl09APJ8w2&aBaHP%}F&Z3#C(6ng^Lz$o!-<0q>=9ZWWYXzkbYix?ik{oy zoo#wi%BI!Yh(uss@Hui=K@90!4cl201G5MdB;-TLEf@iI%ugb6L;6;pX=9G&qX}F= zV(7Ehkf$h+Y>}ZZH7psLjd|}p0+Pqt3(=-NyTVrGSU?IkN-NA%a2pa;neu8rc8G#K zwm3y_$iZdE48Z|*JjQUG4|4`Hk*Zvjk|=k?VI|s0xWUOvSO&SnOt0DP|NWY2+N<&1 ztXqAOLK7D4ZV=jHahmY(Yu1oxN~$J^q~`S&tKs2%GY|l$Z6mLM;udSz#v4Z%7Fz)x za1Yx;&0bD@yV?I)C5>s5je0?v9LFt9 ztBHbea1V*|v9ao|$uJ>sJcz51BvOhCi<1CUJpmudLZ3R0U)w)|Bv>j_s3C~8nzW*W z70#=#S`n{)Y(Wj0{o2~HWGv%N6cOUe3m!I}`SN{F&+;_{ZrN7QBUD@1z!;abIY8dnQf8`m1HGq_%R+~0rw&VP`Fl&Js! From 1aee6c45231e8cbca1ec14024c6dfb74f7982fce Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 10 Jan 2020 22:30:36 -0800 Subject: [PATCH 146/149] Update Version 2.0.md --- doc/Version 2.0.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index 240fc7e..791d94a 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -82,6 +82,7 @@ The file manipulation utilities to copy, delete, rename, create directories, and +REN +NEWDIR +TYPE [NEWTYPE [NEWAUX]] ++CAT [-R] Date: Fri, 10 Jan 2020 22:33:45 -0800 Subject: [PATCH 147/149] Update Version 2.0.md --- doc/Version 2.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index 791d94a..90a5acd 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -12,7 +12,7 @@ Download the four disk images (three if you don't plan to boot an Apple ///): [PLASMA 2.0 DP Demos](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-DEM.PO?raw=true) -[PLASMA 2.0 TCP/IP modules](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-INET.PO?raw=true) +[PLASMA 2.0 DP TCP/IP network modules](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-INET.PO?raw=true) [PLASMA 2.0 DP Apple /// SOS Boot and SANE floating point modules](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-FPSOS.PO?raw=true) From 05f5729adcd324e50d334f59dd93052ba0093224 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 10 Jan 2020 22:34:47 -0800 Subject: [PATCH 148/149] Update Version 2.0.md --- doc/Version 2.0.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index 90a5acd..7894a0c 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -2,19 +2,19 @@ Welcome to PLASMA: the Grand Unifying Platform for the Apple 1, ][, and ///. -Download the four disk images (three if you don't plan to boot an Apple ///): +Download the five disk images: -[PLASMA 2.0 DP 800K Full System](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2.2mg?raw=true) +[PLASMA 2.0 DP3 800K Full System](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2.2mg?raw=true) -[PLASMA 2.0 DP System and ProDOS Boot](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-SYS.PO?raw=true) +[PLASMA 2.0 DP3 System and ProDOS Boot](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-SYS.PO?raw=true) -[PLASMA 2.0 DP Build Tools](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-BLD.PO?raw=true) +[PLASMA 2.0 D3P Build Tools](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-BLD.PO?raw=true) -[PLASMA 2.0 DP Demos](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-DEM.PO?raw=true) +[PLASMA 2.0 DP3 Demos](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-DEM.PO?raw=true) -[PLASMA 2.0 DP TCP/IP network modules](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-INET.PO?raw=true) +[PLASMA 2.0 DP3 TCP/IP network modules](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-INET.PO?raw=true) -[PLASMA 2.0 DP Apple /// SOS Boot and SANE floating point modules](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-FPSOS.PO?raw=true) +[PLASMA 2.0 DP3 Apple /// SOS Boot and SANE floating point modules](https://github.com/dschmenk/PLASMA/blob/master/images/apple/PLASMA2-FPSOS.PO?raw=true) PLASMA can be run from floppies, System in Drive 1, and Build or Demos in Drive 2. Mass storage is the recommended installation that looks like (replacing HARDISK with your volume name of choice): From 348bc4eaf506214fa482d9a7693cab009d79d5c1 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 11 Jan 2020 12:27:41 -0800 Subject: [PATCH 149/149] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fae17ef..d32c782 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 11/10/2020 PLASMA 2.0 Developer Preview 3 Available! +# 1/10/2020 PLASMA 2.0 Developer Preview 3 Available! [Download and read the Release Notes](https://github.com/dschmenk/PLASMA/releases) [Change List](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md#changes-in-plasma-for-20-dp-3)

m_5!5q|L2^y(?BABDMAVpt0YaKXVIYhP;)$liWgXMH}A4Uc7@2 zypNA?6vuG_U*I&(g%aZS5WZ!jAK2(evWK*=xY-zlFihm56eBPi6&Mp1JuaN%P9od5 z7t>j*XKguo1y)02BR2EyIo>@_Zocv-lD{ z$cl;^goP4Z6BRu?n&XZnm!kr=VgjaM8fIWN=0*Aa=M(;j2k;=4Vi{aKid9JBAJ~Ci zc#T6|=a9F_@8SRs;Uk>FS#;wo^x`}&!pIeO0CEsTQ7*rK31KL%!wB4fTQDY9^n_fc zZL))Va3AhREf%64f5u>#-Ss!wYx`E!d6M(T)#rIKkrxj^PBpz`t+?|3)v) z;{q;0<%#P<76J&vL@}UX@5-I5TY>gFxK#HL##k= ziTU)lSeo7*8>nB36(n>^tWfX9eqM%5pB`))x*W630=>W-q!*cK?lM#KdNaq}VRAw8 zQPbys%6P&I>(geM?xv=fc{uKK&A90NxK9_yGu*4mW%00E9_K%b%DCK9RXz5ONmYf; z9fi(>s>0NuU8*;b(37chsJIt%u>cQX2_8WsR$?of(2Nw?@CNo`KMvwBKEZKxq6=s7 zA6&pi{0y1f_9LMqJnQoy%mECQ-ZFhDorR9=C6ausgk%EA>;s8^v%9Wa8f!csdDo0ob zq$mjX5$$q=hy?;Elv3ALIYe#{kf1c2-Sb?Mi*4L%R7m(w!WA&aZ%h0)f?9jHkgIR;jE@~8 zigU*{y6bZDM-_#99{H5~Jp7_Z)=3!~_QuJcQhLJK@v@dS6z!A4@-o{DnJXr|>)F0JXU%(76ePxc7r-Q9Go^jNX!U1)MVg2NH!FVD9wrI}5Iuv+`OSP6c! zvn)LCep1Vc5ti24Y$llW{=HR=?rqX@clN!?%ztMKX$?-lyX+5ff7#7eX0)(gO1oQd z5Aq5tJGm`y`){>1FWEf!zv26%q5X+mO-)Ekl4-*hIy1xuXQrrhW{KrasrbTqR}?w# ziDx2n#0Y1uu$+0KN#p}@%2DENXMreoJ`(AXkHsLTT$DN?k>f0+zDT?pSuFZHOT@&; zGLaD}Y;fneov@uG*GZWX>fo0vWJ&0tUp_4dhCI4_q(w=GsSWNyF7a}-IYL+^p=Wh@ zR%V6T2V_I1m(qlG39;!y8w{4~pSP5< zG@MZ(x444IaYD6<^V(hGgq?xj=z{^sK`w@46vks3^Jm9-)k17$-8O2wupftT3@6Zl zrt!jd!;e(7i5IGKyw`q=+zpxWB53y}^g(~*AQySaM*+s57!y!}$!s!%P2M9fCa)n^ zlB-aII&8%b?807ri=#M>6F7-;xDX!{_BFzFHoD11zmadlL6ZbwH-j5KB%>udq8obP zi3FkgBzWzCExLx#rs%*a>kZ1wvzlQ)&zNMz(#CFEe_*597jE_;yM~} z3%Bt%gpWhw0mP!OPpF|jkDW(;1tXD<0=$m#n2EV4#}Wirv8ckw71F6f4Zg%Se2u+0 zfFn4DdYs2)TtjrCupdGaQjne~RJ%m4-I@G2dY~8jA_qf}hhZ3*$oJ1D6k;5T@fJ!j z6+z6xhggBtSdVI666Ph_$vd$d2kCw;s9eu8LKCs#yMO>mY-Yn3pK)@q6+-3 zpepo7sbc>_Y9fUx{+7x{8Tqu|rGE5lDuVWUit3`bP~G$>yPq!9aNTQ9(7ATbl<4{+ax%o?u5<=L+z13JB#33{9{DbW+g)UCG>P>w}dj!(kQMyYv&_Gfg~q7rr3j-A+zeK?FCIK{a@iv1T^ z8k`I*kboq##wbIm0z*@UMwA+7v{X|JmzqXv8!>7wdA<>4E9Na?-cm!_736hBj!+v6 zLv1u3wl`C#!B^PMq@6~by@z(c;j#}=JBsg7k8`+y%eaQ?_{j(z940%3%x~nT1#T^` IVwWuX2b8FVmjD0& diff --git a/images/apple/PLASMA2.2mg b/images/apple/PLASMA2.2mg index 4f13153e6bc81d5cc644e679eacaacd181c34bc8..d589e98efb7c77ea79273c73c6ce22b0863d9a7b 100644 GIT binary patch delta 2313 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 Date: Tue, 17 Dec 2019 08:11:07 -0800 Subject: [PATCH 044/149] simplify indent/undent code --- src/toolsrc/ed.pla | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index 6b5fb86..357f93e 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -1438,30 +1438,24 @@ def editmode#0 is keytab if flags & insmode indentsel - else - undentsel - fin - if not (flags & selection) cursoff - if not ^(txtlinbuf=>[cursrow]) - curshpos((curscol + 2) & $FE) + if not ^(txtlinbuf=>[cursrow]) + curshpos((curscol + 2) & $FE) else autoindent(txtlinbuf=>[cursrow]) - fin + fin curson + break fin - break - is keydetab + is keydetab undentsel - if not (flags & selection) - cursoff - if not ^(txtlinbuf=>[cursrow]) - curshpos((curscol - 2) & $FFFE) - else - autoindent(txtlinbuf=>[cursrow]) - fin - curson + cursoff + if not ^(txtlinbuf=>[cursrow]) + curshpos((curscol - 2) & $FFFE) + else + autoindent(txtlinbuf=>[cursrow]) fin + curson break is keyctrly flags = flags ^ insmode From 1afb55984999fe5e69db9c198ab6e9d1b24456f2 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Tue, 17 Dec 2019 10:59:06 -0800 Subject: [PATCH 045/149] Remove extraneous OK printouts --- src/toolsrc/ed.pla | 4 +--- src/vmsrc/apple/cmd.pla | 4 +--- src/vmsrc/apple/cmdjit.pla | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index 357f93e..a08a83b 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -1662,10 +1662,8 @@ def cmdmode#0 if perr puts("ERROR: $") putb(perr) - else - puts("OK") + putln fin - putln loop end // diff --git a/src/vmsrc/apple/cmd.pla b/src/vmsrc/apple/cmd.pla index cd33088..29c638d 100755 --- a/src/vmsrc/apple/cmd.pla +++ b/src/vmsrc/apple/cmd.pla @@ -1366,10 +1366,8 @@ def docmds#0 if perr prstr("ERR:$") prbyte(perr) - else - prstr("OK") + crout() fin - crout() fin prstr(pfxop(@prefix, GET_PFX)) rdstr($BA) diff --git a/src/vmsrc/apple/cmdjit.pla b/src/vmsrc/apple/cmdjit.pla index d85bb22..39a54eb 100755 --- a/src/vmsrc/apple/cmdjit.pla +++ b/src/vmsrc/apple/cmdjit.pla @@ -1443,10 +1443,8 @@ def docmds#0 if perr prstr("ERR:$") prbyte(perr) - else - prstr("OK") + crout() fin - crout() fin prstr(pfxop(@prefix, GET_PFX)) rdstr($BA) From ae5ea36e8750dc63e7e2e7569fbd0b81f74f19e1 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Tue, 17 Dec 2019 11:01:05 -0800 Subject: [PATCH 046/149] Remove #$%&! TAB characters --- src/toolsrc/ed.pla | 292 ++++++++++++++++++++++----------------------- 1 file changed, 146 insertions(+), 146 deletions(-) diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index a08a83b..9b0afb0 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -555,8 +555,8 @@ def drawscrn(toprow, ofst)#0 lofst = flags & gutter if lofst - drawgutter(toprow, ofst) - fin + drawgutter(toprow, ofst) + fin // // Draw text // @@ -596,25 +596,25 @@ def cursoff#0 if flags & showcurs ^cursptr = underchr if flags & gutter - scrnptr = txtscrn[cursy] - *scrnptr = *scrnptr | $8080 - ^(scrnptr+2) = ^(scrnptr+2) | $80 - fin + scrnptr = txtscrn[cursy] + *scrnptr = *scrnptr | $8080 + ^(scrnptr+2) = ^(scrnptr+2) | $80 + fin flags = flags & ~showcurs fin end def curson#0 - byte lofst + byte lofst word scrnptr if !(flags & showcurs) - lofst = flags & gutter - if lofst - scrnptr = txtscrn[cursy] - *scrnptr = *scrnptr & $7F7F - ^(scrnptr+2) = ^(scrnptr+2) & $7F - fin + lofst = flags & gutter + if lofst + scrnptr = txtscrn[cursy] + *scrnptr = *scrnptr & $7F7F + ^(scrnptr+2) = ^(scrnptr+2) & $7F + fin cursptr = txtscrn[cursy] + lofst + cursx underchr = ^cursptr ^cursptr = curschr @@ -637,40 +637,40 @@ def redraw#0 curson end def curshpos(hpos)#1 - byte needredraw - - needredraw = TRUE - if hpos < 0; hpos = 0; fin - if hpos > MAXLNLEN; hpos = MAXLNLEN; fin + byte needredraw + + needredraw = TRUE + if hpos < 0; hpos = 0; fin + if hpos > MAXLNLEN; hpos = MAXLNLEN; fin curscol = hpos - cursx = curscol - scrnleft - if cursx > scrnright - cursx = scrnright - scrnleft = curscol - scrnright - elsif cursx < 0 + cursx = curscol - scrnleft + if cursx > scrnright + cursx = scrnright + scrnleft = curscol - scrnright + elsif cursx < 0 cursx = 0 scrnleft = curscol else - needredraw = FALSE + needredraw = FALSE fin return needredraw end def cursvpos(vpos)#1 - byte needredraw + byte needredraw - needredraw = TRUE + needredraw = TRUE if vpos < 0; vpos = 0; fin if vpos > numlines - 1; vpos = numlines - 1; fin cursrow = vpos cursy = cursrow - scrntop if cursy > scrnbottom - cursy = scrnbottom - scrntop = cursrow - scrnbottom - elsif cursy < 0 + cursy = scrnbottom + scrntop = cursrow - scrnbottom + elsif cursy < 0 cursy = 0 scrntop = cursrow else - needredraw = FALSE + needredraw = FALSE fin return needredraw end @@ -719,15 +719,15 @@ def cursup#0 fin end def pgup#0 - cursoff - if cursvpos(cursrow - pgjmp) - drawscrn(scrntop, scrnleft) - else - if flags & selection - drawgutter(scrntop, scrnleft) - fin - fin - curson + cursoff + if cursvpos(cursrow - pgjmp) + drawscrn(scrntop, scrnleft) + else + if flags & selection + drawgutter(scrntop, scrnleft) + fin + fin + curson end def cursdown#0 if cursrow < numlines - 1 @@ -746,15 +746,15 @@ def cursdown#0 fin end def pgdown#0 - cursoff - if cursvpos(cursrow + pgjmp) - drawscrn(scrntop, scrnleft) - else - if flags & selection - drawgutter(scrntop, scrnleft) - fin - fin - curson + cursoff + if cursvpos(cursrow + pgjmp) + drawscrn(scrntop, scrnleft) + else + if flags & selection + drawgutter(scrntop, scrnleft) + fin + fin + curson end def cursleft#0 if curscol > 0 @@ -770,15 +770,15 @@ def cursleft#0 fin end def pgleft#0 - cursoff - if curshpos(curscol - 8) - drawscrn(scrntop, scrnleft) - else - if flags & selection - drawgutter(scrntop, scrnleft) - fin - fin - curson + cursoff + if curshpos(curscol - 8) + drawscrn(scrntop, scrnleft) + else + if flags & selection + drawgutter(scrntop, scrnleft) + fin + fin + curson end def cursright#0 if curscol < MAXLNLEN @@ -794,15 +794,15 @@ def cursright#0 fin end def pgright#0 - cursoff - if curshpos(curscol + 8) - drawscrn(scrntop, scrnleft) - else - if flags & selection - drawgutter(scrntop, scrnleft) - fin - fin - curson + cursoff + if curshpos(curscol + 8) + drawscrn(scrntop, scrnleft) + else + if flags & selection + drawgutter(scrntop, scrnleft) + fin + fin + curson end // // Find string in text @@ -835,8 +835,8 @@ def findtxt#0 // Search from current pos to end // if findline(txtlinbuf=>[cursrow], curscol + 2) - return - fin + return + fin for f = cursrow + 1 to numlines - 1 if findline(txtlinbuf=>[f], 1) cursvpos(f) @@ -909,7 +909,7 @@ def keyin3 is keyenter key = keyctrlf; break is keytab - key = keydetab; break + key = keydetab; break is $80 | '\\' key = keydelete; break // Delete // @@ -963,7 +963,7 @@ def keyin2e is keyenter key = keyctrlf; break is keytab - key = keydetab; break + key = keydetab; break wend fin return key @@ -1186,13 +1186,13 @@ def undentsel#0 redraw end def autoindent(strptr)#0 - byte i - - for i = 1 to ^strptr - if ^(strptr + i) <> keyspace - break + byte i + + for i = 1 to ^strptr + if ^(strptr + i) <> keyspace + break fin - next + next curshpos(i - 1) end def openline(row) @@ -1279,7 +1279,7 @@ def editline(key) byte editstr[MAXLNLEN+1], localchange, need word undoline - localchange = FALSE + localchange = FALSE if (editkey(key)) localchange = TRUE memset(@editstr + 1, $A0A0, MAXLNLEN) @@ -1289,21 +1289,21 @@ def editline(key) repeat if key >= keyspace if key == keydelete - if curscol > 0 - if curscol <= editstr - memcpy(@editstr[curscol], @editstr[curscol + 1], editstr - curscol) - editstr-- - fin - cursoff - if curshpos(curscol - 1) - drawscrn(scrntop, scrnleft) - else - drawrow(cursy, scrnleft, @editstr) - fin - curson - fin + if curscol > 0 + if curscol <= editstr + memcpy(@editstr[curscol], @editstr[curscol + 1], editstr - curscol) + editstr-- + fin + cursoff + if curshpos(curscol - 1) + drawscrn(scrntop, scrnleft) + else + drawrow(cursy, scrnleft, @editstr) + fin + curson + fin elsif curscol < MAXLNLEN - curscol++ + curscol++ if flags & insmode if editstr < MAXLNLEN or editstr.MAXLNLEN == keyspace editstr++ @@ -1347,21 +1347,21 @@ def editline(key) cursoff drawrow(cursy, scrnleft, @editstr) curson - localchange = FALSE + localchange = FALSE fin key = keyin() until not editkey(key) if localchange - flags = flags | changed - delstr(undoline) - if editstr - txtlinbuf=>[cursrow] = newstr(@editstr) - else - txtlinbuf=>[cursrow] = @nullstr - fin - else - txtlinbuf=>[cursrow] = undoline - fin + flags = flags | changed + delstr(undoline) + if editstr + txtlinbuf=>[cursrow] = newstr(@editstr) + else + txtlinbuf=>[cursrow] = @nullstr + fin + else + txtlinbuf=>[cursrow] = undoline + fin fin return key end @@ -1415,10 +1415,10 @@ def editmode#0 is keyctrlo openline(cursrow) if cursrow - autoindent(txtlinbuf=>[cursrow - 1]) - else - curshpos(0) - fin + autoindent(txtlinbuf=>[cursrow - 1]) + else + curshpos(0) + fin redraw break is keyenter @@ -1427,7 +1427,7 @@ def editmode#0 else openline(cursrow + 1) fin - autoindent(txtlinbuf=>[cursrow]) + autoindent(txtlinbuf=>[cursrow]) cursvpos(cursrow + 1) redraw break @@ -1436,26 +1436,26 @@ def editmode#0 redraw break is keytab - if flags & insmode - indentsel - cursoff - if not ^(txtlinbuf=>[cursrow]) - curshpos((curscol + 2) & $FE) + if flags & insmode + indentsel + cursoff + if not ^(txtlinbuf=>[cursrow]) + curshpos((curscol + 2) & $FE) else autoindent(txtlinbuf=>[cursrow]) - fin - curson - break - fin + fin + curson + break + fin is keydetab undentsel - cursoff - if not ^(txtlinbuf=>[cursrow]) - curshpos((curscol - 2) & $FFFE) - else - autoindent(txtlinbuf=>[cursrow]) - fin - curson + cursoff + if not ^(txtlinbuf=>[cursrow]) + curshpos((curscol - 2) & $FFFE) + else + autoindent(txtlinbuf=>[cursrow]) + fin + curson break is keyctrly flags = flags ^ insmode @@ -1579,27 +1579,27 @@ def cmdmode#0 findtxt return is 'T' // Toggle upper/lower case display - if ^cmdptr - when toupper(^(cmdptr + 1)) - is 'G' // Gutter view - flags = flags ^ gutter - if flags & gutter - scrnwidth = 36 - scrnright = 35 - else - scrnwidth = 40 - scrnright = 39 - fin - break - is 'C' // Lower case chip (Apple ][/][+ only) - if flags & uppercase - txtlower - else - txtupper - fin - break - wend - fin + if ^cmdptr + when toupper(^(cmdptr + 1)) + is 'G' // Gutter view + flags = flags ^ gutter + if flags & gutter + scrnwidth = 36 + scrnright = 35 + else + scrnwidth = 40 + scrnright = 39 + fin + break + is 'C' // Lower case chip (Apple ][/][+ only) + if flags & uppercase + txtlower + else + txtupper + fin + break + wend + fin return is 'G' // Goto line # line = strtonum(cmdptr) @@ -1610,7 +1610,7 @@ def cmdmode#0 is 'E' // Edit mode is 0 return - is 'A' // Append file + is 'A' // Append file readtxt(cmdptr, numlines) flags = flags | changed break @@ -1662,7 +1662,7 @@ def cmdmode#0 if perr puts("ERROR: $") putb(perr) - putln + putln fin loop end From b81e9118578f1e32ffebc96655a5787f9580bfeb Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Tue, 17 Dec 2019 13:30:09 -0800 Subject: [PATCH 047/149] Snag a few more easy optimizations --- src/samplesrc/test.pla | 6 +++++- src/toolsrc/codegen.c | 35 ++++++++++++++++++++++++++++++----- src/toolsrc/codeopt.pla | 35 ++++++++++++++++++++++++++++------- 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/src/samplesrc/test.pla b/src/samplesrc/test.pla index a8a1c26..73a29eb 100755 --- a/src/samplesrc/test.pla +++ b/src/samplesrc/test.pla @@ -204,5 +204,9 @@ puti(array:0); puts(" > "); puti(array:0); puts (" is ") puts(array:0 > array:0 ?? "TRUE\n" :: "FALSE\n") puti(array:0); puts(" < "); puti(array:0); puts (" is ") puts(array:0 < array:0 ?? "TRUE\n" :: "FALSE\n") -ptr = 0 +ptr = 5 +puts("5*0="); puti(ptr*0); putln +puts("5*1="); puti(ptr*1); putln +puts("5*2="); puti(ptr*2); putln +puts("5/1="); puti(ptr/1); putln done diff --git a/src/toolsrc/codegen.c b/src/toolsrc/codegen.c index b5fcb46..7471bcb 100755 --- a/src/toolsrc/codegen.c +++ b/src/toolsrc/codegen.c @@ -1230,6 +1230,17 @@ int crunch_seq(t_opseq **seq, int pass) freeops = 1; break; } + if (opnext->code == BINARY_CODE(SHL_TOKEN)) + { + op->code = DUP_CODE; + opnext->code == BINARY_CODE(ADD_TOKEN); + break; + } + if (opnext->code == BINARY_CODE(MUL_TOKEN) || opnext->code == BINARY_CODE(DIV_TOKEN)) + { + freeops = -2; + break; + } } switch (opnext->code) { @@ -1441,13 +1452,27 @@ int crunch_seq(t_opseq **seq, int pass) } break; case BINARY_CODE(MUL_TOKEN): - for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) + if (op->val == 0) { - if (op->val == (1 << shiftcnt)) + op->code = DROP_CODE; + opnext->code = CONST_CODE; + opnext->val = 0; + } + else if (op->val == 2) + { + op->code = DUP_CODE; + opnext->code = BINARY_CODE(ADD_TOKEN); + } + else + { + for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) { - op->val = shiftcnt; - opnext->code = BINARY_CODE(SHL_TOKEN); - break; + if (op->val == (1 << shiftcnt)) + { + op->val = shiftcnt; + opnext->code = BINARY_CODE(SHL_TOKEN); + break; + } } } break; diff --git a/src/toolsrc/codeopt.pla b/src/toolsrc/codeopt.pla index 385cd7f..66e97e4 100644 --- a/src/toolsrc/codeopt.pla +++ b/src/toolsrc/codeopt.pla @@ -79,6 +79,16 @@ def crunch_seq(seq, pass) freeops = 1 break fin + if nextop->opcode == SHL_CODE + op->opcode = DUP_CODE + nextop->opcode = ADD_CODE + op->opgroup = STACK_GROUP + break + fin + if nextop->opcode == MUL_CODE or nextop->opcode == DIV_CODE + freeops = -2 + break + fin fin when nextop->opcode is NEG_CODE @@ -258,13 +268,24 @@ def crunch_seq(seq, pass) fin break is MUL_CODE - for shiftcnt = 0 to 15 - if op=>opval == 1 << shiftcnt - op=>opval = shiftcnt - nextop->opcode = SHL_CODE - break - fin - next + if op=>opval == 0 + op->opcode = DROP_CODE + nextop->opcode = CONST_CODE + nextop->opval = 0 + nextop->opgroup = CONST_GROUP + elsif op=>opval == 2 + op->opcode = DUP_CODE + nextop->opcode = ADD_CODE + op->opgroup = STACK_GROUP + else + for shiftcnt = 2 to 15 + if op=>opval == 1 << shiftcnt + op=>opval = shiftcnt + nextop->opcode = SHL_CODE + break + fin + next + fin break is DIV_CODE for shiftcnt = 0 to 15 From 60e556cc637452aed4c39100f7517207b9c7c201 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Tue, 17 Dec 2019 14:52:35 -0800 Subject: [PATCH 048/149] more low hanging opts (and fix previous cross compiler opt) --- src/toolsrc/codegen.c | 12 +++++++++--- src/toolsrc/codeopt.pla | 2 +- src/vmsrc/apple/plvm01.s | 8 ++++++-- src/vmsrc/apple/plvm02.s | 8 ++++++-- src/vmsrc/apple/plvm03.s | 8 ++++++-- src/vmsrc/apple/plvm802.s | 12 ++++++------ src/vmsrc/apple/plvmjit02.s | 10 +++++++--- 7 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/toolsrc/codegen.c b/src/toolsrc/codegen.c index 7471bcb..f8dd98a 100755 --- a/src/toolsrc/codegen.c +++ b/src/toolsrc/codegen.c @@ -1233,7 +1233,7 @@ int crunch_seq(t_opseq **seq, int pass) if (opnext->code == BINARY_CODE(SHL_TOKEN)) { op->code = DUP_CODE; - opnext->code == BINARY_CODE(ADD_TOKEN); + opnext->code = BINARY_CODE(ADD_TOKEN); break; } if (opnext->code == BINARY_CODE(MUL_TOKEN) || opnext->code == BINARY_CODE(DIV_TOKEN)) @@ -1465,7 +1465,10 @@ int crunch_seq(t_opseq **seq, int pass) } else { - for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) + // + // Constants 0, 1 and 2 handled above + // + for (shiftcnt = 2; shiftcnt < 16; shiftcnt++) { if (op->val == (1 << shiftcnt)) { @@ -1477,7 +1480,10 @@ int crunch_seq(t_opseq **seq, int pass) } break; case BINARY_CODE(DIV_TOKEN): - for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) + // + // Constant 1 handled above + // + for (shiftcnt = 1; shiftcnt < 16; shiftcnt++) { if (op->val == (1 << shiftcnt)) { diff --git a/src/toolsrc/codeopt.pla b/src/toolsrc/codeopt.pla index 66e97e4..6e49f7c 100644 --- a/src/toolsrc/codeopt.pla +++ b/src/toolsrc/codeopt.pla @@ -288,7 +288,7 @@ def crunch_seq(seq, pass) fin break is DIV_CODE - for shiftcnt = 0 to 15 + for shiftcnt = 1 to 15 if op=>opval == 1 << shiftcnt op=>opval = shiftcnt nextop->opcode = SHR_CODE diff --git a/src/vmsrc/apple/plvm01.s b/src/vmsrc/apple/plvm01.s index 73645fe..de74557 100644 --- a/src/vmsrc/apple/plvm01.s +++ b/src/vmsrc/apple/plvm01.s @@ -109,7 +109,7 @@ COMP LDA #$FF ;* OPCODE TABLE ;* !ALIGN 255,0 -OPTBL !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E +OPTBL !WORD ZERO,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 10 12 14 16 18 1A 1C 1E !WORD MINUS1,BREQ,BRNE,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E !WORD DROP,DROP2,DUP,DIVMOD,ADDI,SUBI,ANDI,ORI ; 30 32 34 36 38 3A 3C 3E @@ -388,13 +388,17 @@ LNOT LDA ESTKL,X STA ESTKH,X JMP NEXTOP ;* -;* CONSTANT -1, NYBBLE, BYTE, $FF BYTE, WORD (BELOW) +;* CONSTANT -1, ZERO, NYBBLE, BYTE, $FF BYTE, WORD (BELOW) ;* MINUS1 DEX + LDA #$FF STA ESTKL,X STA ESTKH,X JMP NEXTOP +ZERO DEX + STA ESTKL,X + STA ESTKH,X + JMP NEXTOP CN DEX LSR ; A = CONST * 2 STA ESTKL,X diff --git a/src/vmsrc/apple/plvm02.s b/src/vmsrc/apple/plvm02.s index 9781c0f..3cca995 100755 --- a/src/vmsrc/apple/plvm02.s +++ b/src/vmsrc/apple/plvm02.s @@ -132,7 +132,7 @@ VMCORE = * ;* * ;**************** !ALIGN 255,0 -OPTBL !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E +OPTBL !WORD ZERO,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 10 12 14 16 18 1A 1C 1E !WORD MINUS1,BREQ,BRNE,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E !WORD DROP,DROP2,DUP,DIVMOD,ADDI,SUBI,ANDI,ORI ; 30 32 34 36 38 3A 3C 3E @@ -633,13 +633,17 @@ LNOT LDA ESTKL,X STA ESTKH,X JMP NEXTOP ;* -;* CONSTANT -1, NYBBLE, BYTE, $FF BYTE, WORD (BELOW) +;* CONSTANT -1, ZERO, NYBBLE, BYTE, $FF BYTE, WORD (BELOW) ;* MINUS1 DEX + LDA #$FF STA ESTKL,X STA ESTKH,X JMP NEXTOP +ZERO DEX + STA ESTKL,X + STA ESTKH,X + JMP NEXTOP CN DEX LSR ; A = CONST * 2 STA ESTKL,X diff --git a/src/vmsrc/apple/plvm03.s b/src/vmsrc/apple/plvm03.s index d00c54e..db24f80 100755 --- a/src/vmsrc/apple/plvm03.s +++ b/src/vmsrc/apple/plvm03.s @@ -143,7 +143,7 @@ JENTRY !WORD JITINTRP ; $A0FA ;* OPCODE TABLE ;* !ALIGN 255,0 -OPTBL !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E +OPTBL !WORD ZERO,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 10 12 14 16 18 1A 1C 1E !WORD MINUS1,BREQ,BRNE,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E !WORD DROP,DROP2,DUP,DIVMOD,ADDI,SUBI,ANDI,ORI ; 30 32 34 36 38 3A 3C 3E @@ -551,13 +551,17 @@ LNOT LDA ESTKL,X STA ESTKH,X JMP NEXTOP ;* -;* CONSTANT -1, NYBBLE, BYTE, $FF BYTE, WORD (BELOW) +;* CONSTANT -1, ZERO, NYBBLE, BYTE, $FF BYTE, WORD (BELOW) ;* MINUS1 DEX + LDA #$FF STA ESTKL,X STA ESTKH,X JMP NEXTOP +ZERO DEX + STA ESTKL,X + STA ESTKH,X + JMP NEXTOP CN DEX LSR ; A = CONST * 2 STA ESTKL,X diff --git a/src/vmsrc/apple/plvm802.s b/src/vmsrc/apple/plvm802.s index baf41b6..6015ebc 100644 --- a/src/vmsrc/apple/plvm802.s +++ b/src/vmsrc/apple/plvm802.s @@ -258,7 +258,7 @@ VMCORE = * ;* * ;**************** !ALIGN 255,0 -OPTBL !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E +OPTBL !WORD ZERO,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 10 12 14 16 18 1A 1C 1E !WORD MINUS1,BREQ,BRNE,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E !WORD DROP,DROP2,DUP,DIVMOD,ADDI,SUBI,ANDI,ORI ; 30 32 34 36 38 3A 3C 3E @@ -491,7 +491,7 @@ LCDEFCMD = *-28 ; DEFCMD IN LC MEMORY ;* * ;***************** !ALIGN 255,0 -OPXTBL !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E +OPXTBL !WORD ZERO,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 10 12 14 16 18 1A 1C 1E !WORD MINUS1,BREQ,BRNE,LA,LLA,CB,CW,CSX ; 20 22 24 26 28 2A 2C 2E !WORD DROP,DROP2,DUP,DIVMOD,ADDI,SUBI,ANDI,ORI ; 30 32 34 36 38 3A 3C 3E @@ -849,14 +849,14 @@ ORI INY ;+INC_IP ;* LOGICAL NOT ;* LNOT PLA - BEQ MINUS1 - PEA $0000 - JMP NEXTOP + BNE ZERO ;* -;* CONSTANT -1, NYBBLE, BYTE, $FF BYTE, WORD (BELOW) +;* CONSTANT -1, ZERO, NYBBLE, BYTE, $FF BYTE, WORD (BELOW) ;* MINUS1 PEA $FFFF JMP NEXTOP +ZERO PEA $0000 + JMP NEXTOP CN TXA LSR ; A = CONST * 2 PHA diff --git a/src/vmsrc/apple/plvmjit02.s b/src/vmsrc/apple/plvmjit02.s index 54c2820..8dc1396 100755 --- a/src/vmsrc/apple/plvmjit02.s +++ b/src/vmsrc/apple/plvmjit02.s @@ -206,7 +206,7 @@ VMCORE = * ;* * ;**************** !ALIGN 255,0 -OPTBL !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E +OPTBL !WORD ZERO,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 10 12 14 16 18 1A 1C 1E !WORD MINUS1,BREQ,BRNE,LA,LLA,CB,CW,CS ; 20 22 24 26 28 2A 2C 2E !WORD DROP,DROP2,DUP,DIVMOD,ADDI,SUBI,ANDI,ORI ; 30 32 34 36 38 3A 3C 3E @@ -397,7 +397,7 @@ LCDEFCMD = * ;*-28 ; DEFCMD IN LC MEMORY ;* * ;***************** !ALIGN 255,0 -OPXTBL !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E +OPXTBL !WORD ZERO,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06 08 0A 0C 0E !WORD CN,CN,CN,CN,CN,CN,CN,CN ; 10 12 14 16 18 1A 1C 1E !WORD MINUS1,BREQ,BRNE,LA,LLA,CB,CW,CSX ; 20 22 24 26 28 2A 2C 2E !WORD DROP,DROP2,DUP,DIVMOD,ADDI,SUBI,ANDI,ORI ; 30 32 34 36 38 3A 3C 3E @@ -797,13 +797,17 @@ LNOT LDA ESTKL,X STA ESTKH,X JMP NEXTOP ;* -;* CONSTANT -1, NYBBLE, BYTE, $FF BYTE, WORD (BELOW) +;* CONSTANT -1, ZERO, NYBBLE, BYTE, $FF BYTE, WORD (BELOW) ;* MINUS1 DEX + LDA #$FF STA ESTKL,X STA ESTKH,X JMP NEXTOP +ZERO DEX + STA ESTKL,X + STA ESTKH,X + JMP NEXTOP CN DEX LSR ; A = CONST * 2 STA ESTKL,X From ff3d3c0b8789a4d85213e3a64ffa7a3ef5ec08c8 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Tue, 17 Dec 2019 16:51:33 -0800 Subject: [PATCH 049/149] Simple 65C02 opts I didn't do before. --- src/vmsrc/apple/plvmjit02.s | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vmsrc/apple/plvmjit02.s b/src/vmsrc/apple/plvmjit02.s index 8dc1396..a5b581a 100755 --- a/src/vmsrc/apple/plvmjit02.s +++ b/src/vmsrc/apple/plvmjit02.s @@ -2174,11 +2174,11 @@ CLLBXEND JSR OPCPY CLAB INY ;+INC_IP LDA (IP),Y - STA ESTKH-2,X + STA TMPL INY ;+INC_IP LDA (IP),Y - STA ESTKH-1,X - LDA (ESTKH-2,X) + STA TMPH + LDA (TMP) DEX STA ESTKL,X STZ ESTKH,X @@ -2212,12 +2212,12 @@ CLAWEND JSR OPCPY CLABX INY ;+INC_IP LDA (IP),Y - STA ESTKH-2,X + STA TMPL INY ;+INC_IP LDA (IP),Y - STA ESTKH-1,X + STA TMPH STA ALTRDOFF - LDA (ESTKH-2,X) + LDA (TMP) DEX STA ESTKL,X STZ ESTKH,X From 10a98d53927f99dd216b7d68a9123c35a39bf2fb Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Tue, 17 Dec 2019 21:20:09 -0800 Subject: [PATCH 050/149] Seriously broken dividing zero by anything --- src/toolsrc/codeopt.pla | 7 ++++--- src/vmsrc/apple/plvm802.s | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/toolsrc/codeopt.pla b/src/toolsrc/codeopt.pla index 6e49f7c..f725902 100644 --- a/src/toolsrc/codeopt.pla +++ b/src/toolsrc/codeopt.pla @@ -81,8 +81,8 @@ def crunch_seq(seq, pass) fin if nextop->opcode == SHL_CODE op->opcode = DUP_CODE - nextop->opcode = ADD_CODE op->opgroup = STACK_GROUP + nextop->opcode = ADD_CODE break fin if nextop->opcode == MUL_CODE or nextop->opcode == DIV_CODE @@ -270,13 +270,14 @@ def crunch_seq(seq, pass) is MUL_CODE if op=>opval == 0 op->opcode = DROP_CODE + op->opgroup = STACK_GROUP nextop->opcode = CONST_CODE - nextop->opval = 0 nextop->opgroup = CONST_GROUP + nextop=>opval = 0 elsif op=>opval == 2 op->opcode = DUP_CODE - nextop->opcode = ADD_CODE op->opgroup = STACK_GROUP + nextop->opcode = ADD_CODE else for shiftcnt = 2 to 15 if op=>opval == 1 << shiftcnt diff --git a/src/vmsrc/apple/plvm802.s b/src/vmsrc/apple/plvm802.s index 6015ebc..9d11202 100644 --- a/src/vmsrc/apple/plvm802.s +++ b/src/vmsrc/apple/plvm802.s @@ -638,12 +638,12 @@ _DIV STY IPY LDY #$11 ; #BITS+1 LDX #$00 LDA NOS+2,S ; WE JSR'ED HERE SO OFFSET ACCORDINGLY - BEQ _DIVEX BPL + LDX #$81 EOR #$FFFF INC + STA TMP ; NOS,S + BEQ _DIVEX LDA TOS+2,S BPL + INX From 7a9123b2612df9981bf0822c2e9168ea991df414 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Tue, 17 Dec 2019 21:43:05 -0800 Subject: [PATCH 051/149] Fixes and optimizations for the value of zero, my hero. --- README.md | 2 +- doc/Version 2.0.md | 6 +++++- images/apple/PLASMA2-BLD.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2-FPSOS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes 6 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 74aa20c..a186f62 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 12/16/2019 PLASMA 2.0 Developer Preview 1 E+C Available! +# 12/17/2019 PLASMA 2.0 Developer Preview 1z Available! [Download and read the Release Notes](https://github.com/dschmenk/PLASMA/blob/master/doc/Version%202.0.md) # 4/29/2018 PLASMA 1.2 Available! diff --git a/doc/Version 2.0.md b/doc/Version 2.0.md index 2fd0945..a183038 100644 --- a/doc/Version 2.0.md +++ b/doc/Version 2.0.md @@ -1,4 +1,4 @@ -# PLASMA Version 2.0 Developer Preview 1 E+C +# PLASMA Version 2.0 Developer Preview 1z Welcome to PLASMA: the Grand Unifying Platform for the Apple 1, ][, and ///. @@ -102,6 +102,10 @@ There is a [YouTube playlist](https://www.youtube.com/playlist?list=PLlPKgUMQbJ7 - The documentation is sparse and incomplete. Yep, could use your help... +# Changed in PLASMA for 2.0 DP 1z + +1. Many fixes for the value zero - especially in 65802/65816 divide routine + # Changed in PLASMA for 2.0 DP 1 E+C 1. Greatly improved code editor and additional compiler stats diff --git a/images/apple/PLASMA2-BLD.PO b/images/apple/PLASMA2-BLD.PO index 12ea5b6e22dca593d319b33c5d94621e85e49edb..6288fb682bc58a03514803191e473e7f98b2d3cf 100644 GIT binary patch delta 854 zcmZuvUr19?82`Sz+q}DXrVDc_sKb`VWkS#%k`$I{nT>6XUhJVH@)kbLkhw%{yA2bv zazl2Ye@G!cG+ZV$E6t|}gCL?Fd=aCUqUa?e>W-~*?wwN5h3|g9^ZU;C`&5xRaU&SopY<% z#Tqy0197F}ee z8xQW5REg^Yu$S`?AyNoGUyO)~*c+U;DB^zZH0SICh3}PB=MIo36*0ss;$(;mTLY^W z#>W|d?QfnoQvQas0%Z3lFRKb43J|?A?wJ#G$qA3w0w?oSYK#?vV^o?tx~Et=&nzAr zOmd5uH3+X6AYcN=7Jrot4&WXyl< zWtS&i3c8^pP}eT+Hei-NO*-c@8z=i@EUBS>(6xW7uZqhukfWPdWg?HV{y}_$_<=aW z*n^i@Y9upZ+}F^Ix;}KJMZ;Y#bbCdRTWLRQEk*JpjLjYEM%7mj^4?8p*+r*FM>olS zbVPx6V-x?MSvNr)PkcjINm_@{h8)AL&Q#6=!?|`ioAW|O^T9hU3fDCi{P{S{=EtGC zFadLgDd^FXplH+ZC7*(l!VJ9E?!tF14UXI#l#-PpY@-i}WFlBi>=8_{S49`oCOk|! zMsOKb!i}P{KD7D%8}n~-R<(KsU2#x6*Z7$K)d T@!mo?cLkFT=Bzo2zcYUTRtWca delta 1193 zcmZvaZAep57{~w5+1Ylt`L;A$QA%aa%%rK65=2&F#nhn{6%i763HzeGsJ)2JBtyiP zif;NLdLx5O4L?jxi=yZSDv=24OF{?*RuI?+H)iKza%o_n72KfmXH?sM*Gn3NhO zrGZYK-C?&#EAbUj69)VC;vM!6u~xja2Gf2uRkerKiq|3SelYb+ub``|)!L?Alp8R4 zvYYZ&Sz;}$99R^`p;s)G^!=#bESt+pwwPpd4m-k9G9mM_w8oSLNNbhNm0UKrRrACq%I1%C>NY4?@-^zRlGVVT$&fkmG&xHM1@LE6{S*&GA;(@)hSC)lFh!` zsfSwiNheFaiIAnTwDhgL(FmBzQVts$c{Doqc#zmE6(89dqCL96dXWK#{i66@aOw))4vq$32ZFX`JY$@}QblE2pa|iwe~I0Q&(&s-YzI7D{Rjt>f2`1m$TB zB`W!j%64TIMdIZ>|Gf-b=Xay@IuK zS5Yu`0}Fk(kmc(|nXeCpKGy(O&(W<+*HX6lZAw)w^@qmAp3SG}td52i&p8^S8Rb+R zrR3T;+{X-XuQ9?ci})fUS%N!N#2pb2By_f!mvvqf@kYc4^D?)=f=-h%QAf8eMneAn zyh4{Vzw~l+jIADEFxZ8b;na)Wb_&5w$BWZCFZr~rquFv#Zm?OfDe->_TO}B8TqJKUKJxYz5 zb`j0;DRCsfnI^VA+ywuIXqXbUu*@(8J|i}LXT%|m6LvVlAfJT^)>tjOtS|+xBR%&1 L--E|rPi){X>E9}8 diff --git a/images/apple/PLASMA2-FPSOS.PO b/images/apple/PLASMA2-FPSOS.PO index 8c590863e5e82ab4066903a4970b883eeb2437da..0ae971d01c744fb0374f388db90b05cd31d5054f 100644 GIT binary patch delta 1971 zcmaJ>eQaCR6+ido<<&_Vnz*i#rX+FO$XJ#WoT<~YDjHk_);W}F>W5pkfcgNTl2L!X`{Kkl4MqY9g!q(DMav%)0aI0kwwAQ33jdG=vUBYK z`)kkkyXTyHK7QxipYPNa%hVN1{o8e0UAv}Fn{!PPkO=bBfLh{G~vykEF|;t4~4bsw?o@(6jjvF{a-0H2HV7iMqI*3EV6 z;Sq8x?%)f?7CvtF@~6x`UX$A072Atrq#z+fjxv~JE5fZn)|lxq^SGDtA+ix37|{D=H4 z9SYbm&L>q|7(l|kNNDOX7qi{QBvlzCTLZ$fABKN?JN^=EAbt z2}}+hFzIu-u;RTFTu(%o3?@4*v@7Rv-GkFaaYvqZ>YqeO*P0)U?P@cG7N?md5ea^; z+a}08F7$NvA@#!2)XXXf^tl@P)%D=)a}GPMb9$qIn>9sT=>`4Z1liCrZkGLi;rijX zY6H%g-k$Ziwj<+D`K~g_IV?_He|>_us|U?9u|fUD1Zj~qy;MYg zSs+*mcWiNXBlJU>gE{=(_m|ln%JT`jwh*>!n}BT^VUpL1(8_2lmF6^=ITB%qGjLdI zVG3(GtSL;!WvhfciimAyjxHwCMUypaHfAfz_?DQ>4Gl<7bdq7adTqJV2m{tkkLslu z*|s@i_E_nga~`e3vD-W!F-H*OPf&vqGZBsGZIh&%JgyH+l6Eqrk4%!bJKV)X1K6Xr zSj+6xp}#OmTHV-E*yZoFs2#vuiQ(d%VH+z`tsW3i*>M(8xtR@%e}&27qcZ~vxcW!C z0$nPeN|zX}g=z&4Xjaysw&D;2ce94#YUd{UcyU+QS{@^_o)QGG`mPGTuP2hw0RIoW za_U2Z_}W^em$oi6XlhMpzEpIBy*gI_J}YHdp}=>==C)m$rrn6INEsZmO&GG<3Z9qyd&RLegE(7-`XKKU0tBxAhYw1 zc8+~`1d^^*eLLwN9^B~_H|cIOxZ8wnY7^j!POf{!ZPdn56O;|zn%+e(&i{O^&S8qS K((!|2Z}GowMfz+2 delta 2131 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 delta 3213 zcmb8x3sh8P9suzFckdl$7#Hfs+L{#qTXLGJWb|Db3ev|HOn^InBF0dW&=(62SgDx)C6w73yHuwl97m!jIa;Gt zjhdJ|5>4mW3oSq?Bh`%su}g+TWI@A<3$)`iQ&9a+C`))71qJ$RD*``BzihskZjE%WZ0p(espNp65Q#cu%@F!E5s_ z^?c&>d;7d;zI%NmTxG6G*I`$i>o4xb?j`bSIZigodGci0DIbt!`3JejF|pi|`h<77 zx58WJE%9#mp7;Fd`L`?NTIY7U6WycT$J`g)IgPKC7pTN7Us1)4k5&~?q^Qxk*2xGt z8pnk7)uT6!jMDVqNF|sEBgapj@c2}gyM5#O_swUkr6jdW#uOTyN zCE#|F&xjJl*OH&8EUE@4S@CY%f-mC+!UiQ&a{J>JoE*%(HxNo$d&ss7W$ZsrlDz&& z!Y$;{5m7^;sQCbiItEnYlq=->5|y@CTlDnU$YSk7)LhDXKNK@Xw$;{nu&poFzQ`17 z*S|=;9L-LTRPt+-{DwR8IFP~NSck(mDZiH~MMj{!3sFtw;DEv z*1&h6*I-@vb@(v633l{thP{1TATzuTCWUJuA?SqM;QLS%{16I)>^??$BY83F1{sa_ zP27K-Gz?yorIk0xN}3!LdxPY2a!ovNi&*oL7~mI10Dq4f_+s=evS@%Gh2B9QXh7JY zH3{2M3vy{qd_)uokz#y^dRkz>cnaxvlyYFhbd{CNNOm(BfBpfWJuy-^pg zQtvMBLeG1iOWs^xVTafps~RR{AE&bD|7*){{ZCt-+5RzZ+0=0#Zuv=hw)~ZRQMP#} z{=t@0f4}8KkKMz2o4v1lzV>K+vwek9QVUf^NqAnEROB1!qcc=IJ^oP6ijotpM8D>0 z)z7t1-&%Fu-VODmo$lJmltVc!lee~(HQTR1{W#1-DVeh76Z@}jZB=rWm`hAKB&yw% zg&Yz`x+yDXcFMIeSa+ax>*3vpZ;yTwvqJ~7)l~C9M>X9)^B(Mr$3C2P&4s#_{b!Xy z?_5w8_zJs{aDiQJN^k9TdTNIa)NO52_HcN2Q_JlIVw~PuBUW~}DYMOn4gFn}%9;bk zgNshYk~FLzAyZa$uG3$ef(=%tEZT2;^`+Q0478JcG+mTKT4dH>T6+ ztBw10`v+Quv$uD@7e}eFr|eAG5qlTZ*Es{V=9ELyd6}9;@RXMFy;SE=-A~zg2CKD$ zN3~ij{rN|Vo*QK|;{i#;xCziIO(~>f8RZat?rAz+r~EfAnM+qFiSD^Hubir4+4J-f zB{60`y_kNciEx~Ojia~|1~!V~9y78kimNlS_`SNrz}_I-P$T;@;a)MaorJq+WG@l! zoSr>LxCjFqAl!;n)=fA^Dtnr6fmHS+;VRPDW8#exdJK6}yswnLhs+V5E2XooxrCc; z+Bwm^4iD;PrCU|L9o zGPT_FQARP1cv8pN{2^h@!#A0z;9q%vip)U}wNL1HRwKrPJ# zssVLM)0faKl$5`WF8DzdW-&%pjjP7BMfz|S^DTW>Vh%HfL|@6)ML78Yt2)-yt_o)-4%V}%c}-Kb9y4x$qn4>K@Ant>9=pg9JMP+}M&EHcpi zDgy{x4e@-v0XK-T+raQ%ytW$>gbM~*_#SJzv7KPFFucJCg4xIj=|(j_3gb*;0zbwG z{3B?bG@lSXjV4C; z7_SFS8sQkm$4xYU66?-joy$b{Z!kWG@dcAfxMVW(m$BW6dQdOsZ<>bkA-obZ!!sky sz-v$p(xF78M<$el(ou$4jOwJb#iGyE`_|?+sgVXnBJI2RO;Jbx0}gKLW&i*H From 0b750d46c5dfb9096ecfc85e19184d8a05cd0ccf Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Wed, 18 Dec 2019 18:59:24 -0800 Subject: [PATCH 052/149] Back to fun HGR stuff --- src/libsrc/line.pla | 113 ++++++++++++++ src/makefile | 7 +- src/samplesrc/hgr1test.pla | 143 +++++++++++++++++- src/samplesrc/hgrtest.pla | 300 +++++++++++++++++++++++++++++++++++++ 4 files changed, 561 insertions(+), 2 deletions(-) create mode 100644 src/libsrc/line.pla create mode 100644 src/samplesrc/hgrtest.pla diff --git a/src/libsrc/line.pla b/src/libsrc/line.pla new file mode 100644 index 0000000..b1ebd91 --- /dev/null +++ b/src/libsrc/line.pla @@ -0,0 +1,113 @@ +var hspan, vspan +var err, shorterr, shortlen, longerr, longlen + +export def linespans(h, v)#0 + hspan = h + vspan = v +end +def majorline(ps, major, majorend, minor, dir, majorspan)#0 + // + // Initial half-span step + // + err = err + shorterr + repeat + majorspan(ps, major, minor)#0 + minor = minor + dir // Move to next span + ps = major + 1 // Start of next span = end of previous + 1 + if err >= 0 // Short span + err = err + shorterr + major = major + shortlen + else // Long span + err = err + longerr + major = major + longlen + fin + until major >= majorend + // + // Final half-span step + // + majorspan(ps, majorend, minor)#0 +end +export def line(x1, y1, x2, y2)#0 + var dx, dy, dx2, dy2, halflen, rem, sx, sy + + sx = 1 + sy = 1 + dx = x2 - x1 + if dx < 0 + sx = -1; dx = -dx + fin + dy = y2 - y1 + if dy < 0 + sy = -1; dy = -dy + fin + if dx >= dy + if sx < 0 + x1, x2 = x2, x1; sy = -sy + fin + if dy == 0 + hspan(x1, x2, y1)#0; return + fin + // + // Half-span length and error + // + dy2 = dy * 2 + halflen, rem = divmod(dx, dy2) + err = dy2 - rem + // + // Long-span length = half-span length * 2 + // + longlen = (halflen + 1) * 2 + longerr = err * 2 + if longerr >= dy2 + longerr = longerr - dy2 + longlen-- + fin + // + // Short-span length = long-span length - 1 + // + shortlen = longlen - 1 + shorterr = longerr - dy2 + // + // Initial half-span step + // + err = err + shorterr + ps = x1 + x1 = x1 + halflen + // + // JIT optimize inner loop + // + majorline(x1, x1 + halflen, x2, y1, sy, hspan) + // + // Final half-span step + // + hspan(ps, x2, y2)#0 + else + if sy < 0 + x1, x2 = x2, x1; sx = -sx + fin + if dx == 0 + vspan(y1, y2, x1)#0; return + fin + // + // Half-span length and error + // + dx2 = dx * 2 + halflen, rem = divmod(dy, dx2) + err = dx2 - rem + // + // Long-span length = half-span length * 2 + // + longlen = (halflen + 1) * 2 + longerr = err * 2 + if longerr >= dx2 + longerr = longerr - dx2 + longlen-- + fin + shortlen = longlen - 1 + shorterr = longerr - dx2 + // + // JIT optimize inner loop + // + majorline(y1, y1 + halflen, y2, x1, sx, vspan) + fin +end diff --git a/src/makefile b/src/makefile index 9699cf1..b245a4f 100755 --- a/src/makefile +++ b/src/makefile @@ -57,6 +57,7 @@ ROGUEMAP = rel/ROGUEMAP\#FE1000 ROGUECOMBAT= rel/ROGUECOMBAT\#FE1000 MON = rel/apple/MON\#FE1000 DGRTEST = rel/apple/DGRTEST\#FE1000 +HGRTEST = rel/apple/HGRTEST\#FE1000 MEMMGR = rel/MEMMGR\#FE1000 MEMTEST = rel/MEMTEST\#FE1000 FIBERTEST = rel/FIBERTEST\#FE1000 @@ -86,7 +87,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(DGR) $(DGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(DGR) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc c64: $(PLVMZP_C64) $(PLASM) $(PLVM) $(PLVMC64) @@ -384,6 +385,10 @@ $(DGRTEST): samplesrc/dgrtest.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/dgrtest.pla > samplesrc/dgrtest.a acme --setpc 4094 -o $(DGRTEST) samplesrc/dgrtest.a +$(HGRTEST): samplesrc/hgrtest.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < samplesrc/hgrtest.pla > samplesrc/hgrtest.a + acme --setpc 4094 -o $(HGRTEST) samplesrc/hgrtest.a + $(MON): samplesrc/mon.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/mon.pla > samplesrc/mon.a acme --setpc 4094 -o $(MON) samplesrc/mon.a diff --git a/src/samplesrc/hgr1test.pla b/src/samplesrc/hgr1test.pla index 97ace56..be149cc 100644 --- a/src/samplesrc/hgr1test.pla +++ b/src/samplesrc/hgr1test.pla @@ -93,9 +93,140 @@ word = $02D0,$06D0,$0AD0,$0ED0,$12D0,$16D0,$1AD0,$1ED0 word = $0350,$0750,$0B50,$0F50,$1350,$1750,$1B50,$1F50 word = $03D0,$07D0,$0BD0,$0FD0,$13D0,$17D0,$1BD0,$1FD0 word hcolor[] = $0000,$552A,$2A55,$7F7F,$8080,$D5AA,$AAD5,$FFFF - +word hmask = $8081,$8082,$8084,$8088,$8090,$80A0,$80C0 + = $8180,$8280,$8480,$8880,$9080,$A080,$C080 +word curhclr word ball0[9] = $0000, $1800, $3C00, $7E00, $7E00, $3C00, $1800, $0000 +var hspan, vspan +export def spans(h, v)#0 + hspan = h + vspan = v +end +export def line(x1, y1, x2, y2)#0 + var dx2, dy2, err, sx, sy, ps + var shorterr, shortlen, longerr, longlen, halflen + + sx = sy = 1 + dx2 = (x2 - x1) * 2 + if dx2 < 0 + sx = -1; dx2 = -dx2 + fin + dy2 = (y2 - y1) * 2 + if dy2 < 0 + sy = -1; dy2 = -dy2 + fin + if dx2 >= dy2 + if sx < 0 + x1, x2 = x2, x1; sy = -sy + fin + if dy2 == 0 + hspan(x1, x2, y1)#0; return + fin + ps = x1 + for err = dy2 - dx2 / 2 to 0 step dy2 // Find first half-span length and error + x1++ + next + longlen = (x1 - ps + 1) * 2 // Long-span length = half-span length * 2 + longerr = err * 2 + if longerr >= dy2 + longerr = longerr - dy2 + longlen-- + fin + shortlen = longlen - 1 // Short-span length = long-span length - 1 + shorterr = longerr - dy2 + err = err + shorterr // Do a short-span step + while x1 < x2 + hspan(ps, x1, y1)#0 + y1 = y1 + sy // Move to next span + ps = x1 + 1 // Start of next span = end of previous span + 1 + if err >= 0 // Short span + err = err + shorterr + x1 = x1 + shortlen + else // Long span + err = err + longerr + x1 = x1 + longlen + fin + loop + hspan(ps, x2, y2)#0 // Final span + else + if sy < 0 + x1, x2 = x2, x1; sx = -sx + fin + if dx2 == 0 + vspan(x1, y1, y2)#0; return + fin + ps = y1 + for err = dx2 - dy2 / 2 to 0 step dx2 // Find first half-span length and error + y1++ + next + longlen = (y1 - ps + 1) * 2 + longerr = err * 2 + if longerr >= dx2 + longerr -= longerr - dx2 + longlen-- + fin + shortlen = longlen - 1 + shorterr = longerr - dx2 + err = err + shorterr + while y1 < y2 + vspan(x1, ps, y1)#0 + x1 = x1 + sx + ps = y1 + 1 + if err >= 0 // Short span + err = err + shorterr + y1 = y1 + shortlen + else // Long span + err = err + longerr + y1 = y1 + longlen + fin + loop + vspan(x2, ps, y2)#0 // Final span + fin +end +def hgrPlot(x, y)#0 + var pscan, bytofst, pixofst, pmask, pword + + pscan = hgrscan[y] | hgr1 + wrdofst, pixofst = divmod(x, 14) + pmask = hmask[pixofst] + pword = pscan=>[wrdofst] & ~pmask + pscan=>[wrdofst] = pword | (curhclr & pmask) +end +def hgrHlin(x1, x2, y)#0 + var pscan, bytofst, pixofst, pmask, pword + + pscan = hgrscan[y] | hgr1 + wrdofst, pixofst = divmod(x1, 14) + repeat + pmask = hmask[pixofst] + pword = pscan=>[wrdofst] & ~pmask + pscan=>[wrdofst] = pword | (curhclr & pmask) + pixofst++ + if pixofst > 13 + pixofst = 0 + wrdofst++ + fin + x1++ + until x1 > x2 +end +def hgrVlin(x, y1, y2)#0 + var pscan, bytofst, pixofst, pmask, pword, cmask + + wrdofst, pixofst = divmod(x, 14) + pmask = hmask[pixofst] + cmask = curhclr & pmask + pmask = ~pmask + repeat + pscan = hgrscan[y1] | hgr1 + pword = pscan=>[wrdofst] & pmask + pscan=>[wrdofst] = pword | cmask + y1++ + until y1 > y2 +end +def hgrColor(c)#0 + curhclr = hcolor[c & 0x07] +end def hgrBLT(page, x, y, w, h, pSrc)#0 word pDst byte i @@ -110,11 +241,21 @@ def hgrBLT(page, x, y, w, h, pSrc)#0 h-- until not h end +def testline + var i + + spans(@hgrHlin, @hgrVlin) + hgrColor(7) + for i = 0 to 100 + hgrPlot(i, i) + next +end memset(hgr1, 0, $2000) // Clear HGR page 1 ^showpage1 ^showfull ^showhires ^showgraphics +testline hgrBlt(hgrpage[0], 20, 100, 2, 8, @ball0) getc ^showpage1 diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla new file mode 100644 index 0000000..1d48881 --- /dev/null +++ b/src/samplesrc/hgrtest.pla @@ -0,0 +1,300 @@ +include "inc/cmdsys.plh" +sysflags reshgr1 // Reserve HGR page 1 +// +// Hardware addresses +// +const showgraphics = $C050 +const showtext = $C051 +const showfull = $C052 +const showmix = $C053 +const showpage1 = $C054 +const showpage2 = $C055 +const showlores = $C056 +const showhires = $C057 +const keyboard = $C000 +const keystrobe = $C010 +const hgr1 = $2000 +const hgr2 = $4000 +const page1 = 0 +const page2 = 1 +word hgrpage[] = hgr1, hgr2 +word hgrscan[] = $0000,$0400,$0800,$0C00,$1000,$1400,$1800,$1C00 +word = $0080,$0480,$0880,$0C80,$1080,$1480,$1880,$1C80 +word = $0100,$0500,$0900,$0D00,$1100,$1500,$1900,$1D00 +word = $0180,$0580,$0980,$0D80,$1180,$1580,$1980,$1D80 +word = $0200,$0600,$0A00,$0E00,$1200,$1600,$1A00,$1E00 +word = $0280,$0680,$0A80,$0E80,$1280,$1680,$1A80,$1E80 +word = $0300,$0700,$0B00,$0F00,$1300,$1700,$1B00,$1F00 +word = $0380,$0780,$0B80,$0F80,$1380,$1780,$1B80,$1F80 +word = $0028,$0428,$0828,$0C28,$1028,$1428,$1828,$1C28 +word = $00A8,$04A8,$08A8,$0CA8,$10A8,$14A8,$18A8,$1CA8 +word = $0128,$0528,$0928,$0D28,$1128,$1528,$1928,$1D28 +word = $01A8,$05A8,$09A8,$0DA8,$11A8,$15A8,$19A8,$1DA8 +word = $0228,$0628,$0A28,$0E28,$1228,$1628,$1A28,$1E28 +word = $02A8,$06A8,$0AA8,$0EA8,$12A8,$16A8,$1AA8,$1EA8 +word = $0328,$0728,$0B28,$0F28,$1328,$1728,$1B28,$1F28 +word = $03A8,$07A8,$0BA8,$0FA8,$13A8,$17A8,$1BA8,$1FA8 +word = $0050,$0450,$0850,$0C50,$1050,$1450,$1850,$1C50 +word = $00D0,$04D0,$08D0,$0CD0,$10D0,$14D0,$18D0,$1CD0 +word = $0150,$0550,$0950,$0D50,$1150,$1550,$1950,$1D50 +word = $01D0,$05D0,$09D0,$0DD0,$11D0,$15D0,$19D0,$1DD0 +word = $0250,$0650,$0A50,$0E50,$1250,$1650,$1A50,$1E50 +word = $02D0,$06D0,$0AD0,$0ED0,$12D0,$16D0,$1AD0,$1ED0 +word = $0350,$0750,$0B50,$0F50,$1350,$1750,$1B50,$1F50 +word = $03D0,$07D0,$0BD0,$0FD0,$13D0,$17D0,$1BD0,$1FD0 +word hcolor[] = $0000,$552A,$2A55,$7F7F,$8080,$D5AA,$AAD5,$FFFF +word hmask = $8081,$8082,$8084,$8088,$8090,$80A0,$80C0 +word = $8180,$8280,$8480,$8880,$9080,$A080,$C080 +byte hbmask = $81,$82,$84,$88,$90,$A0,$C0 +byte hlmask = $FF,$FE,$FC,$F8,$F0,$E0,$C0 +byte hrmask = $81,$83,$87,$8F,$9F,$BF,$FF +word curhclr +word ball0[9] = $0000, $1800, $3C00, $7E00, $7E00, $3C00, $1800, $0000 + +var pixel, hspan, vspan +var err, shorterr, shortlen, longerr, longlen +var dx2, dy2, sx, sy + +export def linefuncs(p, h, v)#0 + pixel = p + hspan = h + vspan = v +end +def phline(x1, x2, y)#0 + var x + + if sx < 0 + sy = -sy; x1, x2 = x2, x1 + fin + err = dy2 - dx2 / 2 + for x = x1 to x2 + pixel(x, y)#0 + if err >= 0 + err = err - dx2 + y = y + sy + fin + err = err + dy2 + next +end +def pvline(y1, y2, x)#0 + var y + + if sy < 0 + sx = -sx; y1, y2 = y2, y1 + fin + err = dx2 - dy2 / 2 + for y = y1 to y2 + pixel(x, y)#0 + if err >= 0 + err = err - dy2 + x = x + sx + fin + err = err + dx2 + next +end +def pline(x1, y1, x2, y2)#0 + sx = 1 + sy = 1 + dx2 = (x2 - x1) * 2 + if dx2 < 0 + sx = -1; dx2 = -dx2 + fin + dy2 = (y2 - y1) * 2 + if dy2 < 0 + sy = -1; dy2 = -dy2 + fin + if dx2 >= dy2 + phline(x1, x2, y1) + else + pvline(y1, y2, x1) + fin +end +def majorline(ps, major, majorend, minor, dir, majorspan)#0 + // + // Initial half-span step + // + err = err + shorterr + repeat + majorspan(ps, major, minor)#0 + minor = minor + dir // Move to next span + ps = major + 1 // Start of next span = end of previous + 1 + if err >= 0 // Short span + err = err + shorterr + major = major + shortlen + else // Long span + err = err + longerr + major = major + longlen + fin + until major >= majorend + // + // Final half-span step + // + majorspan(ps, majorend, minor)#0 +end +export def sline(x1, y1, x2, y2)#0 + var dx, dy, dx2, dy2, halflen, rem, sx, sy + + sx = 1 + sy = 1 + dx = x2 - x1 + if dx < 0 + sx = -1; dx = -dx + fin + dy = y2 - y1 + if dy < 0 + sy = -1; dy = -dy + fin + if dx >= dy + if sx < 0 + x1, x2 = x2, x1; sy = -sy + fin + if dy == 0 + hspan(x1, x2, y1)#0; return + fin + // + // Half-span length and error + // + dy2 = dy * 2 + halflen, rem = divmod(dx, dy2) + err = dy2 - rem + // + // Long-span length = half-span length * 2 + // + longlen = (halflen + 1) * 2 + longerr = err * 2 + if longerr >= dy2 + longerr = longerr - dy2 + longlen-- + fin + // + // Short-span length = long-span length - 1 + // + shortlen = longlen - 1 + shorterr = longerr - dy2 + // + // JIT optimize inner loop + // + majorline(x1, x1 + halflen, x2, y1, sy, hspan) + else + if sy < 0 + x1, x2 = x2, x1; sx = -sx + fin + if dx == 0 + vspan(y1, y2, x1)#0; return + fin + // + // Half-span length and error + // + dx2 = dx * 2 + halflen, rem = divmod(dy, dx2) + err = dx2 - rem + // + // Long-span length = half-span length * 2 + // + longlen = (halflen + 1) * 2 + longerr = err * 2 + if longerr >= dx2 + longerr = longerr - dx2 + longlen-- + fin + shortlen = longlen - 1 + shorterr = longerr - dx2 + // + // JIT optimize inner loop + // + majorline(y1, y1 + halflen, y2, x1, sx, vspan) + fin +end + +def hgrPlot(x, y)#0 + word pptr + byte ofst, pixofst, pmask + + ofst, pixofst = divmod(x, 7) + pptr = (hgrscan[y] | hgr1) + ofst + pmask = hbmask[pixofst] + ^pptr = (^pptr & ~pmask) | (curhclr.[ofst & 1] & pmask) +end +def hgrHlin(x1, x2, y)#0 + word pptr, x + byte lofst, lpixofst, lpmask, clr + byte rofst, rpixofst, rpmask + + if x1 == x2 + hgrPlot(x1, y) + else + lofst, lpixofst = divmod(x1, 7) + pptr = (hgrscan[y] | hgr1) + lofst + rofst, rpixofst = divmod(x2, 7) + lpmask = hlmask[lpixofst] + rpmask = hrmask[rpixofst] + if lofst == rofst + lpmask = lpmask & rpmask + ^pptr = (^pptr & ~lpmask) | (curhclr.[pptr.0 & 1] & lpmask) + else + ^pptr = (^pptr & ~lpmask) | (curhclr.[pptr.0 & 1] & lpmask) + pptr++ + for x = lofst + 1 to rofst - 1 + ^pptr = curhclr.[pptr.0 & 1] + pptr++ + next + ^pptr = (^pptr & ~rpmask) | (curhclr.[pptr.0 & 1] & rpmask) + fin + fin +end +def hgrVlin(y1, y2, x)#0 + word pptr, y + byte ofst, pixofst, pmask, cmask + + ofst, pixofst = divmod(x, 7) + pmask = hbmask[pixofst] + cmask = curhclr.[ofst & 1] & pmask + pmask = ~pmask + for y = y1 to y2 + pptr = (hgrscan[y] | hgr1) + ofst + ^pptr = (^pptr & pmask) | cmask + next +end +def hgrColor(c)#0 + curhclr = hcolor[c & $07] +end +def hgrBLT(page, x, y, w, h, pSrc)#0 + word pDst + byte i + + repeat + pDst = hgrscan[y] | page + x + for i = 0 to w - 1 + pDst->[i] = pSrc->[i] + next + pSrc = pSrc + w + y++ + h-- + until not h +end +def testline#0 + var i + + linefuncs(@hgrPlot, @hgrHlin, @hgrVlin) + hgrColor(3) + for i = 0 to 191 + pline(0, 0, i, 191) + pline(0, 0, 191, i) + next + hgrColor(0); + for i = 0 to 191 + sline(0, 0, i, 191) + sline(0, 0, 191, i) + next +end +memset(hgr1, 0, $2000) // Clear HGR page 1 +^showpage1 +^showfull +^showhires +^showgraphics +testline +hgrBlt(hgrpage[0], 20, 100, 2, 8, @ball0) +getc +^showpage1 +^showtext +done From 04139858fc1aad0776c16623029a28574d691c4c Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Wed, 18 Dec 2019 21:48:52 -0800 Subject: [PATCH 053/149] WIP for graphics libraries --- src/inc/dgr.plh | 27 ++- src/inc/linespans.plh | 4 + src/libsrc/apple/dgr.pla | 188 ++++++++---------- src/libsrc/{line.pla => linespans.pla} | 25 +-- src/makefile | 7 +- src/mkrel | 7 +- src/samplesrc/dgrtest.pla | 16 +- src/samplesrc/hgr1test.pla | 263 ------------------------- src/samplesrc/hgrtest.pla | 221 ++++++--------------- 9 files changed, 197 insertions(+), 561 deletions(-) create mode 100644 src/inc/linespans.plh rename src/libsrc/{line.pla => linespans.pla} (80%) delete mode 100644 src/samplesrc/hgr1test.pla diff --git a/src/inc/dgr.plh b/src/inc/dgr.plh index 0449a16..57106dc 100644 --- a/src/inc/dgr.plh +++ b/src/inc/dgr.plh @@ -1,16 +1,25 @@ import dgr word[] dgrbuff - predef dgrPlot(buff, x, y)#0 - predef dgrHLin(buff, x1, x2, y)#0 - predef dgrVLin(buff, x, y1, y2)#0 - predef dgrBLT(buff, x, y, width, height, src)#0 - predef dgrTile(buff, x, y, src)#0 - predef dgrTileStr(buff, x, y, tilestr, strlen, tilebuff)#0 - predef dgrFill(buff, x, y, tile)#0 + predef dgrPlotBuf(x, y, bufptr)#0 + predef dgrHLinBuf(x1, x2, y, bufptr)#0 + predef dgrVLinBuf(x, y1, y2, bufptr)#0 + predef dgrBLTBuf(bufptr, x, y, width, height, src)#0 + predef dgrTileBuf(bufptr, x, y, src)#0 + predef dgrTileStrBuf(bufptr, x, y, tilestr, strlen, tilebuff)#0 + predef dgrFillBuf(bufptr, x, y, tile)#0 predef dgrMode#1 predef txtMode#0 predef dgrShow(page)#1 + predef dgrSwap#0 + predef dgrDrawBuf(page)#0 + predef dgrClearBuf(bufptr, clr)#0 + predef dgrClear(clr)#0 + predef dgrPlot(x, y)#0 predef dgrColor(clr)#0 - predef dgrLine(buff, x1, y1, x2, y2)#0 - predef dgrClear(buff, clr)#0 + predef dgrHLin(x1, x2, y)#0 + predef dgrVLin(y1, y2, x)#0 + predef dgrBLT(x, y, width, height, src)#0 + predef dgrTile(x, y, src)#0 + predef dgrTileStr(x, y, tilestr, strlen, tilebuff)#0 + predef dgrFill(x, y, tile)#0 end diff --git a/src/inc/linespans.plh b/src/inc/linespans.plh new file mode 100644 index 0000000..3145d3f --- /dev/null +++ b/src/inc/linespans.plh @@ -0,0 +1,4 @@ +import linespans + predef setlinespans(h, v)#0 + predef linetospans(x1, y1, x2, y2)#0 +end diff --git a/src/libsrc/apple/dgr.pla b/src/libsrc/apple/dgr.pla index d76d49e..a0063dd 100755 --- a/src/libsrc/apple/dgr.pla +++ b/src/libsrc/apple/dgr.pla @@ -31,6 +31,8 @@ word[] dgr2rows = $0800,$0880,$0900,$0980,$0A00,$0A80,$0B00,$0B80 word = $0828,$08A8,$0928,$09A8,$0A28,$0AA8,$0B28,$0BA8 word = $0850,$08D0,$0950,$09D0,$0A50,$0AD0,$0B50,$0BD0 export word[] dgrbuff = @dgr1rows, @dgr2rows +word drawbufptr +byte drawpage // // Color mapping. // @@ -49,7 +51,7 @@ end // // Plot pixel // -export asm dgrPlot(buff, x, y)#0 +export asm dgrPlotBuf(bufptr, x, y)#0 ; GET BUFFER ADDRESS STX ESP LDA ESTKL+2,X @@ -82,16 +84,23 @@ end // // Plot horizontal row of pixels // -export asm dgrHLin(buff, x1, x2, y)#0 +export asm dgrHLin(x1, x2, y)#0 + DEX + LDA $3000 + STA ESTKL,X + LDA $3001 + STA ESTKH,X +end +export asm dgrHLinBuf(x1, x2, y, bufptr)#0 ; GET BUFFER ADDRESS STX ESP - LDA ESTKL+3,X + LDA ESTKL,X STA SRCL - LDA ESTKH+3,X + LDA ESTKH,X STA SRCH - LDA ESTKL+1,X ; X2 COORD + LDA ESTKL+2,X ; X2 COORD STA TMPH - LDA ESTKL,X ; Y COORD + LDA ESTKL+1,X ; Y COORD AND #$FE TAY LDA (SRC),Y @@ -99,10 +108,10 @@ export asm dgrHLin(buff, x1, x2, y)#0 INY LDA (SRC),Y STA GBASH - LDY ESTKL+2,X ; X1 COORD + LDY ESTKL+3,X ; X1 COORD PHP SEI -- LDA ESTKL,X +- LDA ESTKL+1,X ; Y COORD LSR TYA LDX GCLR ; COLOR @@ -110,8 +119,8 @@ end asm _dgrHLinPix JSR $3000 ; _dgrSetPix LDX ESP - INC ESTKL+2,X ; X1 COORD - LDY ESTKL+2,X + INC ESTKL+3,X ; X1 COORD + LDY ESTKL+3,X CPY TMPH ; X2 COORD BCC - BEQ - @@ -125,14 +134,21 @@ end // // Plot horizontal row of pixels // -export asm dgrVLin(buff, x, y1, y2)#0 +export asm dgrVLin(y1, y2, x)#0 + DEX + LDA $3000 + STA ESTKL,X + LDA $3001 + STA ESTKH,X +end +export asm dgrVLinBuf(y1, y2, x, bufptr)#0 ; GET BUFFER ADDRESS STX ESP - LDA ESTKL+3,X + LDA ESTKL,X STA SRCL - LDA ESTKH+3,X + LDA ESTKH,X STA SRCH - LDA ESTKL+1,X ; Y1 COORD + LDA ESTKL+3,X ; Y1 COORD PHP SEI - AND #$FE @@ -142,17 +158,17 @@ export asm dgrVLin(buff, x, y1, y2)#0 INY LDA (SRC),Y STA GBASH - LDA ESTKL+1,X + LDA ESTKL+3,X LSR - LDA ESTKL+2,X ; X COORD + LDA ESTKL+1,X ; X COORD LDX GCLR ; COLOR end asm _dgrVLinPix JSR $3000 ; _dgrSetPix LDX ESP - INC ESTKL+1,X ; Y1 COORD - LDA ESTKL+1,X - CMP ESTKL,X ; Y2 COORD + INC ESTKL+3,X ; Y1 COORD + LDA ESTKL+3,X + CMP ESTKL+2,X ; Y2 COORD BCC - BEQ - PLP @@ -165,7 +181,7 @@ end // // Draw sprite // -export asm dgrBLT(buff, x, y, width, height, src)#0 +export asm dgrBLTBuf(bufptr, x, y, width, height, src)#0 LDA ESTKL,X ; SPRITE STA SRCL LDA ESTKH,X @@ -326,7 +342,7 @@ end // // Draw 8x8 tile (forced to 2x2 block address) // -export asm dgrTile(buff, x, y, src)#0 +export asm dgrTileBuf(bufptr, x, y, src)#0 STX ESP LDA ESTKL,X ; TILE STA SRCL @@ -413,7 +429,7 @@ end // // Draw a string of tiles // -export asm dgrTileStr(buff, x, y, tilestr, strlen, tilebuff)#0 +export asm dgrTileStrBuf(bufptr, x, y, tilestr, strlen, tilebuff)#0 - DEX DEX DEX @@ -450,7 +466,7 @@ end // // Fill a buffer with tiles // -export asm dgrFill(buff, x, y, tile)#0 +export asm dgrFillBuf(bufptr, x, y, tile)#0 LDA ESTKL+2,X AND #$0F STA ESTKL+2,X @@ -526,6 +542,8 @@ export def dgrMode#1 ^ena80 = 0 ^show80 = 0 ^an3on + drawpage = 1 + drawbufptr = dgrbuff[1] return 1 end // @@ -548,6 +566,15 @@ export def dgrShow(page)#1 ^(showpage1 + page) return page ^ 1 end +export def dgrSwap#0 + ^(showpage1 + drawpage) + drawpage = drawpage ^ 1 + drawbufptr = dgrbuff[drawpage] +end +export def dgrDrawBuf(page)#0 + drawpage = page + drawbufptr = dgrbuff[drawpage] +end // // Set color for clear & plot routines // @@ -555,89 +582,39 @@ export def dgrColor(clr)#0 ^$30 = clr & $0F end // -// Draw line -// -export def dgrLine(buff, x1, y1, x2, y2)#0 - byte dx, dy, dx2, dy2, pp - word sx, sy, err, dd2 - - if x1 < x2 - sx = 1 - dx = x2 - x1 - else - sx = -1 - dx = x1 - x2 - fin - if y1 < y2 - sy = 1 - dy = y2 - y1 - else - sy = -1 - dy = y1 - y2 - fin - dx2 = dx << 1 - dy2 = dy << 1 - if dx >= dy // Horizontal line - if sx < 0 - x1, x2 = x2, x1 - y1, y2 = y2, y1 - sy = -sy - fin - dd2 = dx2 - dy2 - err = dx - dy2 - sx = 1 - while dy - if err < 0 - dgrHLin(buff, x1, x1 + sx - 1, y1) - x1 = x1 + sx - y1 = y1 + sy - sx = 1 - dy-- - err = err + dd2 - else - sx++ - err = err - dy2 - fin - loop - if y2 == y1 - dgrHLin(buff, x1, x2, y1) - fin - else // Vertical line - if sy < 0 - x1, x2 = x2, x1 - y1, y2 = y2, y1 - sx = -sx - fin - dd2 = dy2 - dx2 - err = dy - dx2 - sy = 1 - while dx - if err < 0 - dgrVLin(buff, x1, y1, y1 + sy - 1) - x1 = x1 + sx - y1 = y1 + sy - sy = 1 - dx-- - err = err + dd2 - else - sy++ - err = err - dx2 - fin - loop - if x2 == x1 - dgrVLin(buff, x1, y1, y2) - fin - fin -end -// // Clear the buffer // -export def dgrClear(buff, clr)#0 +export def dgrClearBuf(bufptr, clr)#0 byte[32] clrtile clr = evnclr[clr&$0F] | (oddclr[clr&$0F] << 8) memset(@clrtile, clr, 32) - dgrFill(buff, 0, 0, @clrtile) + dgrFillBuf(bufptr, 0, 0, @clrtile) +end +export def dgrClear(clr)#0 + byte[32] clrtile + + clr = evnclr[clr&$0F] | (oddclr[clr&$0F] << 8) + memset(@clrtile, clr, 32) + dgrFillBuf(drawbufptr, 0, 0, @clrtile) +end +// +// Draw functions +// +export def dgrPlot(x, y)#0 + dgrPlotBuf(drawbufptr, x, y) +end +export def dgrBLT(x, y, width, height, src)#0 + dgrBLTBuf(drawbufptr, x, y, width, height, src) +end +export def dgrTile(x, y, src)#0 + dgrTileBuf(drawbufptr, x, y, src) +end +export def dgrTileStr(x, y, tilestr, strlen, tilebuff)#0 + dgrTileStrBuf(drawbufptr, x, y, tilestr, strlen, tilebuff) +end +export def dgrFill(x, y, tile)#0 + dgrFillBuf(drawbufptr, x, y, tile) end // // Make sure we are a 128K //e or //c @@ -655,12 +632,19 @@ _dgrPlotPix:1 = @_dgrSetPix _dgrHLinPix:1 = @_dgrSetPix _dgrVLinPix:1 = @_dgrSetPix _dgrBLTPix:1 = @_dgrSetPix -_dgrTileTile:1 = @dgrTile -_dgrFillTile:1 = @dgrTile +_dgrTileTile:1 = @dgrTileBuf +_dgrFillTile:1 = @dgrTileBuf _dgrSetEvnEvn:1 = @evnclr _dgrSetEvnOdd:1 = @oddclr _dgrSetOddEvn:1 = @evnclr _dgrSetOddOdd:1 = @oddclr +// +// Fixups for drawbufptr +// +dgrHLin:2 = @drawbufptr +dgrHLin:7 = @drawbufptr+1 +dgrVLin:2 = @drawbufptr +dgrVLin:7 = @drawbufptr+1 // Put read AUX mem routine in scary location memcpy($0100, @auxRead, 9) done diff --git a/src/libsrc/line.pla b/src/libsrc/linespans.pla similarity index 80% rename from src/libsrc/line.pla rename to src/libsrc/linespans.pla index b1ebd91..d63ba80 100644 --- a/src/libsrc/line.pla +++ b/src/libsrc/linespans.pla @@ -1,19 +1,20 @@ +include "inc/cmdsys.plh" var hspan, vspan var err, shorterr, shortlen, longerr, longlen -export def linespans(h, v)#0 +export def setlinespans(h, v)#0 hspan = h vspan = v end -def majorline(ps, major, majorend, minor, dir, majorspan)#0 +def majorline(majorstart, major, majorend, minor, dir, majorspan)#0 // // Initial half-span step // err = err + shorterr repeat - majorspan(ps, major, minor)#0 - minor = minor + dir // Move to next span - ps = major + 1 // Start of next span = end of previous + 1 + majorspan(majorstart, major, minor)#0 + minor = minor + dir // Move to next span + majorstart = major + 1 // Start of next span = end of previous + 1 if err >= 0 // Short span err = err + shorterr major = major + shortlen @@ -25,9 +26,9 @@ def majorline(ps, major, majorend, minor, dir, majorspan)#0 // // Final half-span step // - majorspan(ps, majorend, minor)#0 + majorspan(majorstart, majorend, minor)#0 end -export def line(x1, y1, x2, y2)#0 +export def linetospans(x1, y1, x2, y2)#0 var dx, dy, dx2, dy2, halflen, rem, sx, sy sx = 1 @@ -68,19 +69,9 @@ export def line(x1, y1, x2, y2)#0 shortlen = longlen - 1 shorterr = longerr - dy2 // - // Initial half-span step - // - err = err + shorterr - ps = x1 - x1 = x1 + halflen - // // JIT optimize inner loop // majorline(x1, x1 + halflen, x2, y1, sy, hspan) - // - // Final half-span step - // - hspan(ps, x2, y2)#0 else if sy < 0 x1, x2 = x2, x1; sx = -sx diff --git a/src/makefile b/src/makefile index b245a4f..417399e 100755 --- a/src/makefile +++ b/src/makefile @@ -48,6 +48,7 @@ DHCP = rel/DHCP\#FE1000 HTTPD = rel/HTTPD\#FE1000 TFTPD = rel/TFTPD\#FE1000 DGR = rel/apple/DGR\#FE1000 +LINESPANS = rel/apple/LINESPANS\#FE1000 GRAFIX = rel/apple/GRAFIX\#FE1000 GFXDEMO = rel/apple/GFXDEMO\#FE1000 JOYBUZZ = rel/apple/JOYBUZZ\#FE1000 @@ -87,7 +88,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(DGR) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(DGR) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc c64: $(PLVMZP_C64) $(PLASM) $(PLVM) $(PLVMC64) @@ -213,6 +214,10 @@ $(FIBER): libsrc/fiber.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/fiber.pla > libsrc/fiber.a acme --setpc 4094 -o $(FIBER) libsrc/fiber.a +$(LINESPANS): libsrc/linespans.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < libsrc/linespans.pla > libsrc/linespans.a + acme --setpc 4094 -o $(LINESPANS) libsrc/linespans.a + $(FIBERTEST): samplesrc/fibertest.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/fibertest.pla > samplesrc/fibertest.a acme --setpc 4094 -o $(FIBERTEST) samplesrc/fibertest.a diff --git a/src/mkrel b/src/mkrel index b9c750e..4669219 100755 --- a/src/mkrel +++ b/src/mkrel @@ -9,6 +9,7 @@ rm -rf prodos/sys mkdir prodos/sys cp rel/apple/FILEIO#FE1000 prodos/sys/FILEIO.REL cp rel/apple/CONIO#FE1000 prodos/sys/CONIO.REL +cp rel/apple/LINESPANS#FE1000 prodos/sys/LINESPANS.REL cp rel/apple/DGR#FE1000 prodos/sys/DGR.REL cp rel/ARGS#FE1000 prodos/sys/ARGS.REL cp rel/ED#FE1000 prodos/sys/ED.REL @@ -54,7 +55,8 @@ cp ../sysfiles/ELEMS.CODE#060000 prodos/fpsos/sys/ELEMS.CODE.BIN rm -rf prodos/demos mkdir prodos/demos cp rel/apple/DGRTEST#FE1000 prodos/demos/DGRTEST.REL -cp rel/apple/ROD#FE1000 prodos/demos/ROD.REL +cp rel/apple/HGRTEST#FE1000 prodos/demos/HGRTEST.REL +cp rel/apple/ROD#FE1000 prodos/demos/ROD.REL cp rel/RPNCALC#FE1000 prodos/demos/RPNCALC.REL cp rel/LZ4CAT#FE1000 prodos/demos/LZ4CAT.REL cp rel/PRIMEGAP#FE1000 prodos/demos/PRIMEGAP.REL @@ -97,7 +99,7 @@ cp rel/CODEOPT#FE1000 prodos/bld/CODEOPT.REL mkdir prodos/bld/samples cp samplesrc/hello.pla prodos/bld/samples/HELLO.PLA.TXT cp samplesrc/dgrtest.pla prodos/bld/samples/DGRTEST.PLA.TXT -cp samplesrc/hgr1test.pla prodos/bld/samples/HGR1TEST.PLA.TXT +cp samplesrc/hgrtest.pla prodos/bld/samples/HGRTEST.PLA.TXT cp samplesrc/fibertest.pla prodos/bld/samples/FIBERTEST.PLA.TXT cp samplesrc/mousetest.pla prodos/bld/samples/MOUSETEST.PLA.TXT cp samplesrc/mon.pla prodos/bld/samples/MON.PLA.TXT @@ -135,6 +137,7 @@ mkdir prodos/bld/inc cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT cp inc/cmdsys.plh prodos/bld/inc/CMDSYS.PLH.TXT cp inc/conio.plh prodos/bld/inc/CONIO.PLH.TXT +cp inc/linespans.plh prodos/bld/inc/LINESPANS.PLH.TXT cp inc/dgr.plh prodos/bld/inc/DGR.PLH.TXT cp inc/fiber.plh prodos/bld/inc/FIBER.PLH.TXT cp inc/fileio.plh prodos/bld/inc/FILEIO.PLH.TXT diff --git a/src/samplesrc/dgrtest.pla b/src/samplesrc/dgrtest.pla index d3412c6..41ffdb4 100644 --- a/src/samplesrc/dgrtest.pla +++ b/src/samplesrc/dgrtest.pla @@ -1,4 +1,5 @@ include "inc/dgr.plh" +include "inc/linespans.plh" byte[] sprite1 = $80,$80,$00,$00,$00,$00,$80,$80 byte[] = $80,$00,$0A,$0A,$0A,$0A,$00,$80 @@ -22,26 +23,29 @@ def dgrTest#0 word i, j, ii, ij b = dgrMode() + dgrDrawBuf(0) for k = 15 downto 0 - dgrClear(dgrbuff[0], k) + dgrClear(k) next + setlinespans(@dgrHLin, @dgrVLin) for l = 0 to 79 dgrColor(l) - dgrLine(dgrbuff[0], 0, 0, l, 47) + linetospans(0, 0, l, 47) next for l = 47 downto 0 dgrColor(l) - dgrLine(dgrbuff[0], 0, 0, 79, l) + linetospans(0, 0, 79, l) next ii = 2 ij = -1 i = 40 j = 10 ^$C010 + dgrDrawBuf(1) while ^$C000 < 128 - dgrFill(dgrbuff[b], k, k, @tile1) - dgrBLT(dgrbuff[b], i, j, 8, 8, @sprite1) - b = dgrShow(b) + dgrFill(k, k, @tile1) + dgrBLT(i, j, 8, 8, @sprite1) + dgrSwap k++ i = i + ii if i < -3 or i > 75 diff --git a/src/samplesrc/hgr1test.pla b/src/samplesrc/hgr1test.pla deleted file mode 100644 index be149cc..0000000 --- a/src/samplesrc/hgr1test.pla +++ /dev/null @@ -1,263 +0,0 @@ -include "inc/cmdsys.plh" -sysflags reshgr1 // Reserve HGR page 1 - -// -// Hardware addresses -// -const speaker = $C030 -const showgraphics = $C050 -const showtext = $C051 -const showfull = $C052 -const showmix = $C053 -const showpage1 = $C054 -const showpage2 = $C055 -const showlores = $C056 -const showhires = $C057 -const keyboard = $C000 -const keystrobe = $C010 -const hgr1 = $2000 -const hgr2 = $4000 -const page1 = 0 -const page2 = 1 -word hgrpage[] = hgr1, hgr2 -byte hgradrl[] = $00,$00,$00,$00,$00,$00,$00,$00 -word = $80,$80,$80,$80,$80,$80,$80,$80 -word = $00,$00,$00,$00,$00,$00,$00,$00 -word = $80,$80,$80,$80,$80,$80,$80,$80 -word = $00,$00,$00,$00,$00,$00,$00,$00 -word = $80,$80,$80,$80,$80,$80,$80,$80 -word = $00,$00,$00,$00,$00,$00,$00,$00 -word = $80,$80,$80,$80,$80,$80,$80,$80 -word = $28,$28,$28,$28,$28,$28,$28,$28 -word = $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 -word = $28,$28,$28,$28,$28,$28,$28,$28 -word = $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 -word = $28,$28,$28,$28,$28,$28,$28,$28 -word = $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 -word = $28,$28,$28,$28,$28,$28,$28,$28 -word = $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 -word = $50,$50,$50,$50,$50,$50,$50,$50 -word = $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 -word = $50,$50,$50,$50,$50,$50,$50,$50 -word = $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 -word = $50,$50,$50,$50,$50,$50,$50,$50 -word = $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 -word = $50,$50,$50,$50,$50,$50,$50,$50 -word = $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 -byte hgradrh[] = $00,$04,$08,$0C,$10,$14,$18,$1C -word = $00,$04,$08,$0C,$10,$14,$18,$1C -word = $01,$05,$09,$0D,$11,$15,$19,$1D -word = $01,$05,$09,$0D,$11,$15,$19,$1D -word = $02,$06,$0A,$0E,$12,$16,$1A,$1E -word = $02,$06,$0A,$0E,$12,$16,$1A,$1E -word = $03,$07,$0B,$0F,$13,$17,$1B,$1F -word = $03,$07,$0B,$0F,$13,$17,$1B,$1F -word = $00,$04,$08,$0C,$10,$14,$18,$1C -word = $00,$04,$08,$0C,$10,$14,$18,$1C -word = $01,$05,$09,$0D,$11,$15,$19,$1D -word = $01,$05,$09,$0D,$11,$15,$19,$1D -word = $02,$06,$0A,$0E,$12,$16,$1A,$1E -word = $02,$06,$0A,$0E,$12,$16,$1A,$1E -word = $03,$07,$0B,$0F,$13,$17,$1B,$1F -word = $03,$07,$0B,$0F,$13,$17,$1B,$1F -word = $00,$04,$08,$0C,$10,$14,$18,$1C -word = $00,$04,$08,$0C,$10,$14,$18,$1C -word = $01,$05,$09,$0D,$11,$15,$19,$1D -word = $01,$05,$09,$0D,$11,$15,$19,$1D -word = $02,$06,$0A,$0E,$12,$16,$1A,$1E -word = $02,$06,$0A,$0E,$12,$16,$1A,$1E -word = $03,$07,$0B,$0F,$13,$17,$1B,$1F -word = $03,$07,$0B,$0F,$13,$17,$1B,$1F -word hgrscan[] = $0000,$0400,$0800,$0C00,$1000,$1400,$1800,$1C00 -word = $0080,$0480,$0880,$0C80,$1080,$1480,$1880,$1C80 -word = $0100,$0500,$0900,$0D00,$1100,$1500,$1900,$1D00 -word = $0180,$0580,$0980,$0D80,$1180,$1580,$1980,$1D80 -word = $0200,$0600,$0A00,$0E00,$1200,$1600,$1A00,$1E00 -word = $0280,$0680,$0A80,$0E80,$1280,$1680,$1A80,$1E80 -word = $0300,$0700,$0B00,$0F00,$1300,$1700,$1B00,$1F00 -word = $0380,$0780,$0B80,$0F80,$1380,$1780,$1B80,$1F80 -word = $0028,$0428,$0828,$0C28,$1028,$1428,$1828,$1C28 -word = $00A8,$04A8,$08A8,$0CA8,$10A8,$14A8,$18A8,$1CA8 -word = $0128,$0528,$0928,$0D28,$1128,$1528,$1928,$1D28 -word = $01A8,$05A8,$09A8,$0DA8,$11A8,$15A8,$19A8,$1DA8 -word = $0228,$0628,$0A28,$0E28,$1228,$1628,$1A28,$1E28 -word = $02A8,$06A8,$0AA8,$0EA8,$12A8,$16A8,$1AA8,$1EA8 -word = $0328,$0728,$0B28,$0F28,$1328,$1728,$1B28,$1F28 -word = $03A8,$07A8,$0BA8,$0FA8,$13A8,$17A8,$1BA8,$1FA8 -word = $0050,$0450,$0850,$0C50,$1050,$1450,$1850,$1C50 -word = $00D0,$04D0,$08D0,$0CD0,$10D0,$14D0,$18D0,$1CD0 -word = $0150,$0550,$0950,$0D50,$1150,$1550,$1950,$1D50 -word = $01D0,$05D0,$09D0,$0DD0,$11D0,$15D0,$19D0,$1DD0 -word = $0250,$0650,$0A50,$0E50,$1250,$1650,$1A50,$1E50 -word = $02D0,$06D0,$0AD0,$0ED0,$12D0,$16D0,$1AD0,$1ED0 -word = $0350,$0750,$0B50,$0F50,$1350,$1750,$1B50,$1F50 -word = $03D0,$07D0,$0BD0,$0FD0,$13D0,$17D0,$1BD0,$1FD0 -word hcolor[] = $0000,$552A,$2A55,$7F7F,$8080,$D5AA,$AAD5,$FFFF -word hmask = $8081,$8082,$8084,$8088,$8090,$80A0,$80C0 - = $8180,$8280,$8480,$8880,$9080,$A080,$C080 -word curhclr -word ball0[9] = $0000, $1800, $3C00, $7E00, $7E00, $3C00, $1800, $0000 - -var hspan, vspan -export def spans(h, v)#0 - hspan = h - vspan = v -end -export def line(x1, y1, x2, y2)#0 - var dx2, dy2, err, sx, sy, ps - var shorterr, shortlen, longerr, longlen, halflen - - sx = sy = 1 - dx2 = (x2 - x1) * 2 - if dx2 < 0 - sx = -1; dx2 = -dx2 - fin - dy2 = (y2 - y1) * 2 - if dy2 < 0 - sy = -1; dy2 = -dy2 - fin - if dx2 >= dy2 - if sx < 0 - x1, x2 = x2, x1; sy = -sy - fin - if dy2 == 0 - hspan(x1, x2, y1)#0; return - fin - ps = x1 - for err = dy2 - dx2 / 2 to 0 step dy2 // Find first half-span length and error - x1++ - next - longlen = (x1 - ps + 1) * 2 // Long-span length = half-span length * 2 - longerr = err * 2 - if longerr >= dy2 - longerr = longerr - dy2 - longlen-- - fin - shortlen = longlen - 1 // Short-span length = long-span length - 1 - shorterr = longerr - dy2 - err = err + shorterr // Do a short-span step - while x1 < x2 - hspan(ps, x1, y1)#0 - y1 = y1 + sy // Move to next span - ps = x1 + 1 // Start of next span = end of previous span + 1 - if err >= 0 // Short span - err = err + shorterr - x1 = x1 + shortlen - else // Long span - err = err + longerr - x1 = x1 + longlen - fin - loop - hspan(ps, x2, y2)#0 // Final span - else - if sy < 0 - x1, x2 = x2, x1; sx = -sx - fin - if dx2 == 0 - vspan(x1, y1, y2)#0; return - fin - ps = y1 - for err = dx2 - dy2 / 2 to 0 step dx2 // Find first half-span length and error - y1++ - next - longlen = (y1 - ps + 1) * 2 - longerr = err * 2 - if longerr >= dx2 - longerr -= longerr - dx2 - longlen-- - fin - shortlen = longlen - 1 - shorterr = longerr - dx2 - err = err + shorterr - while y1 < y2 - vspan(x1, ps, y1)#0 - x1 = x1 + sx - ps = y1 + 1 - if err >= 0 // Short span - err = err + shorterr - y1 = y1 + shortlen - else // Long span - err = err + longerr - y1 = y1 + longlen - fin - loop - vspan(x2, ps, y2)#0 // Final span - fin -end -def hgrPlot(x, y)#0 - var pscan, bytofst, pixofst, pmask, pword - - pscan = hgrscan[y] | hgr1 - wrdofst, pixofst = divmod(x, 14) - pmask = hmask[pixofst] - pword = pscan=>[wrdofst] & ~pmask - pscan=>[wrdofst] = pword | (curhclr & pmask) -end -def hgrHlin(x1, x2, y)#0 - var pscan, bytofst, pixofst, pmask, pword - - pscan = hgrscan[y] | hgr1 - wrdofst, pixofst = divmod(x1, 14) - repeat - pmask = hmask[pixofst] - pword = pscan=>[wrdofst] & ~pmask - pscan=>[wrdofst] = pword | (curhclr & pmask) - pixofst++ - if pixofst > 13 - pixofst = 0 - wrdofst++ - fin - x1++ - until x1 > x2 -end -def hgrVlin(x, y1, y2)#0 - var pscan, bytofst, pixofst, pmask, pword, cmask - - wrdofst, pixofst = divmod(x, 14) - pmask = hmask[pixofst] - cmask = curhclr & pmask - pmask = ~pmask - repeat - pscan = hgrscan[y1] | hgr1 - pword = pscan=>[wrdofst] & pmask - pscan=>[wrdofst] = pword | cmask - y1++ - until y1 > y2 -end -def hgrColor(c)#0 - curhclr = hcolor[c & 0x07] -end -def hgrBLT(page, x, y, w, h, pSrc)#0 - word pDst - byte i - - repeat - pDst = hgrscan[y] | page + x - for i = 0 to w - 1 - pDst->[i] = pSrc->[i] - next - pSrc = pSrc + w - y++ - h-- - until not h -end -def testline - var i - - spans(@hgrHlin, @hgrVlin) - hgrColor(7) - for i = 0 to 100 - hgrPlot(i, i) - next -end -memset(hgr1, 0, $2000) // Clear HGR page 1 -^showpage1 -^showfull -^showhires -^showgraphics -testline -hgrBlt(hgrpage[0], 20, 100, 2, 8, @ball0) -getc -^showpage1 -^showtext -done diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index 1d48881..f933cee 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -1,4 +1,5 @@ include "inc/cmdsys.plh" +include "inc/linespans.plh" sysflags reshgr1 // Reserve HGR page 1 // // Hardware addresses @@ -51,160 +52,7 @@ byte hrmask = $81,$83,$87,$8F,$9F,$BF,$FF word curhclr word ball0[9] = $0000, $1800, $3C00, $7E00, $7E00, $3C00, $1800, $0000 -var pixel, hspan, vspan -var err, shorterr, shortlen, longerr, longlen -var dx2, dy2, sx, sy - -export def linefuncs(p, h, v)#0 - pixel = p - hspan = h - vspan = v -end -def phline(x1, x2, y)#0 - var x - - if sx < 0 - sy = -sy; x1, x2 = x2, x1 - fin - err = dy2 - dx2 / 2 - for x = x1 to x2 - pixel(x, y)#0 - if err >= 0 - err = err - dx2 - y = y + sy - fin - err = err + dy2 - next -end -def pvline(y1, y2, x)#0 - var y - - if sy < 0 - sx = -sx; y1, y2 = y2, y1 - fin - err = dx2 - dy2 / 2 - for y = y1 to y2 - pixel(x, y)#0 - if err >= 0 - err = err - dy2 - x = x + sx - fin - err = err + dx2 - next -end -def pline(x1, y1, x2, y2)#0 - sx = 1 - sy = 1 - dx2 = (x2 - x1) * 2 - if dx2 < 0 - sx = -1; dx2 = -dx2 - fin - dy2 = (y2 - y1) * 2 - if dy2 < 0 - sy = -1; dy2 = -dy2 - fin - if dx2 >= dy2 - phline(x1, x2, y1) - else - pvline(y1, y2, x1) - fin -end -def majorline(ps, major, majorend, minor, dir, majorspan)#0 - // - // Initial half-span step - // - err = err + shorterr - repeat - majorspan(ps, major, minor)#0 - minor = minor + dir // Move to next span - ps = major + 1 // Start of next span = end of previous + 1 - if err >= 0 // Short span - err = err + shorterr - major = major + shortlen - else // Long span - err = err + longerr - major = major + longlen - fin - until major >= majorend - // - // Final half-span step - // - majorspan(ps, majorend, minor)#0 -end -export def sline(x1, y1, x2, y2)#0 - var dx, dy, dx2, dy2, halflen, rem, sx, sy - - sx = 1 - sy = 1 - dx = x2 - x1 - if dx < 0 - sx = -1; dx = -dx - fin - dy = y2 - y1 - if dy < 0 - sy = -1; dy = -dy - fin - if dx >= dy - if sx < 0 - x1, x2 = x2, x1; sy = -sy - fin - if dy == 0 - hspan(x1, x2, y1)#0; return - fin - // - // Half-span length and error - // - dy2 = dy * 2 - halflen, rem = divmod(dx, dy2) - err = dy2 - rem - // - // Long-span length = half-span length * 2 - // - longlen = (halflen + 1) * 2 - longerr = err * 2 - if longerr >= dy2 - longerr = longerr - dy2 - longlen-- - fin - // - // Short-span length = long-span length - 1 - // - shortlen = longlen - 1 - shorterr = longerr - dy2 - // - // JIT optimize inner loop - // - majorline(x1, x1 + halflen, x2, y1, sy, hspan) - else - if sy < 0 - x1, x2 = x2, x1; sx = -sx - fin - if dx == 0 - vspan(y1, y2, x1)#0; return - fin - // - // Half-span length and error - // - dx2 = dx * 2 - halflen, rem = divmod(dy, dx2) - err = dx2 - rem - // - // Long-span length = half-span length * 2 - // - longlen = (halflen + 1) * 2 - longerr = err * 2 - if longerr >= dx2 - longerr = longerr - dx2 - longlen-- - fin - shortlen = longlen - 1 - shorterr = longerr - dx2 - // - // JIT optimize inner loop - // - majorline(y1, y1 + halflen, y2, x1, sx, vspan) - fin -end +var err, dx2, dy2, sx, sy def hgrPlot(x, y)#0 word pptr @@ -272,19 +120,70 @@ def hgrBLT(page, x, y, w, h, pSrc)#0 h-- until not h end +def phline(x1, x2, y)#0 + var x + + if sx < 0 + sy = -sy; x1, x2 = x2, x1 + fin + err = dy2 - dx2 / 2 + for x = x1 to x2 + hgrPlot(x, y) + if err >= 0 + err = err - dx2 + y = y + sy + fin + err = err + dy2 + next +end +def pvline(y1, y2, x)#0 + var y + + if sy < 0 + sx = -sx; y1, y2 = y2, y1 + fin + err = dx2 - dy2 / 2 + for y = y1 to y2 + hgrPlot(x, y) + if err >= 0 + err = err - dy2 + x = x + sx + fin + err = err + dx2 + next +end +def simpleline(x1, y1, x2, y2)#0 + sx = 1 + sy = 1 + dx2 = (x2 - x1) * 2 + if dx2 < 0 + sx = -1; dx2 = -dx2 + fin + dy2 = (y2 - y1) * 2 + if dy2 < 0 + sy = -1; dy2 = -dy2 + fin + if dx2 >= dy2 + phline(x1, x2, y1) + else + pvline(y1, y2, x1) + fin +end + def testline#0 var i - linefuncs(@hgrPlot, @hgrHlin, @hgrVlin) - hgrColor(3) + setlinespans(@hgrHlin, @hgrVlin) + hgrColor(2) for i = 0 to 191 - pline(0, 0, i, 191) - pline(0, 0, 191, i) + simpleline(0, 0, i, 191) + simpleline(0, 0, 191, i) next - hgrColor(0); + memset(hgr1, 0, $2000) // Clear HGR page 1 + hgrColor(1); for i = 0 to 191 - sline(0, 0, i, 191) - sline(0, 0, 191, i) + linetospans(0, 0, i, 191) + linetospans(0, 0, 191, i) next end memset(hgr1, 0, $2000) // Clear HGR page 1 From 72f7dea67fdea05f2cbcc0f091b6bdaf80f83e7e Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 19 Dec 2019 10:22:26 -0800 Subject: [PATCH 054/149] Clean up DGRlib --- src/inc/{dgr.plh => dgrlib.plh} | 24 +-- src/libsrc/apple/{dgr.pla => dgrlib.pla} | 201 +++++++++-------------- src/libsrc/linespans.pla | 7 +- src/makefile | 10 +- src/mkrel | 4 +- src/samplesrc/dgrtest.pla | 4 +- 6 files changed, 101 insertions(+), 149 deletions(-) rename src/inc/{dgr.plh => dgrlib.plh} (54%) rename src/libsrc/apple/{dgr.pla => dgrlib.pla} (80%) diff --git a/src/inc/dgr.plh b/src/inc/dgrlib.plh similarity index 54% rename from src/inc/dgr.plh rename to src/inc/dgrlib.plh index 57106dc..ac52049 100644 --- a/src/inc/dgr.plh +++ b/src/inc/dgrlib.plh @@ -1,25 +1,17 @@ -import dgr +import dgrlib word[] dgrbuff - predef dgrPlotBuf(x, y, bufptr)#0 - predef dgrHLinBuf(x1, x2, y, bufptr)#0 - predef dgrVLinBuf(x, y1, y2, bufptr)#0 - predef dgrBLTBuf(bufptr, x, y, width, height, src)#0 - predef dgrTileBuf(bufptr, x, y, src)#0 - predef dgrTileStrBuf(bufptr, x, y, tilestr, strlen, tilebuff)#0 - predef dgrFillBuf(bufptr, x, y, tile)#0 - predef dgrMode#1 - predef txtMode#0 - predef dgrShow(page)#1 - predef dgrSwap#0 - predef dgrDrawBuf(page)#0 - predef dgrClearBuf(bufptr, clr)#0 - predef dgrClear(clr)#0 predef dgrPlot(x, y)#0 - predef dgrColor(clr)#0 predef dgrHLin(x1, x2, y)#0 predef dgrVLin(y1, y2, x)#0 predef dgrBLT(x, y, width, height, src)#0 predef dgrTile(x, y, src)#0 predef dgrTileStr(x, y, tilestr, strlen, tilebuff)#0 predef dgrFill(x, y, tile)#0 + predef dgrClear(clr)#0 + predef dgrMode#1 + predef txtMode#0 + predef dgrShow(page)#1 + predef dgrSwap#0 + predef dgrDrawBuf(page)#0 + predef dgrColor(clr)#0 end diff --git a/src/libsrc/apple/dgr.pla b/src/libsrc/apple/dgrlib.pla similarity index 80% rename from src/libsrc/apple/dgr.pla rename to src/libsrc/apple/dgrlib.pla index a0063dd..d4bd709 100755 --- a/src/libsrc/apple/dgr.pla +++ b/src/libsrc/apple/dgrlib.pla @@ -1,5 +1,4 @@ include "inc/cmdsys.plh" -sysflags restxt1|restxt2|resxtxt1|resxtxt2 // Reserve all text pages // // Apple II hardware constants. // @@ -51,13 +50,13 @@ end // // Plot pixel // -export asm dgrPlotBuf(bufptr, x, y)#0 - ; GET BUFFER ADDRESS - STX ESP - LDA ESTKL+2,X +export asm dgrPlot(x, y)#0 + ; GET ROW BUFFER ADDRESSES + LDA $3000 STA SRCL - LDA ESTKH+2,X - STA SRCH + LDA $3001 + STA SRCH + STX ESP LDA ESTKL,X ; Y COORD AND #$FE TAY @@ -78,29 +77,21 @@ asm _dgrPlotPix LDX ESP INX INX - INX RTS end // // Plot horizontal row of pixels // export asm dgrHLin(x1, x2, y)#0 - DEX - LDA $3000 - STA ESTKL,X - LDA $3001 - STA ESTKH,X -end -export asm dgrHLinBuf(x1, x2, y, bufptr)#0 - ; GET BUFFER ADDRESS - STX ESP - LDA ESTKL,X + ; GET ROW BUFFER ADDRESSES + LDA $3000 STA SRCL - LDA ESTKH,X - STA SRCH - LDA ESTKL+2,X ; X2 COORD + LDA $3001 + STA SRCH + STX ESP + LDA ESTKL+1,X ; X2 COORD STA TMPH - LDA ESTKL+1,X ; Y COORD + LDA ESTKL+0,X ; Y COORD AND #$FE TAY LDA (SRC),Y @@ -108,10 +99,10 @@ export asm dgrHLinBuf(x1, x2, y, bufptr)#0 INY LDA (SRC),Y STA GBASH - LDY ESTKL+3,X ; X1 COORD + LDY ESTKL+2,X ; X1 COORD PHP SEI -- LDA ESTKL+1,X ; Y COORD +- LDA ESTKL+0,X ; Y COORD LSR TYA LDX GCLR ; COLOR @@ -119,8 +110,8 @@ end asm _dgrHLinPix JSR $3000 ; _dgrSetPix LDX ESP - INC ESTKL+3,X ; X1 COORD - LDY ESTKL+3,X + INC ESTKL+2,X ; X1 COORD + LDY ESTKL+2,X CPY TMPH ; X2 COORD BCC - BEQ - @@ -128,27 +119,19 @@ asm _dgrHLinPix INX INX INX - INX RTS end // // Plot horizontal row of pixels // export asm dgrVLin(y1, y2, x)#0 - DEX - LDA $3000 - STA ESTKL,X - LDA $3001 - STA ESTKH,X -end -export asm dgrVLinBuf(y1, y2, x, bufptr)#0 - ; GET BUFFER ADDRESS - STX ESP - LDA ESTKL,X + ; GET ROW BUFFER ADDRESSES + LDA $3000 STA SRCL - LDA ESTKH,X - STA SRCH - LDA ESTKL+3,X ; Y1 COORD + LDA $3001 + STA SRCH + STX ESP + LDA ESTKL+2,X ; Y1 COORD PHP SEI - AND #$FE @@ -158,38 +141,38 @@ export asm dgrVLinBuf(y1, y2, x, bufptr)#0 INY LDA (SRC),Y STA GBASH - LDA ESTKL+3,X + LDA ESTKL+2,X LSR - LDA ESTKL+1,X ; X COORD + LDA ESTKL+0,X ; X COORD LDX GCLR ; COLOR end asm _dgrVLinPix JSR $3000 ; _dgrSetPix LDX ESP - INC ESTKL+3,X ; Y1 COORD - LDA ESTKL+3,X - CMP ESTKL+2,X ; Y2 COORD + INC ESTKL+2,X ; Y1 COORD + LDA ESTKL+2,X + CMP ESTKL+1,X ; Y2 COORD BCC - BEQ - PLP INX INX INX - INX RTS end // // Draw sprite // -export asm dgrBLTBuf(bufptr, x, y, width, height, src)#0 +export asm dgrBLT(x, y, width, height, src)#0 + ; GET ROW BUFFER ADDRESSES + LDA $3000 + STA DSTL + LDA $3001 + STA DSTH LDA ESTKL,X ; SPRITE STA SRCL LDA ESTKH,X STA SRCH - LDA ESTKL+5,X - STA DSTL - LDA ESTKH+5,X - STA DSTH LDA ESTKL+4,X ; X1 COORD CMP #80 BPL ++++ @@ -261,7 +244,6 @@ asm _dgrBLTPix INX INX INX - INX RTS end // @@ -342,16 +324,17 @@ end // // Draw 8x8 tile (forced to 2x2 block address) // -export asm dgrTileBuf(bufptr, x, y, src)#0 +export asm dgrTile(x, y, src)#0 + ; GET ROW BUFFER ADDRESSES + LDA $3000 + STA DSTL + LDA $3001 + STA DSTH STX ESP LDA ESTKL,X ; TILE STA SRCL LDA ESTKH,X STA SRCH - LDA ESTKL+3,X - STA DSTL - LDA ESTKH+3,X - STA DSTH LDA ESTKL+2,X ; X1 COORD CMP #80 BPL ++++ @@ -421,7 +404,6 @@ export asm dgrTileBuf(bufptr, x, y, src)#0 CMP ESTKH+1,X ; Y2 COORD BCC - ++++ INX - INX INX INX RTS @@ -429,22 +411,17 @@ end // // Draw a string of tiles // -export asm dgrTileStrBuf(bufptr, x, y, tilestr, strlen, tilebuff)#0 +export asm dgrTileStr(x, y, tilestr, strlen, tilebuff)#0 - DEX DEX DEX - DEX - LDA ESTKL+9,X ; BUFF - STA ESTKL+3,X - LDA ESTKH+9,X - STA ESTKH+3,X - LDA ESTKL+8,X ; X COORD + LDA ESTKL+7,X ; X COORD STA ESTKL+2,X - LDA ESTKL+7,X ; Y COORD + LDA ESTKL+6,X ; Y COORD STA ESTKL+1,X - LDA ESTKL+4,X ; TILE + LDA ESTKL+3,X ; TILE STA ESTKL,X - LDA ESTKH+4,X ; TILE + LDA ESTKH+3,X ; TILE STA ESTKH,X end asm _dgrTileTile @@ -457,16 +434,17 @@ asm _dgrTileTile STA ESTKL+4,X DEC ESTKL+1,X ; DEC STRLEN BNE - -+ TXA - CLC - ADC #6 - TAX ++ INX + INX + INX + INX + INX RTS end // // Fill a buffer with tiles // -export asm dgrFillBuf(bufptr, x, y, tile)#0 +export asm dgrFill(x, y, tile)#0 LDA ESTKL+2,X AND #$0F STA ESTKL+2,X @@ -485,18 +463,13 @@ export asm dgrFillBuf(bufptr, x, y, tile)#0 - DEX DEX DEX - DEX - LDA ESTKL+7,X ; BUFF - STA ESTKL+3,X - LDA ESTKH+7,X - STA ESTKH+3,X - LDA ESTKL+6,X ; X COORD + LDA ESTKL+5,X ; X COORD STA ESTKL+2,X - LDA ESTKL+5,X ; Y COORD + LDA ESTKL+4,X ; Y COORD STA ESTKL+1,X - LDA ESTKL+4,X ; TILE + LDA ESTKL+3,X ; TILE STA ESTKL,X - LDA ESTKH+4,X ; TILE + LDA ESTKH+3,X ; TILE STA ESTKH,X end asm _dgrFillTile @@ -518,7 +491,6 @@ asm _dgrFillTile INX INX INX - INX RTS end // @@ -532,6 +504,16 @@ asm vlbWait#0 RTS end // +// Clear the buffer +// +export def dgrClear(clr)#0 + byte[32] clrtile + + clr = evnclr[clr&$0F] | (oddclr[clr&$0F] << 8) + memset(@clrtile, clr, 32) + dgrFill(0, 0, @clrtile) +end +// // Set double lores graphics, return draw buffer // export def dgrMode#1 @@ -582,41 +564,6 @@ export def dgrColor(clr)#0 ^$30 = clr & $0F end // -// Clear the buffer -// -export def dgrClearBuf(bufptr, clr)#0 - byte[32] clrtile - - clr = evnclr[clr&$0F] | (oddclr[clr&$0F] << 8) - memset(@clrtile, clr, 32) - dgrFillBuf(bufptr, 0, 0, @clrtile) -end -export def dgrClear(clr)#0 - byte[32] clrtile - - clr = evnclr[clr&$0F] | (oddclr[clr&$0F] << 8) - memset(@clrtile, clr, 32) - dgrFillBuf(drawbufptr, 0, 0, @clrtile) -end -// -// Draw functions -// -export def dgrPlot(x, y)#0 - dgrPlotBuf(drawbufptr, x, y) -end -export def dgrBLT(x, y, width, height, src)#0 - dgrBLTBuf(drawbufptr, x, y, width, height, src) -end -export def dgrTile(x, y, src)#0 - dgrTileBuf(drawbufptr, x, y, src) -end -export def dgrTileStr(x, y, tilestr, strlen, tilebuff)#0 - dgrTileStrBuf(drawbufptr, x, y, tilestr, strlen, tilebuff) -end -export def dgrFill(x, y, tile)#0 - dgrFillBuf(drawbufptr, x, y, tile) -end -// // Make sure we are a 128K //e or //c // if MACHID & $F0 <> $B0 @@ -632,8 +579,8 @@ _dgrPlotPix:1 = @_dgrSetPix _dgrHLinPix:1 = @_dgrSetPix _dgrVLinPix:1 = @_dgrSetPix _dgrBLTPix:1 = @_dgrSetPix -_dgrTileTile:1 = @dgrTileBuf -_dgrFillTile:1 = @dgrTileBuf +_dgrTileTile:1 = @dgrTile +_dgrFillTile:1 = @dgrTile _dgrSetEvnEvn:1 = @evnclr _dgrSetEvnOdd:1 = @oddclr _dgrSetOddEvn:1 = @evnclr @@ -641,10 +588,16 @@ _dgrSetOddOdd:1 = @oddclr // // Fixups for drawbufptr // -dgrHLin:2 = @drawbufptr -dgrHLin:7 = @drawbufptr+1 -dgrVLin:2 = @drawbufptr -dgrVLin:7 = @drawbufptr+1 +dgrPlot:1 = @drawbufptr +dgrPlot:6 = @drawbufptr+1 +dgrHLin:1 = @drawbufptr +dgrHLin:6 = @drawbufptr+1 +dgrVLin:1 = @drawbufptr +dgrVLin:6 = @drawbufptr+1 +dgrBLT:1 = @drawbufptr +dgrBLT:6 = @drawbufptr+1 +dgrTile:1 = @drawbufptr +dgrTile:6 = @drawbufptr+1 // Put read AUX mem routine in scary location memcpy($0100, @auxRead, 9) done diff --git a/src/libsrc/linespans.pla b/src/libsrc/linespans.pla index d63ba80..4f6a745 100644 --- a/src/libsrc/linespans.pla +++ b/src/libsrc/linespans.pla @@ -1,7 +1,12 @@ include "inc/cmdsys.plh" -var hspan, vspan +predef nopLin(a, b, c)#0 + +var hspan = @nopLin +var vspan = @nopLin var err, shorterr, shortlen, longerr, longlen +def nopLin(a, b, c)#0 +end export def setlinespans(h, v)#0 hspan = h vspan = v diff --git a/src/makefile b/src/makefile index 417399e..e055016 100755 --- a/src/makefile +++ b/src/makefile @@ -47,7 +47,7 @@ INET = rel/INET\#FE1000 DHCP = rel/DHCP\#FE1000 HTTPD = rel/HTTPD\#FE1000 TFTPD = rel/TFTPD\#FE1000 -DGR = rel/apple/DGR\#FE1000 +DGRLIB = rel/apple/DGRLIB\#FE1000 LINESPANS = rel/apple/LINESPANS\#FE1000 GRAFIX = rel/apple/GRAFIX\#FE1000 GFXDEMO = rel/apple/GFXDEMO\#FE1000 @@ -88,7 +88,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(DGR) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(DGRLIB) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc c64: $(PLVMZP_C64) $(PLASM) $(PLVM) $(PLVMC64) @@ -382,9 +382,9 @@ $(PORTIO): libsrc/apple/portio.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/portio.pla > libsrc/apple/portio.a acme --setpc 4094 -o $(PORTIO) libsrc/apple/portio.a -$(DGR): libsrc/apple/dgr.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AMOW < libsrc/apple/dgr.pla > libsrc/apple/dgr.a - acme --setpc 4094 -o $(DGR) libsrc/apple/dgr.a +$(DGRLIB): libsrc/apple/dgrlib.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < libsrc/apple/dgrlib.pla > libsrc/apple/dgrlib.a + acme --setpc 4094 -o $(DGRLIB) libsrc/apple/dgrlib.a $(DGRTEST): samplesrc/dgrtest.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/dgrtest.pla > samplesrc/dgrtest.a diff --git a/src/mkrel b/src/mkrel index 4669219..1c7d30e 100755 --- a/src/mkrel +++ b/src/mkrel @@ -10,7 +10,7 @@ mkdir prodos/sys cp rel/apple/FILEIO#FE1000 prodos/sys/FILEIO.REL cp rel/apple/CONIO#FE1000 prodos/sys/CONIO.REL cp rel/apple/LINESPANS#FE1000 prodos/sys/LINESPANS.REL -cp rel/apple/DGR#FE1000 prodos/sys/DGR.REL +cp rel/apple/DGRLIB#FE1000 prodos/sys/DGRLIB.REL cp rel/ARGS#FE1000 prodos/sys/ARGS.REL cp rel/ED#FE1000 prodos/sys/ED.REL cp rel/FIBER#FE1000 prodos/sys/FIBER.REL @@ -138,7 +138,7 @@ cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT cp inc/cmdsys.plh prodos/bld/inc/CMDSYS.PLH.TXT cp inc/conio.plh prodos/bld/inc/CONIO.PLH.TXT cp inc/linespans.plh prodos/bld/inc/LINESPANS.PLH.TXT -cp inc/dgr.plh prodos/bld/inc/DGR.PLH.TXT +cp inc/dgrlib.plh prodos/bld/inc/DGRLIB.PLH.TXT cp inc/fiber.plh prodos/bld/inc/FIBER.PLH.TXT cp inc/fileio.plh prodos/bld/inc/FILEIO.PLH.TXT cp inc/fpstr.plh prodos/bld/inc/FPSTR.PLH.TXT diff --git a/src/samplesrc/dgrtest.pla b/src/samplesrc/dgrtest.pla index 41ffdb4..ea20a0f 100644 --- a/src/samplesrc/dgrtest.pla +++ b/src/samplesrc/dgrtest.pla @@ -1,5 +1,7 @@ -include "inc/dgr.plh" +include "inc/cmdsys.plh" +include "inc/dgrlib.plh" include "inc/linespans.plh" +sysflags restxt1|restxt2|resxtxt1|resxtxt2 // Reserve all text pages byte[] sprite1 = $80,$80,$00,$00,$00,$00,$80,$80 byte[] = $80,$00,$0A,$0A,$0A,$0A,$00,$80 From b9c5a8cb2379c9f7c9e0bc809deff9e5eb2d9612 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Thu, 19 Dec 2019 14:27:08 -0800 Subject: [PATCH 055/149] More WIP for the graphics libraries --- src/inc/dgrlib.plh | 1 - src/libsrc/apple/dgrlib.pla | 2 +- src/makefile | 13 ++- src/mkrel | 4 + src/samplesrc/hgrtest.pla | 178 +++++++++++++++++++++++++----------- src/tftpbld | 7 +- src/tftpdemos | 1 + src/tftpsys | 4 +- src/toolsrc/ed.pla | 38 +++++++- 9 files changed, 189 insertions(+), 59 deletions(-) diff --git a/src/inc/dgrlib.plh b/src/inc/dgrlib.plh index ac52049..a378993 100644 --- a/src/inc/dgrlib.plh +++ b/src/inc/dgrlib.plh @@ -1,5 +1,4 @@ import dgrlib - word[] dgrbuff predef dgrPlot(x, y)#0 predef dgrHLin(x1, x2, y)#0 predef dgrVLin(y1, y2, x)#0 diff --git a/src/libsrc/apple/dgrlib.pla b/src/libsrc/apple/dgrlib.pla index d4bd709..d523f8c 100755 --- a/src/libsrc/apple/dgrlib.pla +++ b/src/libsrc/apple/dgrlib.pla @@ -29,7 +29,7 @@ word = $0450,$04D0,$0550,$05D0,$0650,$06D0,$0750,$07D0 word[] dgr2rows = $0800,$0880,$0900,$0980,$0A00,$0A80,$0B00,$0B80 word = $0828,$08A8,$0928,$09A8,$0A28,$0AA8,$0B28,$0BA8 word = $0850,$08D0,$0950,$09D0,$0A50,$0AD0,$0B50,$0BD0 -export word[] dgrbuff = @dgr1rows, @dgr2rows +word[] dgrbuff = @dgr1rows, @dgr2rows word drawbufptr byte drawpage // diff --git a/src/makefile b/src/makefile index e055016..e8d27d9 100755 --- a/src/makefile +++ b/src/makefile @@ -47,6 +47,7 @@ INET = rel/INET\#FE1000 DHCP = rel/DHCP\#FE1000 HTTPD = rel/HTTPD\#FE1000 TFTPD = rel/TFTPD\#FE1000 +GRLIB = rel/apple/GRLIB\#FE1000 DGRLIB = rel/apple/DGRLIB\#FE1000 LINESPANS = rel/apple/LINESPANS\#FE1000 GRAFIX = rel/apple/GRAFIX\#FE1000 @@ -57,6 +58,7 @@ ROGUE = rel/ROGUE\#FE1000 ROGUEMAP = rel/ROGUEMAP\#FE1000 ROGUECOMBAT= rel/ROGUECOMBAT\#FE1000 MON = rel/apple/MON\#FE1000 +GRTEST = rel/apple/GRTEST\#FE1000 DGRTEST = rel/apple/DGRTEST\#FE1000 HGRTEST = rel/apple/HGRTEST\#FE1000 MEMMGR = rel/MEMMGR\#FE1000 @@ -88,7 +90,8 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(DGRLIB) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) + -rm vmsrc/plvmzp.inc c64: $(PLVMZP_C64) $(PLASM) $(PLVM) $(PLVMC64) @@ -382,10 +385,18 @@ $(PORTIO): libsrc/apple/portio.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/portio.pla > libsrc/apple/portio.a acme --setpc 4094 -o $(PORTIO) libsrc/apple/portio.a +$(GRLIB): libsrc/apple/grlib.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < libsrc/apple/grlib.pla > libsrc/apple/grlib.a + acme --setpc 4094 -o $(GRLIB) libsrc/apple/grlib.a + $(DGRLIB): libsrc/apple/dgrlib.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/dgrlib.pla > libsrc/apple/dgrlib.a acme --setpc 4094 -o $(DGRLIB) libsrc/apple/dgrlib.a +$(GRTEST): samplesrc/grtest.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < samplesrc/grtest.pla > samplesrc/grtest.a + acme --setpc 4094 -o $(GRTEST) samplesrc/grtest.a + $(DGRTEST): samplesrc/dgrtest.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/dgrtest.pla > samplesrc/dgrtest.a acme --setpc 4094 -o $(DGRTEST) samplesrc/dgrtest.a diff --git a/src/mkrel b/src/mkrel index 1c7d30e..f82a996 100755 --- a/src/mkrel +++ b/src/mkrel @@ -10,6 +10,7 @@ mkdir prodos/sys cp rel/apple/FILEIO#FE1000 prodos/sys/FILEIO.REL cp rel/apple/CONIO#FE1000 prodos/sys/CONIO.REL cp rel/apple/LINESPANS#FE1000 prodos/sys/LINESPANS.REL +cp rel/apple/GRLIB#FE1000 prodos/sys/GRLIB.REL cp rel/apple/DGRLIB#FE1000 prodos/sys/DGRLIB.REL cp rel/ARGS#FE1000 prodos/sys/ARGS.REL cp rel/ED#FE1000 prodos/sys/ED.REL @@ -54,6 +55,7 @@ cp ../sysfiles/ELEMS.CODE#060000 prodos/fpsos/sys/ELEMS.CODE.BIN rm -rf prodos/demos mkdir prodos/demos +cp rel/apple/GRTEST#FE1000 prodos/demos/GRTEST.REL cp rel/apple/DGRTEST#FE1000 prodos/demos/DGRTEST.REL cp rel/apple/HGRTEST#FE1000 prodos/demos/HGRTEST.REL cp rel/apple/ROD#FE1000 prodos/demos/ROD.REL @@ -98,6 +100,7 @@ cp rel/CODEOPT#FE1000 prodos/bld/CODEOPT.REL mkdir prodos/bld/samples cp samplesrc/hello.pla prodos/bld/samples/HELLO.PLA.TXT +cp samplesrc/grtest.pla prodos/bld/samples/GRTEST.PLA.TXT cp samplesrc/dgrtest.pla prodos/bld/samples/DGRTEST.PLA.TXT cp samplesrc/hgrtest.pla prodos/bld/samples/HGRTEST.PLA.TXT cp samplesrc/fibertest.pla prodos/bld/samples/FIBERTEST.PLA.TXT @@ -138,6 +141,7 @@ cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT cp inc/cmdsys.plh prodos/bld/inc/CMDSYS.PLH.TXT cp inc/conio.plh prodos/bld/inc/CONIO.PLH.TXT cp inc/linespans.plh prodos/bld/inc/LINESPANS.PLH.TXT +cp inc/grlib.plh prodos/bld/inc/GRLIB.PLH.TXT cp inc/dgrlib.plh prodos/bld/inc/DGRLIB.PLH.TXT cp inc/fiber.plh prodos/bld/inc/FIBER.PLH.TXT cp inc/fileio.plh prodos/bld/inc/FILEIO.PLH.TXT diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index f933cee..b865f24 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -52,13 +52,58 @@ byte hrmask = $81,$83,$87,$8F,$9F,$BF,$FF word curhclr word ball0[9] = $0000, $1800, $3C00, $7E00, $7E00, $3C00, $1800, $0000 -var err, dx2, dy2, sx, sy +asm grInc(buff) +!SOURCE "vmsrc/plvmzp.inc" +GBASL = $26 +GBASH = $27 +GBASE = GBASL +GCLR = $30 +end +asm divmod7(x)#2 + LDA ESTKL,X ; X COORD LSB + LDY ESTKH,X ; X COORD MSB + BNE + ; MUST BE >= 140 + CMP #140 + BCC ++ ++ SEC + SBC #140 + LDY #20 +++ CMP #70 + BCC + + SBC #70 + STA ESTKL,X + TYA + ADC #9 + TAY + LDA ESTKL,X ++ CMP #35 + BCC + + SBC #35 + STA ESTKL,X + TYA + ADC #4 + TAY + LDA ESTKL,X ++ +- CMP #7 + BCC + + SBC #7 + INY + BNE - ++ DEX + STA ESTKL,X ; REMAINDER + STY ESTKL+1,X ; QUOTIENT + LDA #$00 + STA ESTKH,X + STA ESTKH+1,X + RTS +end def hgrPlot(x, y)#0 word pptr byte ofst, pixofst, pmask - ofst, pixofst = divmod(x, 7) + ofst, pixofst = divmod7(x) pptr = (hgrscan[y] | hgr1) + ofst pmask = hbmask[pixofst] ^pptr = (^pptr & ~pmask) | (curhclr.[ofst & 1] & pmask) @@ -71,9 +116,9 @@ def hgrHlin(x1, x2, y)#0 if x1 == x2 hgrPlot(x1, y) else - lofst, lpixofst = divmod(x1, 7) + lofst, lpixofst = divmod7(x1) pptr = (hgrscan[y] | hgr1) + lofst - rofst, rpixofst = divmod(x2, 7) + rofst, rpixofst = divmod7(x2) lpmask = hlmask[lpixofst] rpmask = hrmask[rpixofst] if lofst == rofst @@ -94,14 +139,18 @@ def hgrVlin(y1, y2, x)#0 word pptr, y byte ofst, pixofst, pmask, cmask - ofst, pixofst = divmod(x, 7) - pmask = hbmask[pixofst] - cmask = curhclr.[ofst & 1] & pmask - pmask = ~pmask - for y = y1 to y2 - pptr = (hgrscan[y] | hgr1) + ofst - ^pptr = (^pptr & pmask) | cmask - next + if y1 == y2 + hgrPlot(x, y1) + else + ofst, pixofst = divmod7(x) + pmask = hbmask[pixofst] + cmask = curhclr.[ofst & 1] & pmask + pmask = ~pmask + for y = y1 to y2 + pptr = (hgrscan[y] | hgr1) + ofst + ^pptr = (^pptr & pmask) | cmask + next + fin end def hgrColor(c)#0 curhclr = hcolor[c & $07] @@ -120,39 +169,11 @@ def hgrBLT(page, x, y, w, h, pSrc)#0 h-- until not h end -def phline(x1, x2, y)#0 - var x - - if sx < 0 - sy = -sy; x1, x2 = x2, x1 - fin - err = dy2 - dx2 / 2 - for x = x1 to x2 - hgrPlot(x, y) - if err >= 0 - err = err - dx2 - y = y + sy - fin - err = err + dy2 - next -end -def pvline(y1, y2, x)#0 - var y - - if sy < 0 - sx = -sx; y1, y2 = y2, y1 - fin - err = dx2 - dy2 / 2 - for y = y1 to y2 - hgrPlot(x, y) - if err >= 0 - err = err - dy2 - x = x + sx - fin - err = err + dx2 - next -end def simpleline(x1, y1, x2, y2)#0 + var err, dx2, dy2, sx, sy, x, y + word pptr + byte ofst, pixofst, pmask, clr + sx = 1 sy = 1 dx2 = (x2 - x1) * 2 @@ -163,10 +184,65 @@ def simpleline(x1, y1, x2, y2)#0 if dy2 < 0 sy = -1; dy2 = -dy2 fin + if dx2 >= dy2 - phline(x1, x2, y1) - else - pvline(y1, y2, x1) + if sx < 0 + sy = -sy; x1, x2 = x2, x1 + fin + err = dy2 - dx2 / 2 + ofst, pixofst = divmod7(x1) + pptr = (hgrscan[y1] | hgr1) + ofst + clr = curhclr.[ofst & 1] + for x = x1 to x2 + pmask = hbmask[pixofst] + ^pptr = (^pptr & ~pmask) | (clr & pmask) + pixofst++ + if pixofst > 7 + pixofst = 0 + pptr++ + ofst++ + clr = curhclr.[ofst & 1] + fin + if err >= 0 + err = err - dx2 + y1 = y1 + sy + pptr = (hgrscan[y1] | hgr1) + ofst + fin + err = err + dy2 + next + else + if sy < 0 + sx = -sx; y1, y2 = y2, y1 + fin + err = dx2 - dy2 / 2 + ofst, pixofst = divmod7(x1) + clr = curhclr.[ofst & 1] + pmask = hbmask[pixofst] + for y = y1 to y2 + pptr = (hgrscan[y] | hgr1) + ofst + ^pptr = (^pptr & ~pmask) | (clr & pmask) + if err >= 0 + err = err - dy2 + if sx > 0 + pixofst++ + if pixofst > 7 + pixofst = 0 + ofst++ + clr = curhclr.[ofst & 1] + fin + else + if pixofst == 0 + pixofst = 7 + ofst-- + clr = curhclr.[ofst & 1] + else + pixofst-- + fin + fin + pmask = hbmask[pixofst] + fin + err = err + dx2 + next fin end @@ -175,10 +251,10 @@ def testline#0 setlinespans(@hgrHlin, @hgrVlin) hgrColor(2) - for i = 0 to 191 - simpleline(0, 0, i, 191) - simpleline(0, 0, 191, i) - next + //for i = 0 to 191 + // simpleline(0, 0, i, 191) + // simpleline(0, 0, 191, i) + //next memset(hgr1, 0, $2000) // Clear HGR page 1 hgrColor(1); for i = 0 to 191 diff --git a/src/tftpbld b/src/tftpbld index e5d03d3..b083725 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -8,7 +8,9 @@ echo "BLD/CODEOPT"; atftp $1 --put -l rel/CODEOPT#FE1000 -r $2/BLD/CODEOPT#FE10 echo "BLD/INC/ARGS.PLH"; atftp $1 --put -l inc/args.plh -r $2/BLD/INC/ARGS.PLH#040000 echo "BLD/INC/CMDSYS.PLH"; atftp $1 --put -l inc/cmdsys.plh -r $2/BLD/INC/CMDSYS.PLH#040000 echo "BLD/INC/CONIO.PLH"; atftp $1 --put -l inc/conio.plh -r $2/BLD/INC/CONIO.PLH#040000 -echo "BLD/INC/DGR.PLH"; atftp $1 --put -l inc/dgr.plh -r $2/BLD/INC/DGR.PLH#040000 +echo "BLD/INC/LINESPANS.PLH"; atftp $1 --put -l inc/linespans.plh -r $2/BLD/INC/LINESPANS.PLH#040000 +echo "BLD/INC/GRLIB.PLH"; atftp $1 --put -l inc/grlib.plh -r $2/BLD/INC/GRLIB.PLH#040000 +echo "BLD/INC/DGRLIB.PLH"; atftp $1 --put -l inc/dgrlib.plh -r $2/BLD/INC/DGRLIB.PLH#040000 echo "BLD/INC/FIBER.PLH"; atftp $1 --put -l inc/fiber.plh -r $2/BLD/INC/FIBER.PLH#040000 echo "BLD/INC/FILEIO.PLH"; atftp $1 --put -l inc/fileio.plh -r $2/BLD/INC/FILEIO.PLH#040000 echo "BLD/INC/FPSTR.PLH"; atftp $1 --put -l inc/fpstr.plh -r $2/BLD/INC/FPSTR.PLH#040000 @@ -34,8 +36,9 @@ echo "BLD/SAMPLES/TEST.PLA"; atftp $1 --put -l samplesrc/test.pla -r $ echo "BLD/SAMPLES/FIBERTEST.PLA"; atftp $1 --put -l samplesrc/fibertest.pla -r $2/BLD/SAMPLES/FIBERTEST.PLA#040000 echo "BLD/SAMPLES/MOUSETEST.PLA"; atftp $1 --put -l samplesrc/mousetest.pla -r $2/BLD/SAMPLES/MOUSETEST.PLA#040000 echo "BLD/SAMPLES/ROD.PLA"; atftp $1 --put -l samplesrc/rod.pla -r $2/BLD/SAMPLES/ROD.PLA#040000 +echo "BLD/SAMPLES/GRTEST.PLA"; atftp $1 --put -l samplesrc/grtest.pla -r $2/BLD/SAMPLES/GRTEST.PLA#040000 echo "BLD/SAMPLES/DGRTEST.PLA"; atftp $1 --put -l samplesrc/dgrtest.pla -r $2/BLD/SAMPLES/DGRTEST.PLA#040000 -echo "BLD/SAMPLES/HGR1TEST.PLA"; atftp $1 --put -l samplesrc/hgr1test.pla -r $2/BLD/SAMPLES/HGR1TEST.PLA#040000 +echo "BLD/SAMPLES/HGRTEST.PLA"; atftp $1 --put -l samplesrc/hgrtest.pla -r $2/BLD/SAMPLES/HGRTEST.PLA#040000 echo "BLD/SAMPLES/PLAYSEQ.PLA"; atftp $1 --put -l samplesrc/playseq.pla -r $2/BLD/SAMPLES/PLAYSEQ.PLA#040000 echo "BLD/SAMPLES/RPNCALC.PLA"; atftp $1 --put -l samplesrc/rpncalc.pla -r $2/BLD/SAMPLES/RPNCALC.PLA#040000 echo "BLD/SAMPLES/SIEVE.PLA"; atftp $1 --put -l samplesrc/sieve.pla -r $2/BLD/SAMPLES/SIEVE.PLA#040000 diff --git a/src/tftpdemos b/src/tftpdemos index 5a9bca3..159f871 100755 --- a/src/tftpdemos +++ b/src/tftpdemos @@ -5,6 +5,7 @@ echo "DEMOS/RPNCALC"; atftp $1 --put -l rel/RPNCALC#FE1000 echo "DEMOS/LZ4CAT"; atftp $1 --put -l rel/LZ4CAT#FE1000 -r $2/DEMOS/LZ4CAT#FE1000 echo "DEMOS/SIEVE"; atftp $1 --put -l rel/SIEVE#FE1000 -r $2/DEMOS/SIEVE#FE1000 echo "DEMOS/ROD"; atftp $1 --put -l rel/apple/ROD#FE1000 -r $2/DEMOS/ROD#FE1000 +echo "DEMOS/GRTEST"; atftp $1 --put -l rel/apple/GRTEST#FE1000 -r $2/DEMOS/GRTEST#FE1000 echo "DEMOS/DGRTEST"; atftp $1 --put -l rel/apple/DGRTEST#FE1000 -r $2/DEMOS/DGRTEST#FE1000 # Music demo diff --git a/src/tftpsys b/src/tftpsys index 78b1609..e517321 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -23,7 +23,9 @@ echo "SYS/LONGJUMP"; atftp $1 --put -l rel/LONGJMP#FE1000 -r $2/SYS/LONGJMP#FE10 echo "SYS/LZ4"; atftp $1 --put -l rel/LZ4#FE1000 -r $2/SYS/LZ4#FE1000 echo "SYS/MEMMGR"; atftp $1 --put -l rel/MEMMGR#FE1000 -r $2/SYS/MEMMGR#FE1000 echo "SYS/CONIO"; atftp $1 --put -l rel/apple/CONIO#FE1000 -r $2/SYS/CONIO#FE1000 -echo "SYS/DGR"; atftp $1 --put -l rel/apple/DGR#FE1000 -r $2/SYS/DGR#FE1000 +echo "SYS/LINESPANS"; atftp $1 --put -l rel/apple/LINESPANS#FE1000 -r $2/SYS/LINESPANS#FE1000 +echo "SYS/GRLIB"; atftp $1 --put -l rel/apple/GRLIB#FE1000 -r $2/SYS/GRLIB#FE1000 +echo "SYS/DGRLIB"; atftp $1 --put -l rel/apple/DGRLIB#FE1000 -r $2/SYS/DGRLIB#FE1000 echo "SYS/FILEIO"; atftp $1 --put -l rel/apple/FILEIO#FE1000 -r $2/SYS/FILEIO#FE1000 echo "SYS/JOYBUZZ"; atftp $1 --put -l rel/apple/JOYBUZZ#FE1000 -r $2/SYS/JOYBUZZ#FE1000 echo "SYS/SNDSEQ"; atftp $1 --put -l rel/apple/SNDSEQ#FE1000 -r $2/SYS/SNDSEQ#FE1000 diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index 9b0afb0..1778f57 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -770,8 +770,25 @@ def cursleft#0 fin end def pgleft#0 + word i, strptr + + strptr = txtlinbuf=>[cursrow] + if curscol > ^strptr + i = ^strptr + else + for i = 1 to ^strptr + if ^(strptr + i) <> keyspace + break + fin + next + i-- + if i >= curscol + i = 0 + fin + fin cursoff - if curshpos(curscol - 8) + if curshpos(i) + //if curshpos(curscol - 8) drawscrn(scrntop, scrnleft) else if flags & selection @@ -794,8 +811,25 @@ def cursright#0 fin end def pgright#0 + word i, strptr + + strptr = txtlinbuf=>[cursrow] + if curscol >= ^strptr + i = curscol + 8 + else + for i = 1 to ^strptr + if ^(strptr + i) <> keyspace + break + fin + next + i-- + if curscol >= i + i = ^strptr + fin + fin cursoff - if curshpos(curscol + 8) + if curshpos(i) + //if curshpos(curscol + 8) drawscrn(scrntop, scrnleft) else if flags & selection From 0f1a15fb4a39024c37133ea49746101d67a46946 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Thu, 19 Dec 2019 18:11:59 -0800 Subject: [PATCH 056/149] SOS.INTERP launcher fix and graphics libs WIP --- src/libsrc/apple/dgrlib.pla | 2 +- src/libsrc/apple/sos.pla | 8 ++++---- src/tftpsys | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libsrc/apple/dgrlib.pla b/src/libsrc/apple/dgrlib.pla index d523f8c..d270319 100755 --- a/src/libsrc/apple/dgrlib.pla +++ b/src/libsrc/apple/dgrlib.pla @@ -391,9 +391,9 @@ export asm dgrTile(x, y, src)#0 STA (GBASE),Y ++ INC TMPH ; X COORD INC TMPH ; X COORD - LDX ESP LDA TMPH BMI -- + LDX ESP CMP ESTKH+2,X ; X2 COORD BCC -- PLP diff --git a/src/libsrc/apple/sos.pla b/src/libsrc/apple/sos.pla index 69a41af..2576bf2 100644 --- a/src/libsrc/apple/sos.pla +++ b/src/libsrc/apple/sos.pla @@ -35,10 +35,10 @@ asm sosexec(addr)#0 STA SRCL BCC + INC SRCH -+ LDA DSTL - CMP SRCL - LDA DSTH - SBC SRCH ++; LDA SRCL + CMP DSTL + LDA SRCH + SBC DSTH BCC REVCPY ; ; FORWARD COPY diff --git a/src/tftpsys b/src/tftpsys index e517321..2b1f5d8 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -30,6 +30,7 @@ echo "SYS/FILEIO"; atftp $1 --put -l rel/apple/FILEIO#FE1000 -r $2/SYS/FILEIO# echo "SYS/JOYBUZZ"; atftp $1 --put -l rel/apple/JOYBUZZ#FE1000 -r $2/SYS/JOYBUZZ#FE1000 echo "SYS/SNDSEQ"; atftp $1 --put -l rel/apple/SNDSEQ#FE1000 -r $2/SYS/SNDSEQ#FE1000 echo "SYS/MON"; atftp $1 --put -l rel/apple/MON#FE1000 -r $2/SYS/MON#FE1000 +echo "SYS/SOS"; atftp $1 --put -l rel/apple/SOS#FE1000 -r $2/SYS/SOS#FE1000 echo "SYS/PORTIO"; atftp $1 --put -l rel/apple/PORTIO#FE1000 -r $2/SYS/PORTIO#FE1000 echo "SYS/UTHERNET2";atftp $1 --put -l rel/apple/UTHERNET2#FE1000 -r $2/SYS/UTHERNET2#FE1000 echo "SYS/UTHERNET"; atftp $1 --put -l rel/apple/UTHERNET#FE1000 -r $2/SYS/UTHERNET#FE1000 From 1cd9156d8dbbad742ac25a5c207b4a4101987cc6 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Thu, 19 Dec 2019 18:13:59 -0800 Subject: [PATCH 057/149] First lores graphics library add --- src/inc/grlib.plh | 16 ++ src/libsrc/apple/grlib.pla | 484 +++++++++++++++++++++++++++++++++++++ src/samplesrc/grtest.pla | 66 +++++ 3 files changed, 566 insertions(+) create mode 100644 src/inc/grlib.plh create mode 100644 src/libsrc/apple/grlib.pla create mode 100644 src/samplesrc/grtest.pla diff --git a/src/inc/grlib.plh b/src/inc/grlib.plh new file mode 100644 index 0000000..fec0916 --- /dev/null +++ b/src/inc/grlib.plh @@ -0,0 +1,16 @@ +import grlib + predef grPlot(x, y)#0 + predef grHLin(x1, x2, y)#0 + predef grVLin(y1, y2, x)#0 + predef grBLT(x, y, width, height, src)#0 + predef grTile(x, y, src)#0 + predef grTileStr(x, y, tilestr, strlen, tilebuff)#0 + predef grFill(x, y, tile)#0 + predef grClear(clr)#0 + predef grMode#1 + predef txtMode#0 + predef grShow(page)#1 + predef grSwap#0 + predef grDrawBuf(page)#0 + predef grColor(clr)#0 +end diff --git a/src/libsrc/apple/grlib.pla b/src/libsrc/apple/grlib.pla new file mode 100644 index 0000000..881967d --- /dev/null +++ b/src/libsrc/apple/grlib.pla @@ -0,0 +1,484 @@ +include "inc/cmdsys.plh" +// +// Apple II hardware constants. +// +const showgraphics = $C050 +const showtext = $C051 +const showfull = $C052 +const showmix = $C053 +const showpage1 = $C054 +const showpage2 = $C055 +const showlores = $C056 +const showhires = $C057 +const show40 = $C00C +const show80 = $C00D +const mapmain = $C000 +const mapaux = $C001 +const an3on = $C05E +const an3off = $C05F +const ena80 = $C07E +const dis80 = $C07F +const page1 = 0 +const page2 = 1 +// +// Screen row address arrays. +// +word[] gr1rows = $0400,$0480,$0500,$0580,$0600,$0680,$0700,$0780 +word = $0428,$04A8,$0528,$05A8,$0628,$06A8,$0728,$07A8 +word = $0450,$04D0,$0550,$05D0,$0650,$06D0,$0750,$07D0 +word[] gr2rows = $0800,$0880,$0900,$0980,$0A00,$0A80,$0B00,$0B80 +word = $0828,$08A8,$0928,$09A8,$0A28,$0AA8,$0B28,$0BA8 +word = $0850,$08D0,$0950,$09D0,$0A50,$0AD0,$0B50,$0BD0 +word[] grbuff = @gr1rows, @gr2rows +word drawbufptr +byte drawpage + +asm grInc(buff) +!SOURCE "vmsrc/plvmzp.inc" +GBASL = $26 +GBASH = $27 +GBASE = GBASL +GCLR = $30 +end +// +// Plot pixel +// +export asm grPlot(x, y)#0 + ; GET ROW BUFFER ADDRESSES + LDA $3000 + STA SRCL + LDA $3001 + STA SRCH + LDA ESTKL,X ; Y COORD + AND #$FE + TAY + LDA (SRC),Y + STA GBASL + INY + LDA (SRC),Y + STA GBASH + LDY ESTKL+1,X ; X COORD + LSR ESTKL,X + LDA GCLR ; COLOR + EOR (GBASE),Y + BCS + + ; EVEN ROW + AND #$0F + BCC ++ + ; ODD ROW ++ AND #$F0 +++ EOR (GBASE),Y + STA (GBASE),Y + INX + INX + RTS +end +// +// Plot horizontal row of pixels +// +export asm grHLin(x1, x2, y)#0 + ; GET ROW BUFFER ADDRESSES + LDA $3000 + STA SRCL + LDA $3001 + STA SRCH + LDA ESTKL+1,X ; X2 COORD + STA TMPH + LDA ESTKL+0,X ; Y COORD + AND #$FE + TAY + LDA (SRC),Y + STA GBASL + INY + LDA (SRC),Y + STA GBASH + LDY ESTKL+2,X ; X1 COORD +- LDA ESTKL+0,X ; Y COORD + LSR + LDA GCLR ; COLOR + ; EVEN ROW + EOR (GBASE),Y + BCS + + AND #$0F + BCC ++ + ; ODD ROW ++ AND #$F0 +++ EOR (GBASE),Y + STA (GBASE),Y + INC ESTKL+2,X ; X1 COORD + LDY ESTKL+2,X + CPY TMPH ; X2 COORD + BCC - + BEQ - + INX + INX + INX + RTS +end +// +// Plot horizontal row of pixels +// +export asm grVLin(y1, y2, x)#0 + ; GET ROW BUFFER ADDRESSES + LDA $3000 + STA SRCL + LDA $3001 + STA SRCH + LDA ESTKL+2,X ; Y1 COORD +- AND #$FE + TAY + LDA (SRC),Y + STA GBASL + INY + LDA (SRC),Y + STA GBASH + LDA ESTKL+2,X + LSR + LDY ESTKL+0,X ; X COORD + LDA GCLR ; COLOR + ; EVEN ROW + EOR (GBASE),Y + BCS + + AND #$0F + BCC ++ + ; ODD ROW ++ AND #$F0 +++ EOR (GBASE),Y + STA (GBASE),Y + INC ESTKL+2,X ; Y1 COORD + LDA ESTKL+2,X + CMP ESTKL+1,X ; Y2 COORD + BCC - + BEQ - + INX + INX + INX + RTS +end +// +// Draw sprite +// +export asm grBLT(x, y, width, height, src)#0 + ; GET ROW BUFFER ADDRESSES + LDA $3000 + STA DSTL + LDA $3001 + STA DSTH + LDA ESTKL,X ; SPRITE + STA SRCL + LDA ESTKH,X + STA SRCH + LDA ESTKL+4,X ; X1 COORD + CMP #40 + BPL ++++ + CLC + ADC ESTKL+2,X + BMI ++++ + STA ESTKH+2,X ; X2 COORD + LDA ESTKL+3,X ; Y1 COORD + CMP #48 + BPL ++++ + STA ESTKH+3,X ; Y COORD + CLC + ADC ESTKL+1,X + BMI ++++ + STA ESTKH+1,X ; Y2 COORD + STX ESP + LDA ESTKH+3,X +- CMP #48 + BCC + + LDA SRCL ; SKIP TO NEXT ROW + CLC + ADC ESTKL+2,X ; WIDTH + STA SRCL + LDA SRCH + ADC #$00 + STA SRCH + BNE +++ ++ AND #$FE + TAY + LDA (DST),Y + STA GBASL + INY + LDA (DST),Y + STA GBASH + LDA ESTKL+4,X ; X1 COORD + STA ESTKH+4,X ; X COORD +-- CMP #40 + BCS ++ + STA TMP + LDA ESTKH+3,X ; Y COORD + LSR + LDY #$00 + LDA (SRC),Y + BMI ++ + LDY TMP + EOR (GBASE),Y + BCS oddBLT + ; EVEN ROW + AND #$0F + BCC evnBLT + ; ODD ROW +oddBLT AND #$F0 +evnBLT EOR (GBASE),Y + STA (GBASE),Y +++ INC SRCL + BNE + + INC SRCH ++ INC ESTKH+4,X ; X COORD + LDA ESTKH+4,X + BMI -- + CMP ESTKH+2,X ; X2 COORD + BCC -- ++++ INC ESTKH+3,X ; Y COORD + LDA ESTKH+3,X + BMI - + CMP ESTKH+1,X ; Y2 COORD + BCC - +++++ INX + INX + INX + INX + INX + RTS +end +// +// Draw 8x8 tile (forced to 1x2 block address) +// +export asm grTile(x, y, src)#0 + ; GET ROW BUFFER ADDRESSES + LDA $3000 + STA DSTL + LDA $3001 + STA DSTH + STX ESP + LDA ESTKL,X ; TILE + STA SRCL + LDA ESTKH,X + STA SRCH + LDA ESTKL+2,X ; X1 COORD + CMP #40 + BPL ++++ + CLC + ADC #$08 + BMI ++++ + STA ESTKH+2,X ; X2 COORD + LDA ESTKL+1,X ; Y1 COORD + CMP #48 + BPL ++++ + STA TMPL ; Y COORD + CLC + ADC #$08 + BMI ++++ + STA ESTKH+1,X ; Y2 COORD + LDA TMPL ; Y COORD +- CMP #48 + BCC + + LDA SRCL ; SKIP TO NEXT ROW + ADC #$07 ; CARRY = 1 + STA SRCL + LDA SRCH + ADC #$00 + STA SRCH + BNE +++ ++ AND #$FE + TAY + LDA (DST),Y + STA GBASL + INY + LDA (DST),Y + STA GBASH + LDA ESTKL+2,X ; X1 COORD + STA TMPH ; X COORD +-- TAY + CMP #40 + LDX #$00 + LDA (SRC,X) + INC SRCL + BNE + + INC SRCH ++ BCS ++ + STA (GBASE),Y +++ INC TMPH ; X COORD + LDA TMPH + BMI -- + LDX ESP + CMP ESTKH+2,X ; X2 COORD + BCC -- ++++ INC TMPL ; Y COORD + INC TMPL ; Y COORD + LDA TMPL + BMI - + CMP ESTKH+1,X ; Y2 COORD + BCC - +++++ INX + INX + INX + RTS +end +// +// Draw a string of tiles +// +export asm grTileStr(x, y, tilestr, strlen, tilebuff)#0 +- DEX + DEX + DEX + LDA ESTKL+7,X ; X COORD + STA ESTKL+2,X + LDA ESTKL+6,X ; Y COORD + STA ESTKL+1,X + LDA ESTKL+3,X ; TILE + STA ESTKL,X + LDA ESTKH+3,X ; TILE + STA ESTKH,X +end +asm _grTileTile + JSR $5000 + LDA ESTKL+4,X ; UPDATE X COORD + CLC + ADC #$08 + CMP #40 ; OFF RIGHT SIDE + BPL + + STA ESTKL+4,X + DEC ESTKL+1,X ; DEC STRLEN + BNE - ++ INX + INX + INX + INX + INX + RTS +end +// +// Fill a buffer with tiles +// +export asm grFill(x, y, tile)#0 + LDA ESTKL+2,X + AND #$0F + STA ESTKL+2,X + LDA ESTKL+1,X + AND #$0F + STA ESTKL+1,X + LDA #$00 + SEC + SBC ESTKL+2,X ; ORIGINAL X + STA ESTKL+2,X + STA ESTKH+2,X + LDA #$00 + SEC + SBC ESTKL+1,X + STA ESTKL+1,X +- DEX + DEX + DEX + LDA ESTKL+5,X ; X COORD + STA ESTKL+2,X + LDA ESTKL+4,X ; Y COORD + STA ESTKL+1,X + LDA ESTKL+3,X ; TILE + STA ESTKL,X + LDA ESTKH+3,X ; TILE + STA ESTKH,X +end +asm _grFillTile + JSR $5000 + LDA ESTKL+2,X ; UPDATE X COORD + CLC + ADC #$08 + STA ESTKL+2,X + CMP #40 ; OFF RIGHT SIDE? + BMI - + LDA ESTKH+2,X ; RESTORE X COORD + STA ESTKL+2,X + LDA ESTKL+1,X ; UPDATE Y COORD + CLC + ADC #$08 + STA ESTKL+1,X + CMP #48 ; OFF BOTTOM? + BMI - + INX + INX + INX + RTS +end +// +// Clear the buffer +// +export def grClear(clr)#0 + byte[32] clrtile + + clr = (clr & $0F) | (clr << 4) + clr = (clr & $FF) | (clr << 8) + memset(@clrtile, clr, 32) + grFill(0, 0, @clrtile) +end +// +// Set lores graphics, return draw buffer +// +export def grMode#1 + ^showlores + ^showfull + ^showgraphics + ^showpage1 + ^ena80 = 0 + ^show40 = 0 + ^mapmain = 0 + ^an3off + drawpage = 1 + drawbufptr = grbuff[1] + return 1 +end +// +// Set text mode +// +export def txtMode#0 + ^showtext + ^showpage1 + ^ena80 = 0 + ^show40 = 0 + ^mapmain = 0 + ^an3off + call($FC58, 0, 0, 0, 0) // home() +end +// +// Set display page, return other page +// +export def grShow(page)#1 + page = page & 1 + ^(showpage1 + page) + return page ^ 1 +end +export def grSwap#0 + ^(showpage1 + drawpage) + drawpage = drawpage ^ 1 + drawbufptr = grbuff[drawpage] +end +export def grDrawBuf(page)#0 + drawpage = page + drawbufptr = grbuff[drawpage] +end +// +// Set color for clear & plot routines +// +export def grColor(clr)#0 + ^$30 = (clr & $0F) | (clr << 4) +end +// +// Assembly fixups +// +_grTileTile:1 = @grTile +_grFillTile:1 = @grTile +// +// Fixups for drawbufptr +// +grPlot:1 = @drawbufptr +grPlot:6 = @drawbufptr+1 +grHLin:1 = @drawbufptr +grHLin:6 = @drawbufptr+1 +grVLin:1 = @drawbufptr +grVLin:6 = @drawbufptr+1 +grBLT:1 = @drawbufptr +grBLT:6 = @drawbufptr+1 +grTile:1 = @drawbufptr +grTile:6 = @drawbufptr+1 +done diff --git a/src/samplesrc/grtest.pla b/src/samplesrc/grtest.pla new file mode 100644 index 0000000..da6e3fc --- /dev/null +++ b/src/samplesrc/grtest.pla @@ -0,0 +1,66 @@ +include "inc/cmdsys.plh" +include "inc/grlib.plh" +include "inc/linespans.plh" +sysflags restxt1|restxt2 // Reserve all text pages + +byte[] sprite1 = $80,$80,$00,$00,$00,$00,$80,$80 +byte[] = $80,$00,$0A,$0A,$0A,$0A,$00,$80 +byte[] = $00,$0A,$0F,$0F,$0F,$0F,$0A,$00 +byte[] = $00,$0A,$0F,$80,$80,$0F,$0A,$00 +byte[] = $00,$0A,$0F,$80,$80,$0F,$0A,$00 +byte[] = $00,$0A,$0F,$0F,$0F,$0F,$0A,$00 +byte[] = $80,$00,$0A,$0A,$0A,$0A,$00,$80 +byte[] = $80,$80,$00,$00,$00,$00,$80,$80 + +byte[] tile1 = $88,$11,$88,$11,$88,$11,$AA,$00 +byte[] = $88,$11,$88,$11,$88,$11,$AA,$00 +byte[] = $88,$11,$88,$11,$88,$11,$AA,$00 +byte[] = $0A,$05,$0A,$05,$0A,$05,$0A,$00 + +// +// Test routine +// +def grTest#0 + byte b, l, k + word i, j, ii, ij + + b = grMode() + grDrawBuf(0) + for k = 15 downto 0 + grClear(k) + next + setlinespans(@grHLin, @grVLin) + for l = 0 to 39 + grColor(l) + linetospans(0, 0, l, 47) + next + for l = 47 downto 0 + grColor(l) + linetospans(0, 0, 39, l) + next + ii = 2 + ij = -1 + i = 20 + j = 10 + ^$C010 + grDrawBuf(1) + while ^$C000 < 128 + grFill(k, k, @tile1) + grBLT(i, j, 8, 8, @sprite1) + grSwap + k++ + i = i + ii + if i < -3 or i > 35 + ii = -ii + fin + j = j + ij + if j < -3 or j > 43 + ij = -ij + fin + loop + ^$C010 + txtMode +end + +grTest +done From ae5e5b42371bf7563b2f6f94b9ebd92b3b70f9b2 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 19 Dec 2019 18:30:22 -0800 Subject: [PATCH 058/149] GRLIB WIP --- src/libsrc/apple/grlib.pla | 6 +++++- src/samplesrc/grtest.pla | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libsrc/apple/grlib.pla b/src/libsrc/apple/grlib.pla index 881967d..a534e3c 100644 --- a/src/libsrc/apple/grlib.pla +++ b/src/libsrc/apple/grlib.pla @@ -219,7 +219,11 @@ export asm grBLT(x, y, width, height, src)#0 AND #$0F BCC evnBLT ; ODD ROW -oddBLT AND #$F0 +oddBLT ASL + ASL + ASL + ASL + AND #$F0 evnBLT EOR (GBASE),Y STA (GBASE),Y ++ INC SRCL diff --git a/src/samplesrc/grtest.pla b/src/samplesrc/grtest.pla index da6e3fc..e79817b 100644 --- a/src/samplesrc/grtest.pla +++ b/src/samplesrc/grtest.pla @@ -12,10 +12,10 @@ byte[] = $00,$0A,$0F,$0F,$0F,$0F,$0A,$00 byte[] = $80,$00,$0A,$0A,$0A,$0A,$00,$80 byte[] = $80,$80,$00,$00,$00,$00,$80,$80 -byte[] tile1 = $88,$11,$88,$11,$88,$11,$AA,$00 -byte[] = $88,$11,$88,$11,$88,$11,$AA,$00 -byte[] = $88,$11,$88,$11,$88,$11,$AA,$00 -byte[] = $0A,$05,$0A,$05,$0A,$05,$0A,$00 +byte[] tile1 = $11,$11,$11,$11,$11,$11,$55,$00 +byte[] = $11,$11,$11,$11,$11,$11,$55,$00 +byte[] = $11,$11,$11,$11,$11,$11,$55,$00 +byte[] = $05,$05,$05,$05,$05,$05,$05,$00 // // Test routine From 44c8bf9a1337d6abc395cc429ae491253c24640f Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 19 Dec 2019 18:48:14 -0800 Subject: [PATCH 059/149] Premature GRLIB checking --- src/libsrc/apple/grlib.pla | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libsrc/apple/grlib.pla b/src/libsrc/apple/grlib.pla index a534e3c..ae931d9 100644 --- a/src/libsrc/apple/grlib.pla +++ b/src/libsrc/apple/grlib.pla @@ -213,9 +213,9 @@ export asm grBLT(x, y, width, height, src)#0 LDA (SRC),Y BMI ++ LDY TMP - EOR (GBASE),Y BCS oddBLT ; EVEN ROW + EOR (GBASE),Y AND #$0F BCC evnBLT ; ODD ROW @@ -223,6 +223,7 @@ oddBLT ASL ASL ASL ASL + EOR (GBASE),Y AND #$F0 evnBLT EOR (GBASE),Y STA (GBASE),Y From af90f40f32d52f3cd7c8f07c51777bd6318df413 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 19 Dec 2019 19:38:26 -0800 Subject: [PATCH 060/149] in-line simple line routine --- src/samplesrc/hgrtest.pla | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index b865f24..cb3c5cc 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -190,14 +190,14 @@ def simpleline(x1, y1, x2, y2)#0 sy = -sy; x1, x2 = x2, x1 fin err = dy2 - dx2 / 2 - ofst, pixofst = divmod7(x1) + ofst, pixofst = divmod(x1, 7) pptr = (hgrscan[y1] | hgr1) + ofst - clr = curhclr.[ofst & 1] + clr = curhclr.[ofst & 1] for x = x1 to x2 pmask = hbmask[pixofst] ^pptr = (^pptr & ~pmask) | (clr & pmask) pixofst++ - if pixofst > 7 + if pixofst > 6 pixofst = 0 pptr++ ofst++ @@ -215,7 +215,7 @@ def simpleline(x1, y1, x2, y2)#0 sx = -sx; y1, y2 = y2, y1 fin err = dx2 - dy2 / 2 - ofst, pixofst = divmod7(x1) + ofst, pixofst = divmod(x1, 7) clr = curhclr.[ofst & 1] pmask = hbmask[pixofst] for y = y1 to y2 @@ -225,14 +225,14 @@ def simpleline(x1, y1, x2, y2)#0 err = err - dy2 if sx > 0 pixofst++ - if pixofst > 7 + if pixofst > 6 pixofst = 0 ofst++ clr = curhclr.[ofst & 1] fin else if pixofst == 0 - pixofst = 7 + pixofst = 6 ofst-- clr = curhclr.[ofst & 1] else From 8df7cea4a0db9462e6db8ed81bf6df033c62d54c Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 19 Dec 2019 20:42:37 -0800 Subject: [PATCH 061/149] Add optional goto line number to command line load filename --- src/toolsrc/ed.pla | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index 1778f57..819509f 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -430,6 +430,7 @@ def readtxt(filename, startline)#0 numlines++ fin fin + putln end def writetxt(filename)#0 byte txtbuf[81], refnum @@ -456,6 +457,7 @@ def writetxt(filename)#0 if !(i & $0F); putc('.'); fin next fileio:close(refnum) + putln end // // Screen routines @@ -1713,6 +1715,14 @@ if ^arg strcpy(@filename, arg) puts(@filename) readtxt(@filename, 0) + arg = argNext(arg) + if ^arg + cursrow = strtonum(arg) + if cursrow + curshpos(0) + cursvpos(cursrow - 1) + fin + fin fin curschr = '+' flags = flags | insmode | gutter From 15b4551b2ab69c54ffb063462c4ede9e825b553d Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 20 Dec 2019 00:49:12 -0800 Subject: [PATCH 062/149] Editor write file change to identify very rare write corruption --- src/toolsrc/ed.pla | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index 819509f..dd1cb3a 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -142,9 +142,14 @@ asm lncpy(dststr, srcstr)#0 INX LDY #$00 LDA (SRC),Y + CMP #80 + BCC + + LDA #79 + CLC ++ ADC #$01 ; APPEND CR TO END OF STRING + STA (DST),Y TAY - LDA #$00 - INY + LDA #$0D STA (DST),Y DEY BEQ ++ @@ -156,9 +161,7 @@ CPLNLP LDA (SRC),Y STA (DST),Y DEY BNE CPLNLP - LDA (SRC),Y -++ STA (DST),Y - RTS +++ RTS end asm lnupcpy(dststr, srcstr)#0 LDA ESTKL,X @@ -173,11 +176,11 @@ asm lnupcpy(dststr, srcstr)#0 INX LDY #$00 LDA (SRC),Y + CMP #80 + BCC + + LDA #79 ++ STA (DST),Y TAY - LDA #$00 - INY - STA (DST),Y - DEY BEQ +++ CPUPLP LDA (SRC),Y CMP #$20 @@ -193,9 +196,7 @@ CPUPLP LDA (SRC),Y ++ STA (DST),Y DEY BNE CPUPLP - LDA (SRC),Y -+++ STA (DST),Y - RTS ++++ RTS end def bell#0 putc($07) @@ -433,9 +434,9 @@ def readtxt(filename, startline)#0 putln end def writetxt(filename)#0 - byte txtbuf[81], refnum - byte j, chr word i, strptr + byte refnum, j, chr + byte txtbuf[81] fileio:destroy(filename) fileio:create(filename, $04, $00) // full access, TXT file @@ -452,7 +453,6 @@ def writetxt(filename)#0 // for i = 0 to numlines - 1 lncpy(@txtbuf, txtlinbuf=>[i]) - txtbuf++; txtbuf[txtbuf] = $0D // Add CR to end of line fileio:write(refnum, @txtbuf + 1, txtbuf) if !(i & $0F); putc('.'); fin next From 3d91e4175b9db715188b46fc2456b374296771d7 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 20 Dec 2019 03:36:03 -0800 Subject: [PATCH 063/149] editine c;eanip. still loses ctrl-d once in awhile --- src/toolsrc/ed.pla | 92 +++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 54 deletions(-) diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index dd1cb3a..1bf0458 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -406,7 +406,7 @@ end // File routines // def readtxt(filename, startline)#0 - byte txtbuf[81], refnum, i, j + byte refnum, i, j, txtbuf[MAXLNLEN+2] refnum = fileio:open(filename) if refnum @@ -436,7 +436,7 @@ end def writetxt(filename)#0 word i, strptr byte refnum, j, chr - byte txtbuf[81] + byte txtbuf[MAXLNLEN+2] fileio:destroy(filename) fileio:create(filename, $04, $00) // full access, TXT file @@ -844,7 +844,7 @@ end // Find string in text // def findline(strptr, start)#1 - byte upstr[MAXLNLEN+1], scan, i + byte scan, i, upstr[MAXLNLEN+1] if ^strptr >= findstr lnupcpy(@upstr, strptr) @@ -1312,89 +1312,73 @@ def editkey(key) return FALSE end def editline(key) - byte editstr[MAXLNLEN+1], localchange, need word undoline + byte localchange, editstr[], editlen, editchars[MAXLNLEN+1] localchange = FALSE if (editkey(key)) localchange = TRUE - memset(@editstr + 1, $A0A0, MAXLNLEN) - strstripcpy(@editstr, txtlinbuf=>[cursrow]) undoline = txtlinbuf=>[cursrow] + memset(@editchars, $A0A0, MAXLNLEN) + memcpy(@editchars, undoline + 1, ^undoline) + editlen = MAXLNLEN txtlinbuf=>[cursrow] = @editstr repeat - if key >= keyspace - if key == keydelete + when key + is keyctrld + memcpy(@editchars[curscol], @editchars[curscol + 1], MAXLNLEN - 1 - curscol) + editchars[MAXLNLEN - 1] = keyspace + cursoff + drawrow(cursy, scrnleft, @editstr) + curson + break + is keyctrlr + memset(@editchars, $A0A0, MAXLNLEN) + memcpy(@editchars, undoline + 1, ^undoline) + cursoff + drawrow(cursy, scrnleft, @editstr) + curson + localchange = FALSE + break + is keydelete if curscol > 0 - if curscol <= editstr - memcpy(@editstr[curscol], @editstr[curscol + 1], editstr - curscol) - editstr-- - fin + curscol-- + memcpy(@editchars[curscol], @editchars[curscol + 1], MAXLNLEN - 1 - curscol) + editchars[MAXLNLEN - 1] = keyspace cursoff - if curshpos(curscol - 1) + if curshpos(curscol) drawscrn(scrntop, scrnleft) else drawrow(cursy, scrnleft, @editstr) fin curson fin - elsif curscol < MAXLNLEN - curscol++ + break + otherwise if flags & insmode - if editstr < MAXLNLEN or editstr.MAXLNLEN == keyspace - editstr++ - if curscol >= editstr - editstr = curscol - else - memcpy(@editstr[curscol + 1], @editstr[curscol], editstr - curscol) - fin + if editchars[MAXLNLEN - 1] == keyspace + memcpy(@editchars[curscol+1], @editchars[curscol], MAXLNLEN - 1 - curscol) else - curscol-- - key = editstr[curscol] bell - fin - else - if curscol > editstr - editstr = curscol + break fin fin - editstr[curscol] = caseconv(key) + editchars[curscol] = caseconv(key) cursoff - if curshpos(curscol) + if curshpos(curscol + 1) drawscrn(scrntop, scrnleft) else drawrow(cursy, scrnleft, @editstr) fin curson - else - bell - fin - elsif key == keyctrld - if curscol < editstr - strstripcpy(undoline, @editstr) - memcpy(@editstr[curscol + 1], @editstr[curscol + 2], editstr - curscol) - editstr-- - cursoff - drawrow(cursy, scrnleft, @editstr) - curson - fin - elsif key == keyctrlr - strstripcpy(@editstr, undoline) - cursoff - drawrow(cursy, scrnleft, @editstr) - curson - localchange = FALSE - fin + break + wend key = keyin() until not editkey(key) if localchange flags = flags | changed delstr(undoline) - if editstr - txtlinbuf=>[cursrow] = newstr(@editstr) - else - txtlinbuf=>[cursrow] = @nullstr - fin + txtlinbuf=>[cursrow] = newstr(@editstr) else txtlinbuf=>[cursrow] = undoline fin From 3161692d4a5fa3efd231ae08d1ec6d144bc8636a Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 20 Dec 2019 10:20:09 -0800 Subject: [PATCH 064/149] Fix line edit changed flag --- src/toolsrc/ed.pla | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index 1bf0458..4e8d15d 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -1313,16 +1313,16 @@ def editkey(key) end def editline(key) word undoline - byte localchange, editstr[], editlen, editchars[MAXLNLEN+1] + byte undopos, localchange, editstr[], editlen, editchars[MAXLNLEN+1] - localchange = FALSE if (editkey(key)) - localchange = TRUE + undopos = curscol undoline = txtlinbuf=>[cursrow] + editlen = MAXLNLEN memset(@editchars, $A0A0, MAXLNLEN) memcpy(@editchars, undoline + 1, ^undoline) - editlen = MAXLNLEN txtlinbuf=>[cursrow] = @editstr + localchange = FALSE repeat when key is keyctrld @@ -1331,27 +1331,32 @@ def editline(key) cursoff drawrow(cursy, scrnleft, @editstr) curson + localchange = TRUE break is keyctrlr memset(@editchars, $A0A0, MAXLNLEN) memcpy(@editchars, undoline + 1, ^undoline) cursoff - drawrow(cursy, scrnleft, @editstr) + if curshpos(undopos) + drawscrn(scrntop, scrnleft) + else + drawrow(cursy, scrnleft, @editstr) + fin curson localchange = FALSE break is keydelete if curscol > 0 - curscol-- - memcpy(@editchars[curscol], @editchars[curscol + 1], MAXLNLEN - 1 - curscol) + memcpy(@editchars[curscol - 1], @editchars[curscol], MAXLNLEN - curscol) editchars[MAXLNLEN - 1] = keyspace cursoff - if curshpos(curscol) + if curshpos(curscol - 1) drawscrn(scrntop, scrnleft) else drawrow(cursy, scrnleft, @editstr) fin curson + localchange = TRUE fin break otherwise @@ -1371,6 +1376,7 @@ def editline(key) drawrow(cursy, scrnleft, @editstr) fin curson + localchange = TRUE break wend key = keyin() From ea6656d05b0ba12b7a771b2e10f62644385695af Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Fri, 20 Dec 2019 16:26:10 -0800 Subject: [PATCH 065/149] Basic file managing utilites --- src/inc/fileio.plh | 1 + src/libsrc/apple/fileio.pla | 20 ++++- src/libsrc/cat.pla | 93 +++++++++++++++++++++++ src/libsrc/copy.pla | 146 ++++++++++++++++++++++++++++++++++++ src/libsrc/del.pla | 62 +++++++++++++++ src/libsrc/newdir.pla | 24 ++++++ src/libsrc/ren.pla | 34 +++++++++ src/libsrc/type.pla | 83 ++++++++++++++++++++ src/makefile | 27 ++++++- src/mkrel | 5 ++ src/tftprel | 1 + src/tftpsys | 5 -- 12 files changed, 493 insertions(+), 8 deletions(-) create mode 100644 src/libsrc/cat.pla create mode 100644 src/libsrc/copy.pla create mode 100644 src/libsrc/del.pla create mode 100644 src/libsrc/newdir.pla create mode 100644 src/libsrc/ren.pla create mode 100644 src/libsrc/type.pla diff --git a/src/inc/fileio.plh b/src/inc/fileio.plh index 9b88405..ba7ee72 100644 --- a/src/inc/fileio.plh +++ b/src/inc/fileio.plh @@ -45,6 +45,7 @@ import fileio word write word create word destroy + word rename word newline word online word readblock diff --git a/src/libsrc/apple/fileio.pla b/src/libsrc/apple/fileio.pla index f006ff5..d074c6a 100644 --- a/src/libsrc/apple/fileio.pla +++ b/src/libsrc/apple/fileio.pla @@ -34,20 +34,21 @@ struc t_fileio word write word create word destroy + word rename word newline word online word readblock word writeblock end predef a2getpfx(path), a23setpfx(path), a2getfileinfo(path, fileinfo), a23geteof(refnum), a2iobufs(iobufs), a2open(path), a2close(refnum) -predef a23read(refnum, buf, len), a2write(refnum, buf, len), a2create(path, type, aux), a23destroy(path) +predef a23read(refnum, buf, len), a2write(refnum, buf, len), a2create(path, type, aux), a23destroy(path), a23rename(path, newpath) predef a2newline(refnum, emask, nlchar), a2online(unit, buf), a2readblock(unit, buf, block), a2writeblock(unit, buf, block) // // Exported function table. // word fileio[] word = @a2getpfx, @a23setpfx, @a2getfileinfo, @a23geteof, @a2iobufs, @a2open, @a2close -word = @a23read, @a2write, @a2create, @a23destroy +word = @a23read, @a2write, @a2create, @a23destroy, @a23rename word = @a2newline, @a2online, @a2readblock, @a2writeblock // // SOS/ProDOS error code @@ -293,6 +294,7 @@ def a3create(path, type, aux) return perr end def a1destroy(path) + perr = $01 return perr end def a23destroy(path) @@ -303,6 +305,19 @@ def a23destroy(path) perr = syscall($C1, @params) return perr end +def a1rename(oldpath, newpath) + perr = $01 + return perr +end +def a23rename(path, newpath) + byte params[5] + + params.0 = 2 + params:1 = path + params:3 = newpath + perr = syscall($C2, @params) + return perr +end def a1newline(refnum, emask, nlchar) return perr end @@ -434,6 +449,7 @@ when MACHID & MACHID_MODEL fileio:write = @a1write fileio:create = @a1create fileio:destroy = @a1destroy + fileio:rename = @a1rename fileio:newline = @a1newline fileio:online = @a1online fileio:readblock = @a13readblock diff --git a/src/libsrc/cat.pla b/src/libsrc/cat.pla new file mode 100644 index 0000000..fd10654 --- /dev/null +++ b/src/libsrc/cat.pla @@ -0,0 +1,93 @@ +include "inc/cmdsys.plh" +include "inc/args.plh" +include "inc/fileio.plh" + +var arg, refnum, dirbuf +var page, firstblk, entrylen, entriesblk, i, entry, filecnt + +char[64] path +res[t_fileinfo] fileinfo +// +// Print out a directory entry +// +def printentry()#0 + byte type, len + + type = ^entry + len = type & $0F + ^entry = len + puts(entry) + type = ' ' + when entry->$10 + is $0F // Is it a directory? + type = '/' + break + is $FF // SYSTEM file + type = '-' + break + is $FE // REL file + type = '+' + wend + putc(type) + for len = 16 - len downto 0 + putc(' ') + next + putc('$'); puth(entry->$10) + putln +end +// +// Check arguments and file types +// +arg = argNext(argFirst) +if ^arg + strcpy(@path, arg) +else + fileio:getpfx(@path) +fin +refnum = fileio:open(@path) +if refnum + page = 0 + filecnt = 0 + firstblk = 1 + dirbuf = heapallocalign(512, 8, 0) + repeat + if fileio:read(refnum, dirbuf, 512) == 512 + // + // Skip block pointers + // + entry = dirbuf + 4 + if firstblk + // + // Pull out revelant details from the first block + // + entrylen = dirbuf->$23 + entriesblk = dirbuf->$24 + filecnt = dirbuf=>$25 + entry = entry + entrylen + fin + for i = firstblk to entriesblk + // + // Print directory entry details + // + if ^entry + printentry() + filecnt-- + fin + entry = entry + entrylen + // + // Pause display every screenfull + // + page++ + if page == 23 + getc + page = 0 + fin + next + firstblk = 0 + fin + until filecnt == 0 + fileio:close(0) +else + puts("Unable to open: "); puts(@path); putln +fin +done diff --git a/src/libsrc/copy.pla b/src/libsrc/copy.pla new file mode 100644 index 0000000..881faa9 --- /dev/null +++ b/src/libsrc/copy.pla @@ -0,0 +1,146 @@ +include "inc/cmdsys.plh" +include "inc/args.plh" +include "inc/fileio.plh" + +const MAXBUFSIZE = 16384 +var arg, srcref, dstref, copybuff, copysize, copyxfer +char[64] srcfilename, dstfilename +res[t_fileinfo] srcfileinfo, dstfileinfo +// +// Handy string functions +// +def filefrompath(filestr, pathstr)#0 + byte i + + for i = ^pathstr + 1 downto 1 + if pathstr->[i] == '/' + break + fin + next + ^filestr = ^pathstr - i + memcpy(filestr + 1, pathstr + 1 + i, ^filestr) +end +// +// Check destination filename +// +def checkdst + char[17] basefile + // + // Check if destination exists + // + if fileio:getfileinfo(@dstfilename, @dstfileinfo) == FILE_ERR_OK + // + // Check if copying into a directory + // + if dstfileinfo.file_type == $0F + if dstfilename[dstfilename] <> '/' + // + // Add path seperator + // + dstfilename++ + dstfilename[dstfilename] = '/' + fin + filefrompath(@basefile, @srcfilename) + strcat(@dstfilename, @basefile) + if fileio:getfileinfo(@dstfilename, @dstfileinfo) == FILE_ERR_OK + // + // Check if *that* is a directory + // + if dstfileinfo.file_type == $0F + puts("Destination is a directory filename\n") + return FALSE + fin + else + return TRUE + fin + fin + // + // Remove existing file + // + fileio:destroy(@dstfilename) + fin + return TRUE +end +// +// Check arguments and file types +// +arg = argNext(argFirst) +if ^arg + strcpy(@srcfilename, arg) + fileio:iobufalloc(2) // Reserve two I/O buffers + if fileio:getfileinfo(@srcfilename, @srcfileinfo) == FILE_ERR_OK + // + // Check that source isn't a directory - can't handle that yet + // + if srcfileinfo.file_type == $0F + puts("Can't copy directories (yet)\n") + return + fin + else + // + // File not found + // + puts("File not found: "); puts(@srcfilename); putln + return + fin + srcref = fileio:open(@srcfilename) + if srcref + arg = argNext(arg) + if ^arg + strcpy(@dstfilename, arg) + if checkdst() + // + // Create the destination file and open for writing + // + if fileio:create(@dstfilename, srcfileinfo.file_type, srcfileinfo:aux_type) == FILE_ERR_OK + dstref = fileio:open(@dstfilename) + if dstref + // + // Let the copying begin + // + copysize = MAXBUFSIZE + while isult(heapavail, copysize + 512) + copysize = copysize / 2 + loop + copybuff = heapalloc(copysize) + if copybuff + // + // Round buffer to page boundary for faster transfers + // + copybuff = (copybuff + $FF) & $FF00 + copyxfer = fileio:read(srcref, copybuff, copysize) + while copyxfer + if fileio:write(dstref, copybuff, copyxfer) <> copyxfer + puts("Error writing: "); puts(@dstfilename); putln + break + fin + copyxfer = fileio:read(srcref, copybuff, copysize) + loop + else + puts("No memory available!\n") + fin + else + puts("Unable to open: "); puts(@dstfilename); putln + fin + else + puts("Unable to create: "); puts(@dstfilename); putln + fin + fin + fileio:close(0) + return + fin + else + // + // Unable to open source + // + puts("Unable to open: "); puts(@srcfilename); putln + return + fin + // + // Close all files + // + fileio:close(0) + return +fin +puts("Usage: +COPY SRCFILE DEST\n") +done diff --git a/src/libsrc/del.pla b/src/libsrc/del.pla new file mode 100644 index 0000000..83a07f9 --- /dev/null +++ b/src/libsrc/del.pla @@ -0,0 +1,62 @@ +include "inc/cmdsys.plh" +include "inc/args.plh" +include "inc/fileio.plh" + +char[64] filename +var arg + +// +// Check filename +// +def checkfile + var refnum, dirbuf + res[t_fileinfo] fileinfo + + // + // Check if file exists + // + if fileio:getfileinfo(@filename, @fileinfo) == FILE_ERR_OK + // + // Check if deleting a directory + // + if fileinfo.file_type == $0F + refnum = fileio:open(@filename) + if refnum + // + // Check for files inside directory + // + dirbuf = heapalloc(512) + if fileio:read(refnum, dirbuf, 512) == 512 + fileio:close(refnum) + if dirbuf=>$25 // File count in directory + puts("Directory not empty: "); puts(@filename); putln + return FALSE + fin + fin + fin + fin + return TRUE + fin + puts("File not found: "); puts(@filename); putln + return FALSE +end +// +// Check arguments and file types +// +arg = argNext(argFirst) +if ^arg + strcpy(@filename, arg) + if checkfile() + // + // Remove existing file + // + fileio:destroy(@filename) + fin + // + // Close all files + // + fileio:close(0) + return +fin +puts("Usage: +DEL FILE\n") +done diff --git a/src/libsrc/newdir.pla b/src/libsrc/newdir.pla new file mode 100644 index 0000000..79226b8 --- /dev/null +++ b/src/libsrc/newdir.pla @@ -0,0 +1,24 @@ +include "inc/cmdsys.plh" +include "inc/args.plh" +include "inc/fileio.plh" + +var arg +char[64] filename +res[t_fileinfo] fileinfo +// +// Check arguments and file types +// +arg = argNext(argFirst) +if ^arg + strcpy(@filename, arg) + if fileio:getfileinfo(@filename, @fileinfo) == FILE_ERR_OK + puts("File exists: "); puts(@filename); putln + else + if fileio:create(@filename, $0F, $0000) <> FILE_ERR_OK + puts("Unable to create directory: "); puts(@filename); putln + fin + fin + return +fin +puts("Usage: +NEWDIR PATH\n") +done diff --git a/src/libsrc/ren.pla b/src/libsrc/ren.pla new file mode 100644 index 0000000..f2f5f36 --- /dev/null +++ b/src/libsrc/ren.pla @@ -0,0 +1,34 @@ +include "inc/cmdsys.plh" +include "inc/args.plh" +include "inc/fileio.plh" + +var arg +char[64] oldfilename, newfilename +res[t_fileinfo] fileinfo +// +// Check arguments and file types +// +arg = argNext(argFirst) +if ^arg + strcpy(@oldfilename, arg) + if fileio:getfileinfo(@oldfilename, @fileinfo) <> FILE_ERR_OK + // + // File not found + // + puts("File not found: "); puts(@oldfilename); putln + return + fin + arg = argNext(arg) + if ^arg + strcpy(@newfilename, arg) + // + // Rename file + // + if fileio:rename(@oldfilename, @newfilename) <> FILE_ERR_OK + puts("Unable to rename: "); puts(@oldfilename); puts(" --> "); puts(@newfilename); putln + fin + return + fin +fin +puts("Usage: +REN OLDNAME NEWNAME\n") +done diff --git a/src/libsrc/type.pla b/src/libsrc/type.pla new file mode 100644 index 0000000..10ac895 --- /dev/null +++ b/src/libsrc/type.pla @@ -0,0 +1,83 @@ +include "inc/cmdsys.plh" +include "inc/args.plh" +include "inc/fileio.plh" + +char[64] filename +var arg +// +// Convert byte to two hex chars +// +def btoh(cptr, b)#0 + byte h + + h = ((b >> 4) & $0F) + '0' + if h > '9' + h = h + 7 + fin + ^cptr = h + cptr++ + h = (b & $0F) + '0' + if h > '9' + h = h + 7 + fin + ^cptr = h +end +// +// Check filename +// +def checkfile + var refnum, dirbuf + res[t_fileinfo] fileinfo + + // + // Check if file exists + // + if fileio:getfileinfo(@filename, @fileinfo) == FILE_ERR_OK + // + // Check if deleting a directory + // + if fileinfo.file_type == $0F + refnum = fileio:open(@filename) + if refnum + // + // Check for files inside directory + // + dirbuf = heapalloc(512) + if fileio:read(refnum, dirbuf, 512) == 512 + fileio:close(refnum) + if dirbuf=>$25 // File count in directory + puts("Directory not empty: "); puts(@filename); putln + return FALSE + fin + fin + fin + fin + return TRUE + fin + puts("File not found: "); puts(@filename); putln + return FALSE +end +// +// Check arguments and file types +// +arg = argNext(argFirst) +if ^arg + strcpy(@filename, arg) + // + // Check if file exists + // + if fileio:getfileinfo(@filename, @fileinfo) == FILE_ERR_OK + // + // Check if re-typing a directory + // + if fileinfo.file_type <> $0F + fin + fin + // + // Close all files + // + fileio:close(0) + return +fin +puts("Usage: +TYPE FILE [HEXTYPE [HEXAUX]]\n") +done diff --git a/src/makefile b/src/makefile index e8d27d9..efe8a7f 100755 --- a/src/makefile +++ b/src/makefile @@ -18,6 +18,11 @@ JIT16 = rel/apple/JIT16\#FE1000 JITUNE = rel/apple/JITUNE\#FE1000 SOS = rel/apple/SOS\#FE1000 ROD = rel/apple/ROD\#FE1000 +COPY = rel/COPY\#FE1000 +DEL = rel/DEL\#FE1000 +REN = rel/REN\#FE1000 +CAT = rel/CAT\#FE1000 +NEWDIR = rel/NEWDIR\#FE1000 SIEVE = rel/SIEVE\#FE1000 PRIMEGAP = rel/PRIMEGAP\#FE1000 ARGS = rel/ARGS\#FE1000 @@ -90,7 +95,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -409,6 +414,26 @@ $(MON): samplesrc/mon.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/mon.pla > samplesrc/mon.a acme --setpc 4094 -o $(MON) samplesrc/mon.a +$(COPY): libsrc/copy.pla $(PLVM03) $(PLASM) + ./$(PLASM) -AMOW < libsrc/copy.pla > libsrc/copy.a + acme --setpc 4094 -o $(COPY) libsrc/copy.a + +$(DEL): libsrc/del.pla $(PLVM03) $(PLASM) + ./$(PLASM) -AMOW < libsrc/del.pla > libsrc/del.a + acme --setpc 4094 -o $(DEL) libsrc/del.a + +$(REN): libsrc/ren.pla $(PLVM03) $(PLASM) + ./$(PLASM) -AMOW < libsrc/ren.pla > libsrc/ren.a + acme --setpc 4094 -o $(REN) libsrc/ren.a + +$(CAT): libsrc/cat.pla $(PLVM03) $(PLASM) + ./$(PLASM) -AMOW < libsrc/cat.pla > libsrc/cat.a + acme --setpc 4094 -o $(CAT) libsrc/cat.a + +$(NEWDIR): libsrc/newdir.pla $(PLVM03) $(PLASM) + ./$(PLASM) -AMOW < libsrc/newdir.pla > libsrc/newdir.a + acme --setpc 4094 -o $(NEWDIR) libsrc/newdir.a + $(SOS): libsrc/apple/sos.pla $(PLVM03) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/sos.pla > libsrc/apple/sos.a acme --setpc 4094 -o $(SOS) libsrc/apple/sos.a diff --git a/src/mkrel b/src/mkrel index f82a996..57cc74b 100755 --- a/src/mkrel +++ b/src/mkrel @@ -12,6 +12,11 @@ cp rel/apple/CONIO#FE1000 prodos/sys/CONIO.REL cp rel/apple/LINESPANS#FE1000 prodos/sys/LINESPANS.REL cp rel/apple/GRLIB#FE1000 prodos/sys/GRLIB.REL cp rel/apple/DGRLIB#FE1000 prodos/sys/DGRLIB.REL +cp rel/COPY#FE1000 prodos/sys/COPY.REL +cp rel/DEL#FE1000 prodos/sys/DEL.REL +cp rel/REN#FE1000 prodos/sys/REN.REL +cp rel/CAT#FE1000 prodos/sys/CAT.REL +cp rel/NEWDIR#FE1000 prodos/sys/NEWDIR.REL cp rel/ARGS#FE1000 prodos/sys/ARGS.REL cp rel/ED#FE1000 prodos/sys/ED.REL cp rel/FIBER#FE1000 prodos/sys/FIBER.REL diff --git a/src/tftprel b/src/tftprel index 3fbd73f..2d20b6e 100755 --- a/src/tftprel +++ b/src/tftprel @@ -1,6 +1,7 @@ #!/bin/bash ./tftpsys $1 $2 +./tftputil $1 $2 ./tftpsane $1 $2 ./tftpbld $1 $2 ./tftpdemos $1 $2 diff --git a/src/tftpsys b/src/tftpsys index 2b1f5d8..4cffe31 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -13,14 +13,11 @@ echo "SYS/JITUNE"; atftp $1 --put -l rel/apple/JITUNE#FE1000 -r $2/SYS/JITUNE # Core libraries echo "SYS/ARGS"; atftp $1 --put -l rel/ARGS#FE1000 -r $2/SYS/ARGS#FE1000 echo "SYS/DHCP"; atftp $1 --put -l rel/DHCP#FE1000 -r $2/SYS/DHCP#FE1000 -echo "SYS/ED"; atftp $1 --put -l rel/ED#FE1000 -r $2/SYS/ED#FE1000 -echo "SYS/TFTPD"; atftp $1 --put -l rel/TFTPD#FE1000 -r $2/SYS/TFTPD#FE1000 echo "SYS/ETHERIP"; atftp $1 --put -l rel/ETHERIP#FE1000 -r $2/SYS/ETHERIP#FE1000 echo "SYS/MOUSE"; atftp $1 --put -l rel/apple/MOUSE#FE1000 -r $2/SYS/MOUSE#FE1000 echo "SYS/FIBER"; atftp $1 --put -l rel/FIBER#FE1000 -r $2/SYS/FIBER#FE1000 echo "SYS/INET"; atftp $1 --put -l rel/INET#FE1000 -r $2/SYS/INET#FE1000 echo "SYS/LONGJUMP"; atftp $1 --put -l rel/LONGJMP#FE1000 -r $2/SYS/LONGJMP#FE1000 -echo "SYS/LZ4"; atftp $1 --put -l rel/LZ4#FE1000 -r $2/SYS/LZ4#FE1000 echo "SYS/MEMMGR"; atftp $1 --put -l rel/MEMMGR#FE1000 -r $2/SYS/MEMMGR#FE1000 echo "SYS/CONIO"; atftp $1 --put -l rel/apple/CONIO#FE1000 -r $2/SYS/CONIO#FE1000 echo "SYS/LINESPANS"; atftp $1 --put -l rel/apple/LINESPANS#FE1000 -r $2/SYS/LINESPANS#FE1000 @@ -29,8 +26,6 @@ echo "SYS/DGRLIB"; atftp $1 --put -l rel/apple/DGRLIB#FE1000 -r $2/SYS/DGRLIB# echo "SYS/FILEIO"; atftp $1 --put -l rel/apple/FILEIO#FE1000 -r $2/SYS/FILEIO#FE1000 echo "SYS/JOYBUZZ"; atftp $1 --put -l rel/apple/JOYBUZZ#FE1000 -r $2/SYS/JOYBUZZ#FE1000 echo "SYS/SNDSEQ"; atftp $1 --put -l rel/apple/SNDSEQ#FE1000 -r $2/SYS/SNDSEQ#FE1000 -echo "SYS/MON"; atftp $1 --put -l rel/apple/MON#FE1000 -r $2/SYS/MON#FE1000 -echo "SYS/SOS"; atftp $1 --put -l rel/apple/SOS#FE1000 -r $2/SYS/SOS#FE1000 echo "SYS/PORTIO"; atftp $1 --put -l rel/apple/PORTIO#FE1000 -r $2/SYS/PORTIO#FE1000 echo "SYS/UTHERNET2";atftp $1 --put -l rel/apple/UTHERNET2#FE1000 -r $2/SYS/UTHERNET2#FE1000 echo "SYS/UTHERNET"; atftp $1 --put -l rel/apple/UTHERNET#FE1000 -r $2/SYS/UTHERNET#FE1000 From 91a1b1680793dee8ead96feb8156ce1e986d33b7 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 20 Dec 2019 17:50:10 -0800 Subject: [PATCH 066/149] show & change af files type and aux --- src/inc/fileio.plh | 1 + src/libsrc/apple/fileio.pla | 30 ++++++++++- src/libsrc/cat.pla | 16 +++--- src/libsrc/type.pla | 103 +++++++++++++++++++++--------------- src/makefile | 7 ++- src/mkrel | 1 + 6 files changed, 103 insertions(+), 55 deletions(-) diff --git a/src/inc/fileio.plh b/src/inc/fileio.plh index ba7ee72..2dd87b1 100644 --- a/src/inc/fileio.plh +++ b/src/inc/fileio.plh @@ -37,6 +37,7 @@ import fileio word getpfx word setpfx word getfileinfo + word setfileinfo word geteof word iobufalloc word open diff --git a/src/libsrc/apple/fileio.pla b/src/libsrc/apple/fileio.pla index d074c6a..0060c2a 100644 --- a/src/libsrc/apple/fileio.pla +++ b/src/libsrc/apple/fileio.pla @@ -26,6 +26,7 @@ struc t_fileio word getpfx word setpfx word getfileinfo + word setfileinfo word geteof word iobufalloc word open @@ -40,14 +41,14 @@ struc t_fileio word readblock word writeblock end -predef a2getpfx(path), a23setpfx(path), a2getfileinfo(path, fileinfo), a23geteof(refnum), a2iobufs(iobufs), a2open(path), a2close(refnum) +predef a2getpfx(path), a23setpfx(path), a2getfileinfo(path, fileinfo), a2setfileinfo(path, fileinfo), a23geteof(refnum), a2iobufs(iobufs), a2open(path), a2close(refnum) predef a23read(refnum, buf, len), a2write(refnum, buf, len), a2create(path, type, aux), a23destroy(path), a23rename(path, newpath) predef a2newline(refnum, emask, nlchar), a2online(unit, buf), a2readblock(unit, buf, block), a2writeblock(unit, buf, block) // // Exported function table. // word fileio[] -word = @a2getpfx, @a23setpfx, @a2getfileinfo, @a23geteof, @a2iobufs, @a2open, @a2close +word = @a2getpfx, @a23setpfx, @a2getfileinfo, @a2setfileinfo, @a23geteof, @a2iobufs, @a2open, @a2close word = @a23read, @a2write, @a2create, @a23destroy, @a23rename word = @a2newline, @a2online, @a2readblock, @a2writeblock // @@ -119,6 +120,29 @@ def a3getfileinfo(path, fileinfo) perr = syscall($C4, @params) return perr end +def a1setfileinfo(path, fileinfo) + perr = $01 + return perr +end +def a2setfileinfo(path, fileinfo) + byte params[14] + + params.0 = 7 + params:1 = path + memcpy(@params + 3, fileinfo, 11) + perr = syscall($C3, @params) + return perr +end +def a3setfileinfo(path, fileinfo) + byte params[6] + + params.0 = 3 + params:1 = path + params:3 = fileinfo + params.5 = 15 + perr = syscall($C3, @params) + return perr +end def a1geteof(refnum) return 0 end @@ -427,6 +451,7 @@ when MACHID & MACHID_MODEL is MACHID_III fileio:getpfx = @a3getpfx fileio:getfileinfo = @a3getfileinfo + fileio:setfileinfo = @a3setfileinfo fileio:iobufalloc = @a13iobufs fileio:open = @a3open fileio:close = @a3close @@ -441,6 +466,7 @@ when MACHID & MACHID_MODEL fileio:getpfx = @a1getpfx fileio:setpfx = @a1setpfx fileio:getfileinfo = @a1getfileinfo + fileio:setfileinfo = @a1setfileinfo fileio:geteof = @a1geteof fileio:iobufalloc = @a13iobufs fileio:open = @a1open diff --git a/src/libsrc/cat.pla b/src/libsrc/cat.pla index fd10654..3c01efe 100644 --- a/src/libsrc/cat.pla +++ b/src/libsrc/cat.pla @@ -72,16 +72,16 @@ if refnum if ^entry printentry() filecnt-- + // + // Pause display every screenfull + // + page++ + if page == 23 + getc + page = 0 + fin fin entry = entry + entrylen - // - // Pause display every screenfull - // - page++ - if page == 23 - getc - page = 0 - fin next firstblk = 0 fin diff --git a/src/libsrc/type.pla b/src/libsrc/type.pla index 10ac895..799f9f7 100644 --- a/src/libsrc/type.pla +++ b/src/libsrc/type.pla @@ -3,59 +3,40 @@ include "inc/args.plh" include "inc/fileio.plh" char[64] filename -var arg +res[t_fileinfo] fileinfo +var arg, type, aux // // Convert byte to two hex chars // -def btoh(cptr, b)#0 - byte h - +def putb(b)#0 + char h + h = ((b >> 4) & $0F) + '0' if h > '9' h = h + 7 fin - ^cptr = h - cptr++ + putc(h) h = (b & $0F) + '0' if h > '9' h = h + 7 fin - ^cptr = h + putc(h) end -// -// Check filename -// -def checkfile - var refnum, dirbuf - res[t_fileinfo] fileinfo - - // - // Check if file exists - // - if fileio:getfileinfo(@filename, @fileinfo) == FILE_ERR_OK - // - // Check if deleting a directory - // - if fileinfo.file_type == $0F - refnum = fileio:open(@filename) - if refnum - // - // Check for files inside directory - // - dirbuf = heapalloc(512) - if fileio:read(refnum, dirbuf, 512) == 512 - fileio:close(refnum) - if dirbuf=>$25 // File count in directory - puts("Directory not empty: "); puts(@filename); putln - return FALSE - fin - fin - fin +def htoi(hexptr) + var val, i, n + + val = 0 + for i = 1 to ^hexptr + n = toupper(^(hexptr + i)) - '0' + if n > 9 + n = n - 7 fin - return TRUE - fin - puts("File not found: "); puts(@filename); putln - return FALSE + if n > 15 or n < 0 + return val + fin + val = (val << 4) + n + next + return val end // // Check arguments and file types @@ -71,12 +52,46 @@ if ^arg // Check if re-typing a directory // if fileinfo.file_type <> $0F + // + // Check for optional overrides + // + arg = argNext(arg) + if ^arg + type = htoi(arg) + if type > 255 + puts("TYPE value out of range\n") + return + fin + // + // Can't change something into directory + // + if type <> $0F + fileinfo.file_type = type + arg = argNext(arg) + if ^arg + aux = htoi(arg) + fileinfo:aux_type = aux + fin + // + // Update file type and aux values + // + if fileio:setfileinfo(@filename, @fileinfo) == FILE_ERR_OK + if fileio:getfileinfo(@filename, @fileinfo) <> FILE_ERR_OK + puts("Unable to reload file info: "); puts(@filename) + fin + else + puts("Unable to change TYPE & AUX values: "); puts(@filename) + return + fin + fin + fin + else + puts("Unable to get file info: "); puts(@filename); putln fin fin - // - // Close all files - // - fileio:close(0) + puts(@filename); putc(':') + putc('$'); putb(fileinfo.file_type); putc(' ') + putc('$'); puth(fileinfo:aux_type); putln return fin puts("Usage: +TYPE FILE [HEXTYPE [HEXAUX]]\n") diff --git a/src/makefile b/src/makefile index efe8a7f..ec34786 100755 --- a/src/makefile +++ b/src/makefile @@ -23,6 +23,7 @@ DEL = rel/DEL\#FE1000 REN = rel/REN\#FE1000 CAT = rel/CAT\#FE1000 NEWDIR = rel/NEWDIR\#FE1000 +TYPE = rel/TYPE\#FE1000 SIEVE = rel/SIEVE\#FE1000 PRIMEGAP = rel/PRIMEGAP\#FE1000 ARGS = rel/ARGS\#FE1000 @@ -95,7 +96,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -434,6 +435,10 @@ $(NEWDIR): libsrc/newdir.pla $(PLVM03) $(PLASM) ./$(PLASM) -AMOW < libsrc/newdir.pla > libsrc/newdir.a acme --setpc 4094 -o $(NEWDIR) libsrc/newdir.a +$(TYPE): libsrc/type.pla $(PLVM03) $(PLASM) + ./$(PLASM) -AMOW < libsrc/type.pla > libsrc/type.a + acme --setpc 4094 -o $(TYPE) libsrc/type.a + $(SOS): libsrc/apple/sos.pla $(PLVM03) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/sos.pla > libsrc/apple/sos.a acme --setpc 4094 -o $(SOS) libsrc/apple/sos.a diff --git a/src/mkrel b/src/mkrel index 57cc74b..a1eef8d 100755 --- a/src/mkrel +++ b/src/mkrel @@ -17,6 +17,7 @@ cp rel/DEL#FE1000 prodos/sys/DEL.REL cp rel/REN#FE1000 prodos/sys/REN.REL cp rel/CAT#FE1000 prodos/sys/CAT.REL cp rel/NEWDIR#FE1000 prodos/sys/NEWDIR.REL +cp rel/TYPE#FE1000 prodos/sys/TYPE.REL cp rel/ARGS#FE1000 prodos/sys/ARGS.REL cp rel/ED#FE1000 prodos/sys/ED.REL cp rel/FIBER#FE1000 prodos/sys/FIBER.REL From 48a33a44323fcb4a8ba2273164e96c09a3151be8 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Fri, 20 Dec 2019 17:52:03 -0800 Subject: [PATCH 067/149] Break out the utils --- src/tftputil | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100755 src/tftputil diff --git a/src/tftputil b/src/tftputil new file mode 100755 index 0000000..4f440a6 --- /dev/null +++ b/src/tftputil @@ -0,0 +1,14 @@ +#!/bin/bash + +# Core utilities +echo "SYS/ED"; atftp $1 --put -l rel/ED#FE1000 -r $2/SYS/ED#FE1000 +echo "SYS/COPY"; atftp $1 --put -l rel/COPY#FE1000 -r $2/SYS/COPY#FE1000 +echo "SYS/DEL"; atftp $1 --put -l rel/DEL#FE1000 -r $2/SYS/DEL#FE1000 +echo "SYS/REN"; atftp $1 --put -l rel/REN#FE1000 -r $2/SYS/REN#FE1000 +echo "SYS/CAT"; atftp $1 --put -l rel/CAT#FE1000 -r $2/SYS/CAT#FE1000 +echo "SYS/NEWDIR"; atftp $1 --put -l rel/NEWDIR#FE1000 -r $2/SYS/NEWDIR#FE1000 +echo "SYS/TYPE"; atftp $1 --put -l rel/TYPE#FE1000 -r $2/SYS/TYPE#FE1000 +echo "SYS/TFTPD"; atftp $1 --put -l rel/TFTPD#FE1000 -r $2/SYS/TFTPD#FE1000 +echo "SYS/LZ4"; atftp $1 --put -l rel/LZ4#FE1000 -r $2/SYS/LZ4#FE1000 +echo "SYS/MON"; atftp $1 --put -l rel/apple/MON#FE1000 -r $2/SYS/MON#FE1000 +echo "SYS/SOS"; atftp $1 --put -l rel/apple/SOS#FE1000 -r $2/SYS/SOS#FE1000 From 4aa8c8da1fc598a50dbd5e061ed773c42e8c586f Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 21 Dec 2019 08:30:04 -0800 Subject: [PATCH 068/149] Add utils source and reorg --- src/libsrc/wiznet.pla | 993 ----------------------- src/makefile | 76 +- src/mkrel | 14 +- src/tftpdemos | 1 - src/tftpsys | 1 + src/tftputil | 13 +- src/{libsrc => utilsrc/apple}/cat.pla | 0 src/{libsrc => utilsrc/apple}/copy.pla | 0 src/{libsrc => utilsrc/apple}/del.pla | 0 src/{libsrc => utilsrc}/apple/jitune.pla | 0 src/{samplesrc => utilsrc/apple}/mon.pla | 0 src/{libsrc => utilsrc/apple}/newdir.pla | 0 src/{libsrc => utilsrc/apple}/ren.pla | 0 src/{libsrc => utilsrc}/apple/sos.pla | 0 src/{libsrc => utilsrc/apple}/type.pla | 0 src/{samplesrc => utilsrc}/tftpd.pla | 0 16 files changed, 52 insertions(+), 1046 deletions(-) delete mode 100644 src/libsrc/wiznet.pla rename src/{libsrc => utilsrc/apple}/cat.pla (100%) rename src/{libsrc => utilsrc/apple}/copy.pla (100%) rename src/{libsrc => utilsrc/apple}/del.pla (100%) rename src/{libsrc => utilsrc}/apple/jitune.pla (100%) rename src/{samplesrc => utilsrc/apple}/mon.pla (100%) rename src/{libsrc => utilsrc/apple}/newdir.pla (100%) rename src/{libsrc => utilsrc/apple}/ren.pla (100%) rename src/{libsrc => utilsrc}/apple/sos.pla (100%) rename src/{libsrc => utilsrc/apple}/type.pla (100%) rename src/{samplesrc => utilsrc}/tftpd.pla (100%) diff --git a/src/libsrc/wiznet.pla b/src/libsrc/wiznet.pla deleted file mode 100644 index 079ebf5..0000000 --- a/src/libsrc/wiznet.pla +++ /dev/null @@ -1,993 +0,0 @@ -// -// Wiznet 5100 based ethernet card -// -// TCP/IP is built into hardware, so no dependencies on the software -// layers, like the Uthernet -// -include "inc/cmdsys.plh" -// -// Net object -// -import inet - word iNet -end -struc t_inet - word initIP - word serviceIP - word openUDP - word sendUDP - word closeUDP - word listenTCP - word connectTCP - word sendTCP - word closeTCP - word setInterfaceIP - word getInterfaceHA - word setCallback - word setParam -end -// -// Module don't free memory -// -const modkeep = $2000 -const modinitkeep = $4000 -// -// Wiznet registers -// -const WIZ_MR = $00 -const WIZ_GWR = $01 -const WIZ_SUBR = $05 -const WIZ_SHAR = $09 -const WIZ_SIPR = $0F -const WIZ_IR = $15 -const WIZ_IMR = $16 -const WIZ_RTR = $17 -const WIZ_RCR = $19 -const WIZ_RMSR = $1A -const WIZ_TMSR = $1B -const WIZ_PATR = $1C -const WIZ_PTMR = $28 -const WIZ_PMGC = $29 -const WIZ_UIPR = $2A -const WIZ_UPRT = $2E -// -// Wiznet socket registers -// -const WIZ_SREGS = $0400 -const WIZ_SSIZE = $0100 -const WIZ_SOCK0 = $0400 -const WIZ_SOCK1 = $0500 -const WIZ_SOCK2 = $0600 -const WIZ_SOCK3 = $0700 -const WIZ_SnMR = $00 -const WIZ_SnCR = $01 -const WIZ_SnIR = $02 -const WIZ_SnSR = $03 -const WIZ_SnPORT = $04 -const WIZ_SnDHAR = $06 -const WIZ_SnDIPR = $0C -const WIZ_SnDPORT = $10 -const WIZ_SnMSSR = $12 -const WIZ_SnPROTO = $14 -const WIZ_SnTOS = $15 -const WIZ_SnTTL = $16 -const WIZ_SnFSR = $20 -const WIZ_SnTXRD = $22 -const WIZ_SnTXWR = $24 -const WIZ_SnRSR = $26 -const WIZ_SnRXRD = $28 -// -// Wiznet socket data -// -const WIZ_TXMEM = $4000 -const WIZ_TXSIZE = $0800 -const WIZ_TXMASK = WIZ_TXSIZE-1 -const WIZ_TXMEM0 = $4000 -const WIZ_TXMEM1 = $4800 -const WIZ_TXMEM2 = $5000 -const WIZ_TXMEM3 = $5800 -const WIZ_RXMEM = $6000 -const WIZ_RXSIZE = $0800 -const WIZ_RXMASK = WIZ_RXSIZE-1 -const WIZ_RXMEM0 = $6000 -const WIZ_RXMEM1 = $6800 -const WIZ_RXMEM2 = $7000 -const WIZ_RXMEM3 = $7800 -// -// Wiznet indirect registers -// -byte regidx, regdata -word slot, saveidx -// -// Wiznet MAC address -// -byte[6] wizMAC = $00,$0A,$99,$1E,$02,$B0 -// -// Wiznet IP addresses -// -byte[4] localip -byte[4] subnet -byte[4] gateway -// -// Predefine service routine -// -predef wizServiceIP -// -// Segment list element -// -struc t_segment - word seg_buf - word seg_len -end -// -// Max Ethernet frame size -// -const MAX_FRAME_SIZE = 1518 -const MAC_BROADCAST = $FFFF -const MAC_SIZE = 6 -// -// Ethernet header -// -struc t_ethrhdr - byte[MAC_SIZE] ethr_dst - byte[MAC_SIZE] ethr_src - word ethr_payload -end -const PAYLOAD_IP = $0008 // BE format -const PAYLOAD_ARP = $0608 // BE format -// -// IP datagram header -// -const IP4ADR_SIZE = 4 -struc t_iphdr - byte ip_vers_hlen - byte ip_service - word ip_length - word ip_id - word ip_flags_fragofst - byte ip_ttl - byte ip_proto - word ip_chksm - byte[IP4ADR_SIZE] ip_src - byte[IP4ADR_SIZE] ip_dst - byte[] ip_options -end -const IP_BROADCAST = $FFFF -const IP_PROTO_ICMP = $01 -const IP_PROTO_UDP = $11 -const IP_PROTO_TCP = $06 -word bcast = IP_BROADCAST, IP_BROADCAST -// -// ICMP type/codes -// -const IP_PROTO_ICMP = 1 -const ICMP_ECHO_REQST = 8 -const ICMP_ECHO_REPLY = 0 -// -// ICMP message format -// -struc t_icmp - byte icmp_type - byte icmp_code - word icmp_chksm - word[2] icmp_header -end -// -// UDP IPv4 psuedo header -// -struc t_piphdr - byte[IP4ADR_SIZE] pip_src - byte[IP4ADR_SIZE] pip_dst - byte pip_zero - byte pip_proto - word pip_len -end -// -// UDP header -// -struc t_udphdr - word udp_src - word udp_dst - word udp_len - word udp_chksm -end -// -// TCP header -// -struc t_tcphdr - word tcp_src - word tcp_dst - word tcp_len - word tcp_chksm -end -// -// Local network parameters -// -const MAX_WIZ_CHANNELS = 4 -// -// Channel protocols -// -const WIZ_PROTO_CLOSED = 0 -const WIZ_PROTO_TCP = 1 -const WIZ_PROTO_UDP = 2 -const WIZ_PROTO_IP = 3 -const WIZ_PROTO_RAW = 4 -// -// State transistions -// -const TCP_STATE_CLOSED = 0 -const TCP_STATE_CLOSING = 1 -const TCP_STATE_LISTEN = 2 -const TCP_STATE_CONNECT = 3 -const TCP_STATE_OPEN = 4 -// -// HW channels -// -struc t_channel - byte channel_proto - byte channel_state - word channel_regs - word channel_txmem - word channel_rxmem - word channel_lclport - word channel_remport - byte[4] channel_remip - word channel_recv_func - word channel_recv_parm -end -byte[t_channel * MAX_WIZ_CHANNELS] wizChannel -// -// Service ICMP hook -// -export word hookICMP -// -// Defines for ASM routines -// -asm equates - !SOURCE "vmsrc/plvmzp.inc" -end -// -// Swap bytes in word -// -asm swab - LDA ESTKL,X - LDY ESTKH,X - STA ESTKH,X - STY ESTKL,X - RTS -end -// -// Wiznet I/O functions -// -// POKE WORD TO I/O SPACE -// Note: Big Endian format -// -asm _pokeiow - LDA ESTKH,X -end -asm _pokeiowl - STA $C000 - LDA ESTKL,X -end -asm _pokeiowh - STA $C000 - RTS -end -// -// POKE BYTE TO I/O SPACE -// -asm _pokeio - LDA ESTKL,X -end -asm _pokeiol - STA $C000 - RTS -end -// -// PEEK BYTE FROM I/O SPACE -// -asm _peekio - DEX -end -asm _peekiol - LDA $C000 - STA ESTKL,X - LDA #$00 - STA ESTKH,X - RTS -end -// -// PEEK WORD FROM I/O SPACE -// Note: Big Endian format -// -asm _peekiow - DEX -end -asm _peekiowl - LDA $C000 - STA ESTKH,X -end -asm _peekiowh - LDA $C000 - STA ESTKL,X - RTS -end -// -// WRITE DATA INTO I/O SPACE -// pokedata(BUF, LEN) -// -asm pokedata - LDA ESTKL+1,X - STA SRCL - LDA ESTKH+1,X - STA SRCH - LDY ESTKL,X - BEQ POKELP - LDY #$00 - INC ESTKH,X -POKELP LDA (SRC),Y -end -asm _pokedata - STA $C000 - INY - BNE + - INC SRCH -+ DEC ESTKL,X - BNE POKELP - DEC ESTKH,X - BNE POKELP - INX - RTS -end -// -// READ DATA FROM I/O SPACE -// peekdata(BUF, LEN) -// -asm peekdata - LDA ESTKL+1,X - STA DSTL - LDA ESTKH+1,X - STA DSTH - LDY ESTKL,X - BEQ PEEKLP - LDY #$00 - INC ESTKH,X -end -asm _peekdata -PEEKLP LDA $C000 - STA (DST),Y - INY - BNE + - INC DSTH -+ DEC ESTKL,X - BNE PEEKLP - DEC ESTKH,X - BNE PEEKLP - INX - RTS -end -def pokeiow(io, data) - _pokeiowl.1 = io - _pokeiowh.1 = io+1 - return _pokeiow(data) -end -def pokeio(io, data) - _pokeiol.1 = io - return _pokeio(data) -end -def peekio(io) - _peekiol.1 = io - return _peekio() -end -def peekiow(io) - _peekiowl.1 = io - _peekiowh.1 = io+1 - return _peekiow() -end -def pokereg(reg, data) - _pokeiow(reg) - return _pokeio(data) -end -def peekreg(reg) - _pokeiow(reg) - return _peekio() -end -def pokeregs(reg, buf, len) -// _pokeiow(reg) -// return pokedata(buf, len) - word i - len = len - 1 - for i = 0 to len - _pokeiow(reg + i) - _pokeio(buf->[i]) - next -end -def peekregs(reg, buf, len) -// _pokeiow(reg) -// return peekdata(buf, len) -// There is an issue missing data on back-to-back reads - word i - len = len - 1 - for i = 0 to len - _pokeiow(reg + i) - buf->[i] = _peekio() - next -end -def pokeregw(reg, dataw) - _pokeiow(reg) - _pokeio(dataw.1) - return _pokeio(dataw.0) -end -def peekregw(reg) - word dataw - - _pokeiow(reg) - dataw.1 = _peekio() - _pokeiow(reg + 1) - dataw.0 = _peekio() - return dataw -end -// -// DEBUG -// -def putb(hexb) - return call($FDDA, hexb, 0, 0, 0) -end -def puth(hex) - return call($F941, hex >> 8, hex, 0, 0) -end -def putip(ipptr) - byte i - - for i = 0 to 2 - puti(ipptr->[i]); putc('.') - next - return puti(ipptr->[i]) -end -// -// Send UDP datagram -// -def wizSendUDP(wiz, ipdst, portdst, data, len) - word wizregs, wizdata, txrr, txwr, splitlen - - wizregs = wiz=>channel_regs - wizdata = wiz=>channel_txmem - if !ipdst - ipdst = @bcast - fin - // - // Wait for Tx room - // - repeat; until peekregw(wizregs + WIZ_SnFSR) >= len - // - // Calc new write ptr, check for split - // - txwr = peekregw(wizregs + WIZ_SnTXWR) - txrr = txwr & WIZ_TXMASK - if txrr + len > WIZ_TXSIZE - splitlen = WIZ_TXSIZE - txrr - pokeregs(wizdata + txrr, data, splitlen) - pokeregs(wizdata, data + splitlen, len - splitlen) - else - pokeregs(wizdata + txrr, data, len) - fin - // - // Set destination address/port - // - pokeregs(wizregs + WIZ_SnDIPR, ipdst, IP4ADR_SIZE) - pokeregw(wizregs + WIZ_SnDPORT, portdst) - // - // Update write pointer and send - // - pokeregw(wizregs + WIZ_SnTXWR, txwr + len) - pokereg(wizregs + WIZ_SnCR, $20) // SEND -end -// -// Open UDP channel and set datagram received callback -// -def wizOpenUDP(localport, callback, param) - word wiz - byte i - - if !localport; return -1; fin // invalid port - // - // Look for an existing notification on localport - // - //putc('O') - wiz = @wizChannel - for i = 1 to MAX_WIZ_CHANNELS - if wiz->channel_proto == IP_PROTO_UDP and wiz=>channel_lclport == localport - break - fin - wiz = wiz + t_channel - next - if i > MAX_WIZ_CHANNELS - // - // Add notification on localport if room - // - wiz = @wizChannel - for i = 1 to MAX_WIZ_CHANNELS - if !wiz->channel_proto - break - fin - wiz = wiz + t_channel - next - if i > MAX_WIZ_CHANNELS - return 0 - fin - fin - //putc('0' + i);putln - // - // Fill in this channel and open it - // - wiz->channel_proto = WIZ_PROTO_UDP - wiz=>channel_lclport = localport - wiz=>channel_recv_func = callback - wiz=>channel_recv_parm = param - pokeregw(wiz=>channel_regs + WIZ_SnPORT, localport) - pokereg(wiz=>channel_regs + WIZ_SnMR, $02) // UDP protocol - pokereg(wiz=>channel_regs + WIZ_SnCR, $01) // OPEN - return wiz -end -// -// Close UDP port -// -def wizCloseUDP(wiz) - //putc('S') - if isuge(wiz, @wizChannel) and isult(wiz, @wizChannel + MAX_WIZ_CHANNELS * t_channel) - // - // Clear notiications on this port - // - if wiz->channel_proto == WIZ_PROTO_UDP - //putc('1' + ((wiz=>channel_regs - WIZ_SREGS) >> 8));putln - wiz->channel_proto = WIZ_PROTO_CLOSED - pokereg(wiz=>channel_regs + WIZ_SnCR, $10) // CLOSE - return 0 - fin - fin - //putc('!');putln - // - // Invalid port - // - return -1 -end -// -// Open TCP socket in SERVER mode -// -def wizListenTCP(lclport, callback, param) - word wiz - byte i - - // - // Look for an existing notification on localport - // - //putc('L') - wiz = @wizChannel - for i = 1 to MAX_WIZ_CHANNELS - if wiz->channel_proto == WIZ_PROTO_TCP and wiz->channel_state == TCP_STATE_LISTEN and wiz=>channel_lclport == lclport - break - fin - wiz = wiz + t_channel - next - if i > MAX_WIZ_CHANNELS - // - // Add notification on localport if room - // - wiz = @wizChannel - for i = 1 to MAX_WIZ_CHANNELS - if !wiz->channel_proto - break - fin - wiz = wiz + t_channel - next - if i > MAX_WIZ_CHANNELS - return 0 - fin - fin - //putc('0' + i);putln - // - // Fill in this channel and open it - // - wiz->channel_proto = WIZ_PROTO_TCP - wiz->channel_state = TCP_STATE_LISTEN - wiz=>channel_remip:0 = 0 - wiz=>channel_remip:2 = 0 - wiz=>channel_remport = 0 - wiz=>channel_lclport = lclport - wiz=>channel_recv_func = callback - wiz=>channel_recv_parm = param - pokereg(wiz=>channel_regs + WIZ_SnMR, $01) // TCP protocol - pokeregw(wiz=>channel_regs + WIZ_SnPORT, lclport) - pokereg(wiz=>channel_regs + WIZ_SnCR, $01) // OPEN - while peekreg(wiz=>channel_regs + WIZ_SnSR) <> $13; loop // Wait for init - pokereg(wiz=>channel_regs + WIZ_SnCR, $02) // LISTEN - return wiz -end -// -// Open TCP socket in CLIENT mode -// -def wizConnectTCP(remip, remport, lclport, callback, param) - word wiz - byte i - - // - // Look for an existing notification on localport - // - wiz = @wizChannel - for i = 1 to MAX_WIZ_CHANNELS - if wiz->channel_proto == WIZ_PROTO_TCP and wiz->channel_state == TCP_STATE_CONNECT and wiz=>channel_lclport == lclport - break - fin - wiz = wiz + t_channel - next - if i > MAX_WIZ_CHANNELS - // - // Add notification on localport if room - // - wiz = @wizChannel - for i = 1 to MAX_WIZ_CHANNELS - if !wiz->channel_proto - break - fin - wiz = wiz + t_channel - next - if i > MAX_WIZ_CHANNELS - return 0 - fin - fin - // - // Fill in this channel and open it - // - wiz->channel_proto = WIZ_PROTO_TCP - wiz->channel_state = TCP_STATE_CONNECT - wiz=>channel_remip:0 = remip=>0 - wiz=>channel_remip:2 = remip=>2 - wiz=>channel_remport = remport - wiz=>channel_lclport = lclport - wiz=>channel_recv_func = callback - wiz=>channel_recv_parm = param - pokereg(wiz=>channel_regs + WIZ_SnMR, $01) // TCP protocol - pokeregs(wiz=>channel_regs + WIZ_SnDIPR, remip, IP4ADR_SIZE) - pokeregw(wiz=>channel_regs + WIZ_SnDPORT, remport) - pokeregw(wiz=>channel_regs + WIZ_SnPORT, lclport) - pokereg(wiz=>channel_regs + WIZ_SnCR, $01) // OPEN - while peekreg(wiz=>channel_regs + WIZ_SnSR) <> $13; loop // Wait for init - pokereg(wiz=>channel_regs + WIZ_SnCR, $04) // CONNECT - return wiz -end -// -// Write to TCP socket -// -def wizSendTCP(wiz, data, len) - word wizregs, wizdata, txrr, txwr, splitlen - - if wiz->channel_state <> TCP_STATE_OPEN; return -1; fin - //putc('W');puti(len);putc(':') - wizregs = wiz=>channel_regs - wizdata = wiz=>channel_txmem - // - // Wait for Tx room - // - repeat; until peekregw(wizregs + WIZ_SnFSR) >= len - // - // Calc new write ptr, check for split - // - txwr = peekregw(wizregs + WIZ_SnTXWR) - txrr = txwr & WIZ_TXMASK - if txrr + len > WIZ_TXSIZE - splitlen = WIZ_TXSIZE - txrr - pokeregs(wizdata + txrr, data, splitlen) - pokeregs(wizdata, data + splitlen, len - splitlen) - //putc('(');puti(splitlen);putc(',');puti(len-splitlen);putc(')') - else - pokeregs(wizdata + txrr, data, len) - fin - //puth(txrr);putc('-');putc('>');puth(txwr+len);putln - // - // Update write pointer and send - // - pokeregw(wizregs + WIZ_SnTXWR, txwr + len) - pokereg(wizregs + WIZ_SnCR, $20) // SEND -end -// -// Close TCP socket -// -def wizCloseTCP(wiz) - if isuge(wiz, @wizChannel) and isult(wiz, @wizChannel + MAX_WIZ_CHANNELS * t_channel) - // - // Clear notiications on this port - // - if wiz->channel_proto == WIZ_PROTO_TCP and (wiz->channel_state == TCP_STATE_OPEN or wiz->channel_state == TCP_STATE_CLOSING) - wiz->channel_state = TCP_STATE_CLOSING - pokereg(wiz=>channel_regs + WIZ_SnCR, $08) // DISCON - repeat - wizServiceIP() - until wiz->channel_state == TCP_STATE_CLOSED - wiz->channel_proto = WIZ_PROTO_CLOSED - return 0 - fin - fin - // - // Invalid port - // - return -1 -end -// -// Update notify callback -// -def wizSetCallback(wiz, callback) - if wiz->channel_proto == WIZ_PROTO_UDP or wiz->channel_proto == WIZ_PROTO_TCP - // - // Update callback on this port - // - wiz=>channel_recv_func = callback - return 0 - fin - // - // Invalid port - // - return -1 -end -// -// Update notify param -// -def wizSetParam(wiz, param) - if wiz->channel_proto == WIZ_PROTO_UDP or wiz->channel_proto == WIZ_PROTO_TCP - // - // Update param on this port - // - wiz=>channel_recv_parm = param - return 0 - fin - // - // Invalid port - // - return -1 -end -// -// Service incoming packets -// -def wizServiceIP - word wiz, wizregs, wizdata, rxlen, rxrr, rxwr, rxpkt, splitlen - byte ir, i, sir - - ir = peekreg(WIZ_IR) - if ir and ir <> $FF // Ignore spurious read of IR - //putc('I');putb(ir) - wiz = @wizChannel - for i = 0 to 3 - when ir & (1 << i) - is 1 - is 2 - is 4 - is 8 - wizregs = wiz=>channel_regs - wizdata = wiz=>channel_rxmem - sir = peekreg(wizregs + WIZ_SnIR) - when wiz->channel_proto - is WIZ_PROTO_TCP - if sir & $01 - //putc('C') - // - // Connect TCP socket - // - when wiz->channel_state - is TCP_STATE_LISTEN - peekregs(wiz=>channel_regs + WIZ_SnDIPR, @wiz=>channel_remip, IP4ADR_SIZE) - wiz=>channel_remport = peekregw(wiz=>channel_regs + WIZ_SnDPORT) - is TCP_STATE_CONNECT - wiz->channel_state = TCP_STATE_OPEN - break - otherwise - //putc('?') - wend - fin - if sir & $04 - //putc('R') - // - // Receive TCP packet - // - rxlen = peekregw(wizregs + WIZ_SnRSR) - rxrr = peekregw(wizregs + WIZ_SnRXRD) - rxwr = rxrr & WIZ_RXMASK - rxpkt = heapalloc(rxlen) - //puti(rxlen);putc(':') - if rxwr + rxlen > WIZ_RXSIZE - splitlen = WIZ_RXSIZE - rxwr - peekregs(wizdata + rxwr, rxpkt, splitlen) - peekregs(wizdata, rxpkt + splitlen, rxlen - splitlen) - //putc('(');puti(splitlen);putc(',');puti(rxlen-splitlen);putc(')') - else - peekregs(wizdata + rxwr, rxpkt, rxlen) - fin - //puth(rxwr);putc('-');putc('>');puth(rxwr+rxlen);putln - pokeregw(wizregs + WIZ_SnRXRD, rxrr + rxlen) - pokereg(wizregs + WIZ_SnCR, $40) // RECV - wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,rxpkt,rxlen,wiz=>channel_recv_parm) - heaprelease(rxpkt) - fin - if sir & $02 - //putc('S') - // - // Close TCP socket - // - when wiz->channel_state - is TCP_STATE_OPEN - wiz->channel_state = TCP_STATE_CLOSING - wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,0,wiz=>channel_lclport,0,wiz=>channel_recv_parm) - break - is TCP_STATE_CLOSING - wiz->channel_state = TCP_STATE_CLOSED - pokereg(wiz=>channel_regs + WIZ_SnCR, $10) // CLOSE - break - otherwise - //putc('?') - wend - fin - if sir & $08 - //putc('T') - // - // Timeout on TCP socket - // - when wiz->channel_state - is TCP_STATE_OPEN - wiz->channel_state = TCP_STATE_CLOSING - wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,0,0,wiz=>channel_recv_parm) - break - is TCP_STATE_CONNECT - wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,0,0,wiz=>channel_recv_parm) - is TCP_STATE_CLOSING - wiz->channel_state = TCP_STATE_CLOSED - pokereg(wiz=>channel_regs + WIZ_SnCR, $10) // CLOSE - break - otherwise - //putc('?') - wend - fin - //if sir & $10 - //putc('W');putc('O');putc('K');puth(peekregw(wiz=>channel_regs+WIZ_SnTXWR));putln - // - // Write TCP socket OK - // - //fin - break - is WIZ_PROTO_UDP - //putc('U');putb(sir) - if sir & $04 - //putc('R') - // - // Receive UDP packet - // - rxlen = peekregw(wizregs + WIZ_SnRSR) - rxrr = peekregw(wizregs + WIZ_SnRXRD) - rxwr = rxrr & WIZ_RXMASK - rxpkt = heapalloc(rxlen) - if rxwr + rxlen >= WIZ_RXSIZE - //putc('!') - splitlen = WIZ_RXSIZE - rxwr - peekregs(wizdata + rxwr, rxpkt, splitlen) - peekregs(wizdata, rxpkt + splitlen, rxlen - splitlen) - else - peekregs(wizdata + rxwr, rxpkt, rxlen) - fin - //putc('=');putip(rxpkt);putc(' ');puti(rxlen) - //putc('/');puti(swab(rxpkt=>6)) - //putc(' ');puth(rxrr);putc(' ');puth(rxwr);putln - pokeregw(wizregs + WIZ_SnRXRD, rxrr + rxlen) - pokereg(wizregs + WIZ_SnCR, $40) // RECV - wiz=>channel_recv_func(rxpkt,swab(rxpkt=>4),rxpkt+8,rxlen-8,wiz=>channel_recv_parm) - heaprelease(rxpkt) - fin - break - otherwise - wend - pokereg(wiz=>channel_regs + WIZ_SnIR, sir) // Clear SnIR - ir = ir ^ (1 << i) - break - wend - wiz = wiz + t_channel - next - if ir - // - // Clear IR for now - // - pokereg(WIZ_IR, ir) - fin - fin -end -// -// Set the local IP addresses -// -def setWizIP(newIP, newSubnet, newGateway) - if newIP - localip:0 = newIP=>0; localip:2 = newIP=>2 - pokeregs(WIZ_SIPR, newIP, IP4ADR_SIZE) - fin - if newSubnet - subnet:0 = newSubnet=>0; subnet:2 = newSubnet=>2 - pokeregs(WIZ_SUBR, newSubnet, IP4ADR_SIZE) - fin - if newGateway - gateway:0 = newGateway=>0; gateway:2 = newGateway=>2 - pokeregs(WIZ_GWR, newGateway, IP4ADR_SIZE) - fin -end -// -// Get the interface hardware address -// -def getWizHA(ha) - if ha - ha=>0 = wizMAC:0; ha=>2 = wizMAC:2; ha=>4 = wizMAC:4 - fin - return MAC_SIZE -end -// -// Identify Wiznet card and initialize -// -for slot = $90 to $F0 step $10 - regdata = peekio(slot) - if (regdata & $E4) == $00 - pokeio(slot, $03) // Try setting auto-increment indirect I/F - if peekio(slot) == $03 - saveidx = peekiow(slot + 1) - peekio(slot + 3) // Dummy read to data register should increment index - if peekiow(slot + 1) == saveidx + 1 - // - // Good chance this is it - // - pokeio(slot, $80) // RESET - regidx = slot + 1 - regdata = slot + 3 - _pokedata.1 = regdata - _peekdata.1 = regdata - pokeio(slot, $03) // Auto-increment indirect I/F + enable ping - // - // The following looks redundant, but it sets up the peek/poke locations - // for peekreg(s)/pokereg(s) - // - pokeiow(regidx, WIZ_MR) - pokeio(regdata, $03) // Auto-increment indirect I/F + enable ping - peekio(regdata) - // - // Initialize common registers - // - pokeregs(WIZ_SHAR, @wizMAC, 6) // MAC addr - pokeregw(WIZ_RTR, 5000) // Timeout period to 500ms - pokereg(WIZ_RMSR, $55) // 2K Rx memory/channel - pokereg(WIZ_TMSR, $55) // 2K Tx memory/channel - // - // Fill channel structure - // - saveidx = @wizChannel - for slot = 0 to 3 - saveidx=>channel_regs = WIZ_SREGS + (WIZ_SSIZE * slot) - saveidx=>channel_txmem = WIZ_TXMEM + (WIZ_TXSIZE * slot) - saveidx=>channel_rxmem = WIZ_RXMEM + (WIZ_RXSIZE * slot) - saveidx = saveidx + t_channel - next - // - // Fill in Net class - // - iNet:serviceIP = @wizServiceIP - iNet:openUDP = @wizOpenUDP - iNet:sendUDP = @wizSendUDP - iNet:closeUDP = @wizCloseUDP - iNet:listenTCP = @wizListenTCP - iNet:connectTCP = @wizConnectTCP - iNet:sendTCP = @wizSendTCP - iNet:closeTCP = @wizCloseTCP - iNet:setInterfaceIP = @setWizIP - iNet:getInterfaceHA = @getWizHA - iNet:setCallback = @wizSetCallback - iNet:setParam = @wizSetParam - return modkeep - fin - fin - pokeio(slot, regdata) // Restore register - fin -next -// -// Not found -// -return -1 -done diff --git a/src/makefile b/src/makefile index ec34786..fb51ed1 100755 --- a/src/makefile +++ b/src/makefile @@ -18,12 +18,12 @@ JIT16 = rel/apple/JIT16\#FE1000 JITUNE = rel/apple/JITUNE\#FE1000 SOS = rel/apple/SOS\#FE1000 ROD = rel/apple/ROD\#FE1000 -COPY = rel/COPY\#FE1000 -DEL = rel/DEL\#FE1000 -REN = rel/REN\#FE1000 -CAT = rel/CAT\#FE1000 -NEWDIR = rel/NEWDIR\#FE1000 -TYPE = rel/TYPE\#FE1000 +COPY = rel/apple/COPY\#FE1000 +DEL = rel/apple/DEL\#FE1000 +REN = rel/apple/REN\#FE1000 +CAT = rel/apple/CAT\#FE1000 +NEWDIR = rel/apple/NEWDIR\#FE1000 +TYPE = rel/apple/TYPE\#FE1000 SIEVE = rel/SIEVE\#FE1000 PRIMEGAP = rel/PRIMEGAP\#FE1000 ARGS = rel/ARGS\#FE1000 @@ -118,7 +118,9 @@ clean: -rm libsrc/*.o libsrc/*~ libsrc/*.a -rm libsrc/apple/*.o libsrc/apple/*~ libsrc/apple/*.a -rm libsrc/c64/*.o libsrc/c64/*~ libsrc/c64/*.a - -rm libsrc/*.o libsrc/*~ libsrc/*.a + -rm utilsrc/*.o utilsrc/*~ utilsrc/*.a + -rm utilsrc/apple/*.o utilsrc/apple/*~ utilsrc/apple/*.a + -rm utilsrc/c64/*.o utilsrc/c64/*~ utilsrc/c64/*.a # # PLASMA compiler: plasm @@ -307,9 +309,9 @@ $(HTTPD): samplesrc/httpd.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/httpd.pla > samplesrc/httpd.a acme --setpc 4094 -o $(HTTPD) samplesrc/httpd.a -$(TFTPD): samplesrc/tftpd.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AMOW < samplesrc/tftpd.pla > samplesrc/tftpd.a - acme --setpc 4094 -o $(TFTPD) samplesrc/tftpd.a +$(TFTPD): utilsrc/tftpd.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < utilsrc/tftpd.pla > utilsrc/tftpd.a + acme --setpc 4094 -o $(TFTPD) utilsrc/tftpd.a $(MOUSE): libsrc/apple/mouse.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/mouse.pla > libsrc/apple/mouse.a @@ -411,37 +413,37 @@ $(HGRTEST): samplesrc/hgrtest.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/hgrtest.pla > samplesrc/hgrtest.a acme --setpc 4094 -o $(HGRTEST) samplesrc/hgrtest.a -$(MON): samplesrc/mon.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AMOW < samplesrc/mon.pla > samplesrc/mon.a - acme --setpc 4094 -o $(MON) samplesrc/mon.a +$(MON): utilsrc/apple/mon.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < utilsrc/apple/mon.pla > utilsrc/apple/mon.a + acme --setpc 4094 -o $(MON) utilsrc/apple/mon.a -$(COPY): libsrc/copy.pla $(PLVM03) $(PLASM) - ./$(PLASM) -AMOW < libsrc/copy.pla > libsrc/copy.a - acme --setpc 4094 -o $(COPY) libsrc/copy.a +$(COPY): utilsrc/apple/copy.pla $(PLVM03) $(PLASM) + ./$(PLASM) -AMOW < utilsrc/apple/copy.pla > utilsrc/apple/copy.a + acme --setpc 4094 -o $(COPY) utilsrc/apple/copy.a -$(DEL): libsrc/del.pla $(PLVM03) $(PLASM) - ./$(PLASM) -AMOW < libsrc/del.pla > libsrc/del.a - acme --setpc 4094 -o $(DEL) libsrc/del.a +$(DEL): utilsrc/apple/del.pla $(PLVM03) $(PLASM) + ./$(PLASM) -AMOW < utilsrc/apple/del.pla > utilsrc/apple/del.a + acme --setpc 4094 -o $(DEL) utilsrc/apple/del.a -$(REN): libsrc/ren.pla $(PLVM03) $(PLASM) - ./$(PLASM) -AMOW < libsrc/ren.pla > libsrc/ren.a - acme --setpc 4094 -o $(REN) libsrc/ren.a +$(REN): utilsrc/apple/ren.pla $(PLVM03) $(PLASM) + ./$(PLASM) -AMOW < utilsrc/apple/ren.pla > utilsrc/apple/ren.a + acme --setpc 4094 -o $(REN) utilsrc/apple/ren.a -$(CAT): libsrc/cat.pla $(PLVM03) $(PLASM) - ./$(PLASM) -AMOW < libsrc/cat.pla > libsrc/cat.a - acme --setpc 4094 -o $(CAT) libsrc/cat.a +$(CAT): utilsrc/apple/cat.pla $(PLVM03) $(PLASM) + ./$(PLASM) -AMOW < utilsrc/apple/cat.pla > utilsrc/apple/cat.a + acme --setpc 4094 -o $(CAT) utilsrc/apple/cat.a -$(NEWDIR): libsrc/newdir.pla $(PLVM03) $(PLASM) - ./$(PLASM) -AMOW < libsrc/newdir.pla > libsrc/newdir.a - acme --setpc 4094 -o $(NEWDIR) libsrc/newdir.a +$(NEWDIR): utilsrc/apple/newdir.pla $(PLVM03) $(PLASM) + ./$(PLASM) -AMOW < utilsrc/apple/newdir.pla > utilsrc/apple/newdir.a + acme --setpc 4094 -o $(NEWDIR) utilsrc/apple/newdir.a -$(TYPE): libsrc/type.pla $(PLVM03) $(PLASM) - ./$(PLASM) -AMOW < libsrc/type.pla > libsrc/type.a - acme --setpc 4094 -o $(TYPE) libsrc/type.a +$(TYPE): utilsrc/apple/type.pla $(PLVM03) $(PLASM) + ./$(PLASM) -AMOW < utilsrc/apple/type.pla > utilsrc/apple/type.a + acme --setpc 4094 -o $(TYPE) utilsrc/apple/type.a -$(SOS): libsrc/apple/sos.pla $(PLVM03) $(PLASM) - ./$(PLASM) -AMOW < libsrc/apple/sos.pla > libsrc/apple/sos.a - acme --setpc 4094 -o $(SOS) libsrc/apple/sos.a +$(SOS): utilsrc/apple/sos.pla $(PLVM03) $(PLASM) + ./$(PLASM) -AMOW < utilsrc/apple/sos.pla > utilsrc/apple/sos.a + acme --setpc 4094 -o $(SOS) utilsrc/apple/sos.a $(JIT): libsrc/apple/jit.pla libsrc/jitcore.pla $(PLVMJIT) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/jit.pla > libsrc/apple/jit.a @@ -451,8 +453,8 @@ $(JIT16): libsrc/apple/jit16.pla libsrc/jit16core.pla $(PLVMJIT) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/jit16.pla > libsrc/apple/jit16.a acme --setpc 4094 -o $(JIT16) libsrc/apple/jit16.a -$(JITUNE): libsrc/apple/jitune.pla $(PLVMJIT) $(PLASM) - ./$(PLASM) -AMOW < libsrc/apple/jitune.pla > libsrc/apple/jitune.a - acme --setpc 4094 -o $(JITUNE) libsrc/apple/jitune.a +$(JITUNE): utilsrc/apple/jitune.pla $(PLVMJIT) $(PLASM) + ./$(PLASM) -AMOW < utilsrc/apple/jitune.pla > utilsrc/apple/jitune.a + acme --setpc 4094 -o $(JITUNE) utilsrc/apple/jitune.a diff --git a/src/mkrel b/src/mkrel index a1eef8d..a664252 100755 --- a/src/mkrel +++ b/src/mkrel @@ -12,12 +12,12 @@ cp rel/apple/CONIO#FE1000 prodos/sys/CONIO.REL cp rel/apple/LINESPANS#FE1000 prodos/sys/LINESPANS.REL cp rel/apple/GRLIB#FE1000 prodos/sys/GRLIB.REL cp rel/apple/DGRLIB#FE1000 prodos/sys/DGRLIB.REL -cp rel/COPY#FE1000 prodos/sys/COPY.REL -cp rel/DEL#FE1000 prodos/sys/DEL.REL -cp rel/REN#FE1000 prodos/sys/REN.REL -cp rel/CAT#FE1000 prodos/sys/CAT.REL -cp rel/NEWDIR#FE1000 prodos/sys/NEWDIR.REL -cp rel/TYPE#FE1000 prodos/sys/TYPE.REL +cp rel/apple/COPY#FE1000 prodos/sys/COPY.REL +cp rel/apple/DEL#FE1000 prodos/sys/DEL.REL +cp rel/apple/REN#FE1000 prodos/sys/REN.REL +cp rel/apple/CAT#FE1000 prodos/sys/CAT.REL +cp rel/apple/NEWDIR#FE1000 prodos/sys/NEWDIR.REL +cp rel/apple/TYPE#FE1000 prodos/sys/TYPE.REL cp rel/ARGS#FE1000 prodos/sys/ARGS.REL cp rel/ED#FE1000 prodos/sys/ED.REL cp rel/FIBER#FE1000 prodos/sys/FIBER.REL @@ -90,7 +90,6 @@ cp rel/apple/GFXDEMO#FE1000 prodos/demos/apple3/GFXDEMO.REL cp samplesrc/APPLE3.PIX#060000 prodos/demos/apple3/APPLE3.PIX.BIN mkdir prodos/demos/net -cp rel/TFTPD#FE1000 prodos/demos/net/TFTPD.REL cp rel/HTTPD#FE1000 prodos/demos/net/HTTPD.REL cp samplesrc/index.html prodos/demos/net/INDEX.HTML.TXT @@ -111,7 +110,6 @@ cp samplesrc/dgrtest.pla prodos/bld/samples/DGRTEST.PLA.TXT cp samplesrc/hgrtest.pla prodos/bld/samples/HGRTEST.PLA.TXT cp samplesrc/fibertest.pla prodos/bld/samples/FIBERTEST.PLA.TXT cp samplesrc/mousetest.pla prodos/bld/samples/MOUSETEST.PLA.TXT -cp samplesrc/mon.pla prodos/bld/samples/MON.PLA.TXT cp samplesrc/memtest.pla prodos/bld/samples/MEMTEST.PLA.TXT cp samplesrc/rod.pla prodos/bld/samples/ROD.PLA.TXT cp samplesrc/sieve.pla prodos/bld/samples/SIEVE.PLA.TXT diff --git a/src/tftpdemos b/src/tftpdemos index 159f871..0ea1c38 100755 --- a/src/tftpdemos +++ b/src/tftpdemos @@ -29,6 +29,5 @@ echo "DEMOS/SDUTILS/FATREADDSK"; atftp $1 --put -l rel/apple/FATREADDSK#FE1000 echo "DEMOS/SDUTILS/FATWRITEDSK"; atftp $1 --put -l rel/apple/FATWRITEDSK#FE1000 -r $2/DEMOS/SDUTILS/FATWRITEDSK#FE1000 # Net demos -echo "DEMOS/NET/TFTPD"; atftp $1 --put -l rel/TFTPD#FE1000 -r $2/DEMOS/NET/TFTPD#FE1000 echo "DEMOS/NET/HTTPD"; atftp $1 --put -l rel/HTTPD#FE1000 -r $2/DEMOS/NET/HTTPD#FE1000 atftp $1 --put -l samplesrc/index.html -r $2/DEMOS/NET/INDEX.HTML#040000 diff --git a/src/tftpsys b/src/tftpsys index 4cffe31..10be2d3 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -19,6 +19,7 @@ echo "SYS/FIBER"; atftp $1 --put -l rel/FIBER#FE1000 -r $2/SYS/FIBER#FE1000 echo "SYS/INET"; atftp $1 --put -l rel/INET#FE1000 -r $2/SYS/INET#FE1000 echo "SYS/LONGJUMP"; atftp $1 --put -l rel/LONGJMP#FE1000 -r $2/SYS/LONGJMP#FE1000 echo "SYS/MEMMGR"; atftp $1 --put -l rel/MEMMGR#FE1000 -r $2/SYS/MEMMGR#FE1000 +echo "SYS/LZ4"; atftp $1 --put -l rel/LZ4#FE1000 -r $2/SYS/LZ4#FE1000 echo "SYS/CONIO"; atftp $1 --put -l rel/apple/CONIO#FE1000 -r $2/SYS/CONIO#FE1000 echo "SYS/LINESPANS"; atftp $1 --put -l rel/apple/LINESPANS#FE1000 -r $2/SYS/LINESPANS#FE1000 echo "SYS/GRLIB"; atftp $1 --put -l rel/apple/GRLIB#FE1000 -r $2/SYS/GRLIB#FE1000 diff --git a/src/tftputil b/src/tftputil index 4f440a6..156f93b 100755 --- a/src/tftputil +++ b/src/tftputil @@ -2,13 +2,12 @@ # Core utilities echo "SYS/ED"; atftp $1 --put -l rel/ED#FE1000 -r $2/SYS/ED#FE1000 -echo "SYS/COPY"; atftp $1 --put -l rel/COPY#FE1000 -r $2/SYS/COPY#FE1000 -echo "SYS/DEL"; atftp $1 --put -l rel/DEL#FE1000 -r $2/SYS/DEL#FE1000 -echo "SYS/REN"; atftp $1 --put -l rel/REN#FE1000 -r $2/SYS/REN#FE1000 -echo "SYS/CAT"; atftp $1 --put -l rel/CAT#FE1000 -r $2/SYS/CAT#FE1000 -echo "SYS/NEWDIR"; atftp $1 --put -l rel/NEWDIR#FE1000 -r $2/SYS/NEWDIR#FE1000 -echo "SYS/TYPE"; atftp $1 --put -l rel/TYPE#FE1000 -r $2/SYS/TYPE#FE1000 echo "SYS/TFTPD"; atftp $1 --put -l rel/TFTPD#FE1000 -r $2/SYS/TFTPD#FE1000 -echo "SYS/LZ4"; atftp $1 --put -l rel/LZ4#FE1000 -r $2/SYS/LZ4#FE1000 +echo "SYS/COPY"; atftp $1 --put -l rel/apple/COPY#FE1000 -r $2/SYS/COPY#FE1000 +echo "SYS/DEL"; atftp $1 --put -l rel/apple/DEL#FE1000 -r $2/SYS/DEL#FE1000 +echo "SYS/REN"; atftp $1 --put -l rel/apple/REN#FE1000 -r $2/SYS/REN#FE1000 +echo "SYS/CAT"; atftp $1 --put -l rel/apple/CAT#FE1000 -r $2/SYS/CAT#FE1000 +echo "SYS/NEWDIR"; atftp $1 --put -l rel/apple/NEWDIR#FE1000 -r $2/SYS/NEWDIR#FE1000 +echo "SYS/TYPE"; atftp $1 --put -l rel/apple/TYPE#FE1000 -r $2/SYS/TYPE#FE1000 echo "SYS/MON"; atftp $1 --put -l rel/apple/MON#FE1000 -r $2/SYS/MON#FE1000 echo "SYS/SOS"; atftp $1 --put -l rel/apple/SOS#FE1000 -r $2/SYS/SOS#FE1000 diff --git a/src/libsrc/cat.pla b/src/utilsrc/apple/cat.pla similarity index 100% rename from src/libsrc/cat.pla rename to src/utilsrc/apple/cat.pla diff --git a/src/libsrc/copy.pla b/src/utilsrc/apple/copy.pla similarity index 100% rename from src/libsrc/copy.pla rename to src/utilsrc/apple/copy.pla diff --git a/src/libsrc/del.pla b/src/utilsrc/apple/del.pla similarity index 100% rename from src/libsrc/del.pla rename to src/utilsrc/apple/del.pla diff --git a/src/libsrc/apple/jitune.pla b/src/utilsrc/apple/jitune.pla similarity index 100% rename from src/libsrc/apple/jitune.pla rename to src/utilsrc/apple/jitune.pla diff --git a/src/samplesrc/mon.pla b/src/utilsrc/apple/mon.pla similarity index 100% rename from src/samplesrc/mon.pla rename to src/utilsrc/apple/mon.pla diff --git a/src/libsrc/newdir.pla b/src/utilsrc/apple/newdir.pla similarity index 100% rename from src/libsrc/newdir.pla rename to src/utilsrc/apple/newdir.pla diff --git a/src/libsrc/ren.pla b/src/utilsrc/apple/ren.pla similarity index 100% rename from src/libsrc/ren.pla rename to src/utilsrc/apple/ren.pla diff --git a/src/libsrc/apple/sos.pla b/src/utilsrc/apple/sos.pla similarity index 100% rename from src/libsrc/apple/sos.pla rename to src/utilsrc/apple/sos.pla diff --git a/src/libsrc/type.pla b/src/utilsrc/apple/type.pla similarity index 100% rename from src/libsrc/type.pla rename to src/utilsrc/apple/type.pla diff --git a/src/samplesrc/tftpd.pla b/src/utilsrc/tftpd.pla similarity index 100% rename from src/samplesrc/tftpd.pla rename to src/utilsrc/tftpd.pla From 5ca96095cf603109deba7d250174cc89d9907c5d Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sun, 22 Dec 2019 18:44:58 -0800 Subject: [PATCH 069/149] New 32 bit integer library --- src/libsrc/int32.pla | 231 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 src/libsrc/int32.pla diff --git a/src/libsrc/int32.pla b/src/libsrc/int32.pla new file mode 100644 index 0000000..1eee3e7 --- /dev/null +++ b/src/libsrc/int32.pla @@ -0,0 +1,231 @@ +// +// 32 bit integer math routines +// +include "inc/cmdsys.plh" +// +// Include zero page definitions +// +asm int32Inc + !SOURCE "vmsrc/plvmzp.inc" +ACCUM32 = DSTH+1 +end +export asm accum32zero#0 + LDA #$00 + STA ACCUM32+0 + STA ACCUM32+1 + STA ACCUM32+2 + STA ACCUM32+3 + RTS +end +export asm accum32neg#0 + LDA #$00 + SEC + SBC ACCUM32+0 + STA ACCUM32+0 + LDA #$00 + SBC ACCUM32+1 + STA ACCUM32+1 + LDA #$00 + SBC ACCUM32+2 + STA ACCUM32+2 + LDA #$00 + SBC ACCUM32+3 + STA ACCUM32+3 + RTS +end +export asm accum32loadi(imm16)#0 + LDY #$00 + LDA ESTKL+0,X + STA ACCUM32+0 + LDA ESTKH+0,X + BPL + ; SIGN EXTEND + DEY ++ STA ACCUM32+1 + STY ACCUM32+2 + STY ACCUM32+3 + INX + RTS +end +export asm accum32load(i32ptr)#0 + LDA ESTKL+0,X ; i32PTR + STA SRCL + LDA ESTKH+0,X ; I32PTR + STA SRCL + LDY #$00 + LDA (SRC),Y + STA ACCUM32+0 + INY + LDA (SRC),Y + STA ACCUM32+1 + INY + LDA (SRC),Y + STA ACCUM32+2 + INY + LDA (SRC),Y + STA ACCUM32+3 + INX + RTS +end +export asm accum32store(i32ptr)#0 + LDA ESTKL+0,X ; i32PTR + STA DSTL + LDA ESTKH+0,X ; I32PTR + STA DSTL + LDY #$00 + LDA ACCUM32+0 + STA (DST),Y + INY + LDA ACCUM32+1 + STA (DST),Y + INY + LDA ACCUM32+2 + STA (DST),Y + INY + LDA ACCUM32+3 + STA (DST),Y + RTS +end +export asm accum32addi(imm16)#0 + LDY #$00 + LDA ESTKL+0,X ; IMM16 + CLC + ADC ACCUM32+0 + STA ACCUM32+0 + LDA ESTKH+0,X ; IMM16 + BPL + + DEY ++ ADC ACCUM32+1 + STA ACCUM32+1 + TYA + ADC ACCUM32+2 + STA ACCUM32+2 + TYA + ADC ACCUM32+3 + STA ACCUM32+3 + INX + RTS +end +export asm accum32add(i32ptr)#0 + LDA ESTKL+0,X ; I32PTR + STA SRCL + LDA ESTKH+0,X ; I32PTR + STA SRCL + LDY #$00 + LDA (SRC),Y + CLC + ADC ACCUM32+0 + STA ACCUM32+0 + INY + ADC ACCUM32+1 + STA ACCUM32+1 + INY + ADC ACCUM32+2 + STA ACCUM32+2 + INY + ADC ACCUM32+3 + STA ACCUM32+3 + INX + RTS +end +export asm accum32subi(imm16)#0 + LDY #$00 + LDA ESTKL+0,X ; IMM16 + SEC + SBC ACCUM32+0 + STA ACCUM32+0 + LDA ESTKH+0,X ; IMM16 + BPL + + DEY ++ SBC ACCUM32+1 + STA ACCUM32+1 + TYA + SBC ACCUM32+2 + STA ACCUM32+2 + TYA + SBC ACCUM32+3 + STA ACCUM32+3 + INX + RTS +end +export asm accum32sub(i32ptr)#0 + LDA ESTKL+0,X ; I32PTR + STA SRCL + LDA ESTKH+0,X ; I32PTR + STA SRCL + LDY #$00 + LDA (SRC),Y + SEC + SBC ACCUM32+0 + STA ACCUM32+0 + INY + SBC ACCUM32+1 + STA ACCUM32+1 + INY + SBC ACCUM32+2 + STA ACCUM32+2 + INY + SBC ACCUM32+3 + STA ACCUM32+3 + INX + RTS +end +export asm accum32mul(i32ptr)#0 + LDA ESTKL+1,X ; I32PTR + STA SRCL + LDA ESTKH+1,X ; I32PTR + STA SRCH + STX ESP + LDX #$00 + LDY #$03 + STY IPY + LDA #$80 +_MULLP PHA + LDY IPY + AND (TMP),Y + BEQ + + LDY #$00 + CLC + LDA (SRC),Y + ADC (DST),Y + STA (DST),Y + INY + LDA (SRC),Y + ADC (DST),Y + STA (DST),Y + INY + LDA (SRC),Y + ADC (DST),Y + STA (DST),Y + INY + LDA (SRC),Y + ADC (DST),Y + STA (DST),Y ++ DEX + BEQ ++ + LDY #$00 + ASL (DST),Y + INY + ROL (DST),Y + INY + ROL (DST),Y + INY + ROL (DST),Y + PLA + LSR + BNE _MULLP + LDA #$80 + DEC IPY + +_SHLPRD LDY + ASL ESTKL,X ; MULTPLNDL + ROL ESTKH,X ; MULTPLNDH + DEX + BNE _MULLP + STA ESTKH+1,X ; PRODH + + LDX ESP + INX + INX + INX + RTS +end From 21972866040faa3a92751f31c9040b3c557e2da0 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 22 Dec 2019 21:41:53 -0800 Subject: [PATCH 070/149] int32 WIP --- src/libsrc/int32.pla | 266 ++++++++++++++++++++++++++++++++----------- 1 file changed, 198 insertions(+), 68 deletions(-) diff --git a/src/libsrc/int32.pla b/src/libsrc/int32.pla index 1eee3e7..add490f 100644 --- a/src/libsrc/int32.pla +++ b/src/libsrc/int32.pla @@ -47,9 +47,9 @@ export asm accum32loadi(imm16)#0 RTS end export asm accum32load(i32ptr)#0 - LDA ESTKL+0,X ; i32PTR + LDA ESTKL+0,X ; I32PTR STA SRCL - LDA ESTKH+0,X ; I32PTR + LDA ESTKH+0,X ; I32PTR STA SRCL LDY #$00 LDA (SRC),Y @@ -67,9 +67,9 @@ export asm accum32load(i32ptr)#0 RTS end export asm accum32store(i32ptr)#0 - LDA ESTKL+0,X ; i32PTR + LDA ESTKL+0,X ; I32PTR STA DSTL - LDA ESTKH+0,X ; I32PTR + LDA ESTKH+0,X ; I32PTR STA DSTL LDY #$00 LDA ACCUM32+0 @@ -87,11 +87,11 @@ export asm accum32store(i32ptr)#0 end export asm accum32addi(imm16)#0 LDY #$00 - LDA ESTKL+0,X ; IMM16 + LDA ESTKL+0,X ; IMM16 CLC ADC ACCUM32+0 STA ACCUM32+0 - LDA ESTKH+0,X ; IMM16 + LDA ESTKH+0,X ; IMM16 BPL + DEY + ADC ACCUM32+1 @@ -106,9 +106,9 @@ export asm accum32addi(imm16)#0 RTS end export asm accum32add(i32ptr)#0 - LDA ESTKL+0,X ; I32PTR + LDA ESTKL+0,X ; I32PTR STA SRCL - LDA ESTKH+0,X ; I32PTR + LDA ESTKH+0,X ; I32PTR STA SRCL LDY #$00 LDA (SRC),Y @@ -129,11 +129,11 @@ export asm accum32add(i32ptr)#0 end export asm accum32subi(imm16)#0 LDY #$00 - LDA ESTKL+0,X ; IMM16 + LDA ESTKL+0,X ; IMM16 SEC SBC ACCUM32+0 STA ACCUM32+0 - LDA ESTKH+0,X ; IMM16 + LDA ESTKH+0,X ; IMM16 BPL + DEY + SBC ACCUM32+1 @@ -148,9 +148,9 @@ export asm accum32subi(imm16)#0 RTS end export asm accum32sub(i32ptr)#0 - LDA ESTKL+0,X ; I32PTR + LDA ESTKL+0,X ; I32PTR STA SRCL - LDA ESTKH+0,X ; I32PTR + LDA ESTKH+0,X ; I32PTR STA SRCL LDY #$00 LDA (SRC),Y @@ -169,63 +169,193 @@ export asm accum32sub(i32ptr)#0 INX RTS end -export asm accum32mul(i32ptr)#0 - LDA ESTKL+1,X ; I32PTR - STA SRCL - LDA ESTKH+1,X ; I32PTR - STA SRCH - STX ESP - LDX #$00 - LDY #$03 - STY IPY - LDA #$80 -_MULLP PHA - LDY IPY - AND (TMP),Y +export asm accum32shl(imm8)#0 + LDA ESTKL+0,X ; IMM8 + AND #$01F BEQ + - LDY #$00 - CLC - LDA (SRC),Y - ADC (DST),Y - STA (DST),Y - INY - LDA (SRC),Y - ADC (DST),Y - STA (DST),Y - INY - LDA (SRC),Y - ADC (DST),Y - STA (DST),Y - INY - LDA (SRC),Y - ADC (DST),Y - STA (DST),Y -+ DEX - BEQ ++ - LDY #$00 - ASL (DST),Y - INY - ROL (DST),Y - INY - ROL (DST),Y - INY - ROL (DST),Y - PLA - LSR - BNE _MULLP - LDA #$80 - DEC IPY - -_SHLPRD LDY - ASL ESTKL,X ; MULTPLNDL - ROL ESTKH,X ; MULTPLNDH - DEX - BNE _MULLP - STA ESTKH+1,X ; PRODH - - LDX ESP - INX - INX + TAY +- ASL ACCUM32+0 + ROL ACCUM32+1 + ROL ACCUM32+2 + ROL ACCUM32+3 + DEY + BNE - INX RTS end +export asm accum32shr(imm8)#0 + LDA ESTKL+0,X ; IMM8 + AND #$01F + BEQ + + TAY + LDA #$80 +- CMP ACCUM32 + ROR ACCUM32+3 + ROR ACCUM32+2 + ROR ACCUM32+1 + ROR ACCUM32+0 + DEY + BNE - + INX + RTS +end +export asm accum32muli(imm16)#0 + LDY #$00 + LDA ESTKL+0,X ; IMM16 + STA SRC+0 + LDA ESTKH+0,X ; IMM16 + STA SRC+1 + BPL + ; SIGN EXTENR + DEY ++ STY SRC+2 + STY SRC+3 +end +export asm accum32mul(i32ptr)#0 + LDA ESTKL+0,X ; I32PTR + STA TMPL + LDA ESTKH+0,X ; I32PTR + STA TMPH + LDY #$03 +- LDA (TMP),Y + STA SRC,Y + DEY + BPL - + LDA ACCUM32+0 + STA ESTKL-1,X + LDA ACCUM32+1 + STA ESTKH-1,X + LDA ACCUM32+2 + STA ESTKL+0,X + LDA ACCUM32+3 + STA ESTKH+0,X + LDA #$00 + STA ACCUM32+0 + STA ACCUM32+1 + STA ACCUM32+2 + STA ACCUM32+3 + LDY #$03 + LDA #$80 + STA TMPL +_MULLP AND SRC,Y + BEQ + + CLC + LDA ESTKL-1,X + ADC ACCUM32+0 + STA ACCUM32+0 + LDA ESTKH-1,X + ADC ACCUM32+1 + STA ACCUM32+1 + LDA ESTKL+0,X + ADC ACCUM32+2 + STA ACCUM32+2 + LDA ESTKH+0,X + ADC ACCUM32+3 + STA ACCUM32+3 ++ LSR TMPL + BCC + + DEY + BMI ++ + ROR TMPL ++ ASL ACCUM32+0 + ROL ACCUM32+1 + ROL ACCUM32+2 + ROL ACCUM32+3 + LDA TMPL + BNE _MULLP +++ INX + RTS +end +export asm accum32div(i32ptr)#0 + LDA ESTKL+0,X ; I32PTR + STA TMPL + LDA ESTKH+0,X ; I32PTR + STA TMPH + LDY #$03 +- LDA (TMP),Y + STA SRC,Y + DEY + BPL - + LDA ACCUM32+3 + BMI + + STA ESTKH+0,X + LDA ACCUM32+2 + STA ESTKL+0,X + LDA ACCUM32+1 + STA ESTKH-1,X + LDA ACCUM32+0 + STA ESTKL-1,X + + SEC + LDA #$00 + SBC ACCUM32+0 + STA ESTKL-1,X + LDA #$00 + SBC ACCUM32+1 + STA ESTKH-1,X + LDA #$00 + SBC ACCUM32+2 + STA ESTKL+0,X + LDA #$00 + SBC ACCUM32+3 + STA ESTKH+0,X + + + LDA #$00 + STA ACCUM32+0 + STA ACCUM32+1 + STA ACCUM32+2 + STA ACCUM32+3 + LDY #$03 + + +_NEG LDA #$00 + SEC + SBC ESTKL,X + STA ESTKL,X + LDA #$00 + SBC ESTKH,X + STA ESTKH,X + RTS +_DIV STY IPY + LDY #$11 ; #BITS+1 + LDA #$00 + STA TMPL ; REMNDRL + STA TMPH ; REMNDRH + STA DVSIGN + LDA ESTKH+1,X + BPL + + INX + JSR _NEG + DEX + LDA #$81 + STA DVSIGN ++ ORA ESTKL+1,X ; DVDNDL + BEQ _DIVEX + LDA ESTKH,X + BPL _DIV1 + JSR _NEG + INC DVSIGN +_DIV1 ASL ESTKL+1,X ; DVDNDL + ROL ESTKH+1,X ; DVDNDH + DEY + BCC _DIV1 +_DIVLP ROL TMPL ; REMNDRL + ROL TMPH ; REMNDRH + LDA TMPL ; REMNDRL + CMP ESTKL,X ; DVSRL + LDA TMPH ; REMNDRH + SBC ESTKH,X ; DVSRH + BCC + + STA TMPH ; REMNDRH + LDA TMPL ; REMNDRL + SBC ESTKL,X ; DVSRL + STA TMPL ; REMNDRL + SEC ++ ROL ESTKL+1,X ; DVDNDL + ROL ESTKH+1,X ; DVDNDH + DEY + BNE _DIVLP +_DIVEX INX + LDY IPY + RTS +end From 5f8f6f0a970c3089f76455a91a55336c84917110 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Mon, 23 Dec 2019 17:16:03 -0800 Subject: [PATCH 071/149] int32 WIP --- src/libsrc/int32.pla | 597 +++++++++++++++++++++++++++++++------------ 1 file changed, 427 insertions(+), 170 deletions(-) diff --git a/src/libsrc/int32.pla b/src/libsrc/int32.pla index add490f..3bf74e9 100644 --- a/src/libsrc/int32.pla +++ b/src/libsrc/int32.pla @@ -9,7 +9,7 @@ asm int32Inc !SOURCE "vmsrc/plvmzp.inc" ACCUM32 = DSTH+1 end -export asm accum32zero#0 +export asm zero32#0 LDA #$00 STA ACCUM32+0 STA ACCUM32+1 @@ -17,7 +17,13 @@ export asm accum32zero#0 STA ACCUM32+3 RTS end -export asm accum32neg#0 +export asm zext16to32#0 + LDA #$00 + STA ACCUM32+2 + STA ACCUM32+3 + RTS +end +export asm neg32#0 LDA #$00 SEC SBC ACCUM32+0 @@ -33,23 +39,10 @@ export asm accum32neg#0 STA ACCUM32+3 RTS end -export asm accum32loadi(imm16)#0 - LDY #$00 - LDA ESTKL+0,X - STA ACCUM32+0 - LDA ESTKH+0,X - BPL + ; SIGN EXTEND - DEY -+ STA ACCUM32+1 - STY ACCUM32+2 - STY ACCUM32+3 - INX - RTS -end -export asm accum32load(i32ptr)#0 - LDA ESTKL+0,X ; I32PTR +export asm load32(i32ptr)#0 + LDA ESTKL+0,X ; I32PTR STA SRCL - LDA ESTKH+0,X ; I32PTR + LDA ESTKH+0,X ; I32PTR STA SRCL LDY #$00 LDA (SRC),Y @@ -66,10 +59,23 @@ export asm accum32load(i32ptr)#0 INX RTS end -export asm accum32store(i32ptr)#0 - LDA ESTKL+0,X ; I32PTR +export asm loadi16(imm16)#0 + LDY #$00 + LDA ESTKL+0,X ; IMM16L + STA ACCUM32+0 + LDA ESTKH+0,X ; IMM16H + BPL + ; SIGN EXTEND + DEY ++ STA ACCUM32+1 + STY ACCUM32+2 + STY ACCUM32+3 + INX + RTS +end +export asm store32(i32ptr)#0 + LDA ESTKL+0,X ; I32PTR STA DSTL - LDA ESTKH+0,X ; I32PTR + LDA ESTKH+0,X ; I32PTR STA DSTL LDY #$00 LDA ACCUM32+0 @@ -85,13 +91,38 @@ export asm accum32store(i32ptr)#0 STA (DST),Y RTS end -export asm accum32addi(imm16)#0 +export asm add32(i32ptr)#0 + LDA ESTKL+0,X ; I32PTR + STA SRCL + LDA ESTKH+0,X ; I32PTR + STA SRCL LDY #$00 - LDA ESTKL+0,X ; IMM16 + LDA (SRC),Y CLC ADC ACCUM32+0 STA ACCUM32+0 - LDA ESTKH+0,X ; IMM16 + INY + LDA (SRC),Y + ADC ACCUM32+1 + STA ACCUM32+1 + INY + LDA (SRC),Y + ADC ACCUM32+2 + STA ACCUM32+2 + INY + LDA (SRC),Y + ADC ACCUM32+3 + STA ACCUM32+3 + INX + RTS +end +export asm addi16(imm16)#0 + LDY #$00 + LDA ESTKL+0,X ; IMM16L + CLC + ADC ACCUM32+0 + STA ACCUM32+0 + LDA ESTKH+0,X ; IMM16H BPL + DEY + ADC ACCUM32+1 @@ -105,35 +136,38 @@ export asm accum32addi(imm16)#0 INX RTS end -export asm accum32add(i32ptr)#0 - LDA ESTKL+0,X ; I32PTR +export asm sub32(i32ptr)#0 + LDA ESTKL+0,X ; I32PTR STA SRCL - LDA ESTKH+0,X ; I32PTR + LDA ESTKH+0,X ; I32PTR STA SRCL LDY #$00 LDA (SRC),Y - CLC - ADC ACCUM32+0 + SEC + SBC ACCUM32+0 STA ACCUM32+0 INY - ADC ACCUM32+1 + LDA (SRC),Y + SBC ACCUM32+1 STA ACCUM32+1 INY - ADC ACCUM32+2 + LDA (SRC),Y + SBC ACCUM32+2 STA ACCUM32+2 INY - ADC ACCUM32+3 + LDA (SRC),Y + SBC ACCUM32+3 STA ACCUM32+3 INX RTS end -export asm accum32subi(imm16)#0 +export asm subi16(imm16)#0 LDY #$00 - LDA ESTKL+0,X ; IMM16 + LDA ESTKL+0,X ; IMM16L SEC SBC ACCUM32+0 STA ACCUM32+0 - LDA ESTKH+0,X ; IMM16 + LDA ESTKH+0,X ; IMM16H BPL + DEY + SBC ACCUM32+1 @@ -147,44 +181,43 @@ export asm accum32subi(imm16)#0 INX RTS end -export asm accum32sub(i32ptr)#0 - LDA ESTKL+0,X ; I32PTR - STA SRCL - LDA ESTKH+0,X ; I32PTR - STA SRCL - LDY #$00 - LDA (SRC),Y - SEC - SBC ACCUM32+0 - STA ACCUM32+0 - INY - SBC ACCUM32+1 - STA ACCUM32+1 - INY - SBC ACCUM32+2 - STA ACCUM32+2 - INY - SBC ACCUM32+3 - STA ACCUM32+3 - INX - RTS -end -export asm accum32shl(imm8)#0 - LDA ESTKL+0,X ; IMM8 +export asm shl32(imm8)#0 + LDA ESTKL+0,X ; IMM8 AND #$01F - BEQ + - TAY + CMP #16 + BCC + + LDY ACCUM32+1 + STY ACCUM32+3 + LDY ACCUM32+0 + STY ACCUM32+2 + LDY #$00 + STY ACCUM32+1 + STY ACCUM32+0 + SBC #16 ++ CMP #8 + BCC + + LDY ACCUM32+2 + STY ACCUM32+3 + LDY ACCUM32+1 + STY ACCUM32+2 + LDY ACCUM32+0 + STY ACCUM32+1 + LDY #$00 + STY ACCUM32+0 + SBC #8 ++ TAY + BEQ ++ - ASL ACCUM32+0 ROL ACCUM32+1 ROL ACCUM32+2 ROL ACCUM32+3 DEY BNE - - INX +++ INX RTS end -export asm accum32shr(imm8)#0 - LDA ESTKL+0,X ; IMM8 +export asm shr32(imm8)#0 + LDA ESTKL+0,X ; IMM8 AND #$01F BEQ + TAY @@ -196,31 +229,34 @@ export asm accum32shr(imm8)#0 ROR ACCUM32+0 DEY BNE - - INX ++ INX RTS end -export asm accum32muli(imm16)#0 - LDY #$00 - LDA ESTKL+0,X ; IMM16 - STA SRC+0 - LDA ESTKH+0,X ; IMM16 - STA SRC+1 - BPL + ; SIGN EXTENR - DEY -+ STY SRC+2 - STY SRC+3 -end -export asm accum32mul(i32ptr)#0 - LDA ESTKL+0,X ; I32PTR +export asm mul32(i32ptr)#0 + LDA ESTKL+0,X ; I32PTR STA TMPL - LDA ESTKH+0,X ; I32PTR + LDA ESTKH+0,X ; I32PTR STA TMPH LDY #$03 - LDA (TMP),Y STA SRC,Y DEY BPL - - LDA ACCUM32+0 + INY + BEQ _MUL +end +export asm muli16(imm16)#0 + LDY #$00 + LDA ESTKL+0,X ; IMM16L + STA SRC+0 + LDA ESTKH+0,X ; IMM16H + STA SRC+1 + BPL + ; SIGN EXTEND + DEY ++ STY SRC+2 + STY SRC+3 + LDY #$00 +_MUL LDA ACCUM32+0 STA ESTKL-1,X LDA ACCUM32+1 STA ESTKH-1,X @@ -228,15 +264,14 @@ export asm accum32mul(i32ptr)#0 STA ESTKL+0,X LDA ACCUM32+3 STA ESTKH+0,X - LDA #$00 - STA ACCUM32+0 - STA ACCUM32+1 - STA ACCUM32+2 - STA ACCUM32+3 + STY ACCUM32+0 + STY ACCUM32+1 + STY ACCUM32+2 + STY ACCUM32+3 LDY #$03 LDA #$80 STA TMPL -_MULLP AND SRC,Y +- AND SRC,Y BEQ + CLC LDA ESTKL-1,X @@ -261,101 +296,323 @@ _MULLP AND SRC,Y ROL ACCUM32+2 ROL ACCUM32+3 LDA TMPL - BNE _MULLP + BNE - ++ INX RTS end -export asm accum32div(i32ptr)#0 - LDA ESTKL+0,X ; I32PTR +export asm div32(i32ptr)#2 + LDA ESTKL+0,X ; I32PTR STA TMPL - LDA ESTKH+0,X ; I32PTR + LDA ESTKH+0,X ; I32PTR + STA TMPH + LDY #$03 ; DVSR = SRC..SRC+3 + LDA (TMP),Y + BMI + + STA SRC+3 + DEY +- LDA (TMP),Y + STA SRC,Y + DEY + BPL - + INY + BEQ _DIV ++ SEC +- LDA #$00 + SBC (TMP),Y + STA SRC,Y + DEY + BPL - + LDY #$01 + BNE _DIV +end +export asm divi16(imm16)#2 + LDY #$00 ; DVSR = SRC..SRC+3 + STY SRC+2 + STY SRC+3 + LDA ESTKH+0,X ; IMM16H + BPL + + TYA ; DVSR IS NEG + SEC + SBC ESTKL+0,X ; IMM16L + STA SRC+0 + TYA + SBC ESTKH+0,X ; IMM16L + STA SRC+1 + INY + BNE _DIV ++ STA SRC+1 + LDA ESTKL+0,X ; IMM16L + STA SRC+0 +_DIV STY DIVSGN ; LSB = SIGN OF DVSR + DEX ; REMNDR = ESTK..ESTK+1 + LDY #$00 + STY ESTKL+0,X + STY ESTKH+0,X + STY ESTKL+1,X + STY ESTKH+1,X + LDA SRC+0 ; DIVIDE BY 0? + ORA SRC+1 + ORA SRC+2 + ORA SRC+3 + BNE + + STA ACCUM32+0 ; SET TO 0 AND EXIT + STA ACCUM32+1 + STA ACCUM32+2 + STA ACCUM32+3 +- RTS ++ LDA ACCUM32+0 ; DIVIDE 0? + ORA ACCUM32+1 + ORA ACCUM32+2 + ORA ACCUM32+3 + BEQ - + LDA ACCUM32+3 ; DVDND = ACCUM32 + BPL + + LDA #$81 ; DVDND IS NEG + CLC + ADC DIVSGN + STA DIVSGN + TYA + SEC + SBC ACCUM32+0 + STA ACCUM32+0 + TYA + SBC ACCUM32+1 + STA ACCUM32+1 + TYA + SBC ACCUM32+2 + STA ACCUM32+2 + TYA + SBC ACCUM32+3 + STA ACCUM32+3 ++ LDY #$21 ; #BITS+1 +- ASL ACCUM32+0 ; SKIP DVDND LEADING 0 BITS + ROL ACCUM32+1 + ROL ACCUM32+2 + ROL ACCUM32+3 + DEY + BCC - +- ROL ESTKL+0,X ; REMNDR + ROL ESTKH+0,X + ROL ESTKL+1,X + ROL ESTKH+1,X + LDA ESTKL+0,X ; REMNDR + CMP SRC+0 ; DVSR + LDA ESTKH+0,X ; COMPARE + SBC SRC+1 + LDA ESTKL+1,X + SBC SRC+2 + LDA ESTKH+1,X + SBC SRC+3 + BCC + ; IS LESS THAN? + STA ESTKH+1,X + LDA ESTKL+0,X ; REMNDR + SBC SRC+0 ; DVSR + STA ESTKL+0 ; SUBTRACT + LDA ESTKH+0,X + SBC SRC+1 + STA ESTKH+0,X + LDA ESTKL+1,X + SBC SRC+2 + STA ESTKL+1,X + SEC ++ ROL ACCUM32+0 ; DVDND + ROL ACCUM32+1 ; ROTATE IN RESULT + ROL ACCUM32+2 + ROL ACCUM32+3 + DEY + BNE - + LDA DIVSGN + BPL + + TYA + SEC + SBC ESTKL+0,X + STA ESTKL+0,X + TYA + SBC ESTKH+0,X + STA ESTKH+0,X + TYA + SBC ESTKL+1,X + STA ESTKL+1,X + TYA + SBC ESTKH+1,X + STA ESTKH+1,X + LDA DIVSGN ++ LSR + BCC + + TYA + SEC + SBC ACCUM32+0 + STA ACCUM32+0 + TYA + SBC ACCUM32+1 + STA ACCUM32+1 + TYA + SBC ACCUM32+2 + STA ACCUM32+2 + TYA + SBC ACCUM32+3 + STA ACCUM32+3 ++ RTS +end + +export asm iseq32(i32ptr)#1 + LDA ESTKL+0,X ; I32PTR + STA TMPL + LDA ESTKH+0,X ; I32PTR STA TMPH LDY #$03 - LDA (TMP),Y STA SRC,Y DEY BPL - - LDA ACCUM32+3 - BMI + - STA ESTKH+0,X - LDA ACCUM32+2 - STA ESTKL+0,X + INY + BEQ _ISEQ +end +export asm iseqi16(imm16)#1 + LDY #$00 + LDA ESTKL+0,X ; IMM16L + STA SRC+0 + LDA ESTKH+0,X ; IMM16H + STA SRC+1 + BPL + ; SIGN EXTEND + DEY ++ STY SRC+2 + STY SRC+3 + LDY #$00 +_ISEQ LDA ACCUM32+0 + CMP SRC+0 + BNE + LDA ACCUM32+1 - STA ESTKH-1,X - LDA ACCUM32+0 - STA ESTKL-1,X - - SEC - LDA #$00 - SBC ACCUM32+0 - STA ESTKL-1,X - LDA #$00 - SBC ACCUM32+1 - STA ESTKH-1,X - LDA #$00 - SBC ACCUM32+2 - STA ESTKL+0,X - LDA #$00 - SBC ACCUM32+3 - STA ESTKH+0,X - - - LDA #$00 - STA ACCUM32+0 - STA ACCUM32+1 - STA ACCUM32+2 - STA ACCUM32+3 - LDY #$03 - - -_NEG LDA #$00 - SEC - SBC ESTKL,X - STA ESTKL,X - LDA #$00 - SBC ESTKH,X - STA ESTKH,X - RTS -_DIV STY IPY - LDY #$11 ; #BITS+1 - LDA #$00 - STA TMPL ; REMNDRL - STA TMPH ; REMNDRH - STA DVSIGN - LDA ESTKH+1,X - BPL + - INX - JSR _NEG - DEX - LDA #$81 - STA DVSIGN -+ ORA ESTKL+1,X ; DVDNDL - BEQ _DIVEX - LDA ESTKH,X - BPL _DIV1 - JSR _NEG - INC DVSIGN -_DIV1 ASL ESTKL+1,X ; DVDNDL - ROL ESTKH+1,X ; DVDNDH + CMP SRC+1 + BNE + + LDA ACCUM32+2 + CMP SRC+2 + BNE + + LDA ACCUM32+3 + CMP SRC+3 + BNE + DEY - BCC _DIV1 -_DIVLP ROL TMPL ; REMNDRL - ROL TMPH ; REMNDRH - LDA TMPL ; REMNDRL - CMP ESTKL,X ; DVSRL - LDA TMPH ; REMNDRH - SBC ESTKH,X ; DVSRH - BCC + - STA TMPH ; REMNDRH - LDA TMPL ; REMNDRL - SBC ESTKL,X ; DVSRL - STA TMPL ; REMNDRL - SEC -+ ROL ESTKL+1,X ; DVDNDL - ROL ESTKH+1,X ; DVDNDH - DEY - BNE _DIVLP -_DIVEX INX - LDY IPY ++ STY ESTKL+0,X + STY ESTKH+0,X RTS end +export asm isge32(i32ptr)#1 + LDA ESTKL+0,X ; I32PTR + STA TMPL + LDA ESTKH+0,X ; I32PTR + STA TMPH + LDY #$03 +- LDA (TMP),Y + STA SRC,Y + DEY + BPL - + INY + BEQ _ISGE +end +export asm isgei16(imm16)#1 + LDY #$00 + LDA ESTKL+0,X ; IMM16L + STA SRC+0 + LDA ESTKH+0,X ; IMM16H + STA SRC+1 + BPL + ; SIGN EXTEND + DEY ++ STY SRC+2 + STY SRC+3 + LDY #$00 +_ISGE LDA ACCUM32+0 + CMP SRC+0 + LDA ACCUM32+1 + SBC SRC+1 + LDA ACCUM32+2 + SBC SRC+2 + LDA ACCUM32+3 + SBC SRC+3 + BVC + + EOR #$80 ++ BMI + + DEY ++ STY ESTKL+0,X + STY ESTKH+0,X + RTS +done +export asm isle32(i32ptr)#1 + LDA ESTKL+0,X ; I32PTR + STA TMPL + LDA ESTKH+0,X ; I32PTR + STA TMPH + LDY #$03 +- LDA (TMP),Y + STA SRC,Y + DEY + BPL - + INY + BEQ _ISLE +end +export asm islei16(imm16)#1 + LDY #$00 + LDA ESTKL+0,X ; IMM16L + STA SRC+0 + LDA ESTKH+0,X ; IMM16H + STA SRC+1 + BPL + ; SIGN EXTEND + DEY ++ STY SRC+2 + STY SRC+3 + LDY #$00 +_ISLE LDA SRC+0 + CMP ACCUM32+0 + LDA SRC+1 + SBC ACCUM32+1 + LDA SRC+2 + SBC ACCUM32+2 + LDA SRC+3 + SBC ACCUM32+3 + BVC + + EOR #$80 ++ BMI + + DEY ++ STY ESTKL+0,X + STY ESTKH+0,X + RTS +done +ISGT LDA ESTKL,X + CMP ESTKL+1,X + LDA ESTKH,X + SBC ESTKH+1,X + BVS + + BMI ISTRU + BPL ISFLS ++ +- BMI ISFLS + BPL ISTRU +ISLT LDA ESTKL+1,X + CMP ESTKL,X + LDA ESTKH+1,X + SBC ESTKH,X + BVS - + BMI ISTRU + BPL ISFLS +done +def puti32(i32ptr)#0 + res[t_i32] save + var iptr, rem + char[12] istr + + iptr = @istr.11 + + store32(@save) + load32(i32ptr) + if i32ptr->3 & $80 + neg32() + putc('-') + fin + repeat + rem = divi16(10) + ^iptr = rem + '0' + iptr-- + until isgti16(0) + ^iptr = @istr.11 - iptr + puts(iptr) + load32(@save) +done From a77c50c90a8ca6b769fae3329093a023f36537fe Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Tue, 24 Dec 2019 12:02:56 -0800 Subject: [PATCH 072/149] Add 32 bit integer librbary just to print out file sizes in CAT --- src/inc/fileio.plh | 21 ++++ src/inc/int32.plh | 32 +++++ src/libsrc/apple/fileio.pla | 29 +++-- src/libsrc/int32.pla | 238 +++++++++++++++++++++++------------- src/makefile | 12 +- src/mkrel | 4 + src/samplesrc/int32test.pla | 72 +++++++++++ src/toolsrc/ed.pla | 28 +++-- src/utilsrc/apple/cat.pla | 185 ++++++++++++++++++++-------- src/vmsrc/apple/cmd.pla | 8 +- src/vmsrc/apple/cmdjit.pla | 8 +- src/vmsrc/apple/soscmd.pla | 8 +- 12 files changed, 470 insertions(+), 175 deletions(-) create mode 100644 src/inc/int32.plh create mode 100644 src/samplesrc/int32test.pla diff --git a/src/inc/fileio.plh b/src/inc/fileio.plh index 2dd87b1..04c8cc6 100644 --- a/src/inc/fileio.plh +++ b/src/inc/fileio.plh @@ -18,7 +18,27 @@ import fileio const FILE_ERR_INT_TBL_FULL = $25 const FILE_ERR_IO = $27 // + // File entry struc + // + struc t_fileentry + byte store_namelen + byte entry_name[15] + byte entry_type + word entry_keyptr + word entry_blocks + word entry_EOFL + byte entry_EOFH + word entry_create[2] + byte entry_version + byte entry_minver + byte entry_access + word entry_aux + word entry_mod + word entry_headptr + end + // // File info struc + // struc t_fileinfo byte file_access byte file_type @@ -39,6 +59,7 @@ import fileio word getfileinfo word setfileinfo word geteof + word seteof word iobufalloc word open word close diff --git a/src/inc/int32.plh b/src/inc/int32.plh new file mode 100644 index 0000000..13e0096 --- /dev/null +++ b/src/inc/int32.plh @@ -0,0 +1,32 @@ +import int32 + const t_i32 = 4 + + predef zero32#0 + predef zext16to32#0 + predef neg32#0 + predef load32(i32ptr)#0 + predef loadi16(imm16)#0 + predef store32(i32ptr)#0 + predef add32(i32ptr)#0 + predef addi16(imm16)#0 + predef sub32(i32ptr)#0 + predef subi16(imm16)#0 + predef shl32(imm8)#0 + predef shr32(imm8)#0 + predef mul32(i32ptr)#0 + predef muli16(imm16)#0 + predef div32(i32ptr)#2 + predef divi16(imm16)#2 + predef iseq32(i32ptr)#1 + predef iseqi16(imm16)#1 + predef isge32(i32ptr)#1 + predef isgei16(imm16)#1 + predef isle32(i32ptr)#1 + predef islei16(imm16)#1 + predef isgt32(i32ptr)#1 + predef isgti16(imm16)#1 + predef islt32(i32ptr)#1 + predef islti16(imm16)#1 + predef i32tos(i32ptr, strptr)#1 + predef puti32(i32ptr)#0 +end diff --git a/src/libsrc/apple/fileio.pla b/src/libsrc/apple/fileio.pla index 0060c2a..9851bd9 100644 --- a/src/libsrc/apple/fileio.pla +++ b/src/libsrc/apple/fileio.pla @@ -28,6 +28,7 @@ struc t_fileio word getfileinfo word setfileinfo word geteof + word seteof word iobufalloc word open word close @@ -41,14 +42,14 @@ struc t_fileio word readblock word writeblock end -predef a2getpfx(path), a23setpfx(path), a2getfileinfo(path, fileinfo), a2setfileinfo(path, fileinfo), a23geteof(refnum), a2iobufs(iobufs), a2open(path), a2close(refnum) +predef a2getpfx(path), a23setpfx(path), a2getfileinfo(path, fileinfo), a2setfileinfo(path, fileinfo), a23geteof(refnum)#2, a23seteof(refnum, eofl, eofh), a2iobufs(iobufs), a2open(path), a2close(refnum) predef a23read(refnum, buf, len), a2write(refnum, buf, len), a2create(path, type, aux), a23destroy(path), a23rename(path, newpath) predef a2newline(refnum, emask, nlchar), a2online(unit, buf), a2readblock(unit, buf, block), a2writeblock(unit, buf, block) // // Exported function table. // word fileio[] -word = @a2getpfx, @a23setpfx, @a2getfileinfo, @a2setfileinfo, @a23geteof, @a2iobufs, @a2open, @a2close +word = @a2getpfx, @a23setpfx, @a2getfileinfo, @a2setfileinfo, @a23geteof, @a23seteof, @a2iobufs, @a2open, @a2close word = @a23read, @a2write, @a2create, @a23destroy, @a23rename word = @a2newline, @a2online, @a2readblock, @a2writeblock // @@ -143,17 +144,30 @@ def a3setfileinfo(path, fileinfo) perr = syscall($C3, @params) return perr end -def a1geteof(refnum) - return 0 +def a1geteof(refnum)#2 + return 0, 0 end -def a23geteof(refnum) - byte params[6] +def a23geteof(refnum)#2 + byte params[5] params.0 = 2 params.1 = refnum params:2 = 0 - params:4 = 0 + params.4 = 0 syscall($D1, @params) + return params:2, params.4 +end +def a1seteof(refnum, eofl, eofh) + return 0 +end +def a23seteof(refnum, eofl, eofh) + byte params[5] + + params.0 = 2 + params.1 = refnum + params:2 = eofl + params.4 = eofh + syscall($D0, @params) return params:2 end def a1open(path) @@ -468,6 +482,7 @@ when MACHID & MACHID_MODEL fileio:getfileinfo = @a1getfileinfo fileio:setfileinfo = @a1setfileinfo fileio:geteof = @a1geteof + fileio:seteof = @a1seteof fileio:iobufalloc = @a13iobufs fileio:open = @a1open fileio:close = @a1close diff --git a/src/libsrc/int32.pla b/src/libsrc/int32.pla index 3bf74e9..82a3e80 100644 --- a/src/libsrc/int32.pla +++ b/src/libsrc/int32.pla @@ -2,12 +2,14 @@ // 32 bit integer math routines // include "inc/cmdsys.plh" +const t_i32 = 4 // // Include zero page definitions // asm int32Inc !SOURCE "vmsrc/plvmzp.inc" -ACCUM32 = DSTH+1 +ACCUM32 = DSTH+1 +DVSIGN = TMP+3 end export asm zero32#0 LDA #$00 @@ -41,20 +43,20 @@ export asm neg32#0 end export asm load32(i32ptr)#0 LDA ESTKL+0,X ; I32PTR - STA SRCL + STA TMPL LDA ESTKH+0,X ; I32PTR - STA SRCL + STA TMPH LDY #$00 - LDA (SRC),Y + LDA (TMP),Y STA ACCUM32+0 INY - LDA (SRC),Y + LDA (TMP),Y STA ACCUM32+1 INY - LDA (SRC),Y + LDA (TMP),Y STA ACCUM32+2 INY - LDA (SRC),Y + LDA (TMP),Y STA ACCUM32+3 INX RTS @@ -64,53 +66,54 @@ export asm loadi16(imm16)#0 LDA ESTKL+0,X ; IMM16L STA ACCUM32+0 LDA ESTKH+0,X ; IMM16H + STA ACCUM32+1 BPL + ; SIGN EXTEND DEY -+ STA ACCUM32+1 - STY ACCUM32+2 ++ STY ACCUM32+2 STY ACCUM32+3 INX RTS end export asm store32(i32ptr)#0 LDA ESTKL+0,X ; I32PTR - STA DSTL + STA TMPL LDA ESTKH+0,X ; I32PTR - STA DSTL + STA TMPH LDY #$00 LDA ACCUM32+0 - STA (DST),Y + STA (TMP),Y INY LDA ACCUM32+1 - STA (DST),Y + STA (TMP),Y INY LDA ACCUM32+2 - STA (DST),Y + STA (TMP),Y INY LDA ACCUM32+3 - STA (DST),Y + STA (TMP),Y + INX RTS end export asm add32(i32ptr)#0 LDA ESTKL+0,X ; I32PTR - STA SRCL + STA TMPL LDA ESTKH+0,X ; I32PTR - STA SRCL + STA TMPH LDY #$00 - LDA (SRC),Y + LDA (TMP),Y CLC ADC ACCUM32+0 STA ACCUM32+0 INY - LDA (SRC),Y + LDA (TMP),Y ADC ACCUM32+1 STA ACCUM32+1 INY - LDA (SRC),Y + LDA (TMP),Y ADC ACCUM32+2 STA ACCUM32+2 INY - LDA (SRC),Y + LDA (TMP),Y ADC ACCUM32+3 STA ACCUM32+3 INX @@ -138,52 +141,45 @@ export asm addi16(imm16)#0 end export asm sub32(i32ptr)#0 LDA ESTKL+0,X ; I32PTR - STA SRCL + STA TMPL LDA ESTKH+0,X ; I32PTR - STA SRCL - LDY #$00 - LDA (SRC),Y - SEC - SBC ACCUM32+0 - STA ACCUM32+0 - INY - LDA (SRC),Y - SBC ACCUM32+1 - STA ACCUM32+1 - INY - LDA (SRC),Y - SBC ACCUM32+2 - STA ACCUM32+2 - INY - LDA (SRC),Y - SBC ACCUM32+3 - STA ACCUM32+3 - INX - RTS + STA TMPH + LDY #$03 +- LDA (TMP),Y + STA SRC,Y + DEY + BPL - + BMI _SUB end export asm subi16(imm16)#0 LDY #$00 LDA ESTKL+0,X ; IMM16L - SEC - SBC ACCUM32+0 - STA ACCUM32+0 + STA SRC+0 LDA ESTKH+0,X ; IMM16H - BPL + + STA SRC+1 + BPL + ; SIGN EXTEND DEY -+ SBC ACCUM32+1 ++ STY SRC+2 + STY SRC+3 +_SUB LDA ACCUM32+0 + SEC + SBC SRC+0 + STA ACCUM32+0 + LDA ACCUM32+1 + SBC SRC+1 STA ACCUM32+1 - TYA - SBC ACCUM32+2 + LDA ACCUM32+2 + SBC SRC+2 STA ACCUM32+2 - TYA - SBC ACCUM32+3 + LDA ACCUM32+3 + SBC SRC+3 STA ACCUM32+3 INX RTS end export asm shl32(imm8)#0 LDA ESTKL+0,X ; IMM8 - AND #$01F + AND #$1F CMP #16 BCC + LDY ACCUM32+1 @@ -218,7 +214,7 @@ export asm shl32(imm8)#0 end export asm shr32(imm8)#0 LDA ESTKL+0,X ; IMM8 - AND #$01F + AND #$1F BEQ + TAY LDA #$80 @@ -343,7 +339,7 @@ export asm divi16(imm16)#2 + STA SRC+1 LDA ESTKL+0,X ; IMM16L STA SRC+0 -_DIV STY DIVSGN ; LSB = SIGN OF DVSR +_DIV STY DVSIGN ; LSB = SIGN OF DVSR DEX ; REMNDR = ESTK..ESTK+1 LDY #$00 STY ESTKL+0,X @@ -369,8 +365,8 @@ _DIV STY DIVSGN ; LSB = SIGN OF DVSR BPL + LDA #$81 ; DVDND IS NEG CLC - ADC DIVSGN - STA DIVSGN + ADC DVSIGN + STA DVSIGN TYA SEC SBC ACCUM32+0 @@ -407,7 +403,7 @@ _DIV STY DIVSGN ; LSB = SIGN OF DVSR STA ESTKH+1,X LDA ESTKL+0,X ; REMNDR SBC SRC+0 ; DVSR - STA ESTKL+0 ; SUBTRACT + STA ESTKL+0,X ; SUBTRACT LDA ESTKH+0,X SBC SRC+1 STA ESTKH+0,X @@ -421,7 +417,7 @@ _DIV STY DIVSGN ; LSB = SIGN OF DVSR ROL ACCUM32+3 DEY BNE - - LDA DIVSGN + LDA DVSIGN ; SET SIGNS OF RESULTS BPL + TYA SEC @@ -436,11 +432,10 @@ _DIV STY DIVSGN ; LSB = SIGN OF DVSR TYA SBC ESTKH+1,X STA ESTKH+1,X - LDA DIVSGN + LDA DVSIGN + LSR BCC + TYA - SEC SBC ACCUM32+0 STA ACCUM32+0 TYA @@ -454,7 +449,6 @@ _DIV STY DIVSGN ; LSB = SIGN OF DVSR STA ACCUM32+3 + RTS end - export asm iseq32(i32ptr)#1 LDA ESTKL+0,X ; I32PTR STA TMPL @@ -535,7 +529,7 @@ _ISGE LDA ACCUM32+0 + STY ESTKL+0,X STY ESTKH+0,X RTS -done +end export asm isle32(i32ptr)#1 LDA ESTKL+0,X ; I32PTR STA TMPL @@ -575,32 +569,93 @@ _ISLE LDA SRC+0 + STY ESTKL+0,X STY ESTKH+0,X RTS -done -ISGT LDA ESTKL,X - CMP ESTKL+1,X - LDA ESTKH,X - SBC ESTKH+1,X - BVS + - BMI ISTRU - BPL ISFLS -+ -- BMI ISFLS - BPL ISTRU -ISLT LDA ESTKL+1,X - CMP ESTKL,X - LDA ESTKH+1,X - SBC ESTKH,X - BVS - - BMI ISTRU - BPL ISFLS -done -def puti32(i32ptr)#0 +end +export asm isgt32(i32ptr)#1 + LDA ESTKL+0,X ; I32PTR + STA TMPL + LDA ESTKH+0,X ; I32PTR + STA TMPH + LDY #$03 +- LDA (TMP),Y + STA SRC,Y + DEY + BPL - + INY + BEQ _ISGT +end +export asm isgti16(imm16)#1 + LDY #$00 + LDA ESTKL+0,X ; IMM16L + STA SRC+0 + LDA ESTKH+0,X ; IMM16H + STA SRC+1 + BPL + ; SIGN EXTEND + DEY ++ STY SRC+2 + STY SRC+3 + LDY #$00 +_ISGT LDA SRC+0 + CMP ACCUM32+0 + LDA SRC+1 + SBC ACCUM32+1 + LDA SRC+2 + SBC ACCUM32+2 + LDA SRC+3 + SBC ACCUM32+3 + BVC + + EOR #$80 ++ BPL + + DEY ++ STY ESTKL+0,X + STY ESTKH+0,X + RTS +end +export asm islt32(i32ptr)#1 + LDA ESTKL+0,X ; I32PTR + STA TMPL + LDA ESTKH+0,X ; I32PTR + STA TMPH + LDY #$03 +- LDA (TMP),Y + STA SRC,Y + DEY + BPL - + INY + BEQ _ISLT +end +export asm islti16(imm16)#1 + LDY #$00 + LDA ESTKL+0,X ; IMM16L + STA SRC+0 + LDA ESTKH+0,X ; IMM16H + STA SRC+1 + BPL + ; SIGN EXTEND + DEY ++ STY SRC+2 + STY SRC+3 + LDY #$00 +_ISLT LDA ACCUM32+0 + CMP SRC+0 + LDA ACCUM32+1 + SBC SRC+1 + LDA ACCUM32+2 + SBC SRC+2 + LDA ACCUM32+3 + SBC SRC+3 + BVC + + EOR #$80 ++ BPL + + DEY ++ STY ESTKL+0,X + STY ESTKH+0,X + RTS +end +export def i32tos(i32ptr, strptr)#1 res[t_i32] save - var iptr, rem + word iptr, rem char[12] istr iptr = @istr.11 - store32(@save) load32(i32ptr) if i32ptr->3 & $80 @@ -608,11 +663,20 @@ def puti32(i32ptr)#0 putc('-') fin repeat - rem = divi16(10) + drop, rem = divi16(10) // Only care about LSW of remainder ^iptr = rem + '0' iptr-- - until isgti16(0) + until iseqi16(0) ^iptr = @istr.11 - iptr - puts(iptr) + strcpy(strptr, iptr) load32(@save) + return strptr +end +export def puti32(i32ptr)#0 + char[12] i32str + + puts(i32tos(i32ptr, @i32str)) +end + done + diff --git a/src/makefile b/src/makefile index fb51ed1..b0eedb6 100755 --- a/src/makefile +++ b/src/makefile @@ -36,6 +36,8 @@ FATWDSK = rel/apple/FATWRITEDSK\#FE1000 FATRDSK = rel/apple/FATREADDSK\#FE1000 FILEIO_APL = rel/apple/FILEIO\#FE1000 CONIO_APL = rel/apple/CONIO\#FE1000 +INT32 = rel/INT32\#FE1000 +INT32TEST = rel/INT32TEST\#FE1000 SANE = rel/SANE\#FE1000 FPSTR = rel/FPSTR\#FE1000 FPU = rel/FPU\#FE1000 @@ -96,7 +98,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -265,6 +267,14 @@ $(PRIMEGAP): samplesrc/primegap.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMW < samplesrc/primegap.pla > samplesrc/primegap.a acme --setpc 4094 -o $(PRIMEGAP) samplesrc/primegap.a +$(INT32): libsrc/int32.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < libsrc/int32.pla > libsrc/int32.a + acme --setpc 4094 -o $(INT32) libsrc/int32.a + +$(INT32TEST): samplesrc/int32test.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < samplesrc/int32test.pla > samplesrc/int32test.a + acme --setpc 4094 -o $(INT32TEST) samplesrc/int32test.a + $(SANE): libsrc/sane.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/sane.pla > libsrc/sane.a acme --setpc 4094 -o $(SANE) libsrc/sane.a diff --git a/src/mkrel b/src/mkrel index a664252..ba042fe 100755 --- a/src/mkrel +++ b/src/mkrel @@ -37,6 +37,7 @@ cp rel/apple/JIT16#FE1000 prodos/sys/JIT16.REL cp rel/apple/JITUNE#FE1000 prodos/sys/JITUNE.REL cp rel/LZ4#FE1000 prodos/sys/LZ4.REL cp rel/TFTPD#FE1000 prodos/sys/TFTPD.REL +cp rel/INT32#FE1000 prodos/sys/INT32.REL cp rel/FPSTR#FE1000 prodos/sys/FPSTR.REL cp rel/FPU#FE1000 prodos/sys/FPU.REL cp rel/SANE#FE1000 prodos/sys/SANE.REL @@ -61,6 +62,7 @@ cp ../sysfiles/ELEMS.CODE#060000 prodos/fpsos/sys/ELEMS.CODE.BIN rm -rf prodos/demos mkdir prodos/demos +cp rel/INT32TEST#FE1000 prodos/demos/INT32TEST.REL cp rel/apple/GRTEST#FE1000 prodos/demos/GRTEST.REL cp rel/apple/DGRTEST#FE1000 prodos/demos/DGRTEST.REL cp rel/apple/HGRTEST#FE1000 prodos/demos/HGRTEST.REL @@ -105,6 +107,7 @@ cp rel/CODEOPT#FE1000 prodos/bld/CODEOPT.REL mkdir prodos/bld/samples cp samplesrc/hello.pla prodos/bld/samples/HELLO.PLA.TXT +cp samplesrc/int32test.pla prodos/bld/samples/INT32TEST.PLA.TXT cp samplesrc/grtest.pla prodos/bld/samples/GRTEST.PLA.TXT cp samplesrc/dgrtest.pla prodos/bld/samples/DGRTEST.PLA.TXT cp samplesrc/hgrtest.pla prodos/bld/samples/HGRTEST.PLA.TXT @@ -149,6 +152,7 @@ cp inc/grlib.plh prodos/bld/inc/GRLIB.PLH.TXT cp inc/dgrlib.plh prodos/bld/inc/DGRLIB.PLH.TXT cp inc/fiber.plh prodos/bld/inc/FIBER.PLH.TXT cp inc/fileio.plh prodos/bld/inc/FILEIO.PLH.TXT +cp inc/int32.plh prodos/bld/inc/INT32.PLH.TXT cp inc/fpstr.plh prodos/bld/inc/FPSTR.PLH.TXT cp inc/fpu.plh prodos/bld/inc/FPU.PLH.TXT cp inc/mouse.plh prodos/bld/inc/MOUSE.PLH.TXT diff --git a/src/samplesrc/int32test.pla b/src/samplesrc/int32test.pla new file mode 100644 index 0000000..c9c3946 --- /dev/null +++ b/src/samplesrc/int32test.pla @@ -0,0 +1,72 @@ +include "inc/cmdsys.plh" +include "inc/int32.plh" + +def testi32#0 + word il, ih + res[t_i32] i32 + + ih = 0 + for il = 0 to 10 + load32(@il) + muli16(10) + divi16(2) + store32(@i32) + puti32(@i32); putln + next + muli16(-30000) + store32(@i32) + puti32(@i32); putln + loadi16(100) + if islti16(50) + puts("100 < 50\n") + fin + if islti16(500) + puts("100 < 500\n") + fin + if isgti16(50) + puts("100 > 50\n") + fin + if isgti16(500) + puts("100 > 500\n") + fin + if islei16(50) + puts("100 <= 50\n") + fin + if islei16(500) + puts("100 <= 500\n") + fin + if isgei16(50) + puts("100 >= 50\n") + fin + if isgei16(500) + puts("100 >= 500\n") + fin + + if islti16(100) + puts("100 < 100\n") + fin + if islti16(100) + puts("100 < 100\n") + fin + if isgti16(100) + puts("100 > 100\n") + fin + if isgti16(100) + puts("100 > 100\n") + fin + if islei16(100) + puts("100 <= 100\n") + fin + if islei16(100) + puts("100 <= 100\n") + fin + if isgei16(100) + puts("100 >= 100\n") + fin + if isgei16(100) + puts("100 >= 100\n") + fin +end + +testi32 +done diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index 4e8d15d..d4348a8 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -351,22 +351,26 @@ end def strupper(strptr)#0 byte i, chr - for i = ^strptr downto 1 - chr = (strptr).[i] - if chr & $E0 == $E0 - (strptr).[i] = chr - $E0 - fin - next + if ^strptr + for i = ^strptr downto 1 + chr = (strptr).[i] + if chr & $E0 == $E0 + (strptr).[i] = chr - $E0 + fin + next + fin end def strlower(strptr)#0 byte i, chr - for i = ^strptr downto 1 - chr = (strptr).[i] - if chr & $E0 == $00 - (strptr).[i] = chr + $E0 - fin - next + if ^strptr + for i = ^strptr downto 1 + chr = (strptr).[i] + if chr & $E0 == $00 + (strptr).[i] = chr + $E0 + fin + next + fin end def txtupper#0 word i, strptr diff --git a/src/utilsrc/apple/cat.pla b/src/utilsrc/apple/cat.pla index 3c01efe..e5467ea 100644 --- a/src/utilsrc/apple/cat.pla +++ b/src/utilsrc/apple/cat.pla @@ -1,24 +1,61 @@ include "inc/cmdsys.plh" include "inc/args.plh" include "inc/fileio.plh" +include "inc/int32.plh" var arg, refnum, dirbuf var page, firstblk, entrylen, entriesblk, i, entry, filecnt - -char[64] path +char[64] path, filename res[t_fileinfo] fileinfo +res[t_fileentry] fileentry +// +// Convert byte to two hex chars +// +def putb(b)#0 + char h + + h = ((b >> 4) & $0F) + '0' + if h > '9' + h = h + 7 + fin + putc(h) + h = (b & $0F) + '0' + if h > '9' + h = h + 7 + fin + putc(h) +end +def strupper(strptr)#0 + byte i, chr + + if ^strptr + for i = 1 to ^strptr + chr = strptr->[i] + if chr >= 'a' and chr <= 'z' + strptr->[i] = chr - 'a' + 'A' + fin + next + fin +end +def filefrompath(filestr, pathstr)#0 + byte i + + for i = ^pathstr downto 1 + if pathstr->[i] == '/' + break + fin + next + ^filestr = ^pathstr - i + memcpy(filestr + 1, pathstr + 1 + i, ^filestr) +end // // Print out a directory entry // -def printentry()#0 - byte type, len +def printentry(entryptr)#0 + char type, pad, eofstr[12] - type = ^entry - len = type & $0F - ^entry = len - puts(entry) - type = ' ' - when entry->$10 + puts(entryptr) + when entryptr->entry_type is $0F // Is it a directory? type = '/' break @@ -27,12 +64,22 @@ def printentry()#0 break is $FE // REL file type = '+' + break + otherwise + type = ' ' wend putc(type) - for len = 16 - len downto 0 + for pad = ^entryptr to 14 putc(' ') next - putc('$'); puth(entry->$10) + putc('$'); putb(entryptr->entry_type) + puts(" $"); puth(entryptr=>entry_aux) + entryptr->entry_EOFH.1 = 0 + i32tos(entryptr+entry_EOFL, @eofstr) + for pad = eofstr to 9 + putc(' ') + next + puts(@eofstr) putln end // @@ -41,51 +88,83 @@ end arg = argNext(argFirst) if ^arg strcpy(@path, arg) + strupper(@path) else fileio:getpfx(@path) fin -refnum = fileio:open(@path) -if refnum - page = 0 - filecnt = 0 - firstblk = 1 - dirbuf = heapallocalign(512, 8, 0) - repeat - if fileio:read(refnum, dirbuf, 512) == 512 - // - // Skip block pointers - // - entry = dirbuf + 4 - if firstblk - // - // Pull out revelant details from the first block - // - entrylen = dirbuf->$23 - entriesblk = dirbuf->$24 - filecnt = dirbuf=>$25 - entry = entry + entrylen - fin - for i = firstblk to entriesblk - // - // Print directory entry details - // - if ^entry - printentry() - filecnt-- - // - // Pause display every screenfull - // - page++ - if page == 23 - getc - page = 0 - fin - fin - entry = entry + entrylen - next - firstblk = 0 +// +// Check if file exists +// +if fileio:getfileinfo(@path, @fileinfo) == FILE_ERR_OK + puts("=NAME==========TYPE===AUX====LENGTH=\n") + // + // Check if cataloging a directory + // + if fileinfo.file_type == $0F + fileio:iobufalloc(2) // Reserve two I/O buffers + if path[path] <> '/' // Make sure path ends with a '/' + path++ + path[path] = '/' fin - until filecnt == 0 + page = 21 + filecnt = 0 + firstblk = 1 + dirbuf = heapallocalign(512, 8, 0) + refnum = fileio:open(@path) + repeat + if fileio:read(refnum, dirbuf, 512) == 512 + // + // Skip block pointers + // + entry = dirbuf + 4 + if firstblk + // + // Pull out revelant details from the first block + // + entrylen = dirbuf->$23 + entriesblk = dirbuf->$24 + filecnt = dirbuf=>$25 + entry = entry + entrylen + fin + for i = firstblk to entriesblk + // + // Print directory entry details + // + ^entry = ^entry & $0F + if ^entry + printentry(entry) + filecnt-- + // + // Pause display every screenfull + // + if not page + getc + page = 22 + else + page-- + fin + fin + entry = entry + entrylen + next + firstblk = 0 + fin + until filecnt == 0 + else + // + // Create file entry from file info + // + filefrompath(@fileentry, @path) + fileentry.entry_access = fileinfo.file_access + fileentry.entry_type = fileinfo.file_type + fileentry:entry_create:0 = fileinfo:create_date + fileentry:entry_create:2 = fileinfo:create_time + fileentry:entry_aux = fileinfo:aux_type + fileentry:entry_mod:0 = fileinfo:mod_date + fileentry:entry_mod:2 = fileinfo:mod_time + refnum = fileio:open(@path) + fileentry:entry_EOFL, fileentry.entry_EOFH = fileio:geteof(refnum)#2 + printentry(@fileentry) + fin fileio:close(0) else puts("Unable to open: "); puts(@path); putln diff --git a/src/vmsrc/apple/cmd.pla b/src/vmsrc/apple/cmd.pla index 29c638d..af1df5a 100755 --- a/src/vmsrc/apple/cmd.pla +++ b/src/vmsrc/apple/cmd.pla @@ -1192,10 +1192,8 @@ def catalog(path)#0 entry = entry + entrylen fin for i = firstblk to entriesblk - type = ^entry - if type - len = type & $0F - ^entry = len + if ^entry + ^entry = ^entry & $0F prstr(entry) type = ' ' when entry->$10 @@ -1209,7 +1207,7 @@ def catalog(path)#0 type = '+' wend cout(type) - for len = 18 - len downto 0 + for len = ^entry to 18 cout(' ') next filecnt-- diff --git a/src/vmsrc/apple/cmdjit.pla b/src/vmsrc/apple/cmdjit.pla index 39a54eb..0aeba58 100755 --- a/src/vmsrc/apple/cmdjit.pla +++ b/src/vmsrc/apple/cmdjit.pla @@ -1257,10 +1257,8 @@ def catalog(path)#0 entry = entry + entrylen fin for i = firstblk to entriesblk - type = ^entry - if type - len = type & $0F - ^entry = len + if ^entry + ^entry = ^entry & $0F prstr(entry) type = ' ' when entry->$10 @@ -1274,7 +1272,7 @@ def catalog(path)#0 type = '+' wend cout(type) - for len = 18 - len downto 0 + for len = ^entry to 18 cout(' ') next filecnt-- diff --git a/src/vmsrc/apple/soscmd.pla b/src/vmsrc/apple/soscmd.pla index 694fd90..eef4d83 100755 --- a/src/vmsrc/apple/soscmd.pla +++ b/src/vmsrc/apple/soscmd.pla @@ -176,10 +176,8 @@ def catalog(path)#0 entry = entry + entrylen fin for i = firstblk to entriesblk - type = ^entry - if type - len = type & $0F - ^entry = len + if ^entry + ^entry = ^entry & $0F puts(entry) type = ' ' when entry->$10 @@ -193,7 +191,7 @@ def catalog(path)#0 type = '+' wend putc(type) - for len = 18 - len downto 0 + for len = ^entry to 18 putc(' ') next filecnt-- From 7ba288d2d69c150f42c9a9adf205535726fc511f Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Tue, 24 Dec 2019 15:58:19 -0800 Subject: [PATCH 073/149] HGR lib WIP --- src/inc/hgrlib.plh | 17 +++ src/libsrc/apple/dgrlib.pla | 44 +++--- src/libsrc/apple/grlib.pla | 44 +++--- src/libsrc/apple/hgrlib.pla | 284 +++++++++++++++++++++++++++++++++++ src/makefile | 12 +- src/mkrel | 3 + src/samplesrc/hgrtest.pla | 289 ++++-------------------------------- src/tftpbld | 6 +- src/tftpdemos | 2 + src/tftpsys | 2 + 10 files changed, 398 insertions(+), 305 deletions(-) create mode 100644 src/inc/hgrlib.plh create mode 100644 src/libsrc/apple/hgrlib.pla diff --git a/src/inc/hgrlib.plh b/src/inc/hgrlib.plh new file mode 100644 index 0000000..90560ec --- /dev/null +++ b/src/inc/hgrlib.plh @@ -0,0 +1,17 @@ +import hgrlib + predef hgrPlot(x, y)#0 + predef hgrXorPlot(x, y)#0 + predef hgrHLin(x1, x2, y)#0 + predef hgrVLin(y1, y2, x)#0 + predef hgrBLT(x, y, width, height, srcptr)#0 + predef hgrCopySrc(ofst, y, w, h, srcptr)#0 + predef hgrAndSrc(ofst, y, w, h, srcptr)#0 + predef hgrXorSrc(ofst, y, w, h, srcptr)#0 + predef hgrCopyDst(ofst, y, w, h, dstptr)#0 + predef hgrMode#1 + predef txtMode#0 + predef hgrShow(page)#1 + predef hgrSwap#0 + predef hgrDrawBuf(page)#0 + predef hgrColor(clr)#0 +end diff --git a/src/libsrc/apple/dgrlib.pla b/src/libsrc/apple/dgrlib.pla index d270319..0eccee4 100755 --- a/src/libsrc/apple/dgrlib.pla +++ b/src/libsrc/apple/dgrlib.pla @@ -23,14 +23,14 @@ const page2 = 1 // // Screen row address arrays. // -word[] dgr1rows = $0400,$0480,$0500,$0580,$0600,$0680,$0700,$0780 -word = $0428,$04A8,$0528,$05A8,$0628,$06A8,$0728,$07A8 -word = $0450,$04D0,$0550,$05D0,$0650,$06D0,$0750,$07D0 -word[] dgr2rows = $0800,$0880,$0900,$0980,$0A00,$0A80,$0B00,$0B80 -word = $0828,$08A8,$0928,$09A8,$0A28,$0AA8,$0B28,$0BA8 -word = $0850,$08D0,$0950,$09D0,$0A50,$0AD0,$0B50,$0BD0 -word[] dgrbuff = @dgr1rows, @dgr2rows -word drawbufptr +word[] dgr1row = $0400,$0480,$0500,$0580,$0600,$0680,$0700,$0780 +word = $0428,$04A8,$0528,$05A8,$0628,$06A8,$0728,$07A8 +word = $0450,$04D0,$0550,$05D0,$0650,$06D0,$0750,$07D0 +word[] dgr2row = $0800,$0880,$0900,$0980,$0A00,$0A80,$0B00,$0B80 +word = $0828,$08A8,$0928,$09A8,$0A28,$0AA8,$0B28,$0BA8 +word = $0850,$08D0,$0950,$09D0,$0A50,$0AD0,$0B50,$0BD0 +word[] dgrbuff = @dgr1row, @dgr2row +word drawbuff byte drawpage // // Color mapping. @@ -525,7 +525,7 @@ export def dgrMode#1 ^show80 = 0 ^an3on drawpage = 1 - drawbufptr = dgrbuff[1] + drawbuff = dgrbuff[1] return 1 end // @@ -551,11 +551,11 @@ end export def dgrSwap#0 ^(showpage1 + drawpage) drawpage = drawpage ^ 1 - drawbufptr = dgrbuff[drawpage] + drawbuff = dgrbuff[drawpage] end export def dgrDrawBuf(page)#0 drawpage = page - drawbufptr = dgrbuff[drawpage] + drawbuff = dgrbuff[drawpage] end // // Set color for clear & plot routines @@ -586,18 +586,18 @@ _dgrSetEvnOdd:1 = @oddclr _dgrSetOddEvn:1 = @evnclr _dgrSetOddOdd:1 = @oddclr // -// Fixups for drawbufptr +// Fixups for drawbuff // -dgrPlot:1 = @drawbufptr -dgrPlot:6 = @drawbufptr+1 -dgrHLin:1 = @drawbufptr -dgrHLin:6 = @drawbufptr+1 -dgrVLin:1 = @drawbufptr -dgrVLin:6 = @drawbufptr+1 -dgrBLT:1 = @drawbufptr -dgrBLT:6 = @drawbufptr+1 -dgrTile:1 = @drawbufptr -dgrTile:6 = @drawbufptr+1 +dgrPlot:1 = @drawbuff +dgrPlot:6 = @drawbuff+1 +dgrHLin:1 = @drawbuff +dgrHLin:6 = @drawbuff+1 +dgrVLin:1 = @drawbuff +dgrVLin:6 = @drawbuff+1 +dgrBLT:1 = @drawbuff +dgrBLT:6 = @drawbuff+1 +dgrTile:1 = @drawbuff +dgrTile:6 = @drawbuff+1 // Put read AUX mem routine in scary location memcpy($0100, @auxRead, 9) done diff --git a/src/libsrc/apple/grlib.pla b/src/libsrc/apple/grlib.pla index ae931d9..1fc95dc 100644 --- a/src/libsrc/apple/grlib.pla +++ b/src/libsrc/apple/grlib.pla @@ -23,14 +23,14 @@ const page2 = 1 // // Screen row address arrays. // -word[] gr1rows = $0400,$0480,$0500,$0580,$0600,$0680,$0700,$0780 -word = $0428,$04A8,$0528,$05A8,$0628,$06A8,$0728,$07A8 -word = $0450,$04D0,$0550,$05D0,$0650,$06D0,$0750,$07D0 -word[] gr2rows = $0800,$0880,$0900,$0980,$0A00,$0A80,$0B00,$0B80 -word = $0828,$08A8,$0928,$09A8,$0A28,$0AA8,$0B28,$0BA8 -word = $0850,$08D0,$0950,$09D0,$0A50,$0AD0,$0B50,$0BD0 -word[] grbuff = @gr1rows, @gr2rows -word drawbufptr +word[] gr1row = $0400,$0480,$0500,$0580,$0600,$0680,$0700,$0780 +word = $0428,$04A8,$0528,$05A8,$0628,$06A8,$0728,$07A8 +word = $0450,$04D0,$0550,$05D0,$0650,$06D0,$0750,$07D0 +word[] gr2row = $0800,$0880,$0900,$0980,$0A00,$0A80,$0B00,$0B80 +word = $0828,$08A8,$0928,$09A8,$0A28,$0AA8,$0B28,$0BA8 +word = $0850,$08D0,$0950,$09D0,$0A50,$0AD0,$0B50,$0BD0 +word[] grbuff = @gr1row, @gr2row +word drawbuff byte drawpage asm grInc(buff) @@ -430,7 +430,7 @@ export def grMode#1 ^mapmain = 0 ^an3off drawpage = 1 - drawbufptr = grbuff[1] + drawbuff = grbuff[1] return 1 end // @@ -456,11 +456,11 @@ end export def grSwap#0 ^(showpage1 + drawpage) drawpage = drawpage ^ 1 - drawbufptr = grbuff[drawpage] + drawbuff = grbuff[drawpage] end export def grDrawBuf(page)#0 drawpage = page - drawbufptr = grbuff[drawpage] + drawbuff = grbuff[drawpage] end // // Set color for clear & plot routines @@ -474,16 +474,16 @@ end _grTileTile:1 = @grTile _grFillTile:1 = @grTile // -// Fixups for drawbufptr +// Fixups for drawbuff // -grPlot:1 = @drawbufptr -grPlot:6 = @drawbufptr+1 -grHLin:1 = @drawbufptr -grHLin:6 = @drawbufptr+1 -grVLin:1 = @drawbufptr -grVLin:6 = @drawbufptr+1 -grBLT:1 = @drawbufptr -grBLT:6 = @drawbufptr+1 -grTile:1 = @drawbufptr -grTile:6 = @drawbufptr+1 +grPlot:1 = @drawbuff +grPlot:6 = @drawbuff+1 +grHLin:1 = @drawbuff +grHLin:6 = @drawbuff+1 +grVLin:1 = @drawbuff +grVLin:6 = @drawbuff+1 +grBLT:1 = @drawbuff +grBLT:6 = @drawbuff+1 +grTile:1 = @drawbuff +grTile:6 = @drawbuff+1 done diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla new file mode 100644 index 0000000..e434904 --- /dev/null +++ b/src/libsrc/apple/hgrlib.pla @@ -0,0 +1,284 @@ +include "inc/cmdsys.plh" +// +// Hardware addresses +// +const showgraphics = $C050 +const showtext = $C051 +const showfull = $C052 +const showmix = $C053 +const showpage1 = $C054 +const showpage2 = $C055 +const showlores = $C056 +const showhires = $C057 +const keyboard = $C000 +const keystrobe = $C010 +const hgr1 = $2000 +const hgr2 = $4000 +const page1 = 0 +const page2 = 1 +word hgrbuff[] = hgr1, hgr2 +word hgrscan[] = $0000,$0400,$0800,$0C00,$1000,$1400,$1800,$1C00 +word = $0080,$0480,$0880,$0C80,$1080,$1480,$1880,$1C80 +word = $0100,$0500,$0900,$0D00,$1100,$1500,$1900,$1D00 +word = $0180,$0580,$0980,$0D80,$1180,$1580,$1980,$1D80 +word = $0200,$0600,$0A00,$0E00,$1200,$1600,$1A00,$1E00 +word = $0280,$0680,$0A80,$0E80,$1280,$1680,$1A80,$1E80 +word = $0300,$0700,$0B00,$0F00,$1300,$1700,$1B00,$1F00 +word = $0380,$0780,$0B80,$0F80,$1380,$1780,$1B80,$1F80 +word = $0028,$0428,$0828,$0C28,$1028,$1428,$1828,$1C28 +word = $00A8,$04A8,$08A8,$0CA8,$10A8,$14A8,$18A8,$1CA8 +word = $0128,$0528,$0928,$0D28,$1128,$1528,$1928,$1D28 +word = $01A8,$05A8,$09A8,$0DA8,$11A8,$15A8,$19A8,$1DA8 +word = $0228,$0628,$0A28,$0E28,$1228,$1628,$1A28,$1E28 +word = $02A8,$06A8,$0AA8,$0EA8,$12A8,$16A8,$1AA8,$1EA8 +word = $0328,$0728,$0B28,$0F28,$1328,$1728,$1B28,$1F28 +word = $03A8,$07A8,$0BA8,$0FA8,$13A8,$17A8,$1BA8,$1FA8 +word = $0050,$0450,$0850,$0C50,$1050,$1450,$1850,$1C50 +word = $00D0,$04D0,$08D0,$0CD0,$10D0,$14D0,$18D0,$1CD0 +word = $0150,$0550,$0950,$0D50,$1150,$1550,$1950,$1D50 +word = $01D0,$05D0,$09D0,$0DD0,$11D0,$15D0,$19D0,$1DD0 +word = $0250,$0650,$0A50,$0E50,$1250,$1650,$1A50,$1E50 +word = $02D0,$06D0,$0AD0,$0ED0,$12D0,$16D0,$1AD0,$1ED0 +word = $0350,$0750,$0B50,$0F50,$1350,$1750,$1B50,$1F50 +word = $03D0,$07D0,$0BD0,$0FD0,$13D0,$17D0,$1BD0,$1FD0 +word hcolor[] = $0000,$552A,$2A55,$7F7F,$8080,$D5AA,$AAD5,$FFFF +word hmask = $8081,$8082,$8084,$8088,$8090,$80A0,$80C0 +word = $8180,$8280,$8480,$8880,$9080,$A080,$C080 +byte hbmask = $81,$82,$84,$88,$90,$A0,$C0 +byte hlmask = $FF,$FE,$FC,$F8,$F0,$E0,$C0 +byte hrmask = $81,$83,$87,$8F,$9F,$BF,$FF +word curhclr +byte drawpage = 1 +word drawbuff = hgr2 + +byte ball = $88, $8F, $FF, $F8, $88 +byte = $88, $FF, $FF, $FF, $88 +byte = $8F, $FF, $FF, $FF, $F8 +byte = $FF, $FF, $FF, $FF, $FF +byte = $FF, $FF, $FF, $FF, $FF +byte = $FF, $FF, $FF, $FF, $FF +byte = $FF, $FF, $FF, $FF, $FF +byte = $8F, $FF, $FF, $FF, $F8 +byte = $88, $FF, $FF, $FF, $88 +byte = $88, $8F, $FF, $F8, $88 + +asm grInc(buff) +!SOURCE "vmsrc/plvmzp.inc" +GBASL = $26 +GBASH = $27 +GBASE = GBASL +GCLR = $30 +end + +asm divmod7(x)#2 + LDA ESTKL,X ; X COORD LSB + LDY ESTKH,X ; X COORD MSB + BNE + ; MUST BE >= 140 + CMP #140 + BCC ++ ++ SEC + SBC #140 + LDY #20 +++ CMP #70 + BCC + + SBC #70 + STA ESTKL,X + TYA + ADC #9 + TAY + LDA ESTKL,X ++ CMP #35 + BCC + + SBC #35 + STA ESTKL,X + TYA + ADC #4 + TAY + LDA ESTKL,X ++ +- CMP #7 + BCC + + SBC #7 + INY + BNE - ++ DEX + STA ESTKL,X ; REMAINDER + STY ESTKL+1,X ; QUOTIENT + LDA #$00 + STA ESTKH,X + STA ESTKH+1,X + RTS +end +export def hgrColor(c)#0 + curhclr = hcolor[c & $07] +end +export def hgrPlot(x, y)#0 + word pixptr + byte ofst, pixofst, pmask + + ofst, pixofst = divmod7(x) + pixptr = hgrscan[y] + drawbuff + ofst + pmask = hbmask[pixofst] + ^pixptr = (^pixptr & ~pmask) | (curhclr.[ofst & 1] & pmask) +end +export def hgrXorPlot(x, y)#0 + word pixptr + byte ofst, pixofst, pmask + + ofst, pixofst = divmod7(x) + pixptr = hgrscan[y] + drawbuff + ofst + pmask = hbmask[pixofst] + ^pixptr = ^pixptr ^ (curhclr.[ofst & 1] & pmask) +end +export def hgrHlin(x1, x2, y)#0 + word pixptr, x + byte lofst, lpixofst, lpmask, clr + byte rofst, rpixofst, rpmask + + if x1 == x2 + hgrPlot(x1, y) + else + lofst, lpixofst = divmod7(x1) + pixptr = hgrscan[y] + drawbuff + lofst + rofst, rpixofst = divmod7(x2) + lpmask = hlmask[lpixofst] + rpmask = hrmask[rpixofst] + if lofst == rofst + lpmask = lpmask & rpmask + ^pixptr = (^pixptr & ~lpmask) | (curhclr.[pixptr.0 & 1] & lpmask) + else + ^pixptr = (^pixptr & ~lpmask) | (curhclr.[pixptr.0 & 1] & lpmask) + pixptr++ + for x = lofst + 1 to rofst - 1 + ^pixptr = curhclr.[pixptr.0 & 1] + pixptr++ + next + ^pixptr = (^pixptr & ~rpmask) | (curhclr.[pixptr.0 & 1] & rpmask) + fin + fin +end +export def hgrVlin(y1, y2, x)#0 + word pixptr, y, ofst + byte pixofst, pmask, cmask + + if y1 == y2 + hgrPlot(x, y1) + else + ofst, pixofst = divmod7(x) + ofst = ofst + drawbuff + pmask = hbmask[pixofst] + cmask = curhclr.[ofst & 1] & pmask + pmask = ~pmask + for y = y1 to y2 + pixptr = hgrscan[y] + ofst + ^pixptr = (^pixptr & pmask) | cmask + next + fin +end +export def hgrCopySrc(ofst, y, w, h, srcptr)#0 + word j, dstptr + + ofst = ofst + drawbuff + for j = y to y + h - 1 + dstptr = hgrscan[j] + ofst + memcpy(dstptr, srcptr, w) + srcptr = srcptr + w + next +end +export def hgrAndSrc(ofst, y, w, h, srcptr)#0 + word j, dstptr + byte i + + ofst = ofst + drawbuff + for j = y to y + h - 1 + dstptr = hgrscan[j] + ofst + for i = 0 to w - 1 + dstptr->[i] = dstptr->[i] & srcptr->[i] + next + srcptr = srcptr + w + next +end +export def hgrXorSrc(ofst, y, w, h, srcptr)#0 + word j, dstptr + byte i + + ofst = ofst + drawbuff + for j = y to y + h - 1 + dstptr = hgrscan[j] + ofst + for i = 0 to w - 1 + dstptr->[i] = dstptr->[i] ^ srcptr->[i] + next + srcptr = srcptr + w + next +end +export def hgrCopyDst(ofst, y, w, h, dstptr)#0 + word j, srcptr + + ofst = ofst + drawbuff + for j = y to y + h - 1 + srcptr = hgrscan[j] + ofst + memcpy(dstptr, srcptr, w) + dstptr = dstptr + w + next +end +export def hgrBLT(x, y, w, h, srcptr)#0 + word i, j + word saveclr + byte c + + saveclr = curhclr + for j = y to y + h - 1 + for i = 0 to w - 1 + c = srcptr->[i >> 1] + if i & 1 + curhclr = hcolor[(c >> 4) & $07] + if c & $80 + hgrXorPlot(x + i, j) + else + hgrPlot(x + i, j) + fin + else + curhclr = hcolor[c & $07] + if c & $08 + hgrXorPlot(x + i, j) + else + hgrPlot(x + i, j) + fin + fin + next + srcptr = srcptr + (w + 1) / 2 + next + curhclr = saveclr +end +export def hgrMode#1 + memset(hgr1, 0, $2000) // Clear HGR page 1 + ^showpage1 + ^showfull + ^showhires + ^showgraphics + drawpage = 1 + drawbuff = hgrbuff[1] + return 1 +end +export def txtMode#0 + ^showpage1 + ^showtext +end +// +// Set display page, return other page +// +export def hgrShow(page)#1 + page = page & 1 + ^(showpage1 + page) + return page ^ 1 +end +export def hgrSwap#0 + ^(showpage1 + drawpage) + drawpage = drawpage ^ 1 + drawbuff = hgrbuff[drawpage] +end +export def hgrDrawBuf(page)#0 + drawpage = page & 1 + drawbuff = hgrbuff[drawpage] +end +done diff --git a/src/makefile b/src/makefile index b0eedb6..07274c0 100755 --- a/src/makefile +++ b/src/makefile @@ -55,6 +55,7 @@ INET = rel/INET\#FE1000 DHCP = rel/DHCP\#FE1000 HTTPD = rel/HTTPD\#FE1000 TFTPD = rel/TFTPD\#FE1000 +HGRLIB = rel/apple/HGRLIB\#FE1000 GRLIB = rel/apple/GRLIB\#FE1000 DGRLIB = rel/apple/DGRLIB\#FE1000 LINESPANS = rel/apple/LINESPANS\#FE1000 @@ -66,6 +67,7 @@ ROGUE = rel/ROGUE\#FE1000 ROGUEMAP = rel/ROGUEMAP\#FE1000 ROGUECOMBAT= rel/ROGUECOMBAT\#FE1000 MON = rel/apple/MON\#FE1000 +HGRTEST = rel/apple/HGRTEST\#FE1000 GRTEST = rel/apple/GRTEST\#FE1000 DGRTEST = rel/apple/DGRTEST\#FE1000 HGRTEST = rel/apple/HGRTEST\#FE1000 @@ -98,7 +100,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -403,6 +405,10 @@ $(PORTIO): libsrc/apple/portio.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/portio.pla > libsrc/apple/portio.a acme --setpc 4094 -o $(PORTIO) libsrc/apple/portio.a +$(HGRLIB): libsrc/apple/hgrlib.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < libsrc/apple/hgrlib.pla > libsrc/apple/hgrlib.a + acme --setpc 4094 -o $(HGRLIB) libsrc/apple/hgrlib.a + $(GRLIB): libsrc/apple/grlib.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/grlib.pla > libsrc/apple/grlib.a acme --setpc 4094 -o $(GRLIB) libsrc/apple/grlib.a @@ -411,6 +417,10 @@ $(DGRLIB): libsrc/apple/dgrlib.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/dgrlib.pla > libsrc/apple/dgrlib.a acme --setpc 4094 -o $(DGRLIB) libsrc/apple/dgrlib.a +$(HGRTEST): samplesrc/hgrtest.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < samplesrc/hgrtest.pla > samplesrc/hgrtest.a + acme --setpc 4094 -o $(HGRTEST) samplesrc/hgrtest.a + $(GRTEST): samplesrc/grtest.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/grtest.pla > samplesrc/grtest.a acme --setpc 4094 -o $(GRTEST) samplesrc/grtest.a diff --git a/src/mkrel b/src/mkrel index ba042fe..04516f9 100755 --- a/src/mkrel +++ b/src/mkrel @@ -10,6 +10,7 @@ mkdir prodos/sys cp rel/apple/FILEIO#FE1000 prodos/sys/FILEIO.REL cp rel/apple/CONIO#FE1000 prodos/sys/CONIO.REL cp rel/apple/LINESPANS#FE1000 prodos/sys/LINESPANS.REL +cp rel/apple/HGRLIB#FE1000 prodos/sys/HGRLIB.REL cp rel/apple/GRLIB#FE1000 prodos/sys/GRLIB.REL cp rel/apple/DGRLIB#FE1000 prodos/sys/DGRLIB.REL cp rel/apple/COPY#FE1000 prodos/sys/COPY.REL @@ -63,6 +64,7 @@ cp ../sysfiles/ELEMS.CODE#060000 prodos/fpsos/sys/ELEMS.CODE.BIN rm -rf prodos/demos mkdir prodos/demos cp rel/INT32TEST#FE1000 prodos/demos/INT32TEST.REL +cp rel/apple/HGRTEST#FE1000 prodos/demos/HGRTEST.REL cp rel/apple/GRTEST#FE1000 prodos/demos/GRTEST.REL cp rel/apple/DGRTEST#FE1000 prodos/demos/DGRTEST.REL cp rel/apple/HGRTEST#FE1000 prodos/demos/HGRTEST.REL @@ -148,6 +150,7 @@ cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT cp inc/cmdsys.plh prodos/bld/inc/CMDSYS.PLH.TXT cp inc/conio.plh prodos/bld/inc/CONIO.PLH.TXT cp inc/linespans.plh prodos/bld/inc/LINESPANS.PLH.TXT +cp inc/hgrlib.plh prodos/bld/inc/HGRLIB.PLH.TXT cp inc/grlib.plh prodos/bld/inc/GRLIB.PLH.TXT cp inc/dgrlib.plh prodos/bld/inc/DGRLIB.PLH.TXT cp inc/fiber.plh prodos/bld/inc/FIBER.PLH.TXT diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index cb3c5cc..f118d21 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -1,275 +1,46 @@ include "inc/cmdsys.plh" include "inc/linespans.plh" -sysflags reshgr1 // Reserve HGR page 1 +include "inc/hgrlib.plh" +sysflags reshgr1 | reshgr2 // Reserve HGR page 1 and 2 + +byte ball = $88, $8F, $FF, $F8, $88 +byte = $88, $FF, $FF, $FF, $88 +byte = $8F, $FF, $FF, $FF, $F8 +byte = $FF, $FF, $FF, $FF, $FF +byte = $FF, $FF, $FF, $FF, $FF +byte = $FF, $FF, $FF, $FF, $FF +byte = $FF, $FF, $FF, $FF, $FF +byte = $8F, $FF, $FF, $FF, $F8 +byte = $88, $FF, $FF, $FF, $88 +byte = $88, $8F, $FF, $F8, $88 // -// Hardware addresses +// Sprite routines // -const showgraphics = $C050 -const showtext = $C051 -const showfull = $C052 -const showmix = $C053 -const showpage1 = $C054 -const showpage2 = $C055 -const showlores = $C056 -const showhires = $C057 -const keyboard = $C000 -const keystrobe = $C010 -const hgr1 = $2000 -const hgr2 = $4000 -const page1 = 0 -const page2 = 1 -word hgrpage[] = hgr1, hgr2 -word hgrscan[] = $0000,$0400,$0800,$0C00,$1000,$1400,$1800,$1C00 -word = $0080,$0480,$0880,$0C80,$1080,$1480,$1880,$1C80 -word = $0100,$0500,$0900,$0D00,$1100,$1500,$1900,$1D00 -word = $0180,$0580,$0980,$0D80,$1180,$1580,$1980,$1D80 -word = $0200,$0600,$0A00,$0E00,$1200,$1600,$1A00,$1E00 -word = $0280,$0680,$0A80,$0E80,$1280,$1680,$1A80,$1E80 -word = $0300,$0700,$0B00,$0F00,$1300,$1700,$1B00,$1F00 -word = $0380,$0780,$0B80,$0F80,$1380,$1780,$1B80,$1F80 -word = $0028,$0428,$0828,$0C28,$1028,$1428,$1828,$1C28 -word = $00A8,$04A8,$08A8,$0CA8,$10A8,$14A8,$18A8,$1CA8 -word = $0128,$0528,$0928,$0D28,$1128,$1528,$1928,$1D28 -word = $01A8,$05A8,$09A8,$0DA8,$11A8,$15A8,$19A8,$1DA8 -word = $0228,$0628,$0A28,$0E28,$1228,$1628,$1A28,$1E28 -word = $02A8,$06A8,$0AA8,$0EA8,$12A8,$16A8,$1AA8,$1EA8 -word = $0328,$0728,$0B28,$0F28,$1328,$1728,$1B28,$1F28 -word = $03A8,$07A8,$0BA8,$0FA8,$13A8,$17A8,$1BA8,$1FA8 -word = $0050,$0450,$0850,$0C50,$1050,$1450,$1850,$1C50 -word = $00D0,$04D0,$08D0,$0CD0,$10D0,$14D0,$18D0,$1CD0 -word = $0150,$0550,$0950,$0D50,$1150,$1550,$1950,$1D50 -word = $01D0,$05D0,$09D0,$0DD0,$11D0,$15D0,$19D0,$1DD0 -word = $0250,$0650,$0A50,$0E50,$1250,$1650,$1A50,$1E50 -word = $02D0,$06D0,$0AD0,$0ED0,$12D0,$16D0,$1AD0,$1ED0 -word = $0350,$0750,$0B50,$0F50,$1350,$1750,$1B50,$1F50 -word = $03D0,$07D0,$0BD0,$0FD0,$13D0,$17D0,$1BD0,$1FD0 -word hcolor[] = $0000,$552A,$2A55,$7F7F,$8080,$D5AA,$AAD5,$FFFF -word hmask = $8081,$8082,$8084,$8088,$8090,$80A0,$80C0 -word = $8180,$8280,$8480,$8880,$9080,$A080,$C080 -byte hbmask = $81,$82,$84,$88,$90,$A0,$C0 -byte hlmask = $FF,$FE,$FC,$F8,$F0,$E0,$C0 -byte hrmask = $81,$83,$87,$8F,$9F,$BF,$FF -word curhclr -word ball0[9] = $0000, $1800, $3C00, $7E00, $7E00, $3C00, $1800, $0000 - -asm grInc(buff) -!SOURCE "vmsrc/plvmzp.inc" -GBASL = $26 -GBASH = $27 -GBASE = GBASL -GCLR = $30 +def spriteCompile(spriteprt) + return 0 end - -asm divmod7(x)#2 - LDA ESTKL,X ; X COORD LSB - LDY ESTKH,X ; X COORD MSB - BNE + ; MUST BE >= 140 - CMP #140 - BCC ++ -+ SEC - SBC #140 - LDY #20 -++ CMP #70 - BCC + - SBC #70 - STA ESTKL,X - TYA - ADC #9 - TAY - LDA ESTKL,X -+ CMP #35 - BCC + - SBC #35 - STA ESTKL,X - TYA - ADC #4 - TAY - LDA ESTKL,X -+ -- CMP #7 - BCC + - SBC #7 - INY - BNE - -+ DEX - STA ESTKL,X ; REMAINDER - STY ESTKL+1,X ; QUOTIENT - LDA #$00 - STA ESTKH,X - STA ESTKH+1,X - RTS -end -def hgrPlot(x, y)#0 - word pptr - byte ofst, pixofst, pmask - - ofst, pixofst = divmod7(x) - pptr = (hgrscan[y] | hgr1) + ofst - pmask = hbmask[pixofst] - ^pptr = (^pptr & ~pmask) | (curhclr.[ofst & 1] & pmask) -end -def hgrHlin(x1, x2, y)#0 - word pptr, x - byte lofst, lpixofst, lpmask, clr - byte rofst, rpixofst, rpmask - - if x1 == x2 - hgrPlot(x1, y) - else - lofst, lpixofst = divmod7(x1) - pptr = (hgrscan[y] | hgr1) + lofst - rofst, rpixofst = divmod7(x2) - lpmask = hlmask[lpixofst] - rpmask = hrmask[rpixofst] - if lofst == rofst - lpmask = lpmask & rpmask - ^pptr = (^pptr & ~lpmask) | (curhclr.[pptr.0 & 1] & lpmask) - else - ^pptr = (^pptr & ~lpmask) | (curhclr.[pptr.0 & 1] & lpmask) - pptr++ - for x = lofst + 1 to rofst - 1 - ^pptr = curhclr.[pptr.0 & 1] - pptr++ - next - ^pptr = (^pptr & ~rpmask) | (curhclr.[pptr.0 & 1] & rpmask) - fin - fin -end -def hgrVlin(y1, y2, x)#0 - word pptr, y - byte ofst, pixofst, pmask, cmask - - if y1 == y2 - hgrPlot(x, y1) - else - ofst, pixofst = divmod7(x) - pmask = hbmask[pixofst] - cmask = curhclr.[ofst & 1] & pmask - pmask = ~pmask - for y = y1 to y2 - pptr = (hgrscan[y] | hgr1) + ofst - ^pptr = (^pptr & pmask) | cmask - next - fin -end -def hgrColor(c)#0 - curhclr = hcolor[c & $07] -end -def hgrBLT(page, x, y, w, h, pSrc)#0 - word pDst - byte i - - repeat - pDst = hgrscan[y] | page + x - for i = 0 to w - 1 - pDst->[i] = pSrc->[i] - next - pSrc = pSrc + w - y++ - h-- - until not h -end -def simpleline(x1, y1, x2, y2)#0 - var err, dx2, dy2, sx, sy, x, y - word pptr - byte ofst, pixofst, pmask, clr - - sx = 1 - sy = 1 - dx2 = (x2 - x1) * 2 - if dx2 < 0 - sx = -1; dx2 = -dx2 - fin - dy2 = (y2 - y1) * 2 - if dy2 < 0 - sy = -1; dy2 = -dy2 - fin - - if dx2 >= dy2 - if sx < 0 - sy = -sy; x1, x2 = x2, x1 - fin - err = dy2 - dx2 / 2 - ofst, pixofst = divmod(x1, 7) - pptr = (hgrscan[y1] | hgr1) + ofst - clr = curhclr.[ofst & 1] - for x = x1 to x2 - pmask = hbmask[pixofst] - ^pptr = (^pptr & ~pmask) | (clr & pmask) - pixofst++ - if pixofst > 6 - pixofst = 0 - pptr++ - ofst++ - clr = curhclr.[ofst & 1] - fin - if err >= 0 - err = err - dx2 - y1 = y1 + sy - pptr = (hgrscan[y1] | hgr1) + ofst - fin - err = err + dy2 - next - else - if sy < 0 - sx = -sx; y1, y2 = y2, y1 - fin - err = dx2 - dy2 / 2 - ofst, pixofst = divmod(x1, 7) - clr = curhclr.[ofst & 1] - pmask = hbmask[pixofst] - for y = y1 to y2 - pptr = (hgrscan[y] | hgr1) + ofst - ^pptr = (^pptr & ~pmask) | (clr & pmask) - if err >= 0 - err = err - dy2 - if sx > 0 - pixofst++ - if pixofst > 6 - pixofst = 0 - ofst++ - clr = curhclr.[ofst & 1] - fin - else - if pixofst == 0 - pixofst = 6 - ofst-- - clr = curhclr.[ofst & 1] - else - pixofst-- - fin - fin - pmask = hbmask[pixofst] - fin - err = err + dx2 - next - fin -end - def testline#0 var i setlinespans(@hgrHlin, @hgrVlin) - hgrColor(2) - //for i = 0 to 191 - // simpleline(0, 0, i, 191) - // simpleline(0, 0, 191, i) - //next - memset(hgr1, 0, $2000) // Clear HGR page 1 - hgrColor(1); - for i = 0 to 191 + hgrColor(3) + for i = 0 to 191 step 4 linetospans(0, 0, i, 191) linetospans(0, 0, 191, i) next end -memset(hgr1, 0, $2000) // Clear HGR page 1 -^showpage1 -^showfull -^showhires -^showgraphics +def testblt#0 + var i + + for i = 0 to 200 step 3 + hgrBlt(i, 50, 10, 10, @ball) + hgrBlt(i, 50, 10, 10, @ball) + next +end +hgrMode +hgrDrawBuf(0) testline -hgrBlt(hgrpage[0], 20, 100, 2, 8, @ball0) +testblt getc -^showpage1 -^showtext +txtMode done diff --git a/src/tftpbld b/src/tftpbld index b083725..e54254f 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -9,10 +9,12 @@ echo "BLD/INC/ARGS.PLH"; atftp $1 --put -l inc/args.plh -r $2/BLD/INC/ARG echo "BLD/INC/CMDSYS.PLH"; atftp $1 --put -l inc/cmdsys.plh -r $2/BLD/INC/CMDSYS.PLH#040000 echo "BLD/INC/CONIO.PLH"; atftp $1 --put -l inc/conio.plh -r $2/BLD/INC/CONIO.PLH#040000 echo "BLD/INC/LINESPANS.PLH"; atftp $1 --put -l inc/linespans.plh -r $2/BLD/INC/LINESPANS.PLH#040000 +echo "BLD/INC/HGRLIB.PLH"; atftp $1 --put -l inc/hgrlib.plh -r $2/BLD/INC/HGRLIB.PLH#040000 echo "BLD/INC/GRLIB.PLH"; atftp $1 --put -l inc/grlib.plh -r $2/BLD/INC/GRLIB.PLH#040000 echo "BLD/INC/DGRLIB.PLH"; atftp $1 --put -l inc/dgrlib.plh -r $2/BLD/INC/DGRLIB.PLH#040000 echo "BLD/INC/FIBER.PLH"; atftp $1 --put -l inc/fiber.plh -r $2/BLD/INC/FIBER.PLH#040000 echo "BLD/INC/FILEIO.PLH"; atftp $1 --put -l inc/fileio.plh -r $2/BLD/INC/FILEIO.PLH#040000 +echo "BLD/INC/INT32.PLH"; atftp $1 --put -l inc/int32.plh -r $2/BLD/INC/INT32.PLH#040000 echo "BLD/INC/FPSTR.PLH"; atftp $1 --put -l inc/fpstr.plh -r $2/BLD/INC/FPSTR.PLH#040000 echo "BLD/INC/FPU.PLH"; atftp $1 --put -l inc/fpu.plh -r $2/BLD/INC/FPU.PLH#040000 echo "BLD/INC/GRAFIX.PLH"; atftp $1 --put -l inc/grafix.plh -r $2/BLD/INC/GRAFIX.PLH#040000 @@ -36,13 +38,15 @@ echo "BLD/SAMPLES/TEST.PLA"; atftp $1 --put -l samplesrc/test.pla -r $ echo "BLD/SAMPLES/FIBERTEST.PLA"; atftp $1 --put -l samplesrc/fibertest.pla -r $2/BLD/SAMPLES/FIBERTEST.PLA#040000 echo "BLD/SAMPLES/MOUSETEST.PLA"; atftp $1 --put -l samplesrc/mousetest.pla -r $2/BLD/SAMPLES/MOUSETEST.PLA#040000 echo "BLD/SAMPLES/ROD.PLA"; atftp $1 --put -l samplesrc/rod.pla -r $2/BLD/SAMPLES/ROD.PLA#040000 +echo "BLD/SAMPLES/INT32TEST.PLA"; atftp $1 --put -l samplesrc/int32test.pla -r $2/BLD/SAMPLES/INT32TEST.PLA#040000 +echo "BLD/SAMPLES/HGRTEST.PLA"; atftp $1 --put -l samplesrc/hgrtest.pla -r $2/BLD/SAMPLES/HGRTEST.PLA#040000 echo "BLD/SAMPLES/GRTEST.PLA"; atftp $1 --put -l samplesrc/grtest.pla -r $2/BLD/SAMPLES/GRTEST.PLA#040000 echo "BLD/SAMPLES/DGRTEST.PLA"; atftp $1 --put -l samplesrc/dgrtest.pla -r $2/BLD/SAMPLES/DGRTEST.PLA#040000 echo "BLD/SAMPLES/HGRTEST.PLA"; atftp $1 --put -l samplesrc/hgrtest.pla -r $2/BLD/SAMPLES/HGRTEST.PLA#040000 echo "BLD/SAMPLES/PLAYSEQ.PLA"; atftp $1 --put -l samplesrc/playseq.pla -r $2/BLD/SAMPLES/PLAYSEQ.PLA#040000 echo "BLD/SAMPLES/RPNCALC.PLA"; atftp $1 --put -l samplesrc/rpncalc.pla -r $2/BLD/SAMPLES/RPNCALC.PLA#040000 echo "BLD/SAMPLES/SIEVE.PLA"; atftp $1 --put -l samplesrc/sieve.pla -r $2/BLD/SAMPLES/SIEVE.PLA#040000 -echo "BLD/SAMPLES/MON.PLA"; atftp $1 --put -l samplesrc/mon.pla -r $2/BLD/SAMPLES/MON.PLA#040000 +echo "BLD/SAMPLES/MON.PLA"; atftp $1 --put -l utilsrc/mon.pla -r $2/BLD/SAMPLES/MON.PLA#040000 echo "BLD/SAMPLES/MEMTEST.PLA"; atftp $1 --put -l samplesrc/memtest.pla -r $2/BLD/SAMPLES/MEMTEST.PLA#040000 echo "BLD/SAMPLES/FATCAT.PLA"; atftp $1 --put -l samplesrc/fatcat.pla -r $2/BLD/SAMPLES/FATCAT.PLA#040000 echo "BLD/SAMPLES/GFXDEMO.PLA"; atftp $1 --put -l samplesrc/gfxdemo.pla -r $2/BLD/SAMPLES/GFXDEMO.PLA#040000 diff --git a/src/tftpdemos b/src/tftpdemos index 0ea1c38..8e010d8 100755 --- a/src/tftpdemos +++ b/src/tftpdemos @@ -5,7 +5,9 @@ echo "DEMOS/RPNCALC"; atftp $1 --put -l rel/RPNCALC#FE1000 echo "DEMOS/LZ4CAT"; atftp $1 --put -l rel/LZ4CAT#FE1000 -r $2/DEMOS/LZ4CAT#FE1000 echo "DEMOS/SIEVE"; atftp $1 --put -l rel/SIEVE#FE1000 -r $2/DEMOS/SIEVE#FE1000 echo "DEMOS/ROD"; atftp $1 --put -l rel/apple/ROD#FE1000 -r $2/DEMOS/ROD#FE1000 +echo "DEMOS/HGRTEST"; atftp $1 --put -l rel/apple/HGRTEST#FE1000 -r $2/DEMOS/HGRTEST#FE1000 echo "DEMOS/GRTEST"; atftp $1 --put -l rel/apple/GRTEST#FE1000 -r $2/DEMOS/GRTEST#FE1000 +echo "DEMOS/INT32TEST"; atftp $1 --put -l rel/INT32TEST#FE1000 -r $2/DEMOS/INT32TEST#FE1000 echo "DEMOS/DGRTEST"; atftp $1 --put -l rel/apple/DGRTEST#FE1000 -r $2/DEMOS/DGRTEST#FE1000 # Music demo diff --git a/src/tftpsys b/src/tftpsys index 10be2d3..cf146d9 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -12,6 +12,7 @@ echo "SYS/JITUNE"; atftp $1 --put -l rel/apple/JITUNE#FE1000 -r $2/SYS/JITUNE # Core libraries echo "SYS/ARGS"; atftp $1 --put -l rel/ARGS#FE1000 -r $2/SYS/ARGS#FE1000 +echo "SYS/INT32"; atftp $1 --put -l rel/INT32#FE1000 -r $2/SYS/INT32#FE1000 echo "SYS/DHCP"; atftp $1 --put -l rel/DHCP#FE1000 -r $2/SYS/DHCP#FE1000 echo "SYS/ETHERIP"; atftp $1 --put -l rel/ETHERIP#FE1000 -r $2/SYS/ETHERIP#FE1000 echo "SYS/MOUSE"; atftp $1 --put -l rel/apple/MOUSE#FE1000 -r $2/SYS/MOUSE#FE1000 @@ -22,6 +23,7 @@ echo "SYS/MEMMGR"; atftp $1 --put -l rel/MEMMGR#FE1000 -r $2/SYS/MEMMGR#FE1000 echo "SYS/LZ4"; atftp $1 --put -l rel/LZ4#FE1000 -r $2/SYS/LZ4#FE1000 echo "SYS/CONIO"; atftp $1 --put -l rel/apple/CONIO#FE1000 -r $2/SYS/CONIO#FE1000 echo "SYS/LINESPANS"; atftp $1 --put -l rel/apple/LINESPANS#FE1000 -r $2/SYS/LINESPANS#FE1000 +echo "SYS/HGRLIB"; atftp $1 --put -l rel/apple/HGRLIB#FE1000 -r $2/SYS/HGRLIB#FE1000 echo "SYS/GRLIB"; atftp $1 --put -l rel/apple/GRLIB#FE1000 -r $2/SYS/GRLIB#FE1000 echo "SYS/DGRLIB"; atftp $1 --put -l rel/apple/DGRLIB#FE1000 -r $2/SYS/DGRLIB#FE1000 echo "SYS/FILEIO"; atftp $1 --put -l rel/apple/FILEIO#FE1000 -r $2/SYS/FILEIO#FE1000 From 1f94b7331a9e40980b5b3440c74fa6628a8acda2 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Tue, 24 Dec 2019 16:00:49 -0800 Subject: [PATCH 074/149] export divmod7 --- src/inc/hgrlib.plh | 1 + src/libsrc/apple/hgrlib.pla | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/inc/hgrlib.plh b/src/inc/hgrlib.plh index 90560ec..46daa15 100644 --- a/src/inc/hgrlib.plh +++ b/src/inc/hgrlib.plh @@ -1,4 +1,5 @@ import hgrlib + predef divmod7(x)#2 predef hgrPlot(x, y)#0 predef hgrXorPlot(x, y)#0 predef hgrHLin(x1, x2, y)#0 diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index e434904..233a0ee 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -70,7 +70,7 @@ GBASE = GBASL GCLR = $30 end -asm divmod7(x)#2 +export asm divmod7(x)#2 LDA ESTKL,X ; X COORD LSB LDY ESTKH,X ; X COORD MSB BNE + ; MUST BE >= 140 From dd721f5a75928e84a964e9e0256d4011fe2a5949 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Wed, 25 Dec 2019 10:23:50 -0800 Subject: [PATCH 075/149] HGR sprite library WIP --- src/inc/hgrlib.plh | 4 +- src/libsrc/apple/hgrlib.pla | 74 ++++++++++++++---- src/samplesrc/hgrtest.pla | 149 +++++++++++++++++++++++++++++------- 3 files changed, 183 insertions(+), 44 deletions(-) diff --git a/src/inc/hgrlib.plh b/src/inc/hgrlib.plh index 46daa15..1e2d4e8 100644 --- a/src/inc/hgrlib.plh +++ b/src/inc/hgrlib.plh @@ -4,6 +4,7 @@ import hgrlib predef hgrXorPlot(x, y)#0 predef hgrHLin(x1, x2, y)#0 predef hgrVLin(y1, y2, x)#0 + predef hgrRect(x1, x2, y1, y2)#0 predef hgrBLT(x, y, width, height, srcptr)#0 predef hgrCopySrc(ofst, y, w, h, srcptr)#0 predef hgrAndSrc(ofst, y, w, h, srcptr)#0 @@ -11,8 +12,9 @@ import hgrlib predef hgrCopyDst(ofst, y, w, h, dstptr)#0 predef hgrMode#1 predef txtMode#0 + predef hgrClear#0 predef hgrShow(page)#1 - predef hgrSwap#0 + predef hgrSwap#1 predef hgrDrawBuf(page)#0 predef hgrColor(clr)#0 end diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index 233a0ee..12e4fe5 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -108,7 +108,7 @@ export asm divmod7(x)#2 STA ESTKH,X STA ESTKH+1,X RTS -end +end export def hgrColor(c)#0 curhclr = hcolor[c & $07] end @@ -132,7 +132,7 @@ export def hgrXorPlot(x, y)#0 end export def hgrHlin(x1, x2, y)#0 word pixptr, x - byte lofst, lpixofst, lpmask, clr + byte lofst, lpixofst, lpmask byte rofst, rpixofst, rpmask if x1 == x2 @@ -175,6 +175,52 @@ export def hgrVlin(y1, y2, x)#0 next fin end +export def hgrRect(x1, x2, y1, y2)#0 + word pixptr, x, y, lofst, rofst + byte lpixofst, lpmask, cmask + byte rpixofst, rpmask + + if x1 == x2 + hgrVLin(y1, y2, x1) + else + lofst, lpixofst = divmod7(x1) + rofst, rpixofst = divmod7(x2) + lofst = lofst + drawbuff + rofst = rofst + drawbuff + lpmask = hlmask[lpixofst] + rpmask = hrmask[rpixofst] + if lofst == rofst + lpmask = lpmask & rpmask + cmask = curhclr.[pixptr.0 & 1] & lpmask + lpmask = ~lpmask + for y = y1 to y2 + pixptr = hgrscan[y] + lofst + ^pixptr = (^pixptr & lpmask) | cmask + next + else + for y = y1 to y2 + pixptr = hgrscan[y] + lofst + ^pixptr = (^pixptr & ~lpmask) | (curhclr.[pixptr.0 & 1] & lpmask) + pixptr++ + for x = lofst + 1 to rofst - 1 + ^pixptr = curhclr.[pixptr.0 & 1] + pixptr++ + next + ^pixptr = (^pixptr & ~rpmask) | (curhclr.[pixptr.0 & 1] & rpmask) + next + fin + fin +end +export def hgrCopyDst(ofst, y, w, h, dstptr)#0 + word j, srcptr + + ofst = ofst + drawbuff + for j = y to y + h - 1 + srcptr = hgrscan[j] + ofst + memcpy(dstptr, srcptr, w) + dstptr = dstptr + w + next +end export def hgrCopySrc(ofst, y, w, h, srcptr)#0 word j, dstptr @@ -211,16 +257,6 @@ export def hgrXorSrc(ofst, y, w, h, srcptr)#0 srcptr = srcptr + w next end -export def hgrCopyDst(ofst, y, w, h, dstptr)#0 - word j, srcptr - - ofst = ofst + drawbuff - for j = y to y + h - 1 - srcptr = hgrscan[j] + ofst - memcpy(dstptr, srcptr, w) - dstptr = dstptr + w - next -end export def hgrBLT(x, y, w, h, srcptr)#0 word i, j word saveclr @@ -231,15 +267,15 @@ export def hgrBLT(x, y, w, h, srcptr)#0 for i = 0 to w - 1 c = srcptr->[i >> 1] if i & 1 - curhclr = hcolor[(c >> 4) & $07] - if c & $80 + curhclr = hcolor[c & $07] + if c & $08 hgrXorPlot(x + i, j) else hgrPlot(x + i, j) fin else - curhclr = hcolor[c & $07] - if c & $08 + curhclr = hcolor[(c >> 4) & $07] + if c & $80 hgrXorPlot(x + i, j) else hgrPlot(x + i, j) @@ -264,6 +300,9 @@ export def txtMode#0 ^showpage1 ^showtext end +export def hgrClear#0 + memset(drawbuff, curhclr, $2000) // Clear HGR page 1 +end // // Set display page, return other page // @@ -272,10 +311,11 @@ export def hgrShow(page)#1 ^(showpage1 + page) return page ^ 1 end -export def hgrSwap#0 +export def hgrSwap#1 ^(showpage1 + drawpage) drawpage = drawpage ^ 1 drawbuff = hgrbuff[drawpage] + return drawpage end export def hgrDrawBuf(page)#0 drawpage = page & 1 diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index f118d21..9a7ac16 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -1,46 +1,143 @@ include "inc/cmdsys.plh" -include "inc/linespans.plh" include "inc/hgrlib.plh" -sysflags reshgr1 | reshgr2 // Reserve HGR page 1 and 2 +include "inc/linespans.plh" +sysflags reshgr1|reshgr2 // Reserve HGR page 1 and 2 -byte ball = $88, $8F, $FF, $F8, $88 -byte = $88, $FF, $FF, $FF, $88 -byte = $8F, $FF, $FF, $FF, $F8 -byte = $FF, $FF, $FF, $FF, $FF -byte = $FF, $FF, $FF, $FF, $FF -byte = $FF, $FF, $FF, $FF, $FF -byte = $FF, $FF, $FF, $FF, $FF -byte = $8F, $FF, $FF, $FF, $F8 -byte = $88, $FF, $FF, $FF, $88 -byte = $88, $8F, $FF, $F8, $88 +struc t_sprite + byte s_underofst[2] + var s_undery[2] + var s_width + var s_height + var s_pitch + var s_size + var s_mask[14] + var s_map[14] + var s_under[14] +end + +byte ball = $88, $83, $33, $38, $88 +byte = $88, $33, $11, $33, $88 +byte = $83, $31, $11, $13, $38 +byte = $33, $11, $11, $11, $33 +byte = $33, $11, $11, $11, $33 +byte = $33, $11, $11, $11, $33 +byte = $33, $11, $11, $11, $33 +byte = $83, $31, $11, $13, $38 +byte = $88, $33, $11, $33, $88 +byte = $88, $83, $33, $38, $88 +var sprtBall +byte drawpage // // Sprite routines // -def spriteCompile(spriteprt) - return 0 +export def spriteBLTMask(x, y, w, h, srcptr)#0 + word i, j + byte c + + for j = y to y + h - 1 + for i = 0 to w - 1 + c = srcptr->[i >> 1] + if i & 1 + hgrColor(c & $08 ?? 7 :: 0) + else + hgrColor(c & $80 ?? 7 :: 0) + fin + hgrPlot(x + i, j) + next + srcptr = srcptr + (w + 1) / 2 + next +end +def spriteCompile(w, h, srcptr) + var sprtptr, bytewidth, spritesize, i + + sprtptr = heapalloc(t_sprite) + bytewidth = (w + 7) / 7 + 1 + sprtptr=>s_pitch = bytewidth + spritesize = bytewidth * h + sprtptr=>s_size = spritesize + sprtptr=>s_width = w + sprtptr=>s_height = h + sprtptr=>s_under[0] = heapalloc(spritesize) + sprtptr=>s_under[1] = heapalloc(spritesize) + for i = 0 to 13 + sprtptr=>s_map[i] = heapalloc(spritesize) + sprtptr=>s_mask[i] = heapalloc(spritesize) + hgrColor(0) + hgrRect(0, i + w + 14, 0, h - 1) + hgrBLT(i, 0, w, h, srcptr) + hgrCopyDst(i > 6 ?? 1 :: 0, 0, bytewidth, h, sprtptr=>s_map[i]) + hgrColor(7) + hgrRect(0, i + w + 14, h, h * 2 - 1) + spriteBLTMask(i, h, w, h, srcptr) + hgrCopyDst(i > 6 ?? 1 :: 0, h, bytewidth, h, sprtptr=>s_mask[i]) + next + sprtptr->s_underofst[0] = 255 // Mark as under not valid + sprtptr->s_underofst[1] = 255 + return sprtptr +end +def spriteDraw(page, x, y, sprtptr)#0 + byte ofst, map + var width, height + + ofst, map = divmod7(x) + if ofst & 1 + map = map + 7 + fin + sprtptr->s_underofst[page] = ofst + sprtptr->s_undery[page] = y + width = sprtptr=>s_pitch + height = sprtptr=>s_height + hgrCopyDst(ofst, y, width, height, sprtptr=>s_under[page]) + hgrAndSrc( ofst, y, width, height, sprtptr=>s_mask[map]) + hgrXorSrc( ofst, y, width, height, sprtptr=>s_map[map]) +end +def spriteUnDraw(page, sprtptr)#0 + if sprtptr->s_underofst[page] < 40 + hgrCopySrc(sprtptr->s_underofst[page], sprtptr->s_undery[page], sprtptr=>s_pitch, sprtptr=>s_height, sprtptr=>s_under[page]) + fin end def testline#0 var i setlinespans(@hgrHlin, @hgrVlin) - hgrColor(3) - for i = 0 to 191 step 4 + hgrColor(7) + for i = 0 to 191 step 24 + linetospans(0, 0, 279, i) + next + for i = 0 to 279 step 24 linetospans(0, 0, i, 191) - linetospans(0, 0, 191, i) next end -def testblt#0 - var i +def testblt(sprtptr)#0 + var i, j, ii, jj - for i = 0 to 200 step 3 - hgrBlt(i, 50, 10, 10, @ball) - hgrBlt(i, 50, 10, 10, @ball) - next + i = 100 + ii = 1 + j = 80 + jj = 1 + while ^$C000 < 128 + spriteUnDraw(drawpage, sprtptr) + i = i + ii + if i < 1 or i > 269 + ii = -ii + fin + j = j + jj + if j < 1 or j > 181 + jj = -jj + fin + spriteDraw(drawpage, i, j, sprtptr) + drawpage = hgrSwap() + loop end -hgrMode -hgrDrawBuf(0) +drawpage = hgrMode +hgrDrawBuf(0) // So we can see the compile process +sprtBall = spriteCompile(10, 10, @ball) +hgrColor(0) +hgrClear() testline -testblt +memcpy($4000, $2000, $2000) // Copy to both buffers +hgrDrawbuf(drawpage) +testblt(sprtBall) getc txtMode done From 8aae1077eed2c024b4eec49eace339bca9932897 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Wed, 25 Dec 2019 12:25:28 -0800 Subject: [PATCH 076/149] Sprite list test --- src/inc/hgrlib.plh | 1 + src/libsrc/apple/hgrlib.pla | 13 ++++ src/samplesrc/hgrtest.pla | 142 +++++++++++++++++++++++++++++------- 3 files changed, 129 insertions(+), 27 deletions(-) diff --git a/src/inc/hgrlib.plh b/src/inc/hgrlib.plh index 1e2d4e8..54c0979 100644 --- a/src/inc/hgrlib.plh +++ b/src/inc/hgrlib.plh @@ -9,6 +9,7 @@ import hgrlib predef hgrCopySrc(ofst, y, w, h, srcptr)#0 predef hgrAndSrc(ofst, y, w, h, srcptr)#0 predef hgrXorSrc(ofst, y, w, h, srcptr)#0 + predef hgrOrSrc(ofst, y, w, h, srcptr)#0 predef hgrCopyDst(ofst, y, w, h, dstptr)#0 predef hgrMode#1 predef txtMode#0 diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index 12e4fe5..ddc480f 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -257,6 +257,19 @@ export def hgrXorSrc(ofst, y, w, h, srcptr)#0 srcptr = srcptr + w next end +export def hgrOrSrc(ofst, y, w, h, srcptr)#0 + word j, dstptr + byte i + + ofst = ofst + drawbuff + for j = y to y + h - 1 + dstptr = hgrscan[j] + ofst + for i = 0 to w - 1 + dstptr->[i] = dstptr->[i] ^ srcptr->[i] + next + srcptr = srcptr + w + next +end export def hgrBLT(x, y, w, h, srcptr)#0 word i, j word saveclr diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index 9a7ac16..d13fa0a 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -4,17 +4,20 @@ include "inc/linespans.plh" sysflags reshgr1|reshgr2 // Reserve HGR page 1 and 2 struc t_sprite + var s_xpos + var s_ypos byte s_underofst[2] var s_undery[2] var s_width var s_height var s_pitch - var s_size + var s_size var s_mask[14] var s_map[14] var s_under[14] end +var spriteList[16] byte ball = $88, $83, $33, $38, $88 byte = $88, $33, $11, $33, $88 byte = $83, $31, $11, $13, $38 @@ -38,9 +41,9 @@ export def spriteBLTMask(x, y, w, h, srcptr)#0 for i = 0 to w - 1 c = srcptr->[i >> 1] if i & 1 - hgrColor(c & $08 ?? 7 :: 0) + hgrColor(c & $08 ?? 3 :: 0) else - hgrColor(c & $80 ?? 7 :: 0) + hgrColor(c & $80 ?? 3 :: 0) fin hgrPlot(x + i, j) next @@ -63,11 +66,11 @@ def spriteCompile(w, h, srcptr) sprtptr=>s_map[i] = heapalloc(spritesize) sprtptr=>s_mask[i] = heapalloc(spritesize) hgrColor(0) - hgrRect(0, i + w + 14, 0, h - 1) + hgrRect(0, w + 21, 0, h - 1) hgrBLT(i, 0, w, h, srcptr) hgrCopyDst(i > 6 ?? 1 :: 0, 0, bytewidth, h, sprtptr=>s_map[i]) - hgrColor(7) - hgrRect(0, i + w + 14, h, h * 2 - 1) + hgrColor(3) + hgrRect(0, w + 21, h, h * 2 - 1) spriteBLTMask(i, h, w, h, srcptr) hgrCopyDst(i > 6 ?? 1 :: 0, h, bytewidth, h, sprtptr=>s_mask[i]) next @@ -75,11 +78,32 @@ def spriteCompile(w, h, srcptr) sprtptr->s_underofst[1] = 255 return sprtptr end -def spriteDraw(page, x, y, sprtptr)#0 - byte ofst, map +def spriteDup(sprtsrc) + var sprtdup, spritesize + byte i + + sprtdup = heapalloc(t_sprite) + spritesize = sprtsrc=>s_size + sprtdup=>s_size = spritesize + sprtdup=>s_pitch = sprtsrc=>s_pitch + sprtdup=>s_width = sprtsrc=>s_width + sprtdup=>s_height = sprtsrc=>s_height + sprtdup=>s_under[0] = heapalloc(spritesize) + sprtdup=>s_under[1] = heapalloc(spritesize) + for i = 0 to 13 + sprtdup=>s_map[i] = sprtsrc=>s_map[i] + sprtdup=>s_mask[i] = sprtsrc=>s_mask[i] + next + sprtdup->s_underofst[0] = 255 // Mark as under not valid + sprtdup->s_underofst[1] = 255 + return sprtdup +end +def spriteDraw(page, sprtptr)#0 + byte ofst, map, y var width, height - ofst, map = divmod7(x) + y = sprtptr->s_ypos + ofst, map = divmod7(sprtptr=>s_xpos) if ofst & 1 map = map + 7 fin @@ -91,11 +115,55 @@ def spriteDraw(page, x, y, sprtptr)#0 hgrAndSrc( ofst, y, width, height, sprtptr=>s_mask[map]) hgrXorSrc( ofst, y, width, height, sprtptr=>s_map[map]) end +def spritePos(x, y, sprtptr)#0 + sprtptr=>s_ypos = y + sprtptr=>s_xpos = x +end +def spritePosIndex(x, y, i)#0 + i = i & 15 + if spriteList[i] + spriteList[i]=>s_ypos = y + spriteList[i]=>s_xpos = x + fin +end def spriteUnDraw(page, sprtptr)#0 if sprtptr->s_underofst[page] < 40 hgrCopySrc(sprtptr->s_underofst[page], sprtptr->s_undery[page], sprtptr=>s_pitch, sprtptr=>s_height, sprtptr=>s_under[page]) fin end +def spriteDrawList#0 + byte i + + for i = 15 downto 0 + if spriteList[i] + spriteUnDraw(drawpage, spriteList[i]) + fin + next + for i = 0 to 15 + if spriteList[i] + spriteDraw(drawpage, spriteList[i]) + fin + next +end +def spriteAdd(i, sprtptr) + var sprtprev + + i = i & 15 + sprtprev = spriteList[i] + spriteList[i] = sprtptr + return sprtprev +end +def spriteDel(i) + var sprtprev + + i = i & 15 + sprtprev = spriteList[i] + spriteList[i] = 0 + return sprtprev +end +def spriteDrawPage(page)#0 + drawpage = page & 1 +end def testline#0 var i @@ -108,25 +176,37 @@ def testline#0 linetospans(0, 0, i, 191) next end -def testblt(sprtptr)#0 - var i, j, ii, jj +def testblt(sprtnum)#0 + var[16] i, j, ii, jj + byte k - i = 100 - ii = 1 - j = 80 - jj = 1 + sprtnum = sprtnum - 1 + i[0] = 100 + ii[0] = 1 + j[0] = 80 + jj[0] = -1 + if sprtnum + for k = 1 to sprtnum + i[k] = ((i[k - 1] ^ 37) + 97) % 270 + ii[k] = -ii[k - 1] + j[k] = ((j[k - 1] ^ 29) + 53) % 180 + jj[k] = -jj[k - 1] + next + fin while ^$C000 < 128 - spriteUnDraw(drawpage, sprtptr) - i = i + ii - if i < 1 or i > 269 - ii = -ii - fin - j = j + jj - if j < 1 or j > 181 - jj = -jj - fin - spriteDraw(drawpage, i, j, sprtptr) - drawpage = hgrSwap() + for k = 0 to sprtnum + i[k] = i[k] + ii[k] + if i[k] < 1 or i[k] > 269 + ii[k] = -ii[k] + fin + j[k] = j[k] + jj[k] + if j[k] < 1 or j[k] > 181 + jj[k] = -jj[k] + fin + spritePosIndex(i[k], j[k], k) + next + spriteDrawList() + spriteDrawPage(hgrSwap()) loop end drawpage = hgrMode @@ -137,7 +217,15 @@ hgrClear() testline memcpy($4000, $2000, $2000) // Copy to both buffers hgrDrawbuf(drawpage) -testblt(sprtBall) +spriteAdd(0, sprtBall) +spriteAdd(1, spriteDup(sprtBall)) +spriteAdd(2, spriteDup(sprtBall)) +spriteAdd(3, spriteDup(sprtBall)) +spriteAdd(4, spriteDup(sprtBall)) +spriteAdd(5, spriteDup(sprtBall)) +spriteAdd(6, spriteDup(sprtBall)) +spriteAdd(7, spriteDup(sprtBall)) +testblt(8) getc txtMode done From e258131e717d43981042760095b0ffe5e1ed5ec7 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 26 Dec 2019 11:46:11 -0800 Subject: [PATCH 077/149] Assemly-ize some routines --- src/libsrc/apple/hgrlib.pla | 445 ++++++++++++++++++++++++++++++------ 1 file changed, 376 insertions(+), 69 deletions(-) diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index ddc480f..02ffb54 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -17,6 +17,54 @@ const hgr2 = $4000 const page1 = 0 const page2 = 1 word hgrbuff[] = hgr1, hgr2 +byte hgrscanl[]= $00,$00,$00,$00,$00,$00,$00,$00 +byte = $80,$80,$80,$80,$80,$80,$80,$80 +byte = $00,$00,$00,$00,$00,$00,$00,$00 +byte = $80,$80,$80,$80,$80,$80,$80,$80 +byte = $00,$00,$00,$00,$00,$00,$00,$00 +byte = $80,$80,$80,$80,$80,$80,$80,$80 +byte = $00,$00,$00,$00,$00,$00,$00,$00 +byte = $80,$80,$80,$80,$80,$80,$80,$80 +byte = $28,$28,$28,$28,$28,$28,$28,$28 +byte = $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 +byte = $28,$28,$28,$28,$28,$28,$28,$28 +byte = $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 +byte = $28,$28,$28,$28,$28,$28,$28,$28 +byte = $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 +byte = $28,$28,$28,$28,$28,$28,$28,$28 +byte = $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 +byte = $50,$50,$50,$50,$50,$50,$50,$50 +byte = $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 +byte = $50,$50,$50,$50,$50,$50,$50,$50 +byte = $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 +byte = $50,$50,$50,$50,$50,$50,$50,$50 +byte = $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 +byte = $50,$50,$50,$50,$50,$50,$50,$50 +byte = $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 +byte hgrscanh[]= $00,$04,$08,$0C,$10,$14,$18,$1C +byte = $00,$04,$08,$0C,$10,$14,$18,$1C +byte = $01,$05,$09,$0D,$11,$15,$19,$1D +byte = $01,$05,$09,$0D,$11,$15,$19,$1D +byte = $02,$06,$0A,$0E,$12,$16,$1A,$1E +byte = $02,$06,$0A,$0E,$12,$16,$1A,$1E +byte = $03,$07,$0B,$0F,$13,$17,$1B,$1F +byte = $03,$07,$0B,$0F,$13,$17,$1B,$1F +byte = $00,$04,$08,$0C,$10,$14,$18,$1C +byte = $00,$04,$08,$0C,$10,$14,$18,$1C +byte = $01,$05,$09,$0D,$11,$15,$19,$1D +byte = $01,$05,$09,$0D,$11,$15,$19,$1D +byte = $02,$06,$0A,$0E,$12,$16,$1A,$1E +byte = $02,$06,$0A,$0E,$12,$16,$1A,$1E +byte = $03,$07,$0B,$0F,$13,$17,$1B,$1F +byte = $03,$07,$0B,$0F,$13,$17,$1B,$1F +byte = $00,$04,$08,$0C,$10,$14,$18,$1C +byte = $00,$04,$08,$0C,$10,$14,$18,$1C +byte = $01,$05,$09,$0D,$11,$15,$19,$1D +byte = $01,$05,$09,$0D,$11,$15,$19,$1D +byte = $02,$06,$0A,$0E,$12,$16,$1A,$1E +byte = $02,$06,$0A,$0E,$12,$16,$1A,$1E +byte = $03,$07,$0B,$0F,$13,$17,$1B,$1F +byte = $03,$07,$0B,$0F,$13,$17,$1B,$1F word hgrscan[] = $0000,$0400,$0800,$0C00,$1000,$1400,$1800,$1C00 word = $0080,$0480,$0880,$0C80,$1080,$1480,$1880,$1C80 word = $0100,$0500,$0900,$0D00,$1100,$1500,$1900,$1D00 @@ -109,17 +157,307 @@ export asm divmod7(x)#2 STA ESTKH+1,X RTS end -export def hgrColor(c)#0 - curhclr = hcolor[c & $07] +//export def hgrCopyDst(ofst, y, w, h, dstptr)#0 +// word j, srcptr +// +// ofst = ofst + drawbuff +// for j = y to y + h - 1 +// srcptr = hgrscan[j] + ofst +// memcpy(dstptr, srcptr, w) +// dstptr = dstptr + w +// next +//end +export asm hgrCopyDst(ofst, y, w, h, dstptr)#0 + LDA ESTKL+0,X ; DST PTR + STA DSTL + LDA ESTKH+0,X + STA DSTH +-- LDY ESTKL+3,X ; Y COORD + CPY #192 + BCS + + LDA ESTKL+4,X ; HORIZ OFFSET end -export def hgrPlot(x, y)#0 - word pixptr - byte ofst, pixofst, pmask - - ofst, pixofst = divmod7(x) - pixptr = hgrscan[y] + drawbuff + ofst - pmask = hbmask[pixofst] - ^pixptr = (^pixptr & ~pmask) | (curhclr.[ofst & 1] & pmask) +asm _hgrCopyDst + ADC $8000,Y ; HGRSCANL + STA SRCL + LDA $1000 ; DRAWBUFFH + ADC $9000,Y ; HGRSCANH + STA SRCH + LDY ESTKL+2,X ; WIDTH + DEY +- LDA (SRC),Y + STA (DST),Y + DEY + BPL - ++ LDA DSTL + CLC + ADC ESTKL+2,X ; WIDTH + STA DSTL + BCC + + INC DSTH ++ INC ESTKL+3,X ; Y COORD + DEC ESTKL+1,X ; HEIGHT + BNE -- + INX + INX + INX + INX + INX + RTS +end +//export def hgrCopySrc(ofst, y, w, h, srcptr)#0 +// word j, dstptr +// +// ofst = ofst + drawbuff +// for j = y to y + h - 1 +// dstptr = hgrscan[j] + ofst +// memcpy(dstptr, srcptr, w) +// srcptr = srcptr + w +// next +//end +export asm hgrCopySrc(ofst, y, w, h, srcptr)#0 + LDA ESTKL+0,X ; SRC PTR + STA SRCL + LDA ESTKH+0,X + STA SRCH +-- LDY ESTKL+3,X ; Y COORD + CPY #192 + BCS + + LDA ESTKL+4,X ; HORIZ OFFSET +end +asm _hgrCopySrc + ADC $8000,Y ; HGRSCANL + STA DSTL + LDA $1000 ; DRAWBUFFH + ADC $9000,Y ; HGRSCANH + STA DSTH + LDY ESTKL+2,X ; WIDTH + DEY +- LDA (SRC),Y + STA (DST),Y + DEY + BPL - ++ LDA SRCL + CLC + ADC ESTKL+2,X ; WIDTH + STA SRCL + BCC + + INC SRCH ++ INC ESTKL+3,X ; Y COORD + DEC ESTKL+1,X ; HEIGHT + BNE -- + INX + INX + INX + INX + INX + RTS +end +//export def hgrAndSrc(ofst, y, w, h, srcptr)#0 +// word j, dstptr +// byte i +// +// ofst = ofst + drawbuff +// for j = y to y + h - 1 +// dstptr = hgrscan[j] + ofst +// for i = 0 to w - 1 +// dstptr->[i] = dstptr->[i] & srcptr->[i] +// next +// srcptr = srcptr + w +// next +//end +export asm hgrAndSrc(ofst, y, w, h, srcptr)#0 + LDA ESTKL+0,X ; SRC PTR + STA SRCL + LDA ESTKH+0,X + STA SRCH +-- LDY ESTKL+3,X ; Y COORD + CPY #192 + BCS + + LDA ESTKL+4,X ; HORIZ OFFSET +end +asm _hgrAndSrc + ADC $8000,Y ; HGRSCANL + STA DSTL + LDA $1000 ; DRAWBUFFH + ADC $9000,Y ; HGRSCANH + STA DSTH + LDY ESTKL+2,X ; WIDTH + DEY +- LDA (SRC),Y + AND (DST),Y + STA (DST),Y + DEY + BPL - ++ LDA SRCL + CLC + ADC ESTKL+2,X ; WIDTH + STA SRCL + BCC + + INC SRCH ++ INC ESTKL+3,X ; Y COORD + DEC ESTKL+1,X ; HEIGHT + BNE -- + INX + INX + INX + INX + INX + RTS +end +//export def hgrXorSrc(ofst, y, w, h, srcptr)#0 +// word j, dstptr +// byte i +// +// ofst = ofst + drawbuff +// for j = y to y + h - 1 +// dstptr = hgrscan[j] + ofst +// for i = 0 to w - 1 +// dstptr->[i] = dstptr->[i] ^ srcptr->[i] +// next +// srcptr = srcptr + w +// next +//end +export asm hgrXorSrc(ofst, y, w, h, srcptr)#0 + LDA ESTKL+0,X ; SRC PTR + STA SRCL + LDA ESTKH+0,X + STA SRCH +-- LDY ESTKL+3,X ; Y COORD + CPY #192 + BCS + + LDA ESTKL+4,X ; HORIZ OFFSET +end +asm _hgrXorSrc + ADC $8000,Y ; HGRSCANL + STA DSTL + LDA $1000 ; DRAWBUFFH + ADC $9000,Y ; HGRSCANH + STA DSTH + LDY ESTKL+2,X ; WIDTH + DEY +- LDA (SRC),Y + EOR (DST),Y + STA (DST),Y + DEY + BPL - ++ LDA SRCL + CLC + ADC ESTKL+2,X ; WIDTH + STA SRCL + BCC + + INC SRCH ++ INC ESTKL+3,X ; Y COORD + DEC ESTKL+1,X ; HEIGHT + BNE -- + INX + INX + INX + INX + INX + RTS +end +//export def hgrOrSrc(ofst, y, w, h, srcptr)#0 +// word j, dstptr +// byte i +// +// ofst = ofst + drawbuff +// for j = y to y + h - 1 +// dstptr = hgrscan[j] + ofst +// for i = 0 to w - 1 +// dstptr->[i] = dstptr->[i] ^ srcptr->[i] +// next +// srcptr = srcptr + w +// next +//end +export asm hgrOrSrc(ofst, y, w, h, srcptr)#0 + LDA ESTKL+0,X ; SRC PTR + STA SRCL + LDA ESTKH+0,X + STA SRCH +-- LDY ESTKL+3,X ; Y COORD + CPY #192 + BCS + + LDA ESTKL+4,X ; HORIZ OFFSET +end +asm _hgrOrSrc + ADC $8000,Y ; HGRSCANL + STA DSTL + LDA $1000 ; DRAWBUFFH + ADC $9000,Y ; HGRSCANH + STA DSTH + LDY ESTKL+2,X ; WIDTH + DEY +- LDA (SRC),Y + ORA (DST),Y + STA (DST),Y + DEY + BPL - ++ LDA SRCL + CLC + ADC ESTKL+2,X ; WIDTH + STA SRCL + BCC + + INC SRCH ++ INC ESTKL+3,X ; Y COORD + DEC ESTKL+1,X ; HEIGHT + BNE -- + INX + INX + INX + INX + INX + RTS +end +//export def hgrPlot(x, y)#0 +// word pixptr +// byte ofst, pixofst, pmask +// +// ofst, pixofst = divmod7(x) +// pixptr = hgrscan[y] + drawbuff + ofst +// pmask = hbmask[pixofst] +// ^pixptr = (^pixptr & ~pmask) | (curhclr.[ofst & 1] & pmask) +//end +export asm hgrPlot(x, y)#0 + LDY ESTKL+0,X ; Y COORD + CPY #192 + BCS + +end +asm _hgrPlotA + LDA $8000,Y ; HGRSCANL + STA DSTL + LDA $1000 ; DRAWBUFFH + ORA $9000,Y ; HGRSCANH + STA DSTH + INX +end +asm _hgrPlotB + JSR 1000 ; DIVMOD7 + LDY ESTKL+0,X ; PIXEL OFFSET +end +asm _hgrPlotC + LDA $1000,Y ; HBMASK + STA TMPL + EOR #$FF + STA TMPH + LDA ESTKL+1,X ; HORIZ OFFSET + CMP #40 + BCS + + AND #$01 + TAY +end +asm _hgrPlotD + LDA $2000,Y ; CURHCLR + AND TMPL + STA TMPL + LDY ESTKL+1,X ; HORIZ OFFSET + LDA (DST),Y + AND TMPH + ORA TMPL + STA (DST),Y ++ INX + INX + RTS end export def hgrXorPlot(x, y)#0 word pixptr @@ -211,65 +549,6 @@ export def hgrRect(x1, x2, y1, y2)#0 fin fin end -export def hgrCopyDst(ofst, y, w, h, dstptr)#0 - word j, srcptr - - ofst = ofst + drawbuff - for j = y to y + h - 1 - srcptr = hgrscan[j] + ofst - memcpy(dstptr, srcptr, w) - dstptr = dstptr + w - next -end -export def hgrCopySrc(ofst, y, w, h, srcptr)#0 - word j, dstptr - - ofst = ofst + drawbuff - for j = y to y + h - 1 - dstptr = hgrscan[j] + ofst - memcpy(dstptr, srcptr, w) - srcptr = srcptr + w - next -end -export def hgrAndSrc(ofst, y, w, h, srcptr)#0 - word j, dstptr - byte i - - ofst = ofst + drawbuff - for j = y to y + h - 1 - dstptr = hgrscan[j] + ofst - for i = 0 to w - 1 - dstptr->[i] = dstptr->[i] & srcptr->[i] - next - srcptr = srcptr + w - next -end -export def hgrXorSrc(ofst, y, w, h, srcptr)#0 - word j, dstptr - byte i - - ofst = ofst + drawbuff - for j = y to y + h - 1 - dstptr = hgrscan[j] + ofst - for i = 0 to w - 1 - dstptr->[i] = dstptr->[i] ^ srcptr->[i] - next - srcptr = srcptr + w - next -end -export def hgrOrSrc(ofst, y, w, h, srcptr)#0 - word j, dstptr - byte i - - ofst = ofst + drawbuff - for j = y to y + h - 1 - dstptr = hgrscan[j] + ofst - for i = 0 to w - 1 - dstptr->[i] = dstptr->[i] ^ srcptr->[i] - next - srcptr = srcptr + w - next -end export def hgrBLT(x, y, w, h, srcptr)#0 word i, j word saveclr @@ -299,6 +578,9 @@ export def hgrBLT(x, y, w, h, srcptr)#0 next curhclr = saveclr end +export def hgrColor(c)#0 + curhclr = hcolor[c & $07] +end export def hgrMode#1 memset(hgr1, 0, $2000) // Clear HGR page 1 ^showpage1 @@ -334,4 +616,29 @@ export def hgrDrawBuf(page)#0 drawpage = page & 1 drawbuff = hgrbuff[drawpage] end +// +// Assembly fixups +// +_hgrCopyDst:1 = @hgrscanl +_hgrCopyDst:6 = @drawbuff.1 +_hgrCopyDst:9 = @hgrscanh +_hgrCopySrc:1 = @hgrscanl +_hgrCopySrc:6 = @drawbuff.1 +_hgrCopySrc:9 = @hgrscanh +_hgrAndSrc:1 = @hgrscanl +_hgrAndSrc:6 = @drawbuff.1 +_hgrAndSrc:9 = @hgrscanh +_hgrXorSrc:1 = @hgrscanl +_hgrXorSrc:6 = @drawbuff.1 +_hgrXorSrc:9 = @hgrscanh +_hgrOrSrc:1 = @hgrscanl +_hgrOrSrc:6 = @drawbuff.1 +_hgrOrSrc:9 = @hgrscanh +_hgrPlotA:1 = @hgrscanl +_hgrPlotA:6 = @drawbuff.1 +_hgrPlotA:9 = @hgrscanh +_hgrPlotB:1 = @divmod7 +_hgrPlotC:1 = @hbmask +_hgrPlotD:1 = @curhclr + done From 755c4b424a0e81db5489922187297b74b1e81fdd Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 26 Dec 2019 16:01:38 -0800 Subject: [PATCH 078/149] Assembly-ize some rotuines --- src/libsrc/apple/hgrlib.pla | 415 ++++++++++++++++++++++++++---------- src/makefile | 5 - 2 files changed, 308 insertions(+), 112 deletions(-) diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index 02ffb54..b45e985 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -157,6 +157,21 @@ export asm divmod7(x)#2 STA ESTKH+1,X RTS end +//export def hgrColor(c)#0 +// curhclr = hcolor[c & $07] +//end +export asm hgrColor(c)#0 + LDA ESTKL+0,X ; COLOR + AND #$07 + ASL + TAY + LDA $1000,Y ; HCOLORL + STA $2000 ; CURHCLRL + LDA $1001,Y ; HCOLORH + STA $2001 ; CRHCLRH + INX + RTS +end //export def hgrCopyDst(ofst, y, w, h, dstptr)#0 // word j, srcptr // @@ -459,94 +474,256 @@ asm _hgrPlotD INX RTS end -export def hgrXorPlot(x, y)#0 - word pixptr - byte ofst, pixofst, pmask - - ofst, pixofst = divmod7(x) - pixptr = hgrscan[y] + drawbuff + ofst - pmask = hbmask[pixofst] - ^pixptr = ^pixptr ^ (curhclr.[ofst & 1] & pmask) +//export def hgrXorPlot(x, y)#0 +// word pixptr +// byte ofst, pixofst, pmask +// +// ofst, pixofst = divmod7(x) +// pixptr = hgrscan[y] + drawbuff + ofst +// pmask = hbmask[pixofst] +// ^pixptr = ^pixptr ^ (curhclr.[ofst & 1] & pmask) +//end +export asm hgrXorPlot(x, y)#0 + LDY ESTKL+0,X ; Y COORD + CPY #192 + BCS + end -export def hgrHlin(x1, x2, y)#0 - word pixptr, x - byte lofst, lpixofst, lpmask - byte rofst, rpixofst, rpmask - - if x1 == x2 - hgrPlot(x1, y) - else - lofst, lpixofst = divmod7(x1) - pixptr = hgrscan[y] + drawbuff + lofst - rofst, rpixofst = divmod7(x2) - lpmask = hlmask[lpixofst] - rpmask = hrmask[rpixofst] - if lofst == rofst - lpmask = lpmask & rpmask - ^pixptr = (^pixptr & ~lpmask) | (curhclr.[pixptr.0 & 1] & lpmask) - else - ^pixptr = (^pixptr & ~lpmask) | (curhclr.[pixptr.0 & 1] & lpmask) - pixptr++ - for x = lofst + 1 to rofst - 1 - ^pixptr = curhclr.[pixptr.0 & 1] - pixptr++ - next - ^pixptr = (^pixptr & ~rpmask) | (curhclr.[pixptr.0 & 1] & rpmask) - fin - fin +asm _hgrXorPlotA + LDA $8000,Y ; HGRSCANL + STA DSTL + LDA $1000 ; DRAWBUFFH + ORA $9000,Y ; HGRSCANH + STA DSTH + INX end -export def hgrVlin(y1, y2, x)#0 - word pixptr, y, ofst - byte pixofst, pmask, cmask - - if y1 == y2 - hgrPlot(x, y1) - else - ofst, pixofst = divmod7(x) - ofst = ofst + drawbuff - pmask = hbmask[pixofst] - cmask = curhclr.[ofst & 1] & pmask - pmask = ~pmask - for y = y1 to y2 - pixptr = hgrscan[y] + ofst - ^pixptr = (^pixptr & pmask) | cmask - next - fin +asm _hgrXorPlotB + JSR 1000 ; DIVMOD7 + LDY ESTKL+0,X ; PIXEL OFFSET +end +asm _hgrXorPlotC + LDA $1000,Y ; HBMASK + STA TMPL + LDA ESTKL+1,X ; HORIZ OFFSET + CMP #40 + BCS + + AND #$01 + TAY +end +asm _hgrXorPlotD + LDA $2000,Y ; CURHCLR + AND TMPL + LDY ESTKL+1,X ; HORIZ OFFSET + EOR (DST),Y + STA (DST),Y ++ INX + INX + RTS +end +//export def hgrHLin(x1, x2, y)#0 +// word pixptr, x +// byte lofst, lpixofst, lpmask +// byte rofst, rpixofst, rpmask +// +// if x1 == x2 +// hgrPlot(x1, y) +// else +// lofst, lpixofst = divmod7(x1) +// pixptr = hgrscan[y] + drawbuff + lofst +// rofst, rpixofst = divmod7(x2) +// lpmask = hlmask[lpixofst] +// rpmask = hrmask[rpixofst] +// if lofst == rofst +// lpmask = lpmask & rpmask +// ^pixptr = (^pixptr & ~lpmask) | (curhclr.[pixptr.0 & 1] & lpmask) +// else +// ^pixptr = (^pixptr & ~lpmask) | (curhclr.[pixptr.0 & 1] & lpmask) +// pixptr++ +// for x = lofst + 1 to rofst - 1 +// ^pixptr = curhclr.[pixptr.0 & 1] +// pixptr++ +// next +// ^pixptr = (^pixptr & ~rpmask) | (curhclr.[pixptr.0 & 1] & rpmask) +// fin +// fin +//end +export asm hgrHLin(x1, x2, y)#0 + LDA ESTKL+1 + CMP ESTKL+2 + BNE + + LDA ESTKH+1 + CMP ESTKH+2 + BNE + + LDA ESTKL+0 + STA ESTKL+1 + LDA ESTKH+0 + STA ESTKH+1 + INX +end +asm _hgrHLinA + JMP $F000 ++ LDY ESTKL+0,X ; Y COORD + CPY #192 + BCS + +end +asm _hgrHLinB + LDA $8000,Y ; HGRSCANL + STA DSTL + LDA $1000 ; DRAWBUFFH + ORA $9000,Y ; HGRSCANH + STA DSTH + LDA ESTKL+1,X + STA ESTKL+0,X + LDA ESTKH+1,X + STA ESTKH+0,X +end +asm _hgrHLinC + JSR 1000 ; DIVMOD7 + LDY ESTKL+0,X ; RIGHT PIXEL OFFSET +end +asm _hgrHLinD + LDA $1000,Y ; HRMASK + STA TMPH + INX + INX + INX +end +asm _hgrHLinE + JSR 1000 ; DIVMOD7 + LDY ESTKL+0,X ; LEFT PIXEL OFFSET +end +asm _hgrHLinF + LDA $1000,Y ; HLMASK + STA TMPL + LDA ESTKL+1,X ; LEFT HORIZ OFFSET + TAY + LSR + BCS + +end +asm _hgrHLinG + LDA $2000 ; CURHCLRL + STA SRCL + LDA $2001 ; CURHCLRH + STA SRCH + BCC ++ ++ LDA $2000 ; CURHCLRL + STA SRCH + LDA $2001 ; CURHCLRH + STA SRCL +++ TYA + CMP ESTKL-1,X ; RIGHT HORIZ OFFSET + BNE + + LDA TMPL + AND TMPH + STA TMPL + AND SRCL + STA TMPH + LDA TMPL + EOR #$FF + AND (DST),Y + ORA TMPH + STA (DST),Y + INX + INX + RTS ++ LDA SRCL ; CURHCLR + AND TMPL + STA ESTKL+0,X + LDA TMPL + EOR #$FF + AND (DST),Y + ORA ESTKL+0,X +- STA (DST),Y + INY + TYA + CMP ESTKL-1,X ; RIGHT HORIZ OFFSET + LDA SRCH + BCS + + STA (DST),Y + INY + TYA + CMP ESTKL-1,X ; RIGHT HORIZ OFFSET + LDA SRCL + BCC - ++ AND TMPH + STA ESTKL+0,X + LDA TMPH + EOR #$FF + AND (DST),Y + ORA ESTKL+0,X + STA (DST),Y + INX + INX + RTS +end +//export def hgrVlin(y1, y2, x)#0 +// word pixptr, y, ofst +// byte pixofst, pmask, cmask +// +// if y1 == y2 +// hgrPlot(x, y1) +// else +// ofst, pixofst = divmod7(x) +// ofst = ofst + drawbuff +// pmask = hbmask[pixofst] +// cmask = curhclr.[ofst & 1] & pmask +// pmask = ~pmask +// for y = y1 to y2 +// pixptr = hgrscan[y] + ofst +// ^pixptr = (^pixptr & pmask) | cmask +// next +// fin +//end +export asm hgrVlin(y1, y2, x)#0 + JSR 1000 ; DIVMOD7 + LDY ESTKL+0,X ; PIXEL OFFSET +end +asm _hgrVLinA + LDA $1000,Y ; HBMASK + STA TMPL + EOR #$FF + STA TMPH + LDA ESTKL+1,X ; HORIZ OFFSET + AND #$01 + TAY +end +asm _hgrVLinB + LDA $2000,Y ; CURHCLR + AND TMPL + STA TMPL + LDY ESTKL+3,X ; Y1 COORD +end +asm _hgrVLinC +- LDA $8000,Y ; HGRSCANL + STA DSTL + LDA $1000 ; DRAWBUFFH + ORA $9000,Y ; HGRSCANH + STA DSTH + LDY ESTKL+1,X ; HORIZ OFFSET + LDA (DST),Y + AND TMPH + ORA TMPL + STA (DST),Y + LDY ESTKL+3,X ; Y1 COORD + TYA + INY + STY ESTKL+3,X ; Y1 COORD + CMP ESTKL+2,X ; Y2 COORD + BNE - + INX + INX + INX + INX + RTS end export def hgrRect(x1, x2, y1, y2)#0 - word pixptr, x, y, lofst, rofst - byte lpixofst, lpmask, cmask - byte rpixofst, rpmask + word y if x1 == x2 hgrVLin(y1, y2, x1) else - lofst, lpixofst = divmod7(x1) - rofst, rpixofst = divmod7(x2) - lofst = lofst + drawbuff - rofst = rofst + drawbuff - lpmask = hlmask[lpixofst] - rpmask = hrmask[rpixofst] - if lofst == rofst - lpmask = lpmask & rpmask - cmask = curhclr.[pixptr.0 & 1] & lpmask - lpmask = ~lpmask - for y = y1 to y2 - pixptr = hgrscan[y] + lofst - ^pixptr = (^pixptr & lpmask) | cmask - next - else - for y = y1 to y2 - pixptr = hgrscan[y] + lofst - ^pixptr = (^pixptr & ~lpmask) | (curhclr.[pixptr.0 & 1] & lpmask) - pixptr++ - for x = lofst + 1 to rofst - 1 - ^pixptr = curhclr.[pixptr.0 & 1] - pixptr++ - next - ^pixptr = (^pixptr & ~rpmask) | (curhclr.[pixptr.0 & 1] & rpmask) - next - fin + for y = y1 to y2 + hgrHLin(x1, x2, y) + next fin end export def hgrBLT(x, y, w, h, srcptr)#0 @@ -559,14 +736,14 @@ export def hgrBLT(x, y, w, h, srcptr)#0 for i = 0 to w - 1 c = srcptr->[i >> 1] if i & 1 - curhclr = hcolor[c & $07] + hgrColor(c) if c & $08 hgrXorPlot(x + i, j) else hgrPlot(x + i, j) fin else - curhclr = hcolor[(c >> 4) & $07] + hgrColor(c >> 4) if c & $80 hgrXorPlot(x + i, j) else @@ -578,9 +755,6 @@ export def hgrBLT(x, y, w, h, srcptr)#0 next curhclr = saveclr end -export def hgrColor(c)#0 - curhclr = hcolor[c & $07] -end export def hgrMode#1 memset(hgr1, 0, $2000) // Clear HGR page 1 ^showpage1 @@ -619,26 +793,53 @@ end // // Assembly fixups // -_hgrCopyDst:1 = @hgrscanl -_hgrCopyDst:6 = @drawbuff.1 -_hgrCopyDst:9 = @hgrscanh -_hgrCopySrc:1 = @hgrscanl -_hgrCopySrc:6 = @drawbuff.1 -_hgrCopySrc:9 = @hgrscanh -_hgrAndSrc:1 = @hgrscanl -_hgrAndSrc:6 = @drawbuff.1 -_hgrAndSrc:9 = @hgrscanh -_hgrXorSrc:1 = @hgrscanl -_hgrXorSrc:6 = @drawbuff.1 -_hgrXorSrc:9 = @hgrscanh -_hgrOrSrc:1 = @hgrscanl -_hgrOrSrc:6 = @drawbuff.1 -_hgrOrSrc:9 = @hgrscanh -_hgrPlotA:1 = @hgrscanl -_hgrPlotA:6 = @drawbuff.1 -_hgrPlotA:9 = @hgrscanh -_hgrPlotB:1 = @divmod7 -_hgrPlotC:1 = @hbmask -_hgrPlotD:1 = @curhclr - +_hgrCopyDst:1 = @hgrscanl +_hgrCopyDst:6 = @drawbuff.1 +_hgrCopyDst:9 = @hgrscanh +_hgrCopySrc:1 = @hgrscanl +_hgrCopySrc:6 = @drawbuff.1 +_hgrCopySrc:9 = @hgrscanh +_hgrAndSrc:1 = @hgrscanl +_hgrAndSrc:6 = @drawbuff.1 +_hgrAndSrc:9 = @hgrscanh +_hgrXorSrc:1 = @hgrscanl +_hgrXorSrc:6 = @drawbuff.1 +_hgrXorSrc:9 = @hgrscanh +_hgrOrSrc:1 = @hgrscanl +_hgrOrSrc:6 = @drawbuff.1 +_hgrOrSrc:9 = @hgrscanh +_hgrPlotA:1 = @hgrscanl +_hgrPlotA:6 = @drawbuff.1 +_hgrPlotA:9 = @hgrscanh +_hgrPlotB:1 = @divmod7 +_hgrPlotC:1 = @hbmask +_hgrPlotD:1 = @curhclr +_hgrXorPlotA:1 = @hgrscanl +_hgrXorPlotA:6 = @drawbuff.1 +_hgrXorPlotA:9 = @hgrscanh +_hgrXorPlotB:1 = @divmod7 +_hgrXorPlotC:1 = @hbmask +_hgrXorPlotD:1 = @curhclr +_hgrHLinA:1 = @hgrPlot +_hgrHLinB:1 = @hgrscanl +_hgrHLinB:6 = @drawbuff.1 +_hgrHLinB:9 = @hgrscanh +_hgrHLinC:1 = @divmod7 +_hgrHLinD:1 = @hrmask +_hgrHLinE:1 = @divmod7 +_hgrHLinF:1 = @hlmask +_hgrHLinG:1 = @curhclr +_hgrHLinG:6 = @curhclr.1 +_hgrHLinG:13 = @curhclr.1 +_hgrHLinG:18 = @curhclr +hgrVLin:1 = @divmod7 +_hgrVLinA:1 = @hbmask +_hgrVLinB:1 = @curhclr +_hgrVLinC:1 = @hgrscanl +_hgrVLinC:6 = @drawbuff.1 +_hgrVLinC:9 = @hgrscanh +hgrColor:7 = @hcolor +hgrColor:10 = @curhclr +hgrColor:13 = @hcolor.1 +hgrColor:16 = @curhclr.1 done diff --git a/src/makefile b/src/makefile index 07274c0..024272f 100755 --- a/src/makefile +++ b/src/makefile @@ -70,7 +70,6 @@ MON = rel/apple/MON\#FE1000 HGRTEST = rel/apple/HGRTEST\#FE1000 GRTEST = rel/apple/GRTEST\#FE1000 DGRTEST = rel/apple/DGRTEST\#FE1000 -HGRTEST = rel/apple/HGRTEST\#FE1000 MEMMGR = rel/MEMMGR\#FE1000 MEMTEST = rel/MEMTEST\#FE1000 FIBERTEST = rel/FIBERTEST\#FE1000 @@ -429,10 +428,6 @@ $(DGRTEST): samplesrc/dgrtest.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/dgrtest.pla > samplesrc/dgrtest.a acme --setpc 4094 -o $(DGRTEST) samplesrc/dgrtest.a -$(HGRTEST): samplesrc/hgrtest.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AMOW < samplesrc/hgrtest.pla > samplesrc/hgrtest.a - acme --setpc 4094 -o $(HGRTEST) samplesrc/hgrtest.a - $(MON): utilsrc/apple/mon.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < utilsrc/apple/mon.pla > utilsrc/apple/mon.a acme --setpc 4094 -o $(MON) utilsrc/apple/mon.a From f829682876ad921c31af7efa7a92fa35d6d7c265 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 26 Dec 2019 19:21:04 -0800 Subject: [PATCH 079/149] Assembly-ize mahorline --- src/libsrc/linespans.pla | 198 ++++++++++++++++++++++++++++++++++----- 1 file changed, 175 insertions(+), 23 deletions(-) diff --git a/src/libsrc/linespans.pla b/src/libsrc/linespans.pla index 4f6a745..7e3c0c8 100644 --- a/src/libsrc/linespans.pla +++ b/src/libsrc/linespans.pla @@ -5,34 +5,158 @@ var hspan = @nopLin var vspan = @nopLin var err, shorterr, shortlen, longerr, longlen -def nopLin(a, b, c)#0 +//def nopLin(a, b, c)#0 +//end +//def majorline(majorstart, major, majorend, minor, dir, majorspan)#0 +// // +// // Initial half-span step +// // +// err = err + shorterr +// repeat +// majorspan(majorstart, major, minor)#0 +// minor = minor + dir // Move to next span +// majorstart = major + 1 // Start of next span = end of previous + 1 +// if err >= 0 // Short span +// err = err + shorterr +// major = major + shortlen +// else // Long span +// err = err + longerr +// major = major + longlen +// fin +// until major >= majorend +// // +// // Final half-span step +// // +// majorspan(majorstart, majorend, minor)#0 +//end +asm majorline(majorstart, major, majorend, minor, dir, majorspan)#0 +!SOURCE "vmsrc/plvmzp.inc" + LDA $1000 ; ERRL + CLC + ADC $2000 ; SHORTERRL + STA $1000 ; ERRL + LDA $1001 ; ERRH + ADC $2001 ; SHORTERRH + STA $1001 ; ERRH +end +asm _majorlineA +- DEX + DEX + DEX + LDA ESTKL+8,X ; MAJORSTARTL + STA ESTKL+2,X + LDA ESTKH+8,X ; MAJORSTARTH + STA ESTKH+2,X + LDA ESTKL+7,X ; MAJORL + STA ESTKL+1,X + LDA ESTKH+7,X ; MAJORH + STA ESTKH+1,X + LDA ESTKL+5,X ; MINORL + STA ESTKL+0,X + LDA ESTKH+5,X ; MINORH + STA ESTKH+0,X + LDA ESTKL+3,X ; MAJORSPANL + STA TMPL + LDA ESTKH+3,X ; MAJORSPANH + STA TMPH + JSR JMPTMP + + LDA ESTKL+2,X ; MINORL + CLC + ADC ESTKL+1,X ; DIRL + STA ESTKL+2,X + LDA ESTKH+2,X ; MINORH + ADC ESTKH+1,X ; DIRH + STA ESTKH+2,X + + LDA ESTKL+4,X ; MAJORL + CLC + ADC #$01 + STA ESTKL+5,X ; MAJORSTARTL + LDA ESTKH+4,X ; MAJORH + ADC #$00 + STA ESTKH+5,X ; MAJORSTARTH +end +asm _majorlineB + LDA $1001 ; ERRH + BMI + +end +asm _majorlineC + LDA $1000 ; ERRL + CLC + ADC $2000 ; SHORTERRL + STA $1000 ; ERRL + LDA $1001 ; ERRH + ADC $2001 ; SHORTERRH + STA $1001 ; ERRH + LDA ESTKL+4,X ; MAJORL + CLC + ADC $3000 ; SHORTLENL + STA ESTKL+4,X + LDA ESTKH+4,X ; MAJORH + ADC $3001 ; SHORTLENH + STA ESTKH+4,X + BCC ++ + BCS ++ +end +asm _majorlineD ++ LDA $1000 ; ERRL + CLC + ADC $4000 ; LONGERRL + STA $1000 ; ERRL + LDA $1001 ; ERRH + ADC $4001 ; LONGERRL + STA $1001 ; ERRH + LDA ESTKL+4,X ; MAJORL + CLC + ADC $5000 ; LONGLENL + STA ESTKL+4,X + LDA ESTKH+4,X ; MAJORH + ADC $5001 ; LONGLENH + STA ESTKH+4,X + +++ LDA ESTKL+4,X ; MAJORL + CMP ESTKL+3,X ; MAJORENDL + LDA ESTKH+4,X ; MAJORH + SBC ESTKH+3,X ; MAJORENDH + BCS + +end +asm _majorlineE + JMP $6000 ++ DEX + DEX + DEX + LDA ESTKL+8,X ; MAJORSTARTL + STA ESTKL+2,X + LDA ESTKH+8,X ; MAJORSTARTH + STA ESTKH+2,X + LDA ESTKL+6,X ; MAJORENDL + STA ESTKL+1,X + LDA ESTKH+6,X ; MAJORENDH + STA ESTKH+1,X + LDA ESTKL+5,X ; MINORL + STA ESTKL+0,X + LDA ESTKH+5,X ; MINORH + STA ESTKH+0,X + LDA ESTKL+3,X ; MAJORSPANL + STA TMPL + LDA ESTKH+3,X ; MAJORSPANH + STA TMPH + JSR JMPTMP + INX + INX + INX +end +asm nopLin(a, b, c)#0 + INX + INX + INX + RTS end export def setlinespans(h, v)#0 hspan = h vspan = v end -def majorline(majorstart, major, majorend, minor, dir, majorspan)#0 - // - // Initial half-span step - // - err = err + shorterr - repeat - majorspan(majorstart, major, minor)#0 - minor = minor + dir // Move to next span - majorstart = major + 1 // Start of next span = end of previous + 1 - if err >= 0 // Short span - err = err + shorterr - major = major + shortlen - else // Long span - err = err + longerr - major = major + longlen - fin - until major >= majorend - // - // Final half-span step - // - majorspan(majorstart, majorend, minor)#0 -end export def linetospans(x1, y1, x2, y2)#0 var dx, dy, dx2, dy2, halflen, rem, sx, sy @@ -107,3 +231,31 @@ export def linetospans(x1, y1, x2, y2)#0 majorline(y1, y1 + halflen, y2, x1, sx, vspan) fin end +// +// Assembly fixups +// +majorline:1 = @err +majorline:5 = @shorterr +majorline:8 = @err +majorline:11 = @err.1 +majorline:14 = @shorterr.1 +majorline:17 = @err.1 +_majorlineB:1 = @err.1 +_majorlineC:1 = @err +_majorlineC:5 = @shorterr +_majorlineC:8 = @err +_majorlineC:11 = @err.1 +_majorlineC:14 = @shorterr.1 +_majorlineC:17 = @err.1 +_majorlineC:23 = @shortlen +_majorlineC:30 = @shortlen.1 +_majorlineD:1 = @err +_majorlineD:5 = @longerr +_majorlineD:8 = @err +_majorlineD:11 = @err.1 +_majorlineD:14 = @longerr.1 +_majorlineD:17 = @err.1 +_majorlineD:23 = @longlen +_majorlineD:30 = @longlen.1 +_majorlineE:1 = @_majorlineA +done From 4186c5170d7c3facc203daa5dc4d076d6d1b6dfa Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 26 Dec 2019 21:13:46 -0800 Subject: [PATCH 080/149] Break out sprite library --- src/inc/hgrlib.plh | 2 +- src/inc/sprite.plh | 15 +++ src/libsrc/apple/hgrlib.pla | 7 +- src/libsrc/apple/sprite.pla | 185 ++++++++++++++++++++++++++++++++++++ src/libsrc/linespans.pla | 22 +++-- src/makefile | 7 +- src/mkrel | 2 + src/samplesrc/hgrtest.pla | 184 ++++------------------------------- 8 files changed, 241 insertions(+), 183 deletions(-) create mode 100644 src/inc/sprite.plh create mode 100644 src/libsrc/apple/sprite.pla diff --git a/src/inc/hgrlib.plh b/src/inc/hgrlib.plh index 54c0979..14af0ec 100644 --- a/src/inc/hgrlib.plh +++ b/src/inc/hgrlib.plh @@ -16,6 +16,6 @@ import hgrlib predef hgrClear#0 predef hgrShow(page)#1 predef hgrSwap#1 - predef hgrDrawBuf(page)#0 + predef hgrDrawBuf(page)#1 predef hgrColor(clr)#0 end diff --git a/src/inc/sprite.plh b/src/inc/sprite.plh new file mode 100644 index 0000000..79ae215 --- /dev/null +++ b/src/inc/sprite.plh @@ -0,0 +1,15 @@ +import sprite + predef spriteCompile(w, h, srcptr)#1 + predef spriteDup(sprtsrc)#1 + predef spriteDraw(sprtptr)#0 + predef spriteDrawXor(sprtptr)#0 + predef spriteUnDraw(sprtptr)#0 + predef spriteUnDrawXor(sprtptr)#0 + predef spritePos(x, y, sprtptr)#0 + predef spritePosIndex(x, y, i)#0 + predef spriteDrawList#0 + predef spriteDrawXorList#0 + predef spriteAdd(i, sprtptr)#1 + predef spriteDel(i)#1 + predef spriteDrawBuf(page)#0 +end diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index b45e985..e830d82 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -112,10 +112,6 @@ byte = $88, $8F, $FF, $F8, $88 asm grInc(buff) !SOURCE "vmsrc/plvmzp.inc" -GBASL = $26 -GBASH = $27 -GBASE = GBASL -GCLR = $30 end export asm divmod7(x)#2 @@ -786,9 +782,10 @@ export def hgrSwap#1 drawbuff = hgrbuff[drawpage] return drawpage end -export def hgrDrawBuf(page)#0 +export def hgrDrawBuf(page)#1 drawpage = page & 1 drawbuff = hgrbuff[drawpage] + return drawpage end // // Assembly fixups diff --git a/src/libsrc/apple/sprite.pla b/src/libsrc/apple/sprite.pla new file mode 100644 index 0000000..6bcc86f --- /dev/null +++ b/src/libsrc/apple/sprite.pla @@ -0,0 +1,185 @@ +include "inc/cmdsys.plh" +include "inc/hgrlib.plh" + +struc t_sprite + var s_xpos + var s_ypos + byte s_undermap[2] + byte s_underofst[2] + byte s_undery[2] + byte s_pitch +// var s_width + var s_height + var s_size + var s_mask[14] + var s_map[14] + var s_under[14] +end + +var spriteList[16] +byte drawpage +// +// Sprite routines +// +def spriteBLTMask(x, y, w, h, srcptr)#0 + word i, j + byte c + + for j = y to y + h - 1 + for i = 0 to w - 1 + c = srcptr->[i >> 1] + if i & 1 + hgrColor(c & $08 ?? 3 :: 0) + else + hgrColor(c & $80 ?? 3 :: 0) + fin + hgrPlot(x + i, j) + next + srcptr = srcptr + (w + 1) / 2 + next +end +export def spriteCompile(w, h, srcptr)#1 + var sprtptr, bytewidth, spritesize, i + + sprtptr = heapalloc(t_sprite) + bytewidth = (w + 7) / 7 + 1 + sprtptr->s_pitch = bytewidth + spritesize = bytewidth * h + sprtptr=>s_size = spritesize +// sprtptr=>s_width = w + sprtptr=>s_height = h + sprtptr=>s_under[0] = heapalloc(spritesize) + sprtptr=>s_under[1] = heapalloc(spritesize) + for i = 0 to 13 + sprtptr=>s_map[i] = heapalloc(spritesize) + sprtptr=>s_mask[i] = heapalloc(spritesize) + hgrColor(0) + hgrRect(0, w + 21, 0, h - 1) + hgrBLT(i, 0, w, h, srcptr) + hgrCopyDst(i > 6 ?? 1 :: 0, 0, bytewidth, h, sprtptr=>s_map[i]) + hgrColor(3) + hgrRect(0, w + 21, h, h * 2 - 1) + spriteBLTMask(i, h, w, h, srcptr) + hgrCopyDst(i > 6 ?? 1 :: 0, h, bytewidth, h, sprtptr=>s_mask[i]) + next + sprtptr->s_underofst[0] = 255 // Mark as under not valid + sprtptr->s_underofst[1] = 255 + return sprtptr +end +export def spriteDup(sprtsrc)#1 + var sprtdup, spritesize + byte i + + sprtdup = heapalloc(t_sprite) + spritesize = sprtsrc=>s_size + sprtdup=>s_size = spritesize + sprtdup->s_pitch = sprtsrc->s_pitch +// sprtdup=>s_width = sprtsrc=>s_width + sprtdup=>s_height = sprtsrc=>s_height + sprtdup=>s_under[0] = heapalloc(spritesize) + sprtdup=>s_under[1] = heapalloc(spritesize) + for i = 0 to 13 + sprtdup=>s_map[i] = sprtsrc=>s_map[i] + sprtdup=>s_mask[i] = sprtsrc=>s_mask[i] + next + sprtdup->s_underofst[0] = 255 // Mark as under not valid + sprtdup->s_underofst[1] = 255 + return sprtdup +end +export def spriteDraw(sprtptr)#0 + byte ofst, map, y + var width, height + + y = sprtptr->s_ypos + ofst, map = divmod7(sprtptr=>s_xpos) + if ofst & 1 + map = map + 7 + fin + sprtptr->s_underofst[drawpage] = ofst + sprtptr->s_undery[drawpage] = y + width = sprtptr->s_pitch + height = sprtptr=>s_height + hgrCopyDst(ofst, y, width, height, sprtptr=>s_under[drawpage]) + hgrAndSrc( ofst, y, width, height, sprtptr=>s_mask[map]) + hgrXorSrc( ofst, y, width, height, sprtptr=>s_map[map]) +end +export def spriteUnDraw(sprtptr)#0 + if sprtptr->s_underofst[drawpage] < 40 + hgrCopySrc(sprtptr->s_underofst[drawpage], sprtptr->s_undery[drawpage], sprtptr->s_pitch, sprtptr=>s_height, sprtptr=>s_under[drawpage]) + fin +end +export def spriteDrawXor(sprtptr)#0 + byte ofst, map, y + var width, height + + y = sprtptr->s_ypos + ofst, map = divmod7(sprtptr=>s_xpos) + if ofst & 1 + map = map + 7 + fin + sprtptr->s_undermap[drawpage] = map + sprtptr->s_underofst[drawpage] = ofst + sprtptr->s_undery[drawpage] = y + width = sprtptr->s_pitch + height = sprtptr=>s_height + hgrXorSrc( ofst, y, width, height, sprtptr=>s_map[map]) +end +export def spriteUnDrawXor(sprtptr)#0 + if sprtptr->s_underofst[drawpage] < 40 + hgrXorSrc(sprtptr->s_underofst[drawpage], sprtptr->s_undery[drawpage], sprtptr->s_pitch, sprtptr=>s_height, sprtptr=>s_map[sprtptr->s_undermap[drawpage]]) + fin +end +export def spritePos(x, y, sprtptr)#0 + sprtptr=>s_ypos = y + sprtptr=>s_xpos = x +end +export def spritePosIndex(x, y, i)#0 + i = i & 15 + if spriteList[i] + spriteList[i]=>s_ypos = y + spriteList[i]=>s_xpos = x + fin +end +export def spriteDrawList#0 + byte i + + for i = 15 downto 0 + if spriteList[i] + spriteUnDraw(spriteList[i]) + fin + next + for i = 0 to 15 + if spriteList[i] + spriteDraw(spriteList[i]) + fin + next +end +export def spriteDrawXorList#0 + byte i + for i = 0 to 15 + if spriteList[i] + spriteUnDrawXor(spriteList[i]) + spriteDrawXor(spriteList[i]) + fin + next +end +export def spriteAdd(i, sprtptr)#1 + var sprtprev + + i = i & 15 + sprtprev = spriteList[i] + spriteList[i] = sprtptr + return sprtprev +end +export def spriteDel(i)#1 + var sprtprev + + i = i & 15 + sprtprev = spriteList[i] + spriteList[i] = 0 + return sprtprev +end +export def spriteDrawBuf(page)#0 + drawpage = page & 1 +end +done diff --git a/src/libsrc/linespans.pla b/src/libsrc/linespans.pla index 7e3c0c8..343c80e 100644 --- a/src/libsrc/linespans.pla +++ b/src/libsrc/linespans.pla @@ -38,6 +38,12 @@ asm majorline(majorstart, major, majorend, minor, dir, majorspan)#0 LDA $1001 ; ERRH ADC $2001 ; SHORTERRH STA $1001 ; ERRH + LDA ESTKL+0,X ; MAJORSPANL + STA $A000 + STA $B000 + LDA ESTKH+0,X ; MAJORSPANH + STA $A001 + STA $B001 end asm _majorlineA - DEX @@ -55,11 +61,7 @@ asm _majorlineA STA ESTKL+0,X LDA ESTKH+5,X ; MINORH STA ESTKH+0,X - LDA ESTKL+3,X ; MAJORSPANL - STA TMPL - LDA ESTKH+3,X ; MAJORSPANH - STA TMPH - JSR JMPTMP + JSR $A000 LDA ESTKL+2,X ; MINORL CLC @@ -138,11 +140,7 @@ asm _majorlineE STA ESTKL+0,X LDA ESTKH+5,X ; MINORH STA ESTKH+0,X - LDA ESTKL+3,X ; MAJORSPANL - STA TMPL - LDA ESTKH+3,X ; MAJORSPANH - STA TMPH - JSR JMPTMP + JSR $B000 INX INX INX @@ -240,6 +238,10 @@ majorline:8 = @err majorline:11 = @err.1 majorline:14 = @shorterr.1 majorline:17 = @err.1 +majorline:22 = @_majorlineA.28 +majorline:25 = @_majorlineE.31 +majorline:30 = @_majorlineA.29 +majorline:33 = @_majorlineE.32 _majorlineB:1 = @err.1 _majorlineC:1 = @err _majorlineC:5 = @shorterr diff --git a/src/makefile b/src/makefile index 024272f..77724ff 100755 --- a/src/makefile +++ b/src/makefile @@ -58,6 +58,7 @@ TFTPD = rel/TFTPD\#FE1000 HGRLIB = rel/apple/HGRLIB\#FE1000 GRLIB = rel/apple/GRLIB\#FE1000 DGRLIB = rel/apple/DGRLIB\#FE1000 +SPRITE = rel/apple/SPRITE\#FE1000 LINESPANS = rel/apple/LINESPANS\#FE1000 GRAFIX = rel/apple/GRAFIX\#FE1000 GFXDEMO = rel/apple/GFXDEMO\#FE1000 @@ -99,7 +100,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(SPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -416,6 +417,10 @@ $(DGRLIB): libsrc/apple/dgrlib.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/dgrlib.pla > libsrc/apple/dgrlib.a acme --setpc 4094 -o $(DGRLIB) libsrc/apple/dgrlib.a +$(SPRITE): libsrc/apple/sprite.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < libsrc/apple/sprite.pla > libsrc/apple/sprite.a + acme --setpc 4094 -o $(SPRITE) libsrc/apple/sprite.a + $(HGRTEST): samplesrc/hgrtest.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/hgrtest.pla > samplesrc/hgrtest.a acme --setpc 4094 -o $(HGRTEST) samplesrc/hgrtest.a diff --git a/src/mkrel b/src/mkrel index 04516f9..f36d594 100755 --- a/src/mkrel +++ b/src/mkrel @@ -10,6 +10,7 @@ mkdir prodos/sys cp rel/apple/FILEIO#FE1000 prodos/sys/FILEIO.REL cp rel/apple/CONIO#FE1000 prodos/sys/CONIO.REL cp rel/apple/LINESPANS#FE1000 prodos/sys/LINESPANS.REL +cp rel/apple/SPRITE#FE1000 prodos/sys/SPRITE.REL cp rel/apple/HGRLIB#FE1000 prodos/sys/HGRLIB.REL cp rel/apple/GRLIB#FE1000 prodos/sys/GRLIB.REL cp rel/apple/DGRLIB#FE1000 prodos/sys/DGRLIB.REL @@ -150,6 +151,7 @@ cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT cp inc/cmdsys.plh prodos/bld/inc/CMDSYS.PLH.TXT cp inc/conio.plh prodos/bld/inc/CONIO.PLH.TXT cp inc/linespans.plh prodos/bld/inc/LINESPANS.PLH.TXT +cp inc/sprite.plh prodos/bld/inc/SPRITE.PLH.TXT cp inc/hgrlib.plh prodos/bld/inc/HGRLIB.PLH.TXT cp inc/grlib.plh prodos/bld/inc/GRLIB.PLH.TXT cp inc/dgrlib.plh prodos/bld/inc/DGRLIB.PLH.TXT diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index d13fa0a..905bc00 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -1,178 +1,30 @@ include "inc/cmdsys.plh" include "inc/hgrlib.plh" +include "inc/sprite.plh" include "inc/linespans.plh" sysflags reshgr1|reshgr2 // Reserve HGR page 1 and 2 -struc t_sprite - var s_xpos - var s_ypos - byte s_underofst[2] - var s_undery[2] - var s_width - var s_height - var s_pitch - var s_size - var s_mask[14] - var s_map[14] - var s_under[14] -end - -var spriteList[16] -byte ball = $88, $83, $33, $38, $88 -byte = $88, $33, $11, $33, $88 -byte = $83, $31, $11, $13, $38 -byte = $33, $11, $11, $11, $33 -byte = $33, $11, $11, $11, $33 -byte = $33, $11, $11, $11, $33 -byte = $33, $11, $11, $11, $33 -byte = $83, $31, $11, $13, $38 -byte = $88, $33, $11, $33, $88 -byte = $88, $83, $33, $38, $88 +byte ball = $88, $83, $33, $38, $88 +byte = $88, $33, $11, $33, $88 +byte = $83, $31, $11, $13, $38 +byte = $33, $11, $11, $11, $33 +byte = $33, $11, $11, $11, $33 +byte = $33, $11, $11, $11, $33 +byte = $33, $11, $11, $11, $33 +byte = $83, $31, $11, $13, $38 +byte = $88, $33, $11, $33, $88 +byte = $88, $83, $33, $38, $88 var sprtBall -byte drawpage -// -// Sprite routines -// -export def spriteBLTMask(x, y, w, h, srcptr)#0 - word i, j - byte c - - for j = y to y + h - 1 - for i = 0 to w - 1 - c = srcptr->[i >> 1] - if i & 1 - hgrColor(c & $08 ?? 3 :: 0) - else - hgrColor(c & $80 ?? 3 :: 0) - fin - hgrPlot(x + i, j) - next - srcptr = srcptr + (w + 1) / 2 - next -end -def spriteCompile(w, h, srcptr) - var sprtptr, bytewidth, spritesize, i - - sprtptr = heapalloc(t_sprite) - bytewidth = (w + 7) / 7 + 1 - sprtptr=>s_pitch = bytewidth - spritesize = bytewidth * h - sprtptr=>s_size = spritesize - sprtptr=>s_width = w - sprtptr=>s_height = h - sprtptr=>s_under[0] = heapalloc(spritesize) - sprtptr=>s_under[1] = heapalloc(spritesize) - for i = 0 to 13 - sprtptr=>s_map[i] = heapalloc(spritesize) - sprtptr=>s_mask[i] = heapalloc(spritesize) - hgrColor(0) - hgrRect(0, w + 21, 0, h - 1) - hgrBLT(i, 0, w, h, srcptr) - hgrCopyDst(i > 6 ?? 1 :: 0, 0, bytewidth, h, sprtptr=>s_map[i]) - hgrColor(3) - hgrRect(0, w + 21, h, h * 2 - 1) - spriteBLTMask(i, h, w, h, srcptr) - hgrCopyDst(i > 6 ?? 1 :: 0, h, bytewidth, h, sprtptr=>s_mask[i]) - next - sprtptr->s_underofst[0] = 255 // Mark as under not valid - sprtptr->s_underofst[1] = 255 - return sprtptr -end -def spriteDup(sprtsrc) - var sprtdup, spritesize - byte i - - sprtdup = heapalloc(t_sprite) - spritesize = sprtsrc=>s_size - sprtdup=>s_size = spritesize - sprtdup=>s_pitch = sprtsrc=>s_pitch - sprtdup=>s_width = sprtsrc=>s_width - sprtdup=>s_height = sprtsrc=>s_height - sprtdup=>s_under[0] = heapalloc(spritesize) - sprtdup=>s_under[1] = heapalloc(spritesize) - for i = 0 to 13 - sprtdup=>s_map[i] = sprtsrc=>s_map[i] - sprtdup=>s_mask[i] = sprtsrc=>s_mask[i] - next - sprtdup->s_underofst[0] = 255 // Mark as under not valid - sprtdup->s_underofst[1] = 255 - return sprtdup -end -def spriteDraw(page, sprtptr)#0 - byte ofst, map, y - var width, height - - y = sprtptr->s_ypos - ofst, map = divmod7(sprtptr=>s_xpos) - if ofst & 1 - map = map + 7 - fin - sprtptr->s_underofst[page] = ofst - sprtptr->s_undery[page] = y - width = sprtptr=>s_pitch - height = sprtptr=>s_height - hgrCopyDst(ofst, y, width, height, sprtptr=>s_under[page]) - hgrAndSrc( ofst, y, width, height, sprtptr=>s_mask[map]) - hgrXorSrc( ofst, y, width, height, sprtptr=>s_map[map]) -end -def spritePos(x, y, sprtptr)#0 - sprtptr=>s_ypos = y - sprtptr=>s_xpos = x -end -def spritePosIndex(x, y, i)#0 - i = i & 15 - if spriteList[i] - spriteList[i]=>s_ypos = y - spriteList[i]=>s_xpos = x - fin -end -def spriteUnDraw(page, sprtptr)#0 - if sprtptr->s_underofst[page] < 40 - hgrCopySrc(sprtptr->s_underofst[page], sprtptr->s_undery[page], sprtptr=>s_pitch, sprtptr=>s_height, sprtptr=>s_under[page]) - fin -end -def spriteDrawList#0 - byte i - - for i = 15 downto 0 - if spriteList[i] - spriteUnDraw(drawpage, spriteList[i]) - fin - next - for i = 0 to 15 - if spriteList[i] - spriteDraw(drawpage, spriteList[i]) - fin - next -end -def spriteAdd(i, sprtptr) - var sprtprev - - i = i & 15 - sprtprev = spriteList[i] - spriteList[i] = sprtptr - return sprtprev -end -def spriteDel(i) - var sprtprev - - i = i & 15 - sprtprev = spriteList[i] - spriteList[i] = 0 - return sprtprev -end -def spriteDrawPage(page)#0 - drawpage = page & 1 -end + def testline#0 var i setlinespans(@hgrHlin, @hgrVlin) hgrColor(7) - for i = 0 to 191 step 24 + for i = 0 to 191 step 8 linetospans(0, 0, 279, i) next - for i = 0 to 279 step 24 + for i = 0 to 279 step 8 linetospans(0, 0, i, 191) next end @@ -206,17 +58,17 @@ def testblt(sprtnum)#0 spritePosIndex(i[k], j[k], k) next spriteDrawList() - spriteDrawPage(hgrSwap()) + spriteDrawBuf(hgrSwap()) loop end -drawpage = hgrMode -hgrDrawBuf(0) // So we can see the compile process +hgrMode +spriteDrawBuf(hgrDrawBuf(0)) // So we can see the compile process sprtBall = spriteCompile(10, 10, @ball) hgrColor(0) hgrClear() testline memcpy($4000, $2000, $2000) // Copy to both buffers -hgrDrawbuf(drawpage) +spriteDrawBuf(hgrDrawBuf(1)) spriteAdd(0, sprtBall) spriteAdd(1, spriteDup(sprtBall)) spriteAdd(2, spriteDup(sprtBall)) From cec1252ff6708de46b350bad6e73989cee8dd478 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 26 Dec 2019 21:17:57 -0800 Subject: [PATCH 081/149] Copy sprite library over TFTP --- src/tftpbld | 1 + src/tftpsys | 1 + 2 files changed, 2 insertions(+) diff --git a/src/tftpbld b/src/tftpbld index e54254f..06edefd 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -9,6 +9,7 @@ echo "BLD/INC/ARGS.PLH"; atftp $1 --put -l inc/args.plh -r $2/BLD/INC/ARG echo "BLD/INC/CMDSYS.PLH"; atftp $1 --put -l inc/cmdsys.plh -r $2/BLD/INC/CMDSYS.PLH#040000 echo "BLD/INC/CONIO.PLH"; atftp $1 --put -l inc/conio.plh -r $2/BLD/INC/CONIO.PLH#040000 echo "BLD/INC/LINESPANS.PLH"; atftp $1 --put -l inc/linespans.plh -r $2/BLD/INC/LINESPANS.PLH#040000 +echo "BLD/INC/SPRITE.PLH"; atftp $1 --put -l inc/sprite.plh -r $2/BLD/INC/SPRITE.PLH#040000 echo "BLD/INC/HGRLIB.PLH"; atftp $1 --put -l inc/hgrlib.plh -r $2/BLD/INC/HGRLIB.PLH#040000 echo "BLD/INC/GRLIB.PLH"; atftp $1 --put -l inc/grlib.plh -r $2/BLD/INC/GRLIB.PLH#040000 echo "BLD/INC/DGRLIB.PLH"; atftp $1 --put -l inc/dgrlib.plh -r $2/BLD/INC/DGRLIB.PLH#040000 diff --git a/src/tftpsys b/src/tftpsys index cf146d9..641ae1a 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -22,6 +22,7 @@ echo "SYS/LONGJUMP"; atftp $1 --put -l rel/LONGJMP#FE1000 -r $2/SYS/LONGJMP#FE10 echo "SYS/MEMMGR"; atftp $1 --put -l rel/MEMMGR#FE1000 -r $2/SYS/MEMMGR#FE1000 echo "SYS/LZ4"; atftp $1 --put -l rel/LZ4#FE1000 -r $2/SYS/LZ4#FE1000 echo "SYS/CONIO"; atftp $1 --put -l rel/apple/CONIO#FE1000 -r $2/SYS/CONIO#FE1000 +echo "SYS/SPRITE"; atftp $1 --put -l rel/apple/SPRITE#FE1000 -r $2/SYS/LINESPANS#FE1000 echo "SYS/LINESPANS"; atftp $1 --put -l rel/apple/LINESPANS#FE1000 -r $2/SYS/LINESPANS#FE1000 echo "SYS/HGRLIB"; atftp $1 --put -l rel/apple/HGRLIB#FE1000 -r $2/SYS/HGRLIB#FE1000 echo "SYS/GRLIB"; atftp $1 --put -l rel/apple/GRLIB#FE1000 -r $2/SYS/GRLIB#FE1000 From bc532f445801d4d1cff1f5abc026287cf2879c25 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Thu, 26 Dec 2019 22:37:07 -0800 Subject: [PATCH 082/149] Load/Save sprites to a file --- src/inc/sprite.plh | 2 ++ src/libsrc/apple/hgrlib.pla | 48 ++++++++++++++++----------------- src/libsrc/apple/sprite.pla | 54 ++++++++++++++++++++++++++++++++++--- 3 files changed, 77 insertions(+), 27 deletions(-) diff --git a/src/inc/sprite.plh b/src/inc/sprite.plh index 79ae215..4c26f97 100644 --- a/src/inc/sprite.plh +++ b/src/inc/sprite.plh @@ -1,6 +1,8 @@ import sprite predef spriteCompile(w, h, srcptr)#1 predef spriteDup(sprtsrc)#1 + predef spriteRead(filestr)#1 + predef spriteSave(filestr, sprtptr)#1 predef spriteDraw(sprtptr)#0 predef spriteDrawXor(sprtptr)#0 predef spriteUnDraw(sprtptr)#0 diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index e830d82..6a85e88 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -65,30 +65,30 @@ byte = $02,$06,$0A,$0E,$12,$16,$1A,$1E byte = $02,$06,$0A,$0E,$12,$16,$1A,$1E byte = $03,$07,$0B,$0F,$13,$17,$1B,$1F byte = $03,$07,$0B,$0F,$13,$17,$1B,$1F -word hgrscan[] = $0000,$0400,$0800,$0C00,$1000,$1400,$1800,$1C00 -word = $0080,$0480,$0880,$0C80,$1080,$1480,$1880,$1C80 -word = $0100,$0500,$0900,$0D00,$1100,$1500,$1900,$1D00 -word = $0180,$0580,$0980,$0D80,$1180,$1580,$1980,$1D80 -word = $0200,$0600,$0A00,$0E00,$1200,$1600,$1A00,$1E00 -word = $0280,$0680,$0A80,$0E80,$1280,$1680,$1A80,$1E80 -word = $0300,$0700,$0B00,$0F00,$1300,$1700,$1B00,$1F00 -word = $0380,$0780,$0B80,$0F80,$1380,$1780,$1B80,$1F80 -word = $0028,$0428,$0828,$0C28,$1028,$1428,$1828,$1C28 -word = $00A8,$04A8,$08A8,$0CA8,$10A8,$14A8,$18A8,$1CA8 -word = $0128,$0528,$0928,$0D28,$1128,$1528,$1928,$1D28 -word = $01A8,$05A8,$09A8,$0DA8,$11A8,$15A8,$19A8,$1DA8 -word = $0228,$0628,$0A28,$0E28,$1228,$1628,$1A28,$1E28 -word = $02A8,$06A8,$0AA8,$0EA8,$12A8,$16A8,$1AA8,$1EA8 -word = $0328,$0728,$0B28,$0F28,$1328,$1728,$1B28,$1F28 -word = $03A8,$07A8,$0BA8,$0FA8,$13A8,$17A8,$1BA8,$1FA8 -word = $0050,$0450,$0850,$0C50,$1050,$1450,$1850,$1C50 -word = $00D0,$04D0,$08D0,$0CD0,$10D0,$14D0,$18D0,$1CD0 -word = $0150,$0550,$0950,$0D50,$1150,$1550,$1950,$1D50 -word = $01D0,$05D0,$09D0,$0DD0,$11D0,$15D0,$19D0,$1DD0 -word = $0250,$0650,$0A50,$0E50,$1250,$1650,$1A50,$1E50 -word = $02D0,$06D0,$0AD0,$0ED0,$12D0,$16D0,$1AD0,$1ED0 -word = $0350,$0750,$0B50,$0F50,$1350,$1750,$1B50,$1F50 -word = $03D0,$07D0,$0BD0,$0FD0,$13D0,$17D0,$1BD0,$1FD0 +word //hgrscan[] = $0000,$0400,$0800,$0C00,$1000,$1400,$1800,$1C00 +word // = $0080,$0480,$0880,$0C80,$1080,$1480,$1880,$1C80 +word // = $0100,$0500,$0900,$0D00,$1100,$1500,$1900,$1D00 +word // = $0180,$0580,$0980,$0D80,$1180,$1580,$1980,$1D80 +word // = $0200,$0600,$0A00,$0E00,$1200,$1600,$1A00,$1E00 +word // = $0280,$0680,$0A80,$0E80,$1280,$1680,$1A80,$1E80 +word // = $0300,$0700,$0B00,$0F00,$1300,$1700,$1B00,$1F00 +word // = $0380,$0780,$0B80,$0F80,$1380,$1780,$1B80,$1F80 +word // = $0028,$0428,$0828,$0C28,$1028,$1428,$1828,$1C28 +word // = $00A8,$04A8,$08A8,$0CA8,$10A8,$14A8,$18A8,$1CA8 +word // = $0128,$0528,$0928,$0D28,$1128,$1528,$1928,$1D28 +word // = $01A8,$05A8,$09A8,$0DA8,$11A8,$15A8,$19A8,$1DA8 +word // = $0228,$0628,$0A28,$0E28,$1228,$1628,$1A28,$1E28 +word // = $02A8,$06A8,$0AA8,$0EA8,$12A8,$16A8,$1AA8,$1EA8 +word // = $0328,$0728,$0B28,$0F28,$1328,$1728,$1B28,$1F28 +word // = $03A8,$07A8,$0BA8,$0FA8,$13A8,$17A8,$1BA8,$1FA8 +word // = $0050,$0450,$0850,$0C50,$1050,$1450,$1850,$1C50 +word // = $00D0,$04D0,$08D0,$0CD0,$10D0,$14D0,$18D0,$1CD0 +word // = $0150,$0550,$0950,$0D50,$1150,$1550,$1950,$1D50 +word // = $01D0,$05D0,$09D0,$0DD0,$11D0,$15D0,$19D0,$1DD0 +word // = $0250,$0650,$0A50,$0E50,$1250,$1650,$1A50,$1E50 +word // = $02D0,$06D0,$0AD0,$0ED0,$12D0,$16D0,$1AD0,$1ED0 +word // = $0350,$0750,$0B50,$0F50,$1350,$1750,$1B50,$1F50 +word // = $03D0,$07D0,$0BD0,$0FD0,$13D0,$17D0,$1BD0,$1FD0 word hcolor[] = $0000,$552A,$2A55,$7F7F,$8080,$D5AA,$AAD5,$FFFF word hmask = $8081,$8082,$8084,$8088,$8090,$80A0,$80C0 word = $8180,$8280,$8480,$8880,$9080,$A080,$C080 diff --git a/src/libsrc/apple/sprite.pla b/src/libsrc/apple/sprite.pla index 6bcc86f..60f61c2 100644 --- a/src/libsrc/apple/sprite.pla +++ b/src/libsrc/apple/sprite.pla @@ -1,5 +1,6 @@ include "inc/cmdsys.plh" include "inc/hgrlib.plh" +include "inc/fileio.plh" struc t_sprite var s_xpos @@ -8,7 +9,6 @@ struc t_sprite byte s_underofst[2] byte s_undery[2] byte s_pitch -// var s_width var s_height var s_size var s_mask[14] @@ -46,7 +46,6 @@ export def spriteCompile(w, h, srcptr)#1 sprtptr->s_pitch = bytewidth spritesize = bytewidth * h sprtptr=>s_size = spritesize -// sprtptr=>s_width = w sprtptr=>s_height = h sprtptr=>s_under[0] = heapalloc(spritesize) sprtptr=>s_under[1] = heapalloc(spritesize) @@ -74,7 +73,6 @@ export def spriteDup(sprtsrc)#1 spritesize = sprtsrc=>s_size sprtdup=>s_size = spritesize sprtdup->s_pitch = sprtsrc->s_pitch -// sprtdup=>s_width = sprtsrc=>s_width sprtdup=>s_height = sprtsrc=>s_height sprtdup=>s_under[0] = heapalloc(spritesize) sprtdup=>s_under[1] = heapalloc(spritesize) @@ -86,6 +84,56 @@ export def spriteDup(sprtsrc)#1 sprtdup->s_underofst[1] = 255 return sprtdup end +export def spriteRead(filestr)#1 + var sprtptr, spritesize + byte refnum, i + + sprtptr = 0 + refnum = fileio:open(@filestr) + if refnum + sprtptr = heapalloc(t_sprite) + if fileio:read(refnum, sprtptr, t_sprite) == t_sprite + spritesize = sprtptr=>s_size + sprtptr=>s_under[0] = heapalloc(spritesize) + sprtptr=>s_under[1] = heapalloc(spritesize) + for i = 0 to 13 + sprtptr=>s_map[i] = heapalloc(spritesize) + sprtptr=>s_mask[i] = heapalloc(spritesize) + fileio:read(refnum, sprtptr=>s_map[i], spritesize) + fileio:read(refnum, sprtptr=>s_mask[i], spritesize) + next + sprtptr->s_underofst[0] = 255 // Mark as under not valid + sprtptr->s_underofst[1] = 255 + else + heaprelease(sprtptr) + sprtptr = 0 + fin + fileio:close(refnum) + fin + return sprtptr +end +export def spriteSave(filestr, sprtptr)#1 + var spritesize + byte refnum, i + + fileio:destroy(@filestr) + if fileio:create(@filestr, $06, $0000) == FILE_ERR_OK + refnum = fileio:open(@filestr) + if refnum + if fileio:write(refnum, sprtptr, t_sprite) == t_sprite + spritesize = sprtptr=>s_size + for i = 0 to 13 + fileio:write(refnum, sprtptr=>s_map[i], spritesize) + fileio:write(refnum, sprtptr=>s_mask[i], spritesize) + next + fin + fileio:close(refnum) + return 0 + fin + fin + return -1 +end + export def spriteDraw(sprtptr)#0 byte ofst, map, y var width, height From efead509adfb57e8230731298f2b566b68528bf0 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 27 Dec 2019 14:46:10 -0800 Subject: [PATCH 083/149] Assembly-ize many things and clip sprites --- src/inc/line.plh | 6 + src/inc/linespans.plh | 4 - src/libsrc/apple/hgrlib.pla | 375 +++++++++++++++++++------ src/libsrc/apple/sprite.pla | 258 +++++++++++------ src/libsrc/{linespans.pla => line.pla} | 51 +++- src/makefile | 10 +- src/mkrel | 4 +- src/samplesrc/dgrtest.pla | 6 +- src/samplesrc/grtest.pla | 6 +- src/samplesrc/hgrtest.pla | 10 +- 10 files changed, 540 insertions(+), 190 deletions(-) create mode 100644 src/inc/line.plh delete mode 100644 src/inc/linespans.plh rename src/libsrc/{linespans.pla => line.pla} (86%) diff --git a/src/inc/line.plh b/src/inc/line.plh new file mode 100644 index 0000000..c7e63f4 --- /dev/null +++ b/src/inc/line.plh @@ -0,0 +1,6 @@ +import line + predef setlinespans(h, v)#0 + predef linespans(x1, y1, x2, y2)#0 + predef setlineplot(p)#0 + predef line(x1, y1, x2, y2)#0 +end diff --git a/src/inc/linespans.plh b/src/inc/linespans.plh deleted file mode 100644 index 3145d3f..0000000 --- a/src/inc/linespans.plh +++ /dev/null @@ -1,4 +0,0 @@ -import linespans - predef setlinespans(h, v)#0 - predef linetospans(x1, y1, x2, y2)#0 -end diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index 6a85e88..8397da7 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -110,49 +110,153 @@ byte = $8F, $FF, $FF, $FF, $F8 byte = $88, $FF, $FF, $FF, $88 byte = $88, $8F, $FF, $F8, $88 -asm grInc(buff) -!SOURCE "vmsrc/plvmzp.inc" -end - export asm divmod7(x)#2 - LDA ESTKL,X ; X COORD LSB - LDY ESTKH,X ; X COORD MSB - BNE + ; MUST BE >= 140 - CMP #140 - BCC ++ -+ SEC +!SOURCE "vmsrc/plvmzp.inc" + LDY ESTKH+0,X ; X COORDH + BPL + + LDA #$00 + SEC + SBC ESTKL+0,X + STA ESTKL+0,X + LDA #$00 + SBC ESTKH+0,X + TAY ++ LDA ESTKL+0,X ; X COORDL + CPY #$01 + BEQ ++ ; MUST BE >= 140 + BCC + + LDY #40 ; > 512 SO CLIP AT MAX + LDA #00 + BEQ +++ ++ CMP #140 + BCC + +++ SEC SBC #140 LDY #20 -++ CMP #70 ++ CMP #70 BCC + SBC #70 - STA ESTKL,X + STA ESTKL+0,X TYA ADC #9 TAY - LDA ESTKL,X + LDA ESTKL+0,X + CMP #35 BCC + SBC #35 - STA ESTKL,X + STA ESTKL+0,X TYA ADC #4 TAY - LDA ESTKL,X + LDA ESTKL+0,X + - CMP #7 - BCC + + BCC +++ SBC #7 INY BNE - -+ DEX - STA ESTKL,X ; REMAINDER - STY ESTKL+1,X ; QUOTIENT ++++ DEX + ASL ESTKH+1,X ; CHECK SIGN OF XCOORD + BCS + + STA ESTKL+0,X ; REMAINDERL LDA #$00 - STA ESTKH,X + STA ESTKH+0,X + STY ESTKL+1,X ; QUOTIENTL STA ESTKH+1,X RTS -end ++ EOR #$07 + STA ESTKL+0,X ; REMAINDERL + LDA #$00 + STA ESTKH+0,X + TYA + EOR #$FF + STA ESTKL+1,X ; QUOTIENTL + LDA #$FF + STA ESTKH+1,X + RTS +end +asm clipsrc(ofst, y, w, h, srcptr)#0 + LDA ESTKL+0,X ; SRC PTR + STA SRCL + LDA ESTKH+0,X + STA SRCH + LDA ESTKL+2,X ; WIDTH (SRC PITCH) + STA TMPH ; WIDTH (DRAW WIDTH) +; CLPTOP + LDY ESTKH+3,X ; Y COORDH + BPL CLPBOTM + INY +; STY ESTKH+3,X ; Y COORDH + BNE CLPPED + LDY ESTKL+3,X ; Y COORDL +- LDA SRCL + CLC + ADC ESTKL+2,X ; PITCH + STA SRCL + BCC + + INC SRCH ++ DEC ESTKL+1,X ; HEIGHT + BEQ CLPPED + INY ; Y COORDL + BNE - + STY ESTKL+3,X ; Y COORDL + BEQ CLPLEFT ; BETTER BE ZERO +CLPBOTM BNE CLPPED + LDA ESTKL+3,X ; YCOORDL + CMP #192 + BCS CLPPED +; CLC + ADC ESTKL+1,X ; HEIGHT + SBC #191 + BCC CLPLEFT + STA TMPL + LDA ESTKL+1,X ; HEIGHT + SBC TMPL + STA ESTKL+1,X ; HEIGHT + BEQ CLPPED +CLPLEFT LDY ESTKH+4,X ; HORIZ OFFSETH + BPL CLPRGHT + INY +; STY ESTKH+4,X + BNE CLPPED + LDY ESTKL+4,X ; HORIZ OFFSETL +- INC SRCL + BNE + + INC SRCH ++ DEC TMPH ; WIDTH + BEQ CLPPED + INY ; HORIZ OFFSETL + BNE - + STY ESTKL+4,X ; HORIZ OFFSETL + BEQ CLPDONE ; BETTER BE ZERO +CLPRGHT BNE CLPPED + LDA ESTKL+4,X ; HORIZ OFFSETL + CMP #40 + BCS CLPPED +; CLC + ADC TMPH ; WIDTH + SBC #39 + BCC CLPDONE + STA TMPL + LDA TMPH ; WIDTH + SBC TMPL + STA TMPH ; WIDTH +CLPDONE LDA TMPH + STA ESTKH+2,X ; WIDTH (DRAW WIDTH) +; LDA SRCL +; STA ESTKL+0,X ; SRC PTR +; LDA SRCH +; STA ESTKH+0,X + RTS +CLPPED INX + INX + INX + INX + INX + PLA + PLA + RTS +end //export def hgrColor(c)#0 // curhclr = hcolor[c & $07] //end @@ -179,14 +283,16 @@ end // next //end export asm hgrCopyDst(ofst, y, w, h, dstptr)#0 - LDA ESTKL+0,X ; DST PTR + JSR $C000 ; CLIPSRC +; LDA ESTKL+0,X ; DST PTR + LDA SRCL STA DSTL - LDA ESTKH+0,X +; LDA ESTKH+0,X + LDA SRCH STA DSTH -- LDY ESTKL+3,X ; Y COORD - CPY #192 - BCS + LDA ESTKL+4,X ; HORIZ OFFSET + CLC end asm _hgrCopyDst ADC $8000,Y ; HGRSCANL @@ -194,15 +300,15 @@ asm _hgrCopyDst LDA $1000 ; DRAWBUFFH ADC $9000,Y ; HGRSCANH STA SRCH - LDY ESTKL+2,X ; WIDTH + LDY ESTKH+2,X ; WIDTH DEY - LDA (SRC),Y STA (DST),Y DEY BPL - -+ LDA DSTL + LDA DSTL CLC - ADC ESTKL+2,X ; WIDTH + ADC ESTKL+2,X ; PITCH STA DSTL BCC + INC DSTH @@ -227,14 +333,14 @@ end // next //end export asm hgrCopySrc(ofst, y, w, h, srcptr)#0 - LDA ESTKL+0,X ; SRC PTR - STA SRCL - LDA ESTKH+0,X - STA SRCH + JSR $C000 ; CLIPSRC +; LDA ESTKL+0,X ; SRC PTR +; STA SRCL +; LDA ESTKH+0,X +; STA SRCH -- LDY ESTKL+3,X ; Y COORD - CPY #192 - BCS + LDA ESTKL+4,X ; HORIZ OFFSET + CLC end asm _hgrCopySrc ADC $8000,Y ; HGRSCANL @@ -242,15 +348,15 @@ asm _hgrCopySrc LDA $1000 ; DRAWBUFFH ADC $9000,Y ; HGRSCANH STA DSTH - LDY ESTKL+2,X ; WIDTH + LDY ESTKH+2,X ; WIDTH DEY - LDA (SRC),Y STA (DST),Y DEY BPL - -+ LDA SRCL + LDA SRCL CLC - ADC ESTKL+2,X ; WIDTH + ADC ESTKL+2,X ; PITCH STA SRCL BCC + INC SRCH @@ -278,14 +384,14 @@ end // next //end export asm hgrAndSrc(ofst, y, w, h, srcptr)#0 - LDA ESTKL+0,X ; SRC PTR - STA SRCL - LDA ESTKH+0,X - STA SRCH + JSR $C000 ; CLIPSRC +; LDA ESTKL+0,X ; SRC PTR +; STA SRCL +; LDA ESTKH+0,X +; STA SRCH -- LDY ESTKL+3,X ; Y COORD - CPY #192 - BCS + LDA ESTKL+4,X ; HORIZ OFFSET + CLC end asm _hgrAndSrc ADC $8000,Y ; HGRSCANL @@ -293,16 +399,16 @@ asm _hgrAndSrc LDA $1000 ; DRAWBUFFH ADC $9000,Y ; HGRSCANH STA DSTH - LDY ESTKL+2,X ; WIDTH + LDY ESTKH+2,X ; WIDTH DEY - LDA (SRC),Y AND (DST),Y STA (DST),Y DEY BPL - -+ LDA SRCL + LDA SRCL CLC - ADC ESTKL+2,X ; WIDTH + ADC ESTKL+2,X ; PITCH STA SRCL BCC + INC SRCH @@ -330,14 +436,14 @@ end // next //end export asm hgrXorSrc(ofst, y, w, h, srcptr)#0 - LDA ESTKL+0,X ; SRC PTR - STA SRCL - LDA ESTKH+0,X - STA SRCH + JSR $C000 ; CLIPSRC +; LDA ESTKL+0,X ; SRC PTR +; STA SRCL +; LDA ESTKH+0,X +; STA SRCH -- LDY ESTKL+3,X ; Y COORD - CPY #192 - BCS + LDA ESTKL+4,X ; HORIZ OFFSET + CLC end asm _hgrXorSrc ADC $8000,Y ; HGRSCANL @@ -345,16 +451,16 @@ asm _hgrXorSrc LDA $1000 ; DRAWBUFFH ADC $9000,Y ; HGRSCANH STA DSTH - LDY ESTKL+2,X ; WIDTH + LDY ESTKH+2,X ; WIDTH DEY - LDA (SRC),Y EOR (DST),Y STA (DST),Y DEY BPL - -+ LDA SRCL + LDA SRCL CLC - ADC ESTKL+2,X ; WIDTH + ADC ESTKL+2,X ; PITCH STA SRCL BCC + INC SRCH @@ -382,14 +488,14 @@ end // next //end export asm hgrOrSrc(ofst, y, w, h, srcptr)#0 - LDA ESTKL+0,X ; SRC PTR - STA SRCL - LDA ESTKH+0,X - STA SRCH + JSR $C000 ; CLIPSRC +; LDA ESTKL+0,X ; SRC PTR +; STA SRCL +; LDA ESTKH+0,X +; STA SRCH -- LDY ESTKL+3,X ; Y COORD - CPY #192 - BCS + LDA ESTKL+4,X ; HORIZ OFFSET + CLC end asm _hgrOrSrc ADC $8000,Y ; HGRSCANL @@ -397,16 +503,16 @@ asm _hgrOrSrc LDA $1000 ; DRAWBUFFH ADC $9000,Y ; HGRSCANH STA DSTH - LDY ESTKL+2,X ; WIDTH + LDY ESTKH+2,X ; WIDTH DEY - LDA (SRC),Y ORA (DST),Y STA (DST),Y DEY BPL - -+ LDA SRCL + LDA SRCL CLC - ADC ESTKL+2,X ; WIDTH + ADC ESTKL+2,X ; PITCH STA SRCL BCC + INC SRCH @@ -711,6 +817,99 @@ asm _hgrVLinC INX RTS end +// +// BLT scanline of pixmap +// +asm scanBLT(x, y, w, srcptr)#0 + LDA ESTKL+0,X ; SRC PTR + STA SRCL + LDA ESTKH+0,X + STA SRCH + LDA #$00 +- PHA + LSR + TAY + LDA (SRC),Y + LSR + LSR + LSR + LSR + PHA + DEX + STA ESTKL+0,X +end +asm _scanBLTA + JSR $C000 ; HCOLOR + DEX + DEX + LDA ESTKL+5,X ; X COORDL + STA ESTKL+1,X + LDA ESTKH+5,X ; X COORDH + STA ESTKH+1,X + LDA ESTKL+4,X ; Y COORDL + STA ESTKL+0,X + LDA ESTKH+4,X ; Y COORDH + STA ESTKH+0,X + PLA + AND #$08 + BEQ + +end +asm _scanBLTB + JSR $D000 ; HPLOT + BEQ ++ + BNE ++ ++ JSR $E000 ; HPLOTX +++ INC ESTKL+3,X ; X COORDL + BNE + + INC ESTKH+3,X ; X COORDH ++ PLA + CLC + ADC #$01 + CMP ESTKL+1,X ; WIDTH + BEQ BLTDONE + PHA + LSR + TAY + LDA (SRC),Y + PHA + DEX + STA ESTKL+0,X +end +asm _scanBLTC + JSR $C000 ; HCOLOR + DEX + DEX + LDA ESTKL+5,X ; X COORDL + STA ESTKL+1,X + LDA ESTKH+5,X ; X COORDH + STA ESTKH+1,X + LDA ESTKL+4,X ; Y COORDL + STA ESTKL+0,X + LDA ESTKH+4,X ; Y COORDH + STA ESTKH+0,X + PLA + AND #$08 + BEQ + +end +asm _scanBLTD + JSR $D000 ; HPLOT + BEQ ++ + BNE ++ ++ JSR $E000 ; HPLOTX +++ INC ESTKL+3,X ; X COORDL + BNE + + INC ESTKH+3,X ; X COORDH ++ PLA + CLC + ADC #$01 + CMP ESTKL+1,X ; WIDTH + BNE - +BLTDONE INX + INX + INX + INX + RTS +end export def hgrRect(x1, x2, y1, y2)#0 word y @@ -729,24 +928,25 @@ export def hgrBLT(x, y, w, h, srcptr)#0 saveclr = curhclr for j = y to y + h - 1 - for i = 0 to w - 1 - c = srcptr->[i >> 1] - if i & 1 - hgrColor(c) - if c & $08 - hgrXorPlot(x + i, j) - else - hgrPlot(x + i, j) - fin - else - hgrColor(c >> 4) - if c & $80 - hgrXorPlot(x + i, j) - else - hgrPlot(x + i, j) - fin - fin - next + scanBLT(x, j, w, srcptr) +// for i = 0 to w - 1 +// c = srcptr->[i >> 1] +// if i & 1 +// hgrColor(c) +// if c & $08 +// hgrXorPlot(x + i, j) +// else +// hgrPlot(x + i, j) +// fin +// else +// hgrColor(c >> 4) +// if c & $80 +// hgrXorPlot(x + i, j) +// else +// hgrPlot(x + i, j) +// fin +// fin +// next srcptr = srcptr + (w + 1) / 2 next curhclr = saveclr @@ -790,18 +990,23 @@ end // // Assembly fixups // +hgrCopyDst:1 = @clipsrc _hgrCopyDst:1 = @hgrscanl _hgrCopyDst:6 = @drawbuff.1 _hgrCopyDst:9 = @hgrscanh +hgrCopySrc:1 = @clipsrc _hgrCopySrc:1 = @hgrscanl _hgrCopySrc:6 = @drawbuff.1 _hgrCopySrc:9 = @hgrscanh +hgrAndSrc:1 = @clipsrc _hgrAndSrc:1 = @hgrscanl _hgrAndSrc:6 = @drawbuff.1 _hgrAndSrc:9 = @hgrscanh +hgrXorSrc:1 = @clipsrc _hgrXorSrc:1 = @hgrscanl _hgrXorSrc:6 = @drawbuff.1 _hgrXorSrc:9 = @hgrscanh +hgrOrSrc:1 = @clipsrc _hgrOrSrc:1 = @hgrscanl _hgrOrSrc:6 = @drawbuff.1 _hgrOrSrc:9 = @hgrscanh @@ -839,4 +1044,10 @@ hgrColor:7 = @hcolor hgrColor:10 = @curhclr hgrColor:13 = @hcolor.1 hgrColor:16 = @curhclr.1 +_scanBLTA:1 = @hgrColor +_scanBLTB:1 = @hgrPlot +_scanBLTB:8 = @hgrXorPlot +_scanBLTC:1 = @hgrColor +_scanBLTD:1 = @hgrPlot +_scanBLTD:8 = @hgrXorPlot done diff --git a/src/libsrc/apple/sprite.pla b/src/libsrc/apple/sprite.pla index 60f61c2..358a94a 100644 --- a/src/libsrc/apple/sprite.pla +++ b/src/libsrc/apple/sprite.pla @@ -5,36 +5,119 @@ include "inc/fileio.plh" struc t_sprite var s_xpos var s_ypos + var s_undery[2] + var s_underofst[2] byte s_undermap[2] - byte s_underofst[2] - byte s_undery[2] byte s_pitch - var s_height + byte s_height var s_size var s_mask[14] var s_map[14] var s_under[14] end -var spriteList[16] +var drawList[16] +var undrawList0[16] +var undrawList1[16] +var undrawList[2] = @undrawList0, @undrawList1 byte drawpage // // Sprite routines // +asm scanMask(x, y, w, srcptr)#0 +!SOURCE "vmsrc/plvmzp.inc" + LDA ESTKL+0,X ; SRC PTR + STA SRCL + LDA ESTKH+0,X + STA SRCH + LDA #$00 +- PHA + LSR + TAY + LDA (SRC),Y + AND #$80 + BEQ + + LDA #$03 ++ DEX + STA ESTKL+0,X +end +asm _scanMaskA + JSR $C000 ; HCOLOR + DEX + DEX + LDA ESTKL+5,X ; X COORDL + STA ESTKL+1,X + LDA ESTKH+5,X ; X COORDH + STA ESTKH+1,X + LDA ESTKL+4,X ; Y COORDL + STA ESTKL+0,X + LDA ESTKH+4,X ; Y COORDH + STA ESTKH+0,X +end +asm _scanMaskB + JSR $D000 ; HPLOT + INC ESTKL+3,X ; X COORDL + BNE + + INC ESTKH+3,X ; X COORDH ++ PLA + CLC + ADC #$01 + CMP ESTKL+1,X ; WIDTH + BEQ BLTDONE + PHA + LSR + TAY + LDA (SRC),Y + AND #$08 + BEQ + + LDA #$03 ++ DEX + STA ESTKL+0,X +end +asm _scanMaskC + JSR $C000 ; HCOLOR + DEX + DEX + LDA ESTKL+5,X ; X COORDL + STA ESTKL+1,X + LDA ESTKH+5,X ; X COORDH + STA ESTKH+1,X + LDA ESTKL+4,X ; Y COORDL + STA ESTKL+0,X + LDA ESTKH+4,X ; Y COORDH + STA ESTKH+0,X +end +asm _scanMaskD + JSR $D000 ; HPLOT + INC ESTKL+3,X ; X COORDL + BNE + + INC ESTKH+3,X ; X COORDH ++ PLA + CLC + ADC #$01 + CMP ESTKL+1,X ; WIDTH + BNE - +BLTDONE INX + INX + INX + INX + RTS +end def spriteBLTMask(x, y, w, h, srcptr)#0 word i, j byte c for j = y to y + h - 1 - for i = 0 to w - 1 - c = srcptr->[i >> 1] - if i & 1 - hgrColor(c & $08 ?? 3 :: 0) - else - hgrColor(c & $80 ?? 3 :: 0) - fin - hgrPlot(x + i, j) - next + scanMask(x, j, w, srcptr) +// for i = 0 to w - 1 +// c = srcptr->[i >> 1] +// if i & 1 +// hgrColor(c & $08 ?? 3 :: 0) +// else +// hgrColor(c & $80 ?? 3 :: 0) +// fin +// hgrPlot(x + i, j) +// next srcptr = srcptr + (w + 1) / 2 next end @@ -46,7 +129,7 @@ export def spriteCompile(w, h, srcptr)#1 sprtptr->s_pitch = bytewidth spritesize = bytewidth * h sprtptr=>s_size = spritesize - sprtptr=>s_height = h + sprtptr->s_height = h sprtptr=>s_under[0] = heapalloc(spritesize) sprtptr=>s_under[1] = heapalloc(spritesize) for i = 0 to 13 @@ -61,8 +144,6 @@ export def spriteCompile(w, h, srcptr)#1 spriteBLTMask(i, h, w, h, srcptr) hgrCopyDst(i > 6 ?? 1 :: 0, h, bytewidth, h, sprtptr=>s_mask[i]) next - sprtptr->s_underofst[0] = 255 // Mark as under not valid - sprtptr->s_underofst[1] = 255 return sprtptr end export def spriteDup(sprtsrc)#1 @@ -73,15 +154,13 @@ export def spriteDup(sprtsrc)#1 spritesize = sprtsrc=>s_size sprtdup=>s_size = spritesize sprtdup->s_pitch = sprtsrc->s_pitch - sprtdup=>s_height = sprtsrc=>s_height + sprtdup->s_height = sprtsrc->s_height sprtdup=>s_under[0] = heapalloc(spritesize) sprtdup=>s_under[1] = heapalloc(spritesize) for i = 0 to 13 sprtdup=>s_map[i] = sprtsrc=>s_map[i] sprtdup=>s_mask[i] = sprtsrc=>s_mask[i] next - sprtdup->s_underofst[0] = 255 // Mark as under not valid - sprtdup->s_underofst[1] = 255 return sprtdup end export def spriteRead(filestr)#1 @@ -91,24 +170,22 @@ export def spriteRead(filestr)#1 sprtptr = 0 refnum = fileio:open(@filestr) if refnum - sprtptr = heapalloc(t_sprite) - if fileio:read(refnum, sprtptr, t_sprite) == t_sprite - spritesize = sprtptr=>s_size - sprtptr=>s_under[0] = heapalloc(spritesize) - sprtptr=>s_under[1] = heapalloc(spritesize) - for i = 0 to 13 - sprtptr=>s_map[i] = heapalloc(spritesize) - sprtptr=>s_mask[i] = heapalloc(spritesize) - fileio:read(refnum, sprtptr=>s_map[i], spritesize) - fileio:read(refnum, sprtptr=>s_mask[i], spritesize) - next - sprtptr->s_underofst[0] = 255 // Mark as under not valid - sprtptr->s_underofst[1] = 255 + sprtptr = heapalloc(t_sprite) + if fileio:read(refnum, sprtptr, t_sprite) == t_sprite + spritesize = sprtptr=>s_size + sprtptr=>s_under[0] = heapalloc(spritesize) + sprtptr=>s_under[1] = heapalloc(spritesize) + for i = 0 to 13 + sprtptr=>s_map[i] = heapalloc(spritesize) + sprtptr=>s_mask[i] = heapalloc(spritesize) + fileio:read(refnum, sprtptr=>s_map[i], spritesize) + fileio:read(refnum, sprtptr=>s_mask[i], spritesize) + next else - heaprelease(sprtptr) - sprtptr = 0 - fin - fileio:close(refnum) + heaprelease(sprtptr) + sprtptr = 0 + fin + fileio:close(refnum) fin return sprtptr end @@ -120,62 +197,57 @@ export def spriteSave(filestr, sprtptr)#1 if fileio:create(@filestr, $06, $0000) == FILE_ERR_OK refnum = fileio:open(@filestr) if refnum - if fileio:write(refnum, sprtptr, t_sprite) == t_sprite - spritesize = sprtptr=>s_size - for i = 0 to 13 - fileio:write(refnum, sprtptr=>s_map[i], spritesize) - fileio:write(refnum, sprtptr=>s_mask[i], spritesize) - next - fin - fileio:close(refnum) - return 0 - fin + if fileio:write(refnum, sprtptr, t_sprite) == t_sprite + spritesize = sprtptr=>s_size + for i = 0 to 13 + fileio:write(refnum, sprtptr=>s_map[i], spritesize) + fileio:write(refnum, sprtptr=>s_mask[i], spritesize) + next + fin + fileio:close(refnum) + return 0 + fin fin return -1 end - export def spriteDraw(sprtptr)#0 - byte ofst, map, y - var width, height + byte map, pitch, height + var ofst, y - y = sprtptr->s_ypos + y = sprtptr=>s_ypos ofst, map = divmod7(sprtptr=>s_xpos) if ofst & 1 map = map + 7 fin - sprtptr->s_underofst[drawpage] = ofst - sprtptr->s_undery[drawpage] = y - width = sprtptr->s_pitch - height = sprtptr=>s_height - hgrCopyDst(ofst, y, width, height, sprtptr=>s_under[drawpage]) - hgrAndSrc( ofst, y, width, height, sprtptr=>s_mask[map]) - hgrXorSrc( ofst, y, width, height, sprtptr=>s_map[map]) + sprtptr=>s_underofst[drawpage] = ofst + sprtptr=>s_undery[drawpage] = y + pitch = sprtptr->s_pitch + height = sprtptr->s_height + hgrCopyDst(ofst, y, pitch, height, sprtptr=>s_under[drawpage]) + hgrAndSrc( ofst, y, pitch, height, sprtptr=>s_mask[map]) + hgrXorSrc( ofst, y, pitch, height, sprtptr=>s_map[map]) end export def spriteUnDraw(sprtptr)#0 - if sprtptr->s_underofst[drawpage] < 40 - hgrCopySrc(sprtptr->s_underofst[drawpage], sprtptr->s_undery[drawpage], sprtptr->s_pitch, sprtptr=>s_height, sprtptr=>s_under[drawpage]) - fin + hgrCopySrc(sprtptr=>s_underofst[drawpage], sprtptr=>s_undery[drawpage], sprtptr->s_pitch, sprtptr->s_height, sprtptr=>s_under[drawpage]) end export def spriteDrawXor(sprtptr)#0 - byte ofst, map, y - var width, height + byte map, pitch, height + var ofst, y - y = sprtptr->s_ypos + y = sprtptr=>s_ypos ofst, map = divmod7(sprtptr=>s_xpos) if ofst & 1 map = map + 7 fin sprtptr->s_undermap[drawpage] = map - sprtptr->s_underofst[drawpage] = ofst - sprtptr->s_undery[drawpage] = y - width = sprtptr->s_pitch - height = sprtptr=>s_height - hgrXorSrc( ofst, y, width, height, sprtptr=>s_map[map]) + sprtptr=>s_underofst[drawpage] = ofst + sprtptr=>s_undery[drawpage] = y + pitch = sprtptr->s_pitch + height = sprtptr->s_height + hgrXorSrc( ofst, y, pitch, height, sprtptr=>s_map[map]) end export def spriteUnDrawXor(sprtptr)#0 - if sprtptr->s_underofst[drawpage] < 40 - hgrXorSrc(sprtptr->s_underofst[drawpage], sprtptr->s_undery[drawpage], sprtptr->s_pitch, sprtptr=>s_height, sprtptr=>s_map[sprtptr->s_undermap[drawpage]]) - fin + hgrXorSrc(sprtptr=>s_underofst[drawpage], sprtptr=>s_undery[drawpage], sprtptr->s_pitch, sprtptr->s_height, sprtptr=>s_map[sprtptr->s_undermap[drawpage]]) end export def spritePos(x, y, sprtptr)#0 sprtptr=>s_ypos = y @@ -183,51 +255,67 @@ export def spritePos(x, y, sprtptr)#0 end export def spritePosIndex(x, y, i)#0 i = i & 15 - if spriteList[i] - spriteList[i]=>s_ypos = y - spriteList[i]=>s_xpos = x + if drawList[i] + drawList[i]=>s_ypos = y + drawList[i]=>s_xpos = x fin end export def spriteDrawList#0 byte i + var undrawptr + undrawptr = undrawList[drawpage] for i = 15 downto 0 - if spriteList[i] - spriteUnDraw(spriteList[i]) + if undrawptr=>[i] + spriteUnDraw(undrawptr=>[i]) fin next for i = 0 to 15 - if spriteList[i] - spriteDraw(spriteList[i]) + if drawList[i] + spriteDraw(drawList[i]) fin next + memcpy(undrawptr, @drawList, 16*2) end export def spriteDrawXorList#0 byte i + var undrawptr + + undrawptr = undrawList[drawpage] for i = 0 to 15 - if spriteList[i] - spriteUnDrawXor(spriteList[i]) - spriteDrawXor(spriteList[i]) + if undrawptr=>[i] + spriteUnDrawXor(undrawptr=>[i]) + fin + if drawList[i] + spriteDrawXor(drawList[i]) fin next + memcpy(undrawptr, @drawList, 16*2) end export def spriteAdd(i, sprtptr)#1 var sprtprev i = i & 15 - sprtprev = spriteList[i] - spriteList[i] = sprtptr + sprtprev = drawList[i] + drawList[i] = sprtptr return sprtprev end export def spriteDel(i)#1 var sprtprev i = i & 15 - sprtprev = spriteList[i] - spriteList[i] = 0 + sprtprev = drawList[i] + drawList[i] = 0 return sprtprev end export def spriteDrawBuf(page)#0 drawpage = page & 1 end +// +// Assembly fixups +// +_scanMaskA:1 = @hgrColor +_scanMaskB:1 = @hgrPlot +_scanMaskC:1 = @hgrColor +_scanMaskD:1 = @hgrPlot done diff --git a/src/libsrc/linespans.pla b/src/libsrc/line.pla similarity index 86% rename from src/libsrc/linespans.pla rename to src/libsrc/line.pla index 343c80e..183d2e3 100644 --- a/src/libsrc/linespans.pla +++ b/src/libsrc/line.pla @@ -1,8 +1,10 @@ include "inc/cmdsys.plh" predef nopLin(a, b, c)#0 +predef nopPix(a, b)#0 var hspan = @nopLin var vspan = @nopLin +var plot = @nopPix var err, shorterr, shortlen, longerr, longlen //def nopLin(a, b, c)#0 @@ -147,6 +149,8 @@ asm _majorlineE end asm nopLin(a, b, c)#0 INX +end +asm nopPix(a, b)#0 INX INX RTS @@ -155,7 +159,7 @@ export def setlinespans(h, v)#0 hspan = h vspan = v end -export def linetospans(x1, y1, x2, y2)#0 +export def linespans(x1, y1, x2, y2)#0 var dx, dy, dx2, dy2, halflen, rem, sx, sy sx = 1 @@ -229,6 +233,51 @@ export def linetospans(x1, y1, x2, y2)#0 majorline(y1, y1 + halflen, y2, x1, sx, vspan) fin end +export def setlineplot(p)#0 + plot = p +end +export def line(x1, y1, x2, y2)#0 + var sx, sy, dx2, dy2, x, y + + sx = 1 + sy = 1 + dx2 = (x2 - x1) * 2 + if dx2 < 0 + sx = -1; dx2 = -dx2 + fin + dy2 = (y2 - y1) * 2 + if dy2 < 0 + sy = -1; dy2 = -dy2 + fin + if dx2 >= dy2 + if sx < 0 + sy = -sy; x1, x2 = x2, x1 + fin + err = dy2 - dx2 / 2 + for x = x1 to x2 + plot(x, y) + if err >= 0 + err = err - dx2 + y = y + sy + fin + err = err + dy2 + next + else + if sy < 0 + sx = -sx; y1, y2 = y2, y1 + fin + err = dx2 - dy2 / 2 + for y = y1 to y2 + plot(x, y) + if err >= 0 + err = err - dy2 + x = x + sx + fin + err = err + dx2 + next + fin + end + // // Assembly fixups // diff --git a/src/makefile b/src/makefile index 77724ff..a4b60d6 100755 --- a/src/makefile +++ b/src/makefile @@ -59,7 +59,7 @@ HGRLIB = rel/apple/HGRLIB\#FE1000 GRLIB = rel/apple/GRLIB\#FE1000 DGRLIB = rel/apple/DGRLIB\#FE1000 SPRITE = rel/apple/SPRITE\#FE1000 -LINESPANS = rel/apple/LINESPANS\#FE1000 +LINE = rel/apple/LINE\#FE1000 GRAFIX = rel/apple/GRAFIX\#FE1000 GFXDEMO = rel/apple/GFXDEMO\#FE1000 JOYBUZZ = rel/apple/JOYBUZZ\#FE1000 @@ -100,7 +100,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINESPANS) $(SPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINE) $(SPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -229,9 +229,9 @@ $(FIBER): libsrc/fiber.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/fiber.pla > libsrc/fiber.a acme --setpc 4094 -o $(FIBER) libsrc/fiber.a -$(LINESPANS): libsrc/linespans.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AMOW < libsrc/linespans.pla > libsrc/linespans.a - acme --setpc 4094 -o $(LINESPANS) libsrc/linespans.a +$(LINE): libsrc/line.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < libsrc/line.pla > libsrc/line.a + acme --setpc 4094 -o $(LINE) libsrc/line.a $(FIBERTEST): samplesrc/fibertest.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/fibertest.pla > samplesrc/fibertest.a diff --git a/src/mkrel b/src/mkrel index f36d594..8ac8a18 100755 --- a/src/mkrel +++ b/src/mkrel @@ -9,7 +9,7 @@ rm -rf prodos/sys mkdir prodos/sys cp rel/apple/FILEIO#FE1000 prodos/sys/FILEIO.REL cp rel/apple/CONIO#FE1000 prodos/sys/CONIO.REL -cp rel/apple/LINESPANS#FE1000 prodos/sys/LINESPANS.REL +cp rel/apple/LINE#FE1000 prodos/sys/LINE.REL cp rel/apple/SPRITE#FE1000 prodos/sys/SPRITE.REL cp rel/apple/HGRLIB#FE1000 prodos/sys/HGRLIB.REL cp rel/apple/GRLIB#FE1000 prodos/sys/GRLIB.REL @@ -150,7 +150,7 @@ mkdir prodos/bld/inc cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT cp inc/cmdsys.plh prodos/bld/inc/CMDSYS.PLH.TXT cp inc/conio.plh prodos/bld/inc/CONIO.PLH.TXT -cp inc/linespans.plh prodos/bld/inc/LINESPANS.PLH.TXT +cp inc/line.plh prodos/bld/inc/LINE.PLH.TXT cp inc/sprite.plh prodos/bld/inc/SPRITE.PLH.TXT cp inc/hgrlib.plh prodos/bld/inc/HGRLIB.PLH.TXT cp inc/grlib.plh prodos/bld/inc/GRLIB.PLH.TXT diff --git a/src/samplesrc/dgrtest.pla b/src/samplesrc/dgrtest.pla index ea20a0f..46910fa 100644 --- a/src/samplesrc/dgrtest.pla +++ b/src/samplesrc/dgrtest.pla @@ -1,6 +1,6 @@ include "inc/cmdsys.plh" include "inc/dgrlib.plh" -include "inc/linespans.plh" +include "inc/line.plh" sysflags restxt1|restxt2|resxtxt1|resxtxt2 // Reserve all text pages byte[] sprite1 = $80,$80,$00,$00,$00,$00,$80,$80 @@ -32,11 +32,11 @@ def dgrTest#0 setlinespans(@dgrHLin, @dgrVLin) for l = 0 to 79 dgrColor(l) - linetospans(0, 0, l, 47) + linespans(0, 0, l, 47) next for l = 47 downto 0 dgrColor(l) - linetospans(0, 0, 79, l) + linespans(0, 0, 79, l) next ii = 2 ij = -1 diff --git a/src/samplesrc/grtest.pla b/src/samplesrc/grtest.pla index e79817b..58569a4 100644 --- a/src/samplesrc/grtest.pla +++ b/src/samplesrc/grtest.pla @@ -1,6 +1,6 @@ include "inc/cmdsys.plh" include "inc/grlib.plh" -include "inc/linespans.plh" +include "inc/line.plh" sysflags restxt1|restxt2 // Reserve all text pages byte[] sprite1 = $80,$80,$00,$00,$00,$00,$80,$80 @@ -32,11 +32,11 @@ def grTest#0 setlinespans(@grHLin, @grVLin) for l = 0 to 39 grColor(l) - linetospans(0, 0, l, 47) + linespans(0, 0, l, 47) next for l = 47 downto 0 grColor(l) - linetospans(0, 0, 39, l) + linespans(0, 0, 39, l) next ii = 2 ij = -1 diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index 905bc00..41e6451 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -1,7 +1,7 @@ include "inc/cmdsys.plh" include "inc/hgrlib.plh" include "inc/sprite.plh" -include "inc/linespans.plh" +include "inc/line.plh" sysflags reshgr1|reshgr2 // Reserve HGR page 1 and 2 byte ball = $88, $83, $33, $38, $88 @@ -22,10 +22,10 @@ def testline#0 setlinespans(@hgrHlin, @hgrVlin) hgrColor(7) for i = 0 to 191 step 8 - linetospans(0, 0, 279, i) + linespans(0, 0, 279, i) next for i = 0 to 279 step 8 - linetospans(0, 0, i, 191) + linespans(0, 0, i, 191) next end def testblt(sprtnum)#0 @@ -48,11 +48,11 @@ def testblt(sprtnum)#0 while ^$C000 < 128 for k = 0 to sprtnum i[k] = i[k] + ii[k] - if i[k] < 1 or i[k] > 269 + if i[k] < -10 or i[k] > 280 ii[k] = -ii[k] fin j[k] = j[k] + jj[k] - if j[k] < 1 or j[k] > 181 + if j[k] < -10 or j[k] > 192 jj[k] = -jj[k] fin spritePosIndex(i[k], j[k], k) From a056e00e93548a2328787eebdb58ede3dd0be194 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 27 Dec 2019 15:17:53 -0800 Subject: [PATCH 084/149] Clean up some build problems --- src/inc/{line.plh => lines.plh} | 2 +- src/libsrc/{line.pla => lines.pla} | 0 src/makefile | 10 ++-- src/mkrel | 4 +- src/samplesrc/dgrtest.pla | 78 +++++++++++++-------------- src/samplesrc/grtest.pla | 78 +++++++++++++-------------- src/samplesrc/hgrtest.pla | 85 +++++++++++++++--------------- src/tftpbld | 2 +- src/tftpsys | 4 +- 9 files changed, 132 insertions(+), 131 deletions(-) rename src/inc/{line.plh => lines.plh} (91%) rename src/libsrc/{line.pla => lines.pla} (100%) diff --git a/src/inc/line.plh b/src/inc/lines.plh similarity index 91% rename from src/inc/line.plh rename to src/inc/lines.plh index c7e63f4..b9afda4 100644 --- a/src/inc/line.plh +++ b/src/inc/lines.plh @@ -1,4 +1,4 @@ -import line +import lines predef setlinespans(h, v)#0 predef linespans(x1, y1, x2, y2)#0 predef setlineplot(p)#0 diff --git a/src/libsrc/line.pla b/src/libsrc/lines.pla similarity index 100% rename from src/libsrc/line.pla rename to src/libsrc/lines.pla diff --git a/src/makefile b/src/makefile index a4b60d6..8d5dad2 100755 --- a/src/makefile +++ b/src/makefile @@ -59,7 +59,7 @@ HGRLIB = rel/apple/HGRLIB\#FE1000 GRLIB = rel/apple/GRLIB\#FE1000 DGRLIB = rel/apple/DGRLIB\#FE1000 SPRITE = rel/apple/SPRITE\#FE1000 -LINE = rel/apple/LINE\#FE1000 +LINES = rel/apple/LINES\#FE1000 GRAFIX = rel/apple/GRAFIX\#FE1000 GFXDEMO = rel/apple/GFXDEMO\#FE1000 JOYBUZZ = rel/apple/JOYBUZZ\#FE1000 @@ -100,7 +100,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINE) $(SPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINES) $(SPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -229,9 +229,9 @@ $(FIBER): libsrc/fiber.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/fiber.pla > libsrc/fiber.a acme --setpc 4094 -o $(FIBER) libsrc/fiber.a -$(LINE): libsrc/line.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AMOW < libsrc/line.pla > libsrc/line.a - acme --setpc 4094 -o $(LINE) libsrc/line.a +$(LINES): libsrc/lines.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < libsrc/lines.pla > libsrc/lines.a + acme --setpc 4094 -o $(LINES) libsrc/lines.a $(FIBERTEST): samplesrc/fibertest.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/fibertest.pla > samplesrc/fibertest.a diff --git a/src/mkrel b/src/mkrel index 8ac8a18..344df15 100755 --- a/src/mkrel +++ b/src/mkrel @@ -9,7 +9,7 @@ rm -rf prodos/sys mkdir prodos/sys cp rel/apple/FILEIO#FE1000 prodos/sys/FILEIO.REL cp rel/apple/CONIO#FE1000 prodos/sys/CONIO.REL -cp rel/apple/LINE#FE1000 prodos/sys/LINE.REL +cp rel/apple/LINES#FE1000 prodos/sys/LINES.REL cp rel/apple/SPRITE#FE1000 prodos/sys/SPRITE.REL cp rel/apple/HGRLIB#FE1000 prodos/sys/HGRLIB.REL cp rel/apple/GRLIB#FE1000 prodos/sys/GRLIB.REL @@ -150,7 +150,7 @@ mkdir prodos/bld/inc cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT cp inc/cmdsys.plh prodos/bld/inc/CMDSYS.PLH.TXT cp inc/conio.plh prodos/bld/inc/CONIO.PLH.TXT -cp inc/line.plh prodos/bld/inc/LINE.PLH.TXT +cp inc/lines.plh prodos/bld/inc/LINES.PLH.TXT cp inc/sprite.plh prodos/bld/inc/SPRITE.PLH.TXT cp inc/hgrlib.plh prodos/bld/inc/HGRLIB.PLH.TXT cp inc/grlib.plh prodos/bld/inc/GRLIB.PLH.TXT diff --git a/src/samplesrc/dgrtest.pla b/src/samplesrc/dgrtest.pla index 46910fa..11ca80f 100644 --- a/src/samplesrc/dgrtest.pla +++ b/src/samplesrc/dgrtest.pla @@ -1,6 +1,6 @@ include "inc/cmdsys.plh" include "inc/dgrlib.plh" -include "inc/line.plh" +include "inc/lines.plh" sysflags restxt1|restxt2|resxtxt1|resxtxt2 // Reserve all text pages byte[] sprite1 = $80,$80,$00,$00,$00,$00,$80,$80 @@ -21,45 +21,45 @@ byte[] = $0A,$05,$0A,$05,$0A,$05,$0A,$00 // Test routine // def dgrTest#0 - byte b, l, k - word i, j, ii, ij + byte b, l, k + word i, j, ii, ij - b = dgrMode() - dgrDrawBuf(0) - for k = 15 downto 0 - dgrClear(k) - next - setlinespans(@dgrHLin, @dgrVLin) - for l = 0 to 79 - dgrColor(l) - linespans(0, 0, l, 47) - next - for l = 47 downto 0 - dgrColor(l) - linespans(0, 0, 79, l) - next - ii = 2 - ij = -1 - i = 40 - j = 10 - ^$C010 - dgrDrawBuf(1) - while ^$C000 < 128 - dgrFill(k, k, @tile1) - dgrBLT(i, j, 8, 8, @sprite1) - dgrSwap - k++ - i = i + ii - if i < -3 or i > 75 - ii = -ii - fin - j = j + ij - if j < -3 or j > 43 - ij = -ij - fin - loop - ^$C010 - txtMode + b = dgrMode() + dgrDrawBuf(0) + for k = 15 downto 0 + dgrClear(k) + next + setlinespans(@dgrHLin, @dgrVLin) + for l = 0 to 79 + dgrColor(l) + linespans(0, 0, l, 47) + next + for l = 47 downto 0 + dgrColor(l) + linespans(0, 0, 79, l) + next + ii = 2 + ij = -1 + i = 40 + j = 10 + ^$C010 + dgrDrawBuf(1) + while ^$C000 < 128 + dgrFill(k, k, @tile1) + dgrBLT(i, j, 8, 8, @sprite1) + dgrSwap + k++ + i = i + ii + if i < -3 or i > 75 + ii = -ii + fin + j = j + ij + if j < -3 or j > 43 + ij = -ij + fin + loop + ^$C010 + txtMode end dgrTest diff --git a/src/samplesrc/grtest.pla b/src/samplesrc/grtest.pla index 58569a4..48ea2ff 100644 --- a/src/samplesrc/grtest.pla +++ b/src/samplesrc/grtest.pla @@ -1,6 +1,6 @@ include "inc/cmdsys.plh" include "inc/grlib.plh" -include "inc/line.plh" +include "inc/lines.plh" sysflags restxt1|restxt2 // Reserve all text pages byte[] sprite1 = $80,$80,$00,$00,$00,$00,$80,$80 @@ -21,45 +21,45 @@ byte[] = $05,$05,$05,$05,$05,$05,$05,$00 // Test routine // def grTest#0 - byte b, l, k - word i, j, ii, ij + byte b, l, k + word i, j, ii, ij - b = grMode() - grDrawBuf(0) - for k = 15 downto 0 - grClear(k) - next - setlinespans(@grHLin, @grVLin) - for l = 0 to 39 - grColor(l) - linespans(0, 0, l, 47) - next - for l = 47 downto 0 - grColor(l) - linespans(0, 0, 39, l) - next - ii = 2 - ij = -1 - i = 20 - j = 10 - ^$C010 - grDrawBuf(1) - while ^$C000 < 128 - grFill(k, k, @tile1) - grBLT(i, j, 8, 8, @sprite1) - grSwap - k++ - i = i + ii - if i < -3 or i > 35 - ii = -ii - fin - j = j + ij - if j < -3 or j > 43 - ij = -ij - fin - loop - ^$C010 - txtMode + b = grMode() + grDrawBuf(0) + for k = 15 downto 0 + grClear(k) + next + setlinespans(@grHLin, @grVLin) + for l = 0 to 39 + grColor(l) + linespans(0, 0, l, 47) + next + for l = 47 downto 0 + grColor(l) + linespans(0, 0, 39, l) + next + ii = 2 + ij = -1 + i = 20 + j = 10 + ^$C010 + grDrawBuf(1) + while ^$C000 < 128 + grFill(k, k, @tile1) + grBLT(i, j, 8, 8, @sprite1) + grSwap + k++ + i = i + ii + if i < -3 or i > 35 + ii = -ii + fin + j = j + ij + if j < -3 or j > 43 + ij = -ij + fin + loop + ^$C010 + txtMode end grTest diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index 41e6451..e695993 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -1,7 +1,7 @@ include "inc/cmdsys.plh" include "inc/hgrlib.plh" include "inc/sprite.plh" -include "inc/line.plh" +include "inc/lines.plh" sysflags reshgr1|reshgr2 // Reserve HGR page 1 and 2 byte ball = $88, $83, $33, $38, $88 @@ -17,50 +17,51 @@ byte = $88, $83, $33, $38, $88 var sprtBall def testline#0 - var i - - setlinespans(@hgrHlin, @hgrVlin) - hgrColor(7) - for i = 0 to 191 step 8 - linespans(0, 0, 279, i) - next - for i = 0 to 279 step 8 - linespans(0, 0, i, 191) - next + var i + + setlinespans(@hgrHlin, @hgrVlin) + hgrColor(7) + for i = 0 to 191 step 8 + linespans(0, 0, 279, i) + next + for i = 0 to 279 step 8 + linespans(0, 0, i, 191) + next end def testblt(sprtnum)#0 - var[16] i, j, ii, jj - byte k - - sprtnum = sprtnum - 1 - i[0] = 100 - ii[0] = 1 - j[0] = 80 - jj[0] = -1 - if sprtnum - for k = 1 to sprtnum - i[k] = ((i[k - 1] ^ 37) + 97) % 270 - ii[k] = -ii[k - 1] - j[k] = ((j[k - 1] ^ 29) + 53) % 180 - jj[k] = -jj[k - 1] - next - fin - while ^$C000 < 128 - for k = 0 to sprtnum - i[k] = i[k] + ii[k] - if i[k] < -10 or i[k] > 280 - ii[k] = -ii[k] - fin - j[k] = j[k] + jj[k] - if j[k] < -10 or j[k] > 192 - jj[k] = -jj[k] - fin - spritePosIndex(i[k], j[k], k) - next - spriteDrawList() - spriteDrawBuf(hgrSwap()) - loop + var[16] i, j, ii, jj + byte k + + sprtnum = sprtnum - 1 + i[0] = 100 + ii[0] = 1 + j[0] = 80 + jj[0] = -1 + if sprtnum + for k = 1 to sprtnum + i[k] = ((i[k - 1] ^ 37) + 97) % 270 + ii[k] = -ii[k - 1] + j[k] = ((j[k - 1] ^ 29) + 53) % 180 + jj[k] = -jj[k - 1] + next + fin + while ^$C000 < 128 + for k = 0 to sprtnum + i[k] = i[k] + ii[k] + if i[k] < -10 or i[k] > 280 + ii[k] = -ii[k] + fin + j[k] = j[k] + jj[k] + if j[k] < -10 or j[k] > 192 + jj[k] = -jj[k] + fin + spritePosIndex(i[k], j[k], k) + next + spriteDrawList() + spriteDrawBuf(hgrSwap()) + loop end + hgrMode spriteDrawBuf(hgrDrawBuf(0)) // So we can see the compile process sprtBall = spriteCompile(10, 10, @ball) diff --git a/src/tftpbld b/src/tftpbld index 06edefd..9026726 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -8,7 +8,7 @@ echo "BLD/CODEOPT"; atftp $1 --put -l rel/CODEOPT#FE1000 -r $2/BLD/CODEOPT#FE10 echo "BLD/INC/ARGS.PLH"; atftp $1 --put -l inc/args.plh -r $2/BLD/INC/ARGS.PLH#040000 echo "BLD/INC/CMDSYS.PLH"; atftp $1 --put -l inc/cmdsys.plh -r $2/BLD/INC/CMDSYS.PLH#040000 echo "BLD/INC/CONIO.PLH"; atftp $1 --put -l inc/conio.plh -r $2/BLD/INC/CONIO.PLH#040000 -echo "BLD/INC/LINESPANS.PLH"; atftp $1 --put -l inc/linespans.plh -r $2/BLD/INC/LINESPANS.PLH#040000 +echo "BLD/INC/LINES.PLH"; atftp $1 --put -l inc/lines.plh -r $2/BLD/INC/LINES.PLH#040000 echo "BLD/INC/SPRITE.PLH"; atftp $1 --put -l inc/sprite.plh -r $2/BLD/INC/SPRITE.PLH#040000 echo "BLD/INC/HGRLIB.PLH"; atftp $1 --put -l inc/hgrlib.plh -r $2/BLD/INC/HGRLIB.PLH#040000 echo "BLD/INC/GRLIB.PLH"; atftp $1 --put -l inc/grlib.plh -r $2/BLD/INC/GRLIB.PLH#040000 diff --git a/src/tftpsys b/src/tftpsys index 641ae1a..ac879f8 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -22,8 +22,8 @@ echo "SYS/LONGJUMP"; atftp $1 --put -l rel/LONGJMP#FE1000 -r $2/SYS/LONGJMP#FE10 echo "SYS/MEMMGR"; atftp $1 --put -l rel/MEMMGR#FE1000 -r $2/SYS/MEMMGR#FE1000 echo "SYS/LZ4"; atftp $1 --put -l rel/LZ4#FE1000 -r $2/SYS/LZ4#FE1000 echo "SYS/CONIO"; atftp $1 --put -l rel/apple/CONIO#FE1000 -r $2/SYS/CONIO#FE1000 -echo "SYS/SPRITE"; atftp $1 --put -l rel/apple/SPRITE#FE1000 -r $2/SYS/LINESPANS#FE1000 -echo "SYS/LINESPANS"; atftp $1 --put -l rel/apple/LINESPANS#FE1000 -r $2/SYS/LINESPANS#FE1000 +echo "SYS/SPRITE"; atftp $1 --put -l rel/apple/SPRITE#FE1000 -r $2/SYS/SPRITE#FE1000 +echo "SYS/LINES"; atftp $1 --put -l rel/apple/LINES#FE1000 -r $2/SYS/LINES#FE1000 echo "SYS/HGRLIB"; atftp $1 --put -l rel/apple/HGRLIB#FE1000 -r $2/SYS/HGRLIB#FE1000 echo "SYS/GRLIB"; atftp $1 --put -l rel/apple/GRLIB#FE1000 -r $2/SYS/GRLIB#FE1000 echo "SYS/DGRLIB"; atftp $1 --put -l rel/apple/DGRLIB#FE1000 -r $2/SYS/DGRLIB#FE1000 From 8a960f018b290da981ed51a8fdb4bccded1bf992 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 27 Dec 2019 17:51:31 -0800 Subject: [PATCH 085/149] Fix lines in all directions --- src/libsrc/apple/hgrlib.pla | 11 +++-------- src/libsrc/lines.pla | 16 ++++++++++++---- src/samplesrc/hgrtest.pla | 18 +++++++++++++----- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index 8397da7..5ff84f7 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -655,17 +655,12 @@ export asm hgrHLin(x1, x2, y)#0 LDA ESTKH+1 CMP ESTKH+2 BNE + - LDA ESTKL+0 - STA ESTKL+1 - LDA ESTKH+0 - STA ESTKH+1 - INX end asm _hgrHLinA - JMP $F000 + JSR $F000 + INX + RTS + LDY ESTKL+0,X ; Y COORD - CPY #192 - BCS + end asm _hgrHLinB LDA $8000,Y ; HGRSCANL diff --git a/src/libsrc/lines.pla b/src/libsrc/lines.pla index 183d2e3..ce2f256 100644 --- a/src/libsrc/lines.pla +++ b/src/libsrc/lines.pla @@ -174,7 +174,9 @@ export def linespans(x1, y1, x2, y2)#0 fin if dx >= dy if sx < 0 - x1, x2 = x2, x1; sy = -sy + y1, y2 = y2, y1 + x1, x2 = x2, x1 + sy = -sy fin if dy == 0 hspan(x1, x2, y1)#0; return @@ -205,7 +207,9 @@ export def linespans(x1, y1, x2, y2)#0 majorline(x1, x1 + halflen, x2, y1, sy, hspan) else if sy < 0 - x1, x2 = x2, x1; sx = -sx + x1, x2 = x2, x1 + y1, y2 = y2, y1 + sx = -sx fin if dx == 0 vspan(y1, y2, x1)#0; return @@ -251,7 +255,9 @@ export def line(x1, y1, x2, y2)#0 fin if dx2 >= dy2 if sx < 0 - sy = -sy; x1, x2 = x2, x1 + x1, x2 = x2, x1 + y1, y2 = y2, y1 + sy = -sy fin err = dy2 - dx2 / 2 for x = x1 to x2 @@ -264,7 +270,9 @@ export def line(x1, y1, x2, y2)#0 next else if sy < 0 - sx = -sx; y1, y2 = y2, y1 + y1, y2 = y2, y1 + x1, x2 = x2, x1 + sx = -sx fin err = dx2 - dy2 / 2 for y = y1 to y2 diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index e695993..d8a9b6b 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -21,11 +21,11 @@ def testline#0 setlinespans(@hgrHlin, @hgrVlin) hgrColor(7) - for i = 0 to 191 step 8 - linespans(0, 0, 279, i) + for i = 0 to 191 step 16 + linespans(0, i, 279, 191 - i) next - for i = 0 to 279 step 8 - linespans(0, 0, i, 191) + for i = 0 to 279 step 14 + linespans(i, 0, 279 - i, 191) next end def testblt(sprtnum)#0 @@ -78,7 +78,15 @@ spriteAdd(4, spriteDup(sprtBall)) spriteAdd(5, spriteDup(sprtBall)) spriteAdd(6, spriteDup(sprtBall)) spriteAdd(7, spriteDup(sprtBall)) -testblt(8) +spriteAdd(8, spriteDup(sprtBall)) +spriteAdd(9, spriteDup(sprtBall)) +spriteAdd(10, spriteDup(sprtBall)) +spriteAdd(11, spriteDup(sprtBall)) +spriteAdd(12, spriteDup(sprtBall)) +spriteAdd(13, spriteDup(sprtBall)) +spriteAdd(14, spriteDup(sprtBall)) +spriteAdd(15, spriteDup(sprtBall)) +testblt(16) getc txtMode done From c7c69fe0d5802699ae9caef267e2e682f48cd5a0 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 27 Dec 2019 18:37:21 -0800 Subject: [PATCH 086/149] Update line spacing --- src/samplesrc/hgrtest.pla | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index d8a9b6b..168365c 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -21,10 +21,10 @@ def testline#0 setlinespans(@hgrHlin, @hgrVlin) hgrColor(7) - for i = 0 to 191 step 16 + for i = 0 to 191 step 8 linespans(0, i, 279, 191 - i) next - for i = 0 to 279 step 14 + for i = 0 to 279 step 9 linespans(i, 0, 279 - i, 191) next end From b5f832b0b2c61eb630e4ac52f7f9acce3b3d8a61 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Fri, 27 Dec 2019 19:01:01 -0800 Subject: [PATCH 087/149] Fix simple line plot routine --- src/libsrc/lines.pla | 10 +++++----- src/samplesrc/hgrtest.pla | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/libsrc/lines.pla b/src/libsrc/lines.pla index ce2f256..d2fbc3c 100644 --- a/src/libsrc/lines.pla +++ b/src/libsrc/lines.pla @@ -261,10 +261,10 @@ export def line(x1, y1, x2, y2)#0 fin err = dy2 - dx2 / 2 for x = x1 to x2 - plot(x, y) + plot(x, y1)#0 if err >= 0 err = err - dx2 - y = y + sy + y1 = y1 + sy fin err = err + dy2 next @@ -276,14 +276,14 @@ export def line(x1, y1, x2, y2)#0 fin err = dx2 - dy2 / 2 for y = y1 to y2 - plot(x, y) + plot(x1, y)#0 if err >= 0 err = err - dy2 - x = x + sx + x1 = x1 + sx fin err = err + dx2 next - fin + fin end // diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index 168365c..1083c25 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -20,12 +20,15 @@ def testline#0 var i setlinespans(@hgrHlin, @hgrVlin) + setlineplot(@hgrXorPlot) hgrColor(7) for i = 0 to 191 step 8 linespans(0, i, 279, 191 - i) + //line(0, i, 279, 191 - i) next for i = 0 to 279 step 9 linespans(i, 0, 279 - i, 191) + //line(i, 0, 279 - i, 191) next end def testblt(sprtnum)#0 From 322546a0b16397a3d00e995396bb8030acd60807 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 28 Dec 2019 08:19:31 -0800 Subject: [PATCH 088/149] Add sprite center --- src/inc/sprite.plh | 2 +- src/libsrc/apple/sprite.pla | 17 ++++++++++++----- src/samplesrc/hgrtest.pla | 6 +++--- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/inc/sprite.plh b/src/inc/sprite.plh index 4c26f97..da90150 100644 --- a/src/inc/sprite.plh +++ b/src/inc/sprite.plh @@ -1,5 +1,5 @@ import sprite - predef spriteCompile(w, h, srcptr)#1 + predef spriteCompile(w, h, xcenter, ycenter, srcptr)#1 predef spriteDup(sprtsrc)#1 predef spriteRead(filestr)#1 predef spriteSave(filestr, sprtptr)#1 diff --git a/src/libsrc/apple/sprite.pla b/src/libsrc/apple/sprite.pla index 358a94a..5f60ee1 100644 --- a/src/libsrc/apple/sprite.pla +++ b/src/libsrc/apple/sprite.pla @@ -8,6 +8,8 @@ struc t_sprite var s_undery[2] var s_underofst[2] byte s_undermap[2] + byte s_xcenter + byte s_ycenter byte s_pitch byte s_height var s_size @@ -121,7 +123,7 @@ def spriteBLTMask(x, y, w, h, srcptr)#0 srcptr = srcptr + (w + 1) / 2 next end -export def spriteCompile(w, h, srcptr)#1 +export def spriteCompile(w, h, xcenter, ycenter, srcptr)#1 var sprtptr, bytewidth, spritesize, i sprtptr = heapalloc(t_sprite) @@ -130,6 +132,8 @@ export def spriteCompile(w, h, srcptr)#1 spritesize = bytewidth * h sprtptr=>s_size = spritesize sprtptr->s_height = h + sprtptr->s_xcenter = xcenter + sprtptr->s_ycenter = ycenter sprtptr=>s_under[0] = heapalloc(spritesize) sprtptr=>s_under[1] = heapalloc(spritesize) for i = 0 to 13 @@ -155,6 +159,9 @@ export def spriteDup(sprtsrc)#1 sprtdup=>s_size = spritesize sprtdup->s_pitch = sprtsrc->s_pitch sprtdup->s_height = sprtsrc->s_height + sprtdup->s_height = sprtsrc->s_height + sprtdup->s_xcenter = sprtsrc->s_xcenter + sprtdup->s_ycenter = sprtsrc->s_ycenter sprtdup=>s_under[0] = heapalloc(spritesize) sprtdup=>s_under[1] = heapalloc(spritesize) for i = 0 to 13 @@ -250,14 +257,14 @@ export def spriteUnDrawXor(sprtptr)#0 hgrXorSrc(sprtptr=>s_underofst[drawpage], sprtptr=>s_undery[drawpage], sprtptr->s_pitch, sprtptr->s_height, sprtptr=>s_map[sprtptr->s_undermap[drawpage]]) end export def spritePos(x, y, sprtptr)#0 - sprtptr=>s_ypos = y - sprtptr=>s_xpos = x + sprtptr=>s_ypos = y - sprtptr->s_ycenter + sprtptr=>s_xpos = x - sprtptr->s_xcenter end export def spritePosIndex(x, y, i)#0 i = i & 15 if drawList[i] - drawList[i]=>s_ypos = y - drawList[i]=>s_xpos = x + drawList[i]=>s_ypos = y - drawList[i]->s_ycenter + drawList[i]=>s_xpos = x - drawList[i]->s_xcenter fin end export def spriteDrawList#0 diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index 1083c25..9646a73 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -51,11 +51,11 @@ def testblt(sprtnum)#0 while ^$C000 < 128 for k = 0 to sprtnum i[k] = i[k] + ii[k] - if i[k] < -10 or i[k] > 280 + if i[k] < 0 or i[k] > 279 ii[k] = -ii[k] fin j[k] = j[k] + jj[k] - if j[k] < -10 or j[k] > 192 + if j[k] < 0 or j[k] > 191 jj[k] = -jj[k] fin spritePosIndex(i[k], j[k], k) @@ -67,7 +67,7 @@ end hgrMode spriteDrawBuf(hgrDrawBuf(0)) // So we can see the compile process -sprtBall = spriteCompile(10, 10, @ball) +sprtBall = spriteCompile(10, 10, 5, 5, @ball) hgrColor(0) hgrClear() testline From 4a4468cc227d73f153271c9e092b1f43b9d3ee85 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 28 Dec 2019 09:47:24 -0800 Subject: [PATCH 089/149] Fix divmod7 for negative numbers --- src/libsrc/apple/hgrlib.pla | 29 ++++++++++++++--------------- src/samplesrc/hgrtest.pla | 4 ++-- src/toolsrc/ed.pla | 3 +++ 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index 5ff84f7..d5411e5 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -112,17 +112,15 @@ byte = $88, $8F, $FF, $F8, $88 export asm divmod7(x)#2 !SOURCE "vmsrc/plvmzp.inc" + LDA ESTKL+0,X ; X COORDL LDY ESTKH+0,X ; X COORDH BPL + - LDA #$00 - SEC - SBC ESTKL+0,X - STA ESTKL+0,X - LDA #$00 - SBC ESTKH+0,X + TYA ; DEAL WITH NEG X COORD + EOR #$FF TAY -+ LDA ESTKL+0,X ; X COORDL - CPY #$01 + LDA ESTKL+0,X + EOR #$FF ++ CPY #$01 BEQ ++ ; MUST BE >= 140 BCC + LDY #40 ; > 512 SO CLIP AT MAX @@ -159,20 +157,21 @@ export asm divmod7(x)#2 ASL ESTKH+1,X ; CHECK SIGN OF XCOORD BCS + STA ESTKL+0,X ; REMAINDERL - LDA #$00 - STA ESTKH+0,X STY ESTKL+1,X ; QUOTIENTL - STA ESTKH+1,X + LDY #$00 + STY ESTKH+0,X + STY ESTKH+1,X RTS + EOR #$07 + SBC #$01 STA ESTKL+0,X ; REMAINDERL - LDA #$00 - STA ESTKH+0,X TYA EOR #$FF STA ESTKL+1,X ; QUOTIENTL - LDA #$FF - STA ESTKH+1,X + LDY #$00 + STY ESTKH+0,X + DEY + STY ESTKH+1,X RTS end asm clipsrc(ofst, y, w, h, srcptr)#0 diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index 9646a73..a2b802e 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -51,11 +51,11 @@ def testblt(sprtnum)#0 while ^$C000 < 128 for k = 0 to sprtnum i[k] = i[k] + ii[k] - if i[k] < 0 or i[k] > 279 + if i[k] < -5 or i[k] > 284 ii[k] = -ii[k] fin j[k] = j[k] + jj[k] - if j[k] < 0 or j[k] > 191 + if j[k] < -5 or j[k] > 196 jj[k] = -jj[k] fin spritePosIndex(i[k], j[k], k) diff --git a/src/toolsrc/ed.pla b/src/toolsrc/ed.pla index d4348a8..a0ae85a 100755 --- a/src/toolsrc/ed.pla +++ b/src/toolsrc/ed.pla @@ -1149,6 +1149,9 @@ def cutsel#0 next memcpy(@txtlinbuf=>[firstsel], @txtlinbuf=>[lastsel + 1], (numlines - lastsel + 1) * 2) numlines = numlines - numcliplines + for lastsel = numlines to numlines + numcliplines + txtlinbuf=>[lastsel] = @nullstr + next cursrow = firstsel if cursrow >= numlines cursrow = numlines - 1 From c09b15f37702eae66aac0fb3512078dd72308d55 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 28 Dec 2019 12:03:59 -0800 Subject: [PATCH 090/149] A little re-org and assembly-izing --- src/inc/{sprite.plh => hgrsprite.plh} | 2 +- .../apple/{sprite.pla => hgrsprite.pla} | 0 src/libsrc/lines.pla | 254 +++++++++++++++--- src/makefile | 12 +- src/mkrel | 6 +- src/samplesrc/hgrtest.pla | 2 +- src/tftpbld | 2 +- src/tftpsys | 4 +- 8 files changed, 228 insertions(+), 54 deletions(-) rename src/inc/{sprite.plh => hgrsprite.plh} (96%) rename src/libsrc/apple/{sprite.pla => hgrsprite.pla} (100%) diff --git a/src/inc/sprite.plh b/src/inc/hgrsprite.plh similarity index 96% rename from src/inc/sprite.plh rename to src/inc/hgrsprite.plh index da90150..d2daed0 100644 --- a/src/inc/sprite.plh +++ b/src/inc/hgrsprite.plh @@ -1,4 +1,4 @@ -import sprite +import hgrsprite predef spriteCompile(w, h, xcenter, ycenter, srcptr)#1 predef spriteDup(sprtsrc)#1 predef spriteRead(filestr)#1 diff --git a/src/libsrc/apple/sprite.pla b/src/libsrc/apple/hgrsprite.pla similarity index 100% rename from src/libsrc/apple/sprite.pla rename to src/libsrc/apple/hgrsprite.pla diff --git a/src/libsrc/lines.pla b/src/libsrc/lines.pla index d2fbc3c..eec08c9 100644 --- a/src/libsrc/lines.pla +++ b/src/libsrc/lines.pla @@ -2,9 +2,10 @@ include "inc/cmdsys.plh" predef nopLin(a, b, c)#0 predef nopPix(a, b)#0 -var hspan = @nopLin -var vspan = @nopLin -var plot = @nopPix +byte jmpplot = $4C // Sneaky! +var plot = @nopPix +var hspan = @nopLin +var vspan = @nopLin var err, shorterr, shortlen, longerr, longlen //def nopLin(a, b, c)#0 @@ -82,7 +83,7 @@ asm _majorlineA STA ESTKH+5,X ; MAJORSTARTH end asm _majorlineB - LDA $1001 ; ERRH + LDY $1001 ; ERRH BMI + end asm _majorlineC @@ -90,7 +91,7 @@ asm _majorlineC CLC ADC $2000 ; SHORTERRL STA $1000 ; ERRL - LDA $1001 ; ERRH + TYA ; ERRH ADC $2001 ; SHORTERRH STA $1001 ; ERRH LDA ESTKL+4,X ; MAJORL @@ -108,7 +109,7 @@ asm _majorlineD CLC ADC $4000 ; LONGERRL STA $1000 ; ERRL - LDA $1001 ; ERRH + TYA ; ERRH ADC $4001 ; LONGERRL STA $1001 ; ERRH LDA ESTKL+4,X ; MAJORL @@ -143,9 +144,11 @@ asm _majorlineE LDA ESTKH+5,X ; MINORH STA ESTKH+0,X JSR $B000 - INX - INX - INX + TXA + CLC + ADC #$06 + TAX + RTS end asm nopLin(a, b, c)#0 INX @@ -155,6 +158,179 @@ asm nopPix(a, b)#0 INX RTS end +//def hline(x1, x2, dx2, y, dy2, sy)#0 +// var dyx2, x +// +// err = dy2 - dx2 / 2 +// dyx2 = dy2 - dx2 +// for x = x1 to x2 +// plot(x, y)#0 +// if err >= 0 +// y = y + sy +// err = err + dyx2 +// else +// err = err + dy2 +// fin +// next +//end +asm hline(x1, x2, dx2, y, dy2, sy)#0 + LDA ESTKH+3,X ; DX2H + LSR + STA TMPH + LDA ESTKL+3,X ; DX2L + ROR + STA TMPL + LDA ESTKL+1,X ; DY2L + SEC + SBC TMPL + STA $1000 ; ERRL + LDA ESTKH+1,X ; DY2H + SBC TMPH + STA $1001 ; ERRH + LDA ESTKL+1,X ; DY2L + SEC + SBC ESTKL+3,X ; DX2L + STA ESTKL+3,X ; DYX2L + LDA ESTKH+1,X ; DY2H + SBC ESTKH+3,X ; DX2H + STA ESTKH+3,X ; DYX2H +- DEX + DEX + LDA ESTKL+7,X ; XL + STA ESTKL+1,X + LDA ESTKH+7,X ; XH + STA ESTKH+1,X + LDA ESTKL+4,X ; YL + STA ESTKL+0,X + LDA ESTKH+4,X ; YH + STA ESTKH+0,X +end +asm _hlineA + JSR $2000 ; PLOT + LDA $1001 ; ERRH + BMI + + LDA ESTKL+2,X ; YL + CLC + ADC ESTKL+0,X ; SYL + STA ESTKL+2,X + LDA ESTKH+2,X ; YH + ADC ESTKH+0,X ; SYH + STA ESTKH+2,X + LDA ESTKL+3,X ; DYX2L + LDY ESTKH+3,X ; DYX2H + BEQ ++ + BNE ++ +end +asm _hlineB ++ LDA ESTKL+1,X ; DY2L + LDY ESTKH+1,X ; DY2H +++ CLC + ADC $1000 ; ERRL + STA $1000 ; ERRL + TYA + ADC $1001 ; ERRH + STA $1001 ; ERRH + LDA ESTKL+5,X ; X1L + CMP ESTKL+4,X ; X2L + LDA ESTKH+5,X + SBC ESTKH+4,X + BCS + + INC ESTKL+5,X ; XL + BNE - + INC ESTKH+5,X ; XH + BCC - ++ TXA + ADC #$05 + TAX + RTS +end +//def vline(y1, y2, dy2, x, dx2, sx)#0 +// var dxy2, y +// +// err = dx2 - dy2 / 2 +// dxy2 = dx2 - dy2 +// for y = y1 to y2 +// plot(x, y)#0 +// if err >= 0 +// x = x + sx +// err = err + dxy2 +// else +// err = err + dx2 +// fin +// next +//end +asm vline(y1, y2, dy2, x, dx2, sx)#0 + LDA ESTKH+3,X ; DY2H + LSR + STA TMPH + LDA ESTKL+3,X ; DY2L + ROR + STA TMPL + LDA ESTKL+1,X ; DX2L + SEC + SBC TMPL + STA $1000 ; ERRL + LDA ESTKH+1,X ; DX2H + SBC TMPH + STA $1001 ; ERRH + LDA ESTKL+1,X ; DX2L + SEC + SBC ESTKL+3,X ; DX2L + STA ESTKL+3,X ; DXY2L + LDA ESTKH+1,X ; DX2H + SBC ESTKH+3,X ; DY2H + STA ESTKH+3,X ; DXY2H +- DEX + DEX + LDA ESTKL+4,X ; XL + STA ESTKL+1,X + LDA ESTKH+4,X ; XH + STA ESTKH+1,X + LDA ESTKL+7,X ; YL + STA ESTKL+0,X + LDA ESTKH+7,X ; YH + STA ESTKH+0,X +end +asm _vlineA + JSR $2000 ; PLOT + LDA $1001 ; ERRH + BMI + + LDA ESTKL+2,X ; XL + CLC + ADC ESTKL+0,X ; SXL + STA ESTKL+2,X + LDA ESTKH+2,X ; XH + ADC ESTKH+0,X ; SXH + STA ESTKH+2,X + LDA ESTKL+3,X ; DXY2L + LDY ESTKH+3,X ; DXY2H + BEQ ++ + BNE ++ +end +asm _vlineB ++ LDA ESTKL+1,X ; DX2L + LDY ESTKH+1,X ; DX2H +++ CLC + ADC $1000 ; ERRL + STA $1000 ; ERRL + TYA + ADC $1001 ; ERRH + STA $1001 ; ERRH + LDA ESTKL+5,X ; Y1L + CMP ESTKL+4,X ; Y2L + LDA ESTKH+5,X + SBC ESTKH+4,X + BCS + + INC ESTKL+5,X ; YL + BNE - + INC ESTKH+5,X ; YH + BCC - ++ TXA + ADC #$05 + TAX + RTS +end + export def setlinespans(h, v)#0 hspan = h vspan = v @@ -241,17 +417,17 @@ export def setlineplot(p)#0 plot = p end export def line(x1, y1, x2, y2)#0 - var sx, sy, dx2, dy2, x, y + var sx, sy, dx2, dy2 sx = 1 sy = 1 dx2 = (x2 - x1) * 2 if dx2 < 0 - sx = -1; dx2 = -dx2 + sx = -1; dx2 = -dx2 fin dy2 = (y2 - y1) * 2 if dy2 < 0 - sy = -1; dy2 = -dy2 + sy = -1; dy2 = -dy2 fin if dx2 >= dy2 if sx < 0 @@ -259,30 +435,14 @@ export def line(x1, y1, x2, y2)#0 y1, y2 = y2, y1 sy = -sy fin - err = dy2 - dx2 / 2 - for x = x1 to x2 - plot(x, y1)#0 - if err >= 0 - err = err - dx2 - y1 = y1 + sy - fin - err = err + dy2 - next + hline(x1, x2, dx2, y1, dy2, sy) else if sy < 0 y1, y2 = y2, y1 x1, x2 = x2, x1 sx = -sx fin - err = dx2 - dy2 / 2 - for y = y1 to y2 - plot(x1, y)#0 - if err >= 0 - err = err - dy2 - x1 = x1 + sx - fin - err = err + dx2 - next + vline(y1, y2, dy2, x1, dx2, sx) fin end @@ -303,18 +463,32 @@ _majorlineB:1 = @err.1 _majorlineC:1 = @err _majorlineC:5 = @shorterr _majorlineC:8 = @err -_majorlineC:11 = @err.1 -_majorlineC:14 = @shorterr.1 -_majorlineC:17 = @err.1 -_majorlineC:23 = @shortlen -_majorlineC:30 = @shortlen.1 +_majorlineC:12 = @shorterr.1 +_majorlineC:15 = @err.1 +_majorlineC:21 = @shortlen +_majorlineC:28 = @shortlen.1 _majorlineD:1 = @err _majorlineD:5 = @longerr _majorlineD:8 = @err -_majorlineD:11 = @err.1 -_majorlineD:14 = @longerr.1 -_majorlineD:17 = @err.1 -_majorlineD:23 = @longlen -_majorlineD:30 = @longlen.1 +_majorlineD:12 = @longerr.1 +_majorlineD:15 = @err.1 +_majorlineD:21 = @longlen +_majorlineD:28 = @longlen.1 _majorlineE:1 = @_majorlineA +hline:16 = @err +hline:23 = @err.1 +_hlineA:1 = @jmpplot +_hlineA:4 = @err.1 +_hlineB:6 = @err +_hlineB:9 = @err +_hlineB:13 = @err.1 +_hlineB:16 = @err.1 +vline:16 = @err +vline:23 = @err.1 +_vlineA:1 = @jmpplot +_vlineA:4 = @err.1 +_vlineB:6 = @err +_vlineB:9 = @err +_vlineB:13 = @err.1 +_vlineB:16 = @err.1 done diff --git a/src/makefile b/src/makefile index 8d5dad2..01f759e 100755 --- a/src/makefile +++ b/src/makefile @@ -58,8 +58,8 @@ TFTPD = rel/TFTPD\#FE1000 HGRLIB = rel/apple/HGRLIB\#FE1000 GRLIB = rel/apple/GRLIB\#FE1000 DGRLIB = rel/apple/DGRLIB\#FE1000 -SPRITE = rel/apple/SPRITE\#FE1000 -LINES = rel/apple/LINES\#FE1000 +HGRSPRITE = rel/apple/HGRSPRITE\#FE1000 +LINES = rel/LINES\#FE1000 GRAFIX = rel/apple/GRAFIX\#FE1000 GFXDEMO = rel/apple/GFXDEMO\#FE1000 JOYBUZZ = rel/apple/JOYBUZZ\#FE1000 @@ -100,7 +100,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINES) $(SPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(COPY) $(DEL) $(REN) $(CAT) $(NEWDIR) $(TYPE) $(SOS) $(ROD) $(SIEVE) $(PRIMEGAP) $(MOUSE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(TFTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(LINES) $(HGRSPRITE) $(HGRLIB) $(HGRTEST) $(GRLIB) $(DGRLIB) $(GRTEST) $(DGRTEST) $(HGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(INT32) $(INT32TEST) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc @@ -417,9 +417,9 @@ $(DGRLIB): libsrc/apple/dgrlib.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < libsrc/apple/dgrlib.pla > libsrc/apple/dgrlib.a acme --setpc 4094 -o $(DGRLIB) libsrc/apple/dgrlib.a -$(SPRITE): libsrc/apple/sprite.pla $(PLVM02) $(PLASM) - ./$(PLASM) -AMOW < libsrc/apple/sprite.pla > libsrc/apple/sprite.a - acme --setpc 4094 -o $(SPRITE) libsrc/apple/sprite.a +$(HGRSPRITE): libsrc/apple/hgrsprite.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < libsrc/apple/hgrsprite.pla > libsrc/apple/hgrsprite.a + acme --setpc 4094 -o $(HGRSPRITE) libsrc/apple/hgrsprite.a $(HGRTEST): samplesrc/hgrtest.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/hgrtest.pla > samplesrc/hgrtest.a diff --git a/src/mkrel b/src/mkrel index 344df15..3854133 100755 --- a/src/mkrel +++ b/src/mkrel @@ -9,8 +9,8 @@ rm -rf prodos/sys mkdir prodos/sys cp rel/apple/FILEIO#FE1000 prodos/sys/FILEIO.REL cp rel/apple/CONIO#FE1000 prodos/sys/CONIO.REL -cp rel/apple/LINES#FE1000 prodos/sys/LINES.REL -cp rel/apple/SPRITE#FE1000 prodos/sys/SPRITE.REL +cp rel/LINES#FE1000 prodos/sys/LINES.REL +cp rel/apple/HGRSPRITE#FE1000 prodos/sys/HGRSPRITE.REL cp rel/apple/HGRLIB#FE1000 prodos/sys/HGRLIB.REL cp rel/apple/GRLIB#FE1000 prodos/sys/GRLIB.REL cp rel/apple/DGRLIB#FE1000 prodos/sys/DGRLIB.REL @@ -151,7 +151,7 @@ cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT cp inc/cmdsys.plh prodos/bld/inc/CMDSYS.PLH.TXT cp inc/conio.plh prodos/bld/inc/CONIO.PLH.TXT cp inc/lines.plh prodos/bld/inc/LINES.PLH.TXT -cp inc/sprite.plh prodos/bld/inc/SPRITE.PLH.TXT +cp inc/hgrsprite.plh prodos/bld/inc/HGRSPRITE.PLH.TXT cp inc/hgrlib.plh prodos/bld/inc/HGRLIB.PLH.TXT cp inc/grlib.plh prodos/bld/inc/GRLIB.PLH.TXT cp inc/dgrlib.plh prodos/bld/inc/DGRLIB.PLH.TXT diff --git a/src/samplesrc/hgrtest.pla b/src/samplesrc/hgrtest.pla index a2b802e..f04b3d4 100644 --- a/src/samplesrc/hgrtest.pla +++ b/src/samplesrc/hgrtest.pla @@ -1,6 +1,6 @@ include "inc/cmdsys.plh" include "inc/hgrlib.plh" -include "inc/sprite.plh" +include "inc/hgrsprite.plh" include "inc/lines.plh" sysflags reshgr1|reshgr2 // Reserve HGR page 1 and 2 diff --git a/src/tftpbld b/src/tftpbld index 9026726..9a53911 100755 --- a/src/tftpbld +++ b/src/tftpbld @@ -9,7 +9,7 @@ echo "BLD/INC/ARGS.PLH"; atftp $1 --put -l inc/args.plh -r $2/BLD/INC/ARG echo "BLD/INC/CMDSYS.PLH"; atftp $1 --put -l inc/cmdsys.plh -r $2/BLD/INC/CMDSYS.PLH#040000 echo "BLD/INC/CONIO.PLH"; atftp $1 --put -l inc/conio.plh -r $2/BLD/INC/CONIO.PLH#040000 echo "BLD/INC/LINES.PLH"; atftp $1 --put -l inc/lines.plh -r $2/BLD/INC/LINES.PLH#040000 -echo "BLD/INC/SPRITE.PLH"; atftp $1 --put -l inc/sprite.plh -r $2/BLD/INC/SPRITE.PLH#040000 +echo "BLD/INC/HGRSPRITE.PLH";atftp $1 --put -l inc/hgrsprite.plh -r $2/BLD/INC/HGRSPRITE.PLH#040000 echo "BLD/INC/HGRLIB.PLH"; atftp $1 --put -l inc/hgrlib.plh -r $2/BLD/INC/HGRLIB.PLH#040000 echo "BLD/INC/GRLIB.PLH"; atftp $1 --put -l inc/grlib.plh -r $2/BLD/INC/GRLIB.PLH#040000 echo "BLD/INC/DGRLIB.PLH"; atftp $1 --put -l inc/dgrlib.plh -r $2/BLD/INC/DGRLIB.PLH#040000 diff --git a/src/tftpsys b/src/tftpsys index ac879f8..8c986bb 100755 --- a/src/tftpsys +++ b/src/tftpsys @@ -22,8 +22,8 @@ echo "SYS/LONGJUMP"; atftp $1 --put -l rel/LONGJMP#FE1000 -r $2/SYS/LONGJMP#FE10 echo "SYS/MEMMGR"; atftp $1 --put -l rel/MEMMGR#FE1000 -r $2/SYS/MEMMGR#FE1000 echo "SYS/LZ4"; atftp $1 --put -l rel/LZ4#FE1000 -r $2/SYS/LZ4#FE1000 echo "SYS/CONIO"; atftp $1 --put -l rel/apple/CONIO#FE1000 -r $2/SYS/CONIO#FE1000 -echo "SYS/SPRITE"; atftp $1 --put -l rel/apple/SPRITE#FE1000 -r $2/SYS/SPRITE#FE1000 -echo "SYS/LINES"; atftp $1 --put -l rel/apple/LINES#FE1000 -r $2/SYS/LINES#FE1000 +echo "SYS/HGRSPRITE"; atftp $1 --put -l rel/apple/HGRSPRITE#FE1000 -r $2/SYS/HGRSPRITE#FE1000 +echo "SYS/LINES"; atftp $1 --put -l rel/LINES#FE1000 -r $2/SYS/LINES#FE1000 echo "SYS/HGRLIB"; atftp $1 --put -l rel/apple/HGRLIB#FE1000 -r $2/SYS/HGRLIB#FE1000 echo "SYS/GRLIB"; atftp $1 --put -l rel/apple/GRLIB#FE1000 -r $2/SYS/GRLIB#FE1000 echo "SYS/DGRLIB"; atftp $1 --put -l rel/apple/DGRLIB#FE1000 -r $2/SYS/DGRLIB#FE1000 From 8c885a6b8b94be7b06e4bb4b8e52154c422a5e85 Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Sat, 28 Dec 2019 13:40:04 -0800 Subject: [PATCH 091/149] Remove old pixmap data --- src/libsrc/apple/hgrlib.pla | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/libsrc/apple/hgrlib.pla b/src/libsrc/apple/hgrlib.pla index d5411e5..0d716c2 100644 --- a/src/libsrc/apple/hgrlib.pla +++ b/src/libsrc/apple/hgrlib.pla @@ -99,17 +99,6 @@ word curhclr byte drawpage = 1 word drawbuff = hgr2 -byte ball = $88, $8F, $FF, $F8, $88 -byte = $88, $FF, $FF, $FF, $88 -byte = $8F, $FF, $FF, $FF, $F8 -byte = $FF, $FF, $FF, $FF, $FF -byte = $FF, $FF, $FF, $FF, $FF -byte = $FF, $FF, $FF, $FF, $FF -byte = $FF, $FF, $FF, $FF, $FF -byte = $8F, $FF, $FF, $FF, $F8 -byte = $88, $FF, $FF, $FF, $88 -byte = $88, $8F, $FF, $F8, $88 - export asm divmod7(x)#2 !SOURCE "vmsrc/plvmzp.inc" LDA ESTKL+0,X ; X COORDL From 64f4f56379cc6a3f103fd550354789c51fff2cfd Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 28 Dec 2019 16:18:51 -0800 Subject: [PATCH 092/149] Add Apple /// non-jit default to free up a little memory and update images to DP2 --- images/apple/PLASMA2-BLD.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2-DEM.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2-FPSOS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2-INET.PO | Bin 0 -> 143360 bytes images/apple/PLASMA2-SYS.PO | Bin 143360 -> 143360 bytes images/apple/PLASMA2.2mg | Bin 819264 -> 819264 bytes src/makefile | 15 +- src/mkrel | 40 +- src/toolsrc/ed.pla | 2 +- src/toolsrc/plasm.pla | 2 +- src/vmsrc/apple/a1cmd.pla | 4 +- src/vmsrc/apple/cmd.pla | 2 +- src/vmsrc/apple/cmdjit.pla | 2 +- src/vmsrc/apple/plvm03.s | 6 +- src/vmsrc/apple/plvmjit03.s | 1436 +++++++++++++++++++++++++++++++++ src/vmsrc/apple/soscmd.pla | 59 +- src/vmsrc/apple/soscmdjit.pla | 329 ++++++++ src/vmsrc/apple/sossys.pla | 36 +- src/vmsrc/apple/sossysjit.pla | 1309 ++++++++++++++++++++++++++++++ 19 files changed, 3125 insertions(+), 117 deletions(-) create mode 100644 images/apple/PLASMA2-INET.PO create mode 100755 src/vmsrc/apple/plvmjit03.s create mode 100755 src/vmsrc/apple/soscmdjit.pla create mode 100755 src/vmsrc/apple/sossysjit.pla diff --git a/images/apple/PLASMA2-BLD.PO b/images/apple/PLASMA2-BLD.PO index 6288fb682bc58a03514803191e473e7f98b2d3cf..2a33e3b19efa589a3192f7a81ecf0f01d5baa373 100644 GIT binary patch delta 11191 zcmb_i3wRt?b)GvKY2{dJ$)y; z%I?aRLdrNaO(8%aUJ}s~0uinHfF{%;F?|FQCv9m);$w&;KE zo!On)hvo2fKWTU7p8q`V>zs4X%$Zk9&%9dt`TdGfBuORG<5eXU+oT^zxNud-(zimb z-F?B1kYs+!4@cIuAYvN z#RkSQST#rTZH$0*b{**Gx53sB7aFj`Rsr@SW|L+>u1l)!3m)yhv#-wToKgXE z`?Jh-NgH8Xx=YlnH4xWh7ssVt8@zL8#x%gz0@jjaoVUC8NJ#C-AeHsd%8G2(L0l?a zzIO0h2y?LM`G+@Iin;|WpWzOQ|@@q;a2gP zifhB#h?>xnylpBRO?bw9>M8HG2GtHoQ&Ud{uXmg9sYop8nMyqz+>ts^`=wNc{Pg_B z61jZ!B9oWcyjr?YBeTy`$n0FTOYx75#v}TmUFNWUYBDyw%QNHM7O=Mi*$2s~dxGn( z!S%6N`nCtRhk|<4GvoKEGXbAE3p=w|j}mtW2}B+U4y62_ z-e4r+LsQ9kE=yZ%YBm%f^2A0GNyzo7r+q30sSvz1I{XgM=$?r-u10vTg}xdv8Qz{q zW*a`7NapKjWxP8!tZnn#2Q)d8?B2MEPpF58*`wJO(Zcbp*3|v=n_4lfq0`|hr!+LS z$HS)&Opkb`!lRluhuRj4#NwWz2qq!bQu{oX)N^MyxE5UvZ!yCq9h5ww)*jnVl9cPE zGU?~*omONtXgcWP+x!7fGJX`!N#i1*;w9CduQu_k(MSY zb-)c}ZD5z=?dln54A@|Pz|~A=u!7#Ng@-*O5N;&MdE}803ZK$A0sy!T$l}{C50Z8VSC+d!O=AFn$H2wwu8f+;< zZXF)>=*tXTwNF}<<;$!}i+Er_fw9ea9&#^>6>=q;?~&!&dhX%Q^}A$4k0u*MI2wvY z6G=6Bx84{~_o+MiqOz~7d$oA1G2raaz1mFD-<-^8k7}dY&`2yi+!*jcx_z<@5s-Y;T0=lABEw9J^u(xrptA&w zYB>VZe32{gMXta%ipA&A4Rd_56(+BskTd4zixlQ-3?#9~#Tvv8OUC(H+~QC?HJt}-yyM)!B~}VQ8gFcB-i7^hi5asbVS0#flKOi7!yB-P$Uzc#mbX&sIXIitfX75_8PfV#%?48B3(b?(pIJ{yUyX zeYv+}arK=)Wyr$H&IVVk&r07jS$f+tS@~%Eib;7o0Z)CgZjE;|K0txm3_BEa9U(`M zL&>-&#p>%^qjB^m;z{kRuPhmjQ#P7XgX>ba*Lx`o-EStLSrVK%Xcp0#g5GxSgiEd* z&ON(idS41EKa`}7)v4DPI(YzO9y8F(O{s6!ZG-*IuzQP=w)$xOq3t|rc9;atEQ3=Y zso#PVSL^&;vU2mj{kQPVH$PaW9BA+86gN{P-YrO^HqqhSmVhaTkbga#m8PY_x2|2^ z1wwlk!39}Qvva3p#rUxFT2}QUQxR~9ioj}A1d6Jvkt(;f(&@Ps`jN^7QQ;V%B1a~b zL*b*A=gM?q6-cEIuB&j^Fo+fjabqcmGB7%psj9!X-Lj02uz?{7W*svQOP-7*F%j>RR!Wbo&DL6Zs3RDp z!-$wJN%;`8HfJq_!;4Grk>#RWyL+%AF0=VF%Grl@h)k(&Dl)d!?WQ6^QcF;vF!w8W zQ+mXw>SNqT#kIt7o=crn0pd;kOCLjWB^LZhEUxMix>b`g)h`;!O`EAwiyrZ&{oSO& z^97H;A=75&0)b2mk1q&bEzp^1H6t2tyjjIvM0n~bvNx_kSldk~dC=dGi)$K2+ z&f;q5y{(_mwc!{w(_G>&pjIR|`PJ^-S5U9TmeWmx4-YXGP$;sn{0jFMR%o&1C?tKH zPv|pf{n3nw#hRJO^yCu2K9e9^X)50#pMjMlCZz!5er%Ki3V&TbF&RQ1@4vH$`wDBc zbJDorV;h<)FpBBO)5Q~LqxmS@NuEvT;Vi&N`HDe(yM+gp~X*WDngP}Y!GKh!E-x6_!82b zf-D&phJcNY?+jy*)&C!Yc<-;mXg)$2g zXy;QQhUk#a)i_k-Cvz3FQLL~&7)kPyQ*?S#V$bgO{U71Sn!`CrAP%38rjL zAlVZn+vC9nsWVQhcd3oLylRcQ2j4eg9IT`QnmM+XE(mL#d!v|D8Z=X6Fwbi88q95}q0yMI%%I>;;`gexO)BL@bhBR# z>=tz>((mYk#b+fCG@jhLaf5zqgtgWkGoI?>v_B5M-tj^^M7j-+U@<-!+5=(%8 zPlyGU&ZP{2r85i__&kD~X{4GQb`KqVJYFJ3VzDVVchhL5M-uKFuyr76@OsJRhGObz zO&tnHu|qXAIfiRd@5S@2n86R#5RoJgfO!zotctK7+k^g__+JaTXRkZGn~@&SH9h5k z;S@G#XSye~$)TxP&-R^258+A!nICQsJ$IqiIT%Zhsm9>+$Oy^-g?r&gw}nwu>4ZSb zSbH;Ew!m2RXzGoF5zo8wAq<;rc-?#u8)E0O2n^IRGMXI-6w~;~J8a$MfaF8KuP>tp zUUL})&1(Ys@kpTHs8P^dPE3K3wGA6Z-2zfhkb0U}|MFw&FEqHc^2iCJ80;R^l0$BK zFo&&y3}z#ne@HGmao64AZ1!-;ns*Nl!Euj{>EjcT$!Kiqo;XNvuyc=9ZcSC*=Pphs zI4wLB<)$h9&^trY?EPm5bhdH$LLHqLFz2J`6XC zz-}cO<~i7rNnowR%AGv_uwsx9VW3qVj-8IeC5iaAjGRVnEv~|pqwDA*o!RwqT!^4d zEj(1?f*;lI+TPZ{FERt*r+%Cso4Z)d)?*NOscr%ziGK2>AwmJKj8US3Oai+ee=TAw zads7BOR)ixRCS`JhX0a1I)a+6i(3Rsij<8!QX)(?Ht}|fkz_EzHh|px3g6M>1Zkkr>NJU{=ETzq==-uK*x4e&Ob|4Nzs-ZQww z>kr?Q=f5LgbN_EX@LLc5_WM8Z&x@qbgE|D`NHlHzygmfUj6eP3mXsN~XduKy~0 zA06vvEN4g;%X-5YEBe@DbI^I2JzC2)&wYxq@LavZR?U5%u^Z`X;K0@T6xd2Go;wv= z5!mu7&1e&eNny7F2$iO>qi{t5j1m%nTA&OAwuBUw%k9c}V>lBR4|vNOLc zfp{y`gEQdi^qpuc;7CA0jr|Iq1b{2KlDUt=7uZ}z+7}=l&hi*HF6%MocDdLy3#Ckv zf9Df?4KA!=O8w(ceCpFr&VT0jet+Q){_v0f__Lq;lc%2k{GXm%{K7NOp8w*X{rO+~ z<#S*9^7AiTc=4sb`s=^>%HRIo-=FudVU6xm?Ze!q15sb|Z-ItzkEmur+f}_}PcC41EE%pKY0&2rxgZ zIRD82yL6r07dZckJ~qfI%b;P$#G3I{($V|$HNht(sH-+Mjc=LT(9dr1lL0$EyJmc& z_^n>@NfqN8%tn)EE%6MLc!i-4_Op9$aDDY_|M>Nnzwu8Pg}2y3l9l0TUTkE&mY8{* zK(8h8cMWB!qzZ2@*7qpBD!;^#Ty*%uG^`=h3FWfnmR4-A>ip$VRrvux$Uj~QFIz*fj_ zy^W@&XTQpdlwwAo$4cb?ExWYzD~ZWyDsh#9{yz)fU>g@oWLC6dWm)Pr_42~&tW+`4 bmt3nVR6T)ldW2)ljZ*d4S|6l delta 11195 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 diff --git a/images/apple/PLASMA2-DEM.PO b/images/apple/PLASMA2-DEM.PO index b008aff4b0c169b57f82fc4cc8ac1f5476597cc4..5d144ce9e5bd1bf8c2171e02f4caf3999c54b4db 100644 GIT binary patch delta 4817 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 delta 5929 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 diff --git a/images/apple/PLASMA2-INET.PO b/images/apple/PLASMA2-INET.PO new file mode 100644 index 0000000000000000000000000000000000000000..dd75073710d8a2ee95808341bb75518414c8e919 GIT binary patch literal 143360 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