Isopolis - Atari ST 256 bytes

A 256 bytes Atari ST (1985) cityscape attempt for
Outline 2025 which came
after some iterative
Dimetric cube experiment using the HAKMEM
149 algorithm.
The original idea was way more ambitious /
real-time with palette rotation and building details but i couldn't
pull it off, the end result is still okay anyway even if a bit dull
and not animated, this algorithm wasn't really suited for this
platform perhaps, it is too fancy, ARM would be best due to heavy
use of shifts !
Buildings could perhaps be done better with
simple x,y iterations or specific Line
A calls. (using fill patterns for details ?)
First implementation was all grayscale but it was
a tad boring so the gradient / shades were added up, trails were a
quick cheap addition which ended up okay.
This use Line A putpixel
heavily.
The initial prototype wasn't particularly
optimized and i departed heavily from it, had to look at some
issues :
- good predictable randomness, ended up using a 16 bits MCG (8 bytes)
- good seed, chosen value turns out to be the first palette value, had some luck...
- trying to fill the scene (gradient, colors, shades, trails), building details was too heavy / noisy, also experimented with geom variations
- speed, first tests were on 32 MHz m68k, draw speed was fine but it was very slow at 8 MHz...
Biggest issue after optimizations was to get around crashes on
specific RAM amount (>= 4MB) due to unchecked putpixel calls,
this was concerning as it was the compo machine...
The crash fix was to check every putpixel calls for
coordinates that goes outside the screen, this ended up too heavy
so i had another go at optimizations.
The speed improved by a factor of two with the fix so ~1m5s vs
+2 minutes to render the screenshot above, not instant yet... but
way more acceptable ! Many speed optimization may be left over.
(especially on the use of word vs long)
Actual binary size is 288 bytes (300 bytes with
clean exit) due to the 32 bytes program header but the party didn't
count the header.
Versions

very early version, different seed / gradient,
kinda liked this due to density and colors

early version with the palette

different geom, no bytes change

a mix of both geom; heavier

shading variations, too dim

"CGA"
like

fancier gradient (inspiration was C64 They are spraying
by Gordian) : (y >> 5) & (y >> 3)

messy if run for too long... (~2 minutes)
Sources
; vasmm68k_mot -m68000 -Fbin isopolis.s -o
isopolis.tos
dc.w $601a ; ph_branch
dc.l end-start ; ph_tlen
dc.l $0 ; ph_dlen
dc.l $0 ; ph_blen
dc.l $0 ; ph_slen
dc.l $0 ; ph_res1
dc.l $0 ; ph_prgflags
dc.w $1 ; ph_absflag
start
dc.w $a000 ; Line A init call
movem.l (a0),a1-a4
sf -6(a0) ; disable cursor / blinking
; supervisor mode for mem. access
move.w #$20,-(sp)
trap #1
; palette setup
lea pal(pc),a2
movem.l (a2),d0-d5
movem.l d0-d5,$ff8240
; vertical gradient
move.w #199,d7; d0,d7 shorter but seems to crash
with different RAM setup (>= 4MB)
y:
move.w d7,d5
asr.w #5,d5
move.w #319,d6 ; d3 save
2 bytes but way too slow...
x:
move.w d5,(a3)
move.w d6,(a4)
move.w d7,2(a4)
dc.w $a001
dbra d6,x
dbra d7,y
loop:
; trails
move.w #9,(a3)
move.w d7,(a4)
move.w d3,2(a4)
cmp.w #199,d3
bgt skipTrail
dc.w $a001
skipTrail
addq.w #1,d7 ;
framecount
; building setup
move.w d7,d2
and.w #63,d2 ; very fast
when using d3 but has shading issues
bne.s skipNext
move.w (a2),d0
mulu #47989,d0 ; rng, seed at pal(pc)
move.w d0,(a2)
asr.l #7,d0 ; higher bits for better small range values
move.l d0,d4
and.w #7,d4
bne.s skip
moveq #2,d4
skip
subq.w #1,d4 ; s
moveq #1,d3
lsl.l d4,d3
subq.w #1,d3 ; r
move.l d0,d2
and.w #511,d2 ; can be removed with move.w below for 4 bytes gains
but meh result (may works with different seed though)
move.l d2,a5 ; x offset
swap d0
and.w #127,d0
add.w #52,d0
move.l d0,a6 ; y offset
skipNext
move.l d3,d6 ; x
and.w d7,d6
clr.l d5 ; y
swap d7
; iterate & draw
move.w #1276,d7
i:
move.l d6,d0
asr.l d4,d0
add.l d0,d5 ; y += x >> rs1
move.l d5,d0
asr.l #8,d0
sub.l d0,d6 ; x -= y >> 8
; y -= i & 1
btst.l #0,d7
beq skipAdjust
subq.l #1,d5
skipAdjust
;move.w d7,d0
;and.l #1,d0
;sub.l d0,d5 ; y -= i & 1
; top color
move.l #11,a1
sub.l d4,a1
; geom variation but inconsistent (note : use d1 as shift value for
asr.w #1,.. below)
;clr.l d1
;tst.w (a2)
;blt s
;moveq #1,d1
s
move.l d3,d2
asr.w #1,d2
sub.l d5,d2 ; (r >> 1) - y
move.l d3,d0
sub.l d6,d0
asr.w #1,d0 ; (r - x) >> 1
; face color
move.l d0,d1
bpl skipNegate
neg.l d0
skipNegate
cmp.l d2,d0
blt draw
tst.w d1
bmi skipLeft
subq.w #1,a1
bra.s draw
skipLeft
subq.w #2,a1
draw
move.w a1,(a3) ; color
move.w d6,d2
add.w a5,d2
swap d2
move.w d5,d2
add.w a6,d2
cmp.w #199,d2
bgt skipDraw
move.l d2,(a4)
; slower ->
;move.w a5,(a4) ; offset
;add.w d6,(a4) ; + x
;move.w a6,2(a4) ; offset
;add.w d5,2(a4) ; + y
dc.w $a001 ; plot
skipDraw
dbra d7,i
swap d7
bra loop
; clean exit support (+12 bytes)
; cmp.b #$39,$fffc02
; bne loop
; clr.l -(a7)
; trap #1
pal
dc.w $036,$136,$236,$336,$436,$546,$656
dc.w $666,$444,$777
end
back to top


