Quick'n'Dirty Guide To
Coding Frame Buffer FX In Open Firmware
introduction
while playing around with booting custom darwin kernels, i recently discovered that my powerbook provides lots of fun without even booting an operating system. so i spent all of breakpoint 05 demo party in open firmware, trying to create some graphical effects. since there is not much documentation on this topic on the web, i wrote up the results of my try-and-error research here. since this is by no means exhaustive or coherent, feel free to contact me with questions =)
you can check out what i have accomplished so far if your dare:
hello.4th
setup the developing environment
to quickly write and test code for open firmware, a setup consisting of two hosts is recommended. the idea is to boot into open firmware on the mac and load the forth code via tftp over an ethernet link. a file called hello.4th located in /tftpboot on the server can be loaded in open firmware by the following command:
boot enet:172.23.5.23,hello.4th,172.23.5.5
with that setup, it is possible to conveniently edit the forth code on another machine and test it right away, without having to switch between darwin and open firmware. to avoid having to keep CMD-ALT-O-F pressed after booting every time, do setenv auto-boot? false
. this will drop you to open firmware after power on. to continue to boot into darwin, use mac-boot
.
header.4th
dev screen
one feature of open firmware is the ability to traverse the device tree via the dev
command. depending on where in the device tree you are located, there are different forth words available. use dev screen
to make the main screen the current dev node. (actually, screen is a devalias to the corresponding device node, try devalias screen
to check where it's pointing to) this gives you some interesting words:
screen-width
these expand to the dimension of the screen in pixels
screen-heightset-colors
this enables you to specify an 8bit palette.frame-buffer-adr
this is the base address of the frame buffer. write bytes to the memory range betweenframe-buffer-adr
andframe-buffer-adr + screen-width * screen-height
and watch how the pixels on the screen take on the corresponding index color.
variable RGB-temp struct ( 000 )
: color! ( r g b index -- )
>r
RGB-temp 2+ c!
RGB-temp 1+ c!
RGB-temp c!
RGB-temp
r>
1 set-colors
;
using this word, we can define our own palette. unfortunately, index #0 is used as text color and index #f is used as background color, so in order to still be able to read the text, we can only use index #10 to index #ff for a nice grayscale palette:
ff ff ff 0 color! ( foreground color )
00 00 00 F color! ( background color )
100 10 do i i i i color! loop
color.4th
fb.4th
sine table
since open firmwares forth interpreter doesnt know about floating point arithmetics, it is necessary to work with integer sine tables. a short c program generates a forth table consisting of 360 entries ranging from 0x8 to 0x7F (so we can add two sine values later on without minding index wrap around)
sin.c
tsin.4th
trig.4th
a sine field in forth
: sinefield ( -- )
numlines 0 do
i
screen-width 0 do
dup
dup sin i sin +
swap i pixeladr
c!
loop
drop
loop
;
since the primary data structure in forth is the stack, nested counting loops look kinda ugly =)
sinefield.4th