From 0b750d46c5dfb9096ecfc85e19184d8a05cd0ccf Mon Sep 17 00:00:00 2001 From: Dave Schmenk Date: Wed, 18 Dec 2019 18:59:24 -0800 Subject: [PATCH] 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