From 57cf76357b956061ec64e1c5424fa12560acad95 Mon Sep 17 00:00:00 2001 From: Martin Haye Date: Mon, 12 Aug 2013 06:34:37 -0700 Subject: [PATCH] Tentative build process for the Apple II. --- .gitignore | 3 +- Platform/Apple/tools/A2Copy/build.xml | 3 +- .../tools/A2Copy/nbproject/build-impl.xml | 99 +- .../A2Copy/nbproject/genfiles.properties | 8 +- Platform/Apple/virtual/build.xml | 57 + .../Apple/virtual/data/disks/base.2mg.bz2 | Bin 0 -> 39616 bytes .../Apple/virtual/data/tables/precast.bin | Bin 0 -> 17538 bytes .../virtual/src/include/sample.build.props | 8 + Platform/Apple/virtual/src/raycast/build.xml | 56 + Platform/Apple/virtual/src/raycast/main.s | 0 Platform/Apple/virtual/src/raycast/render.s | 1149 +++++++++++++++++ 11 files changed, 1322 insertions(+), 61 deletions(-) create mode 100644 Platform/Apple/virtual/build.xml create mode 100644 Platform/Apple/virtual/data/disks/base.2mg.bz2 create mode 100644 Platform/Apple/virtual/data/tables/precast.bin create mode 100644 Platform/Apple/virtual/src/include/sample.build.props create mode 100644 Platform/Apple/virtual/src/raycast/build.xml delete mode 100644 Platform/Apple/virtual/src/raycast/main.s create mode 100644 Platform/Apple/virtual/src/raycast/render.s diff --git a/.gitignore b/.gitignore index 8c262ef5..4c410b76 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /OutlawEditor/target/ /Platform/Apple/tools/A2Copy/nbproject/private/ /Platform/Apple/tools/A2Copy/dist/ -/Platform/Apple/tools/A2Copy/build/ \ No newline at end of file +/Platform/Apple/tools/A2Copy/build/ +/Platform/Apple/virtual/data/images/*.bin diff --git a/Platform/Apple/tools/A2Copy/build.xml b/Platform/Apple/tools/A2Copy/build.xml index b5380796..f29a3fd4 100644 --- a/Platform/Apple/tools/A2Copy/build.xml +++ b/Platform/Apple/tools/A2Copy/build.xml @@ -51,8 +51,7 @@ -init-macrodef-junit: defines macro for junit execution -init-macrodef-debug: defines macro for class debugging -init-macrodef-java: defines macro for class execution - -do-jar-with-manifest: JAR building (if you are using a manifest) - -do-jar-without-manifest: JAR building (if you are not using a manifest) + -do-jar: JAR building run: execution of project -javadoc-build: Javadoc generation test-report: JUnit report generation diff --git a/Platform/Apple/tools/A2Copy/nbproject/build-impl.xml b/Platform/Apple/tools/A2Copy/nbproject/build-impl.xml index c7fc01b8..2d13575a 100644 --- a/Platform/Apple/tools/A2Copy/nbproject/build-impl.xml +++ b/Platform/Apple/tools/A2Copy/nbproject/build-impl.xml @@ -54,6 +54,7 @@ is divided into following sections: + @@ -71,10 +72,11 @@ is divided into following sections: - + - - + + + @@ -91,12 +93,6 @@ is divided into following sections: - - - - - - @@ -115,24 +111,12 @@ is divided into following sections: - + - + - - - - - - - - - - - - @@ -188,6 +172,9 @@ is divided into following sections: + + + @@ -275,6 +262,7 @@ is divided into following sections: + @@ -314,6 +302,7 @@ is divided into following sections: + @@ -446,7 +435,7 @@ is divided into following sections: - + @@ -837,7 +826,7 @@ is divided into following sections: - + @@ -966,41 +955,25 @@ is divided into following sections: - - - - - - - - - - - - - To run this application from the command line without Ant, try: - - - - - - - java -cp "${run.classpath.with.dist.jar}" ${main.class} - - + - + - + - + + + + + + @@ -1008,23 +981,41 @@ is divided into following sections: - + To run this application from the command line without Ant, try: java -jar "${dist.jar.resolved}" - + + + + + + + + + + + + + + + + + - + + - + + + + + + + + + + + + + + + + + + + + + + + + + Building raycast. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Platform/Apple/virtual/data/disks/base.2mg.bz2 b/Platform/Apple/virtual/data/disks/base.2mg.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..dbbcab7787c58d1950dfb89308ff0c2253b15227 GIT binary patch literal 39616 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 z zoe=);{ueBQO|T0t!N&*r5TDE!=JUWENC|f#O%5R^+2%*q+qSFHMf)k|QTGAw9{=|L zL;n9iASX2j5>vD3Mf6H)Bm4$gN>7<7x6nuEA#@cw3hjWwHU|d#iCAA(8`9oYbQN_G z_KAw+@K0tSGn^UAOkqBU{L%_~9k_@pNX!^18|4#v3*Ch-LZ;AGXeBfgKLv_g7btF3 zpt$A4(qai+(YNzYoRUMDcs4Ot{*ec7Jl~)B|GE6%{92APY22EWxAKqg&U^jA|EHeP zed+FW=N$k0t^A+Ts^bLOgE_IPI@DKS% ztbXmSe}w-}b!W=4ec7IDS2puE|NEW!zkJ~W$*L4ORg=cU_%1L^QiQkjpRe{yqOc!heqHZvFQA|8V|+vp^0DLmrEVT$UR0S$X~y|3AWizSI9` zc$7Q;`~Lg`kKmMH!Mj&LF6-am|9?3Dojd>V#x#0421cSCmrcRf!XPi;?4PjzoKZxwH4Z$)1PUpZe{Uul0Sf4aYfzZkfGX@S&W zVd#-b4i=Qduh~Un5PE2QiQbS0dTLxDN0J?SY!Z@e;dtn|v4qX<$$#hPlrd>BDKTM_ zZ1TmrVkKZbadD?q;%?xn=c((h?XBgj;j8Yi>aP;06sQ=i5G)7&Y8mkVK5+l#u{Ks~*4nfVtw$Ts zhP27r)IZIC=hY}Qw6SnZK~tj1AM1{_6I+}mF4kD%?EOSpFnX&sWn^)m7e6 z>RtKokL>^ZaF<{qAgTY8|E`)^DW!aJnQ+NaabOyMlK=h-{eO8-exyL^H@$*76pel( zGdaD2J`_YDR1l?nZ2tRi^#A3-`EdcP!W3pPhXt&|(HLVBCO}Q&fu1^mqIy3f|NXD^ z|K%n5NdclHYC;1W)e?c|h@KdTk(hGG%b(=G|GoWx@98D{-TwdY^#A1n4w^sGWvKj{ z{eOAjbH2MeWFk2)qA5o*pu@N5_v|vGr?(hI2|s# z*Y3~hu1rWuC}>NurN*ayWdBQ)Q4RZ0Fc=K6(ecqvyu z(J^`}q!0YMur5th3R(d}4#THS(Z19^)jrbR)85wJ&|cO4puNbSjifscLFRoAWZ$>) zoB0j=*ZeB*43`LtpyzFF?)ne1`OhGu{{XW3xA^Oj?7sy0{WH+Vd?b<(*#+L-hx6Yr z;TeyiU*InE4O}z7qy7cXmMRyHQ1*iVQ~!yt#Ao8K;zJ<2w}J3p1JZj5nDH54$H$XeE$1qIo@0U0*8Kr9-;f_F1m$oK!5TT=u^H3{mQ4IZ}}+nFCTzD z=H1ZGy!9{Szq8Q`^b|ct579kz2i-*1(N%OAeUHwgGw4((SN)6cKp*lA=tsT+eaYWL zfAU%AQ$7Lx%7>wEc|Y_o?}9$&t$!o`osD1MXZTnA2;axQ;M@2nzK(ywKjI(oMSLEg z!Kd(X4E=ZH2k1k-0R6~kpfC9Z^d}#IKIH?@ue=BPmUn=E_pjx@Uy&E&8F@k;lZWIU zxl3-7o8$($My`?{b4G^!e;oRdk3c{2LFh}~2mQ&rp-*`S_;vr@{P!#9c6cs5m41~T zOAn!g_nvfDx-H#;-~S%yL*5Df$lJk}{_o_!v!U1Q1@xRflb`&}{CBqhmH&nRx&Nu} ziSM!Rk?(=`zV{dJUGHtrEzi%M>z-@wtL`7&m!Wt0qU(a|oa>D9l=Fo1nDeOPu;ZZP zfMcJ1kA0VYhkYB&|5y2O@KNwV;C|qq|E~Xz@0RbT_lEbn=O<6jGk%CX$<9YD*4I=O3KB4_wPUaFaP@=|M + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Platform/Apple/virtual/src/raycast/main.s b/Platform/Apple/virtual/src/raycast/main.s deleted file mode 100644 index e69de29b..00000000 diff --git a/Platform/Apple/virtual/src/raycast/render.s b/Platform/Apple/virtual/src/raycast/render.s new file mode 100644 index 00000000..be289a7e --- /dev/null +++ b/Platform/Apple/virtual/src/raycast/render.s @@ -0,0 +1,1149 @@ + +CODEBEG = * + + .pc02 ; Enable 65c02 ops + +; This code is written bottom-up. That is, +; simple routines first, then routines that +; call those to build complexity. The main +; code is at the very end. We jump to it now. + JMP TEST + +; Conditional assembly flags +DBLBUF = 0 ; whether to double-buffer +DEBUG = 0 ; turn on verbose logging + +; Constants +TOPLINE = $2000 +NLINES = 126 +SKYCOL = $11 ; blue +GROUNDCOL = $2 ; orange / black + +; My zero page +LINECT = $3 ; len 1 +BUMP = $4 ; len 1 +TXCOLNUM = $5 ; len 1 +PLINE = $6 ; len 2 +PDST = $8 ; len 2 +PTEX = $A ; len 2 +PBUMP = $C ; len 2 +PIXNUM = $E ; len 1 +BYTENUM = $F ; len 1 +PTMP = $10 ; len 2 +BACKBUF = $12 ; len 1 (value 0 or 1) +FRONTBUF = $13 ; len 1 (value 0 or 1) +PCAST = $14 ; len 2 + +; Monitor zero page +STARTADDR = $3C +ENDADDR = $3E +DESTADDR = $42 + +; Place to stick ProDOS names temporarily +NAMEBUF = $280 + +; Tables and buffers +SH0101 = $1000 +SH0123 = $1100 +SH0145 = $1200 +SH0156 = $1300 +SH0157 = $1400 +SH4501 = $1500 +SH4523 = $1600 +SH4545 = $1700 +SH4556 = $1800 +SH4557 = $1900 +BLITIDXL = $1A00 ; size $80 +BLITIDXH = $1A80 ; size $80 +DCMIDXL = $1B00 ; size $40 (one entry per two lines) +DCMIDXH = $1B40 ; size $40 +X1B80 = $1B80 ; unused +DCMROLL = $1C00 ; size 11*(126/2) = 693 = $2B5, plus 1 for rts +CBLITROLL = $1F00 ; size 3*(126/2) = 189 = $BD, plus 2 for tya & rts + +PRODOSBUF = $1000 ; temporary, before tbls built +SCREEN = $2000 + +TEXTURES = $4000 ; size $5550 (5460 bytes x 4 textures) +TEXSIZE = 5460 +TEX0 = TEXTURES +TEX1 = TEX0+TEXSIZE +TEX2 = TEX1+TEXSIZE +TEX3 = TEX2+TEXSIZE +UN9550 = $9550 ; unused +BLITROLL = $A000 ; size 29*126 = 3654 = $E80, plus 1 for rts +BUMPS = $AF00 ; len 64*64 = $1000 +GLOBALPG = $BF00 ; ProDOS global page +MLI = GLOBALPG ; also the call point for ProDOS MLI +MEMMAP = $BF58 + +; I/O locations +KBD = $C000 +CLRAUXRD = $C002 +SETAUXRD = $C003 +CLRAUXWR = $C004 +SETAUXWR = $C005 +CLRAUXZP = $C008 +SETAUXZP = $C009 +KBDSTRB = $C010 +CLRTEXT = $C050 +SETTEXT = $C051 +CLRMIXED = $C052 +SETMIXED = $C053 +PAGE1 = $C054 +PAGE2 = $C055 +CLRHIRES = $C056 +SETHIRES = $C057 + +; ROM routines +AUXMOVE = $C311 +PRNTAX = $F941 +RDKEY = $FD0C +CROUT = $FD8E +PRBYTE = $FDDA +COUT = $FDED +PRERR = $FF2D +MONITOR = $FF69 + +; Pixel offsets for even and odd blit lines +BLITOFFE: .byte 5,8,11,1,17,20,24 +BLITOFFO: .byte 34,37,40,30,46,49,53 +; texture addresses +TEXADRL: .byte TEX0,>TEX1,>TEX2,>TEX3 + ; mip level offsets +MIPOFFL: .byte <0,<4096,<5120,<5376,<5440,<5456,<5460 +MIPOFFH: .byte >0,>4096,>5120,>5376,>5440,>5456,>5460 + +NEXTLINE: + LDA PLINE+1 ; Hi byte of line + CLC + ADC #4 ; Next line is 1K up + TAX + EOR PLINE+1 + AND #$20 ; Past end of screen? + BEQ @DONE ; If not, we're done + TXA + SEC + SBC #$20 ; Back to start + TAX + LDA PLINE ; Lo byte + CLC + ADC #$80 ; Inner blks offset by 128 bytes + STA PLINE + BCC @DONE + INX ; Next page + TXA + AND #7 + CMP #4 ; Still inside inner blk? + BNE @DONE ; If so we're done + TXA + SEC + SBC #4 ; Back to start of inner blk + TAX + LDA PLINE + CLC + ADC #$28 ; Outer blks offset by 40 bytes + STA PLINE +@DONE: + STX PLINE+1 + RTS + +; Template for blitting code + +BLITTPL: ; comments show byte offset +; even rows + LDA SH0157 ; 0: pixel 3 + ASL ; 3: save half of pix 3 in carry + ORA SH0101 ; 4: pixel 0 + ORA SH0123 ; 7: pixel 1 + ORA SH0145 ; 10: pixel 2 + STA (0),Y ; 13: even column + INY ; 15: prep for odd + LDA SH0101 ; 16: pixel 4 + ORA SH0123 ; 19: pixel 5 + ROL ; 22: recover half of pix 3 + ORA SH0156 ; 23: pixel 6 - after rol to ensure right hi bit + STA (0),Y ; 26: odd column + DEY ; 28: prep for even +; odd rows + LDA SH4557 ; 29: pixel 3 + ASL ; 32: save half of pix 3 in carry + ORA SH4501 ; 33: pixel 0 + ORA SH4523 ; 36: pixel 1 + ORA SH4545 ; 39: pixel 2 + STA (2),Y ; 42: even column + INY ; 44: prep for odd + LDA SH4501 ; 45: pixel 4 + ORA SH4523 ; 48: pixel 5 + ROL ; 51: recover half of pix 3 + ORA SH4556 ; 52: pixel 6 - after rol to ensure right hi bit + STA (2),Y ; 55: odd column + DEY ; 57: prep for even + ; 58: total + +; Create the unrolled blit code +MAKEBLIT: + LDA #0 ; Start with line zero + STA LINECT + LDA #TOPLINE + STA PLINE+1 + LDA #BLITROLL + STA PDST+1 +@LINELUP: +; Copy the template + LDY #57 +@COPY: + LDA BLITTPL,Y + STA (PDST),Y + DEY + BPL @COPY + ; Record the address for the even line + JSR @STIDX +; Set the even line pointers + LDY #14 + JSR @STLINE + LDY #27 + JSR @STLINE + ; Get ready for odd line + JSR @ADVANCE + ; Record the address for the odd line + JSR @STIDX +; Set the odd line pointers + LDY #14 + JSR @STLINE + LDY #27 + JSR @STLINE + ; Prepare for next iteration + JSR @ADVANCE +; Loop until all lines are done + LDA LINECT + CMP #NLINES + BNE @LINELUP + JSR @STIDX ; Last addr to index + JMP STRTS ; Finish with RTS for cleanliness +@STLINE: ; Subroutine to store PLINE to PDST + LDA LINECT + ASL + STA (PDST),Y + RTS +@STIDX: ; Subroutine to store tbl ptr to index + LDY LINECT + LDA PDST + STA BLITIDXL,Y + LDA PDST+1 + STA BLITIDXH,Y + RTS +@ADVANCE: ; Subroutine to go to next unroll + LDA #29 + JSR ADVPDST + INC LINECT + JMP NEXTLINE + +; Create code to clear the blit +MAKECBLIT: + LDX #0 + LDY #0 +@LUP: + LDA @ST + STA CBLITROLL,X + INX + LDA BLITIDXL,Y + STA CBLITROLL,X + INX + LDA BLITIDXH,Y +@ST: + STA CBLITROLL,X + INX + INY + INY + CPY #64 + BNE @NOSWITCH + LDA @TYA ; switch from sky color to ground color + STA CBLITROLL,X + INX +@NOSWITCH: + CPY #NLINES + BNE @LUP + LDA @RTS + STA CBLITROLL,X +@RTS: + RTS +@TYA: + TYA + +; Clear the blit +CLRBLIT: + LDY #GROUNDCOL +CLRBLIT2: + LDX BLITOFFE+0 + LDA #SKYCOL + JSR CBLITROLL + LDX BLITOFFE+1 + LDA #SKYCOL + JSR CBLITROLL + LDX BLITOFFE+2 + LDA #SKYCOL + JSR CBLITROLL + LDX BLITOFFE+3 + LDA #SKYCOL + JSR CBLITROLL + LDX BLITOFFE+4 + LDA #SKYCOL + JSR CBLITROLL + LDX BLITOFFE+5 + LDA #SKYCOL + JSR CBLITROLL + LDX BLITOFFE+6 + LDA #SKYCOL + JSR CBLITROLL + LDX BLITOFFO+0 + LDA #SKYCOL + JSR CBLITROLL + LDX BLITOFFO+1 + LDA #SKYCOL + JSR CBLITROLL + LDX BLITOFFO+2 + LDA #SKYCOL + JSR CBLITROLL + LDX BLITOFFO+3 + LDA #SKYCOL + JSR CBLITROLL + LDX BLITOFFO+4 + LDA #SKYCOL + JSR CBLITROLL + LDX BLITOFFO+5 + LDA #SKYCOL + JSR CBLITROLL + LDX BLITOFFO+6 + LDA #SKYCOL + JMP CBLITROLL + +; Construct the shift tables +MAKESHIFT: + LDX #0 +@SH01: + TXA + AND #3 +@SH0101: + STA SH0101,X +@SH0123: + ASL + ASL + STA SH0123,X +@SH0145: + ASL + ASL + ORA #$80 + STA SH0145,X +@SH0156: + ASL + ORA #$80 + STA SH0156,X +@SH0157: + ASL + ASL + PHP + LSR + PLP + ROR + STA SH0157,X +@SH45: + TXA + LSR + LSR + LSR + LSR + AND #3 +@SH4501: + ORA #$80 + STA SH4501,X +@SH4523: + ASL + ASL + ORA #$80 + STA SH4523,X +@SH4545: + ASL + ASL + ORA #$80 + STA SH4545,X +@SH4556: + ASL + ORA #$80 + STA SH4556,X +@SH4557: + ASL + ASL + PHP + LSR + PLP + ROR + STA SH4557,X +@NEXT: + INX + BNE @SH01 + RTS + +; Template for decimation. Offsets in comments +DCMTPL: + LDA (PTEX),Y ; 0 + STA BLITROLL,X ; 2 + STA BLITROLL+29,X ; 5 + LDA (PBUMP),Y ; 8 + TAY ; 10 + ; 11 + +; Unroll the decimation code +MAKEDCM: + LDX #0 ; Line counter + LDA #DCMROLL + STA PDST+1 +@ONESET: +; Save address to the index + JSR @STIDX + LDY #11 ; Copy the template +@COPYSET: + LDA DCMTPL,Y + STA (PDST),Y + DEY + BPL @COPYSET + LDY #3 + JSR @STBLIT + LDY #6 + JSR @STBLIT + LDA #11 + JSR ADVPDST +@MORE: + ; Loop until all lines done + CPX #NLINES + BCC @ONESET + JSR @STIDX ; Last addr to index + JMP STRTS ; Finish with an RTS for cleanliness +@STBLIT: ; Store current blit addr + LDA BLITIDXL,X + STA (PDST),Y + INY + LDA BLITIDXH,X + STA (PDST),Y + INX ; Next line + RTS +@STIDX: + TXA + LSR ; One entry per two lines + TAY + LDA PDST + STA DCMIDXL,Y + LDA PDST+1 + STA DCMIDXH,Y + RTS + +STRTS: + LDA #$60 ; Store an RTS at PDST + LDY #0 + STA (PDST),Y + RTS +ADVPDST: ; Add A to PDST + CLC + ADC PDST + STA PDST + BCC @RTS + INC PDST+1 +@RTS: + RTS + +; Clear all the memory we're going to fill +CLRMEM: + LDX #$10 + LDA #$BE + JMP CLRSCR2 + +; Clear the screens +CLRSCR: + LDX #>SCREEN + .if DBLBUF + LDA #>SCREEN + $40 ; both hi-res screens + .else + LDA #>SCREEN + $20 ; one hi-res screen + .endif +CLRSCR2: + STA @LIMIT+1 + LDY #0 + STY PDST + TYA +@OUTER: + STX PDST+1 +@INNER: + STA (PDST),Y + INY + BNE @INNER + INX +@LIMIT: + CPX #>SCREEN + $20 + BNE @OUTER + RTS + +; Make a simple texture with alternating colors. +; Input: Y = tex num +; A, X: color numbers, 0-3 +SIMPLETEX: + STA @LD1+1 + TXA + ASL + ASL + ASL + ASL + STA @LD2+1 + LDA TEXADRL,Y + STA PDST + LDA TEXADRH,Y + STA PDST+1 + LDX #>TEXSIZE + LDY #0 + STY @LIM+1 +@OUTER: +@LD1: + LDA #0 +@LD2: + ORA #0 +@LUP: + STA (PDST),Y + INY +@LIM: + CPY #0 + BNE @LUP + INC PDST+1 + DEX + BMI @DONE + BNE @OUTER + LDA #BUMPS + STA PDST+1 + LDA #0 + STA @RATIOL + LDA #1 + STA @RATIOH +; Goal is to make ratio = 63 divided by targetSize. +; The calculation is cool & weird, but I verified +; in Python that the logic actually works. You +; start with hi=1, lo=0. To calculate the next +; step, add hi to low and take the sum mod the next +; target size. To use the ratio, increment by hi +; and lo. Whenever the low byte goes beyond the +; target size, add an extra to hi. +@ONEPASS: + LDA LINECT ; Init A with the lo byte = target size + LSR ; ...div 2 + LDX #0 ; Hi byte always starts at zero + LDY #0 ; Location to store at +@BUMPLUP: + CLC ; increment lo byte by ratio + ADC @RATIOL + CMP LINECT ; if we wrap around, need extra hi-byte bump + BCC @NOBM + SEC + SBC LINECT + INX +@NOBM: + PHA ; save lo byte + TXA ; now work on hi byte + CLC + ADC @RATIOH + TAX + STA (PDST),Y ; store to the table + TAY ; next loc to store + CPX #63 ; check for end of column + PLA ; get lo byte back + BCC @BUMPLUP ; loop until whole column is done + LDA #64 + JSR ADVPDST ; advance dst to next column +@NEXT: + DEC LINECT ; all columns complete? + BEQ @DONE + LDA @RATIOL ; next ratio calculation (see explanation above) + CLC + ADC @RATIOH +@MODLUP: + CMP LINECT + BCC @NOMOD + INC @RATIOH + SEC + SBC LINECT + BNE @MODLUP ; this must indeed be a loop +@NOMOD: + STA @RATIOL + JMP @ONEPASS ; next column +@DONE: + RTS +@RATIOL: .byte 0 +@RATIOH: .byte 0 + +; Decimate a column of the texture +; Input: Y - texture number +; TXCOLNUM - src column num in the texture +; PIXNUM - dst pixel num in the blit roll +; LINECT - height to render, in dbl lines +; The output will be vertically centered. +DCMCOL: + ; if height is zero, render nothing + LDA LINECT + BNE @NOTZERO + RTS +@NOTZERO: + ; determine mip level in X reg + LDX #0 + LDA LINECT + STA @ADJHT + LDA TXCOLNUM + STA @ADJCOL + LDA #32 +@MIPLUP: + CMP LINECT + BCC @GOTMIP + INX + ASL @ADJHT + LSR @ADJCOL + LSR + CMP #2 + BCS @MIPLUP +@GOTMIP: + .if DEBUG + LDA #"t" + JSR COUT + TYA + JSR PRBYTE + LDA #" " + JSR COUT + + LDA #"h" + JSR COUT + LDA LINECT + JSR PRBYTE + LDA #" " + JSR COUT + + LDA #"m" + JSR COUT + TXA + JSR PRBYTE + LDA #" " + JSR COUT + .endif + + ; calc addr of tex + LDA TEXADRL,Y + CLC + ADC MIPOFFL,X + STA PDST + LDA TEXADRH,Y + ADC MIPOFFH,X + STA PDST+1 + + .if DEBUG + LDA #"a" + JSR COUT + LDA PDST+1 + JSR PRBYTE + LDA PDST + JSR PRBYTE + LDA #" " + JSR COUT + .endif + +@CALCOFF: ; calc offset within tex + LDA #0 + STA PTEX+1 + LDA @ADJCOL +@SHIFT: + ASL + ROL PTEX+1 + INX ; Note: destroys mip level + CPX #6 + BNE @SHIFT + + .if DEBUG + PHA + LDA #"x" + JSR COUT + LDA @ADJCOL + JSR PRBYTE + LDA #" " + JSR COUT + + LDA #"o" + JSR COUT + LDA PTEX+1 + JSR PRBYTE + PLA + PHA + JSR PRBYTE + LDA #" " + JSR COUT + PLA + .endif + + CLC + ADC PDST + STA PTEX + LDA PTEX+1 + ADC PDST+1 + STA PTEX+1 +; calculate bump table ptr + LDX @ADJHT + JSR CALCBUMP + ; figure first line in decim unroll + LDA #63 + SEC + SBC LINECT ; height 63 is first in decim tbl + LSR + TAX + LDA DCMIDXL,X + STA @CALL+1 + LDA DCMIDXH,X + STA @CALL+2 + ; figure last line of decim unroll + TXA + CLC + ADC LINECT + TAX + LDA DCMIDXL,X + STA PTMP + LDA DCMIDXH,X + STA PTMP+1 +; determine blit offset for writing + LDY PIXNUM + LDX BLITOFFE,Y + ; store RTS so decim returns @ right moment + LDY #0 + LDA (PTMP),Y ; save existing byte + PHA + LDA @RTS + STA (PTMP),Y + + .if DEBUG + PHX + PHY + JSR RDKEY + PHA + JSR CROUT + PLA + PLY + PLX + CMP #$9B + BNE @NOTESC + BRK +@NOTESC: + NOP + .endif + +@CALL: + JSR DCMROLL +; fix RTS to what it was before + LDY #0 + PLA + STA (PTMP),Y + + .if DEBUG + LDY BYTENUM ; to see results early + STA SETAUXZP + JSR BLITROLL + STA CLRAUXZP + .endif + +@RTS: + RTS +@ADJHT: .byte 0 +@ADJCOL: .byte 0 + +; Calc pointer into the bump table +; Input: X - height to render in dbl lines +CALCBUMP: + STX @SUB+1 + LDA #0 + STA PBUMP+1 + LDA #63 ; bump 63 is actually first + SEC +@SUB: + SBC #0 + BPL @NOTNEG + LDA #0 +@NOTNEG: + + .if DEBUG + PHA + LDA #"b" + JSR COUT + PLA + PHA + JSR PRBYTE + LDA #" " + JSR COUT + PLA + .endif + + LDX #6 +@LUP: + ASL + ROL PBUMP+1 + DEX + BNE @LUP + CLC + ADC #BUMPS + STA PBUMP+1 + + .if DEBUG + LDA #"p" + JSR COUT + LDA PBUMP+1 + JSR PRBYTE + LDA PBUMP + JSR PRBYTE + LDA #" " + JSR COUT + .endif + + RTS + +; Build table of screen line pointers +; on aux zero-page +MAKELINES: + LDA #0 + STA LINECT + LDA #TOPLINE + STA PLINE+1 +@LUP: + LDA LINECT + ASL + TAX + LDA PLINE + LDY PLINE+1 + STA SETAUXZP + STA 0,X + STY 1,X + STA CLRAUXZP + JSR NEXTLINE + INC LINECT + LDA LINECT + CMP #NLINES + BNE @LUP + RTS + +; Set screen lines to current back buf +SETBKBUF: +; calculate screen start + LDA BACKBUF + ASL + ASL + ASL + ASL + ASL + CLC + ADC #$20 + STA SETAUXZP + STA $FF + LDX #0 +@LUP: + LDA 1,X + AND #$1F + ORA $FF + STA 1,X + INX + INX + BNE @LUP + STA CLRAUXZP + RTS + +; Load file, len-prefixed name in A/X (hi/lo), to addr on stack +; (push hi byte first, then push lo byte) +BLOAD: + STX @MLICMD+1 ; filename lo + STA @MLICMD+2 ; filename hi + LDA #PRODOSBUF + STA @MLICMD+4 + LDA #$C8 ; open + LDX #3 + JSR @DOMLI + LDA @MLICMD+5 ; get handle and put it in place + STA @MLICMD+1 + PLY ; save ret addr + PLX + PLA + STA @MLICMD+2 ; load addr lo + PLA + STA @MLICMD+3 ; load addr hi + PHX ; restore ret addr + PHY + LDA #$CA ; read + STA @MLICMD+5 ; also length (more than enough) + LDX #4 + JSR @DOMLI +@CLOSE: + STZ @MLICMD+1 ; close all + LDA #$CC + LDX #1 + ; fall through +@DOMLI: + STA @MLIOP + STX @MLICMD + JSR MLI +@MLIOP: .byte 0 + .addr @MLICMD + BCS @ERR + RTS +@ERR: + JSR PRBYTE + JSR PRERR + LDX #$FF + TXS + JMP MONITOR +@MLICMD: .res 10 ; 10 bytes should be plenty + +; Copy X pages starting at pg Y to aux mem +CPTOAUX: + STA SETAUXWR + STY PDST+1 + LDY #0 + STY PDST +@LUP: + LDA (PDST),Y + STA (PDST),Y + INY + BNE @LUP + INC PDST+1 + DEX + BNE @LUP + STA CLRAUXWR + RTS + +; Fetch the next byte from the pre-raycasted data +; Note this routine needs to be copied to aux mem. +GETCAST: + LDY #0 + STA SETAUXRD + LDA (PCAST),Y + STA CLRAUXRD + INC PCAST + BNE @DONE + INC PCAST+1 +@DONE: + RTS + +; Test code to see if things really work +TEST: + ; clear ProDOS mem map so it lets us load + LDX #$18 + LDA #1 +@MEMLUP: + STA MEMMAP-1,X + LDA #0 + DEX + BNE @MEMLUP +; load the pre-raycast data + LDA #$20 ; addr hi + PHA + LDA #0 ; addr lo + PHA + LDX #<@PRECASTNM + LDA #>@PRECASTNM + JSR BLOAD +; copy it to aux mem + LDY #$20 + LDX #$60 + JSR CPTOAUX + LDA #0 ; set ptr to it + STA PCAST + LDA #$20 + STA PCAST+1 +; copy our code to aux mem + LDY #>CODEBEG + LDX #>CODEEND - >CODEBEG + 1 + JSR CPTOAUX +; set up everything else + JSR CLRMEM + ; load the textures + LDA #>TEX0 + PHA + LDA #@TEX0NAME + JSR BLOAD + + LDA #>TEX1 + PHA + LDA #@TEX1NAME + JSR BLOAD + + LDA #>TEX2 + PHA + LDA #@TEX2NAME + JSR BLOAD + + LDA #>TEX3 + PHA + LDA #@TEX3NAME + JSR BLOAD +; build all the unrolls and tables + JSR MAKEBLIT + JSR MAKECBLIT + JSR MAKESHIFT + JSR MAKEDCM + JSR MAKEBUMPS + JSR MAKELINES + JSR CLRSCR +; set up front and back buffers + LDA #0 + STA FRONTBUF + .if DBLBUF + LDA #1 + .endif + STA BACKBUF + + BIT CLRTEXT + BIT SETHIRES + + LDA #63 + STA LINECT + LDA #1 + STA @DIR + JSR CLRBLIT +@ONELVL: + LDA #0 + STA PIXNUM + STA BYTENUM + .if DBLBUF + JSR SETBKBUF + .endif + + .if DEBUG + LDA PCAST+1 + JSR PRBYTE + LDA PCAST + JSR PRBYTE + JSR CROUT + .endif + +@ONECOL: + JSR GETCAST ; first byte is height + CMP #$FF + BNE @NORESET +; found end of cast data, start over + LDA #0 + STA PCAST + LDA #$20 + STA PCAST+1 + JSR GETCAST +@NORESET: + CMP #63 + BCC @HTOK + LDA #62 +@HTOK: + STA LINECT + JSR GETCAST ; second byte is tex num and tex col + PHA + AND #$3F + CMP #63 + BCC @COLOK + LDA #62 +@COLOK: + STA TXCOLNUM + PLA + LSR ; div by 64 + LSR + LSR + LSR + LSR + LSR + TAY ; Y now holds tex num + JSR DCMCOL + INC PIXNUM + LDA PIXNUM + CMP #7 + BNE @ONECOL +@FLUSH: + LDY BYTENUM + STA SETAUXZP + JSR BLITROLL + STA CLRAUXZP + JSR CLRBLIT + LDA #0 + STA PIXNUM + INC BYTENUM + INC BYTENUM + LDA BYTENUM + CMP #18 + BNE @ONECOL +@NEXTLVL: +; flip onto the screen + .if DBLBUF + LDX BACKBUF + LDA FRONTBUF + STA BACKBUF + STX FRONTBUF + LDA PAGE1,X + .endif + ; adv past FE in cast data + JSR GETCAST + CMP #$FE + BNE @ERR + JSR GETCAST + CMP #$FE + BEQ @INCDEC +@ERR: + BRK +@INCDEC: + LDA KBD ; stop if ESC is pressed + CMP #$9B + BEQ @DONE + JMP @ONELVL +@DONE: + STA KBDSTRB ; eat the keypress + BIT SETTEXT + BIT PAGE1 + RTS +@DIR: .byte 1 +@TEX0NAME: .byte 21 + .byte "/LL/ASSETS/BUILDING01" +@TEX1NAME: .byte 21 + .byte "/LL/ASSETS/BUILDING02" +@TEX2NAME: .byte 21 + .byte "/LL/ASSETS/BUILDING03" +@TEX3NAME: .byte 21 + .byte "/LL/ASSETS/BUILDING04" +@PRECASTNM: .byte 18 + .byte "/LL/ASSETS/PRECAST" + +CODEEND = * +