├── 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 |
--------------------------------------------------------------------------------