Dreamcast low-level dev.
Contents
Introduction
The Dreamcast can be a challenging target for codegolfing, the
SH-4 CPU is a
traditional RISC to the core with 16-bit instruction size, this is
good for codegolfing but being RISC and without the "hacks" of
similar RISC CPU such as ARM (barrel shifter) there is constraints
such as :
- MOV only supports an 8-bit immediate; loading constants may
pass by a load operation or tricks
- you cannot shift by arbitrary constant amount
- delay
slot
- available
addressing modes may be annoying although not so horrible for
RISC
All these constraints are somehow balanced by the 16-bit
instruction size but some of these can still become a pain for
codegolfing...
The good stuff for codegolfing is relative to the amount of
available registers and instructions such as the floating-point
instructions (2-way superscalar architecture, SIMD), there is also
no headers. (unless you count the IP.BIN boot program or image file
as header)
How to run old intros
There is some
256b and
128b for Dreamcast but they don't run anymore on the emulators
i tried, to run them you may have to use official BIOS file and
change VIDEO_RAM (and also VIDEO_BASE) constant to 0xa5200000
instead of 0xa5000000 then assemble. (see setup below)
This is due to the state of the PowerVR graphics engine after
boot which is set to this address on original BIOS, it was probably
unneeded at the time of these intros due to the state of Dreamcast
emulation.
This is not a perfect solution though because the intros will
run in a tiny area of the screen, this might be due to the intro
being made for a different video mode... didn't look yet but what i
know is that after boot the display mode is 640*480 RGB565, this
might depend on video connection type (cable type in Redream)
though which was set to RGB for my test.
The alternative is to change the framebuffer start address and
setup a video mode, this is much bigger obviously, it can be done
by looking at
dreamhal videos mode setup.
Documentation
-
dreamhal hardware abstraction library is a good quick starting
resource (C code)
- SH4 manual and hardware documentation can be found here
- Dreamcast Dev/Box manual can be also useful
- Raymond
Chen articles on the SuperH-3 is incredibly useful as a
starting point (and apply to SH-4), giving many hints and
tricks
Setup (on LINUX)
Here is a guide to setup a Dreamcast development environment,
note that i was only interested in running SH4 assembly code for
raw graphics stuff so i didn't test anything else :
Emulators
- Redream seems accurate so i use this, there is also Reicast which works fine
Toolchain
I basically followed
this guide up to building KOS examples to build the toolchain
on my machine.
Build may fail due to unavailable GNU mirror, this can be
easily fixed by using another one by editing the file
scripts/download.mk.
The steps i added afterward to be able to build images so the
program can be run on the Dreamcast is related to compiling
mkdcdisc tool
:
sudo apt install git meson build-essential pkg-config libisofs-dev
git clone https://gitlab.com/simulant/mkdcdisc /opt/toolchains/dc/mkdcdisc
cd /opt/toolchains/dc/mkdcdisc
CC=gcc-13 CXX=g++-13 meson setup builddir
note : you might have to replace gcc and g++ version, i used this because mine were old and compilation failedCC=gcc-13 CXX=g++-13 meson compile -C builddir
Assembly and running
your program
/opt/toolchains/dc/sh-elf/bin/sh-elf-as
-little test.s -o test.o
/opt/toolchains/dc/sh-elf/bin/sh-elf-ld --oformat elf32-shl -Ttext
0x8c010000 test.o -o test.elf
/opt/toolchains/dc/mkdcdisc/builddir/mkdcdisc -e test.elf -o
test.cdi -n "my test disc"
Then you can just call either reicast or redream with the .cdi
file as input on the command-line.
Note that you may need the original BIOS file. (emulator
provided one didn't work for me)
Note : There is also the old way (without mkdcdisc) with
mkisofs and cdi4dc tools detailed here.
cdi4dc tool can be downloaded here for Linux and you will
need to generate a valid IP.BIN file as well for this process,
makeip
is able to do that.
Assembly build shell script
Here is a shell script to assemble a .s, build the .cdi and
run it with redream, pass the .s filename without the extension to
assemble your code (may want to change redream path as well)
:
#!/bin/sh
set -eu
/opt/toolchains/dc/sh-elf/bin/sh-elf-as -little $1.s -o $1.o
/opt/toolchains/dc/sh-elf/bin/sh-elf-ld --oformat elf32-shl -Ttext
0x8c010000 $1.o -o $1.elf
/opt/toolchains/dc/mkdcdisc/builddir/mkdcdisc -v 3 -e $1.elf -o
$1.cdi -n "" -m
~/redream.x86_64-linux-v1.5.0-1106-g01ef607/redream
$1.cdi
SH-4 basic template for pixels write after boot
This code clear the screen and plot a white centered pixel
right after boot, the video mode after boot is 640*480 RGB565 but
might depend on video connection type (cable type in Redream), mine
was set to RGB here. (composite also works)
Note that accessing VRAM directly is slow on the Dreamcast but
is handy for raw stuff !
mov.l VIDEO_BASE,r0
mov #0,r1
mov.l CLRCOUNT,r2
clr:
mov.l r1,@r0
dt r2
bf/s clr
add #4,r0
bra main
nop
.align 4
CLRCOUNT: .long 640*480
main:
mov #-1,r1 ! full white; pixel16 = ((r >>
3) << 11) | ((g >> 2) << 5) | ((b >> 3)
<< 0)
mov.l CENTERED_PIXEL_ADDR,r0
mov.l r1,@r0
bra main
nop
.align 4
VIDEO_BASE: .long 0xa5200000
CENTERED_PIXEL_ADDR: .long 0xa5200000 + (320 +
(320 * 480)) * 4
As a small "trick" you can use r0 to reuse the VIDEO_BASE with
indexed register indirect addressing mode :
...
mov.l VIDEO_BASE,r0
main:
mov #-1,r2
mov.l CENTERED_PIXEL_ADDR,r1
mov.l r2,@(r0,r1)
bra main
nop
.align 4
VIDEO_BASE: .long 0xa5200000
CENTERED_PIXEL_ADDR: .long (320 + (320 * 480)) *
4
back to top