-
Notifications
You must be signed in to change notification settings - Fork 20
/
carrera3d.bas
220 lines (192 loc) · 5.51 KB
/
carrera3d.bas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
' ------------- Carrera 3D ---------------
' ----------- by DMSC - 2015 -------------
'
' Modified to run under FastBasic - 2017
' Reserve memory for graphics and set 160x96 mode
' dlist = display lists pointer.
' 150 bytes per display list, total of 11*6 = 66 display lists,
' but can't cross 1k boundary => 11KBytes, 44 pages
' gbase = graphic data pointer
' 40 bytes per line, total of 48*4*2 = 384 lines => 15KBytes, 60 pages
dim memory(27647) byte
' display list must be aligned to 1024 bytes:
dlist = (adr(memory)+1023)/1024 * 1024
gbase = dlist + $2C00
' Sets graphics mode, 160x96, 4 colors.
graphics 7
pmgraphics 1
' Sets the start of the image to 255, (full color 3),
' we then use a "move" to copy to all the line.
img = dpeek(88)
' Make display-lists and graphics data
' Size of display list
dlsize = 156
' Loop over all Y values
for y=1 to 48
r = y+14
zpos = 19200/r - 300
p = r/8
n = (r+p+3)/2
z = 2*r+p
' Loop over the 4 possible X values
for x=0 to 3
' Clean the screen
mset img, 80, 255
' Draws the road with color 1 borders
color 1
plot x,1
drawto p+x,1
color 0
drawto z+x-1,1
color 1
drawto z+p+x,1
move img+n, gbase + x * 80, 80
' Draw the road with color 2 borders
color 2
plot x,1
drawto p+x,1
plot z+x,1
drawto z+p+x,1
move img+n, gbase + 40 + x * 80, 80
next x
' Now, calculate the shifted track position for each curve value and set
' the value in each of the display lists.
d = dlist + 3 * y
for curvature=-5 to 5
' Calculate the X position
x = 81 - y * 189/100
x = ( x*x*curvature/729 + 80 -r -p )
' Get the graphics address to print this position
tmp = gbase + 40 - n + x&3 * 80
tmp = tmp - x/4
' Calculate each of the 6 frames (with shifted Z value)
for z=zpos to zpos+100 step 17
poke d,77
dpoke d+1, tmp + (z/50)&1 * 40
d = d + dlsize
next z
d = d+88
next curvature
' Advance the pointer to the graphics data
gbase=gbase+320
' Fixes crossing over 4KB - this depends on the initial address!!
if gbase&4095 > $EFF
gbase = gbase+256
endif
next y
' Adds display list first and last bytes to all DLs
d = dlist
for curvature=0 to 10
for z=0 to 5
' First, 3 * 8 blank lines
dpoke d, $7070
poke d+2, $70
d = d + dlsize
' At end, 8 blank lines, one text window line
dpoke d-9, $4270
dpoke d-7, dpeek(660)
' Jump to start
poke d-5, $41
dpoke d-4, d - dlsize
next z
d = d + 88
next curvature
' Clears PM data
mset pmadr(0), 1024, 0
' Our car bitmap data for the PM 0 and 1
data pm1() byte = $18,$18,$18,$3C,$3C,$24,$24,$3C,$00,$18,$18,$3C,$7E,$7E,$00,$FF,$00,$7E,$7E
data pm0() byte = $24,$24,$24,$3C,$3C,$00,$7E,$18,$DB,$C3,$C3,$C3,$FF,$FF,$FF,$C3,$C3,$C3,$C3
' Move to PM
move adr(pm1), pmadr(1)+97, 19
move adr(pm0), pmadr(0)+99, 19
' P/M over playfield and P0+P1 / P2+P3 blends
poke 623,33
' Set color registers
poke 712, 8
dpoke 704, $4482
poke 710, $D2
dpoke 708, $EE52
dpoke 706, $8640
' P0 quad width, P1 double width
dpoke $d008, 259
' P2 shows distance traveled, set a basic shape
dpoke pmadr(2)+131, 511
' Enable ANTIC P/M DMA
poke 559, 58
' Start of game loop
spos = 3000
do
'# Current "drag"
drag = 0
'# Position in track
trackPos = 0
'# Current speed
speed = 0
'# Track "low" position
trackLow = 0
'# Location of "curve" DL ( 1024 * (c+5) )
curvature = 5
'# End of current track segment
segend = 99
'# Position of car
x = 1920
' Main game loop, starts from "spos".
' On first run has a value bigger than the end,
' so the race goes straight to the end screen.
for z=spos to 3000
' Waits for VBLANK, read collision register
pause
tmp = peek($d004)
' Clear collision register
poke $d01e, 0
' Set PM0 and PM1 x coordinates
pmhpos 0, x/16 - 8
pmhpos 1, x/16
' Sets DL (for next frame)
dpoke 560, dlist + curvature * 1024 + dlsize * (trackPos mod 6)
' Advance track position
trackLow = trackLow + speed
trackPos = trackPos + trackLow / 112
trackLow = trackLow mod 112
' "motor" sound. Note the values of frequency=k*31-1 produce pure tones,
' but we don't have enough space to filter out.
sound 0, 255 - speed, 6, 8
' Process collisions with the outside of the track
if tmp
' Decreases the speed by 5%
speed = speed * 19 / 20
else
' Increases the speed, max speed is 2 if button is not pressed, 1 if pressed.
' Scaled by 112
speed = ( 211 + 112 * STRIG(0) + speed * 99 ) / 100
endif
' Read joystick
tmp = STICK(0)
' Updates X position, adds joystick and "drag" times "speed"
' As drag is scaled by 50/9, speed by 112, and c by 16, we need to
' divide by (50*112)/(9*16) = 38.88 ~ 39
x = x + (tmp&4) * 4 - (tmp&8) * 2 - drag*speed/39
' Test if current track segment is over
if trackPos > segend
' Yes, generate a new segment
' (first, set text position to 0)
poke 657, 0
' New random direction
curvature = rand(11)
' Drag is from -0.9 to 0.9 (scaled by 50/9)
drag = curvature - 5
' New random length, from 10 to 110.
segend=segend+rand(100)+10
' Shows the current time and position
print "T:"; z, "D:"; trackPos,
endif
' Sets the Player 2 position to current track position
pmhpos 2, 48 + trackPos / 32
next z
' End of game, shows score, turns of sound and waits for keystroke
print "LAST:"; trackPos,
sound
get tmp
' Next race starts at time 0 (a full race)
spos=0
loop