├── basic ├── !Boot.txt ├── Line3D.o ├── Line5.o ├── Menu.txt ├── Filler.txt ├── Line5.txt ├── Line3D.txt ├── 3D.txt ├── 3DSolid.txt └── Polyhed.txt ├── beeb3d.ssd ├── demo.ssd ├── images ├── xor1.png ├── xor2.png ├── filled1.png ├── filled2.png ├── filled3.png ├── wireframe1.png ├── wireframe2.png ├── wireframe3.png ├── wireframe4.png ├── wireframe5.png └── wireframe6.png ├── demo.asm ├── beeb3d_solid.asm ├── .vscode └── tasks.json ├── beeb3d.asm ├── source ├── fastmultiply.asm ├── renderer.asm ├── main.asm ├── linedraw5f.asm ├── linedraw4.asm ├── maths.asm ├── culling.asm └── models.asm └── README.md /basic/!Boot.txt: -------------------------------------------------------------------------------- 1 | CHAIN"Menu" 2 | 3 | 4 | -------------------------------------------------------------------------------- /beeb3d.ssd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/beeb3d.ssd -------------------------------------------------------------------------------- /demo.ssd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/demo.ssd -------------------------------------------------------------------------------- /basic/Line3D.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/basic/Line3D.o -------------------------------------------------------------------------------- /basic/Line5.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/basic/Line5.o -------------------------------------------------------------------------------- /images/xor1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/images/xor1.png -------------------------------------------------------------------------------- /images/xor2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/images/xor2.png -------------------------------------------------------------------------------- /images/filled1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/images/filled1.png -------------------------------------------------------------------------------- /images/filled2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/images/filled2.png -------------------------------------------------------------------------------- /images/filled3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/images/filled3.png -------------------------------------------------------------------------------- /images/wireframe1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/images/wireframe1.png -------------------------------------------------------------------------------- /images/wireframe2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/images/wireframe2.png -------------------------------------------------------------------------------- /images/wireframe3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/images/wireframe3.png -------------------------------------------------------------------------------- /images/wireframe4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/images/wireframe4.png -------------------------------------------------------------------------------- /images/wireframe5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/images/wireframe5.png -------------------------------------------------------------------------------- /images/wireframe6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondotm/bbc-micro-3d/HEAD/images/wireframe6.png -------------------------------------------------------------------------------- /demo.asm: -------------------------------------------------------------------------------- 1 | ;---------------------------------------------------------------------------------------------------------- 2 | ; Fast 3D Rendering Demo 3 | ; 6502/BBC Micro 4 | ; Original 1994 code written by Nick Jameson 5 | ;---------------------------------------------------------------------------------------------------------- 6 | ; Ported to BeebAsm & Annotated - by https://github.com/simondotm 7 | ;---------------------------------------------------------------------------------------------------------- 8 | 9 | ; Build options 10 | WIREFRAME = FALSE 11 | 12 | INCLUDE "source/main.asm" 13 | 14 | SAVE "Main", start, end, entry 15 | -------------------------------------------------------------------------------- /beeb3d_solid.asm: -------------------------------------------------------------------------------- 1 | ;---------------------------------------------------------------------------------------------------------- 2 | ; Fast 3D Rendering Demo 3 | ; 6502/BBC Micro 4 | ; Original 1994 code written by Nick Jameson 5 | ;---------------------------------------------------------------------------------------------------------- 6 | ; 7 | ; Ported to BeebAsm & Annotated - by https://github.com/simondotm 8 | ;---------------------------------------------------------------------------------------------------------- 9 | 10 | ; Build options 11 | WIREFRAME = FALSE 12 | 13 | INCLUDE "source/main.asm" 14 | 15 | ; output a binary file of the compiled code (for inclusion in source.asm to build the demo disk) 16 | ; compile with "BeebAsm.exe -i beeb3d_solid.asm" 17 | SAVE "beeb3d_solid.bin", start, end, entry 18 | -------------------------------------------------------------------------------- /basic/Menu.txt: -------------------------------------------------------------------------------- 1 | 10MODE7 2 | 20*KEY 10 CH."MENU"|M 3 | 25PRINTCHR$(134)+"BBC Micro 3D Graphics Rendering Demo" 4 | 26PRINTCHR$(135)+" Written by Nick Jameson, 1994" 5 | 27PRINTCHR$(135)+" Ported to BeebAsm by Simon M, 2016" 6 | 30PRINT'CHR$(131)+"Please select:"' 7 | 40PRINT CHR$(133)+"1. BeebAsm - 3D wireframe" 8 | 41PRINT CHR$(133)+"2. BeebAsm - 3D solid" 9 | 42PRINT CHR$(133)+"3.BBC BASIC - 3D rotation" 10 | 43PRINT CHR$(133)+"4.BBC BASIC - 3D filled" 11 | 44PRINT CHR$(133)+"5.BBC BASIC - Polyhedron" 12 | 45PRINT CHR$(133)+"6.BBC BASIC - Filler" 13 | 50G$=GET$ 14 | 51IFG$="1"THENCLS:*RUN A.Beeb3D 15 | 52IFG$="2"THENCLS:*RUN A.Beeb3Ds 16 | 60IFG$="3"THENCLS:PAGE=&3000:CHAIN"3D" 17 | 70IFG$="4"THENCLS:PAGE=&3500:CHAIN"3DSolid" 18 | 80IFG$="5"THENCLS:PAGE=&3000:CHAIN"Polyhed" 19 | 81IFG$="6"THENCLS:PAGE=&3000:CHAIN"Filler" 20 | 90GOTO50 21 | -------------------------------------------------------------------------------- /basic/Filler.txt: -------------------------------------------------------------------------------- 1 | 10 MODE 7 2 | 20 FOR pass=0TO 3STEP 3 3 | 30 P%=&5000 4 | 40 [OPTpass 5 | 50 .fill SEC:LDX#&B8 6 | 60 .loop 7 | 70 LDA&5D40,X 8 | 80 EOR &5D41,X:STA&5D41,X 9 | 90 EOR &5D42,X:STA&5D42,X 10 | 100 EOR &5D43,X:STA&5D43,X 11 | 110 EOR &5D44,X:STA&5D44,X 12 | 120 EOR &5D45,X:STA&5D45,X 13 | 130 EOR &5D46,X:STA&5D46,X 14 | 140 EOR &5D47,X:STA&5D47,X 15 | 150 ] 16 | 160 FOR A%=&5E80 TO &7A00 STEP &140 17 | 170 [OPTpass 18 | 180 EOR A%,X:STAA%,X 19 | 190 EOR A%+1,X:STAA%+1,X 20 | 200 EOR A%+2,X:STAA%+2,X 21 | 210 EOR A%+3,X:STAA%+3,X 22 | 220 EOR A%+4,X:STAA%+4,X 23 | 230 EOR A%+5,X:STAA%+5,X 24 | 240 EOR A%+6,X:STAA%+6,X 25 | 250 EOR A%+7,X:STAA%+7,X 26 | 260 ]NEXT 27 | 270 [OPTpass 28 | 280 TXA:SBC#8:BCCfilled:TAX:JMPloop 29 | 290 .filled RTS 30 | 300 ]NEXT 31 | 310 MODE 5 32 | 320 GCOL 3,1 33 | 330 MOVE 0,500 34 | 340 DRAW 1280,700 35 | 350 MOVE 1280,300 36 | 360 DRAW 0,600 37 | 370 GCOL 3,3 38 | 380 MOVE 0,800 39 | 390 DRAW 1280,400 40 | 400 MOVE 1280,850 41 | 410 DRAW 0,380 42 | 420 key=GET 43 | 430 CALL fill 44 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "cmd", 4 | "isShellCommand": true, 5 | "showOutput": "always", 6 | "echoCommand": true, 7 | "suppressTaskName": true, 8 | "args": [ 9 | "/C" 10 | ], 11 | "tasks": [ 12 | { 13 | "taskName": "Run 'beeb3d.ssd' in Emulator", 14 | "isTestCommand": true, 15 | "args": [ 16 | "BeebEm.exe beeb3d.ssd" 17 | ] 18 | }, 19 | { 20 | "taskName": "demo.ssd", 21 | "problemMatcher": { 22 | "owner": "6502", 23 | "fileLocation": [ 24 | "relative", 25 | "${workspaceRoot}" 26 | ], 27 | "pattern": { 28 | "regexp": "^(.*):(\\d+):\\s+(warning|error):\\s+(.*)$", 29 | "file": 1, 30 | "line": 2, 31 | "severity": 3, 32 | "message": 4 33 | } 34 | }, 35 | "args": [ 36 | "BeebAsm.exe -v -i demo.asm -do demo.ssd -boot Main" 37 | ] 38 | }, 39 | { 40 | "taskName": "beeb3d.ssd", 41 | "problemMatcher": { 42 | "owner": "6502", 43 | "fileLocation": [ 44 | "relative", 45 | "${workspaceRoot}" 46 | ], 47 | "pattern": { 48 | "regexp": "^(.*):(\\d+):\\s+(warning|error):\\s+(.*)$", 49 | "file": 1, 50 | "line": 2, 51 | "severity": 3, 52 | "message": 4 53 | } 54 | }, 55 | "args": [ 56 | "BeebAsm.exe -i beeb3d_solid.asm|BeebAsm.exe -v -i beeb3d.asm -do beeb3d.ssd -opt 3" 57 | ], 58 | "isBuildCommand": true 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /beeb3d.asm: -------------------------------------------------------------------------------- 1 | ;---------------------------------------------------------------------------------------------------------- 2 | ; Fast 3D Rendering Demo 3 | ; 6502/BBC Micro 4 | ; Original 1994 code written by Nick Jameson 5 | ;---------------------------------------------------------------------------------------------------------- 6 | ; Ported to BeebAsm & Annotated - by https://github.com/simondotm 7 | ;---------------------------------------------------------------------------------------------------------- 8 | 9 | ; This project builds the "beeb3d.ssd" demo disk, containing both the original BASIC code and the BeebAsm ports along with a Menu 10 | ; BeebAsm doesn't have a way to reset variables in one compilation run so the build is a bit long winded. 11 | ; A pre-requisite for assembling this file is to assemble beeb3d_solid.asm first, to output a beeb3d_solid.bin file 12 | ; - this is the executable for the solid demo 13 | ; (if using BeebVSC, the tasks.json file includes this pre-requisite) 14 | ; 15 | ; we then include main.asm and assemble the wireframe demo here, then write the solid executable to the same disk 16 | ; (both demos have the same load & execution address fortunately) 17 | 18 | 19 | ;---------------------------------------------------------------------------------------------------------- 20 | ; Assemble the wireframe version of the code 21 | ;---------------------------------------------------------------------------------------------------------- 22 | ; Build options 23 | WIREFRAME = TRUE 24 | INCLUDE "source/main.asm" 25 | SAVE "A.Beeb3D", start, end, entry 26 | 27 | ;---------------------------------------------------------------------------------------------------------- 28 | ; write the assembled wireframe code to disk too, same code entry point 29 | ;---------------------------------------------------------------------------------------------------------- 30 | PUTFILE "beeb3d_solid.bin", "A.Beeb3Ds", start, entry 31 | 32 | ;---------------------------------------------------------------------------------------------------------- 33 | ; Now create a disk of various BASIC source file demonstrations 34 | ;---------------------------------------------------------------------------------------------------------- 35 | PUTBASIC "basic\3D.txt", "3D" 36 | PUTBASIC "basic\3DSolid.txt", "3DSolid" 37 | PUTBASIC "basic\Polyhed.txt", "Polyhed" 38 | PUTBASIC "basic\Menu.txt", "Menu" 39 | PUTBASIC "basic\Filler.txt", "Filler" 40 | PUTBASIC "basic\Line5.txt", "S.Line5" ; for reference 41 | PUTBASIC "basic\Line3D.txt", "S.Line3D" ; for reference 42 | 43 | ; Compiled object files for line drawing (loaded by the BASIC programs) 44 | PUTFILE "basic\Line5.o", "Line5", &2F03 45 | PUTFILE "basic\Line3D.o", "Line3D", &26BA 46 | 47 | ; Add the project readme 48 | PUTFILE "README.md", "README", 0 49 | 50 | ; Add the boot file 51 | PUTFILE "basic\!Boot.txt", "!Boot", 0 52 | 53 | ; done 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /source/fastmultiply.asm: -------------------------------------------------------------------------------- 1 | 2 | ; quarter square lookup tables 3 | ; table1 = n*n/4, where n=0..510 4 | ; table2 = (n-255)*(n-255)/4, where n=0..510 5 | ; 6 | ; table2 + table1 origins must be page aligned 7 | 8 | 9 | 10 | IF CONTIGUOUS_TABLES 11 | ; specify contiguous tables 12 | SQUARETABLE2_LSB = &0E00 13 | SQUARETABLE1_LSB = SQUARETABLE2_LSB+256 14 | SQUARETABLE2_MSB = SQUARETABLE1_LSB+512 15 | SQUARETABLE1_MSB = SQUARETABLE2_MSB+256 16 | ELSE 17 | ; msb & lsb tables can be in different memory locations 18 | ; enables us to move the program org down a bit 19 | ; as we can spread the two 768 bytes tables around the memory map 20 | SQUARETABLE2_LSB = &0E00 21 | SQUARETABLE1_LSB = SQUARETABLE2_LSB+256 22 | 23 | SQUARETABLE2_MSB = &0900 ;&1100 24 | SQUARETABLE1_MSB = SQUARETABLE2_MSB+256 25 | ENDIF 26 | 27 | 28 | 29 | 30 | 31 | ;---------------------------------------------------------------------------------------------------------- 32 | ; setup quarter square multiplication tables 33 | ;---------------------------------------------------------------------------------------------------------- 34 | ; f(x) = x^2 / 4. Then a*b = f(a+b) - f(a-b) 35 | ; 36 | ; This implementation uses two tables of squares: 37 | ; table1 = n*n/4, where n=0..510 38 | ; table2 = (n-255)*(n-255)/4, where n=0..510 39 | ; 40 | ; Unsigned multiplication of two 8-bit terms is computed as: 41 | ; r = table1[a+b] - table2[(a EOR 255)+b] 42 | ; where r is a 16-bit unsigned result 43 | ;---------------------------------------------------------------------------------------------------------- 44 | ; A clever innovation with this code is that it takes advantage of overlaps in the table 45 | ; which means the tables fit into 1536 bytes instead of the usual 2048. 46 | ; 47 | ; &0000-&01FF = table2 lsb 48 | ; &0100-&02FF = table1 lsb 49 | ; &0300-&04FF = table2 msb 50 | ; &0400-&05FF = table1 msb 51 | ;---------------------------------------------------------------------------------------------------------- 52 | .initialise_multiply 53 | { 54 | 55 | ; set the msb of lmul0, lmul1, rmul0 and rmul1 just once 56 | ; for the entire lifecycle of the application 57 | ; - the lsb of these 16-bit addresses will be set as the multiplication terms 58 | LDA#HI(SQUARETABLE1_LSB):STA lmul0+1:STA rmul0+1 59 | LDA#HI(SQUARETABLE1_MSB):STA lmul1+1:STA rmul1+1 60 | 61 | ; compute table1 62 | 63 | ; x=y=lhs=0 64 | ; while y<256: 65 | ; if y>0: 66 | ; lhs += x 67 | ; table1[offset+y] = lhs 68 | ; x = x + 1 69 | ; 70 | ; lhs += x 71 | ; offset = y 72 | ; table1[offset+y] = lhs 73 | ; y = y + 1 74 | 75 | ; effectively the same as: 76 | ; for n in range(0,511): # 0-510 77 | ; table1[n] = n*n/4 78 | 79 | ; initialise counters and indices 80 | LDA#0:TAX:TAY 81 | STX lhs:STY lhs+1 82 | 83 | ; skip increment on first iteration 84 | CLC 85 | BCC go 86 | 87 | .loop2 88 | TXA:ADC lhs:STA lhs:STA(lmul0),Y 89 | LDA#0:ADC lhs+1:STA lhs+1:STA(lmul1),Y 90 | INX 91 | 92 | .go 93 | STY lmul0:STY lmul1 94 | TXA:ADC lhs:STA lhs:STA(lmul0),Y 95 | LDA#0:ADC lhs+1:STA lhs+1:STA(lmul1),Y 96 | INY 97 | BNE loop2 98 | 99 | ; compute table2 100 | 101 | ; for x in range(0,256): 102 | ; table2[x] = table1[255-x] 103 | ; table2[x+256] = table1[x+1] 104 | ; 105 | ; effectively the same as: 106 | ; for n in range(0,511): # 0-510 107 | ; table2[n] = (n-255)*(n-255)/4 108 | 109 | 110 | LDX#0:LDY#&FF 111 | .loop3 112 | LDA SQUARETABLE1_LSB+1,Y:STA SQUARETABLE2_LSB,X 113 | LDA SQUARETABLE1_MSB+1,Y:STA SQUARETABLE2_MSB,X 114 | DEY:INX:BNE loop3 115 | 116 | rts 117 | } 118 | 119 | 120 | -------------------------------------------------------------------------------- /source/renderer.asm: -------------------------------------------------------------------------------- 1 | 2 | IF WIREFRAME 3 | linedraw = linedraw4 4 | ELSE 5 | linedraw = linedraw5f 6 | ENDIF 7 | 8 | ;---------------------------------------------------------------------------------------------------------- 9 | ; clear the draw buffer 10 | ;---------------------------------------------------------------------------------------------------------- 11 | 12 | 13 | IF WIREFRAME 14 | .wipe 15 | { 16 | LDX#&2F:CMP#&30:BNE wipe0:JMP wipe1 17 | .wipe0 LDA#0 18 | .loop 19 | FOR Y%, &5D40, &7A00, &140 20 | FOR X%, Y%, Y%+144, 48 21 | STA X%,X 22 | NEXT 23 | NEXT 24 | DEX:BMI wiped:JMP loop 25 | .wiped RTS 26 | .wipe1 LDA#0 27 | .loop2 28 | FOR Y%, &3540, &5200, &140 29 | FOR X%, Y%, Y%+144, 48 30 | STA X%,X 31 | NEXT 32 | NEXT 33 | DEX:BMI wiped1:JMP loop2 34 | .wiped1 35 | RTS 36 | } 37 | 38 | ELSE 39 | 40 | 41 | .wipe 42 | { 43 | LDA#0:LDX#&2F 44 | .loop5 45 | FOR Y%, &3A40, &5700, &140 46 | FOR X%, Y%, Y%+144, 48 47 | STA X%,X 48 | NEXT 49 | NEXT 50 | DEX:BMI wiped:JMP loop5 51 | .wiped 52 | RTS 53 | } 54 | 55 | 56 | ; xor fill the back buffer to the front buffer 57 | .fill 58 | { 59 | SEC:LDX#&B8 60 | .loop6 61 | LDA &3A40,X 62 | EOR &3A41,X:STA&5D41,X 63 | EOR &3A42,X:STA&5D42,X 64 | EOR &3A43,X:STA&5D43,X 65 | EOR &3A44,X:STA&5D44,X 66 | EOR &3A45,X:STA&5D45,X 67 | EOR &3A46,X:STA&5D46,X 68 | EOR &3A47,X:STA&5D47,X 69 | 70 | FOR A%,&5E80, &7A00, &140 71 | 72 | EOR A%-&2300,X:STAA%,X 73 | EOR A%-&22FF,X:STAA%+1,X 74 | EOR A%-&22FE,X:STAA%+2,X 75 | EOR A%-&22FD,X:STAA%+3,X 76 | EOR A%-&22FC,X:STAA%+4,X 77 | EOR A%-&22FB,X:STAA%+5,X 78 | EOR A%-&22FA,X:STAA%+6,X 79 | EOR A%-&22F9,X:STAA%+7,X 80 | 81 | NEXT 82 | TXA:SBC#8:BCC filled:TAX:JMP loop6 83 | .filled 84 | RTS 85 | } 86 | 87 | ; copy the back buffer to the front buffer 88 | .fill_copy 89 | { 90 | LDA#0:LDX#&2F 91 | .loop5 92 | FOR Y%, &3A40, &5700, &140 93 | FOR X%, Y%, Y%+144, 48 94 | LDA X%,X:STA X%+(&5D40-&3A40),X 95 | NEXT 96 | NEXT 97 | DEX:BMI wiped:JMP loop5 98 | .wiped 99 | RTS 100 | } 101 | 102 | ENDIF 103 | 104 | 105 | ;---------------------------------------------------------------------------------------------------------- 106 | ; present the list of visible lines for the current model to the line renderer 107 | ;---------------------------------------------------------------------------------------------------------- 108 | ; inputs - 109 | ; line[] contains 64-bit array of visible lines to be rendered 110 | ; linestarts - points to the current models line indices array (p0) 111 | ; lineends - points to the current models line indices array (p1) 112 | ; (linestarts & lineends addresses are set by the 'load_next_model' routine) 113 | ;---------------------------------------------------------------------------------------------------------- 114 | ; for each linestart and lineend vertex index (p0,p1) the routine fetches the transformed 2D screen coordinate 115 | ; and submits these coordinates to the line renderer. 116 | ; 2D screen coordinates are cached, so they are only ever transformed once, even if referenced by multiple lines 117 | ;---------------------------------------------------------------------------------------------------------- 118 | 119 | 120 | IF WIREFRAME 121 | .drawlines 122 | 123 | ; index of current line in the line list for this model 124 | LDA#0:STA lhs+1 125 | ; number of lines in the line list for this model 126 | LDA nlines:STA lhs 127 | 128 | ; for each line in the linelist 129 | ; fetch low bit of the 64 bit line[] array to determine 130 | ; its visibility, draw only if marked as visible 131 | .loop 132 | LSR line+7 133 | ROR line+6 134 | ROR line+5 135 | ROR line+4 136 | ROR line+3 137 | ROR line+2 138 | ROR line+1 139 | ROR line 140 | BCC noline 141 | 142 | ; get the current line index 143 | LDY lhs+1 144 | 145 | ; linestarts and lineends are setup when model first loaded 146 | ; they point to the line list buffer 147 | .linestarts LDA &8000,Y:PHA 148 | .lineends LDA &8000,Y:TAX 149 | ; fetch screen coords for vertex linelist[1] 150 | JSR getcoordinates 151 | STA x0:STY y0 152 | PLA:TAX 153 | ; fetch screen coords for vertex linelist[0] 154 | JSR getcoordinates 155 | STA x1:STY y1 156 | 157 | ; render the line from x0,y0 to x1,y1 158 | JSR linedraw 159 | 160 | .noline 161 | INC lhs+1 ; next line in list 162 | DEC lhs ; for each line in list 163 | BPL loop 164 | RTS 165 | 166 | ELSE 167 | 168 | ; in fill mode, the line bit array contains 2 bits per line. 169 | ; so a maximum of 32 lines for filled objects. (non filled have 64 lines) 170 | .drawlines 171 | 172 | LDA#0:STA lhs+1 173 | LDA nlines:STA lhs 174 | .loopD 175 | ; two bits per pixel for each line, to indicate colour. 176 | LDA line:AND #3:BEQ noline:PHA 177 | LDY lhs+1 178 | .linestarts LDA &8000,Y:PHA 179 | .lineends LDA &8000,Y:TAX 180 | JSR getcoordinates 181 | STA x0:STY y0 182 | PLA:TAX 183 | JSR getcoordinates 184 | STA x1:STY y1 185 | PLA:TAX ; line colour in X 186 | JSR linedraw 187 | .noline 188 | ; shift two bits per pixel rather than one 189 | LSR line+7 190 | ROR line+6 191 | ROR line+5 192 | ROR line+4 193 | ROR line+3 194 | ROR line+2 195 | ROR line+1 196 | ROR line 197 | LSR line+7 198 | ROR line+6 199 | ROR line+5 200 | ROR line+4 201 | ROR line+3 202 | ROR line+2 203 | ROR line+1 204 | ROR line 205 | INC lhs+1:DEC lhs:BPL loopD 206 | RTS 207 | ENDIF -------------------------------------------------------------------------------- /source/main.asm: -------------------------------------------------------------------------------- 1 | ;---------------------------------------------------------------------------------------------------------- 2 | ; Fast 3D Rendering Demo 3 | ; 6502/BBC Micro 4 | ; Original 1994 code written by Nick Jameson 5 | ;---------------------------------------------------------------------------------------------------------- 6 | ; 7 | ; Ported to BeebAsm & Annotated - by https://github.com/simondotm 8 | ;---------------------------------------------------------------------------------------------------------- 9 | 10 | ; ENSURE WIREFRAME & 11 | 12 | ; specify true to force multiplication tables to be contiguous in memory 13 | ; if false they are separated into different memory locations to free up 768 bytes 14 | ; which allows just enough more RAM to have more models in the wireframe demo 15 | CONTIGUOUS_TABLES = FALSE 16 | 17 | 18 | ;---------------------------------------------------------------------------------------------------------- 19 | ; Zero Page Vars 20 | ;---------------------------------------------------------------------------------------------------------- 21 | 22 | 23 | ; 3x3 rotation matrix 24 | ; 16-bit unit vectors 25 | m00lsb=0:m00msb=9 26 | m01lsb=1:m01msb=&A 27 | m02lsb=2:m02msb=&B 28 | m10lsb=3:m10msb=&C 29 | m11lsb=4:m11msb=&D 30 | m12lsb=5:m12msb=&E 31 | m20lsb=6:m20msb=&F 32 | m21lsb=7:m21msb=&10 33 | m22lsb=8:m22msb=&11 34 | 35 | adr=&12 36 | 37 | xr=&1A 38 | yr=&1C 39 | zr=&1E 40 | 41 | product=&20 42 | 43 | ; 8-bit rotation angles 44 | rx=&22 45 | ry=&23 46 | rz=&24 47 | 48 | ; model data 49 | npts=&30 50 | nlines=&31 51 | nsurfs=&32 52 | maxvis=&33 53 | 54 | lhs=&40 55 | rhs=&42 56 | 57 | lmul0=&44 58 | lmul1=&46 59 | rmul0=&48 60 | rmul1=&4A 61 | 62 | surfs=&50 63 | oldsurfs=&52 64 | surfsdone=&54 65 | visible=&56 66 | 67 | ; ptr to the lines array for the current model 68 | lines=&57 69 | 70 | ; 64-bit line flag array (8 bytes) 71 | ; set by 'hiddenlineremoval' 72 | line=&59 73 | 74 | ; temp address 75 | odr=&61 76 | 77 | ; logic vars 78 | space=&63 79 | p=&64 80 | f=&65 81 | flicker=&66 82 | pause=&67 83 | culling=&68 ; culling = 0=disabled, 255=enabled 84 | cullingdb=&69 ; culling key debounce 85 | opt_filled=&6A 86 | opt_filled_db=&6B 87 | 88 | ; line rendering coordinates, start and end 89 | x0=&70:y0=&71 90 | x1=&72:y1=&73 91 | 92 | ; logic vars 93 | scr=&74 94 | err=&76 95 | errs=&77 96 | cnt=&78 97 | ls=&79 98 | dx=&FF 99 | dy=&7A 100 | scrstrt=&7B 101 | c=&7C 102 | 103 | 104 | ;---------------------------------------------------------------------------------------------------------- 105 | ; Code 106 | ;---------------------------------------------------------------------------------------------------------- 107 | 108 | IF CONTIGUOUS_TABLES 109 | 110 | ORG &1400 111 | 112 | ELSE 113 | 114 | ORG &1100 115 | 116 | ENDIF 117 | 118 | .start 119 | ; included first to ensure page alignment 120 | INCLUDE "source/fastmultiply.asm" 121 | INCLUDE "source/maths.asm" 122 | 123 | 124 | 125 | ;---------------------------------------------------------------------------------------------------------- 126 | ; main loop 127 | ;---------------------------------------------------------------------------------------------------------- 128 | 129 | .entry 130 | { 131 | ; initialise variables 132 | LDX#0 133 | STX adr 134 | STX space:STX p:STX f:STX flicker:STX cullingdb:STX opt_filled_db 135 | LDA#1:STA pause 136 | LDA#255:STA culling 137 | LDA#1:STA opt_filled 138 | 139 | ; initialise display 140 | .loop 141 | LDA vdus,X:BMI nomess:JSR &FFEE 142 | INX:BNE loop 143 | .nomess 144 | 145 | ; prepare model data for runtime 146 | JSR initialise_models 147 | 148 | ; disable interrupts & NMI 149 | SEI:LDA#&40:STA &D00:LDX#&FF:TXS 150 | 151 | ; initialise rotation angles of model 152 | LDA#0:STA rx 153 | LDA#&7B:STA ry 154 | LDA#&C3:STA rz 155 | 156 | 157 | ; setup multiplication tables 158 | jsr initialise_multiply 159 | 160 | 161 | ; load first model 162 | JSR reset_model 163 | 164 | IF WIREFRAME 165 | LDA#&58:STA scrstrt 166 | ELSE 167 | LDA#&35:STA scrstrt 168 | ENDIF 169 | 170 | ; main loop 171 | .frame 172 | 173 | ; check for space bar pressed 174 | LDA#&81:LDX#&9D:LDY#&FF:JSR &FFF4 175 | TYA:BEQ nopress:LDA space:BNE nopress 176 | JSR load_next_model:LDA#1 177 | .nopress STA space 178 | 179 | 180 | IF WIREFRAME 181 | ; wireframe mode runs in 10K mode 4, 1 bit per pixel 182 | ; and uses a double buffer 183 | LDA scrstrt:LSR A:LSR A:LSR A 184 | LDX#&C:STX &FE00:STA &FE01 185 | 186 | ; check for "F" keypress to toggle vsync 187 | LDA#&81:LDX#&BC:LDY#&FF:JSR &FFF4 188 | TYA:BEQ nof:LDA f:BNE nof 189 | LDA flicker:EOR #1:STA flicker:LDA#1 190 | .nof STA f 191 | LDA flicker:AND pause:BNE fastandflicker 192 | CLI:LDA#19:JSR &FFF4:SEI 193 | .fastandflicker 194 | LDA scrstrt:EOR #&68:STA scrstrt 195 | ENDIF 196 | 197 | ; clear the draw buffer 198 | JSR wipe 199 | 200 | ; check for "C" pressed to toggle backface culling 201 | LDA#&81:LDX#&AD:LDY#&FF:JSR &FFF4 202 | TYA:BEQ noc:LDA cullingdb:BNE noc 203 | LDA culling:EOR #255:STA culling:LDA#1 204 | .noc STA cullingdb 205 | 206 | IF WIREFRAME==FALSE 207 | ; check for "L" pressed to toggle XOR poly filler 208 | LDA#&81:LDX#&A9:LDY#&FF:JSR &FFF4 209 | TYA:BEQ nol:LDA opt_filled_db:BNE nol 210 | LDA opt_filled:EOR #1:STA opt_filled:LDA#1 211 | .nol STA opt_filled_db 212 | ENDIF 213 | 214 | 215 | ; check for "P" pressed to pause rotation 216 | LDA#&81:LDX#&C8:LDY#&FF:JSR &FFF4 217 | TYA:BEQ nop:LDA p:BNE nop 218 | LDA pause:EOR #1:STA pause:LDA#1 219 | .nop STA p 220 | LDA pause:BEQ nrot 221 | 222 | ; rotate the model 223 | JSR rotate 224 | 225 | .nrot 226 | 227 | ; compute rotation matrix 228 | JSR matrix 229 | 230 | ; clear transformed vertex buffer 231 | JSR newpoints 232 | 233 | ; initialise visibility of lines array for this frame 234 | JSR resetvisibility 235 | 236 | ; check if back face culling is enabled, skip if not 237 | LDA culling 238 | BEQ noculling 239 | 240 | ; eliminate hidden surfaces 241 | JSR hiddensurfaceremoval 242 | 243 | ; determine visible lines to be rendered 244 | JSR hiddenlineremoval 245 | 246 | .noculling 247 | 248 | ; render the model 249 | JSR drawlines 250 | 251 | IF WIREFRAME == FALSE 252 | ; apply shading 253 | LDA opt_filled 254 | BNE dofill 255 | JSR fill_copy ; copy back buffer to front rather than xor fill from back to front 256 | JMP filldone 257 | 258 | .dofill 259 | JSR fill ; xor fill back buffer to front buffer 260 | 261 | .filldone 262 | ENDIF 263 | 264 | JMP frame 265 | 266 | } 267 | 268 | ;---------------------------------------------------------------------------------------------------------- 269 | ; Display initialisation table 270 | ;---------------------------------------------------------------------------------------------------------- 271 | .vdus 272 | IF WIREFRAME 273 | EQUB 22,4 274 | ELSE 275 | EQUB 22,5 276 | ENDIF 277 | 278 | EQUB 23,0,10,32,0,0,0,0,0,0 279 | EQUB 255 280 | 281 | 282 | ;---------------------------------------------------------------------------------------------------------- 283 | ; Includes 284 | ;---------------------------------------------------------------------------------------------------------- 285 | 286 | ; the following modules contain WIREFRAME conditional code, so cannot be earlier in the file without changing execution address 287 | INCLUDE "source/culling.asm" 288 | 289 | 290 | IF WIREFRAME 291 | INCLUDE "source/linedraw4.asm" 292 | ELSE 293 | INCLUDE "source/linedraw5f.asm" 294 | ENDIF 295 | 296 | INCLUDE "source/renderer.asm" 297 | 298 | INCLUDE "source/models.asm" 299 | 300 | 301 | .end 302 | 303 | 304 | PRINT "Coordinates data size is ", coordinates_end-coordinates_start, " bytes" 305 | PRINT " Trig table data size is ", trigtable_end-trigtable_start, " bytes" 306 | PRINT "Code from", ~start, "to", ~end, ", size is", (end-start), "bytes" 307 | 308 | 309 | 310 | 311 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 3D Rendering Demo for BBC Micro 2 | 3 | Written in 6502/BBC BASIC/BeebAsm 4 | 5 | Original source written in 1994 by [Nick Jameson](http://nojameson.net/) 6 | 7 | BeebAsm port by [Simon M](https://github.com/simondotm) 8 | 9 | Demo version [here](https://bitshifters.github.io/jsbeeb/?disc=https://bitshifters.github.io/content/wip/sd-beeb3d.ssd&autoboot&model=Master) 10 | 11 | # Introduction 12 | 13 | Nick recently shared one of his archived BBC Micro disks that contained some interesting routines he'd written back in the 90's. A closer look at this revealed there were a few demos on these disks that were presenting some amazing high performance 3D rendered graphics, that were clearly pushing the limits of the BBC Micro's abilities. 14 | 15 | To achieve this high performance, Nick had incorporated a number of very innovative coding techniques so we wanted to figure out how that worked! 16 | 17 | This led to an annotated version of the code being ported to BeebAsm for the benefit of the 6502/BBC Micro development community, and so here it is. 18 | 19 | # Screenshots 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | # Building the project 36 | 37 | Use [BeebAsm](https://github.com/tom-seddon/beebasm) to assemble the code and compile the demo disk SSD file. 38 | 39 | `BeebAsm.exe -v -i demo.asm -do demo.ssd -boot Main` for standalone testing 40 | 41 | `BeebAsm.exe -i beeb3d_solid.asm` then `BeebAsm.exe -v -i beeb3d.asm -do beeb3d.ssd -opt 3` for creating the `beeb3d.ssd` disk 42 | 43 | There is also a build configuration for Visual Studio Code using the [Beeb VSC](https://marketplace.visualstudio.com/items?itemName=simondotm.beeb-vsc) extension. Hit `CTRL+SHIFT+B` to build, and `CTRL+SHIFT+T` to run in BeebEm. 44 | 45 | If using BeebVSC, two build targets exist - `demo.ssd` and `beeb3d.asm` 46 | 47 | # Running the project 48 | 49 | If running `beeb3d.ssd` a menu will show, otherwise `demo.ssd` will boot straight into the standalone demo. 50 | 51 | - Press `C` to toggle back face culling 52 | - Press `P` to pause the rotation 53 | - Press `SPACE` to cycle through the models 54 | 55 | 56 | - Press `F` in wireframe mode to toggle the vsync 57 | - Press `L` in solid mode to toggle the Filler 58 | 59 | 60 | # Notes 61 | 62 | ## BeebAsm port 63 | 64 | ### Annotations 65 | The original BBC BASIC source code was ported to BeebAsm and annotated, mainly for learning and understanding the techniques that were making it work. However Nick kindly gave us his permission to share it, so it is now also a way of preserving the code and making it accessible to the BBC Micro development community. 66 | 67 | The annotations are just my initial interpretations of the code (and certainly not exhaustive) so I'm sure there may be places where I've judged the code incorrectly. The line plotting routines have not yet been documented, and some annotations need further work, eg. the 3D rotation matrix, transform and cross product routine needs more work to determine things like XYZ rotation matrix order (lh/rh), winding order of the surfaces, and the exact calculations driving some of the maths. For now though, I'm just gonna commit it "as is" with the intention of coming back to this soon. 68 | 69 | ### Changes from original code 70 | I had to make a few alterations here and there to get the code compiling in BeebAsm, but overall I tried to keep the code functionality and structure the same. 71 | 72 | - The solid and wireframe demo contain a lot of common code, so both now exist in one project for ease of reference, but they are conditionally compiled with the `WIREFRAME=TRUE/FALSE` variable. I think it would be possible to unify the code to switch between the two modes in one runtime, but would need a lot of memory juggling and code changes to achieve that so I left that alone! 73 | - The model data was read into interleaved memory addresses in the BASIC version, but BeebAsm doesn't support random access, so I concocted the various `MD_***` macros to assist with this along with an initialisation routine that de-serialised the model data back to the optimized interleaved format at runtime 74 | - BeebAsm has many useful functions, one of which is the `INCLUDE` directive, so the code has been broken out into separate source files, again for easier reference 75 | - The extra rendering options (back face culling toggle and filling toggle) were added 76 | - The memory locations of the quarter square multiplication tables were changed to variables rather than hard coded, and `CONTIGUOUS_TABLES` was added as a compile option which frees up a bit of extra RAM to enable a couple more models 77 | - Some extra models were incorporated from Nick's original wireframe demo, however the Icosahedron model could not be ported as is contains more than 16 surfaces (and Nick's original 'polyhed' demo did not use the optimized hidden surface routines which only allow upto 16 surfaces per model. This could be fixed but would need the code to handle models with >16 surfaces differently 78 | 79 | 80 | # Techniques 81 | 82 | Some of the technical innovations that give the demo it's speed are as follows: 83 | - Fast 3D rotation matrix building using compound angle formulae rather than multiplications 84 | - Fast 3D vertex transform routine, using pre-loaded table look-ups rather than multiplications 85 | - Table based sin/cos tables, with 16-bit fixed point precision 86 | - Fast multiplication based on quarter square tables, but overlapped to used 1536 bytes of RAM instead of the usual 2048 bytes 87 | - Screen space hidden surface removal 88 | - Caching of transformed screen space vertices 89 | - Temporal caching of visible surfaces to minimize number of hidden surface tests 90 | - Optimized unrolled Bresenham line drawing for 1-bit-per-pixel mode 4 91 | - Optimized unrolled Bresenham line drawing for 2-bit-per-pixel mode 5, supporting 3 colours and XOR based vertical polygon fill 92 | - Optimized vertical polygon filling routine 93 | - Optimal model data format enables only the minimum number of lines to be rendered given a list of visible surfaces 94 | - Rendering window, to enable double buffering and/or rapid buffer updates 95 | 96 | These routines are particularly well optimized for the 8-bit 6502 CPU. 97 | 98 | ## Polygon Filler 99 | 100 | In solid fill mode, the rendering routines use a custom Bresenham routine to plot only the top most vertical elements of the line. Each line for a surface can be assigned one of three colours, and the object is filled vertically using XOR to transmit a colour from the top of the visible surface to the bottom. You can see in the two images below the cube is first rendered in a special wireframe mode (with only the topmost pixels for any vertical pixel column being drawn), and then the XOR filler works by scanning from top-bottom XORing a pixel with the pixel directly above it, creating the fill effect. This is then repeated from left to right to achieve the filled cube. 101 | 102 | 103 | 104 | 105 | **TODO** - Add further information here about the various tricks described above 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /basic/Line5.txt: -------------------------------------------------------------------------------- 1 | 1 REM RUN WITH PAGE=&4000 2 | 10 MODE 7 3 | 20 CLEAR 4 | 30 x0=&70:y0=&71 5 | 40 x1=&72:y1=&73 6 | 50 scr=&74 7 | 60 err=&76 8 | 70 errs=&77 9 | 80 cnt=&78 10 | 90 ls=&79 11 | 100 dx=&FF 12 | 110 dy=&7A 13 | 120 scrstrt=&7B 14 | 130 c=&7C 15 | 140 FOR pass=0TO 3STEP 3 16 | 150 P%=&2F03 17 | 160 [OPTpass 18 | 170 .colors EQUD&FFF00FED 19 | 180 .strt0 20 | 190 EQUBa00 AND &FF:EQUBa10 AND &FF 21 | 200 EQUBa60 AND &FF:EQUBa70 AND &FF 22 | 210 EQUBa00 DIV 256:EQUBa10 DIV 256 23 | 220 EQUBa60 DIV 256:EQUBa70 DIV 256 24 | 230 .strt1 25 | 240 EQUBa71 AND &FF:EQUBa61 AND &FF 26 | 250 EQUBa11 AND &FF:EQUBa01 AND &FF 27 | 260 EQUBa71 DIV 256:EQUBa61 DIV 256 28 | 270 EQUBa11 DIV 256:EQUBa01 DIV 256 29 | 280 .strt2 30 | 290 EQUBp02 AND &FF:EQUBp52 AND &FF 31 | 300 EQUBp62 AND &FF:EQUBp72 AND &FF 32 | 310 EQUBp02 DIV 256:EQUBp52 DIV 256 33 | 320 EQUBp62 DIV 256:EQUBp72 DIV 256 34 | 330 .strt3 35 | 340 EQUBp73 AND &FF:EQUBp63 AND &FF 36 | 350 EQUBp53 AND &FF:EQUBp03 AND &FF 37 | 360 EQUBp73 DIV 256:EQUBp63 DIV 256 38 | 370 EQUBp53 DIV 256:EQUBp03 DIV 256 39 | 380 .noline RTS 40 | 390 .linedraw 41 | 400 LDAcolors,X:STAc 42 | 410 LSRx0:LSRx1 43 | 420 LDAx0:CMPx1:BCCitsoknow:BEQnoline 44 | 430 LDXx0:LDYx1:STYx0:STXx1 45 | 440 LDXy0:LDYy1:STYy0:STXy1 46 | 450 .itsoknow DECx1 47 | 460 LDAy0:SEC:SBCy1:BCSdyok 48 | 470 SBC#0:EOR #&FF 49 | 480 LDXx0:LDYx1:STYx0:STXx1 50 | 490 LDYy1:STYy0 51 | 500 .dyok STAdy 52 | 510 LDAx0:SBCx1:PHP:BCSdxok 53 | 520 SBC#0:EOR #&FF 54 | 530 .dxok TAX 55 | 540 LDA#&80:STAscr 56 | 550 LDAy0:LSRA:LSRA:LSRA:STAscr+1 57 | 560 LSRA:RORscr:LSRA:RORscr 58 | 570 ADCscr+1:STAscr+1 59 | 580 LDAx0:AND #&7C:ASLA:ADCscr:STAscr 60 | 590 LDAscrstrt:ADCscr+1:STAscr+1 61 | 600 LDAx0:AND #3:TAY 62 | 610 CPXdy:BCSnotsteep:JMPsteep 63 | 620 .notsteep 64 | 630 LDAdy:BEQhorizontal:STAcnt 65 | 640 TXA:LSRA:STAerr:STAerrs 66 | 650 LDA#2:STAls 67 | 660 .backh PLP:BCCright 68 | 670 LDAstrt1,Y:STAx1 69 | 680 LDAstrt1+4,Y:STAy1 70 | 690 LDAy0:AND #7:TAY 71 | 700 STXb01+5:STXb51+5 72 | 710 STXb61+5:STXb71+5 73 | 720 LDAdy 74 | 730 STAb01+1:STAb51+1 75 | 740 STAb61+1:STAb71+1 76 | 750 SEC:JMP(x1) 77 | 760 .horizontal STXerr 78 | 770 LDA#1:STAls:STAcnt:STAdy 79 | 780 BNEbackh 80 | 790 .right 81 | 800 LDAstrt0,Y:STAx1 82 | 810 LDAstrt0+4,Y:STAy1 83 | 820 LDAy0:AND #7:TAY 84 | 830 STXb00+5:STXb50+5 85 | 840 STXb60+5:STXb70+5 86 | 850 LDAdy 87 | 860 STAb00+1:STAb50+1 88 | 870 STAb60+1:STAb70+1 89 | 880 SEC:JMP(x1) 90 | 890 .steep 91 | 900 TXA:BEQvertical:STXcnt 92 | 910 LDAdy:LSRA:STAerrs 93 | 920 LDA#2:STAls 94 | 930 .backv PLP:BCSleft 95 | 940 LDAstrt2,Y:STAx1 96 | 950 LDAstrt2+4,Y:STAy1 97 | 960 LDAy0:AND #7:TAY 98 | 970 STXa02+1:STXa52+1 99 | 980 STXa62+1:STXa72+1 100 | 990 LDAdy 101 | 1000 STAb02+1:STAb52+1 102 | 1010 STAb62+1:STAb72+1 103 | 1020 LDXerrs:SEC:JMP(x1) 104 | 1030 .vertical LDAdy:STAerrs 105 | 1040 LDX#1:STXls:STXcnt 106 | 1050 BNEbackv 107 | 1060 .left 108 | 1070 LDAstrt3,Y:STAx1 109 | 1080 LDAstrt3+4,Y:STAy1 110 | 1090 LDAy0:AND #7:TAY 111 | 1100 STXa03+1:STXa53+1 112 | 1110 STXa63+1:STXa73+1 113 | 1120 LDAdy 114 | 1130 STAb03+1:STAb53+1 115 | 1140 STAb63+1:STAb73+1 116 | 1150 LDXerrs:SEC:JMP(x1) 117 | 1160 .a00 LDAerr:LDX#&FF 118 | 1170 .b00 SBC#dy:BCSb50:ADC#dx:STAerr 119 | 1180 LDA#&88:AND c:EOR (scr),Y:STA(scr),Y 120 | 1190 DECcnt:BEQe00:.f00 DEY:BPLa10 121 | 1200 LDAscr:SBC#&40:STAscr:DECscr+1 122 | 1210 LDY#7:BCSa10:DECscr+1:SEC:BCSa10 123 | 1220 .e00 DECls:BEQd00:LDAerr:SBCerrs 124 | 1230 STAerr:INCcnt:BCSf00 125 | 1240 .d00 RTS 126 | 1250 .a10 LDAerr:LDX#&77 127 | 1260 .b50 SBC#dy:BCSb60:ADC#dx:STAerr 128 | 1270 TXA:AND #&CC:AND c:EOR (scr),Y:STA(scr),Y 129 | 1280 DECcnt:BEQe50:.f50 DEY:BPLa60 130 | 1290 LDAscr:SBC#&40:STAscr:DECscr+1 131 | 1300 LDY#7:BCSa60:DECscr+1:SEC:BCSa60 132 | 1310 .e50 DECls:BEQd50:LDAerr:SBCerrs 133 | 1320 STAerr:INCcnt:BCSf50 134 | 1330 .d50 RTS 135 | 1340 .a60 LDAerr:LDX#&33 136 | 1350 .b60 SBC#dy:BCSb70:ADC#dx:STAerr 137 | 1360 TXA:AND #&EE:AND c:EOR (scr),Y:STA(scr),Y 138 | 1370 DECcnt:BEQe60:.f60 DEY:BPLa70 139 | 1380 LDAscr:SBC#&40:STAscr:DECscr+1 140 | 1390 LDY#7:BCSa70:DECscr+1:SEC:BCSa70 141 | 1400 .e60 DECls:BEQd60:LDAerr:SBCerrs 142 | 1410 STAerr:INCcnt:BCSf60 143 | 1420 .d60 RTS 144 | 1430 .a70 LDAerr:LDX#&11 145 | 1440 .b70 SBC#dy:BCSby0:ADC#dx:STAerr 146 | 1450 TXA:AND c:EOR (scr),Y:STA(scr),Y 147 | 1460 DECcnt:BEQe70:.f70 DEY:BPLad0 148 | 1470 LDAscr:SBC#&38:LDY#7:STAscr 149 | 1480 LDAscr+1:SBC#1:STAscr+1:JMPa00 150 | 1490 .e70 DECls:BEQd70:LDAerr:SBCerrs 151 | 1500 STAerr:INCcnt:BCSf70 152 | 1510 .d70 RTS:.by0 STAerr 153 | 1520 TXA:AND c:EOR (scr),Y:STA(scr),Y 154 | 1530 .ad0 LDAscr:ADC#7:STAscr:BCSac0 155 | 1540 SEC:JMPa00 156 | 1550 .ac0 INCscr+1:JMPa00 157 | 1560 .a01 LDAerr:LDX#&FF 158 | 1570 .b01 SBC#dy:BCSb51:ADC#dx:STAerr 159 | 1580 LDA#&11:AND c:EOR (scr),Y:STA(scr),Y 160 | 1590 DECcnt:BEQe01:.f01 DEY:BPLa11 161 | 1600 LDAscr:SBC#&40:STAscr:DECscr+1 162 | 1610 LDY#7:BCSa11:DECscr+1:SEC:BCSa11 163 | 1620 .e01 DECls:BEQd01:LDAerr:SBCerrs 164 | 1630 STAerr:INCcnt:BCSf01 165 | 1640 .d01 RTS 166 | 1650 .a11 LDAerr:LDX#&EE 167 | 1660 .b51 SBC#dy:BCSb61:ADC#dx:STAerr 168 | 1670 TXA:AND #&33:AND c:EOR (scr),Y:STA(scr),Y 169 | 1680 DECcnt:BEQe51:.f51 DEY:BPLa61 170 | 1690 LDAscr:SBC#&40:STAscr:DECscr+1 171 | 1700 LDY#7:BCSa61:DECscr+1:SEC:BCSa61 172 | 1710 .e51 DECls:BEQd51:LDAerr:SBCerrs 173 | 1720 STAerr:INCcnt:BCSf51 174 | 1730 .d51 RTS 175 | 1740 .a61 LDAerr:LDX#&CC 176 | 1750 .b61 SBC#dy:BCSb71:ADC#dx:STAerr 177 | 1760 TXA:AND #&77:AND c:EOR (scr),Y:STA(scr),Y 178 | 1770 DECcnt:BEQe61:.f61 DEY:BPLa71 179 | 1780 LDAscr:SBC#&40:STAscr:DECscr+1 180 | 1790 LDY#7:BCSa71:DECscr+1:SEC:BCSa71 181 | 1800 .e61 DECls:BEQd61:LDAerr:SBCerrs 182 | 1810 STAerr:INCcnt:BCSf61 183 | 1820 .d61 RTS 184 | 1830 .a71 LDAerr:LDX#&88 185 | 1840 .b71 SBC#dy:BCSby1:ADC#dx:STAerr 186 | 1850 TXA:AND c:EOR (scr),Y:STA(scr),Y 187 | 1860 DECcnt:BEQe71:.f71 DEY:BPLsb1 188 | 1870 LDAscr:SBC#&48:LDY#7:STAscr 189 | 1880 LDAscr+1:SBC#1:STAscr+1:JMPa01 190 | 1890 .e71 DECls:BEQd71:LDAerr:SBCerrs 191 | 1900 STAerr:INCcnt:BCSf71 192 | 1910 .d71 RTS:.by1 STAerr 193 | 1920 TXA:AND c:EOR (scr),Y:STA(scr),Y 194 | 1930 .sb1 LDAscr:SBC#8:STAscr:BCCsc1 195 | 1940 JMPa01 196 | 1950 .sc1 DECscr+1:SEC:JMPa01 197 | 1960 .p02 LDA#&88:AND c:EOR (scr),Y:STA(scr),Y 198 | 1970 TXA:.a02 SBC#dx:BCCb02 199 | 1980 DEY:BPLa02:TAX 200 | 1990 .s02 LDY#7:DECscr+1:LDAscr:SBC#&40 201 | 2000 STAscr:TXA:BCSa02:DECscr+1:SEC:BCSa02 202 | 2010 .e02 DECls:BEQd02:SBCerrs 203 | 2020 INCcnt:BCSn02:.d02 RTS 204 | 2030 .b02 ADC#dy:DECcnt:BEQe02 205 | 2040 .n02 TAX:DEY:BPLp52:LDY#7:DECscr+1:LDAscr:SBC#&40:STAscr:BCSp52:DECscr+1:SEC 206 | 2050 .p52 LDA#&44:AND c:EOR (scr),Y:STA(scr),Y 207 | 2060 TXA:.a52 SBC#dx:BCCb52 208 | 2070 DEY:BPLa52:TAX 209 | 2080 .s52 LDY#7:DECscr+1:LDAscr:SBC#&40 210 | 2090 STAscr:TXA:BCSa52:DECscr+1:SEC:BCSa52 211 | 2100 .e52 DECls:BEQd52:SBCerrs 212 | 2110 INCcnt:BCSn52:.d52 RTS 213 | 2120 .b52 ADC#dy:DECcnt:BEQe52 214 | 2130 .n52 TAX:DEY:BPLp62:LDY#7:DECscr+1:LDAscr:SBC#&40:STAscr:BCSp62:DECscr+1:SEC 215 | 2140 .p62 LDA#&22:AND c:EOR (scr),Y:STA(scr),Y 216 | 2150 TXA:.a62 SBC#dx:BCCb62 217 | 2160 DEY:BPLa62:TAX 218 | 2170 .s62 LDY#7:DECscr+1:LDAscr:SBC#&40 219 | 2180 STAscr:TXA:BCSa62:DECscr+1:SEC:BCSa62 220 | 2190 .e62 DECls:BEQd62:SBCerrs 221 | 2200 INCcnt:BCSn62:.d62 RTS 222 | 2210 .b62 ADC#dy:DECcnt:BEQe62 223 | 2220 .n62 TAX:DEY:BPLp72:LDY#7:DECscr+1:LDAscr:SBC#&40:STAscr:BCSp72:DECscr+1:SEC 224 | 2230 .p72 LDA#&11:AND c:EOR (scr),Y:STA(scr),Y 225 | 2240 TXA:.a72 SBC#dx:BCCb72 226 | 2250 DEY:BPLa72:TAX 227 | 2260 .s72 LDY#7:DECscr+1:LDAscr:SBC#&40 228 | 2270 STAscr:TXA:BCSa72:DECscr+1:SEC:BCSa72 229 | 2280 .e72 DECls:BEQd72:SBCerrs 230 | 2290 INCcnt:BCSn72:.d72 RTS 231 | 2300 .b72 ADC#dy:DECcnt:BEQe72 232 | 2310 .n72 TAX:DEY:BMIs82 233 | 2320 LDAscr:ADC#7:STAscr:BCSac2 234 | 2330 SEC:JMPp02:.ac2 INCscr+1:JMPp02 235 | 2340 .s82 LDY#7:LDAscr:SBC#&38:STAscr 236 | 2350 LDAscr+1:SBC#1:STAscr+1:JMPp02 237 | 2360 .p03 LDA#&11:AND c:EOR (scr),Y:STA(scr),Y 238 | 2370 TXA:.a03 SBC#dx:BCCb03 239 | 2380 DEY:BPLa03:TAX 240 | 2390 .s03 LDY#7:DECscr+1:LDAscr:SBC#&40 241 | 2400 STAscr:TXA:BCSa03:DECscr+1:SEC:BCSa03 242 | 2410 .e03 DECls:BEQd03:SBCerrs 243 | 2420 INCcnt:BCSn03:.d03 RTS 244 | 2430 .b03 ADC#dy:DECcnt:BEQe03 245 | 2440 .n03 TAX:DEY:BPLp53:LDY#7:DECscr+1:LDAscr:SBC#&40:STAscr:BCSp53:DECscr+1:SEC 246 | 2450 .p53 LDA#&22:AND c:EOR (scr),Y:STA(scr),Y 247 | 2460 TXA:.a53 SBC#dx:BCCb53 248 | 2470 DEY:BPLa53:TAX 249 | 2480 .s53 LDY#7:DECscr+1:LDAscr:SBC#&40 250 | 2490 STAscr:TXA:BCSa53:DECscr+1:SEC:BCSa53 251 | 2500 .e53 DECls:BEQd53:SBCerrs 252 | 2510 INCcnt:BCSn53:.d53 RTS 253 | 2520 .b53 ADC#dy:DECcnt:BEQe53 254 | 2530 .n53 TAX:DEY:BPLp63:LDY#7:DECscr+1:LDAscr:SBC#&40:STAscr:BCSp63:DECscr+1:SEC 255 | 2540 .p63 LDA#&44:AND c:EOR (scr),Y:STA(scr),Y 256 | 2550 TXA:.a63 SBC#dx:BCCb63 257 | 2560 DEY:BPLa63:TAX 258 | 2570 .s63 LDY#7:DECscr+1:LDAscr:SBC#&40 259 | 2580 STAscr:TXA:BCSa63:DECscr+1:SEC:BCSa63 260 | 2590 .e63 DECls:BEQd63:SBCerrs 261 | 2600 INCcnt:BCSn63:.d63 RTS 262 | 2610 .b63 ADC#dy:DECcnt:BEQe63 263 | 2620 .n63 TAX:DEY:BPLp73:LDY#7:DECscr+1:LDAscr:SBC#&40:STAscr:BCSp73:DECscr+1:SEC 264 | 2630 .p73 LDA#&88:AND c:EOR (scr),Y:STA(scr),Y 265 | 2640 TXA:.a73 SBC#dx:BCCb73 266 | 2650 DEY:BPLa73:TAX 267 | 2660 .s73 LDY#7:DECscr+1:LDAscr:SBC#&40 268 | 2670 STAscr:TXA:BCSa73:DECscr+1:SEC:BCSa73 269 | 2680 .e73 DECls:BEQd73:SBCerrs 270 | 2690 INCcnt:BCSn73:.d73 RTS 271 | 2700 .b73 ADC#dy:DECcnt:BEQe73 272 | 2710 .n73 TAX:DEY:BMIs83 273 | 2720 LDAscr:SBC#8:STAscr:BCCac3 274 | 2730 JMPp03:.ac3 DECscr+1:SEC:JMPp03 275 | 2740 .s83 LDY#7:LDAscr:SBC#&48:STAscr 276 | 2750 LDAscr+1:SBC#1:STAscr+1:JMPp03 277 | 2760 ]NEXT 278 | 2770 *SAVE Line5 2F03 3500 279 | -------------------------------------------------------------------------------- /source/linedraw5f.asm: -------------------------------------------------------------------------------- 1 | 2 | ;---------------------------------------------------------------------------------------------------------- 3 | ; Line rendering routine for 2-bits per pixel mode 5, filled/XOR mode 4 | ; Not yet annotated 5 | ;---------------------------------------------------------------------------------------------------------- 6 | 7 | 8 | 9 | .linedraw5f_noline RTS 10 | 11 | .linedraw5f 12 | { 13 | LDA colors,X:STA c 14 | LSR x0:LSR x1 15 | LDA x0:CMP x1:BCC itsoknow:BEQ linedraw5f_noline 16 | LDX x0:LDY x1:STY x0:STX x1 17 | LDX y0:LDY y1:STY y0:STX y1 18 | .itsoknow DEC x1 19 | LDA y0:SEC:SBC y1:BCS dyok 20 | SBC #0:EOR #&FF 21 | LDX x0:LDY x1:STY x0:STX x1 22 | LDY y1:STY y0 23 | .dyok STA dy 24 | LDA x0:SBC x1:PHP:BCS dxok 25 | SBC #0:EOR #&FF 26 | .dxok TAX 27 | LDA #&80:STA scr 28 | LDA y0:LSR A:LSR A:LSR A:STA scr+1 29 | LSR A:ROR scr:LSR A:ROR scr 30 | ADC scr+1:STA scr+1 31 | LDA x0:AND #&7C:ASL A:ADC scr:STA scr 32 | LDA scrstrt:ADC scr+1:STA scr+1 33 | LDA x0:AND #3:TAY 34 | CPX dy:BCS notsteep:JMP steep 35 | .notsteep 36 | LDA dy:BEQ horizontal:STA cnt 37 | TXA:LSR A:STA err:STA errs 38 | LDA #2:STA ls 39 | .backh PLP:BCC right 40 | LDA strt1,Y:STA x1 41 | LDA strt1+4,Y:STA y1 42 | LDA y0:AND #7:TAY 43 | STX b01+5:STX b51+5 44 | STX b61+5:STX b71+5 45 | LDA dy 46 | STA b01+1:STA b51+1 47 | STA b61+1:STA b71+1 48 | SEC:JMP (x1) 49 | .horizontal STX err 50 | LDA #1:STA ls:STA cnt:STA dy 51 | BNE backh 52 | .right 53 | LDA strt0,Y:STA x1 54 | LDA strt0+4,Y:STA y1 55 | LDA y0:AND #7:TAY 56 | STX b00+5:STX b50+5 57 | STX b60+5:STX b70+5 58 | LDA dy 59 | STA b00+1:STA b50+1 60 | STA b60+1:STA b70+1 61 | SEC:JMP (x1) 62 | .steep 63 | TXA:BEQ vertical:STX cnt 64 | LDA dy:LSR A:STA errs 65 | LDA #2:STA ls 66 | .backv PLP:BCS left 67 | LDA strt2,Y:STA x1 68 | LDA strt2+4,Y:STA y1 69 | LDA y0:AND #7:TAY 70 | STX a02+1:STX a52+1 71 | STX a62+1:STX a72+1 72 | LDA dy 73 | STA b02+1:STA b52+1 74 | STA b62+1:STA b72+1 75 | LDX errs:SEC:JMP (x1) 76 | .vertical LDA dy:STA errs 77 | LDX #1:STX ls:STX cnt 78 | BNE backv 79 | .left 80 | LDA strt3,Y:STA x1 81 | LDA strt3+4,Y:STA y1 82 | LDA y0:AND #7:TAY 83 | STX a03+1:STX a53+1 84 | STX a63+1:STX a73+1 85 | LDA dy 86 | STA b03+1:STA b53+1 87 | STA b63+1:STA b73+1 88 | LDX errs:SEC:JMP (x1) 89 | .a00 LDA err:LDX #&FF 90 | .b00 SBC #dy:BCS b50:ADC #dx:STA err 91 | LDA #&88:AND c:EOR (scr),Y:STA (scr),Y 92 | DEC cnt:BEQ e00:.f00 DEY:BPL a10 93 | LDA scr:SBC #&40:STA scr:DEC scr+1 94 | LDY #7:BCS a10:DEC scr+1:SEC:BCS a10 95 | .e00 DEC ls:BEQ d00:LDA err:SBC errs 96 | STA err:INC cnt:BCS f00 97 | .d00 RTS 98 | .a10 LDA err:LDX #&77 99 | .b50 SBC #dy:BCS b60:ADC #dx:STA err 100 | TXA:AND #&CC:AND c:EOR (scr),Y:STA (scr),Y 101 | DEC cnt:BEQ e50:.f50 DEY:BPL a60 102 | LDA scr:SBC #&40:STA scr:DEC scr+1 103 | LDY #7:BCS a60:DEC scr+1:SEC:BCS a60 104 | .e50 DEC ls:BEQ d50:LDA err:SBC errs 105 | STA err:INC cnt:BCS f50 106 | .d50 RTS 107 | .a60 LDA err:LDX #&33 108 | .b60 SBC #dy:BCS b70:ADC #dx:STA err 109 | TXA:AND #&EE:AND c:EOR (scr),Y:STA (scr),Y 110 | DEC cnt:BEQ e60:.f60 DEY:BPL a70 111 | LDA scr:SBC #&40:STA scr:DEC scr+1 112 | LDY #7:BCS a70:DEC scr+1:SEC:BCS a70 113 | .e60 DEC ls:BEQ d60:LDA err:SBC errs 114 | STA err:INC cnt:BCS f60 115 | .d60 RTS 116 | .a70 LDA err:LDX #&11 117 | .b70 SBC #dy:BCS by0:ADC #dx:STA err 118 | TXA:AND c:EOR (scr),Y:STA (scr),Y 119 | DEC cnt:BEQ e70:.f70 DEY:BPL ad0 120 | LDA scr:SBC #&38:LDY #7:STA scr 121 | LDA scr+1:SBC #1:STA scr+1:JMP a00 122 | .e70 DEC ls:BEQ d70:LDA err:SBC errs 123 | STA err:INC cnt:BCS f70 124 | .d70 RTS:.by0 STA err 125 | TXA:AND c:EOR (scr),Y:STA (scr),Y 126 | .ad0 LDA scr:ADC #7:STA scr:BCS ac0 127 | SEC:JMP a00 128 | .ac0 INC scr+1:JMP a00 129 | .a01 LDA err:LDX #&FF 130 | .b01 SBC #dy:BCS b51:ADC #dx:STA err 131 | LDA #&11:AND c:EOR (scr),Y:STA (scr),Y 132 | DEC cnt:BEQ e01:.f01 DEY:BPL a11 133 | LDA scr:SBC #&40:STA scr:DEC scr+1 134 | LDY #7:BCS a11:DEC scr+1:SEC:BCS a11 135 | .e01 DEC ls:BEQ d01:LDA err:SBC errs 136 | STA err:INC cnt:BCS f01 137 | .d01 RTS 138 | .a11 LDA err:LDX #&EE 139 | .b51 SBC #dy:BCS b61:ADC #dx:STA err 140 | TXA:AND #&33:AND c:EOR (scr),Y:STA (scr),Y 141 | DEC cnt:BEQ e51:.f51 DEY:BPL a61 142 | LDA scr:SBC #&40:STA scr:DEC scr+1 143 | LDY #7:BCS a61:DEC scr+1:SEC:BCS a61 144 | .e51 DEC ls:BEQ d51:LDA err:SBC errs 145 | STA err:INC cnt:BCS f51 146 | .d51 RTS 147 | .a61 LDA err:LDX #&CC 148 | .b61 SBC #dy:BCS b71:ADC #dx:STA err 149 | TXA:AND #&77:AND c:EOR (scr),Y:STA (scr),Y 150 | DEC cnt:BEQ e61:.f61 DEY:BPL a71 151 | LDA scr:SBC #&40:STA scr:DEC scr+1 152 | LDY #7:BCS a71:DEC scr+1:SEC:BCS a71 153 | .e61 DEC ls:BEQ d61:LDA err:SBC errs 154 | STA err:INC cnt:BCS f61 155 | .d61 RTS 156 | .a71 LDA err:LDX #&88 157 | .b71 SBC #dy:BCS by1:ADC #dx:STA err 158 | TXA:AND c:EOR (scr),Y:STA (scr),Y 159 | DEC cnt:BEQ e71:.f71 DEY:BPL sb1 160 | LDA scr:SBC #&48:LDY #7:STA scr 161 | LDA scr+1:SBC #1:STA scr+1:JMP a01 162 | .e71 DEC ls:BEQ d71:LDA err:SBC errs 163 | STA err:INC cnt:BCS f71 164 | .d71 RTS:.by1 STA err 165 | TXA:AND c:EOR (scr),Y:STA (scr),Y 166 | .sb1 LDA scr:SBC #8:STA scr:BCC sc1 167 | JMP a01 168 | .sc1 DEC scr+1:SEC:JMP a01 169 | .p02 LDA #&88:AND c:EOR (scr),Y:STA (scr),Y 170 | TXA:.a02 SBC #dx:BCC b02 171 | DEY:BPL a02:TAX 172 | .s02 LDY #7:DEC scr+1:LDA scr:SBC #&40 173 | STA scr:TXA:BCS a02:DEC scr+1:SEC:BCS a02 174 | .e02 DEC ls:BEQ d02:SBC errs 175 | INC cnt:BCS n02:.d02 RTS 176 | .b02 ADC #dy:DEC cnt:BEQ e02 177 | .n02 TAX:DEY:BPL p52:LDY #7:DEC scr+1:LDA scr:SBC #&40:STA scr:BCS p52:DEC scr+1:SEC 178 | .p52 LDA #&44:AND c:EOR (scr),Y:STA (scr),Y 179 | TXA:.a52 SBC #dx:BCC b52 180 | DEY:BPL a52:TAX 181 | .s52 LDY #7:DEC scr+1:LDA scr:SBC #&40 182 | STA scr:TXA:BCS a52:DEC scr+1:SEC:BCS a52 183 | .e52 DEC ls:BEQ d52:SBC errs 184 | INC cnt:BCS n52:.d52 RTS 185 | .b52 ADC #dy:DEC cnt:BEQ e52 186 | .n52 TAX:DEY:BPL p62:LDY #7:DEC scr+1:LDA scr:SBC #&40:STA scr:BCS p62:DEC scr+1:SEC 187 | .p62 LDA #&22:AND c:EOR (scr),Y:STA (scr),Y 188 | TXA:.a62 SBC #dx:BCC b62 189 | DEY:BPL a62:TAX 190 | .s62 LDY #7:DEC scr+1:LDA scr:SBC #&40 191 | STA scr:TXA:BCS a62:DEC scr+1:SEC:BCS a62 192 | .e62 DEC ls:BEQ d62:SBC errs 193 | INC cnt:BCS n62:.d62 RTS 194 | .b62 ADC #dy:DEC cnt:BEQ e62 195 | .n62 TAX:DEY:BPL p72:LDY #7:DEC scr+1:LDA scr:SBC #&40:STA scr:BCS p72:DEC scr+1:SEC 196 | .p72 LDA #&11:AND c:EOR (scr),Y:STA (scr),Y 197 | TXA:.a72 SBC #dx:BCC b72 198 | DEY:BPL a72:TAX 199 | .s72 LDY #7:DEC scr+1:LDA scr:SBC #&40 200 | STA scr:TXA:BCS a72:DEC scr+1:SEC:BCS a72 201 | .e72 DEC ls:BEQ d72:SBC errs 202 | INC cnt:BCS n72:.d72 RTS 203 | .b72 ADC #dy:DEC cnt:BEQ e72 204 | .n72 TAX:DEY:BMI s82 205 | LDA scr:ADC #7:STA scr:BCS ac2 206 | SEC:JMP p02:.ac2 INC scr+1:JMP p02 207 | .s82 LDY #7:LDA scr:SBC #&38:STA scr 208 | LDA scr+1:SBC #1:STA scr+1:JMP p02 209 | .p03 LDA #&11:AND c:EOR (scr),Y:STA (scr),Y 210 | TXA:.a03 SBC #dx:BCC b03 211 | DEY:BPL a03:TAX 212 | .s03 LDY #7:DEC scr+1:LDA scr:SBC #&40 213 | STA scr:TXA:BCS a03:DEC scr+1:SEC:BCS a03 214 | .e03 DEC ls:BEQ d03:SBC errs 215 | INC cnt:BCS n03:.d03 RTS 216 | .b03 ADC #dy:DEC cnt:BEQ e03 217 | .n03 TAX:DEY:BPL p53:LDY #7:DEC scr+1:LDA scr:SBC #&40:STA scr:BCS p53:DEC scr+1:SEC 218 | .p53 LDA #&22:AND c:EOR (scr),Y:STA (scr),Y 219 | TXA:.a53 SBC #dx:BCC b53 220 | DEY:BPL a53:TAX 221 | .s53 LDY #7:DEC scr+1:LDA scr:SBC #&40 222 | STA scr:TXA:BCS a53:DEC scr+1:SEC:BCS a53 223 | .e53 DEC ls:BEQ d53:SBC errs 224 | INC cnt:BCS n53:.d53 RTS 225 | .b53 ADC #dy:DEC cnt:BEQ e53 226 | .n53 TAX:DEY:BPL p63:LDY #7:DEC scr+1:LDA scr:SBC #&40:STA scr:BCS p63:DEC scr+1:SEC 227 | .p63 LDA #&44:AND c:EOR (scr),Y:STA (scr),Y 228 | TXA:.a63 SBC #dx:BCC b63 229 | DEY:BPL a63:TAX 230 | .s63 LDY #7:DEC scr+1:LDA scr:SBC #&40 231 | STA scr:TXA:BCS a63:DEC scr+1:SEC:BCS a63 232 | .e63 DEC ls:BEQ d63:SBC errs 233 | INC cnt:BCS n63:.d63 RTS 234 | .b63 ADC #dy:DEC cnt:BEQ e63 235 | .n63 TAX:DEY:BPL p73:LDY #7:DEC scr+1:LDA scr:SBC #&40:STA scr:BCS p73:DEC scr+1:SEC 236 | .p73 LDA #&88:AND c:EOR (scr),Y:STA (scr),Y 237 | TXA:.a73 SBC #dx:BCC b73 238 | DEY:BPL a73:TAX 239 | .s73 LDY #7:DEC scr+1:LDA scr:SBC #&40 240 | STA scr:TXA:BCS a73:DEC scr+1:SEC:BCS a73 241 | .e73 DEC ls:BEQ d73:SBC errs 242 | INC cnt:BCS n73:.d73 RTS 243 | .b73 ADC #dy:DEC cnt:BEQ e73 244 | .n73 TAX:DEY:BMI s83 245 | LDA scr:SBC #8:STA scr:BCC ac3 246 | JMP p03:.ac3 DEC scr+1:SEC:JMP p03 247 | .s83 LDY #7:LDA scr:SBC #&48:STA scr 248 | LDA scr+1:SBC #1:STA scr+1 249 | JMP p03 250 | 251 | 252 | ; 2bpp mode colour lookup table 253 | ; 0 = WWYR - not used, as no lines are rendered in black 254 | ; 1 = RRRR 255 | ; 2 = YYYY 256 | ; 3 = WWWW 257 | .colors EQUD&FFF00F00;ED 258 | 259 | 260 | .strt0 261 | EQUB a00 AND &FF:EQUB a10 AND &FF 262 | EQUB a60 AND &FF:EQUB a70 AND &FF 263 | EQUB a00 DIV 256:EQUB a10 DIV 256 264 | EQUB a60 DIV 256:EQUB a70 DIV 256 265 | .strt1 266 | EQUB a71 AND &FF:EQUB a61 AND &FF 267 | EQUB a11 AND &FF:EQUB a01 AND &FF 268 | EQUB a71 DIV 256:EQUB a61 DIV 256 269 | EQUB a11 DIV 256:EQUB a01 DIV 256 270 | .strt2 271 | EQUB p02 AND &FF:EQUB p52 AND &FF 272 | EQUB p62 AND &FF:EQUB p72 AND &FF 273 | EQUB p02 DIV 256:EQUB p52 DIV 256 274 | EQUB p62 DIV 256:EQUB p72 DIV 256 275 | .strt3 276 | EQUB p73 AND &FF:EQUB p63 AND &FF 277 | EQUB p53 AND &FF:EQUB p03 AND &FF 278 | EQUB p73 DIV 256:EQUB p63 DIV 256 279 | EQUB p53 DIV 256:EQUB p03 DIV 256 280 | } 281 | -------------------------------------------------------------------------------- /basic/Line3D.txt: -------------------------------------------------------------------------------- 1 | 1 REM RUN WITH PAGE=&4000 2 | 10 MODE 7 3 | 20 x0=&70:y0=&71 4 | 30 x1=&72:y1=&73 5 | 40 scr=&74 6 | 50 err=&76 7 | 60 errs=&77 8 | 70 cnt=&78 9 | 80 ls=&79 10 | 90 dx=&FF 11 | 100 dy=&7A 12 | 110 scrstrt=&7B 13 | 120 FOR pass=0TO 3STEP 3 14 | 130 P%=&26BA 15 | 140 [OPTpass 16 | 150 .strt0 17 | 160 EQUBa00 AND &FF:EQUBa10 AND &FF 18 | 170 EQUBa20 AND &FF:EQUBa30 AND &FF 19 | 180 EQUBa40 AND &FF:EQUBa50 AND &FF 20 | 190 EQUBa60 AND &FF:EQUBa70 AND &FF 21 | 200 EQUBa00 DIV 256:EQUBa10 DIV 256 22 | 210 EQUBa20 DIV 256:EQUBa30 DIV 256 23 | 220 EQUBa40 DIV 256:EQUBa50 DIV 256 24 | 230 EQUBa60 DIV 256:EQUBa70 DIV 256 25 | 240 .strt1 26 | 250 EQUBa71 AND &FF:EQUBa61 AND &FF 27 | 260 EQUBa51 AND &FF:EQUBa41 AND &FF 28 | 270 EQUBa31 AND &FF:EQUBa21 AND &FF 29 | 280 EQUBa11 AND &FF:EQUBa01 AND &FF 30 | 290 EQUBa71 DIV 256:EQUBa61 DIV 256 31 | 300 EQUBa51 DIV 256:EQUBa41 DIV 256 32 | 310 EQUBa31 DIV 256:EQUBa21 DIV 256 33 | 320 EQUBa11 DIV 256:EQUBa01 DIV 256 34 | 330 .strt2 35 | 340 EQUBp02 AND &FF:EQUBp12 AND &FF 36 | 350 EQUBp22 AND &FF:EQUBp32 AND &FF 37 | 360 EQUBp42 AND &FF:EQUBp52 AND &FF 38 | 370 EQUBp62 AND &FF:EQUBp72 AND &FF 39 | 380 EQUBp02 DIV 256:EQUBp12 DIV 256 40 | 390 EQUBp22 DIV 256:EQUBp32 DIV 256 41 | 400 EQUBp42 DIV 256:EQUBp52 DIV 256 42 | 410 EQUBp62 DIV 256:EQUBp72 DIV 256 43 | 420 .strt3 44 | 430 EQUBp73 AND &FF:EQUBp63 AND &FF 45 | 440 EQUBp53 AND &FF:EQUBp43 AND &FF 46 | 450 EQUBp33 AND &FF:EQUBp23 AND &FF 47 | 460 EQUBp13 AND &FF:EQUBp03 AND &FF 48 | 470 EQUBp73 DIV 256:EQUBp63 DIV 256 49 | 480 EQUBp53 DIV 256:EQUBp43 DIV 256 50 | 490 EQUBp33 DIV 256:EQUBp23 DIV 256 51 | 500 EQUBp13 DIV 256:EQUBp03 DIV 256 52 | 510 .linedraw 53 | 520 LDAy0:SEC:SBCy1:BCSdyok 54 | 530 SBC#0:EOR #&FF 55 | 540 LDXx0:LDYx1:STYx0:STXx1 56 | 550 LDYy1:STYy0 57 | 560 .dyok STAdy 58 | 570 LDAx0:SBCx1:PHP:BCSdxok 59 | 580 SBC#0:EOR #&FF 60 | 590 .dxok TAX 61 | 600 LDA#&80:STAscr 62 | 610 LDAy0:LSRA:LSRA:LSRA:STAscr+1 63 | 620 LSRA:RORscr:LSRA:RORscr 64 | 630 ADCscr+1:STAscr+1 65 | 640 LDAx0:AND #&F8:ADCscr:STAscr 66 | 650 LDAscrstrt:ADCscr+1:STAscr+1 67 | 660 LDAx0:AND #7:TAY 68 | 670 CPXdy:BCSnotsteep:JMPsteep 69 | 680 .notsteep 70 | 690 LDAdy:BEQhorizontal:STAcnt 71 | 700 TXA:LSRA:STAerr:STAerrs 72 | 710 LDA#2:STAls 73 | 720 .backh PLP:BCCright 74 | 730 LDAstrt1,Y:STAx1 75 | 740 LDAstrt1+8,Y:STAy1 76 | 750 LDAy0:AND #7:TAY 77 | 760 STXb01+5:STXb11+5 78 | 770 STXb21+5:STXb31+5 79 | 780 STXb41+5:STXb51+5 80 | 790 STXb61+5:STXb71+5 81 | 800 LDAdy 82 | 810 STAb01+1:STAb11+1 83 | 820 STAb21+1:STAb31+1 84 | 830 STAb41+1:STAb51+1 85 | 840 STAb61+1:STAb71+1 86 | 850 SEC:JMP(x1) 87 | 860 .horizontal STXerr 88 | 870 LDA#1:STAls:STAcnt:STAdy 89 | 880 BNEbackh 90 | 890 .right 91 | 900 LDAstrt0,Y:STAx1 92 | 910 LDAstrt0+8,Y:STAy1 93 | 920 LDAy0:AND #7:TAY 94 | 930 STXb00+5:STXb10+5 95 | 940 STXb20+5:STXb30+5 96 | 950 STXb40+5:STXb50+5 97 | 960 STXb60+5:STXb70+5 98 | 970 LDAdy 99 | 980 STAb00+1:STAb10+1 100 | 990 STAb20+1:STAb30+1 101 | 1000 STAb40+1:STAb50+1 102 | 1010 STAb60+1:STAb70+1 103 | 1020 SEC:JMP(x1) 104 | 1030 .steep 105 | 1040 TXA:BEQvertical:STXcnt 106 | 1050 LDAdy:LSRA:STAerrs 107 | 1060 LDA#2:STAls 108 | 1070 .backv PLP:BCSleft 109 | 1080 LDAstrt2,Y:STAx1 110 | 1090 LDAstrt2+8,Y:STAy1 111 | 1100 LDAy0:AND #7:TAY 112 | 1110 STXa02+1:STXa12+1 113 | 1120 STXa22+1:STXa32+1 114 | 1130 STXa42+1:STXa52+1 115 | 1140 STXa62+1:STXa72+1 116 | 1150 LDAdy 117 | 1160 STAb02+1:STAb12+1 118 | 1170 STAb22+1:STAb32+1 119 | 1180 STAb42+1:STAb52+1 120 | 1190 STAb62+1:STAb72+1 121 | 1200 LDXerrs:SEC:JMP(x1) 122 | 1210 .vertical LDAdy:STAerrs 123 | 1220 LDX#1:STXls:STXcnt 124 | 1230 BNEbackv 125 | 1240 .left 126 | 1250 LDAstrt3,Y:STAx1 127 | 1260 LDAstrt3+8,Y:STAy1 128 | 1270 LDAy0:AND #7:TAY 129 | 1280 STXa03+1:STXa13+1 130 | 1290 STXa23+1:STXa33+1 131 | 1300 STXa43+1:STXa53+1 132 | 1310 STXa63+1:STXa73+1 133 | 1320 LDAdy 134 | 1330 STAb03+1:STAb13+1 135 | 1340 STAb23+1:STAb33+1 136 | 1350 STAb43+1:STAb53+1 137 | 1360 STAb63+1:STAb73+1 138 | 1370 LDXerrs:SEC:JMP(x1) 139 | 1380 .a00 LDAerr:LDX#&FF 140 | 1390 .b00 SBC#dy:BCSb10:ADC#dx:STAerr 141 | 1400 LDA#&80:OR A(scr),Y:STA(scr),Y 142 | 1410 DECcnt:BEQe00:.f00 DEY:BPLa10 143 | 1420 LDAscr:SBC#&40:STAscr:DECscr+1 144 | 1430 LDY#7:BCSa10:DECscr+1:SEC:BCSa10 145 | 1440 .e00 DECls:BEQd00:LDAerr:SBCerrs 146 | 1450 STAerr:INCcnt:BCSf00 147 | 1460 .d00 RTS 148 | 1470 .a10 LDAerr:LDX#&7F 149 | 1480 .b10 SBC#dy:BCSb20:ADC#dx:STAerr 150 | 1490 TXA:AND #&C0:OR A(scr),Y:STA(scr),Y 151 | 1500 DECcnt:BEQe10:.f10 DEY:BPLa20 152 | 1510 LDAscr:SBC#&40:STAscr:DECscr+1 153 | 1520 LDY#7:BCSa20:DECscr+1:SEC:BCSa20 154 | 1530 .e10 DECls:BEQd10:LDAerr:SBCerrs 155 | 1540 STAerr:INCcnt:BCSf10 156 | 1550 .d10 RTS 157 | 1560 .a20 LDAerr:LDX#&3F 158 | 1570 .b20 SBC#dy:BCSb30:ADC#dx:STAerr 159 | 1580 TXA:AND #&E0:OR A(scr),Y:STA(scr),Y 160 | 1590 DECcnt:BEQe20:.f20 DEY:BPLa30 161 | 1600 LDAscr:SBC#&40:STAscr:DECscr+1 162 | 1610 LDY#7:BCSa30:DECscr+1:SEC:BCSa30 163 | 1620 .e20 DECls:BEQd20:LDAerr:SBCerrs 164 | 1630 STAerr:INCcnt:BCSf20 165 | 1640 .d20 RTS 166 | 1650 .a30 LDAerr:LDX#&1F 167 | 1660 .b30 SBC#dy:BCSb40:ADC#dx:STAerr 168 | 1670 TXA:AND #&F0:OR A(scr),Y:STA(scr),Y 169 | 1680 DECcnt:BEQe30:.f30 DEY:BPLa40 170 | 1690 LDAscr:SBC#&40:STAscr:DECscr+1 171 | 1700 LDY#7:BCSa40:DECscr+1:SEC:BCSa40 172 | 1710 .e30 DECls:BEQd30:LDAerr:SBCerrs 173 | 1720 STAerr:INCcnt:BCSf30 174 | 1730 .d30 RTS 175 | 1740 .a40 LDAerr:LDX#&F 176 | 1750 .b40 SBC#dy:BCSb50:ADC#dx:STAerr 177 | 1760 TXA:AND #&F8:OR A(scr),Y:STA(scr),Y 178 | 1770 DECcnt:BEQe40:.f40 DEY:BPLa50 179 | 1780 LDAscr:SBC#&40:STAscr:DECscr+1 180 | 1790 LDY#7:BCSa50:DECscr+1:SEC:BCSa50 181 | 1800 .e40 DECls:BEQd40:LDAerr:SBCerrs 182 | 1810 STAerr:INCcnt:BCSf40 183 | 1820 .d40 RTS 184 | 1830 .a50 LDAerr:LDX#7 185 | 1840 .b50 SBC#dy:BCSb60:ADC#dx:STAerr 186 | 1850 TXA:AND #&FC:OR A(scr),Y:STA(scr),Y 187 | 1860 DECcnt:BEQe50:.f50 DEY:BPLa60 188 | 1870 LDAscr:SBC#&40:STAscr:DECscr+1 189 | 1880 LDY#7:BCSa60:DECscr+1:SEC:BCSa60 190 | 1890 .e50 DECls:BEQd50:LDAerr:SBCerrs 191 | 1900 STAerr:INCcnt:BCSf50 192 | 1910 .d50 RTS 193 | 1920 .a60 LDAerr:LDX#3 194 | 1930 .b60 SBC#dy:BCSb70:ADC#dx:STAerr 195 | 1940 TXA:AND #&FE:OR A(scr),Y:STA(scr),Y 196 | 1950 DECcnt:BEQe60:.f60 DEY:BPLa70 197 | 1960 LDAscr:SBC#&40:STAscr:DECscr+1 198 | 1970 LDY#7:BCSa70:DECscr+1:SEC:BCSa70 199 | 1980 .e60 DECls:BEQd60:LDAerr:SBCerrs 200 | 1990 STAerr:INCcnt:BCSf60 201 | 2000 .d60 RTS 202 | 2010 .a70 LDAerr:LDX#1 203 | 2020 .b70 SBC#dy:BCSby0:ADC#dx:STAerr 204 | 2030 TXA:OR A(scr),Y:STA(scr),Y 205 | 2040 DECcnt:BEQe70:.f70 DEY:BPLad0 206 | 2050 LDAscr:SBC#&38:LDY#7:STAscr 207 | 2060 LDAscr+1:SBC#1:STAscr+1:JMPa00 208 | 2070 .e70 DECls:BEQd70:LDAerr:SBCerrs 209 | 2080 STAerr:INCcnt:BCSf70 210 | 2090 .d70 RTS:.by0 STAerr 211 | 2100 TXA:OR A(scr),Y:STA(scr),Y 212 | 2110 .ad0 LDAscr:ADC#7:STAscr:BCSac0 213 | 2120 SEC:JMPa00 214 | 2130 .ac0 INCscr+1:JMPa00 215 | 2140 .a01 LDAerr:LDX#&FF 216 | 2150 .b01 SBC#dy:BCSb11:ADC#dx:STAerr 217 | 2160 LDA#1:OR A(scr),Y:STA(scr),Y 218 | 2170 DECcnt:BEQe01:.f01 DEY:BPLa11 219 | 2180 LDAscr:SBC#&40:STAscr:DECscr+1 220 | 2190 LDY#7:BCSa11:DECscr+1:SEC:BCSa11 221 | 2200 .e01 DECls:BEQd01:LDAerr:SBCerrs 222 | 2210 STAerr:INCcnt:BCSf01 223 | 2220 .d01 RTS 224 | 2230 .a11 LDAerr:LDX#&FE 225 | 2240 .b11 SBC#dy:BCSb21:ADC#dx:STAerr 226 | 2250 TXA:AND #3:OR A(scr),Y:STA(scr),Y 227 | 2260 DECcnt:BEQe11:.f11 DEY:BPLa21 228 | 2270 LDAscr:SBC#&40:STAscr:DECscr+1 229 | 2280 LDY#7:BCSa21:DECscr+1:SEC:BCSa21 230 | 2290 .e11 DECls:BEQd11:LDAerr:SBCerrs 231 | 2300 STAerr:INCcnt:BCSf11 232 | 2310 .d11 RTS 233 | 2320 .a21 LDAerr:LDX#&FC 234 | 2330 .b21 SBC#dy:BCSb31:ADC#dx:STAerr 235 | 2340 TXA:AND #7:OR A(scr),Y:STA(scr),Y 236 | 2350 DECcnt:BEQe21:.f21 DEY:BPLa31 237 | 2360 LDAscr:SBC#&40:STAscr:DECscr+1 238 | 2370 LDY#7:BCSa31:DECscr+1:SEC:BCSa31 239 | 2380 .e21 DECls:BEQd21:LDAerr:SBCerrs 240 | 2390 STAerr:INCcnt:BCSf21 241 | 2400 .d21 RTS 242 | 2410 .a31 LDAerr:LDX#&F8 243 | 2420 .b31 SBC#dy:BCSb41:ADC#dx:STAerr 244 | 2430 TXA:AND #&F:OR A(scr),Y:STA(scr),Y 245 | 2440 DECcnt:BEQe31:.f31 DEY:BPLa41 246 | 2450 LDAscr:SBC#&40:STAscr:DECscr+1 247 | 2460 LDY#7:BCSa41:DECscr+1:SEC:BCSa41 248 | 2470 .e31 DECls:BEQd31:LDAerr:SBCerrs 249 | 2480 STAerr:INCcnt:BCSf31 250 | 2490 .d31 RTS 251 | 2500 .a41 LDAerr:LDX#&F0 252 | 2510 .b41 SBC#dy:BCSb51:ADC#dx:STAerr 253 | 2520 TXA:AND #&1F:OR A(scr),Y:STA(scr),Y 254 | 2530 DECcnt:BEQe41:.f41 DEY:BPLa51 255 | 2540 LDAscr:SBC#&40:STAscr:DECscr+1 256 | 2550 LDY#7:BCSa51:DECscr+1:SEC:BCSa51 257 | 2560 .e41 DECls:BEQd41:LDAerr:SBCerrs 258 | 2570 STAerr:INCcnt:BCSf41 259 | 2580 .d41 RTS 260 | 2590 .a51 LDAerr:LDX#&E0 261 | 2600 .b51 SBC#dy:BCSb61:ADC#dx:STAerr 262 | 2610 TXA:AND #&3F:OR A(scr),Y:STA(scr),Y 263 | 2620 DECcnt:BEQe51:.f51 DEY:BPLa61 264 | 2630 LDAscr:SBC#&40:STAscr:DECscr+1 265 | 2640 LDY#7:BCSa61:DECscr+1:SEC:BCSa61 266 | 2650 .e51 DECls:BEQd51:LDAerr:SBCerrs 267 | 2660 STAerr:INCcnt:BCSf51 268 | 2670 .d51 RTS 269 | 2680 .a61 LDAerr:LDX#&C0 270 | 2690 .b61 SBC#dy:BCSb71:ADC#dx:STAerr 271 | 2700 TXA:AND #&7F:OR A(scr),Y:STA(scr),Y 272 | 2710 DECcnt:BEQe61:.f61 DEY:BPLa71 273 | 2720 LDAscr:SBC#&40:STAscr:DECscr+1 274 | 2730 LDY#7:BCSa71:DECscr+1:SEC:BCSa71 275 | 2740 .e61 DECls:BEQd61:LDAerr:SBCerrs 276 | 2750 STAerr:INCcnt:BCSf61 277 | 2760 .d61 RTS 278 | 2770 .a71 LDAerr:LDX#&80 279 | 2780 .b71 SBC#dy:BCSby1:ADC#dx:STAerr 280 | 2790 TXA:OR A(scr),Y:STA(scr),Y 281 | 2800 DECcnt:BEQe71:.f71 DEY:BPLsb1 282 | 2810 LDAscr:SBC#&48:LDY#7:STAscr 283 | 2820 LDAscr+1:SBC#1:STAscr+1:JMPa01 284 | 2830 .e71 DECls:BEQd71:LDAerr:SBCerrs 285 | 2840 STAerr:INCcnt:BCSf71 286 | 2850 .d71 RTS:.by1 STAerr 287 | 2860 TXA:OR A(scr),Y:STA(scr),Y 288 | 2870 .sb1 LDAscr:SBC#8:STAscr:BCCsc1 289 | 2880 JMPa01 290 | 2890 .sc1 DECscr+1:SEC:JMPa01 291 | 2900 .p02 LDA#&80:OR A(scr),Y:STA(scr),Y 292 | 2910 TXA:.a02 SBC#dx:BCCb02:TAX 293 | 2920 DEY:BPLp02 294 | 2930 .s02 LDY#7:DECscr+1:LDAscr:SBC#&40 295 | 2940 STAscr:BCSp02:DECscr+1:SEC:BCSp02 296 | 2950 .e02 DECls:BEQd02:SBCerrs 297 | 2960 INCcnt:BCSn02:.d02 RTS 298 | 2970 .b02 ADC#dy:DECcnt:BEQe02 299 | 2980 .n02 TAX:DEY:BMIs12 300 | 2990 .p12 LDA#&40:OR A(scr),Y:STA(scr),Y 301 | 3000 TXA:.a12 SBC#dx:BCCb12:TAX 302 | 3010 DEY:BPLp12 303 | 3020 .s12 LDY#7:DECscr+1:LDAscr:SBC#&40 304 | 3030 STAscr:BCSp12:DECscr+1:SEC:BCSp12 305 | 3040 .e12 DECls:BEQd12:SBCerrs 306 | 3050 INCcnt:BCSn12:.d12 RTS 307 | 3060 .b12 ADC#dy:DECcnt:BEQe12 308 | 3070 .n12 TAX:DEY:BMIs22 309 | 3080 .p22 LDA#&20:OR A(scr),Y:STA(scr),Y 310 | 3090 TXA:.a22 SBC#dx:BCCb22:TAX 311 | 3100 DEY:BPLp22 312 | 3110 .s22 LDY#7:DECscr+1:LDAscr:SBC#&40 313 | 3120 STAscr:BCSp22:DECscr+1:SEC:BCSp22 314 | 3130 .e22 DECls:BEQd22:SBCerrs 315 | 3140 INCcnt:BCSn22:.d22 RTS 316 | 3150 .b22 ADC#dy:DECcnt:BEQe22 317 | 3160 .n22 TAX:DEY:BMIs32 318 | 3170 .p32 LDA#&10:OR A(scr),Y:STA(scr),Y 319 | 3180 TXA:.a32 SBC#dx:BCCb32:TAX 320 | 3190 DEY:BPLp32 321 | 3200 .s32 LDY#7:DECscr+1:LDAscr:SBC#&40 322 | 3210 STAscr:BCSp32:DECscr+1:SEC:BCSp32 323 | 3220 .e32 DECls:BEQd32:SBCerrs 324 | 3230 INCcnt:BCSn32:.d32 RTS 325 | 3240 .b32 ADC#dy:DECcnt:BEQe32 326 | 3250 .n32 TAX:DEY:BMIs42 327 | 3260 .p42 LDA#8:OR A(scr),Y:STA(scr),Y 328 | 3270 TXA:.a42 SBC#dx:BCCb42:TAX 329 | 3280 DEY:BPLp42 330 | 3290 .s42 LDY#7:DECscr+1:LDAscr:SBC#&40 331 | 3300 STAscr:BCSp42:DECscr+1:SEC:BCSp42 332 | 3310 .e42 DECls:BEQd42:SBCerrs 333 | 3320 INCcnt:BCSn42:.d42 RTS 334 | 3330 .b42 ADC#dy:DECcnt:BEQe42 335 | 3340 .n42 TAX:DEY:BMIs52 336 | 3350 .p52 LDA#4:OR A(scr),Y:STA(scr),Y 337 | 3360 TXA:.a52 SBC#dx:BCCb52:TAX 338 | 3370 DEY:BPLp52 339 | 3380 .s52 LDY#7:DECscr+1:LDAscr:SBC#&40 340 | 3390 STAscr:BCSp52:DECscr+1:SEC:BCSp52 341 | 3400 .e52 DECls:BEQd52:SBCerrs 342 | 3410 INCcnt:BCSn52:.d52 RTS 343 | 3420 .b52 ADC#dy:DECcnt:BEQe52 344 | 3430 .n52 TAX:DEY:BMIs62 345 | 3440 .p62 LDA#2:OR A(scr),Y:STA(scr),Y 346 | 3450 TXA:.a62 SBC#dx:BCCb62:TAX 347 | 3460 DEY:BPLp62 348 | 3470 .s62 LDY#7:DECscr+1:LDAscr:SBC#&40 349 | 3480 STAscr:BCSp62:DECscr+1:SEC:BCSp62 350 | 3490 .e62 DECls:BEQd62:SBCerrs 351 | 3500 INCcnt:BCSn62:.d62 RTS 352 | 3510 .b62 ADC#dy:DECcnt:BEQe62 353 | 3520 .n62 TAX:DEY:BMIs72 354 | 3530 .p72 LDA#1:OR A(scr),Y:STA(scr),Y 355 | 3540 TXA:.a72 SBC#dx:BCCb72:TAX 356 | 3550 DEY:BPLp72 357 | 3560 .s72 LDY#7:DECscr+1:LDAscr:SBC#&40 358 | 3570 STAscr:BCSp72:DECscr+1:SEC:BCSp72 359 | 3580 .e72 DECls:BEQd72:SBCerrs 360 | 3590 INCcnt:BCSn72:.d72 RTS 361 | 3600 .b72 ADC#dy:DECcnt:BEQe72 362 | 3610 .n72 TAX:DEY:BMIs82 363 | 3620 LDAscr:ADC#7:STAscr:BCSac2 364 | 3630 SEC:JMPp02:.ac2 INCscr+1:JMPp02 365 | 3640 .s82 LDY#7:LDAscr:SBC#&38:STAscr 366 | 3650 LDAscr+1:SBC#1:STAscr+1:JMPp02 367 | 3660 .p03 LDA#1:OR A(scr),Y:STA(scr),Y 368 | 3670 TXA:.a03 SBC#dx:BCCb03:TAX 369 | 3680 DEY:BPLp03 370 | 3690 .s03 LDY#7:DECscr+1:LDAscr:SBC#&40 371 | 3700 STAscr:BCSp03:DECscr+1:SEC:BCSp03 372 | 3710 .e03 DECls:BEQd03:SBCerrs 373 | 3720 INCcnt:BCSn03:.d03 RTS 374 | 3730 .b03 ADC#dy:DECcnt:BEQe03 375 | 3740 .n03 TAX:DEY:BMIs13 376 | 3750 .p13 LDA#2:OR A(scr),Y:STA(scr),Y 377 | 3760 TXA:.a13 SBC#dx:BCCb13:TAX 378 | 3770 DEY:BPLp13 379 | 3780 .s13 LDY#7:DECscr+1:LDAscr:SBC#&40 380 | 3790 STAscr:BCSp13:DECscr+1:SEC:BCSp13 381 | 3800 .e13 DECls:BEQd13:SBCerrs 382 | 3810 INCcnt:BCSn13:.d13 RTS 383 | 3820 .b13 ADC#dy:DECcnt:BEQe13 384 | 3830 .n13 TAX:DEY:BMIs23 385 | 3840 .p23 LDA#4:OR A(scr),Y:STA(scr),Y 386 | 3850 TXA:.a23 SBC#dx:BCCb23:TAX 387 | 3860 DEY:BPLp23 388 | 3870 .s23 LDY#7:DECscr+1:LDAscr:SBC#&40 389 | 3880 STAscr:BCSp23:DECscr+1:SEC:BCSp23 390 | 3890 .e23 DECls:BEQd23:SBCerrs 391 | 3900 INCcnt:BCSn23:.d23 RTS 392 | 3910 .b23 ADC#dy:DECcnt:BEQe23 393 | 3920 .n23 TAX:DEY:BMIs33 394 | 3930 .p33 LDA#8:OR A(scr),Y:STA(scr),Y 395 | 3940 TXA:.a33 SBC#dx:BCCb33:TAX 396 | 3950 DEY:BPLp33 397 | 3960 .s33 LDY#7:DECscr+1:LDAscr:SBC#&40 398 | 3970 STAscr:BCSp33:DECscr+1:SEC:BCSp33 399 | 3980 .e33 DECls:BEQd33:SBCerrs 400 | 3990 INCcnt:BCSn33:.d33 RTS 401 | 4000 .b33 ADC#dy:DECcnt:BEQe33 402 | 4010 .n33 TAX:DEY:BMIs43 403 | 4020 .p43 LDA#&10:OR A(scr),Y:STA(scr),Y 404 | 4030 TXA:.a43 SBC#dx:BCCb43:TAX 405 | 4040 DEY:BPLp43 406 | 4050 .s43 LDY#7:DECscr+1:LDAscr:SBC#&40 407 | 4060 STAscr:BCSp43:DECscr+1:SEC:BCSp43 408 | 4070 .e43 DECls:BEQd43:SBCerrs 409 | 4080 INCcnt:BCSn43:.d43 RTS 410 | 4090 .b43 ADC#dy:DECcnt:BEQe43 411 | 4100 .n43 TAX:DEY:BMIs53 412 | 4110 .p53 LDA#&20:OR A(scr),Y:STA(scr),Y 413 | 4120 TXA:.a53 SBC#dx:BCCb53:TAX 414 | 4130 DEY:BPLp53 415 | 4140 .s53 LDY#7:DECscr+1:LDAscr:SBC#&40 416 | 4150 STAscr:BCSp53:DECscr+1:SEC:BCSp53 417 | 4160 .e53 DECls:BEQd53:SBCerrs 418 | 4170 INCcnt:BCSn53:.d53 RTS 419 | 4180 .b53 ADC#dy:DECcnt:BEQe53 420 | 4190 .n53 TAX:DEY:BMIs63 421 | 4200 .p63 LDA#&40:OR A(scr),Y:STA(scr),Y 422 | 4210 TXA:.a63 SBC#dx:BCCb63:TAX 423 | 4220 DEY:BPLp63 424 | 4230 .s63 LDY#7:DECscr+1:LDAscr:SBC#&40 425 | 4240 STAscr:BCSp63:DECscr+1:SEC:BCSp63 426 | 4250 .e63 DECls:BEQd63:SBCerrs 427 | 4260 INCcnt:BCSn63:.d63 RTS 428 | 4270 .b63 ADC#dy:DECcnt:BEQe63 429 | 4280 .n63 TAX:DEY:BMIs73 430 | 4290 .p73 LDA#&80:OR A(scr),Y:STA(scr),Y 431 | 4300 TXA:.a73 SBC#dx:BCCb73:TAX 432 | 4310 DEY:BPLp73 433 | 4320 .s73 LDY#7:DECscr+1:LDAscr:SBC#&40 434 | 4330 STAscr:BCSp73:DECscr+1:SEC:BCSp73 435 | 4340 .e73 DECls:BEQd73:SBCerrs 436 | 4350 INCcnt:BCSn73:.d73 RTS 437 | 4360 .b73 ADC#dy:DECcnt:BEQe73 438 | 4370 .n73 TAX:DEY:BMIs83 439 | 4380 LDAscr:SBC#8:STAscr:BCCac3 440 | 4390 JMPp03:.ac3 DECscr+1:SEC:JMPp03 441 | 4400 .s83 LDY#7:LDAscr:SBC#&48:STAscr 442 | 4410 LDAscr+1:SBC#1:STAscr+1:JMPp03 443 | 4420 ]NEXT 444 | 4430 *SAVE Line3D 26BA 3000 445 | -------------------------------------------------------------------------------- /source/linedraw4.asm: -------------------------------------------------------------------------------- 1 | 2 | ;---------------------------------------------------------------------------------------------------------- 3 | ; Line rendering routine for 1-bit per pixel mode 4 4 | ; Not yet annotated 5 | ;---------------------------------------------------------------------------------------------------------- 6 | 7 | 8 | 9 | 10 | 11 | .linedraw4 12 | { 13 | LDA y0:SEC:SBC y1:BCS dyok 14 | SBC #0:EOR #&FF 15 | LDX x0:LDY x1:STY x0:STX x1 16 | LDY y1:STY y0 17 | .dyok STA dy 18 | LDA x0:SBC x1:PHP:BCS dxok 19 | SBC #0:EOR #&FF 20 | .dxok TAX 21 | LDA #&80:STA scr 22 | LDA y0:LSR A:LSR A:LSR A:STA scr+1 23 | LSR A:ROR scr:LSR A:ROR scr 24 | ADC scr+1:STA scr+1 25 | LDA x0:AND #&F8:ADC scr:STA scr 26 | LDA scrstrt:ADC scr+1:STA scr+1 27 | LDA x0:AND #7:TAY 28 | CPX dy:BCS notsteep:JMP steep 29 | 30 | .notsteep 31 | LDA dy:BEQ horizontal:STA cnt 32 | TXA:LSR A:STA err:STA errs 33 | LDA #2:STA ls 34 | .backh PLP:BCC right 35 | LDA strt1,Y:STA x1 36 | LDA strt1+8,Y:STA y1 37 | LDA y0:AND #7:TAY 38 | STX b01+5:STX b11+5 39 | STX b21+5:STX b31+5 40 | STX b41+5:STX b51+5 41 | STX b61+5:STX b71+5 42 | LDA dy 43 | STA b01+1:STA b11+1 44 | STA b21+1:STA b31+1 45 | STA b41+1:STA b51+1 46 | STA b61+1:STA b71+1 47 | SEC:JMP (x1) 48 | .horizontal STX err 49 | LDA #1:STA ls:STA cnt:STA dy 50 | BNE backh 51 | .right 52 | LDA strt0,Y:STA x1 53 | LDA strt0+8,Y:STA y1 54 | LDA y0:AND #7:TAY 55 | STX b00+5:STX b10+5 56 | STX b20+5:STX b30+5 57 | STX b40+5:STX b50+5 58 | STX b60+5:STX b70+5 59 | LDA dy 60 | STA b00+1:STA b10+1 61 | STA b20+1:STA b30+1 62 | STA b40+1:STA b50+1 63 | STA b60+1:STA b70+1 64 | SEC:JMP (x1) 65 | 66 | .steep 67 | TXA:BEQ vertical:STX cnt 68 | LDA dy:LSR A:STA errs 69 | LDA #2:STA ls 70 | .backv PLP:BCS left 71 | LDA strt2,Y:STA x1 72 | LDA strt2+8,Y:STA y1 73 | LDA y0:AND #7:TAY 74 | STX a02+1:STX a12+1 75 | STX a22+1:STX a32+1 76 | STX a42+1:STX a52+1 77 | STX a62+1:STX a72+1 78 | LDA dy 79 | STA b02+1:STA b12+1 80 | STA b22+1:STA b32+1 81 | STA b42+1:STA b52+1 82 | STA b62+1:STA b72+1 83 | LDX errs:SEC:JMP (x1) 84 | 85 | .vertical LDA dy:STA errs 86 | LDX #1:STX ls:STX cnt 87 | BNE backv 88 | .left 89 | LDA strt3,Y:STA x1 90 | LDA strt3+8,Y:STA y1 91 | LDA y0:AND #7:TAY 92 | STX a03+1:STX a13+1 93 | STX a23+1:STX a33+1 94 | STX a43+1:STX a53+1 95 | STX a63+1:STX a73+1 96 | LDA dy 97 | STA b03+1:STA b13+1 98 | STA b23+1:STA b33+1 99 | STA b43+1:STA b53+1 100 | STA b63+1:STA b73+1 101 | LDX errs:SEC:JMP (x1) 102 | 103 | .a00 LDA err:LDX #&FF 104 | .b00 SBC #dy:BCS b10:ADC #dx:STA err 105 | LDA #&80:ORA(scr),Y:STA (scr),Y 106 | DEC cnt:BEQ e00:.f00 DEY:BPL a10 107 | LDA scr:SBC #&40:STA scr:DEC scr+1 108 | LDY #7:BCS a10:DEC scr+1:SEC:BCS a10 109 | .e00 DEC ls:BEQ d00:LDA err:SBC errs 110 | STA err:INC cnt:BCS f00 111 | .d00 RTS 112 | 113 | .a10 LDA err:LDX #&7F 114 | .b10 SBC #dy:BCS b20:ADC #dx:STA err 115 | TXA:AND #&C0:ORA(scr),Y:STA (scr),Y 116 | DEC cnt:BEQ e10:.f10 DEY:BPL a20 117 | LDA scr:SBC #&40:STA scr:DEC scr+1 118 | LDY #7:BCS a20:DEC scr+1:SEC:BCS a20 119 | .e10 DEC ls:BEQ d10:LDA err:SBC errs 120 | STA err:INC cnt:BCS f10 121 | .d10 RTS 122 | 123 | .a20 LDA err:LDX #&3F 124 | .b20 SBC #dy:BCS b30:ADC #dx:STA err 125 | TXA:AND #&E0:ORA(scr),Y:STA (scr),Y 126 | DEC cnt:BEQ e20:.f20 DEY:BPL a30 127 | LDA scr:SBC #&40:STA scr:DEC scr+1 128 | LDY #7:BCS a30:DEC scr+1:SEC:BCS a30 129 | .e20 DEC ls:BEQ d20:LDA err:SBC errs 130 | STA err:INC cnt:BCS f20 131 | .d20 RTS 132 | 133 | .a30 LDA err:LDX #&1F 134 | .b30 SBC #dy:BCS b40:ADC #dx:STA err 135 | TXA:AND #&F0:ORA(scr),Y:STA (scr),Y 136 | DEC cnt:BEQ e30:.f30 DEY:BPL a40 137 | LDA scr:SBC #&40:STA scr:DEC scr+1 138 | LDY #7:BCS a40:DEC scr+1:SEC:BCS a40 139 | .e30 DEC ls:BEQ d30:LDA err:SBC errs 140 | STA err:INC cnt:BCS f30 141 | .d30 RTS 142 | 143 | .a40 LDA err:LDX #&F 144 | .b40 SBC #dy:BCS b50:ADC #dx:STA err 145 | TXA:AND #&F8:ORA(scr),Y:STA (scr),Y 146 | DEC cnt:BEQ e40:.f40 DEY:BPL a50 147 | LDA scr:SBC #&40:STA scr:DEC scr+1 148 | LDY #7:BCS a50:DEC scr+1:SEC:BCS a50 149 | .e40 DEC ls:BEQ d40:LDA err:SBC errs 150 | STA err:INC cnt:BCS f40 151 | .d40 RTS 152 | 153 | .a50 LDA err:LDX #7 154 | .b50 SBC #dy:BCS b60:ADC #dx:STA err 155 | TXA:AND #&FC:ORA(scr),Y:STA (scr),Y 156 | DEC cnt:BEQ e50:.f50 DEY:BPL a60 157 | LDA scr:SBC #&40:STA scr:DEC scr+1 158 | LDY #7:BCS a60:DEC scr+1:SEC:BCS a60 159 | .e50 DEC ls:BEQ d50:LDA err:SBC errs 160 | STA err:INC cnt:BCS f50 161 | .d50 RTS 162 | 163 | .a60 LDA err:LDX #3 164 | .b60 SBC #dy:BCS b70:ADC #dx:STA err 165 | TXA:AND #&FE:ORA(scr),Y:STA (scr),Y 166 | DEC cnt:BEQ e60:.f60 DEY:BPL a70 167 | LDA scr:SBC #&40:STA scr:DEC scr+1 168 | LDY #7:BCS a70:DEC scr+1:SEC:BCS a70 169 | .e60 DEC ls:BEQ d60:LDA err:SBC errs 170 | STA err:INC cnt:BCS f60 171 | .d60 RTS 172 | 173 | .a70 LDA err:LDX #1 174 | .b70 SBC #dy:BCS by0:ADC #dx:STA err 175 | TXA:ORA(scr),Y:STA (scr),Y 176 | DEC cnt:BEQ e70:.f70 DEY:BPL ad0 177 | LDA scr:SBC #&38:LDY #7:STA scr 178 | LDA scr+1:SBC #1:STA scr+1:JMP a00 179 | .e70 DEC ls:BEQ d70:LDA err:SBC errs 180 | STA err:INC cnt:BCS f70 181 | .d70 RTS:.by0 STA err 182 | TXA:ORA(scr),Y:STA (scr),Y 183 | .ad0 LDA scr:ADC #7:STA scr:BCS ac0 184 | SEC:JMP a00 185 | .ac0 INC scr+1:JMP a00 186 | .a01 LDA err:LDX #&FF 187 | .b01 SBC #dy:BCS b11:ADC #dx:STA err 188 | LDA #1:ORA(scr),Y:STA (scr),Y 189 | DEC cnt:BEQ e01:.f01 DEY:BPL a11 190 | LDA scr:SBC #&40:STA scr:DEC scr+1 191 | LDY #7:BCS a11:DEC scr+1:SEC:BCS a11 192 | .e01 DEC ls:BEQ d01:LDA err:SBC errs 193 | STA err:INC cnt:BCS f01 194 | .d01 RTS 195 | 196 | .a11 LDA err:LDX #&FE 197 | .b11 SBC #dy:BCS b21:ADC #dx:STA err 198 | TXA:AND #3:ORA(scr),Y:STA (scr),Y 199 | DEC cnt:BEQ e11:.f11 DEY:BPL a21 200 | LDA scr:SBC #&40:STA scr:DEC scr+1 201 | LDY #7:BCS a21:DEC scr+1:SEC:BCS a21 202 | .e11 DEC ls:BEQ d11:LDA err:SBC errs 203 | STA err:INC cnt:BCS f11 204 | .d11 RTS 205 | 206 | .a21 LDA err:LDX #&FC 207 | .b21 SBC #dy:BCS b31:ADC #dx:STA err 208 | TXA:AND #7:ORA(scr),Y:STA (scr),Y 209 | DEC cnt:BEQ e21:.f21 DEY:BPL a31 210 | LDA scr:SBC #&40:STA scr:DEC scr+1 211 | LDY #7:BCS a31:DEC scr+1:SEC:BCS a31 212 | .e21 DEC ls:BEQ d21:LDA err:SBC errs 213 | STA err:INC cnt:BCS f21 214 | .d21 RTS 215 | 216 | .a31 LDA err:LDX #&F8 217 | .b31 SBC #dy:BCS b41:ADC #dx:STA err 218 | TXA:AND #&F:ORA(scr),Y:STA (scr),Y 219 | DEC cnt:BEQ e31:.f31 DEY:BPL a41 220 | LDA scr:SBC #&40:STA scr:DEC scr+1 221 | LDY #7:BCS a41:DEC scr+1:SEC:BCS a41 222 | .e31 DEC ls:BEQ d31:LDA err:SBC errs 223 | STA err:INC cnt:BCS f31 224 | .d31 RTS 225 | 226 | .a41 LDA err:LDX #&F0 227 | .b41 SBC #dy:BCS b51:ADC #dx:STA err 228 | TXA:AND #&1F:ORA(scr),Y:STA (scr),Y 229 | DEC cnt:BEQ e41:.f41 DEY:BPL a51 230 | LDA scr:SBC #&40:STA scr:DEC scr+1 231 | LDY #7:BCS a51:DEC scr+1:SEC:BCS a51 232 | .e41 DEC ls:BEQ d41:LDA err:SBC errs 233 | STA err:INC cnt:BCS f41 234 | .d41 RTS 235 | 236 | .a51 LDA err:LDX #&E0 237 | .b51 SBC #dy:BCS b61:ADC #dx:STA err 238 | TXA:AND #&3F:ORA(scr),Y:STA (scr),Y 239 | DEC cnt:BEQ e51:.f51 DEY:BPL a61 240 | LDA scr:SBC #&40:STA scr:DEC scr+1 241 | LDY #7:BCS a61:DEC scr+1:SEC:BCS a61 242 | .e51 DEC ls:BEQ d51:LDA err:SBC errs 243 | STA err:INC cnt:BCS f51 244 | .d51 RTS 245 | 246 | .a61 LDA err:LDX #&C0 247 | .b61 SBC #dy:BCS b71:ADC #dx:STA err 248 | TXA:AND #&7F:ORA(scr),Y:STA (scr),Y 249 | DEC cnt:BEQ e61:.f61 DEY:BPL a71 250 | LDA scr:SBC #&40:STA scr:DEC scr+1 251 | LDY #7:BCS a71:DEC scr+1:SEC:BCS a71 252 | .e61 DEC ls:BEQ d61:LDA err:SBC errs 253 | STA err:INC cnt:BCS f61 254 | .d61 RTS 255 | 256 | .a71 LDA err:LDX #&80 257 | .b71 SBC #dy:BCS by1:ADC #dx:STA err 258 | TXA:ORA(scr),Y:STA (scr),Y 259 | DEC cnt:BEQ e71:.f71 DEY:BPL sb1 260 | LDA scr:SBC #&48:LDY #7:STA scr 261 | LDA scr+1:SBC #1:STA scr+1:JMP a01 262 | .e71 DEC ls:BEQ d71:LDA err:SBC errs 263 | STA err:INC cnt:BCS f71 264 | .d71 RTS:.by1 STA err 265 | TXA:ORA(scr),Y:STA (scr),Y 266 | .sb1 LDA scr:SBC #8:STA scr:BCC sc1 267 | JMP a01 268 | .sc1 DEC scr+1:SEC:JMP a01 269 | .p02 LDA #&80:ORA(scr),Y:STA (scr),Y 270 | TXA:.a02 SBC #dx:BCC b02:TAX 271 | DEY:BPL p02 272 | .s02 LDY #7:DEC scr+1:LDA scr:SBC #&40 273 | STA scr:BCS p02:DEC scr+1:SEC:BCS p02 274 | .e02 DEC ls:BEQ d02:SBC errs 275 | INC cnt:BCS n02:.d02 RTS 276 | .b02 ADC #dy:DEC cnt:BEQ e02 277 | .n02 TAX:DEY:BMI s12 278 | .p12 LDA #&40:ORA(scr),Y:STA (scr),Y 279 | TXA:.a12 SBC #dx:BCC b12:TAX 280 | DEY:BPL p12 281 | .s12 LDY #7:DEC scr+1:LDA scr:SBC #&40 282 | STA scr:BCS p12:DEC scr+1:SEC:BCS p12 283 | .e12 DEC ls:BEQ d12:SBC errs 284 | INC cnt:BCS n12:.d12 RTS 285 | .b12 ADC #dy:DEC cnt:BEQ e12 286 | .n12 TAX:DEY:BMI s22 287 | .p22 LDA #&20:ORA(scr),Y:STA (scr),Y 288 | TXA:.a22 SBC #dx:BCC b22:TAX 289 | DEY:BPL p22 290 | .s22 LDY #7:DEC scr+1:LDA scr:SBC #&40 291 | STA scr:BCS p22:DEC scr+1:SEC:BCS p22 292 | .e22 DEC ls:BEQ d22:SBC errs 293 | INC cnt:BCS n22:.d22 RTS 294 | .b22 ADC #dy:DEC cnt:BEQ e22 295 | .n22 TAX:DEY:BMI s32 296 | .p32 LDA #&10:ORA(scr),Y:STA (scr),Y 297 | TXA:.a32 SBC #dx:BCC b32:TAX 298 | DEY:BPL p32 299 | .s32 LDY #7:DEC scr+1:LDA scr:SBC #&40 300 | STA scr:BCS p32:DEC scr+1:SEC:BCS p32 301 | .e32 DEC ls:BEQ d32:SBC errs 302 | INC cnt:BCS n32:.d32 RTS 303 | .b32 ADC #dy:DEC cnt:BEQ e32 304 | .n32 TAX:DEY:BMI s42 305 | .p42 LDA #8:ORA(scr),Y:STA (scr),Y 306 | TXA:.a42 SBC #dx:BCC b42:TAX 307 | DEY:BPL p42 308 | .s42 LDY #7:DEC scr+1:LDA scr:SBC #&40 309 | STA scr:BCS p42:DEC scr+1:SEC:BCS p42 310 | .e42 DEC ls:BEQ d42:SBC errs 311 | INC cnt:BCS n42:.d42 RTS 312 | .b42 ADC #dy:DEC cnt:BEQ e42 313 | .n42 TAX:DEY:BMI s52 314 | .p52 LDA #4:ORA(scr),Y:STA (scr),Y 315 | TXA:.a52 SBC #dx:BCC b52:TAX 316 | DEY:BPL p52 317 | .s52 LDY #7:DEC scr+1:LDA scr:SBC #&40 318 | STA scr:BCS p52:DEC scr+1:SEC:BCS p52 319 | .e52 DEC ls:BEQ d52:SBC errs 320 | INC cnt:BCS n52:.d52 RTS 321 | .b52 ADC #dy:DEC cnt:BEQ e52 322 | .n52 TAX:DEY:BMI s62 323 | .p62 LDA #2:ORA(scr),Y:STA (scr),Y 324 | TXA:.a62 SBC #dx:BCC b62:TAX 325 | DEY:BPL p62 326 | .s62 LDY #7:DEC scr+1:LDA scr:SBC #&40 327 | STA scr:BCS p62:DEC scr+1:SEC:BCS p62 328 | .e62 DEC ls:BEQ d62:SBC errs 329 | INC cnt:BCS n62:.d62 RTS 330 | .b62 ADC #dy:DEC cnt:BEQ e62 331 | .n62 TAX:DEY:BMI s72 332 | .p72 LDA #1:ORA(scr),Y:STA (scr),Y 333 | TXA:.a72 SBC #dx:BCC b72:TAX 334 | DEY:BPL p72 335 | .s72 LDY #7:DEC scr+1:LDA scr:SBC #&40 336 | STA scr:BCS p72:DEC scr+1:SEC:BCS p72 337 | .e72 DEC ls:BEQ d72:SBC errs 338 | INC cnt:BCS n72:.d72 RTS 339 | .b72 ADC #dy:DEC cnt:BEQ e72 340 | .n72 TAX:DEY:BMI s82 341 | LDA scr:ADC #7:STA scr:BCS ac2 342 | SEC:JMP p02:.ac2 INC scr+1:JMP p02 343 | .s82 LDY #7:LDA scr:SBC #&38:STA scr 344 | LDA scr+1:SBC #1:STA scr+1:JMP p02 345 | .p03 LDA #1:ORA(scr),Y:STA (scr),Y 346 | TXA:.a03 SBC #dx:BCC b03:TAX 347 | DEY:BPL p03 348 | .s03 LDY #7:DEC scr+1:LDA scr:SBC #&40 349 | STA scr:BCS p03:DEC scr+1:SEC:BCS p03 350 | .e03 DEC ls:BEQ d03:SBC errs 351 | INC cnt:BCS n03:.d03 RTS 352 | .b03 ADC #dy:DEC cnt:BEQ e03 353 | .n03 TAX:DEY:BMI s13 354 | .p13 LDA #2:ORA(scr),Y:STA (scr),Y 355 | TXA:.a13 SBC #dx:BCC b13:TAX 356 | DEY:BPL p13 357 | .s13 LDY #7:DEC scr+1:LDA scr:SBC #&40 358 | STA scr:BCS p13:DEC scr+1:SEC:BCS p13 359 | .e13 DEC ls:BEQ d13:SBC errs 360 | INC cnt:BCS n13:.d13 RTS 361 | .b13 ADC #dy:DEC cnt:BEQ e13 362 | .n13 TAX:DEY:BMI s23 363 | .p23 LDA #4:ORA(scr),Y:STA (scr),Y 364 | TXA:.a23 SBC #dx:BCC b23:TAX 365 | DEY:BPL p23 366 | .s23 LDY #7:DEC scr+1:LDA scr:SBC #&40 367 | STA scr:BCS p23:DEC scr+1:SEC:BCS p23 368 | .e23 DEC ls:BEQ d23:SBC errs 369 | INC cnt:BCS n23:.d23 RTS 370 | .b23 ADC #dy:DEC cnt:BEQ e23 371 | .n23 TAX:DEY:BMI s33 372 | .p33 LDA #8:ORA(scr),Y:STA (scr),Y 373 | TXA:.a33 SBC #dx:BCC b33:TAX 374 | DEY:BPL p33 375 | .s33 LDY #7:DEC scr+1:LDA scr:SBC #&40 376 | STA scr:BCS p33:DEC scr+1:SEC:BCS p33 377 | .e33 DEC ls:BEQ d33:SBC errs 378 | INC cnt:BCS n33:.d33 RTS 379 | .b33 ADC #dy:DEC cnt:BEQ e33 380 | .n33 TAX:DEY:BMI s43 381 | .p43 LDA #&10:ORA(scr),Y:STA (scr),Y 382 | TXA:.a43 SBC #dx:BCC b43:TAX 383 | DEY:BPL p43 384 | .s43 LDY #7:DEC scr+1:LDA scr:SBC #&40 385 | STA scr:BCS p43:DEC scr+1:SEC:BCS p43 386 | .e43 DEC ls:BEQ d43:SBC errs 387 | INC cnt:BCS n43:.d43 RTS 388 | .b43 ADC #dy:DEC cnt:BEQ e43 389 | .n43 TAX:DEY:BMI s53 390 | .p53 LDA #&20:ORA(scr),Y:STA (scr),Y 391 | TXA:.a53 SBC #dx:BCC b53:TAX 392 | DEY:BPL p53 393 | .s53 LDY #7:DEC scr+1:LDA scr:SBC #&40 394 | STA scr:BCS p53:DEC scr+1:SEC:BCS p53 395 | .e53 DEC ls:BEQ d53:SBC errs 396 | INC cnt:BCS n53:.d53 RTS 397 | .b53 ADC #dy:DEC cnt:BEQ e53 398 | .n53 TAX:DEY:BMI s63 399 | .p63 LDA #&40:ORA(scr),Y:STA (scr),Y 400 | TXA:.a63 SBC #dx:BCC b63:TAX 401 | DEY:BPL p63 402 | .s63 LDY #7:DEC scr+1:LDA scr:SBC #&40 403 | STA scr:BCS p63:DEC scr+1:SEC:BCS p63 404 | .e63 DEC ls:BEQ d63:SBC errs 405 | INC cnt:BCS n63:.d63 RTS 406 | .b63 ADC #dy:DEC cnt:BEQ e63 407 | .n63 TAX:DEY:BMI s73 408 | .p73 LDA #&80:ORA(scr),Y:STA (scr),Y 409 | TXA:.a73 SBC #dx:BCC b73:TAX 410 | DEY:BPL p73 411 | .s73 LDY #7:DEC scr+1:LDA scr:SBC #&40 412 | STA scr:BCS p73:DEC scr+1:SEC:BCS p73 413 | .e73 DEC ls:BEQ d73:SBC errs 414 | INC cnt:BCS n73:.d73 RTS 415 | .b73 ADC #dy:DEC cnt:BEQ e73 416 | .n73 TAX:DEY:BMI s83 417 | LDA scr:SBC #8:STA scr:BCC ac3 418 | JMP p03:.ac3 DEC scr+1:SEC:JMP p03 419 | .s83 LDY #7:LDA scr:SBC #&48:STA scr 420 | LDA scr+1:SBC #1:STA scr+1 421 | JMP p03 422 | 423 | 424 | .strt0 425 | EQUB a00 AND &FF:EQUB a10 AND &FF 426 | EQUB a20 AND &FF:EQUB a30 AND &FF 427 | EQUB a40 AND &FF:EQUB a50 AND &FF 428 | EQUB a60 AND &FF:EQUB a70 AND &FF 429 | EQUB a00 DIV 256:EQUB a10 DIV 256 430 | EQUB a20 DIV 256:EQUB a30 DIV 256 431 | EQUB a40 DIV 256:EQUB a50 DIV 256 432 | EQUB a60 DIV 256:EQUB a70 DIV 256 433 | .strt1 434 | EQUB a71 AND &FF:EQUB a61 AND &FF 435 | EQUB a51 AND &FF:EQUB a41 AND &FF 436 | EQUB a31 AND &FF:EQUB a21 AND &FF 437 | EQUB a11 AND &FF:EQUB a01 AND &FF 438 | EQUB a71 DIV 256:EQUB a61 DIV 256 439 | EQUB a51 DIV 256:EQUB a41 DIV 256 440 | EQUB a31 DIV 256:EQUB a21 DIV 256 441 | EQUB a11 DIV 256:EQUB a01 DIV 256 442 | .strt2 443 | EQUB p02 AND &FF:EQUB p12 AND &FF 444 | EQUB p22 AND &FF:EQUB p32 AND &FF 445 | EQUB p42 AND &FF:EQUB p52 AND &FF 446 | EQUB p62 AND &FF:EQUB p72 AND &FF 447 | EQUB p02 DIV 256:EQUB p12 DIV 256 448 | EQUB p22 DIV 256:EQUB p32 DIV 256 449 | EQUB p42 DIV 256:EQUB p52 DIV 256 450 | EQUB p62 DIV 256:EQUB p72 DIV 256 451 | .strt3 452 | EQUB p73 AND &FF:EQUB p63 AND &FF 453 | EQUB p53 AND &FF:EQUB p43 AND &FF 454 | EQUB p33 AND &FF:EQUB p23 AND &FF 455 | EQUB p13 AND &FF:EQUB p03 AND &FF 456 | EQUB p73 DIV 256:EQUB p63 DIV 256 457 | EQUB p53 DIV 256:EQUB p43 DIV 256 458 | EQUB p33 DIV 256:EQUB p23 DIV 256 459 | EQUB p13 DIV 256:EQUB p03 DIV 256 460 | } 461 | -------------------------------------------------------------------------------- /source/maths.asm: -------------------------------------------------------------------------------- 1 | ALIGN 256 2 | 3 | 4 | ;---------------------------------------------------------------------------------------------------------- 5 | ; screen space 3D perspective projection table 6 | ;---------------------------------------------------------------------------------------------------------- 7 | ; 256 x 8-bit entries. Uses unsigned Z as a table index. 8 | ; [page aligned] 9 | .perspective 10 | d=&100 11 | oz=&80 12 | FOR Z%, -128, 127 13 | EQUB &FF*d/(d+oz+Z%)+.5 14 | NEXT 15 | 16 | ;---------------------------------------------------------------------------------------------------------- 17 | ; transformed vertex buffers (max 64 verts per model) 18 | ;---------------------------------------------------------------------------------------------------------- 19 | 20 | ; array of bytes to indicate if vertex N has already been transformed in the current render frame 21 | ; 0=untransformed, 255=transformed 22 | .ptsdone SKIP &40 23 | 24 | ;---------------------------------------------------------------------------------------------------------- 25 | ; screen space vertex coordinates, max 64 verts per model 26 | ;---------------------------------------------------------------------------------------------------------- 27 | ; calculated by 'transform' routine 28 | .sx SKIP &40 29 | .sy SKIP &40 30 | 31 | ;---------------------------------------------------------------------------------------------------------- 32 | ; sin/cos lookup table 33 | ;---------------------------------------------------------------------------------------------------------- 34 | ; provides 256 degrees of range for angles 35 | 36 | ; data format: 37 | ; 16-bit (approximately 1 bit sign, 3 bits integer, 12 bits fraction [1:3:12]) entries 38 | ; 39 | ; cos table is offset from sin table by 64 bytes (90 degrees) 40 | ; 41 | ; stored as: 42 | ; 256+64 bytes lsb 43 | ; followed by: 44 | ; 256+64 bytes msb 45 | ; 46 | ; could potentially be optimized using page alignment, 47 | ; but since it is really only used to create rotation matrix once per frame, and would need more memory, 48 | ; probably not worth it. 49 | 50 | .trigtable_start 51 | .slsb 52 | smsb=slsb+&140 53 | ; cos table offsets 54 | clsb=slsb+&40 55 | cmsb=clsb+&140 56 | 57 | 58 | ; sin table values are stored as 16-bit values 59 | ; they are multiplied by &1fa0 = 8096 or (&fd << 5) or (253 << 5) or (% 0001 1111 1010 0000) 60 | ; which gives fixed point precision as well as overall scale 61 | ; 62 | ; Original author (Nick) notes: 63 | ; The &1FA0 is a bit arbitrary. 64 | ; Note that the way the program uses the sine table to build the rotation matrix 65 | ; (no multiplications there, it's all done with compound angle formulae) 66 | ; it doesn't matter what this number is - it just results in a scaling of the whole object. 67 | ; I knew it had to be a bit less than &2000 but obviously couldn't be bothered to work out 68 | ; exactly how big it could be. Changing it to &1FE0 seems to be fine but &1FF0 is too big. 69 | 70 | SINCOS_SCALE = 253 << 5 ; = &1fa0, but can be 255 << 5 (&1fe0) as a maximum, given current range of input coordinates 71 | ; SM: could be calculated as the largest number that can support full range of 8-bit vertex coordinates without overflow 72 | 73 | FOR A%, 0, &13F 74 | S% = SINCOS_SCALE * SIN( A%*2*PI /256 )+.5 75 | EQUB LO(S%) 76 | NEXT 77 | FOR A%, 0, &13F 78 | S% = SINCOS_SCALE * SIN( A%*2*PI /256 )+.5 79 | EQUB HI(S%) 80 | NEXT 81 | .trigtable_end 82 | 83 | 84 | ;---------------------------------------------------------------------------------------------------------- 85 | ; clear/reset the transformed vertex buffer array 86 | ;---------------------------------------------------------------------------------------------------------- 87 | ; called once per frame 88 | ; ptsdone contains 0 if vertex has not yet been transformed 89 | ; or 255 if vertex has been transformed 90 | ;---------------------------------------------------------------------------------------------------------- 91 | .newpoints 92 | { 93 | LDA#0:LDX npts 94 | .loop4 95 | STA ptsdone,X 96 | DEX:BPL loop4 97 | RTS 98 | } 99 | 100 | 101 | ;---------------------------------------------------------------------------------------------------------- 102 | ; fetch a 2D screen space transformed vertex coordinate 103 | ;---------------------------------------------------------------------------------------------------------- 104 | ; input - X=vertex id to fetch 105 | ; output - A is screen space X coord, Y is screen space Y coord 106 | ; X is preserved 107 | ; (transformed vertices are cached) 108 | ;---------------------------------------------------------------------------------------------------------- 109 | .getcoordinates 110 | { 111 | LDA ptsdone,X:BPL transform 112 | LDA sx,X 113 | LDY sy,X 114 | RTS 115 | } 116 | 117 | 118 | ;---------------------------------------------------------------------------------------------------------- 119 | ; update model rotation angles 120 | ;---------------------------------------------------------------------------------------------------------- 121 | .rotate 122 | { 123 | INC rx 124 | INC ry:INC ry 125 | INC rz:INC rz:INC rz 126 | RTS 127 | } 128 | 129 | ;---------------------------------------------------------------------------------------------------------- 130 | ; table of addresses pointing to each address in the transform routine 131 | ; that uses a coefficent of the 3x3 rotation matrix 132 | ;---------------------------------------------------------------------------------------------------------- 133 | ; the 'matrix' routine uses this address table to load the computed 134 | ; rotation matrix coefficients directly into the transform routine 135 | ; for speed. (since transform is called multiple times per frame) 136 | ;---------------------------------------------------------------------------------------------------------- 137 | .unitvectors 138 | ; offset 0 = lsb of each address 139 | EQUB u00 AND &FF:EQUB u01 AND &FF:EQUB u02 AND &FF 140 | EQUB u10 AND &FF:EQUB u11 AND &FF:EQUB u12 AND &FF 141 | EQUB u20 AND &FF:EQUB u21 AND &FF:EQUB u22 AND &FF 142 | ; offset 9 = msb of each address 143 | EQUB u00 DIV 256:EQUB u01 DIV 256:EQUB u02 DIV 256 144 | EQUB u10 DIV 256:EQUB u11 DIV 256:EQUB u12 DIV 256 145 | EQUB u20 DIV 256:EQUB u21 DIV 256:EQUB u22 DIV 256 146 | 147 | 148 | 149 | ;---------------------------------------------------------------------------------------------------------- 150 | ; Apply 3D -> 2D perspective projection transform to given vertex id 151 | ;---------------------------------------------------------------------------------------------------------- 152 | ; inputs - 153 | ; X is vertex index N (0-npts) 154 | ; .x, .y, .z addresses preloaded with vertex buffer address for current model 155 | ; .u00...u22 addresses preloaded with rotation matrix coefficients by 'matrix' routine 156 | ; output - 157 | ; A, sx[N] = screen X coord 158 | ; Y, sy[N] = screen Y coord 159 | ; ptsdone[N] = 255 160 | ;---------------------------------------------------------------------------------------------------------- 161 | ; uses table lookups for all multiplies for speed 162 | 163 | ; prior to calling this routine, the following address setup modifications have been completed: 164 | ; 1 - the X/Y/Z vertex buffer address for the currently selected model has been applied to .x, .y, .z 165 | ; 2 - the unit vectors for the current rotation matrix has been applied to u00 ... u22 by the matrix routine 166 | 167 | ; Matrix * Vector 168 | ; V' = M * V 169 | ; 170 | ; x' = x*a + y*b + z*c 171 | ; y' = x*d + y*e + z*f 172 | ; z' = x*g + y*h + z*i 173 | ; 174 | ; 9 multiplies, 6 adds 175 | 176 | ; where M = [ a b c ] 177 | ; [ d e f ] 178 | ; [ g h i ] 179 | ; and V = [ x y z ] 180 | ;---------------------------------------------------------------------------------------------------------- 181 | 182 | .transform 183 | 184 | ; mark this vertex as transformed, so that it will be cached if re-used 185 | LDA#&FF:STA ptsdone,X 186 | 187 | ; fetch & transform vertex X coord 188 | ; (vertex buffer address set by load_next_model) 189 | .x LDY &8000,X 190 | 191 | ; x' = x*a 192 | SEC:.u00 193 | LDA SQUARETABLE2_LSB,Y:SBC SQUARETABLE2_LSB,Y:STA xr 194 | LDA SQUARETABLE2_MSB,Y:SBC SQUARETABLE2_MSB,Y:STA xr+1 195 | 196 | ; y' = x*b 197 | SEC:.u10 198 | LDA SQUARETABLE2_LSB,Y:SBC SQUARETABLE2_LSB,Y:STA yr 199 | LDA SQUARETABLE2_MSB,Y:SBC SQUARETABLE2_MSB,Y:STA yr+1 200 | 201 | ; z' = x*c 202 | SEC:.u20 203 | LDA SQUARETABLE2_LSB,Y:SBC SQUARETABLE2_LSB,Y:STA zr 204 | LDA SQUARETABLE2_MSB,Y:SBC SQUARETABLE2_MSB,Y:STA zr+1 205 | 206 | ; fetch & transform vertex Y coord 207 | ; (vertex buffer address set by load_next_model) 208 | .y LDY &8000,X 209 | 210 | ; x' += y*d 211 | SEC:.u01 212 | LDA SQUARETABLE2_LSB,Y:SBC SQUARETABLE2_LSB,Y:STA product 213 | LDA SQUARETABLE2_MSB,Y:SBC SQUARETABLE2_MSB,Y:STA product+1 214 | LDA product:CLC:ADC xr:STA xr 215 | LDA product+1:ADC xr+1:STA xr+1 216 | 217 | ; y' += y*e 218 | SEC:.u11 219 | LDA SQUARETABLE2_LSB,Y:SBC SQUARETABLE2_LSB,Y:STA product 220 | LDA SQUARETABLE2_MSB,Y:SBC SQUARETABLE2_MSB,Y:STA product+1 221 | LDA product:CLC:ADC yr:STA yr 222 | LDA product+1:ADC yr+1:STA yr+1 223 | 224 | ; z' += y*f 225 | SEC:.u21 226 | LDA SQUARETABLE2_LSB,Y:SBC SQUARETABLE2_LSB,Y:STA product 227 | LDA SQUARETABLE2_MSB,Y:SBC SQUARETABLE2_MSB,Y:STA product+1 228 | LDA product:CLC:ADC zr:STA zr 229 | LDA product+1:ADC zr+1:STA zr+1 230 | 231 | ; fetch & transform vertex Z coord 232 | ; (vertex buffer address set by load_next_model) 233 | .z LDY &8000,X 234 | 235 | ; x' += z*g 236 | SEC:.u02 237 | LDA SQUARETABLE2_LSB,Y:SBC SQUARETABLE2_LSB,Y:STA product 238 | LDA SQUARETABLE2_MSB,Y:SBC SQUARETABLE2_MSB,Y:STA product+1 239 | LDA product:CLC:ADC xr:STA xr 240 | LDA product+1:ADC xr+1:STA xr+1 241 | 242 | ; y' += z*h 243 | SEC:.u12 244 | LDA SQUARETABLE2_LSB,Y:SBC SQUARETABLE2_LSB,Y:STA product 245 | LDA SQUARETABLE2_MSB,Y:SBC SQUARETABLE2_MSB,Y:STA product+1 246 | LDA product:CLC:ADC yr:STA yr 247 | LDA product+1:ADC yr+1:STA yr+1 248 | 249 | ; z' += z*i 250 | SEC:.u22 251 | LDA SQUARETABLE2_LSB,Y:SBC SQUARETABLE2_LSB,Y:STA product 252 | LDA SQUARETABLE2_MSB,Y:SBC SQUARETABLE2_MSB,Y:STA product+1 253 | LDA product:CLC:ADC zr:STA zr 254 | LDA product+1:ADC zr+1 255 | 256 | ; xr, yr, zr now contain the rotated vertex coordinate 257 | ; A contains the msb of the z coordinate 258 | 259 | ; now calculate screen space coordinates using perspective projection 260 | 261 | 262 | ASL zr:ROL A:ASL zr 263 | ADC#&80:TAY 264 | 265 | CLC 266 | LDA#&80:ADC perspective,Y:STA adr:STA adr+2 267 | 268 | IF CONTIGUOUS_TABLES 269 | ; This routine assumes the square tables are contiguous in memory 270 | LDA#HI(SQUARETABLE2_LSB):ADC#0:STA adr+1 271 | ADC#3:STA adr+3 ; SQUARETABLE2_MSB 272 | CLC 273 | LDA adr:ADC#1:STA adr+4:STA adr+6 274 | CLC 275 | LDA adr+1:ADC#0:STA adr+5 276 | ADC#3:STA adr+7 ; SQUARETABLE2_MSB 277 | ELSE 278 | LDA #0:ADC#0:STA adr+1:STA adr+3 279 | LDA adr:ADC#1:STA adr+4:STA adr+6 280 | LDA adr+1:ADC#0:STA adr+5:STA adr+7 281 | 282 | LDA#HI(SQUARETABLE2_LSB):CLC:ADC adr+1:STA adr+1 283 | LDA#HI(SQUARETABLE2_MSB):CLC:ADC adr+3:STA adr+3 284 | LDA#HI(SQUARETABLE2_LSB):CLC:ADC adr+5:STA adr+5 285 | LDA#HI(SQUARETABLE2_MSB):CLC:ADC adr+7:STA adr+7 286 | ENDIF 287 | 288 | 289 | ; compute screen space Y coord 290 | LDA yr+1:ASL yr:ROL A:ASL yr 291 | ADC#&80:TAY:SEC:EOR #&FF:STY zr:STA zr+1 292 | LDA(adr),Y:LDY zr+1:SBC(adr+4),Y:STA yr 293 | LDY zr:LDA(adr+2),Y:LDY zr+1:SBC(adr+6),Y 294 | ASL yr:ADC#&80:STA sy,X 295 | 296 | ; compute screen space X coord 297 | LDA xr+1:ASL xr:ROL A:ASL xr 298 | ADC#&80:TAY:SEC:EOR #&FF:STY zr:STA zr+1 299 | LDA(adr),Y:LDY zr+1:SBC(adr+4),Y:STA xr 300 | LDY zr:LDA(adr+2),Y:LDY zr+1:SBC(adr+6),Y 301 | ASL xr:ADC#&80:STA sx,X 302 | 303 | LDY sy,X 304 | ; A contains screen space X coord 305 | ; Y contains screen space Y coord 306 | RTS 307 | 308 | ;---------------------------------------------------------------------------------------------------------- 309 | ; construct a standard 3D XYZ rotation matrix 310 | ;---------------------------------------------------------------------------------------------------------- 311 | ; inputs - rx,ry,rz contain rotation angles (8 bit precision) 312 | ; outputs - m00 ... m22 contain the rotation matrix (16-bits precision) 313 | ; - this routine also updates the transform routine directly with the 314 | ; computed matrix coefficients, which is a useful optimization 315 | ; since transform is called multiple times when transforming the model vertices 316 | ;---------------------------------------------------------------------------------------------------------- 317 | 318 | .matrix 319 | { 320 | ; rx, ry, rz are the input X/Y/Z unsigned 8-bit rotation angles, 0-255 321 | 322 | ; m12 = -sin(rx) 323 | LDY rx 324 | SEC 325 | LDA#0:SBC slsb,Y:STA m12lsb 326 | LDA#0:SBC smsb,Y:ASL m12lsb 327 | ROL A:ASL m12lsb:ROL A:STA m12msb 328 | 329 | ; X = rx-ry 330 | ; adr[3] = rx-ry+rz 331 | TYA:SEC:SBC ry:TAX 332 | CLC:ADC rz:STA adr+3 333 | ; Y = rx+ry 334 | ; adr[2] = rx+ry+rz 335 | TYA:CLC:ADC ry:TAY 336 | CLC:ADC rz:STA adr+2 337 | 338 | ; m02 = sin(rx-ry)-sin(rx+ry) 339 | SEC 340 | LDA slsb,X:SBC slsb,Y:STA m02lsb 341 | LDA smsb,X:SBC smsb,Y:ASL m02lsb 342 | ROL A:STA m02msb 343 | 344 | ; m22 = cos(rx+ry)-cos(rx-ry) 345 | CLC 346 | LDA clsb,Y:ADC clsb,X:STA m22lsb 347 | LDA cmsb,Y:ADC cmsb,X:ASL m22lsb 348 | ROL A:STA m22msb 349 | 350 | ; m10 351 | ; adr[4] = rx+ry-rz 352 | ; adr[5] = rx-ry-rz 353 | TYA:SEC:SBC rz:STA adr+4 354 | TXA:SEC:SBC rz:STA adr+5 355 | LDA rx:CLC:ADC rz:TAY 356 | LDA rx:SEC:SBC rz:TAX 357 | 358 | SEC 359 | LDA slsb,Y:SBC slsb,X:STA m10lsb 360 | LDA smsb,Y:SBC smsb,X:ASL m10lsb 361 | ROL A:STA m10msb 362 | 363 | ; m11 364 | CLC 365 | LDA clsb,X:ADC clsb,Y:STA m11lsb 366 | LDA cmsb,Y:ADC cmsb,X:ASL m11lsb 367 | ROL A:STA m11msb 368 | 369 | ; m21 370 | LDA ry:SEC:SBC rz:TAY 371 | LDA rz:CLC:ADC ry:TAX:SEC 372 | LDA clsb,X:SBC clsb,Y:STA m21lsb 373 | LDA cmsb,X:SBC cmsb,Y:ASL m21lsb 374 | ROL A:STA m21msb 375 | 376 | ; m01 377 | SEC 378 | LDA slsb,Y:SBC slsb,X:STA m01lsb 379 | LDA smsb,Y:SBC smsb,X:ASL m01lsb 380 | ROL A:STA m01msb 381 | 382 | ; m00 383 | CLC 384 | LDA clsb,Y:ADC clsb,X:STA m00lsb 385 | LDA cmsb,X:ADC cmsb,Y:ASL m00lsb 386 | ROL A:STA m00msb 387 | 388 | ; m20 389 | CLC 390 | LDA slsb,X:ADC slsb,Y:STA m20lsb 391 | LDA smsb,Y:ADC smsb,X:ASL m20lsb 392 | ROL A:STA m20msb 393 | 394 | ; Y= 395 | LDY adr+4:LDX adr+3 396 | 397 | SEC 398 | LDA m00lsb:SBC slsb,X:STA m00lsb 399 | LDA m00msb:SBC smsb,X:STA m00msb 400 | 401 | CLC 402 | LDA slsb,Y:ADC m21lsb:STA m21lsb 403 | LDA m21msb:ADC smsb,Y:STA m21msb 404 | 405 | CLC 406 | LDA clsb,Y:ADC m20lsb:STA m20lsb 407 | LDA cmsb,Y:ADC m20msb:STA m20msb 408 | 409 | SEC 410 | LDA m01lsb:SBC clsb,X:STA m01lsb 411 | LDA m01msb:SBC cmsb,X:STA m01msb 412 | 413 | CLC 414 | LDA clsb,Y:ADC m01lsb:STA m01lsb 415 | LDA cmsb,Y:ADC m01msb:STA m01msb 416 | 417 | CLC 418 | LDA m21lsb:ADC slsb,X:STA m21lsb 419 | LDA m21msb:ADC smsb,X:STA m21msb 420 | 421 | SEC 422 | LDA m20lsb:SBC clsb,X:STA m20lsb 423 | LDA m20msb:SBC cmsb,X:STA m20msb 424 | 425 | SEC 426 | LDA m00lsb:SBC slsb,Y:STA m00lsb 427 | LDA m00msb:SBC smsb,Y:STA m00msb 428 | 429 | LDX adr+5:LDY adr+2 430 | 431 | SEC 432 | LDA m20lsb:SBC clsb,Y:STA m20lsb 433 | LDA m20msb:SBC cmsb,Y:STA m20msb 434 | 435 | CLC 436 | LDA m00lsb:ADC slsb,X:STA m00lsb 437 | LDA m00msb:ADC smsb,X:STA m00msb 438 | 439 | CLC 440 | LDA m21lsb:ADC slsb,X:STA m21lsb 441 | LDA m21msb:ADC smsb,X:STA m21msb 442 | 443 | CLC 444 | LDA clsb,Y:ADC m01lsb:STA m01lsb 445 | LDA cmsb,Y:ADC m01msb:STA m01msb 446 | 447 | CLC 448 | LDA slsb,Y:ADC m21lsb:STA m21lsb 449 | LDA smsb,Y:ADC m21msb:STA m21msb 450 | 451 | CLC 452 | LDA slsb,Y:ADC m00lsb:STA m00lsb 453 | LDA smsb,Y:ADC m00msb:STA m00msb 454 | 455 | CLC 456 | LDA clsb,X:ADC m20lsb:STA m20lsb 457 | LDA cmsb,X:ADC m20msb:STA m20msb 458 | 459 | SEC 460 | LDA m01lsb:SBC clsb,X:STA m01lsb 461 | LDA m01msb:SBC cmsb,X:STA m01msb 462 | 463 | ; m00 ... m22 lsb & msb 464 | ; now contain the 3x3 rotation matrix elements 465 | 466 | ; next, 467 | ; for each element of the 3x3 matrix; 468 | ; transfer the rotation matrix coefficients directly 469 | ; into each related part of the (vector * matrix) vertex transform routine 470 | 471 | LDX#8 472 | .loop7 473 | ; fetch the transform routine coefficient address for the current element of the matrix 474 | ; [ u00, u01, u02 ] 475 | ; [ u10, u11, u12 ] 476 | ; [ u20, u21, u22 ] 477 | 478 | LDA unitvectors,X:STA adr ; lsb 479 | LDA unitvectors+9,X:STA adr+1 ; msb 480 | 481 | ; get the high byte of the coefficent 482 | ; complement with high bit of low byte and convert from signed to unsigned (for lookup table access) 483 | LDA m00msb,X:ASL m00lsb,X:ADC#&80 484 | 485 | ; store sin table offset lsb's for this coefficient directly into the transform routine 486 | 487 | ; (+1 is lsb after LDA instruction) 488 | ; (+9 is lsb after SBC instruction) 489 | LDY#1:STA(adr),Y:LDY#9:STA(adr),Y 490 | 491 | ; A = -A (two's complement negate) 492 | CLC:EOR #&FF:ADC#1 493 | 494 | ; (+4 is lsb after second LDA instruction) 495 | ; (+12 is lsb after second SBC instruction) 496 | LDY#4:STA(adr),Y:LDY#&C:STA(adr),Y 497 | 498 | DEX:BPL loop7 499 | RTS 500 | } -------------------------------------------------------------------------------- /source/culling.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ;---------------------------------------------------------------------------------------------------------- 4 | ; perform hidden surface removal for the current model 5 | ;---------------------------------------------------------------------------------------------------------- 6 | ; inputs - 7 | ; prior to calling this routine, load_next_model has set the opposites lookups to point to the current model's 8 | ; opposites array 9 | ; oldsurfs, contains copy of previous visible surfs bit array (or &ffff on first render of this model) 10 | ; 11 | ; outputs - 12 | ; surfs contains 16 bit array of visible surfaces [where (bit == 1) ? hidden : visible] 13 | ; oldsurfs = surfs 14 | ; 15 | ;---------------------------------------------------------------------------------------------------------- 16 | ; Back face culling can be CPU expensive, due to the need for cross product multiplications for visibility determination 17 | ; This routine uses four clever optimization techniques, that take advantage of the following observations: 18 | ; 1 - 3D models that are backface culled have a finite number of surfaces (maxvis) that can ever be visible at once 19 | ; 2 - visible surfaces tend to be consistently visible over multiple render frames 20 | ; 3 - 3D models tend to contain surfaces that are in direct opposition 21 | ; 4 - cross product implemented using a factored equation and table lookup based multiplication 22 | ; 23 | ; For 1, the routine has an early out once the maxvis surface visibility counter is reached, eliminating redundant visibility checks 24 | ; For 2, the routine first rechecks only surfaces that were previously visible on the last render frame 25 | ; which increases probability of early-out with the minimum number (maxvis) of visibility calcs 26 | ; For 3, when calculating a surfaces visibility, the routine eliminates any opposite surfaces from 27 | ; further visibility calcs, which further reduces the number of overall visibility calculations that are required. 28 | ;---------------------------------------------------------------------------------------------------------- 29 | .hiddensurfaceremoval 30 | 31 | ; set number of visible surfaces to zero 32 | LDA#0:STA visible 33 | 34 | ; oldsurfs = 16 bit array, where set bits mean surface is hidden, clear bits mean surface is visible 35 | ; surfs = 16 bit array, where set bits mean surface is hidden, clear bits mean surface is visible 36 | ; surfsdone = 16 bit array, where set bits mean surface has been processed this frame 37 | 38 | ; store inverted version of oldsurfs in surfsdone 39 | ; surfsdone = oldsurfs EOR &ffff 40 | ; this effectively means any previously visible surfaces are pre-marked as done 41 | ; as far as the second phase of surface visibility testing goes. 42 | ; we can then deal with these specific cases in just the first phase. 43 | LDA oldsurfs:EOR #&FF:STA surfsdone 44 | LDA oldsurfs+1:EOR #&FF:STA surfsdone+1 45 | 46 | ; setup loop - bring the relevant bits of oldsurfs to the top of oldsurfs 47 | 48 | ; a=15-nsurfs 49 | ; if nsurfs == 15, skip the unused bits shift 50 | LDA#&F:SEC:SBC nsurfs:BEQ nloop 51 | 52 | ; discard unused bits in the oldsurfs bit array by shifting them out 53 | ; n = 15-nsurfs 54 | ; for y=n; y>0; y--) 55 | ; oldsurfs <<= 1 56 | TAY 57 | LDA oldsurfs 58 | .loop8 59 | ASL A:ROL oldsurfs+1:DEY:BNE loop8 60 | STA oldsurfs 61 | ; now, the topmost bits in oldsurfs contains only the relevant bits we want to look at 62 | 63 | .nloop 64 | 65 | ; first phase - re-check visibility of previously visible surfaces 66 | ; 67 | ; 1. loop through all surfaces, and check visibility only of those that were previously visible. 68 | ; 2. any that still remain visible have their opposite surface (if any) marked as hidden/done 69 | ; 3. maintain a counter of surfaces we know are visible in this render frame 70 | ; 71 | ; for Y=nsurfs, y>=0, --y 72 | LDY nsurfs 73 | 74 | .loop9 75 | ; grab the next visibility bit from the top of oldsurfs 76 | ; oldsurfs << 1, top bit into carry 77 | ASL oldsurfs:ROL oldsurfs+1 78 | 79 | ; check if this surface was previously hidden 80 | ; if C is set, this surface was previously hidden so, 81 | ; skip first phase visibility test, as we're only interested in visible surfaces for this phase 82 | BCS hidesurface 83 | ; else 84 | ; test visibility of surface Y, to see if it is still visible 85 | JSR clockwisetest:BCS hidesurface 86 | 87 | ; yep, surface Y is still visible, so mark it's opposite as 'done' (ie. deduced to be not visible) 88 | 89 | ; fetch the 16-bit opposite data array for this surface 90 | ; and mark the opposite surface id as processed 91 | 92 | ; x=y*2 (word indexing for opposites array) 93 | TYA:ASL A:TAX 94 | ; surfsdone |= opposites[y] 95 | .opposite0 LDA &8000,X:INX 96 | ORA surfsdone:STA surfsdone 97 | .opposite1 LDA &8000,X 98 | ORA surfsdone+1:STA surfsdone+1 99 | 100 | ; ++visible 101 | INC visible 102 | 103 | ; carry bit is clear (visible surface) 104 | 105 | .hidesurface 106 | ; if we reached here because a previously visible surface is now hidden, the carry bit will be set 107 | 108 | ; update surfs bit array 109 | ; surfs = (surfs << 1) | (carryset ? 1 : 0) 110 | ROL surfs:ROL surfs+1 111 | DEY:BPL loop9 112 | 113 | ; now we have the bottom nsurf bits of surfs representing correct visibility status for any previously visible surfaces 114 | ; however any previously hidden surfaces may not have correct representation in the surfs bit array at this stage. 115 | ; if visible == maxvis however, that wont matter because we've already determined all possible visible surfaces 116 | ; and we'll early out of the routine, however if visible != maxvis, we'll correct these bits in the next phase. 117 | 118 | ; SM: Possible bug here? - since we're not marking the phase 1 visible surfaces as done, 119 | ; if visible != maxvis, wont we end up potentially re-calculating the same visible surfaces? 120 | 121 | 122 | 123 | 124 | ; ------------------------------------------------- 125 | ; second phase, loop again through each surface in the model 126 | ; if not 'done', check visibility, update surfs bit array and mark it (and it's opposite) as done 127 | ; importantly, we early exit once we've counted 'maxvis' visible surfaces 128 | ; - thanks to the first phase loop, there's much higher probability of this early exit happening quickly 129 | 130 | ; for y=nsurfs; y>=0; --y 131 | LDY nsurfs 132 | ; currentsurfacebit = bits[y] 133 | ; (oldsurfs gets reused as a temp var in this section) 134 | LDA bits,Y:STA oldsurfs 135 | LDA bits+16,Y:STA oldsurfs+1 136 | 137 | .loopA 138 | ; early out optimization 139 | ; if (visible == maxvis) for this model 140 | ; - early exit as there's no need to process any more surfaces since we've hit maxvis limit 141 | LDX visible:CPX maxvis:BEQ doneit 142 | 143 | ; check if current surface has already been 'done', and skip the clockwise test if so 144 | ; if (surfsdone & currentsurfacebit) 145 | ; continue; 146 | LDA surfsdone:AND oldsurfs:BNE surfdone 147 | LDA surfsdone+1:AND oldsurfs+1:BNE surfdone 148 | 149 | ; otherwise check if surface is visible 150 | JSR clockwisetest:BCS surfdone 151 | 152 | ; surface is indeed visible, 153 | ; so clear the bit for this surface in surfs bit array by masking surfs with inverse currentsurfacebit 154 | ; 155 | ; surfs = (currentsurfacebit EOR &FFFF) & surfs 156 | LDA oldsurfs:EOR #&FF:AND surfs:STA surfs 157 | LDA oldsurfs+1:EOR #&FF:AND surfs+1:STA surfs+1 158 | 159 | ; X=y*2 for word addressing 160 | ; mark the surface opposite this one as done 161 | ; surfsdone |= opposite[y] 162 | TYA:ASL A:TAX 163 | .opposite2 LDA &8000,X:INX 164 | ORA surfsdone:STA surfsdone 165 | .opposite3 LDA &8000,X 166 | ORA surfsdone+1:STA surfsdone+1 167 | 168 | ; visible++ 169 | INC visible 170 | 171 | .surfdone 172 | 173 | ; currentsurfacebit >>= 1 174 | LSR oldsurfs+1:ROR oldsurfs 175 | 176 | ; continue 177 | DEY:BPL loopA 178 | 179 | ; 180 | .doneit 181 | ; surfs now contains 16-bit array, where bit clear for visible surface, bit set for hidden surface 182 | ; oldsurfs = surfs 183 | ; return surfs[] - 16 bit array, where any bit set indicates a hidden surface 184 | LDA surfs:STA oldsurfs 185 | LDA surfs+1:STA oldsurfs+1 186 | RTS 187 | 188 | ;---------------------------------------------------------------------------------------------------------- 189 | ; perform a clockwise orientation test for a given surface 190 | ;---------------------------------------------------------------------------------------------------------- 191 | ; 192 | ; on entry, Y is the index of the surface being tested 193 | ; 194 | ; on exit, carry is set if surface is in anti-clockwise presentation (ie. hidden) 195 | ; Y is preserved 196 | ; 197 | ; prior to calling this routine, load_next_model has stored the 198 | ; pointers to the surface data for the model into clock0/1/2 199 | ; 200 | ; surfaces are represented as 3 points representing a triangle, presented in CW winding order 201 | ; culling is determined by detecting CCW presentation of the surface vertices in screen space 202 | ; 203 | 204 | ; cross product method: 205 | ; a = 1/2 * sum[0 to (n - 1)] of ( XiY((i+1) mod n) - X((i+1) mod n)Yi ) 206 | 207 | ; a = x0*y1 - x1*y0 208 | ; a += x1*y2 - x2*y1 209 | ; a += x2*y0 - x0*y2 210 | ; a *= 0.5 211 | ; if a > 0 then CCW 212 | ; if a < 0 the CW 213 | ; if a == 0 then back facing 214 | 215 | ; mac = sx0*sy1-sx1*sy0+sx1*sy2-sx2*sy1+sx2*sy0-sx0*sy2 216 | ; SX0*SY1+SX1*SY2+SX2*SY0-SX0*SY2-SX1*SY0-SX2*SY1 217 | 218 | 219 | 220 | ; alternative: 221 | ; (y1 - y0) * (x2 - x1) - (x1 - x0) * (y2 - y1) 222 | 223 | ; (a+b) (a-b) = a x a + a x -b + b x a + b x -b 224 | ; sy1*sx2-sx1*sy1-sy0*sx2+sx1*sy0-sx1*sy2-sy1*sx1-sx0*sy2+sy1*sx0 225 | ; if positive, surface is visible 226 | ;---------------------------------------------------------------------------------------------------------- 227 | 228 | .clockwisetest 229 | 230 | ; store surface id being tested 231 | STY ls 232 | 233 | ; getcoordinates routine returns screen x in A and screen y in Y 234 | 235 | ; fetch screen coordinate for surface point 0 236 | .clock0 LDX &8000,Y 237 | JSR getcoordinates 238 | STA x0:STY y0 239 | ; fetch screen coordinate for surface point 1 240 | LDY ls 241 | .clock1 LDX &8000,Y 242 | JSR getcoordinates 243 | STA x1:STY y1 244 | ; fetch screen coordinate for surface point 2 245 | LDY ls 246 | .clock2 LDX &8000,Y 247 | JSR getcoordinates 248 | 249 | ; now: 250 | ; x0,y0 = point 0 on the surface tri 251 | ; y1,y1 = point 1 on the surface tri 252 | ; A,Y = point 2 on the surface tri 253 | 254 | LDX#0 255 | 256 | ; abs(x2-x0) 257 | SEC 258 | SBC x0:BCS x20p 259 | ; if x2 > x0, negate result, increment counter X 260 | SBC#0:EOR #&FF ; sets carry 261 | INX 262 | .x20p STA lmul0 263 | 264 | ; carry is set 265 | 266 | ; abs(y1-y0) 267 | LDA y1:SBC y0:BCS y10p 268 | ; if y1 > y0, negate result, decrement counter X 269 | SBC#0:EOR #&FF ; sets carry 270 | DEX 271 | .y10p STA lmul1 272 | 273 | ; 274 | ; abs(y2-y0) 275 | TYA:LDY#0 276 | SBC y0:BCS y20p 277 | SBC#0:EOR #&FF:INY 278 | .y20p STA rmul0 279 | 280 | ; abs(x1-x0) 281 | LDA x1:SBC x0:BCS x10p 282 | SBC#0:EOR #&FF:DEY 283 | .x10p STA rmul1 284 | 285 | ; X contains 1,0, or 255 for the x2-x0 and y1-y0 test 286 | ; Y contains 1,0, or 255 for the y2-y0 and x1-x0 test 287 | ; 1 or 255 if just one test was less than the other 288 | ; 0 if both tests were less than the other 289 | ; 0 if both tests were greater than the other 290 | 291 | ; compare the results from both tests 292 | STX cnt 293 | CPX#1 ; set carry if X >= 1 (ie. not zero) 294 | TYA 295 | EOR cnt 296 | 297 | ; 1 eor 0 = 1, bit 0 set 298 | ; 0 eor 255 = 255, bit 0 set 299 | ; 1 eor 1 = 0, bit 0 clear 300 | ; 1 eor 255 = 254, bit 0 clear 301 | 302 | 303 | ; if bit 0 is clear, compute full outer product 304 | AND #1:BEQ compare 305 | ; otherwise: 306 | ; preserve Y and return 307 | ; carry bit is set = surface is hidden/CCW 308 | LDY ls 309 | RTS 310 | 311 | ; if X = 0, carry is clear, both terms are positive 312 | ; 313 | .compare BCC bothpos 314 | 315 | ; 316 | JSR multiply 317 | LDY lhs:CPY rhs ; carry set if rhs >= lhs 318 | LDA lhs+1:SBC rhs+1 319 | ; preserve Y and return 320 | LDY ls 321 | RTS 322 | 323 | .bothpos SEC 324 | JSR multiply 325 | LDY rhs:CPY lhs 326 | LDA rhs+1:SBC lhs+1 327 | 328 | ; preserve Y and return 329 | LDY ls 330 | RTS 331 | 332 | ;---------------------------------------------------------------------------------------------------------- 333 | ; outer/cross product multiplication 334 | ;---------------------------------------------------------------------------------------------------------- 335 | ; inputs: 336 | ; lmul0, lmul1 contain 1st two terms (8-bit values) 337 | ; rmul0, rmul1 contain 2nd two terms (8-bit values) 338 | ; returns: 339 | ; lmul0 * lmul1 in lhs (16-bits) 340 | ; rmul0 * rmul1 in rhs (16-bits) 341 | ;---------------------------------------------------------------------------------------------------------- 342 | 343 | .multiply 344 | { 345 | LDY lmul1:TYA 346 | LDX lmul0:STX lmul1 347 | SBC lmul0:BCS mabsl 348 | SBC#0:EOR #&FF 349 | .mabsl TAX 350 | LDA(lmul0),Y:SBC SQUARETABLE1_LSB,X:STA lhs 351 | LDA(lmul1),Y:SBC SQUARETABLE1_MSB,X:STA lhs+1 352 | 353 | LDY rmul1:TYA 354 | LDX rmul0:STX rmul1 355 | SBC rmul0:BCS mabsr 356 | SBC#0:EOR #&FF 357 | .mabsr TAX 358 | LDA(rmul0),Y:SBC SQUARETABLE1_LSB,X:STA rhs 359 | LDA(rmul1),Y:SBC SQUARETABLE1_MSB,X:STA rhs+1 360 | RTS 361 | } 362 | 363 | ;---------------------------------------------------------------------------------------------------------- 364 | ; Initialise the line visibility array based on culling preference 365 | ;---------------------------------------------------------------------------------------------------------- 366 | .resetvisibility 367 | { 368 | ; use culling value to reset the lines array 369 | ; if culling is on, they are reset to zero (and line visibility set to surface visibiity) 370 | ; if culling is off, they are all set to 255 (and line visibility is forced) 371 | LDA culling 372 | EOR #&FF 373 | TAY 374 | 375 | ; reset the 64-bit line visibility array 376 | STY line 377 | STY line+1 378 | STY line+2 379 | STY line+3 380 | STY line+4 381 | STY line+5 382 | STY line+6 383 | STY line+7 384 | 385 | RTS 386 | } 387 | 388 | ;---------------------------------------------------------------------------------------------------------- 389 | ; Determine the minimum set of lines to be rendered for the current model based on currently visible surfaces 390 | ;---------------------------------------------------------------------------------------------------------- 391 | ; inputs - 392 | ; (lines) points to the lines data block for this model 393 | ; surfs contains 16-bit array of visible surfaces 394 | ; outputs - 395 | ; line[] contains 64-bit array of visible lines to be rendered 396 | ; surfs >>= nsurfs 397 | ;---------------------------------------------------------------------------------------------------------- 398 | ; given the list of visible surfaces 399 | ; set a bit in the 64-bit output array (ZP "line") array for each line 400 | ; that is associated with the visible surface 401 | ; 8 bits x 8 bytes = 64 bits, or 64 lines per object 402 | ; in this way, lines are only ever drawn once, even if shared across surfaces 403 | ;---------------------------------------------------------------------------------------------------------- 404 | 405 | .hiddenlineremoval 406 | { 407 | LDY #0 408 | 409 | LDX nsurfs 410 | 411 | ; for y=0; y>= 1 (low bit into carry) 418 | ; if low bit was set, surface is not visible 419 | LSR surfs+1:ROR surfs:BCS nosurf 420 | 421 | 422 | IF WIREFRAME 423 | LDA(lines),Y:ORA line:STA line:INY 424 | LDA(lines),Y:ORA line+1:STA line+1:INY 425 | LDA(lines),Y:ORA line+2:STA line+2:INY 426 | LDA(lines),Y:ORA line+3:STA line+3:INY 427 | LDA(lines),Y:ORA line+4:STA line+4:INY 428 | LDA(lines),Y:ORA line+5:STA line+5:INY 429 | LDA(lines),Y:ORA line+6:STA line+6:INY 430 | LDA(lines),Y:ORA line+7:STA line+7:INY 431 | ELSE 432 | LDA(lines),Y:EOR line:STA line:INY 433 | LDA(lines),Y:EOR line+1:STA line+1:INY 434 | LDA(lines),Y:EOR line+2:STA line+2:INY 435 | LDA(lines),Y:EOR line+3:STA line+3:INY 436 | LDA(lines),Y:EOR line+4:STA line+4:INY 437 | LDA(lines),Y:EOR line+5:STA line+5:INY 438 | LDA(lines),Y:EOR line+6:STA line+6:INY 439 | LDA(lines),Y:EOR line+7:STA line+7:INY 440 | ENDIF 441 | DEX:BPL loopC 442 | RTS 443 | 444 | ; skip to lines entry for the next surface 445 | .nosurf TYA:ADC#7:TAY 446 | DEX:BPL loopC 447 | RTS 448 | } 449 | 450 | 451 | 452 | ;---------------------------------------------------------------------------------------------------------- 453 | ; surface index to 16-bit bitmask 454 | ; lookup table 455 | ;---------------------------------------------------------------------------------------------------------- 456 | 457 | ; used by hiddensurfaceremoval routine to convert a surface id to a bitfield for use with surfs array 458 | ; supports maximum 16 surfaces 459 | 460 | ; SM: could ALIGN 32 this table to ensure no page boundary cycle hits, but might waste a few bytes and not sure its worth the memory/speed tradeoff. 461 | .bits 462 | ; lsb table for surface ID[0-7] 463 | EQUB 1,2,4,8,16,32,64,128 464 | EQUD 0:EQUD 0 465 | ; msb table for surface ID[8-15] 466 | EQUD 0:EQUD 0 467 | EQUB 1,2,4,8,16,32,64,128 468 | 469 | -------------------------------------------------------------------------------- /basic/3D.txt: -------------------------------------------------------------------------------- 1 | 10 REM RUN WITH PAGE=&3000 2 | 20 MODE 7 3 | 30 PROCassemble 4 | 40 IF P%>&26BAPRINT "Out of memory":END 5 | 50 CALL start 6 | 60 DEF PROCassemble 7 | 70 *LOAD Line3D 26BA 8 | 80 *TAPE 9 | 90 linedraw=&26FA 10 | 100 m00lsb=0:m00msb=9 11 | 110 m01lsb=1:m01msb=&A 12 | 120 m02lsb=2:m02msb=&B 13 | 130 m10lsb=3:m10msb=&C 14 | 140 m11lsb=4:m11msb=&D 15 | 150 m12lsb=5:m12msb=&E 16 | 160 m20lsb=6:m20msb=&F 17 | 170 m21lsb=7:m21msb=&10 18 | 180 m22lsb=8:m22msb=&11 19 | 190 adr=&12 20 | 200 xr=&1A 21 | 210 yr=&1C 22 | 220 zr=&1E 23 | 230 product=&20 24 | 240 rx=&22 25 | 250 ry=&23 26 | 260 rz=&24 27 | 270 npts=&30 28 | 280 nlines=&31 29 | 290 nsurfs=&32 30 | 300 maxvis=&33 31 | 310 lhs=&40 32 | 320 rhs=&42 33 | 330 lmul0=&44 34 | 340 lmul1=&46 35 | 350 rmul0=&48 36 | 360 rmul1=&4A 37 | 370 surfs=&50 38 | 380 oldsurfs=&52 39 | 390 surfsdone=&54 40 | 400 visible=&56 41 | 410 lines=&57 42 | 420 line=&59 43 | 430 odr=&61 44 | 440 space=&63 45 | 450 p=&64 46 | 460 f=&65 47 | 470 flicker=&66 48 | 480 pause=&67 49 | 490 x0=&70:y0=&71 50 | 500 x1=&72:y1=&73 51 | 510 scr=&74 52 | 520 err=&76 53 | 530 errs=&77 54 | 540 cnt=&78 55 | 550 ls=&79 56 | 560 dx=&FF 57 | 570 dy=&7A 58 | 580 scrstrt=&7B 59 | 590 FOR pass=0TO 3STEP 3 60 | 600 P%=&1400 61 | 610 [OPTpass 62 | 620 .perspective OPT FNperspective 63 | 630 .ptsdone EQUS STRING$(&40," ") 64 | 640 .sx EQUS STRING$(&40," ") 65 | 650 .sy EQUS STRING$(&40," ") 66 | 660 .slsb OPT FNsintab 67 | 670 .bits EQUD&08040201:EQUD&80402010 68 | 680 EQUD0:EQUD0 69 | 690 EQUD0:EQUD0 70 | 700 EQUD&08040201:EQUD&80402010 71 | 710 .vdus 72 | 720 EQUD&170416:EQUD&200A 73 | 730 EQUD0:EQUB&FF 74 | 740 .start 75 | 750 LDX#0:STXadr:STXspace:STXf:STXp:STXflicker 76 | 760 LDA#1:STApause 77 | 770 .loop 78 | 780 LDAvdus,X:BMIcls:JSR&FFEE 79 | 790 INX:BNEloop 80 | 800 .cls 81 | 810 LDA#&30:STAadr+1:LDY#0:TYA 82 | 820 .loop 83 | 830 STA(adr),Y:INY:BNEloop 84 | 840 INCadr+1:BPLloop 85 | 850 SEI:LDA#&40:STA&D00:LDX#&FF:TXS 86 | 860 LDA#0:STArx 87 | 870 LDA#&7B:STAry 88 | 880 LDA#&C3:STArz 89 | 890 CLC 90 | 900 LDA#&F:STAlmul0+1:STArmul0+1 91 | 910 LDA#&12:STAlmul1+1:STArmul1+1 92 | 920 LDA#0:TAX:TAY 93 | 930 STXlhs:STYlhs+1:BCCgo 94 | 940 .loop 95 | 950 TXA:ADClhs:STAlhs:STA(lmul0),Y 96 | 960 LDA#0:ADClhs+1:STAlhs+1:STA(lmul1),Y 97 | 970 INX:.go STYlmul0:STYlmul1 98 | 980 TXA:ADClhs:STAlhs:STA(lmul0),Y 99 | 990 LDA#0:ADClhs+1:STAlhs+1:STA(lmul1),Y 100 | 1000 INY:BNEloop 101 | 1010 LDX#0:LDY#&FF 102 | 1020 .loop 103 | 1030 LDA&F01,Y:STA&E00,X 104 | 1040 LDA&1201,Y:STA&1100,X 105 | 1050 DEY:INX:BNEloop 106 | 1060 JSRback 107 | 1070 LDA#&58:STAscrstrt 108 | 1080 .frame 109 | 1090 LDA#&81:LDX#&9D:LDY#&FF:JSR&FFF4 110 | 1100 TYA:BEQnopress:LDAspace:BNEnopress 111 | 1110 JSRmodify:LDA#1 112 | 1120 .nopress STAspace 113 | 1130 LDAscrstrt:LSRA:LSRA:LSRA 114 | 1140 LDX#&C:STX&FE00:STA&FE01 115 | 1150 LDA#&81:LDX#&BC:LDY#&FF:JSR&FFF4 116 | 1160 TYA:BEQnof:LDAf:BNEnof 117 | 1170 LDAflicker:EOR #1:STAflicker:LDA#1 118 | 1180 .nof STAf 119 | 1190 LDAflicker:AND pause:BNEfastandflicker 120 | 1200 CLI:LDA#19:JSR&FFF4:SEI 121 | 1210 .fastandflicker 122 | 1220 LDAscrstrt:EOR #&68:STAscrstrt 123 | 1230 JSRwipe 124 | 1240 LDA#&81:LDX#&C8:LDY#&FF:JSR&FFF4 125 | 1250 TYA:BEQnop:LDAp:BNEnop 126 | 1260 LDApause:EOR #1:STApause:LDA#1 127 | 1270 .nop STAp 128 | 1280 LDApause:BEQnrot 129 | 1290 JSRrotate 130 | 1300 .nrot 131 | 1310 JSRmatrix 132 | 1320 JSRnewpoints 133 | 1330 JSRhiddensurfaceremoval 134 | 1340 JSRhiddenlineremoval 135 | 1350 JSRdrawlines 136 | 1360 JMPframe 137 | 1370 .rotate 138 | 1380 INCrx 139 | 1390 INCry:INCry 140 | 1400 INCrz:INCrz:INCrz 141 | 1410 RTS 142 | 1420 .newpoints 143 | 1430 LDA#0:LDXnpts 144 | 1440 .loop 145 | 1450 STAptsdone,X 146 | 1460 DEX:BPLloop 147 | 1470 RTS 148 | 1480 .wipe 149 | 1490 LDX#&2F:CMP#&30:BNEwipe0:JMPwipe1 150 | 1500 .wipe0 LDA#0 151 | 1510 .loop 152 | 1520 ]:FOR Y%=&5D40 TO &7A00 STEP &140 153 | 1530 FOR X%=Y%TO Y%+144STEP 48 154 | 1540 [OPTpass:STAX%,X:]NEXT , 155 | 1550 [OPTpass:DEX:BMIwiped:JMPloop 156 | 1560 .wiped RTS 157 | 1570 .wipe1 LDA#0 158 | 1580 .loop 159 | 1590 ]FOR Y%=&3540TO &5200STEP &140 160 | 1600 FOR X%=Y%TO Y%+144STEP 48 161 | 1610 [OPTpass:STAX%,X:]NEXT , 162 | 1620 [OPTpass:DEX:BMIwiped1:JMPloop 163 | 1630 .wiped1 RTS 164 | 1640 .unitvectors 165 | 1650 EQUBu00 AND &FF:EQUBu01 AND &FF:EQUBu02 AND &FF 166 | 1660 EQUBu10 AND &FF:EQUBu11 AND &FF:EQUBu12 AND &FF 167 | 1670 EQUBu20 AND &FF:EQUBu21 AND &FF:EQUBu22 AND &FF 168 | 1680 EQUBu00 DIV 256:EQUBu01 DIV 256:EQUBu02 DIV 256 169 | 1690 EQUBu10 DIV 256:EQUBu11 DIV 256:EQUBu12 DIV 256 170 | 1700 EQUBu20 DIV 256:EQUBu21 DIV 256:EQUBu22 DIV 256 171 | 1710 .getcoordinates 172 | 1720 LDAptsdone,X:BPLtransform 173 | 1730 LDAsx,X 174 | 1740 LDYsy,X 175 | 1750 RTS 176 | 1760 .transform 177 | 1770 LDA#&FF:STAptsdone,X 178 | 1780 .x LDY&8000,X 179 | 1790 SEC:.u00 180 | 1800 LDA&E00,Y:SBC&E00,Y:STAxr 181 | 1810 LDA&1100,Y:SBC&1100,Y:STAxr+1 182 | 1820 SEC:.u10 183 | 1830 LDA&E00,Y:SBC&E00,Y:STAyr 184 | 1840 LDA&1100,Y:SBC&1100,Y:STAyr+1 185 | 1850 SEC:.u20 186 | 1860 LDA&E00,Y:SBC&E00,Y:STAzr 187 | 1870 LDA&1100,Y:SBC&1100,Y:STAzr+1 188 | 1880 .y LDY&8000,X 189 | 1890 SEC:.u01 190 | 1900 LDA&E00,Y:SBC&E00,Y:STAproduct 191 | 1910 LDA&1100,Y:SBC&1100,Y:STAproduct+1 192 | 1920 LDAproduct:CLC:ADCxr:STAxr 193 | 1930 LDAproduct+1:ADCxr+1:STAxr+1 194 | 1940 SEC:.u11 195 | 1950 LDA&E00,Y:SBC&E00,Y:STAproduct 196 | 1960 LDA&1100,Y:SBC&1100,Y:STAproduct+1 197 | 1970 LDAproduct:CLC:ADCyr:STAyr 198 | 1980 LDAproduct+1:ADCyr+1:STAyr+1 199 | 1990 SEC:.u21 200 | 2000 LDA&E00,Y:SBC&E00,Y:STAproduct 201 | 2010 LDA&1100,Y:SBC&1100,Y:STAproduct+1 202 | 2020 LDAproduct:CLC:ADCzr:STAzr 203 | 2030 LDAproduct+1:ADCzr+1:STAzr+1 204 | 2040 .z LDY&8000,X 205 | 2050 SEC:.u02 206 | 2060 LDA&E00,Y:SBC&E00,Y:STAproduct 207 | 2070 LDA&1100,Y:SBC&1100,Y:STAproduct+1 208 | 2080 LDAproduct:CLC:ADCxr:STAxr 209 | 2090 LDAproduct+1:ADCxr+1:STAxr+1 210 | 2100 SEC:.u12 211 | 2110 LDA&E00,Y:SBC&E00,Y:STAproduct 212 | 2120 LDA&1100,Y:SBC&1100,Y:STAproduct+1 213 | 2130 LDAproduct:CLC:ADCyr:STAyr 214 | 2140 LDAproduct+1:ADCyr+1:STAyr+1 215 | 2150 SEC:.u22 216 | 2160 LDA&E00,Y:SBC&E00,Y:STAproduct 217 | 2170 LDA&1100,Y:SBC&1100,Y:STAproduct+1 218 | 2180 LDAproduct:CLC:ADCzr:STAzr 219 | 2190 LDAproduct+1:ADCzr+1 220 | 2200 ASLzr:ROLA:ASLzr 221 | 2210 ADC#&80:TAY:CLC 222 | 2220 LDA#&80:ADCperspective,Y:STAadr:STAadr+2 223 | 2230 LDA#&E:ADC#0:STAadr+1:ADC#3:STAadr+3 224 | 2240 LDAadr:ADC#1:STAadr+4:STAadr+6 225 | 2250 LDAadr+1:ADC#0:STAadr+5:ADC#3:STAadr+7 226 | 2260 LDAyr+1:ASLyr:ROLA:ASLyr 227 | 2270 ADC#&80:TAY:SEC:EOR #&FF:STYzr:STAzr+1 228 | 2280 LDA(adr),Y:LDYzr+1:SBC(adr+4),Y:STAyr 229 | 2290 LDYzr:LDA(adr+2),Y:LDYzr+1:SBC(adr+6),Y 230 | 2300 ASLyr:ADC#&80:STAsy,X 231 | 2310 LDAxr+1:ASLxr:ROLA:ASLxr 232 | 2320 ADC#&80:TAY:SEC:EOR #&FF:STYzr:STAzr+1 233 | 2330 LDA(adr),Y:LDYzr+1:SBC(adr+4),Y:STAxr 234 | 2340 LDYzr:LDA(adr+2),Y:LDYzr+1:SBC(adr+6),Y 235 | 2350 ASLxr:ADC#&80:STAsx,X 236 | 2360 LDYsy,X 237 | 2370 RTS 238 | 2380 .matrix 239 | 2390 LDYrx:SEC 240 | 2400 LDA#0:SBCslsb,Y:STAm12lsb 241 | 2410 LDA#0:SBCsmsb,Y:ASLm12lsb 242 | 2420 ROLA:ASLm12lsb:ROLA:STAm12msb 243 | 2430 TYA:SEC:SBCry 244 | 2440 TAX:CLC:ADCrz:STAadr+3 245 | 2450 TYA:CLC:ADCry 246 | 2460 TAY:CLC:ADCrz:STAadr+2:SEC 247 | 2470 LDAslsb,X:SBCslsb,Y:STAm02lsb 248 | 2480 LDAsmsb,X:SBCsmsb,Y:ASLm02lsb 249 | 2490 ROLA:STAm02msb:CLC 250 | 2500 LDAclsb,Y:ADCclsb,X:STAm22lsb 251 | 2510 LDAcmsb,Y:ADCcmsb,X:ASLm22lsb 252 | 2520 ROLA:STAm22msb 253 | 2530 TYA:SEC:SBCrz:STAadr+4 254 | 2540 TXA:SEC:SBCrz:STAadr+5 255 | 2550 LDArx:CLC:ADCrz:TAY 256 | 2560 LDArx:SEC:SBCrz:TAX:SEC 257 | 2570 LDAslsb,Y:SBCslsb,X:STAm10lsb 258 | 2580 LDAsmsb,Y:SBCsmsb,X:ASLm10lsb 259 | 2590 ROLA:STAm10msb:CLC 260 | 2600 LDAclsb,X:ADCclsb,Y:STAm11lsb 261 | 2610 LDAcmsb,Y:ADCcmsb,X:ASLm11lsb 262 | 2620 ROLA:STAm11msb 263 | 2630 LDAry:SEC:SBCrz:TAY 264 | 2640 LDArz:CLC:ADCry:TAX:SEC 265 | 2650 LDAclsb,X:SBCclsb,Y:STAm21lsb 266 | 2660 LDAcmsb,X:SBCcmsb,Y:ASLm21lsb 267 | 2670 ROLA:STAm21msb:SEC 268 | 2680 LDAslsb,Y:SBCslsb,X:STAm01lsb 269 | 2690 LDAsmsb,Y:SBCsmsb,X:ASLm01lsb 270 | 2700 ROLA:STAm01msb:CLC 271 | 2710 LDAclsb,Y:ADCclsb,X:STAm00lsb 272 | 2720 LDAcmsb,X:ADCcmsb,Y:ASLm00lsb 273 | 2730 ROLA:STAm00msb:CLC 274 | 2740 LDAslsb,X:ADCslsb,Y:STAm20lsb 275 | 2750 LDAsmsb,Y:ADCsmsb,X:ASLm20lsb 276 | 2760 ROLA:STAm20msb 277 | 2770 LDYadr+4:LDXadr+3:SEC 278 | 2780 LDAm00lsb:SBCslsb,X:STAm00lsb 279 | 2790 LDAm00msb:SBCsmsb,X:STAm00msb:CLC 280 | 2800 LDAslsb,Y:ADCm21lsb:STAm21lsb 281 | 2810 LDAm21msb:ADCsmsb,Y:STAm21msb:CLC 282 | 2820 LDAclsb,Y:ADCm20lsb:STAm20lsb 283 | 2830 LDAcmsb,Y:ADCm20msb:STAm20msb:SEC 284 | 2840 LDAm01lsb:SBCclsb,X:STAm01lsb 285 | 2850 LDAm01msb:SBCcmsb,X:STAm01msb:CLC 286 | 2860 LDAclsb,Y:ADCm01lsb:STAm01lsb 287 | 2870 LDAcmsb,Y:ADCm01msb:STAm01msb:CLC 288 | 2880 LDAm21lsb:ADCslsb,X:STAm21lsb 289 | 2890 LDAm21msb:ADCsmsb,X:STAm21msb:SEC 290 | 2900 LDAm20lsb:SBCclsb,X:STAm20lsb 291 | 2910 LDAm20msb:SBCcmsb,X:STAm20msb:SEC 292 | 2920 LDAm00lsb:SBCslsb,Y:STAm00lsb 293 | 2930 LDAm00msb:SBCsmsb,Y:STAm00msb 294 | 2940 LDXadr+5:LDYadr+2:SEC 295 | 2950 LDAm20lsb:SBCclsb,Y:STAm20lsb 296 | 2960 LDAm20msb:SBCcmsb,Y:STAm20msb:CLC 297 | 2970 LDAm00lsb:ADCslsb,X:STAm00lsb 298 | 2980 LDAm00msb:ADCsmsb,X:STAm00msb:CLC 299 | 2990 LDAm21lsb:ADCslsb,X:STAm21lsb 300 | 3000 LDAm21msb:ADCsmsb,X:STAm21msb:CLC 301 | 3010 LDAclsb,Y:ADCm01lsb:STAm01lsb 302 | 3020 LDAcmsb,Y:ADCm01msb:STAm01msb:CLC 303 | 3030 LDAslsb,Y:ADCm21lsb:STAm21lsb 304 | 3040 LDAsmsb,Y:ADCm21msb:STAm21msb:CLC 305 | 3050 LDAslsb,Y:ADCm00lsb:STAm00lsb 306 | 3060 LDAsmsb,Y:ADCm00msb:STAm00msb:CLC 307 | 3070 LDAclsb,X:ADCm20lsb:STAm20lsb 308 | 3080 LDAcmsb,X:ADCm20msb:STAm20msb:SEC 309 | 3090 LDAm01lsb:SBCclsb,X:STAm01lsb 310 | 3100 LDAm01msb:SBCcmsb,X:STAm01msb 311 | 3110 LDX#8 312 | 3120 .loop 313 | 3130 LDAunitvectors,X:STAadr 314 | 3140 LDAunitvectors+9,X:STAadr+1 315 | 3150 LDAm00msb,X:ASLm00lsb,X:ADC#&80 316 | 3160 LDY#1:STA(adr),Y:LDY#9:STA(adr),Y 317 | 3170 CLC:EOR #&FF:ADC#1 318 | 3180 LDY#4:STA(adr),Y:LDY#&C:STA(adr),Y 319 | 3190 DEX:BPLloop 320 | 3200 RTS 321 | 3210 .hiddensurfaceremoval 322 | 3220 LDA#0:STAvisible 323 | 3230 LDAoldsurfs:EOR #&FF:STAsurfsdone 324 | 3240 LDAoldsurfs+1:EOR #&FF:STAsurfsdone+1 325 | 3250 LDA#&F:SEC:SBCnsurfs:BEQnloop 326 | 3260 TAY:LDAoldsurfs 327 | 3270 .loop 328 | 3280 ASLA:ROLoldsurfs+1:DEY:BNEloop 329 | 3290 STAoldsurfs:.nloop 330 | 3300 LDYnsurfs 331 | 3310 .loop 332 | 3320 ASLoldsurfs:ROLoldsurfs+1 333 | 3330 BCShidesurface 334 | 3340 JSRclockwisetest:BCShidesurface 335 | 3350 TYA:ASLA:TAX 336 | 3360 .opposite0 LDA&8000,X:INX 337 | 3370 ORAsurfsdone:STAsurfsdone 338 | 3380 .opposite1 LDA&8000,X 339 | 3390 ORAsurfsdone+1:STAsurfsdone+1 340 | 3400 INCvisible 341 | 3410 .hidesurface 342 | 3420 ROLsurfs:ROLsurfs+1 343 | 3430 DEY:BPLloop 344 | 3440 LDYnsurfs 345 | 3450 LDAbits,Y:STAoldsurfs 346 | 3460 LDAbits+16,Y:STAoldsurfs+1 347 | 3470 .loop 348 | 3480 LDXvisible:CPXmaxvis:BEQdoneit 349 | 3490 LDAsurfsdone:AND oldsurfs:BNEsurfdone 350 | 3500 LDAsurfsdone+1:AND oldsurfs+1:BNEsurfdone 351 | 3510 JSRclockwisetest:BCSsurfdone 352 | 3520 LDAoldsurfs:EOR #&FF:AND surfs:STAsurfs 353 | 3530 LDAoldsurfs+1:EOR #&FF:AND surfs+1:STAsurfs+1 354 | 3540 TYA:ASLA:TAX 355 | 3550 .opposite2 LDA&8000,X:INX 356 | 3560 ORAsurfsdone:STAsurfsdone 357 | 3570 .opposite3 LDA&8000,X 358 | 3580 ORAsurfsdone+1:STAsurfsdone+1 359 | 3590 INCvisible 360 | 3600 .surfdone 361 | 3610 LSRoldsurfs+1:RORoldsurfs 362 | 3620 DEY:BPLloop 363 | 3630 .doneit 364 | 3640 LDAsurfs:STAoldsurfs 365 | 3650 LDAsurfs+1:STAoldsurfs+1 366 | 3660 RTS 367 | 3670 .clockwisetest STYls 368 | 3680 .clock0 LDX&8000,Y 369 | 3690 JSRgetcoordinates 370 | 3700 STAx0:STYy0:LDYls 371 | 3710 .clock1 LDX&8000,Y 372 | 3720 JSRgetcoordinates 373 | 3730 STAx1:STYy1:LDYls 374 | 3740 .clock2 LDX&8000,Y 375 | 3750 JSRgetcoordinates 376 | 3760 SEC:LDX#0 377 | 3770 SBCx0:BCSx20p 378 | 3780 SBC#0:EOR #&FF:INX 379 | 3790 .x20p STAlmul0 380 | 3800 LDAy1:SBCy0:BCSy10p 381 | 3810 SBC#0:EOR #&FF:DEX 382 | 3820 .y10p STAlmul1 383 | 3830 TYA:LDY#0 384 | 3840 SBCy0:BCSy20p 385 | 3850 SBC#0:EOR #&FF:INY 386 | 3860 .y20p STArmul0 387 | 3870 LDAx1:SBCx0:BCSx10p 388 | 3880 SBC#0:EOR #&FF:DEY 389 | 3890 .x10p STArmul1:STXcnt 390 | 3900 CPX#1:TYA 391 | 3910 EOR cnt:AND #1:BEQcompare 392 | 3920 LDYls:RTS 393 | 3930 .compare BCCbothpos 394 | 3940 JSRmultiply 395 | 3950 LDYlhs:CPYrhs 396 | 3960 LDAlhs+1:SBCrhs+1 397 | 3970 LDYls:RTS 398 | 3980 .bothpos SEC 399 | 3990 JSRmultiply 400 | 4000 LDYrhs:CPYlhs 401 | 4010 LDArhs+1:SBClhs+1 402 | 4020 LDYls:RTS 403 | 4030 .multiply 404 | 4040 LDYlmul1:TYA 405 | 4050 LDXlmul0:STXlmul1 406 | 4060 SBClmul0:BCSmabsl 407 | 4070 SBC#0:EOR #&FF 408 | 4080 .mabsl TAX 409 | 4090 LDA(lmul0),Y:SBC&F00,X:STAlhs 410 | 4100 LDA(lmul1),Y:SBC&1200,X:STAlhs+1 411 | 4110 LDYrmul1:TYA 412 | 4120 LDXrmul0:STXrmul1 413 | 4130 SBCrmul0:BCSmabsr 414 | 4140 SBC#0:EOR #&FF 415 | 4150 .mabsr TAX 416 | 4160 LDA(rmul0),Y:SBC&F00,X:STArhs 417 | 4170 LDA(rmul1),Y:SBC&1200,X:STArhs+1 418 | 4180 RTS 419 | 4190 .hiddenlineremoval 420 | 4200 LDXnsurfs:LDY#0 421 | 4210 STYline 422 | 4220 STYline+1 423 | 4230 STYline+2 424 | 4240 STYline+3 425 | 4250 STYline+4 426 | 4260 STYline+5 427 | 4270 STYline+6 428 | 4280 STYline+7 429 | 4290 .loop 430 | 4300 LSRsurfs+1:RORsurfs:BCSnosurf 431 | 4310 LDA(lines),Y:ORAline:STAline:INY 432 | 4320 LDA(lines),Y:ORAline+1:STAline+1:INY 433 | 4330 LDA(lines),Y:ORAline+2:STAline+2:INY 434 | 4340 LDA(lines),Y:ORAline+3:STAline+3:INY 435 | 4350 LDA(lines),Y:ORAline+4:STAline+4:INY 436 | 4360 LDA(lines),Y:ORAline+5:STAline+5:INY 437 | 4370 LDA(lines),Y:ORAline+6:STAline+6:INY 438 | 4380 LDA(lines),Y:ORAline+7:STAline+7:INY 439 | 4390 DEX:BPLloop:RTS 440 | 4400 .nosurf TYA:ADC#7:TAY 441 | 4410 DEX:BPLloop:RTS 442 | 4420 .drawlines 443 | 4430 LDA#0:STAlhs+1 444 | 4440 LDAnlines:STAlhs 445 | 4450 .loop 446 | 4460 LSRline+7 447 | 4470 RORline+6 448 | 4480 RORline+5 449 | 4490 RORline+4 450 | 4500 RORline+3 451 | 4510 RORline+2 452 | 4520 RORline+1 453 | 4530 RORline 454 | 4540 BCCnoline 455 | 4550 LDYlhs+1 456 | 4560 .linestarts LDA&8000,Y:PHA 457 | 4570 .lineends LDA&8000,Y:TAX 458 | 4580 JSRgetcoordinates 459 | 4590 STAx0:STYy0 460 | 4600 PLA:TAX 461 | 4610 JSRgetcoordinates 462 | 4620 STAx1:STYy1 463 | 4630 JSRlinedraw 464 | 4640 .noline INClhs+1:DEClhs:BPLloop 465 | 4650 RTS 466 | 4660 .back LDA#coordinates AND &FF:STAodr 467 | 4670 LDA#coordinates DIV 256:STAodr+1 468 | 4680 .modify 469 | 4690 LDA#&FF:STAoldsurfs:STAoldsurfs+1 470 | 4700 LDY#0 471 | 4710 LDA(odr),Y:BMIback:STAnpts:INY 472 | 4720 LDA(odr),Y:STAnlines:INY 473 | 4730 LDA(odr),Y:STAnsurfs:INY 474 | 4740 LDA(odr),Y:STAmaxvis 475 | 4750 LDAodr:SEC:ADC#3:STAodr:STAx+1 476 | 4760 LDAodr+1:ADC#0:STAodr+1:STAx+2 477 | 4770 LDAodr:SEC:ADCnpts:STAodr:STAy+1 478 | 4780 LDAodr+1:ADC#0:STAodr+1:STAy+2 479 | 4790 LDAodr:SEC:ADCnpts:STAodr:STAz+1 480 | 4800 LDAodr+1:ADC#0:STAodr+1:STAz+2 481 | 4810 LDAodr:SEC:ADCnpts:STAodr:STAclock0+1 482 | 4820 LDAodr+1:ADC#0:STAodr+1:STAclock0+2 483 | 4830 LDAodr:SEC:ADCnsurfs:STAodr:STAclock1+1 484 | 4840 LDAodr+1:ADC#0:STAodr+1:STAclock1+2 485 | 4850 LDAodr:SEC:ADCnsurfs:STAodr:STAclock2+1 486 | 4860 LDAodr+1:ADC#0:STAodr+1:STAclock2+2 487 | 4870 LDAodr:SEC:ADCnsurfs:STAodr:STAopposite0+1:STAopposite1+1:STAopposite2+1:STAopposite3+1 488 | 4880 LDAodr+1:ADC#0:STAodr+1:STAopposite0+2:STAopposite1+2:STAopposite2+2:STAopposite3+2 489 | 4890 LDAodr:SEC:ADCnsurfs:STAodr 490 | 4900 LDAodr+1:ADC#0:STAodr+1 491 | 4910 LDAodr:SEC:ADCnsurfs:STAodr:STAlines 492 | 4920 LDAodr+1:ADC#0:STAodr+1:STAlines+1 493 | 4930 LDY#7 494 | 4940 .loop 495 | 4950 LDAodr:SEC:ADCnsurfs:STAodr 496 | 4960 LDAodr+1:ADC#0:STAodr+1 497 | 4970 DEY:BPLloop 498 | 4980 LDAodr:STAlinestarts+1:SEC:ADCnlines:STAodr:STAlineends+1 499 | 4990 LDAodr+1:STAlinestarts+2:ADC#0:STAodr+1:STAlineends+2 500 | 5000 LDAodr:SEC:ADCnlines:STAodr 501 | 5010 LDAodr+1:ADC#0:STAodr+1 502 | 5020 RTS 503 | 5030 .coordinates OPT FNreaddata 504 | 5040 ] 505 | 5050 clsb=slsb+&40 506 | 5060 smsb=slsb+&140 507 | 5070 cmsb=clsb+&140 508 | 5080 NEXT 509 | 5090 ENDPROC 510 | 5100 DEF FNperspective 511 | 5110 IF pass<2P%=P%+&100:=pass 512 | 5120 d=&100 513 | 5130 oz=&80 514 | 5140 FOR Z%=-128TO 127 515 | 5150 ?P%=&FF*d/(d+oz+Z%)+.5 516 | 5160 P%=P%+1 517 | 5170 NEXT 518 | 5180 =pass 519 | 5190 DEF FNsintab 520 | 5200 IF pass<2P%=P%+&280:=pass 521 | 5210 FOR A%=0TO &13F 522 | 5220 S%=&1FA0*SIN (A%*2*PI /256)+.5 523 | 5230 ?P%=S%AND &FF 524 | 5240 P%?&140=(S%AND &FF00)DIV 256 525 | 5250 P%=P%+1 526 | 5260 NEXT 527 | 5270 P%=P%+&140 528 | 5280 =pass 529 | 5290 DEF FNreaddata 530 | 5300 RESTORE 5730 531 | 5310 READ NPTS%:IF NPTS%=&FF ?P%=&FF:P%=P%+1:=pass 532 | 5320 READ NLINES%,NSURFS%,MAXVIS%,SCALE% 533 | 5330 ?P%=NPTS%-1:P%=P%+1 534 | 5340 ?P%=NLINES%-1:P%=P%+1 535 | 5350 ?P%=NSURFS%-1:P%=P%+1 536 | 5360 ?P%=MAXVIS%:P%=P%+1 537 | 5370 FOR I%=1TO NPTS% 538 | 5380 READ X%,Y%,Z% 539 | 5390 ?P%=SCALE%*X%+128 540 | 5400 ?(P%+NPTS%)=SCALE%*Y%+128 541 | 5410 ?(P%+2*NPTS%)=SCALE%*Z%+128 542 | 5420 P%=P%+1 543 | 5430 NEXT 544 | 5440 P%=P%+2*NPTS% 545 | 5450 FOR I%=1TO NSURFS% 546 | 5460 READ C1%,C2%,C3% 547 | 5470 ?P%=C1% 548 | 5480 ?(P%+NSURFS%)=C2% 549 | 5490 ?(P%+2*NSURFS%)=C3% 550 | 5500 P%=P%+1 551 | 5510 NEXT 552 | 5520 P%=P%+2*NSURFS% 553 | 5530 FOR I%=1TO NSURFS% 554 | 5540 READ OPPS% 555 | 5550 IF OPPS%>&7FS%=0ELSE S%=2^OPPS% 556 | 5560 ?P%=S%AND &FF 557 | 5570 ?(P%+1)=S%DIV 256 558 | 5580 P%=P%+2 559 | 5590 NEXT 560 | 5600 FOR I%=1TO NSURFS% 561 | 5610 READ LIN1%,LIN2% 562 | 5620 !P%=LIN2% 563 | 5630 !(P%+4)=LIN1% 564 | 5640 P%=P%+8 565 | 5650 NEXT 566 | 5660 FOR I%=1TO 2*NLINES% 567 | 5670 READ PT% 568 | 5680 ?P%=PT% 569 | 5690 P%=P%+1 570 | 5700 NEXT 571 | 5710 GOTO 5310 572 | 5720 REM Cube data 573 | 5730 DATA 8,12,6,3 574 | 5740 DATA 1 575 | 5750 DATA +50,+50,+50 576 | 5760 DATA +50,+50,-50 577 | 5770 DATA +50,-50,+50 578 | 5780 DATA +50,-50,-50 579 | 5790 DATA -50,+50,+50 580 | 5800 DATA -50,+50,-50 581 | 5810 DATA -50,-50,+50 582 | 5820 DATA -50,-50,-50 583 | 5830 DATA 4,6,0 584 | 5840 DATA 5,7,4 585 | 5850 DATA 1,4,0 586 | 5860 DATA 3,1,0 587 | 5870 DATA 3,2,6 588 | 5880 DATA 7,1,3 589 | 5890 DATA 5,3,4,1,2,0 590 | 5900 DATA 0,&701 591 | 5910 DATA 0,&164 592 | 5920 DATA 0,&00F 593 | 5930 DATA 0,&A12 594 | 5940 DATA 0,&CC0 595 | 5950 DATA 0,&0B8 596 | 5960 DATA 0,1,4,1,1,5,6,3,4,0,2,2 597 | 5970 DATA 4,0,5,5,3,7,7,7,6,2,6,3 598 | 5980 REM Viper data 599 | 5990 DATA 15,20,7,5 600 | 6000 DATA 4 601 | 6010 DATA 0,19,0,0,1,-6 602 | 6020 DATA 0,1,6,-10,-19,-6 603 | 6030 DATA -19,-19,0,-10,-19,6 604 | 6040 DATA 10,-19,6,19,-19,0 605 | 6050 DATA 10,-19,-6,-3,-19,-4 606 | 6060 DATA -12,-19,0,-3,-19,4 607 | 6070 DATA 3,-19,-4,3,-19,4 608 | 6080 DATA 12,-19,0 609 | 6090 DATA 1,8,3 610 | 6100 DATA 0,1,3 611 | 6110 DATA 0,8,1 612 | 6120 DATA 0,2,6 613 | 6130 DATA 0,5,2 614 | 6140 DATA 2,5,6 615 | 6150 DATA 6,3,8 616 | 6160 DATA 5,&80,&80,&80,&80,0,&80 617 | 6170 DATA 0,&18100 618 | 6180 DATA 0,&30009 619 | 6190 DATA 0,&08085 620 | 6200 DATA 0,&80046 621 | 6210 DATA 0,&60012 622 | 6220 DATA 0,&C0020 623 | 6230 DATA 0,&07FF8 624 | 6240 DATA 0,2,0,3,4,5,6,7,8,9,10 625 | 6250 DATA 11,12,13,14,1,3,0,5,2 626 | 6260 DATA 1,0,7,4,5,6,7,8,3,10,11 627 | 6270 DATA 9,13,14,12,8,1,4,2,6 628 | 6280 REM Cobra MkIII data 629 | 6290 DATA 22,32,13,9 630 | 6300 DATA 6 631 | 6310 DATA -19,-8,0,-19,-4.5,0 632 | 6320 DATA -16,-8,-1,-5,9,0 633 | 6330 DATA -5,-8,2,5,-8,2 634 | 6340 DATA 0,3,-3.5,0,9,0 635 | 6350 DATA 0,12,0,5,9,0 636 | 6360 DATA 0,-8,-2,16,-8,-1 637 | 6370 DATA 19,-4.5,0,19,-8,0 638 | 6380 DATA -5,-8,-1,-2,-8,-1 639 | 6390 DATA -2,-8,1.5,-5,-8,1 640 | 6400 DATA 2,-8,-1,5,-8,-1 641 | 6410 DATA 5,-8,1,2,-8,1.5 642 | 6420 DATA 0,1,2 643 | 6430 DATA 1,3,2 644 | 6440 DATA 2,3,6 645 | 6450 DATA 2,6,10 646 | 6460 DATA 3,9,6 647 | 6470 DATA 10,6,11 648 | 6480 DATA 6,9,11 649 | 6490 DATA 11,9,12 650 | 6500 DATA 11,12,13 651 | 6510 DATA 13,9,5 652 | 6520 DATA 5,3,4 653 | 6530 DATA 4,3,0 654 | 6540 DATA 4,10,5 655 | 6550 DATA &80,&80,&80,&80,&80,&80,&80,&80,&80,&80,&80,&80,&80 656 | 6560 DATA 0,&00000007 657 | 6570 DATA 0,&0000001C 658 | 6580 DATA 0,&000000B0 659 | 6590 DATA 0,&00020420 660 | 6600 DATA 0,&000003C0 661 | 6610 DATA 0,&00040C00 662 | 6620 DATA 0,&00001900 663 | 6630 DATA 0,&00007000 664 | 6640 DATA 0,&0001C000 665 | 6650 DATA 0,&80092000 666 | 6660 DATA 0,&C0100240 667 | 6670 DATA 0,&40200009 668 | 6680 DATA 0,&3FFE8002 669 | 6690 DATA 0,0,1,1,2,2,3,3 670 | 6700 DATA 6,7,10,6,9,9,11,11 671 | 6710 DATA 12,2,11,5,4,0,14,15 672 | 6720 DATA 16,14,18,19,20,18,3,5 673 | 6730 DATA 1,2,2,3,3,6,9,6 674 | 6740 DATA 9,8,6,11,11,12,12,13 675 | 6750 DATA 13,10,10,13,5,4,15,16 676 | 6760 DATA 17,17,19,20,21,21,4,9 677 | 6770 DATA &FF 678 | -------------------------------------------------------------------------------- /basic/3DSolid.txt: -------------------------------------------------------------------------------- 1 | 10 REM RUN WITH PAGE=&3500 2 | 20 MODE 7 3 | 30 PROCassemble 4 | 40 IF P%>&2F03PRINT "Out of memory":END 5 | 50 CALL start 6 | 60 DEF PROCassemble 7 | 70 *LOAD Line5 2F03 8 | 80 *TAPE 9 | 90 linedraw=&2F28 10 | 100 m00lsb=0:m00msb=9 11 | 110 m01lsb=1:m01msb=&A 12 | 120 m02lsb=2:m02msb=&B 13 | 130 m10lsb=3:m10msb=&C 14 | 140 m11lsb=4:m11msb=&D 15 | 150 m12lsb=5:m12msb=&E 16 | 160 m20lsb=6:m20msb=&F 17 | 170 m21lsb=7:m21msb=&10 18 | 180 m22lsb=8:m22msb=&11 19 | 190 adr=&12 20 | 200 xr=&1A 21 | 210 yr=&1C 22 | 220 zr=&1E 23 | 230 product=&20 24 | 240 rx=&22 25 | 250 ry=&23 26 | 260 rz=&24 27 | 270 npts=&30 28 | 280 nlines=&31 29 | 290 nsurfs=&32 30 | 300 maxvis=&33 31 | 310 lhs=&40 32 | 320 rhs=&42 33 | 330 lmul0=&44 34 | 340 lmul1=&46 35 | 350 rmul0=&48 36 | 360 rmul1=&4A 37 | 370 surfs=&50 38 | 380 oldsurfs=&52 39 | 390 surfsdone=&54 40 | 400 visible=&56 41 | 410 lines=&57 42 | 420 line=&59 43 | 430 odr=&61 44 | 440 space=&63 45 | 450 p=&64 46 | 460 pause=&67 47 | 470 x0=&70:y0=&71 48 | 480 x1=&72:y1=&73 49 | 490 scr=&74 50 | 500 err=&76 51 | 510 errs=&77 52 | 520 cnt=&78 53 | 530 ls=&79 54 | 540 dx=&FF 55 | 550 dy=&7A 56 | 560 scrstrt=&7B 57 | 570 c=&7C 58 | 580 FOR pass=0TO 3STEP 3 59 | 590 P%=&1400 60 | 600 [OPTpass 61 | 610 .perspective OPT FNperspective 62 | 620 .ptsdone EQUS STRING$(&40," ") 63 | 630 .sx EQUS STRING$(&40," ") 64 | 640 .sy EQUS STRING$(&40," ") 65 | 650 .slsb OPT FNsintab 66 | 660 .bits EQUD&08040201:EQUD&80402010 67 | 670 EQUD0:EQUD0 68 | 680 EQUD0:EQUD0 69 | 690 EQUD&08040201:EQUD&80402010 70 | 700 .vdus 71 | 710 EQUD&170516:EQUD&200A 72 | 720 EQUD0:EQUB&FF 73 | 730 .start 74 | 740 LDX#0:STXspace:STXp 75 | 750 LDA#1:STApause 76 | 760 .loop 77 | 770 LDAvdus,X:BMInomess:JSR&FFEE 78 | 780 INX:BNEloop 79 | 790 .nomess 80 | 800 SEI:LDA#&40:STA&D00:LDX#&FF:TXS 81 | 810 LDA#0:STArx 82 | 820 LDA#&7B:STAry 83 | 830 LDA#&C3:STArz 84 | 840 CLC 85 | 850 LDA#&F:STAlmul0+1:STArmul0+1 86 | 860 LDA#&12:STAlmul1+1:STArmul1+1 87 | 870 LDA#0:TAX:TAY 88 | 880 STXlhs:STYlhs+1:BCCgo 89 | 890 .loop 90 | 900 TXA:ADClhs:STAlhs:STA(lmul0),Y 91 | 910 LDA#0:ADClhs+1:STAlhs+1:STA(lmul1),Y 92 | 920 INX:.go STYlmul0:STYlmul1 93 | 930 TXA:ADClhs:STAlhs:STA(lmul0),Y 94 | 940 LDA#0:ADClhs+1:STAlhs+1:STA(lmul1),Y 95 | 950 INY:BNEloop 96 | 960 LDX#0:LDY#&FF 97 | 970 .loop 98 | 980 LDA&F01,Y:STA&E00,X 99 | 990 LDA&1201,Y:STA&1100,X 100 | 1000 DEY:INX:BNEloop 101 | 1010 JSRback 102 | 1020 LDA#&35:STAscrstrt 103 | 1030 .frame 104 | 1040 LDA#&81:LDX#&9D:LDY#&FF:JSR&FFF4 105 | 1050 TYA:BEQnopress:LDAspace:BNEnopress 106 | 1060 JSRmodify:LDA#1 107 | 1070 .nopress STAspace 108 | 1080 JSRwipe 109 | 1090 LDA#&81:LDX#&C8:LDY#&FF:JSR&FFF4 110 | 1100 TYA:BEQnop:LDAp:BNEnop 111 | 1110 LDApause:EOR #1:STApause:LDA#1 112 | 1120 .nop STAp 113 | 1130 LDApause:BEQnrot 114 | 1140 JSRrotate:JSRrotate 115 | 1150 .nrot 116 | 1160 JSRmatrix 117 | 1170 JSRnewpoints 118 | 1180 JSRhiddensurfaceremoval 119 | 1190 JSRhiddenlineremoval 120 | 1200 JSRdrawlines 121 | 1210 JSRfill 122 | 1220 JMPframe 123 | 1230 .rotate 124 | 1240 INCrx 125 | 1250 INCry:INCry 126 | 1260 INCrz:INCrz:INCrz 127 | 1270 RTS 128 | 1280 .newpoints 129 | 1290 LDA#0:LDXnpts 130 | 1300 .loop 131 | 1310 STAptsdone,X 132 | 1320 DEX:BPLloop 133 | 1330 RTS 134 | 1340 .wipe LDA#0:LDX#&2F 135 | 1350 .loop 136 | 1360 ]FOR Y%=&3A40 TO &5700 STEP &140 137 | 1370 FOR X%=Y%TO Y%+144STEP 48 138 | 1380 [OPTpass:STAX%,X:]NEXT , 139 | 1390 [OPTpass:DEX:BMIwiped:JMPloop 140 | 1400 .wiped RTS 141 | 1410 .fill SEC:LDX#&B8 142 | 1420 .loop 143 | 1430 LDA&3A40,X 144 | 1440 EOR &3A41,X:STA&5D41,X 145 | 1450 EOR &3A42,X:STA&5D42,X 146 | 1460 EOR &3A43,X:STA&5D43,X 147 | 1470 EOR &3A44,X:STA&5D44,X 148 | 1480 EOR &3A45,X:STA&5D45,X 149 | 1490 EOR &3A46,X:STA&5D46,X 150 | 1500 EOR &3A47,X:STA&5D47,X 151 | 1510 ] 152 | 1520 FOR A%=&5E80 TO &7A00 STEP &140 153 | 1530 [OPTpass 154 | 1540 EOR A%-&2300,X:STAA%,X 155 | 1550 EOR A%-&22FF,X:STAA%+1,X 156 | 1560 EOR A%-&22FE,X:STAA%+2,X 157 | 1570 EOR A%-&22FD,X:STAA%+3,X 158 | 1580 EOR A%-&22FC,X:STAA%+4,X 159 | 1590 EOR A%-&22FB,X:STAA%+5,X 160 | 1600 EOR A%-&22FA,X:STAA%+6,X 161 | 1610 EOR A%-&22F9,X:STAA%+7,X 162 | 1620 ]NEXT 163 | 1630 [OPTpass 164 | 1640 TXA:SBC#8:BCCfilled:TAX:JMPloop 165 | 1650 .filled RTS 166 | 1660 .unitvectors 167 | 1670 EQUBu00 AND &FF:EQUBu01 AND &FF:EQUBu02 AND &FF 168 | 1680 EQUBu10 AND &FF:EQUBu11 AND &FF:EQUBu12 AND &FF 169 | 1690 EQUBu20 AND &FF:EQUBu21 AND &FF:EQUBu22 AND &FF 170 | 1700 EQUBu00 DIV 256:EQUBu01 DIV 256:EQUBu02 DIV 256 171 | 1710 EQUBu10 DIV 256:EQUBu11 DIV 256:EQUBu12 DIV 256 172 | 1720 EQUBu20 DIV 256:EQUBu21 DIV 256:EQUBu22 DIV 256 173 | 1730 .getcoordinates 174 | 1740 LDAptsdone,X:BPLtransform 175 | 1750 LDAsx,X 176 | 1760 LDYsy,X 177 | 1770 RTS 178 | 1780 .transform 179 | 1790 LDA#&FF:STAptsdone,X 180 | 1800 .x LDY&8000,X 181 | 1810 SEC:.u00 182 | 1820 LDA&E00,Y:SBC&E00,Y:STAxr 183 | 1830 LDA&1100,Y:SBC&1100,Y:STAxr+1 184 | 1840 SEC:.u10 185 | 1850 LDA&E00,Y:SBC&E00,Y:STAyr 186 | 1860 LDA&1100,Y:SBC&1100,Y:STAyr+1 187 | 1870 SEC:.u20 188 | 1880 LDA&E00,Y:SBC&E00,Y:STAzr 189 | 1890 LDA&1100,Y:SBC&1100,Y:STAzr+1 190 | 1900 .y LDY&8000,X 191 | 1910 SEC:.u01 192 | 1920 LDA&E00,Y:SBC&E00,Y:STAproduct 193 | 1930 LDA&1100,Y:SBC&1100,Y:STAproduct+1 194 | 1940 LDAproduct:CLC:ADCxr:STAxr 195 | 1950 LDAproduct+1:ADCxr+1:STAxr+1 196 | 1960 SEC:.u11 197 | 1970 LDA&E00,Y:SBC&E00,Y:STAproduct 198 | 1980 LDA&1100,Y:SBC&1100,Y:STAproduct+1 199 | 1990 LDAproduct:CLC:ADCyr:STAyr 200 | 2000 LDAproduct+1:ADCyr+1:STAyr+1 201 | 2010 SEC:.u21 202 | 2020 LDA&E00,Y:SBC&E00,Y:STAproduct 203 | 2030 LDA&1100,Y:SBC&1100,Y:STAproduct+1 204 | 2040 LDAproduct:CLC:ADCzr:STAzr 205 | 2050 LDAproduct+1:ADCzr+1:STAzr+1 206 | 2060 .z LDY&8000,X 207 | 2070 SEC:.u02 208 | 2080 LDA&E00,Y:SBC&E00,Y:STAproduct 209 | 2090 LDA&1100,Y:SBC&1100,Y:STAproduct+1 210 | 2100 LDAproduct:CLC:ADCxr:STAxr 211 | 2110 LDAproduct+1:ADCxr+1:STAxr+1 212 | 2120 SEC:.u12 213 | 2130 LDA&E00,Y:SBC&E00,Y:STAproduct 214 | 2140 LDA&1100,Y:SBC&1100,Y:STAproduct+1 215 | 2150 LDAproduct:CLC:ADCyr:STAyr 216 | 2160 LDAproduct+1:ADCyr+1:STAyr+1 217 | 2170 SEC:.u22 218 | 2180 LDA&E00,Y:SBC&E00,Y:STAproduct 219 | 2190 LDA&1100,Y:SBC&1100,Y:STAproduct+1 220 | 2200 LDAproduct:CLC:ADCzr:STAzr 221 | 2210 LDAproduct+1:ADCzr+1 222 | 2220 ASLzr:ROLA:ASLzr 223 | 2230 ADC#&80:TAY:CLC 224 | 2240 LDA#&80:ADCperspective,Y:STAadr:STAadr+2 225 | 2250 LDA#&E:ADC#0:STAadr+1:ADC#3:STAadr+3 226 | 2260 LDAadr:ADC#1:STAadr+4:STAadr+6 227 | 2270 LDAadr+1:ADC#0:STAadr+5:ADC#3:STAadr+7 228 | 2280 LDAyr+1:ASLyr:ROLA:ASLyr 229 | 2290 ADC#&80:TAY:SEC:EOR #&FF:STYzr:STAzr+1 230 | 2300 LDA(adr),Y:LDYzr+1:SBC(adr+4),Y:STAyr 231 | 2310 LDYzr:LDA(adr+2),Y:LDYzr+1:SBC(adr+6),Y 232 | 2320 ASLyr:ADC#&80:STAsy,X 233 | 2330 LDAxr+1:ASLxr:ROLA:ASLxr 234 | 2340 ADC#&80:TAY:SEC:EOR #&FF:STYzr:STAzr+1 235 | 2350 LDA(adr),Y:LDYzr+1:SBC(adr+4),Y:STAxr 236 | 2360 LDYzr:LDA(adr+2),Y:LDYzr+1:SBC(adr+6),Y 237 | 2370 ASLxr:ADC#&80:STAsx,X 238 | 2380 LDYsy,X 239 | 2390 RTS 240 | 2400 .matrix 241 | 2410 LDYrx:SEC 242 | 2420 LDA#0:SBCslsb,Y:STAm12lsb 243 | 2430 LDA#0:SBCsmsb,Y:ASLm12lsb 244 | 2440 ROLA:ASLm12lsb:ROLA:STAm12msb 245 | 2450 TYA:SEC:SBCry 246 | 2460 TAX:CLC:ADCrz:STAadr+3 247 | 2470 TYA:CLC:ADCry 248 | 2480 TAY:CLC:ADCrz:STAadr+2:SEC 249 | 2490 LDAslsb,X:SBCslsb,Y:STAm02lsb 250 | 2500 LDAsmsb,X:SBCsmsb,Y:ASLm02lsb 251 | 2510 ROLA:STAm02msb:CLC 252 | 2520 LDAclsb,Y:ADCclsb,X:STAm22lsb 253 | 2530 LDAcmsb,Y:ADCcmsb,X:ASLm22lsb 254 | 2540 ROLA:STAm22msb 255 | 2550 TYA:SEC:SBCrz:STAadr+4 256 | 2560 TXA:SEC:SBCrz:STAadr+5 257 | 2570 LDArx:CLC:ADCrz:TAY 258 | 2580 LDArx:SEC:SBCrz:TAX:SEC 259 | 2590 LDAslsb,Y:SBCslsb,X:STAm10lsb 260 | 2600 LDAsmsb,Y:SBCsmsb,X:ASLm10lsb 261 | 2610 ROLA:STAm10msb:CLC 262 | 2620 LDAclsb,X:ADCclsb,Y:STAm11lsb 263 | 2630 LDAcmsb,Y:ADCcmsb,X:ASLm11lsb 264 | 2640 ROLA:STAm11msb 265 | 2650 LDAry:SEC:SBCrz:TAY 266 | 2660 LDArz:CLC:ADCry:TAX:SEC 267 | 2670 LDAclsb,X:SBCclsb,Y:STAm21lsb 268 | 2680 LDAcmsb,X:SBCcmsb,Y:ASLm21lsb 269 | 2690 ROLA:STAm21msb:SEC 270 | 2700 LDAslsb,Y:SBCslsb,X:STAm01lsb 271 | 2710 LDAsmsb,Y:SBCsmsb,X:ASLm01lsb 272 | 2720 ROLA:STAm01msb:CLC 273 | 2730 LDAclsb,Y:ADCclsb,X:STAm00lsb 274 | 2740 LDAcmsb,X:ADCcmsb,Y:ASLm00lsb 275 | 2750 ROLA:STAm00msb:CLC 276 | 2760 LDAslsb,X:ADCslsb,Y:STAm20lsb 277 | 2770 LDAsmsb,Y:ADCsmsb,X:ASLm20lsb 278 | 2780 ROLA:STAm20msb 279 | 2790 LDYadr+4:LDXadr+3:SEC 280 | 2800 LDAm00lsb:SBCslsb,X:STAm00lsb 281 | 2810 LDAm00msb:SBCsmsb,X:STAm00msb:CLC 282 | 2820 LDAslsb,Y:ADCm21lsb:STAm21lsb 283 | 2830 LDAm21msb:ADCsmsb,Y:STAm21msb:CLC 284 | 2840 LDAclsb,Y:ADCm20lsb:STAm20lsb 285 | 2850 LDAcmsb,Y:ADCm20msb:STAm20msb:SEC 286 | 2860 LDAm01lsb:SBCclsb,X:STAm01lsb 287 | 2870 LDAm01msb:SBCcmsb,X:STAm01msb:CLC 288 | 2880 LDAclsb,Y:ADCm01lsb:STAm01lsb 289 | 2890 LDAcmsb,Y:ADCm01msb:STAm01msb:CLC 290 | 2900 LDAm21lsb:ADCslsb,X:STAm21lsb 291 | 2910 LDAm21msb:ADCsmsb,X:STAm21msb:SEC 292 | 2920 LDAm20lsb:SBCclsb,X:STAm20lsb 293 | 2930 LDAm20msb:SBCcmsb,X:STAm20msb:SEC 294 | 2940 LDAm00lsb:SBCslsb,Y:STAm00lsb 295 | 2950 LDAm00msb:SBCsmsb,Y:STAm00msb 296 | 2960 LDXadr+5:LDYadr+2:SEC 297 | 2970 LDAm20lsb:SBCclsb,Y:STAm20lsb 298 | 2980 LDAm20msb:SBCcmsb,Y:STAm20msb:CLC 299 | 2990 LDAm00lsb:ADCslsb,X:STAm00lsb 300 | 3000 LDAm00msb:ADCsmsb,X:STAm00msb:CLC 301 | 3010 LDAm21lsb:ADCslsb,X:STAm21lsb 302 | 3020 LDAm21msb:ADCsmsb,X:STAm21msb:CLC 303 | 3030 LDAclsb,Y:ADCm01lsb:STAm01lsb 304 | 3040 LDAcmsb,Y:ADCm01msb:STAm01msb:CLC 305 | 3050 LDAslsb,Y:ADCm21lsb:STAm21lsb 306 | 3060 LDAsmsb,Y:ADCm21msb:STAm21msb:CLC 307 | 3070 LDAslsb,Y:ADCm00lsb:STAm00lsb 308 | 3080 LDAsmsb,Y:ADCm00msb:STAm00msb:CLC 309 | 3090 LDAclsb,X:ADCm20lsb:STAm20lsb 310 | 3100 LDAcmsb,X:ADCm20msb:STAm20msb:SEC 311 | 3110 LDAm01lsb:SBCclsb,X:STAm01lsb 312 | 3120 LDAm01msb:SBCcmsb,X:STAm01msb 313 | 3130 LDX#8 314 | 3140 .loop 315 | 3150 LDAunitvectors,X:STAadr 316 | 3160 LDAunitvectors+9,X:STAadr+1 317 | 3170 LDAm00msb,X:ASLm00lsb,X:ADC#&80 318 | 3180 LDY#1:STA(adr),Y:LDY#9:STA(adr),Y 319 | 3190 CLC:EOR #&FF:ADC#1 320 | 3200 LDY#4:STA(adr),Y:LDY#&C:STA(adr),Y 321 | 3210 DEX:BPLloop 322 | 3220 RTS 323 | 3230 .hiddensurfaceremoval 324 | 3240 LDA#0:STAvisible 325 | 3250 LDAoldsurfs:EOR #&FF:STAsurfsdone 326 | 3260 LDAoldsurfs+1:EOR #&FF:STAsurfsdone+1 327 | 3270 LDA#&F:SEC:SBCnsurfs:BEQnloop 328 | 3280 TAY:LDAoldsurfs 329 | 3290 .loop 330 | 3300 ASLA:ROLoldsurfs+1:DEY:BNEloop 331 | 3310 STAoldsurfs:.nloop 332 | 3320 LDYnsurfs 333 | 3330 .loop 334 | 3340 ASLoldsurfs:ROLoldsurfs+1 335 | 3350 BCShidesurface 336 | 3360 JSRclockwisetest:BCShidesurface 337 | 3370 TYA:ASLA:TAX 338 | 3380 .opposite0 LDA&8000,X:INX 339 | 3390 ORAsurfsdone:STAsurfsdone 340 | 3400 .opposite1 LDA&8000,X 341 | 3410 ORAsurfsdone+1:STAsurfsdone+1 342 | 3420 INCvisible 343 | 3430 .hidesurface 344 | 3440 ROLsurfs:ROLsurfs+1 345 | 3450 DEY:BPLloop 346 | 3460 LDYnsurfs 347 | 3470 LDAbits,Y:STAoldsurfs 348 | 3480 LDAbits+16,Y:STAoldsurfs+1 349 | 3490 .loop 350 | 3500 LDXvisible:CPXmaxvis:BEQdoneit 351 | 3510 LDAsurfsdone:AND oldsurfs:BNEsurfdone 352 | 3520 LDAsurfsdone+1:AND oldsurfs+1:BNEsurfdone 353 | 3530 JSRclockwisetest:BCSsurfdone 354 | 3540 LDAoldsurfs:EOR #&FF:AND surfs:STAsurfs 355 | 3550 LDAoldsurfs+1:EOR #&FF:AND surfs+1:STAsurfs+1 356 | 3560 TYA:ASLA:TAX 357 | 3570 .opposite2 LDA&8000,X:INX 358 | 3580 ORAsurfsdone:STAsurfsdone 359 | 3590 .opposite3 LDA&8000,X 360 | 3600 ORAsurfsdone+1:STAsurfsdone+1 361 | 3610 INCvisible 362 | 3620 .surfdone 363 | 3630 LSRoldsurfs+1:RORoldsurfs 364 | 3640 DEY:BPLloop 365 | 3650 .doneit 366 | 3660 LDAsurfs:STAoldsurfs 367 | 3670 LDAsurfs+1:STAoldsurfs+1 368 | 3680 RTS 369 | 3690 .clockwisetest STYls 370 | 3700 .clock0 LDX&8000,Y 371 | 3710 JSRgetcoordinates 372 | 3720 STAx0:STYy0:LDYls 373 | 3730 .clock1 LDX&8000,Y 374 | 3740 JSRgetcoordinates 375 | 3750 STAx1:STYy1:LDYls 376 | 3760 .clock2 LDX&8000,Y 377 | 3770 JSRgetcoordinates 378 | 3780 SEC:LDX#0 379 | 3790 SBCx0:BCSx20p 380 | 3800 SBC#0:EOR #&FF:INX 381 | 3810 .x20p STAlmul0 382 | 3820 LDAy1:SBCy0:BCSy10p 383 | 3830 SBC#0:EOR #&FF:DEX 384 | 3840 .y10p STAlmul1 385 | 3850 TYA:LDY#0 386 | 3860 SBCy0:BCSy20p 387 | 3870 SBC#0:EOR #&FF:INY 388 | 3880 .y20p STArmul0 389 | 3890 LDAx1:SBCx0:BCSx10p 390 | 3900 SBC#0:EOR #&FF:DEY 391 | 3910 .x10p STArmul1:STXcnt 392 | 3920 CPX#1:TYA 393 | 3930 EOR cnt:AND #1:BEQcompare 394 | 3940 LDYls:RTS 395 | 3950 .compare BCCbothpos 396 | 3960 JSRmultiply 397 | 3970 LDYlhs:CPYrhs 398 | 3980 LDAlhs+1:SBCrhs+1 399 | 3990 LDYls:RTS 400 | 4000 .bothpos SEC 401 | 4010 JSRmultiply 402 | 4020 LDYrhs:CPYlhs 403 | 4030 LDArhs+1:SBClhs+1 404 | 4040 LDYls:RTS 405 | 4050 .multiply 406 | 4060 LDYlmul1:TYA 407 | 4070 LDXlmul0:STXlmul1 408 | 4080 SBClmul0:BCSmabsl 409 | 4090 SBC#0:EOR #&FF 410 | 4100 .mabsl TAX 411 | 4110 LDA(lmul0),Y:SBC&F00,X:STAlhs 412 | 4120 LDA(lmul1),Y:SBC&1200,X:STAlhs+1 413 | 4130 LDYrmul1:TYA 414 | 4140 LDXrmul0:STXrmul1 415 | 4150 SBCrmul0:BCSmabsr 416 | 4160 SBC#0:EOR #&FF 417 | 4170 .mabsr TAX 418 | 4180 LDA(rmul0),Y:SBC&F00,X:STArhs 419 | 4190 LDA(rmul1),Y:SBC&1200,X:STArhs+1 420 | 4200 RTS 421 | 4210 .hiddenlineremoval 422 | 4220 LDXnsurfs:LDY#0 423 | 4230 STYline 424 | 4240 STYline+1 425 | 4250 STYline+2 426 | 4260 STYline+3 427 | 4270 STYline+4 428 | 4280 STYline+5 429 | 4290 STYline+6 430 | 4300 STYline+7 431 | 4310 .loop 432 | 4320 LSRsurfs+1:RORsurfs:BCSnosurf 433 | 4330 LDA(lines),Y:EOR line:STAline:INY 434 | 4340 LDA(lines),Y:EOR line+1:STAline+1:INY 435 | 4350 LDA(lines),Y:EOR line+2:STAline+2:INY 436 | 4360 LDA(lines),Y:EOR line+3:STAline+3:INY 437 | 4370 LDA(lines),Y:EOR line+4:STAline+4:INY 438 | 4380 LDA(lines),Y:EOR line+5:STAline+5:INY 439 | 4390 LDA(lines),Y:EOR line+6:STAline+6:INY 440 | 4400 LDA(lines),Y:EOR line+7:STAline+7:INY 441 | 4410 DEX:BPLloop:RTS 442 | 4420 .nosurf TYA:ADC#7:TAY 443 | 4430 DEX:BPLloop:RTS 444 | 4440 .drawlines 445 | 4450 LDA#0:STAlhs+1 446 | 4460 LDAnlines:STAlhs 447 | 4470 .loop 448 | 4480 LDAline:AND #3:BEQnoline:PHA 449 | 4490 LDYlhs+1 450 | 4500 .linestarts LDA&8000,Y:PHA 451 | 4510 .lineends LDA&8000,Y:TAX 452 | 4520 JSRgetcoordinates 453 | 4530 STAx0:STYy0 454 | 4540 PLA:TAX 455 | 4550 JSRgetcoordinates 456 | 4560 STAx1:STYy1 457 | 4570 PLA:TAX:JSRlinedraw 458 | 4580 .noline 459 | 4590 LSRline+7 460 | 4600 RORline+6 461 | 4610 RORline+5 462 | 4620 RORline+4 463 | 4630 RORline+3 464 | 4640 RORline+2 465 | 4650 RORline+1 466 | 4660 RORline 467 | 4670 LSRline+7 468 | 4680 RORline+6 469 | 4690 RORline+5 470 | 4700 RORline+4 471 | 4710 RORline+3 472 | 4720 RORline+2 473 | 4730 RORline+1 474 | 4740 RORline 475 | 4750 INClhs+1:DEClhs:BPLloop 476 | 4760 RTS 477 | 4770 .back LDA#coordinates AND &FF:STAodr 478 | 4780 LDA#coordinates DIV 256:STAodr+1 479 | 4790 .modify 480 | 4800 LDA#&FF:STAoldsurfs:STAoldsurfs+1 481 | 4810 LDY#0 482 | 4820 LDA(odr),Y:BMIback:STAnpts:INY 483 | 4830 LDA(odr),Y:STAnlines:INY 484 | 4840 LDA(odr),Y:STAnsurfs:INY 485 | 4850 LDA(odr),Y:STAmaxvis 486 | 4860 LDAodr:SEC:ADC#3:STAodr:STAx+1 487 | 4870 LDAodr+1:ADC#0:STAodr+1:STAx+2 488 | 4880 LDAodr:SEC:ADCnpts:STAodr:STAy+1 489 | 4890 LDAodr+1:ADC#0:STAodr+1:STAy+2 490 | 4900 LDAodr:SEC:ADCnpts:STAodr:STAz+1 491 | 4910 LDAodr+1:ADC#0:STAodr+1:STAz+2 492 | 4920 LDAodr:SEC:ADCnpts:STAodr:STAclock0+1 493 | 4930 LDAodr+1:ADC#0:STAodr+1:STAclock0+2 494 | 4940 LDAodr:SEC:ADCnsurfs:STAodr:STAclock1+1 495 | 4950 LDAodr+1:ADC#0:STAodr+1:STAclock1+2 496 | 4960 LDAodr:SEC:ADCnsurfs:STAodr:STAclock2+1 497 | 4970 LDAodr+1:ADC#0:STAodr+1:STAclock2+2 498 | 4980 LDAodr:SEC:ADCnsurfs:STAodr:STAopposite0+1:STAopposite1+1:STAopposite2+1:STAopposite3+1 499 | 4990 LDAodr+1:ADC#0:STAodr+1:STAopposite0+2:STAopposite1+2:STAopposite2+2:STAopposite3+2 500 | 5000 LDAodr:SEC:ADCnsurfs:STAodr 501 | 5010 LDAodr+1:ADC#0:STAodr+1 502 | 5020 LDAodr:SEC:ADCnsurfs:STAodr:STAlines 503 | 5030 LDAodr+1:ADC#0:STAodr+1:STAlines+1 504 | 5040 LDY#7 505 | 5050 .loop 506 | 5060 LDAodr:SEC:ADCnsurfs:STAodr 507 | 5070 LDAodr+1:ADC#0:STAodr+1 508 | 5080 DEY:BPLloop 509 | 5090 LDAodr:STAlinestarts+1:SEC:ADCnlines:STAodr:STAlineends+1 510 | 5100 LDAodr+1:STAlinestarts+2:ADC#0:STAodr+1:STAlineends+2 511 | 5110 LDAodr:SEC:ADCnlines:STAodr 512 | 5120 LDAodr+1:ADC#0:STAodr+1 513 | 5130 RTS 514 | 5140 .coordinates OPT FNreaddata 515 | 5150 ] 516 | 5160 clsb=slsb+&40 517 | 5170 smsb=slsb+&140 518 | 5180 cmsb=clsb+&140 519 | 5190 NEXT 520 | 5200 ENDPROC 521 | 5210 DEF FNperspective 522 | 5220 IF pass<2P%=P%+&100:=pass 523 | 5230 d=&100 524 | 5240 oz=&80 525 | 5250 FOR Z%=-128TO 127 526 | 5260 ?P%=&FF*d/(d+oz+Z%)+.5 527 | 5270 P%=P%+1 528 | 5280 NEXT 529 | 5290 =pass 530 | 5300 DEF FNsintab 531 | 5310 IF pass<2P%=P%+&280:=pass 532 | 5320 FOR A%=0TO &13F 533 | 5330 S%=&1FA0*SIN (A%*2*PI /256)+.5 534 | 5340 ?P%=S%AND &FF 535 | 5350 P%?&140=(S%AND &FF00)DIV 256 536 | 5360 P%=P%+1 537 | 5370 NEXT 538 | 5380 P%=P%+&140 539 | 5390 =pass 540 | 5400 DEF FNreaddata 541 | 5410 RESTORE 5840 542 | 5420 READ NPTS%:IF NPTS%=&FF ?P%=&FF:P%=P%+1:=pass 543 | 5430 READ NLINES%,NSURFS%,MAXVIS%,SCALE% 544 | 5440 ?P%=NPTS%-1:P%=P%+1 545 | 5450 ?P%=NLINES%-1:P%=P%+1 546 | 5460 ?P%=NSURFS%-1:P%=P%+1 547 | 5470 ?P%=MAXVIS%:P%=P%+1 548 | 5480 FOR I%=1TO NPTS% 549 | 5490 READ X%,Y%,Z% 550 | 5500 ?P%=SCALE%*X%+128 551 | 5510 ?(P%+NPTS%)=SCALE%*Y%+128 552 | 5520 ?(P%+2*NPTS%)=SCALE%*Z%+128 553 | 5530 P%=P%+1 554 | 5540 NEXT 555 | 5550 P%=P%+2*NPTS% 556 | 5560 FOR I%=1TO NSURFS% 557 | 5570 READ C1%,C2%,C3% 558 | 5580 ?P%=C1% 559 | 5590 ?(P%+NSURFS%)=C2% 560 | 5600 ?(P%+2*NSURFS%)=C3% 561 | 5610 P%=P%+1 562 | 5620 NEXT 563 | 5630 P%=P%+2*NSURFS% 564 | 5640 FOR I%=1TO NSURFS% 565 | 5650 READ OPPS% 566 | 5660 IF OPPS%>&7FS%=0ELSE S%=2^OPPS% 567 | 5670 ?P%=S%AND &FF 568 | 5680 ?(P%+1)=S%DIV 256 569 | 5690 P%=P%+2 570 | 5700 NEXT 571 | 5710 FOR I%=1TO NSURFS% 572 | 5720 READ LIN1%,LIN2% 573 | 5730 !P%=LIN2% 574 | 5740 !(P%+4)=LIN1% 575 | 5750 P%=P%+8 576 | 5760 NEXT 577 | 5770 FOR I%=1TO 2*NLINES% 578 | 5780 READ PT% 579 | 5790 ?P%=PT% 580 | 5800 P%=P%+1 581 | 5810 NEXT 582 | 5820 GOTO 5420 583 | 5830 REM Cube data 584 | 5840 DATA 8,12,6,3 585 | 5850 DATA 1 586 | 5860 DATA +50,+50,+50 587 | 5870 DATA +50,+50,-50 588 | 5880 DATA +50,-50,+50 589 | 5890 DATA +50,-50,-50 590 | 5900 DATA -50,+50,+50 591 | 5910 DATA -50,+50,-50 592 | 5920 DATA -50,-50,+50 593 | 5930 DATA -50,-50,-50 594 | 5940 DATA 4,6,0 595 | 5950 DATA 5,7,4 596 | 5960 DATA 1,4,0 597 | 5970 DATA 3,1,0 598 | 5980 DATA 3,2,6 599 | 5990 DATA 7,1,3 600 | 6000 DATA 5,3,4,1,2,0 601 | 6010 DATA 0,&150001 602 | 6020 DATA 0,&022820 603 | 6030 DATA 0,&0000FF 604 | 6040 DATA 0,&880208 605 | 6050 DATA 0,&F0F000 606 | 6060 DATA 0,&004540 607 | 6070 DATA 0,1,4,1,1,5,6,3,4,0,2,2 608 | 6080 DATA 4,0,5,5,3,7,7,7,6,2,6,3 609 | 6090 REM Viper data 610 | 6100 DATA 15,20,7,5 611 | 6110 DATA 4 612 | 6120 DATA 0,19,0,0,1,-6 613 | 6130 DATA 0,1,6,-10,-19,-6 614 | 6140 DATA -19,-19,0,-10,-19,6 615 | 6150 DATA 10,-19,6,19,-19,0 616 | 6160 DATA 10,-19,-6,-3,-19,-4 617 | 6170 DATA -12,-19,0,-3,-19,4 618 | 6180 DATA 3,-19,-4,3,-19,4 619 | 6190 DATA 12,-19,0 620 | 6200 DATA 1,8,3 621 | 6210 DATA 0,1,3 622 | 6220 DATA 0,8,1 623 | 6230 DATA 0,2,6 624 | 6240 DATA 0,5,2 625 | 6250 DATA 2,5,6 626 | 6260 DATA 6,3,8 627 | 6270 DATA 5,&80,&80,&80,&80,0,&80 628 | 6280 DATA &01,&40010000 629 | 6290 DATA &0A,&00000082 630 | 6300 DATA &00,&C000C033 631 | 6310 DATA &80,&00002028 632 | 6320 DATA &3C,&0000030C 633 | 6330 DATA &50,&00000400 634 | 6340 DATA &00,&3FFFFFC0 635 | 6350 DATA 0,2,0,3,4,5,6,7,8,9,10 636 | 6360 DATA 11,12,13,14,1,3,0,5,2 637 | 6370 DATA 1,0,7,4,5,6,7,8,3,10,11 638 | 6380 DATA 9,13,14,12,8,1,4,2,6 639 | 6390 REM Cobra MkIII data 640 | 6400 DATA 22,32,13,9 641 | 6410 DATA 6 642 | 6420 DATA -19,-8,0,-19,-4.5,0 643 | 6430 DATA -16,-8,-1,-5,9,0 644 | 6440 DATA -5,-8,2,5,-8,2 645 | 6450 DATA 0,3,-3.5,0,9,0 646 | 6460 DATA 0,12,0,5,9,0 647 | 6470 DATA 0,-8,-2,16,-8,-1 648 | 6480 DATA 19,-4.5,0,19,-8,0 649 | 6490 DATA -5,-8,-1,-2,-8,-1 650 | 6500 DATA -2,-8,1.5,-5,-8,1 651 | 6510 DATA 2,-8,-1,5,-8,-1 652 | 6520 DATA 5,-8,1,2,-8,1.5 653 | 6530 DATA 0,1,2 654 | 6540 DATA 1,3,2 655 | 6550 DATA 2,3,6 656 | 6560 DATA 2,6,10 657 | 6570 DATA 3,9,6 658 | 6580 DATA 10,6,11 659 | 6590 DATA 6,9,11 660 | 6600 DATA 11,9,12 661 | 6610 DATA 11,12,13 662 | 6620 DATA 13,9,5 663 | 6630 DATA 5,3,4 664 | 6640 DATA 4,3,0 665 | 6650 DATA 4,10,5 666 | 6660 DATA &80,&80,&80,&80,&80,&80,&80,&80,&80,&80,&80,&80,&80 667 | 6670 DATA 0,&15 668 | 6680 DATA 0,&02A0 669 | 6690 DATA 0,&4500 670 | 6700 DATA &08,&00200800 671 | 6710 DATA 0,&03F000 672 | 6720 DATA &20,&00A00000 673 | 6730 DATA 0,&01410000 674 | 6740 DATA 0,&2A000000 675 | 6750 DATA &01,&50000000 676 | 6760 DATA &C00000C3,&0C000000 677 | 6770 DATA &A0000200,&00002000 678 | 6780 DATA &30000C00,&000000C3 679 | 6790 DATA &0FFFFFFC,&C000000C 680 | 6800 DATA 0,0,1,1,2,2,3,3 681 | 6810 DATA 6,7,10,6,9,9,11,11 682 | 6820 DATA 12,2,11,5,4,0,14,15 683 | 6830 DATA 16,14,18,19,20,18,3,5 684 | 6840 DATA 1,2,2,3,3,6,9,6 685 | 6850 DATA 9,8,6,11,11,12,12,13 686 | 6860 DATA 13,10,10,13,5,4,15,16 687 | 6870 DATA 17,17,19,20,21,21,4,9 688 | 6880 DATA &FF 689 | -------------------------------------------------------------------------------- /basic/Polyhed.txt: -------------------------------------------------------------------------------- 1 | 10 REM RUN WITH PAGE=&3000 2 | 20 MODE 7 3 | 30 PROCassemble 4 | 40 IF P%>&26BAPRINT "Out of memory":END 5 | 50 CALL start 6 | 60 DEF PROCassemble 7 | 70 *LOAD Line3D 26BA 8 | 80 *TAPE 9 | 90 linedraw=&26FA 10 | 100 m00lsb=0:m00msb=9 11 | 110 m01lsb=1:m01msb=&A 12 | 120 m02lsb=2:m02msb=&B 13 | 130 m10lsb=3:m10msb=&C 14 | 140 m11lsb=4:m11msb=&D 15 | 150 m12lsb=5:m12msb=&E 16 | 160 m20lsb=6:m20msb=&F 17 | 170 m21lsb=7:m21msb=&10 18 | 180 m22lsb=8:m22msb=&11 19 | 190 adr=&12 20 | 200 xr=&1A 21 | 210 yr=&1C 22 | 220 zr=&1E 23 | 230 product=&20 24 | 240 rx=&22 25 | 250 ry=&23 26 | 260 rz=&24 27 | 270 npts=&30 28 | 280 nlines=&31 29 | 290 nsurfs=&32 30 | 300 maxvis=&33 31 | 310 lhs=&40 32 | 320 rhs=&42 33 | 330 lmul0=&44 34 | 340 lmul1=&46 35 | 350 rmul0=&48 36 | 360 rmul1=&4A 37 | 370 surfs=&50 38 | 380 oldsurfs=&52 39 | 390 surfsdone=&54 40 | 400 visible=&56 41 | 410 lines=&57 42 | 420 line=&59 43 | 430 odr=&61 44 | 440 space=&63 45 | 450 p=&64 46 | 460 f=&65 47 | 470 flicker=&66 48 | 480 pause=&67 49 | 490 x0=&70:y0=&71 50 | 500 x1=&72:y1=&73 51 | 510 scr=&74 52 | 520 err=&76 53 | 530 errs=&77 54 | 540 cnt=&78 55 | 550 ls=&79 56 | 560 dx=&FF 57 | 570 dy=&7A 58 | 580 scrstrt=&7B 59 | 590 FOR pass=0TO 3STEP 3 60 | 600 P%=&1400 61 | 610 [OPTpass 62 | 620 .perspective OPT FNperspective 63 | 630 .ptsdone EQUS STRING$(&40," ") 64 | 640 .sx EQUS STRING$(&40," ") 65 | 650 .sy EQUS STRING$(&40," ") 66 | 660 .slsb OPT FNsintab 67 | 670 .bits EQUD&08040201:EQUD&80402010 68 | 680 EQUD0:EQUD0 69 | 690 EQUD0:EQUD0 70 | 700 EQUD&08040201:EQUD&80402010 71 | 710 .vdus 72 | 720 EQUD&170416:EQUD&200A 73 | 730 EQUD0:EQUB&FF 74 | 740 .start 75 | 750 LDX#0:STXadr:STXspace:STXf:STXp:STXflicker 76 | 760 LDA#1:STApause 77 | 770 .loop 78 | 780 LDAvdus,X:BMIcls:JSR&FFEE 79 | 790 INX:BNEloop 80 | 800 .cls 81 | 810 LDA#&30:STAadr+1:LDY#0:TYA 82 | 820 .loop 83 | 830 STA(adr),Y:INY:BNEloop 84 | 840 INCadr+1:BPLloop 85 | 850 SEI:LDA#&40:STA&D00:LDX#&FF:TXS 86 | 860 LDA#0:STArx 87 | 870 LDA#&7B:STAry 88 | 880 LDA#&C3:STArz 89 | 890 CLC 90 | 900 LDA#&F:STAlmul0+1:STArmul0+1 91 | 910 LDA#&12:STAlmul1+1:STArmul1+1 92 | 920 LDA#0:TAX:TAY 93 | 930 STXlhs:STYlhs+1:BCCgo 94 | 940 .loop 95 | 950 TXA:ADClhs:STAlhs:STA(lmul0),Y 96 | 960 LDA#0:ADClhs+1:STAlhs+1:STA(lmul1),Y 97 | 970 INX:.go STYlmul0:STYlmul1 98 | 980 TXA:ADClhs:STAlhs:STA(lmul0),Y 99 | 990 LDA#0:ADClhs+1:STAlhs+1:STA(lmul1),Y 100 | 1000 INY:BNEloop 101 | 1010 LDX#0:LDY#&FF 102 | 1020 .loop 103 | 1030 LDA&F01,Y:STA&E00,X 104 | 1040 LDA&1201,Y:STA&1100,X 105 | 1050 DEY:INX:BNEloop 106 | 1060 JSRback 107 | 1070 LDA#&58:STAscrstrt 108 | 1080 .frame 109 | 1090 LDA#&81:LDX#&9D:LDY#&FF:JSR&FFF4 110 | 1100 TYA:BEQnopress:LDAspace:BNEnopress 111 | 1110 JSRmodify:LDA#1 112 | 1120 .nopress STAspace 113 | 1130 LDAscrstrt:LSRA:LSRA:LSRA 114 | 1140 LDX#&C:STX&FE00:STA&FE01 115 | 1150 LDA#&81:LDX#&BC:LDY#&FF:JSR&FFF4 116 | 1160 TYA:BEQnof:LDAf:BNEnof 117 | 1170 LDAflicker:EOR #1:STAflicker:LDA#1 118 | 1180 .nof STAf 119 | 1190 LDAflicker:AND pause:BNEfastandflicker 120 | 1200 CLI:LDA#19:JSR&FFF4:SEI 121 | 1210 .fastandflicker 122 | 1220 LDAscrstrt:EOR #&68:STAscrstrt 123 | 1230 JSRwipe 124 | 1240 LDA#&81:LDX#&C8:LDY#&FF:JSR&FFF4 125 | 1250 TYA:BEQnop:LDAp:BNEnop 126 | 1260 LDApause:EOR #1:STApause:LDA#1 127 | 1270 .nop STAp 128 | 1280 LDApause:BEQnrot 129 | 1290 JSRrotate 130 | 1300 .nrot 131 | 1310 JSRmatrix 132 | 1320 JSRnewpoints 133 | 1340 JSRhiddenlineremoval 134 | 1350 JSRdrawlines 135 | 1360 JMPframe 136 | 1370 .rotate 137 | 1380 INCrx 138 | 1390 INCry:INCry 139 | 1400 INCrz:INCrz:INCrz 140 | 1410 RTS 141 | 1420 .newpoints 142 | 1430 LDA#0:LDXnpts 143 | 1440 .loop 144 | 1450 STAptsdone,X 145 | 1460 DEX:BPLloop 146 | 1470 RTS 147 | 1480 .wipe 148 | 1490 LDX#&2F:CMP#&30:BNEwipe0:JMPwipe1 149 | 1500 .wipe0 LDA#0 150 | 1510 .loop 151 | 1520 ]FOR Y%=&5D40 TO &7A00 STEP &140 152 | 1530 FOR X%=Y%TO Y%+144STEP 48 153 | 1540 [OPTpass:STAX%,X:]NEXT , 154 | 1550 [OPTpass:DEX:BMIwiped:JMPloop 155 | 1560 .wiped RTS 156 | 1570 .wipe1 LDA#0 157 | 1580 .loop 158 | 1590 ]FOR Y%=&3540TO &5200STEP &140 159 | 1600 FOR X%=Y%TO Y%+144STEP 48 160 | 1610 [OPTpass:STAX%,X:]NEXT , 161 | 1620 [OPTpass:DEX:BMIwiped1:JMPloop 162 | 1630 .wiped1 RTS 163 | 1640 .unitvectors 164 | 1650 EQUBu00 AND &FF:EQUBu01 AND &FF:EQUBu02 AND &FF 165 | 1660 EQUBu10 AND &FF:EQUBu11 AND &FF:EQUBu12 AND &FF 166 | 1670 EQUBu20 AND &FF:EQUBu21 AND &FF:EQUBu22 AND &FF 167 | 1680 EQUBu00 DIV 256:EQUBu01 DIV 256:EQUBu02 DIV 256 168 | 1690 EQUBu10 DIV 256:EQUBu11 DIV 256:EQUBu12 DIV 256 169 | 1700 EQUBu20 DIV 256:EQUBu21 DIV 256:EQUBu22 DIV 256 170 | 1710 .getcoordinates 171 | 1720 LDAptsdone,X:BPLtransform 172 | 1730 LDAsx,X 173 | 1740 LDYsy,X 174 | 1750 RTS 175 | 1760 .transform 176 | 1770 LDA#&FF:STAptsdone,X 177 | 1780 .x LDY&8000,X 178 | 1790 SEC:.u00 179 | 1800 LDA&E00,Y:SBC&E00,Y:STAxr 180 | 1810 LDA&1100,Y:SBC&1100,Y:STAxr+1 181 | 1820 SEC:.u10 182 | 1830 LDA&E00,Y:SBC&E00,Y:STAyr 183 | 1840 LDA&1100,Y:SBC&1100,Y:STAyr+1 184 | 1850 SEC:.u20 185 | 1860 LDA&E00,Y:SBC&E00,Y:STAzr 186 | 1870 LDA&1100,Y:SBC&1100,Y:STAzr+1 187 | 1880 .y LDY&8000,X 188 | 1890 SEC:.u01 189 | 1900 LDA&E00,Y:SBC&E00,Y:STAproduct 190 | 1910 LDA&1100,Y:SBC&1100,Y:STAproduct+1 191 | 1920 LDAproduct:CLC:ADCxr:STAxr 192 | 1930 LDAproduct+1:ADCxr+1:STAxr+1 193 | 1940 SEC:.u11 194 | 1950 LDA&E00,Y:SBC&E00,Y:STAproduct 195 | 1960 LDA&1100,Y:SBC&1100,Y:STAproduct+1 196 | 1970 LDAproduct:CLC:ADCyr:STAyr 197 | 1980 LDAproduct+1:ADCyr+1:STAyr+1 198 | 1990 SEC:.u21 199 | 2000 LDA&E00,Y:SBC&E00,Y:STAproduct 200 | 2010 LDA&1100,Y:SBC&1100,Y:STAproduct+1 201 | 2020 LDAproduct:CLC:ADCzr:STAzr 202 | 2030 LDAproduct+1:ADCzr+1:STAzr+1 203 | 2040 .z LDY&8000,X 204 | 2050 SEC:.u02 205 | 2060 LDA&E00,Y:SBC&E00,Y:STAproduct 206 | 2070 LDA&1100,Y:SBC&1100,Y:STAproduct+1 207 | 2080 LDAproduct:CLC:ADCxr:STAxr 208 | 2090 LDAproduct+1:ADCxr+1:STAxr+1 209 | 2100 SEC:.u12 210 | 2110 LDA&E00,Y:SBC&E00,Y:STAproduct 211 | 2120 LDA&1100,Y:SBC&1100,Y:STAproduct+1 212 | 2130 LDAproduct:CLC:ADCyr:STAyr 213 | 2140 LDAproduct+1:ADCyr+1:STAyr+1 214 | 2150 SEC:.u22 215 | 2160 LDA&E00,Y:SBC&E00,Y:STAproduct 216 | 2170 LDA&1100,Y:SBC&1100,Y:STAproduct+1 217 | 2180 LDAproduct:CLC:ADCzr:STAzr 218 | 2190 LDAproduct+1:ADCzr+1 219 | 2200 ASLzr:ROLA:ASLzr 220 | 2210 ADC#&80:TAY:CLC 221 | 2220 LDA#&80:ADCperspective,Y:STAadr:STAadr+2 222 | 2230 LDA#&E:ADC#0:STAadr+1:ADC#3:STAadr+3 223 | 2240 LDAadr:ADC#1:STAadr+4:STAadr+6 224 | 2250 LDAadr+1:ADC#0:STAadr+5:ADC#3:STAadr+7 225 | 2260 LDAyr+1:ASLyr:ROLA:ASLyr 226 | 2270 ADC#&80:TAY:SEC:EOR #&FF:STYzr:STAzr+1 227 | 2280 LDA(adr),Y:LDYzr+1:SBC(adr+4),Y:STAyr 228 | 2290 LDYzr:LDA(adr+2),Y:LDYzr+1:SBC(adr+6),Y 229 | 2300 ASLyr:ADC#&80:STAsy,X 230 | 2310 LDAxr+1:ASLxr:ROLA:ASLxr 231 | 2320 ADC#&80:TAY:SEC:EOR #&FF:STYzr:STAzr+1 232 | 2330 LDA(adr),Y:LDYzr+1:SBC(adr+4),Y:STAxr 233 | 2340 LDYzr:LDA(adr+2),Y:LDYzr+1:SBC(adr+6),Y 234 | 2350 ASLxr:ADC#&80:STAsx,X 235 | 2360 LDYsy,X 236 | 2370 RTS 237 | 2380 .matrix 238 | 2390 LDYrx:SEC 239 | 2400 LDA#0:SBCslsb,Y:STAm12lsb 240 | 2410 LDA#0:SBCsmsb,Y:ASLm12lsb 241 | 2420 ROLA:ASLm12lsb:ROLA:STAm12msb 242 | 2430 TYA:SEC:SBCry 243 | 2440 TAX:CLC:ADCrz:STAadr+3 244 | 2450 TYA:CLC:ADCry 245 | 2460 TAY:CLC:ADCrz:STAadr+2:SEC 246 | 2470 LDAslsb,X:SBCslsb,Y:STAm02lsb 247 | 2480 LDAsmsb,X:SBCsmsb,Y:ASLm02lsb 248 | 2490 ROLA:STAm02msb:CLC 249 | 2500 LDAclsb,Y:ADCclsb,X:STAm22lsb 250 | 2510 LDAcmsb,Y:ADCcmsb,X:ASLm22lsb 251 | 2520 ROLA:STAm22msb 252 | 2530 TYA:SEC:SBCrz:STAadr+4 253 | 2540 TXA:SEC:SBCrz:STAadr+5 254 | 2550 LDArx:CLC:ADCrz:TAY 255 | 2560 LDArx:SEC:SBCrz:TAX:SEC 256 | 2570 LDAslsb,Y:SBCslsb,X:STAm10lsb 257 | 2580 LDAsmsb,Y:SBCsmsb,X:ASLm10lsb 258 | 2590 ROLA:STAm10msb:CLC 259 | 2600 LDAclsb,X:ADCclsb,Y:STAm11lsb 260 | 2610 LDAcmsb,Y:ADCcmsb,X:ASLm11lsb 261 | 2620 ROLA:STAm11msb 262 | 2630 LDAry:SEC:SBCrz:TAY 263 | 2640 LDArz:CLC:ADCry:TAX:SEC 264 | 2650 LDAclsb,X:SBCclsb,Y:STAm21lsb 265 | 2660 LDAcmsb,X:SBCcmsb,Y:ASLm21lsb 266 | 2670 ROLA:STAm21msb:SEC 267 | 2680 LDAslsb,Y:SBCslsb,X:STAm01lsb 268 | 2690 LDAsmsb,Y:SBCsmsb,X:ASLm01lsb 269 | 2700 ROLA:STAm01msb:CLC 270 | 2710 LDAclsb,Y:ADCclsb,X:STAm00lsb 271 | 2720 LDAcmsb,X:ADCcmsb,Y:ASLm00lsb 272 | 2730 ROLA:STAm00msb:CLC 273 | 2740 LDAslsb,X:ADCslsb,Y:STAm20lsb 274 | 2750 LDAsmsb,Y:ADCsmsb,X:ASLm20lsb 275 | 2760 ROLA:STAm20msb 276 | 2770 LDYadr+4:LDXadr+3:SEC 277 | 2780 LDAm00lsb:SBCslsb,X:STAm00lsb 278 | 2790 LDAm00msb:SBCsmsb,X:STAm00msb:CLC 279 | 2800 LDAslsb,Y:ADCm21lsb:STAm21lsb 280 | 2810 LDAm21msb:ADCsmsb,Y:STAm21msb:CLC 281 | 2820 LDAclsb,Y:ADCm20lsb:STAm20lsb 282 | 2830 LDAcmsb,Y:ADCm20msb:STAm20msb:SEC 283 | 2840 LDAm01lsb:SBCclsb,X:STAm01lsb 284 | 2850 LDAm01msb:SBCcmsb,X:STAm01msb:CLC 285 | 2860 LDAclsb,Y:ADCm01lsb:STAm01lsb 286 | 2870 LDAcmsb,Y:ADCm01msb:STAm01msb:CLC 287 | 2880 LDAm21lsb:ADCslsb,X:STAm21lsb 288 | 2890 LDAm21msb:ADCsmsb,X:STAm21msb:SEC 289 | 2900 LDAm20lsb:SBCclsb,X:STAm20lsb 290 | 2910 LDAm20msb:SBCcmsb,X:STAm20msb:SEC 291 | 2920 LDAm00lsb:SBCslsb,Y:STAm00lsb 292 | 2930 LDAm00msb:SBCsmsb,Y:STAm00msb 293 | 2940 LDXadr+5:LDYadr+2:SEC 294 | 2950 LDAm20lsb:SBCclsb,Y:STAm20lsb 295 | 2960 LDAm20msb:SBCcmsb,Y:STAm20msb:CLC 296 | 2970 LDAm00lsb:ADCslsb,X:STAm00lsb 297 | 2980 LDAm00msb:ADCsmsb,X:STAm00msb:CLC 298 | 2990 LDAm21lsb:ADCslsb,X:STAm21lsb 299 | 3000 LDAm21msb:ADCsmsb,X:STAm21msb:CLC 300 | 3010 LDAclsb,Y:ADCm01lsb:STAm01lsb 301 | 3020 LDAcmsb,Y:ADCm01msb:STAm01msb:CLC 302 | 3030 LDAslsb,Y:ADCm21lsb:STAm21lsb 303 | 3040 LDAsmsb,Y:ADCm21msb:STAm21msb:CLC 304 | 3050 LDAslsb,Y:ADCm00lsb:STAm00lsb 305 | 3060 LDAsmsb,Y:ADCm00msb:STAm00msb:CLC 306 | 3070 LDAclsb,X:ADCm20lsb:STAm20lsb 307 | 3080 LDAcmsb,X:ADCm20msb:STAm20msb:SEC 308 | 3090 LDAm01lsb:SBCclsb,X:STAm01lsb 309 | 3100 LDAm01msb:SBCcmsb,X:STAm01msb 310 | 3110 LDX#8 311 | 3120 .loop 312 | 3130 LDAunitvectors,X:STAadr 313 | 3140 LDAunitvectors+9,X:STAadr+1 314 | 3150 LDAm00msb,X:ASLm00lsb,X:ADC#&80 315 | 3160 LDY#1:STA(adr),Y:LDY#9:STA(adr),Y 316 | 3170 CLC:EOR #&FF:ADC#1 317 | 3180 LDY#4:STA(adr),Y:LDY#&C:STA(adr),Y 318 | 3190 DEX:BPLloop 319 | 3200 RTS 320 | 3670 .clockwisetest STYls 321 | 3680 .clock0 LDX&8000,Y 322 | 3690 JSRgetcoordinates 323 | 3700 STAx0:STYy0:LDYls 324 | 3710 .clock1 LDX&8000,Y 325 | 3720 JSRgetcoordinates 326 | 3730 STAx1:STYy1:LDYls 327 | 3740 .clock2 LDX&8000,Y 328 | 3750 JSRgetcoordinates 329 | 3760 SEC:LDX#0 330 | 3770 SBCx0:BCSx20p 331 | 3780 SBC#0:EOR #&FF:INX 332 | 3790 .x20p STAlmul0 333 | 3800 LDAy1:SBCy0:BCSy10p 334 | 3810 SBC#0:EOR #&FF:DEX 335 | 3820 .y10p STAlmul1 336 | 3830 TYA:LDY#0 337 | 3840 SBCy0:BCSy20p 338 | 3850 SBC#0:EOR #&FF:INY 339 | 3860 .y20p STArmul0 340 | 3870 LDAx1:SBCx0:BCSx10p 341 | 3880 SBC#0:EOR #&FF:DEY 342 | 3890 .x10p STArmul1:STXcnt 343 | 3900 CPX#1:TYA 344 | 3910 EOR cnt:AND #1:BEQcompare 345 | 3920 LDYls:RTS 346 | 3930 .compare BCCbothpos 347 | 3940 JSRmultiply 348 | 3950 LDYlhs:CPYrhs 349 | 3960 LDAlhs+1:SBCrhs+1 350 | 3970 LDYls:RTS 351 | 3980 .bothpos SEC 352 | 3990 JSRmultiply 353 | 4000 LDYrhs:CPYlhs 354 | 4010 LDArhs+1:SBClhs+1 355 | 4020 LDYls:RTS 356 | 4030 .multiply 357 | 4040 LDYlmul1:TYA 358 | 4050 LDXlmul0:STXlmul1 359 | 4060 SBClmul0:BCSmabsl 360 | 4070 SBC#0:EOR #&FF 361 | 4080 .mabsl TAX 362 | 4090 LDA(lmul0),Y:SBC&F00,X:STAlhs 363 | 4100 LDA(lmul1),Y:SBC&1200,X:STAlhs+1 364 | 4110 LDYrmul1:TYA 365 | 4120 LDXrmul0:STXrmul1 366 | 4130 SBCrmul0:BCSmabsr 367 | 4140 SBC#0:EOR #&FF 368 | 4150 .mabsr TAX 369 | 4160 LDA(rmul0),Y:SBC&F00,X:STArhs 370 | 4170 LDA(rmul1),Y:SBC&1200,X:STArhs+1 371 | 4180 RTS 372 | 4190 .hiddenlineremoval 373 | 4200 LDXnsurfs:LDY#0 374 | 4210 STYline 375 | 4220 STYline+1 376 | 4230 STYline+2 377 | 4240 STYline+3 378 | 4250 STYline+4 379 | 4260 STYline+5 380 | 4270 STYline+6 381 | 4280 STYline+7 382 | 4290 .loop TXA 383 | 4300 PHA:EOR #&FF:SEC:ADCnsurfs:TAY:JSRclockwisetest:BCSnosurf 384 | 4301 PLA:TAX:EOR #&FF:SEC:ADCnsurfs:ASLA:ASLA:ASLA:TAY 385 | 4310 LDA(lines),Y:ORAline:STAline:INY 386 | 4320 LDA(lines),Y:ORAline+1:STAline+1:INY 387 | 4330 LDA(lines),Y:ORAline+2:STAline+2:INY 388 | 4340 LDA(lines),Y:ORAline+3:STAline+3:INY 389 | 4350 LDA(lines),Y:ORAline+4:STAline+4:INY 390 | 4360 LDA(lines),Y:ORAline+5:STAline+5:INY 391 | 4370 LDA(lines),Y:ORAline+6:STAline+6:INY 392 | 4380 LDA(lines),Y:ORAline+7:STAline+7:INY 393 | 4390 DEX:BPLloop:RTS 394 | 4400 .nosurf PLA:TAX 395 | 4410 DEX:BPLloop:RTS 396 | 4420 .drawlines 397 | 4430 LDA#0:STAlhs+1 398 | 4440 LDAnlines:STAlhs 399 | 4450 .loop 400 | 4460 LSRline+7 401 | 4470 RORline+6 402 | 4480 RORline+5 403 | 4490 RORline+4 404 | 4500 RORline+3 405 | 4510 RORline+2 406 | 4520 RORline+1 407 | 4530 RORline 408 | 4540 BCCnoline 409 | 4550 LDYlhs+1 410 | 4560 .linestarts LDA&8000,Y:PHA 411 | 4570 .lineends LDA&8000,Y:TAX 412 | 4580 JSRgetcoordinates 413 | 4590 STAx0:STYy0 414 | 4600 PLA:TAX 415 | 4610 JSRgetcoordinates 416 | 4620 STAx1:STYy1 417 | 4630 JSRlinedraw 418 | 4640 .noline INClhs+1:DEClhs:BPLloop 419 | 4650 RTS 420 | 4660 .back LDA#coordinates AND &FF:STAodr 421 | 4670 LDA#coordinates DIV 256:STAodr+1 422 | 4680 .modify 423 | 4690 LDA#&FF:STAoldsurfs:STAoldsurfs+1 424 | 4700 LDY#0 425 | 4710 LDA(odr),Y:BMIback:STAnpts:INY 426 | 4720 LDA(odr),Y:STAnlines:INY 427 | 4730 LDA(odr),Y:STAnsurfs:INY 428 | 4740 LDA(odr),Y:STAmaxvis 429 | 4750 LDAodr:SEC:ADC#3:STAodr:STAx+1 430 | 4760 LDAodr+1:ADC#0:STAodr+1:STAx+2 431 | 4770 LDAodr:SEC:ADCnpts:STAodr:STAy+1 432 | 4780 LDAodr+1:ADC#0:STAodr+1:STAy+2 433 | 4790 LDAodr:SEC:ADCnpts:STAodr:STAz+1 434 | 4800 LDAodr+1:ADC#0:STAodr+1:STAz+2 435 | 4810 LDAodr:SEC:ADCnpts:STAodr:STAclock0+1 436 | 4820 LDAodr+1:ADC#0:STAodr+1:STAclock0+2 437 | 4830 LDAodr:SEC:ADCnsurfs:STAodr:STAclock1+1 438 | 4840 LDAodr+1:ADC#0:STAodr+1:STAclock1+2 439 | 4850 LDAodr:SEC:ADCnsurfs:STAodr:STAclock2+1 440 | 4860 LDAodr+1:ADC#0:STAodr+1:STAclock2+2 441 | 4870 LDAodr:SEC:ADCnsurfs:STAodr 442 | 4880 LDAodr+1:ADC#0:STAodr+1 443 | 4890 LDAodr:SEC:ADCnsurfs:STAodr 444 | 4900 LDAodr+1:ADC#0:STAodr+1 445 | 4910 LDAodr:SEC:ADCnsurfs:STAodr:STAlines 446 | 4920 LDAodr+1:ADC#0:STAodr+1:STAlines+1 447 | 4930 LDY#7 448 | 4940 .loop 449 | 4950 LDAodr:SEC:ADCnsurfs:STAodr 450 | 4960 LDAodr+1:ADC#0:STAodr+1 451 | 4970 DEY:BPLloop 452 | 4980 LDAodr:STAlinestarts+1:SEC:ADCnlines:STAodr:STAlineends+1 453 | 4990 LDAodr+1:STAlinestarts+2:ADC#0:STAodr+1:STAlineends+2 454 | 5000 LDAodr:SEC:ADCnlines:STAodr 455 | 5010 LDAodr+1:ADC#0:STAodr+1 456 | 5020 RTS 457 | 5030 .coordinates OPT FNreaddata 458 | 5040 ] 459 | 5050 clsb=slsb+&40 460 | 5060 smsb=slsb+&140 461 | 5070 cmsb=clsb+&140 462 | 5080 NEXT 463 | 5090 ENDPROC 464 | 5100 DEF FNperspective 465 | 5110 IF pass<2P%=P%+&100:=pass 466 | 5120 d=&100 467 | 5130 oz=&80 468 | 5140 FOR Z%=-128TO 127 469 | 5150 ?P%=&FF*d/(d+oz+Z%)+.5 470 | 5160 P%=P%+1 471 | 5170 NEXT 472 | 5180 =pass 473 | 5190 DEF FNsintab 474 | 5200 IF pass<2P%=P%+&280:=pass 475 | 5210 FOR A%=0TO &13F 476 | 5220 S%=&1FA0*SIN (A%*2*PI /256)+.5 477 | 5230 ?P%=S%AND &FF 478 | 5240 P%?&140=(S%AND &FF00)DIV 256 479 | 5250 P%=P%+1 480 | 5260 NEXT 481 | 5270 P%=P%+&140 482 | 5280 =pass 483 | 5290 DEF FNreaddata 484 | 5300 RESTORE 5693 485 | 5310 READ NPTS%:IF NPTS%=&FF ?P%=&FF:P%=P%+1:=pass 486 | 5320 READ NLINES%,NSURFS%,MAXVIS%,SCALE 487 | 5330 ?P%=NPTS%-1:P%=P%+1 488 | 5340 ?P%=NLINES%-1:P%=P%+1 489 | 5350 ?P%=NSURFS%-1:P%=P%+1 490 | 5360 ?P%=MAXVIS%:P%=P%+1 491 | 5370 FOR I%=1TO NPTS% 492 | 5380 READ X,Y,Z 493 | 5381 X%=SCALE*X+.5 494 | 5382 Y%=SCALE*Y+.5 495 | 5383 Z%=SCALE*Z+.5 496 | 5390 ?P%=X%+128 497 | 5400 ?(P%+NPTS%)=Y%+128 498 | 5410 ?(P%+2*NPTS%)=Z%+128 499 | 5420 P%=P%+1 500 | 5430 NEXT 501 | 5440 P%=P%+2*NPTS% 502 | 5450 FOR I%=1TO NSURFS% 503 | 5460 READ C1%,C2%,C3% 504 | 5470 ?P%=C1% 505 | 5480 ?(P%+NSURFS%)=C2% 506 | 5490 ?(P%+2*NSURFS%)=C3% 507 | 5500 P%=P%+1 508 | 5510 NEXT 509 | 5520 P%=P%+2*NSURFS% 510 | 5530 FOR I%=1TO NSURFS% 511 | 5540 READ OPPS% 512 | 5550 IF OPPS%>&7FS%=0ELSE S%=2^OPPS% 513 | 5560 ?P%=S%AND &FF 514 | 5570 ?(P%+1)=S%DIV 256 515 | 5580 P%=P%+2 516 | 5590 NEXT 517 | 5600 FOR I%=1TO NSURFS% 518 | 5610 READ LIN1%,LIN2% 519 | 5620 !P%=LIN2% 520 | 5630 !(P%+4)=LIN1% 521 | 5640 P%=P%+8 522 | 5650 NEXT 523 | 5660 FOR I%=1TO 2*NLINES% 524 | 5670 READ PT% 525 | 5680 ?P%=PT% 526 | 5690 P%=P%+1 527 | 5691 NEXT :GOTO 5310 528 | 5692 REM Tetrahedron data 529 | 5693 DATA 4,6,4,3 530 | 5694 DATA 112 531 | 5695 DATA 1,-0.3536,0 532 | 5696 DATA -0.5,-0.3536,-0.866 533 | 5697 DATA -0.5,-0.3536,0.866 534 | 5698 DATA 0,1.0607,0 535 | 5699 DATA 1,2,3 536 | 5700 DATA 0,3,2 537 | 5701 DATA 0,1,3 538 | 5702 DATA 0,2,1 539 | 5703 DATA &80,&80,&80,&80 540 | 5704 DATA 0,7 541 | 5705 DATA 0,&1A 542 | 5706 DATA 0,&2C 543 | 5707 DATA 0,&31 544 | 5708 DATA 1,2,1,0,0,0 545 | 5709 DATA 2,3,3,3,2,1 546 | 5720 REM Cube data 547 | 5730 DATA 8,12,6,3 548 | 5740 DATA 1.369 549 | 5750 DATA +50,+50,+50 550 | 5760 DATA +50,+50,-50 551 | 5770 DATA +50,-50,+50 552 | 5780 DATA +50,-50,-50 553 | 5790 DATA -50,+50,+50 554 | 5800 DATA -50,+50,-50 555 | 5810 DATA -50,-50,+50 556 | 5820 DATA -50,-50,-50 557 | 5830 DATA 4,6,0 558 | 5840 DATA 5,7,4 559 | 5850 DATA 1,4,0 560 | 5860 DATA 3,1,0 561 | 5870 DATA 3,2,6 562 | 5880 DATA 7,1,3 563 | 5890 DATA 5,3,4,1,2,0 564 | 5900 DATA 0,&701 565 | 5910 DATA 0,&164 566 | 5920 DATA 0,&00F 567 | 5930 DATA 0,&A12 568 | 5940 DATA 0,&CC0 569 | 5950 DATA 0,&0B8 570 | 5960 DATA 0,1,4,1,1,5,6,3,4,0,2,2 571 | 5970 DATA 4,0,5,5,3,7,7,7,6,2,6,3 572 | 5971 REM Octahedron data 573 | 5972 DATA 6,12,8,4 574 | 5973 DATA 119 575 | 5974 DATA 0,-1,0,-1,0,0,0,0,-1 576 | 5975 DATA 0,1,0,1,0,0,0,0,1 577 | 5976 DATA 0,1,2 578 | 5977 DATA 0,5,1 579 | 5978 DATA 1,5,3 580 | 5979 DATA 1,3,2 581 | 5980 DATA 3,5,4 582 | 5981 DATA 2,3,4 583 | 5982 DATA 0,2,4 584 | 5983 DATA 0,4,5 585 | 5984 DATA 4,5,6,7,0,1,2,3 586 | 5985 DATA 0,7 587 | 5986 DATA 0,&19 588 | 5987 DATA 0,&70 589 | 5988 DATA 0,&C4 590 | 5989 DATA 0,&320 591 | 5990 DATA 0,&680 592 | 5991 DATA 0,&C02 593 | 5992 DATA 0,&908 594 | 5993 DATA 0,0,1,0,1,3,1,2,4,3,2,0 595 | 5994 DATA 1,2,2,5,5,5,3,3,5,4,4,4 596 | 6006 REM Dodecahedron data 597 | 6007 DATA 20,30,12,6 598 | 6008 DATA -72 599 | 6010 DATA 1,-1.3090,0 600 | 6020 DATA 0.3090,-1.3090,-0.9511 601 | 6030 DATA -0.8090,-1.3090,-0.5878 602 | 6040 DATA -0.8090,-1.3090,0.5878 603 | 6050 DATA 0.3090,-1.3090,0.9511 604 | 6060 DATA 1.6180,-0.3090,0 605 | 6070 DATA 0.5,-0.3090,-1.5388 606 | 6080 DATA -1.3090,-0.3090,-0.9511 607 | 6090 DATA -1.3090,-0.3090,0.9511 608 | 6100 DATA 0.5,-0.3090,1.5388 609 | 6120 DATA -1,1.3090,0 610 | 6130 DATA -0.3090,1.3090,0.9511 611 | 6140 DATA 0.8090,1.3090,0.5878 612 | 6150 DATA 0.8090,1.3090,-0.5878 613 | 6160 DATA -0.3090,1.3090,-0.9511 614 | 6170 DATA -1.6180,0.3090,0 615 | 6180 DATA -0.5,0.3090,1.5388 616 | 6190 DATA 1.3090,0.3090,0.9511 617 | 6200 DATA 1.3090,0.3090,-0.9511 618 | 6210 DATA -0.5,0.3090,-1.5388 619 | 6220 DATA 0,2,4 620 | 6230 DATA 10,7,14 621 | 6240 DATA 3,16,4 622 | 6250 DATA 18,6,0 623 | 6260 DATA 9,16,12 624 | 6270 DATA 2,7,8 625 | 6280 DATA 10,14,12 626 | 6290 DATA 0,4,17 627 | 6300 DATA 13,14,6 628 | 6310 DATA 8,10,16 629 | 6320 DATA 19,2,6 630 | 6330 DATA 12,18,17 631 | 6340 DATA 6,7,8,9,10,11,0,1,2,3,4,5 632 | 6341 DATA 0,&307 633 | 6342 DATA 0,&12040440 634 | 6343 DATA 0,&4084804 635 | 6344 DATA 0,&21101001 636 | 6345 DATA 0,&28A010 637 | 6346 DATA 0,&2414200 638 | 6347 DATA 0,&F8 639 | 6348 DATA 0,&28200802 640 | 6349 DATA 0,&920480 641 | 6350 DATA 0,&14408008 642 | 6351 DATA 0,&851100 643 | 6352 DATA 0,&9022020 644 | 6359 DATA 0,0,3,10,11,12,10,13,1,2 645 | 6360 DATA 14,4,1,12,3,11,2,13,7,9 646 | 6370 DATA 6,9,8,6,5,7,8,5,10,0 647 | 6380 DATA 1,4,4,11,12,13,14,14,2,3 648 | 6390 DATA 19,9,6,17,8,16,7,18,19,16 649 | 6400 DATA 18,17,15,19,18,15,16,17,15,5 650 | 8800 REM Icosahedron data 651 | 8810 DATA 12,30,20,10 652 | 8820 DATA -91 653 | 9000 DATA 2.32830644E-11,-1.309,0 654 | 9010 DATA -0.9472,0.5854,-0.6882 655 | 9020 DATA -0.3618,-0.5854,1.11352 656 | 9030 DATA 0.9472,-0.5854,-0.6882 657 | 9040 DATA 0.3618,0.5854,1.11352 658 | 9050 DATA -1.1708,-0.5854,0 659 | 9060 DATA -2.32830644E-11,1.309,0 660 | 9070 DATA 0.9472,-0.5854,0.6882 661 | 9080 DATA 0.3618,0.5854,-1.11352 662 | 9090 DATA -0.9472,0.5854,0.6882 663 | 9100 DATA -0.3618,-0.5854,-1.11352 664 | 9110 DATA 1.1708,0.5854,0 665 | 9111 DATA 0,7,3 666 | 9120 DATA 0,3,10 667 | 9130 DATA 0,10,5 668 | 9140 DATA 0,5,2 669 | 9150 DATA 0,2,7 670 | 9160 DATA 3,7,11 671 | 9170 DATA 3,8,10 672 | 9180 DATA 1,5,10 673 | 9190 DATA 2,5,9 674 | 9200 DATA 2,4,7 675 | 9210 DATA 9,1,6 676 | 9220 DATA 4,9,6 677 | 9230 DATA 11,4,6 678 | 9240 DATA 8,11,6 679 | 9250 DATA 1,8,6 680 | 9260 DATA 5,1,9 681 | 9270 DATA 4,2,9 682 | 9280 DATA 4,11,7 683 | 9290 DATA 3,11,8 684 | 9300 DATA 1,10,8 685 | 9310 DATA 10,11,12,13,14,15,16,17,18,19,0,1,2,3,4,5,6,7,8,9 686 | 9320 DATA 0,&E0000 687 | 9330 DATA 0,&38000 688 | 9340 DATA 0,&E000 689 | 9350 DATA 0,&3800 690 | 9360 DATA 0,&80C00 691 | 9370 DATA 0,&40300 692 | 9380 DATA 0,&100C0 693 | 9390 DATA 0,&4030 694 | 9400 DATA 0,&100C 695 | 9410 DATA 0,&403 696 | 9420 DATA 0,&700000 697 | 9430 DATA 0,&1C00000 698 | 9440 DATA 0,&7000000 699 | 9450 DATA 0,&1C000000 700 | 9460 DATA 0,&30200000 701 | 9470 DATA 0,&100028 702 | 9480 DATA 0,&800006 703 | 9490 DATA 0,&2000201 704 | 9500 DATA 0,&8000180 705 | 9510 DATA 0,&20000050 706 | 9520 DATA 4,2,2,5,1,1,8,3,3,7,2,0,2,0,5,0,3,0,3,0,1,1,6,4,4,4,6,8,6,1 707 | 9530 DATA 7,4,9,9,10,5,10,8,11,11,7,2,5,5,10,10,10,3,7,7,9,6,9,9,6,11,11,11,8,8 708 | 9540 DATA &FF 709 | -------------------------------------------------------------------------------- /source/models.asm: -------------------------------------------------------------------------------- 1 | 2 | ;---------------------------------------------------------------------------------------------------------- 3 | ; De-serialise triplet byte vertex data (for vertices & surfaces) 4 | ;---------------------------------------------------------------------------------------------------------- 5 | ; inputs - A=npts 6 | ; X/Y=points array address lo/hi 7 | ; 8 | ; Function is necessary since BeebAsm doesn't allow arbitrary memory 9 | ; layouts/data writes. 10 | ; We assemble the data interleaved X/Y/Z 11 | ; then this function copies the buffer to temp memory 12 | ; before copying it back, de-interleaved 13 | ;---------------------------------------------------------------------------------------------------------- 14 | TEMP_ADDR = &0E00 15 | .fix_verts 16 | { 17 | sta npts 18 | stx adr+0 19 | sty adr+1 20 | lda #LO(TEMP_ADDR) 21 | sta odr+0 22 | lda #HI(TEMP_ADDR) 23 | sta odr+1 24 | 25 | ; *3 26 | lda npts 27 | clc 28 | adc npts 29 | adc npts 30 | tay 31 | dey 32 | 33 | 34 | ; copy points to spare memory 35 | .copyloop 36 | lda (adr),y 37 | sta (odr),y 38 | dey 39 | bpl copyloop 40 | 41 | ; copy back de-interleaved 42 | lda #0 43 | sta rx 44 | lda npts 45 | sta ry 46 | clc 47 | adc npts 48 | sta rz 49 | ldx npts 50 | .fixloop 51 | ldy #0:lda (odr),y:ldy rx:sta (adr),y 52 | ldy #1:lda (odr),y:ldy ry:sta (adr),y 53 | ldy #2:lda (odr),y:ldy rz:sta (adr),y 54 | inc rx:inc ry:inc rz 55 | lda odr+0 56 | clc 57 | adc #3 58 | sta odr+0 59 | lda odr+1 60 | adc #0 61 | sta odr+1 62 | dex 63 | bne fixloop 64 | rts 65 | } 66 | 67 | MACRO FIX_MODEL model_data, vert_data, surfs_data 68 | lda model_data+0 ; npts 69 | clc 70 | adc #1 71 | ldx #LO(vert_data) 72 | ldy #HI(vert_data) 73 | jsr fix_verts 74 | 75 | lda model_data+2 ; nsurfs 76 | clc 77 | adc #1 78 | ldx #LO(surfs_data) 79 | ldy #HI(surfs_data) 80 | jsr fix_verts 81 | ENDMACRO 82 | 83 | ;---------------------------------------------------------------------------------------------------------- 84 | ; Initialisation function to fix-up the model data 85 | ; Converts model data from an assembled data format into a runtime data format 86 | ;---------------------------------------------------------------------------------------------------------- 87 | 88 | .initialise_models 89 | { 90 | IF WIREFRAME 91 | FIX_MODEL model_data_tetra, verts_data_tetra, surfs_data_tetra 92 | ENDIF 93 | FIX_MODEL model_data_cube, verts_data_cube, surfs_data_cube 94 | 95 | IF WIREFRAME 96 | FIX_MODEL model_data_octa, verts_data_octa, surfs_data_octa 97 | FIX_MODEL model_data_dodeca, verts_data_dodeca, surfs_data_dodeca 98 | ; icosa not compatible with code, as it has >15 surfaces 99 | ; FIX_MODEL model_data_icosa, verts_data_icosa, surfs_data_icosa 100 | ENDIF 101 | 102 | 103 | FIX_MODEL model_data_viper, verts_data_viper, surfs_data_viper 104 | FIX_MODEL model_data_cobra, verts_data_cobra, surfs_data_cobra 105 | rts 106 | } 107 | 108 | 109 | ;---------------------------------------------------------------------------------------------------------- 110 | ; Reset to the first model, then fall into the load model data routine 111 | ;---------------------------------------------------------------------------------------------------------- 112 | 113 | .reset_model 114 | { 115 | LDA#coordinates_start AND &FF:STA odr 116 | LDA#coordinates_start DIV 256:STA odr+1 117 | 118 | } 119 | 120 | ;---------------------------------------------------------------------------------------------------------- 121 | ; Load model data 122 | ; Sets up variables and address pointers for the next model in the model data array 123 | ;---------------------------------------------------------------------------------------------------------- 124 | 125 | .load_next_model 126 | { 127 | ; initialise all surfaces to hidden 128 | LDA#&FF:STA oldsurfs:STA oldsurfs+1 129 | 130 | LDY#0 131 | LDA(odr),Y 132 | ; if first byte of model data is 255 we have reached 133 | ; end of model list, so reset to the beginnning 134 | BMI reset_model 135 | 136 | ; otherwise capture model data 137 | STA npts:INY 138 | LDA(odr),Y:STA nlines:INY 139 | LDA(odr),Y:STA nsurfs:INY 140 | LDA(odr),Y:STA maxvis 141 | 142 | ; setup transform routine to load vertices from this model 143 | LDA odr:SEC:ADC#3:STA odr:STA x+1 144 | LDA odr+1:ADC#0:STA odr+1:STA x+2 145 | LDA odr:SEC:ADC npts:STA odr:STA y+1 146 | LDA odr+1:ADC#0:STA odr+1:STA y+2 147 | LDA odr:SEC:ADC npts:STA odr:STA z+1 148 | LDA odr+1:ADC#0:STA odr+1:STA z+2 149 | 150 | ; setup clockwisetest routine 151 | ; - load ptrs to surfaces for this model 152 | 153 | ; store ptr to surfaces p0 154 | LDA odr:SEC:ADC npts:STA odr:STA clock0+1 155 | LDA odr+1:ADC#0:STA odr+1:STA clock0+2 156 | ; store ptr to surfaces p1 157 | LDA odr:SEC:ADC nsurfs:STA odr:STA clock1+1 158 | LDA odr+1:ADC#0:STA odr+1:STA clock1+2 159 | ; store ptr to surfaces p2 160 | LDA odr:SEC:ADC nsurfs:STA odr:STA clock2+1 161 | LDA odr+1:ADC#0:STA odr+1:STA clock2+2 162 | 163 | ; setup hiddensurfaceremoval routine 164 | ; - load ptrs to opposites data array for this model 165 | LDA odr:SEC:ADC nsurfs:STA odr:STA opposite0+1:STA opposite1+1:STA opposite2+1:STA opposite3+1 166 | LDA odr+1:ADC#0:STA odr+1:STA opposite0+2:STA opposite1+2:STA opposite2+2:STA opposite3+2 167 | 168 | ; setup lines address (ZP) to point to the lines array for this model 169 | LDA odr:SEC:ADC nsurfs:STA odr 170 | LDA odr+1:ADC#0:STA odr+1 171 | LDA odr:SEC:ADC nsurfs:STA odr:STA lines 172 | LDA odr+1:ADC#0:STA odr+1:STA lines+1 173 | 174 | ; setup the drawlines routine 175 | ; - load ptr to the vertex indices for this model 176 | LDY#7 177 | .loopE 178 | LDA odr:SEC:ADC nsurfs:STA odr 179 | LDA odr+1:ADC#0:STA odr+1 180 | DEY:BPL loopE 181 | LDA odr:STA linestarts+1:SEC:ADC nlines:STA odr:STA lineends+1 182 | LDA odr+1:STA linestarts+2:ADC#0:STA odr+1:STA lineends+2 183 | LDA odr:SEC:ADC nlines:STA odr 184 | LDA odr+1:ADC#0:STA odr+1 185 | RTS 186 | } 187 | 188 | 189 | ;---------------------------------------------------------------------------------------------------------- 190 | ; start of model data block 191 | ;---------------------------------------------------------------------------------------------------------- 192 | .coordinates_start 193 | 194 | ; models comprise: 195 | ; header 196 | ; vertex data - 3 bytes per vertex (x,y,z) 197 | ; surface data - 3 bytes per surface (v0,v1,v2), describe a CW triangle/plane of the surface 198 | ; opposites data - 1 byte per surface 199 | ; lines data - 8 bytes per surface, a 64-bit array of the lines rendered by each surface 200 | ; linelist data - 2 bytes per surface, the start and end vertex index for each line in the model 201 | 202 | MACRO MD_HEADER npts, nlines, nsurfs, maxvis 203 | EQUB npts-1 204 | EQUB nlines-1 205 | EQUB nsurfs-1 206 | EQUB maxvis 207 | ENDMACRO 208 | 209 | ; store a signed X,Y,Z vertex, scaled by 'scale' 210 | ; stored in 8 bits unsigned format 211 | MACRO MD_POINT x, y, z, scale 212 | EQUB INT(x * scale + 128) 213 | EQUB INT(y * scale + 128) 214 | EQUB INT(z * scale + 128) 215 | ENDMACRO 216 | 217 | 218 | 219 | ; store the first three indices of vertices that describe 220 | ; a surface. 221 | ; presented in clockwise orientation 222 | ; if rendered CCW they are considered hidden 223 | MACRO MD_SURF p0, p1, p2 224 | EQUB p0 225 | EQUB p1 226 | EQUB p2 227 | ENDMACRO 228 | 229 | 230 | ; opposites array describes any surfaces that are opposite to the current surface 231 | ; in this way they can be eliminated without extra clockwisetest's 232 | ; stored as a 16-bit bitfield, where #bit is set for the opposite surface id 233 | MACRO MD_OPP opps 234 | IF opps > &7f 235 | EQUW 0 236 | ELSE 237 | ; sdm: some shapes use opps ids > 15 which is larger than 16bit 238 | A = 2^ opps 239 | EQUB LO(A) 240 | EQUB HI(A) 241 | ENDIF 242 | ENDMACRO 243 | 244 | ; declare lines that are rendered for a given surface 245 | ; stored as 64-bit array (8 bytes) 246 | ; each bit in the array corresponds to an MD_LINE object 247 | ; There must be one MD_LINE declared for each MD_SURF 248 | MACRO MD_LINE p0, p1 249 | EQUD p1 250 | EQUD p0 251 | ENDMACRO 252 | 253 | 254 | ; add a line to the linelist for the model 255 | ; where p0 and p1 are the two vertex indices for the line 256 | MACRO MD_INDEX p0, p1 257 | EQUB p0 258 | EQUB p1 259 | ENDMACRO 260 | 261 | 262 | IF WIREFRAME 263 | ; Tetrahedron data 264 | .model_data_tetra 265 | TETRA_NPTS = 4 266 | TETRA_NLINES = 6 267 | TETRA_NSURFS = 4 268 | TETRA_MAXVIS = 3 269 | TETRA_SCALE = 112 270 | 271 | MD_HEADER TETRA_NPTS,TETRA_NLINES,TETRA_NSURFS,TETRA_MAXVIS 272 | 273 | .verts_data_tetra 274 | 275 | 276 | MD_POINT 1,-0.3536,0, TETRA_SCALE 277 | MD_POINT -0.5,-0.3536,-0.866, TETRA_SCALE 278 | MD_POINT -0.5,-0.3536,0.866, TETRA_SCALE 279 | MD_POINT 0,1.0607,0, TETRA_SCALE 280 | 281 | .surfs_data_tetra 282 | MD_SURF 1,2,3 283 | MD_SURF 0,3,2 284 | MD_SURF 0,1,3 285 | MD_SURF 0,2,1 286 | 287 | MD_OPP &80 288 | MD_OPP &80 289 | MD_OPP &80 290 | MD_OPP &80 291 | 292 | MD_LINE 0,7 293 | MD_LINE 0,&1A 294 | MD_LINE 0,&2C 295 | MD_LINE 0,&31 296 | 297 | MD_INDEX 1,2 298 | MD_INDEX 1,0 299 | MD_INDEX 0,0 300 | MD_INDEX 2,3 301 | MD_INDEX 3,3 302 | MD_INDEX 2,1 303 | ENDIF 304 | 305 | 306 | 307 | 308 | ; Cube data 309 | .model_data_cube 310 | CUBE_NPTS = 8 311 | CUBE_NLINES = 12 312 | CUBE_NSURFS = 6 313 | CUBE_MAXVIS = 3 314 | CUBE_SCALE = 1.369 315 | 316 | MD_HEADER CUBE_NPTS,CUBE_NLINES,CUBE_NSURFS,CUBE_MAXVIS 317 | 318 | .verts_data_cube 319 | MD_POINT +50,+50,+50, CUBE_SCALE 320 | MD_POINT +50,+50,-50, CUBE_SCALE 321 | MD_POINT +50,-50,+50, CUBE_SCALE 322 | MD_POINT +50,-50,-50, CUBE_SCALE 323 | MD_POINT -50,+50,+50, CUBE_SCALE 324 | MD_POINT -50,+50,-50, CUBE_SCALE 325 | MD_POINT -50,-50,+50, CUBE_SCALE 326 | MD_POINT -50,-50,-50, CUBE_SCALE 327 | 328 | 329 | .surfs_data_cube 330 | MD_SURF 4,6,0 331 | MD_SURF 5,7,4 332 | MD_SURF 1,4,0 333 | MD_SURF 3,1,0 334 | MD_SURF 3,2,6 335 | MD_SURF 7,1,3 336 | 337 | MD_OPP 5 338 | MD_OPP 3 339 | MD_OPP 4 340 | MD_OPP 1 341 | MD_OPP 2 342 | MD_OPP 0 343 | 344 | IF WIREFRAME 345 | MD_LINE 0,&701 346 | MD_LINE 0,&164 347 | MD_LINE 0,&00F 348 | MD_LINE 0,&A12 349 | MD_LINE 0,&CC0 350 | MD_LINE 0,&0B8 351 | ELSE 352 | MD_LINE 0,&150001 353 | MD_LINE 0,&022820 354 | MD_LINE 0,&0000FF 355 | MD_LINE 0,&880208 356 | MD_LINE 0,&F0F000 357 | MD_LINE 0,&004540 358 | ENDIF 359 | 360 | MD_INDEX 0,1 361 | MD_INDEX 4,1 362 | MD_INDEX 1,5 363 | MD_INDEX 6,3 364 | MD_INDEX 4,0 365 | MD_INDEX 2,2 366 | MD_INDEX 4,0 367 | MD_INDEX 5,5 368 | MD_INDEX 3,7 369 | MD_INDEX 7,7 370 | MD_INDEX 6,2 371 | MD_INDEX 6,3 372 | 373 | ; wireframe only models 374 | IF WIREFRAME 375 | ; Octahedron data 376 | .model_data_octa 377 | 378 | OCTA_NPTS = 6 379 | OCTA_NLINES = 12 380 | OCTA_NSURFS = 8 381 | OCTA_MAXVIS = 4 382 | OCTA_SCALE = 119 383 | 384 | MD_HEADER OCTA_NPTS,OCTA_NLINES,OCTA_NSURFS,OCTA_MAXVIS 385 | 386 | .verts_data_octa 387 | MD_POINT 0,-1,0, OCTA_SCALE 388 | MD_POINT -1,0,0, OCTA_SCALE 389 | MD_POINT 0,0,-1, OCTA_SCALE 390 | MD_POINT 0,1,0, OCTA_SCALE 391 | MD_POINT 1,0,0, OCTA_SCALE 392 | MD_POINT 0,0,1, OCTA_SCALE 393 | 394 | .surfs_data_octa 395 | MD_SURF 0,1,2 396 | MD_SURF 0,5,1 397 | MD_SURF 1,5,3 398 | MD_SURF 1,3,2 399 | MD_SURF 3,5,4 400 | MD_SURF 2,3,4 401 | MD_SURF 0,2,4 402 | MD_SURF 0,4,5 403 | 404 | MD_OPP 4 405 | MD_OPP 5 406 | MD_OPP 6 407 | MD_OPP 7 408 | MD_OPP 0 409 | MD_OPP 1 410 | MD_OPP 2 411 | MD_OPP 3 412 | 413 | MD_LINE 0,7 414 | MD_LINE 0,&19 415 | MD_LINE 0,&70 416 | MD_LINE 0,&C4 417 | MD_LINE 0,&320 418 | MD_LINE 0,&680 419 | MD_LINE 0,&C02 420 | MD_LINE 0,&908 421 | 422 | MD_INDEX 0,0 423 | MD_INDEX 1,0 424 | MD_INDEX 1,3 425 | MD_INDEX 1,2 426 | MD_INDEX 4,3 427 | MD_INDEX 2,0 428 | MD_INDEX 1,2 429 | MD_INDEX 2,5 430 | MD_INDEX 5,5 431 | MD_INDEX 3,3 432 | MD_INDEX 5,4 433 | MD_INDEX 4,4 434 | 435 | 436 | ; Dodecahedron data 437 | .model_data_dodeca 438 | DODECA_NPTS = 20 439 | DODECA_NLINES = 30 440 | DODECA_NSURFS = 12 441 | DODECA_MAXVIS = 6 442 | DODECA_SCALE = -72 443 | 444 | MD_HEADER DODECA_NPTS,DODECA_NLINES,DODECA_NSURFS,DODECA_MAXVIS 445 | 446 | .verts_data_dodeca 447 | MD_POINT 1,-1.3090,0, DODECA_SCALE 448 | MD_POINT 0.3090,-1.3090,-0.9511, DODECA_SCALE 449 | MD_POINT -0.8090,-1.3090,-0.5878, DODECA_SCALE 450 | MD_POINT -0.8090,-1.3090,0.5878, DODECA_SCALE 451 | MD_POINT 0.3090,-1.3090,0.9511, DODECA_SCALE 452 | MD_POINT 1.6180,-0.3090,0, DODECA_SCALE 453 | MD_POINT 0.5,-0.3090,-1.5388, DODECA_SCALE 454 | MD_POINT -1.3090,-0.3090,-0.9511, DODECA_SCALE 455 | MD_POINT -1.3090,-0.3090,0.9511, DODECA_SCALE 456 | MD_POINT 0.5,-0.3090,1.5388, DODECA_SCALE 457 | MD_POINT -1,1.3090,0, DODECA_SCALE 458 | MD_POINT -0.3090,1.3090,0.9511, DODECA_SCALE 459 | MD_POINT 0.8090,1.3090,0.5878, DODECA_SCALE 460 | MD_POINT 0.8090,1.3090,-0.5878, DODECA_SCALE 461 | MD_POINT -0.3090,1.3090,-0.9511, DODECA_SCALE 462 | MD_POINT -1.6180,0.3090,0, DODECA_SCALE 463 | MD_POINT -0.5,0.3090,1.5388, DODECA_SCALE 464 | MD_POINT 1.3090,0.3090,0.9511, DODECA_SCALE 465 | MD_POINT 1.3090,0.3090,-0.9511, DODECA_SCALE 466 | MD_POINT -0.5,0.3090,-1.5388, DODECA_SCALE 467 | 468 | .surfs_data_dodeca 469 | MD_SURF 0,2,4 470 | MD_SURF 10,7,14 471 | MD_SURF 3,16,4 472 | MD_SURF 18,6,0 473 | MD_SURF 9,16,12 474 | MD_SURF 2,7,8 475 | MD_SURF 10,14,12 476 | MD_SURF 0,4,17 477 | MD_SURF 13,14,6 478 | MD_SURF 8,10,16 479 | MD_SURF 19,2,6 480 | MD_SURF 12,18,17 481 | 482 | MD_OPP 6 483 | MD_OPP 7 484 | MD_OPP 8 485 | MD_OPP 9 486 | MD_OPP 10 487 | MD_OPP 11 488 | MD_OPP 0 489 | MD_OPP 1 490 | MD_OPP 2 491 | MD_OPP 3 492 | MD_OPP 4 493 | MD_OPP 5 494 | 495 | MD_LINE 0,&307 496 | MD_LINE 0,&12040440 497 | MD_LINE 0,&4084804 498 | MD_LINE 0,&21101001 499 | MD_LINE 0,&28A010 500 | MD_LINE 0,&2414200 501 | MD_LINE 0,&F8 502 | MD_LINE 0,&28200802 503 | MD_LINE 0,&920480 504 | MD_LINE 0,&14408008 505 | MD_LINE 0,&851100 506 | MD_LINE 0,&9022020 507 | 508 | MD_INDEX 0,0 509 | MD_INDEX 3,10 510 | MD_INDEX 11,12 511 | MD_INDEX 10,13 512 | MD_INDEX 1,2 513 | MD_INDEX 14,4 514 | MD_INDEX 1,12 515 | MD_INDEX 3,11 516 | MD_INDEX 2,13 517 | MD_INDEX 7,9 518 | MD_INDEX 6,9 519 | MD_INDEX 8,6 520 | MD_INDEX 5,7 521 | MD_INDEX 8,5 522 | MD_INDEX 10,0 523 | MD_INDEX 1,4 524 | MD_INDEX 4,11 525 | MD_INDEX 12,13 526 | MD_INDEX 14,14 527 | MD_INDEX 2,3 528 | MD_INDEX 19,9 529 | MD_INDEX 6,17 530 | MD_INDEX 8,16 531 | MD_INDEX 7,18 532 | MD_INDEX 19,16 533 | MD_INDEX 18,17 534 | MD_INDEX 15,19 535 | MD_INDEX 18,15 536 | MD_INDEX 16,17 537 | MD_INDEX 15,5 538 | 539 | ; Icosahedron model contains more than 15 surfaces 540 | ; so cannot be rendered using the optimized surface removal, unless that optimization is disabled 541 | IF FALSE 542 | 543 | ; Icosahedron data 544 | .model_data_icosa 545 | ICOSA_NPTS = 12 546 | ICOSA_NLINES = 30 547 | ICOSA_NSURFS = 20 548 | ICOSA_MAXVIS = 10 549 | ICOSA_SCALE = -91 550 | 551 | MD_HEADER ICOSA_NPTS,ICOSA_NLINES,ICOSA_NSURFS,ICOSA_MAXVIS 552 | 553 | .verts_data_icosa 554 | MD_POINT 2.32830644E-11,-1.309,0, ICOSA_SCALE 555 | MD_POINT -0.9472,0.5854,-0.6882, ICOSA_SCALE 556 | MD_POINT -0.3618,-0.5854,1.11352, ICOSA_SCALE 557 | MD_POINT 0.9472,-0.5854,-0.6882, ICOSA_SCALE 558 | MD_POINT 0.3618,0.5854,1.11352, ICOSA_SCALE 559 | MD_POINT -1.1708,-0.5854,0, ICOSA_SCALE 560 | MD_POINT -2.32830644E-11,1.309,0, ICOSA_SCALE 561 | MD_POINT 0.9472,-0.5854,0.6882, ICOSA_SCALE 562 | MD_POINT 0.3618,0.5854,-1.11352, ICOSA_SCALE 563 | MD_POINT -0.9472,0.5854,0.6882, ICOSA_SCALE 564 | MD_POINT -0.3618,-0.5854,-1.11352, ICOSA_SCALE 565 | MD_POINT 1.1708,0.5854,0, ICOSA_SCALE 566 | 567 | .surfs_data_icosa 568 | MD_SURF 0,7,3 569 | MD_SURF 0,3,10 570 | MD_SURF 0,10,5 571 | MD_SURF 0,5,2 572 | MD_SURF 0,2,7 573 | MD_SURF 3,7,11 574 | MD_SURF 3,8,10 575 | MD_SURF 1,5,10 576 | MD_SURF 2,5,9 577 | MD_SURF 2,4,7 578 | MD_SURF 9,1,6 579 | MD_SURF 4,9,6 580 | MD_SURF 11,4,6 581 | MD_SURF 8,11,6 582 | MD_SURF 1,8,6 583 | MD_SURF 5,1,9 584 | MD_SURF 4,2,9 585 | MD_SURF 4,11,7 586 | MD_SURF 3,11,8 587 | MD_SURF 1,10,8 588 | 589 | MD_OPP 10 590 | MD_OPP 11 591 | MD_OPP 12 592 | MD_OPP 13 593 | MD_OPP 14 594 | MD_OPP 15 595 | MD_OPP 16 596 | MD_OPP 17 597 | MD_OPP 18 598 | MD_OPP 19 599 | MD_OPP 0 600 | MD_OPP 1 601 | MD_OPP 2 602 | MD_OPP 3 603 | MD_OPP 4 604 | MD_OPP 5 605 | MD_OPP 6 606 | MD_OPP 7 607 | MD_OPP 8 608 | MD_OPP 9 609 | 610 | MD_LINE 0,&E0000 611 | MD_LINE 0,&38000 612 | MD_LINE 0,&E000 613 | MD_LINE 0,&3800 614 | MD_LINE 0,&80C00 615 | MD_LINE 0,&40300 616 | MD_LINE 0,&100C0 617 | MD_LINE 0,&4030 618 | MD_LINE 0,&100C 619 | MD_LINE 0,&403 620 | MD_LINE 0,&700000 621 | MD_LINE 0,&1C00000 622 | MD_LINE 0,&7000000 623 | MD_LINE 0,&1C000000 624 | MD_LINE 0,&30200000 625 | MD_LINE 0,&100028 626 | MD_LINE 0,&800006 627 | MD_LINE 0,&2000201 628 | MD_LINE 0,&8000180 629 | MD_LINE 0,&20000050 630 | 631 | MD_INDEX 4,2 632 | MD_INDEX 2,5 633 | MD_INDEX 1,1 634 | MD_INDEX 8,3 635 | MD_INDEX 3,7 636 | MD_INDEX 2,0 637 | MD_INDEX 2,0 638 | MD_INDEX 5,0 639 | MD_INDEX 3,0 640 | MD_INDEX 3,0 641 | MD_INDEX 1,1 642 | MD_INDEX 6,4 643 | MD_INDEX 4,4 644 | MD_INDEX 6,8 645 | MD_INDEX 6,1 646 | MD_INDEX 7,4 647 | MD_INDEX 9,9 648 | MD_INDEX 10,5 649 | MD_INDEX 10,8 650 | MD_INDEX 11,11 651 | MD_INDEX 7,2 652 | MD_INDEX 5,5 653 | MD_INDEX 10,10 654 | MD_INDEX 10,3 655 | MD_INDEX 7,7 656 | MD_INDEX 9,6 657 | MD_INDEX 9,9 658 | MD_INDEX 6,11 659 | MD_INDEX 11,11 660 | MD_INDEX 8,8 661 | 662 | ENDIF ; Icosahedron only 663 | 664 | ENDIF ; wireframe only 665 | 666 | 667 | 668 | ; Viper data 669 | .model_data_viper 670 | VIPER_NPTS = 15 671 | VIPER_NLINES = 20 672 | VIPER_NSURFS = 7 673 | VIPER_MAXVIS = 5 674 | VIPER_SCALE = 4 675 | 676 | MD_HEADER VIPER_NPTS, VIPER_NLINES, VIPER_NSURFS, VIPER_MAXVIS 677 | 678 | .verts_data_viper 679 | MD_POINT 0,19,0, VIPER_SCALE 680 | MD_POINT 0,1,-6, VIPER_SCALE 681 | MD_POINT 0,1,6, VIPER_SCALE 682 | MD_POINT -10,-19,-6, VIPER_SCALE 683 | MD_POINT -19,-19,0, VIPER_SCALE 684 | MD_POINT -10,-19,6, VIPER_SCALE 685 | MD_POINT 10,-19,6, VIPER_SCALE 686 | MD_POINT 19,-19,0, VIPER_SCALE 687 | MD_POINT 10,-19,-6, VIPER_SCALE 688 | MD_POINT -3,-19,-4, VIPER_SCALE 689 | MD_POINT -12,-19,0, VIPER_SCALE 690 | MD_POINT -3,-19,4, VIPER_SCALE 691 | MD_POINT 3,-19,-4, VIPER_SCALE 692 | MD_POINT 3,-19,4, VIPER_SCALE 693 | MD_POINT 12,-19,0, VIPER_SCALE 694 | 695 | .surfs_data_viper 696 | MD_SURF 1,8,3 697 | MD_SURF 0,1,3 698 | MD_SURF 0,8,1 699 | MD_SURF 0,2,6 700 | MD_SURF 0,5,2 701 | MD_SURF 2,5,6 702 | MD_SURF 6,3,8 703 | 704 | MD_OPP 5 705 | MD_OPP &80 706 | MD_OPP &80 707 | MD_OPP &80 708 | MD_OPP &80 709 | MD_OPP 0 710 | MD_OPP &80 711 | 712 | IF WIREFRAME 713 | MD_LINE 0,&18100 714 | MD_LINE 0,&30009 715 | MD_LINE 0,&08085 716 | MD_LINE 0,&80046 717 | MD_LINE 0,&60012 718 | MD_LINE 0,&C0020 719 | MD_LINE 0,&07FF8 720 | ELSE 721 | MD_LINE &01,&40010000 722 | MD_LINE &0A,&00000082 723 | MD_LINE &00,&C000C033 724 | MD_LINE &80,&00002028 725 | MD_LINE &3C,&0000030C 726 | MD_LINE &50,&00000400 727 | MD_LINE &00,&3FFFFFC0 728 | ENDIF 729 | 730 | MD_INDEX 0,2 731 | MD_INDEX 0,3 732 | MD_INDEX 4,5 733 | MD_INDEX 6,7 734 | MD_INDEX 8,9 735 | MD_INDEX 10,11 736 | MD_INDEX 12,13 737 | MD_INDEX 14,1 738 | MD_INDEX 3,0 739 | MD_INDEX 5,2 740 | MD_INDEX 1,0 741 | MD_INDEX 7,4 742 | MD_INDEX 5,6 743 | MD_INDEX 7,8 744 | MD_INDEX 3,10 745 | MD_INDEX 11,9 746 | MD_INDEX 13,14 747 | MD_INDEX 12,8 748 | MD_INDEX 1,4 749 | MD_INDEX 2,6 750 | 751 | ; Cobra MkIII data 752 | .model_data_cobra 753 | COBRA_NPTS = 22 754 | COBRA_NLINES = 32 755 | COBRA_NSURFS = 13 756 | COBRA_MAXVIS = 9 757 | COBRA_SCALE = 6 758 | 759 | MD_HEADER COBRA_NPTS, COBRA_NLINES, COBRA_NSURFS, COBRA_MAXVIS 760 | 761 | .verts_data_cobra 762 | MD_POINT -19,-8,0, COBRA_SCALE 763 | MD_POINT -19,-4.5,0, COBRA_SCALE 764 | MD_POINT -16,-8,-1, COBRA_SCALE 765 | MD_POINT -5,9,0, COBRA_SCALE 766 | MD_POINT -5,-8,2, COBRA_SCALE 767 | MD_POINT 5,-8,2, COBRA_SCALE 768 | MD_POINT 0,3,-3.5, COBRA_SCALE 769 | MD_POINT 0,9,0, COBRA_SCALE 770 | MD_POINT 0,12,0, COBRA_SCALE 771 | MD_POINT 5,9,0, COBRA_SCALE 772 | MD_POINT 0,-8,-2, COBRA_SCALE 773 | MD_POINT 16,-8,-1, COBRA_SCALE 774 | MD_POINT 19,-4.5,0, COBRA_SCALE 775 | MD_POINT 19,-8,0, COBRA_SCALE 776 | MD_POINT -5,-8,-1, COBRA_SCALE 777 | MD_POINT -2,-8,-1, COBRA_SCALE 778 | MD_POINT -2,-8,1.5, COBRA_SCALE 779 | MD_POINT -5,-8,1, COBRA_SCALE 780 | MD_POINT 2,-8,-1, COBRA_SCALE 781 | MD_POINT 5,-8,-1, COBRA_SCALE 782 | MD_POINT 5,-8,1, COBRA_SCALE 783 | MD_POINT 2,-8,1.5, COBRA_SCALE 784 | 785 | .surfs_data_cobra 786 | MD_SURF 0,1,2 787 | MD_SURF 1,3,2 788 | MD_SURF 2,3,6 789 | MD_SURF 2,6,10 790 | MD_SURF 3,9,6 791 | MD_SURF 10,6,11 792 | MD_SURF 6,9,11 793 | MD_SURF 11,9,12 794 | MD_SURF 11,12,13 795 | MD_SURF 13,9,5 796 | MD_SURF 5,3,4 797 | MD_SURF 4,3,0 798 | MD_SURF 4,10,5 799 | 800 | MD_OPP &80 801 | MD_OPP &80 802 | MD_OPP &80 803 | MD_OPP &80 804 | MD_OPP &80 805 | MD_OPP &80 806 | MD_OPP &80 807 | MD_OPP &80 808 | MD_OPP &80 809 | MD_OPP &80 810 | MD_OPP &80 811 | MD_OPP &80 812 | MD_OPP &80 813 | 814 | IF WIREFRAME 815 | MD_LINE 0,&00000007 816 | MD_LINE 0,&0000001C 817 | MD_LINE 0,&000000B0 818 | MD_LINE 0,&00020420 819 | MD_LINE 0,&000003C0 820 | MD_LINE 0,&00040C00 821 | MD_LINE 0,&00001900 822 | MD_LINE 0,&00007000 823 | MD_LINE 0,&0001C000 824 | MD_LINE 0,&80092000 825 | MD_LINE 0,&C0100240 826 | MD_LINE 0,&40200009 827 | MD_LINE 0,&3FFE8002 828 | ELSE 829 | MD_LINE 0,&15 830 | MD_LINE 0,&02A0 831 | MD_LINE 0,&4500 832 | MD_LINE &08,&00200800 833 | MD_LINE 0,&03F000 834 | MD_LINE &20,&00A00000 835 | MD_LINE 0,&01410000 836 | MD_LINE 0,&2A000000 837 | MD_LINE &01,&50000000 838 | MD_LINE &C00000C3,&0C000000 839 | MD_LINE &A0000200,&00002000 840 | MD_LINE &30000C00,&000000C3 841 | MD_LINE &0FFFFFFC,&C000000C 842 | ENDIF 843 | 844 | MD_INDEX 0,0 845 | MD_INDEX 1,1 846 | MD_INDEX 2,2 847 | MD_INDEX 3,3 848 | MD_INDEX 6,7 849 | MD_INDEX 10,6 850 | MD_INDEX 9,9 851 | MD_INDEX 11,11 852 | MD_INDEX 12,2 853 | MD_INDEX 11,5 854 | MD_INDEX 4,0 855 | MD_INDEX 14,15 856 | MD_INDEX 16,14 857 | MD_INDEX 18,19 858 | MD_INDEX 20,18 859 | MD_INDEX 3,5 860 | MD_INDEX 1,2 861 | MD_INDEX 2,3 862 | MD_INDEX 3,6 863 | MD_INDEX 9,6 864 | MD_INDEX 9,8 865 | MD_INDEX 6,11 866 | MD_INDEX 11,12 867 | MD_INDEX 12,13 868 | MD_INDEX 13,10 869 | MD_INDEX 10,13 870 | MD_INDEX 5,4 871 | MD_INDEX 15,16 872 | MD_INDEX 17,17 873 | MD_INDEX 19,20 874 | MD_INDEX 21,21 875 | MD_INDEX 4,9 876 | 877 | .model_data_finish 878 | EQUB &FF 879 | 880 | .coordinates_end 881 | --------------------------------------------------------------------------------