1. Copperbars
This is the first coding example I upload here. This is an old effect the Amiga was very famous for: the copperbars, or rasterbars.
These bars were very easy to do on an Amiga, as all that was needed was to put color values paired with the coloraddress into a copperlist. When the copperlist was done, the processor didn't need to do any more during that frame with colorchanges or anything. The special chips in the Amiga took care of it all.
THIS DEMO
This demo uses the Copper to change the background colors according to how 3 virtual rasterbars are moving in a circular manner. There isn't any real fancy coding behind this, the code is quite easy to read as no real codeoptimization is done.
The circular movements that are in the demo are made with precalculated sinus and cosinustables, the trigonometrytabels are 360 degrees (or 2pi) projected onto 256 bitgrads. The amplitudes and zeroaxis are modified to suite assemblycoding with integers, for example the cos255table has an amplitude of 127 and zeroaxis of 128. This gives a table with integervalues in the range of [0,255], and thus a byte is sufficent to store the value.
The 3 copperbars are moving upanddown according to a precalced sinustable, called sin255_60. This table is made up mostly in the same manner as the cos255table, but here the amplitude is 30 and the values of the table are [0,60]. This makes an circle with a radius of 30.
The copperbars are 30px high with each row having an own colorvalue (execpt the two in the middle have the same colorvalue). Each of the bars have pure red, green or blue colors, this is used as an other effect.
Sinus is used to calculate the heightposition of the bars and cosinus as depthposition. If we could look into the monitor from the side, the bars would seem to make a perfect circle in their movement. This isn't suprising if you know about the "unit circle" of trigonometry. The Copperbars could be made to move in many different patterns.
161 
; change angles according to anglespeed

162 
move.b anglespeed,d1

163 
move.l #sin255_60,a0

164 
move.l #cos255,a1

165 
move.l #cbar_a,a2

166 
move.l #cbar_y,a3

167 
move.l #cbar_z,a4

168 
move.b #4,d2

169 
loop_copperbars:

170 
move.b (a2),d3 ; angle

171 
add.b d1,d3 ; angle + anglespeed

172 
move.b (a0,d3),d4 ; y from sintable

173 
move.b (a1,d3),d5 ; z from costable

174 
move.b d3,(a2)+ ; angle

175 
move.b d4,(a3)+ ; y

176 
move.b d5,(a4)+ ; z

177 
subq.b #1,d2

178 
bne loop_copperbars

Here we can see from the source how the sin255_60 and cos255 tables are used as lookup tables for values. Cbar_a is angle, _y is height position and _z is depth position. The fetched values are then stored into memory for later processing.
After this we have to get the relative positions of the bars correct according to their depth position. This is a matter of sorting the bars from largest to smallest depthvalue. As here is only 3 bars used, I didn't write a sorting routine, but merely compairing 3 pairs of bars can sort it out without a routine, this is a little messy, but efficient.
180 
; get zvalue for all bars

181 
move.l #0,copperbars_z ; 0 to z for all 3 bars

182 
move.l #cbar_z,a2

183 
move.b (a2)+,d1

184 
move.b (a2)+,d2

185 
move.b (a2)+,d3

186 
moveq #0,d4 ; z red

187 
moveq #0,d5 ; z grn

188 
moveq #0,d6 ; z blu

189 
; compare zvalues

190 
cmp.b d1,d2

191 
bcc z1

192 
addq #1,d5

193 
bra z1e

194 
z1:

195 
addq #1,d4

196 
z1e:

197 
cmp.b d1,d3

198 
bcc z2

199 
addq #1,d6

200 
bra z2e

201 
z2:

202 
addq #1,d4

203 
z2e:

204 
cmp.b d2,d3

205 
bcc z3

206 
addq #1,d6

207 
bra z3e

208 
z3:

209 
addq #1,d5

210 
z3e:

211 
move.l #cbar_z,a2

212 
move.b d4,(a2)+ ; red

213 
move.b d5,(a2)+ ; grn

214 
move.b d6,(a2)+ ; blu

Registers d1 & d4 are for the REDbar, d2 & d5 are for the GRNbar and d3 & d6 are or the BLUbar. In each comparison the "color" with the larger value will get an 1 added to its companion register d(n+3). After this the values stored for depth are 0, 1, 2 and these values are easy to use for testing agaist an iterative index in a loop.
In the iterative loop all the rasterlines are put into an array in the correct order: the lowest first and then the others painted over. The routine could be optimized to not paint the same line in the array many times, but as I wanted a special "addative"/"ORed"mode for painting as well, the optimizition doesn't work. The "addative"mode plays with logigalOR to get more colors from the copperbars, but at the same time the "3D"illusion of the bars is gone.
253 
loop_copperline_render:

254 
cmp.b #0,cbar_mode

255 
bne cbar_additive

256 
move.w (a2)+,(a3)+

257 
bra cbar_normal

258 
cbar_additive:

259 
move.w (a2)+,d1

260 
ori.w d1,(a3)+

261 
cbar_normal:

262 
subq.b #1,d7

263 
bne loop_copperline_render

In this codesnippet the difference between normal "overpainting" of lines in the array and the "addative" ORed value. Red or Grn = Yel, Grn or Blu = Cya, Blu or Red = Mag and different hues of those colors. But at this time everything is still "painted" into an array, not a copperlist.
271 
move.l #copperlines1,a2

272 
move.w cbar_start,d3 ; startline

273 
move.w #0,d7

274 
loop_rasterlines_copper:

275 
move.w d3,d4

276 
add.w d7,d4

277 
cmp.w #256,d4 ; PAL needs a trick to handle more than 256 lines in overscan

278 
bne no_PAL_fix

279 
move.l #$ffdffffe,(a6)+

280 
no_PAL_fix:

281 
; wait

282 
move.w d7,d4 ; d4=d7

283 
add.w d3,d4 ; d4=d7+d3 (d7+startline)

284 
lsl.w #8,d4 ; d4=(d7+startline)<<8

285 
add.w #$07,d4 ; d4=(d7+startline)<<8+07

286 
move.w d4,(a6)+ ; Wait  first line ex: $6407

287 
move.w #$fffe,(a6)+ ; Mask

288 
; color

289 
move.w #$0180,(a6)+ ; Color0

290 
move.w (a2)+,(a6)+ ; Colordata

291 
;

292 
addq.w #1,d7

293 
cmp.w #90,d7

294 
bcs loop_rasterlines_copper

Addressregister a6 is here a pointer to the copperlist that is being generated.
Write a Comment