Home
Admin | Edit

Eadem Mutata Resurgo - RISC OS 128 bytes

link

A mode 13 320x256 256 colors 128 bytes procedural graphics for RISC OS shown at at Lovebyte 2025.

Target hardware was 1987 Acorn Archimedes computers (A305, A310 etc.), may works on any versions of RISC OS though, even on a Raspberry PI !

Algorithm is a simplified variant of the one i used in Bloom 612; it is a double integer circle algorithm with a scaling pass, it render a colorful logarithmic spiral.

The algorithm was already quite small, it use a lot of shifts which is very easy to do with the ARM barrel shifter, i thought this was a perfect opportunity to simplify it and try a 128 bytes program on ARM, i was unsure of the result since each instructions takes 4 bytes on early ARM (no thumb) but there is still a lot of cool things with ARM such as 3 operands instructions, "flexible" constant load, multiply plus accumulate and conditional instructions, they help a lot.

8 bytes are used to setup the screen mode, 24 bytes are used to get the screen address so the remaining 96 bytes is the algorithm code. (32 instructions total !)

ARM code (note : BBC Basic inline assembly syntax)

swi OS_WriteI+22
swi OS_WriteI+13 ; mode 13

adr r0,screenAddrInput
adr r1,screenAddrOutput
swi "OS_ReadVduVariables"
ldr r0,[r1] ; screen address in r0

mov r2,#1048576
mov r3,#0
mov r4,#524288
mov r5,#262144

mov r12,#320

mov r1,#16777216
.l
 add r2,r2,r3,ASR #5
 sub r3,r3,r2,ASR #5

 add r4,r4,r5,ASR #6
 sub r5,r5,r4,ASR #6

 mov r7,r4,ASR #13
 mov r8,r2,ASR r7
 mov r9,r3,ASR r7
 mov r9,r9,ASR #16
 mla r10,r9,r12,r0
 add r10,r10,r8,ASR #16
 add r10,r10,#41216

 strb r6,[r10,#-96] ; plot

 movs r11,r1,ASL #17
 addeq r2,r2,r2,ASR #7
 subeq r4,r4,r4,ASR #6
 addeq r6,r6,#1

 subs r1,r1,#1
 bne l

; swi "OS_Exit" ; clean exit (+4 bytes)

.screenAddrInput
 .dcd 148
 .dcd -1
.screenAddrOutput

p5js prototype code

let x0 = 1 << 20
let y0 = 0

let x2 = 1 << 19
let y2 = 1 << 18

function setup() {
  createCanvas(320, 256)
 
  background(0)
 
  noLoop()
}

function draw() {
  let f = 0

  loadPixels()
  for (let i = 16777216; i >= 0; i -= 1) {
    x0 += y0 >> 5
    y0 -= x0 >> 5

    x2 += y2 >> 6
    y2 -= x2 >> 6

    let s = x2 >> 13
    let px = (x0 >> 16) >> s
    let py = (y0 >> 16) >> s
    
    let offset = (width / 2 + height / 2 * width) * 4
    let index = offset + (px + (py * width)) * 4

    let p = pal[f & 255] // note : pal is a 256 values array of { r: n, g: n, b: n } which represent the colors palette

    pixels[index + 0] = p.r
    pixels[index + 1] = p.g
    pixels[index + 2] = p.b

    if ((i & 32767) == 0) {
      x0 += x0 >> 7
      x2 -= x2 >> 6
      
      f += 1
    }
  }
  updatePixels()
}

back to topLicence Creative Commons