Trying to build and run a working Saturn sample program

sparrow

New Member
I've been banging my head against a wall for a couple of weeks now, on and off, so I'm hoping some kind person here can point me in the right direction :)

My goal: get a sample program building from source and running on a Saturn emulator, so I can start feeling my way around a working program, iterating changes and learning about the Saturn bit by bit.
(Running on real HW would be fine too, but from what I can tell that is more difficult for a beginner given lack of available tools.)
My main target at first is graphics, so anything that puts pixels on the screen will do, maybe with some basic controller input for parameter tweaking.

Where I'm at right now: I can build the SBL and SGL sample programs no problem, but I cannot get them to run in an emulator. I have actually failed to get *anything* that is not part of a pre-built ISO to run in an emulator.
Since I'm not sure where I'm going wrong, I will describe in as much detail as I can below how I got to this point.

I'm not attached to getting these specific samples to run, anything will do I guess! I just chose them since they were official, seemed to be well documented, and used standard build tools. I've downloaded a bunch of homebrew samples too, but all the ones I've found so far looked like they would send me down a rabbit hole of using ancient windows binaries of dubious origin which I was keen to resist if at all possible...

My background: programmer with experience in various languages and environments, including C/C++ on a variety of platforms, but no embedded experience - I'm used to having the linker magically produce an executable and having the OS run it for me! :)

Environment: Linux using GNU toolchain, and Yabause or Mednafen as the emulator.
(I would consider switching to Windows if the tooling is much better, although all my Windows experience is MSVC rather than GNU tools.)


What I have done so far:


1) Built sh-elf GNU tools using this thread as a guide: Building your own toolchains

I used GCC 9.3.0, and Binutils 2.34, in addition to the old `gasp` asm-preprocessor from Binutils 2.12 needed by SEGA's `gasm` script.

When set up to do Saturn dev, my PATH includes an sh-elf symlinks dir looking something like this:

Code:
as -> ../bin/sh-elf-as
gasm -> ../../libs/SBL6/segalib/awk/gasm.sh
gasp -> ../../binutils-2.12/bin/sh-elf-gasp
gcc -> ../bin/sh-elf-gcc
ld -> ../bin/sh-elf-ld
objcopy -> ../bin/sh-elf-objcopy
objdump -> ../bin/sh-elf-objdump
(There's more, but I abbreviated the list for clarity)

gasm.sh is SBL's GASM.BAT converted to bash, it seems to be working fine.

With this setup, most SEGA Makefile seem to work out of the box without modifications.



2) Built SBL samples

I downloaded SBL601.ZIP from antime.kapsi.fi and built some samples with the above tools using the sample's provided Makefile.

The linker complained about 'ambiguous object format' of the pre-built .a files under segalib/lib, but that was easily fixed with `objcopy -O elf32-sh in.a out.a && mv out.a in.a`, after which there were no problems.

Depending on the the sample, I now have a game.cof file, and in the case of game_cd, a game.bin file.
The .cof file is sometimes actually an ELF depending on the specific sample, but whatever - objcopy detects the format correctly regardless of extension.

3) Make a disc image

I've done this two ways:
a) produce a BIN/CUE for SBL's game_cd sample, because that includes CD audio.
b) produce an ISO containing the game.bin file for other more self-contained samples, using a mkiso command I found on this forum.

I'll go through both.

3.a) Try to run SBL game_cd via BIN/CUE

Run `make` inside the game_cd directory. This produces a game.bin file.

Strangely for SBL samples, but not for SGL samples, the `objcopy -O binary` command used to produce the game.bin file outputs padding prior to the actual code at the 0x06010000 start address, so the game.bin file itself is 97mb of mostly junk.

I worked around this with `dd if=game.bin of=game.new bs=1 skip=100728832 && mv game.new game.bin` to chop off the first 0x6010000 bytes, and the resulting game.bin file now looks similar other non-inflated .bin files from other samples.

Ok, so now to turn this into a CD image.

First, I copied segasmp/sys/ip_gnu.bin to ip.bin in the game_cd directory. I don't 100% understand the IP.BIN format yet, but I understand from the docs that this one is for use with the samples. I have tried with both the provided binary, and a binary rebuilt from source. I have confirmed that the ip.bin contains the correct start address.

Then I opened Dosbox and used VCDTOOLS:

vcdbuild.exe game.scr

This produces GAME.DSK and GAME.RTI.

I then used CyberwarriorX's tool to turn this into a CUE/BIN:

stripvcd.exe game.rti -o cd.bin

If I load this CUE/BIN in either emulator, it shows the SEGA logo, goes to a black screen, and hangs.

In Yabause if I open the debugger, the master SH2 always seems to be executing at an address that corresponds to a function _SND_ChgMap in the game binary, which seems to be SBL internals (appears in segalib binaries).

I do not know SH2 ASM (or indeed any ASM!), so I can't really follow what it is doing, but it does not look like much. (I was looking forward to learning SH2 as part of this project, but I'd rather start on working code to be honest...)

(It's worth noting I guess that even if I did get this process to work, it's way too involved for any kind of reasonable iteration cycle... I guess I might be able to automate it?)

3.b) Try to run a bin-only sample via ISO

I've tried this on numerous samples such as several under segasmp/sblsgl, or segasmp/spr, and samples from the SGL libraries such as samples/akira or demos/biplane.

Build steps are the same as above, and to make the ISO I use this command:

Code:
genisoimage -sysid "SEGA SATURN" -volid "volumeid" -volset "volumeset" -publisher "SEGA ENTERPRISES, LTD." -preparer "SEGA ENTERPRISES, LTD." -appid "applicationid" -generic-boot ../../sys/ip_gnu.bin -full-iso9660-filenames -o OUT.ISO game.bin
(Note that SGL ip.bin differs from SBL sample ip.bin, so that part of the command changes.)

Loading this results in a brief pause, and then bailing to the BIOS CD player screen, with a 'start application' button that repeats the process.

I have sucessfully used this genisoimage command to reproduce a working image from an existing ISO I found - i.e. I extracted the ip.bin from the ISO, and copied the files out, and then re-built a new ISO from the files and the ip.bin. That worked, so it's probably not a problem with the command above but rather the files I am feeding into it?


Anyway... I could keep grinding on this for a while I'm sure, but I'm almost out of energy at this point. Does anyone have any pointers for me? :)

Please let me know if I'm down totally the wrong path - thanks!
 

antime

Extra Hard Mid Boss
To cut down on the complexity, first try getting your sample running using the emulator's file loading functionality (Yabause has one, I have no idea about Mednafen). You can also further cut it down by not calling any libraries, just have a simple loop or something, and then use the emulator's debugger to step through execution.

If converting the final object to binary produces a padded file, it usually means there's something wrong with the linker script, or linker invocation. Something (usually the linker script) should be setting the location counter to 0x6010000, now it's defaulting to zero.

And yes, writing makefiles or CMake scripts, or whatever your preferred build tool is, is someting you should set up immediately. CMake is pretty well supported in IDEs nowadays, if those are your thing. Even Visual Studio supports them, but I have no idea if it properly supports external cross compilers as well. Some of my colleagues at work use CLion by JetBrains, and seem to be mostly happy with it.
 

sparrow

New Member
Thanks for the reply. Do you have a specific version of Yabause that you can recommend? I'll get that one set up. The Yabause website has disappeared from the internet, so I used the version bundled with my Linux distro - 0.9.14 - which does not appear to have any bin loading functionality (--binary is listed in command line help, but it does nothing)

I will try the small loop idea later today, good call. Didn't cross my mind because of the lack of output, but I guess seeing my code in the debugger is a good enough test.
 

vbt

Staff member
it think the binary is so big because rodata section is missing
try a linker script like here :

 

sparrow

New Member
Progress!

First, for the SBL6 samples, the following patch alluded to by vbt fixes the padded game.bin issue:

Code:
diff --git a/segasmp/lib/saturn.lnk b/segasmp/lib/saturn.lnk
index abcd8aa..7bbf814 100644
--- a/segasmp/lib/saturn.lnk
+++ b/segasmp/lib/saturn.lnk
@@ -26,6 +26,12 @@ SECTIONS
                SIZEOF_R = . - STARTOF_R;
                ENDOF_R = .;
        }
+
+    .rodata ALIGN(0x10) :
+    {
+       *(.rodata)
+    }
+
        .bss ALIGN(0x10) (NOLOAD):
        {
                STARTOF_B = .;
With this, the game_cd sample built via vcdtools as described above actually works!


Second, I got Yabause's --binary option to work now, which opens up a whole bunch of things I can run and experiment with. All the SBL samples I've tried so far work, and a couple of other bits and pieces.

I have no idea what the problem with --binary was before... I guess Yabause is finnicky about the address syntax and I just didn't try the right combo?
I also still don't know why building an ISO wasn't working, but thankfully it's irrelevant to my needs for now :)

I think this is the foothold I needed. Hopefully I wont be back to ask for help until I'm ready to start developing on real hardware.
Thanks so much for your suggestions!
 

vbt

Staff member
Progress!

First, for the SBL6 samples, the following patch alluded to by vbt fixes the padded game.bin issue:

Code:
diff --git a/segasmp/lib/saturn.lnk b/segasmp/lib/saturn.lnk
index abcd8aa..7bbf814 100644
--- a/segasmp/lib/saturn.lnk
+++ b/segasmp/lib/saturn.lnk
@@ -26,6 +26,12 @@ SECTIONS
                SIZEOF_R = . - STARTOF_R;
                ENDOF_R = .;
        }
+
+    .rodata ALIGN(0x10) :
+    {
+       *(.rodata)
+    }
+
        .bss ALIGN(0x10) (NOLOAD):
        {
                STARTOF_B = .;
With this, the game_cd sample built via vcdtools as described above actually works!


Second, I got Yabause's --binary option to work now, which opens up a whole bunch of things I can run and experiment with. All the SBL samples I've tried so far work, and a couple of other bits and pieces.

I have no idea what the problem with --binary was before... I guess Yabause is finnicky about the address syntax and I just didn't try the right combo?
I also still don't know why building an ISO wasn't working, but thankfully it's irrelevant to my needs for now :)

I think this is the foothold I needed. Hopefully I wont be back to ask for help until I'm ready to start developing on real hardware.
Thanks so much for your suggestions!
share you iso and we will check it
common way to build iso looks like this :

mkisofs -sysid "SEGA SATURN" -volid "SoundPlayer" -volset "SoundPlayer" -publisher "SEGA ENTERPRISES, LTD." -preparer "SEGA ENTERPRISES, LTD." -appid "SoundPlayer" -abstract "ABS.TXT" -copyright "CPY.TXT" -biblio "BIB.TXT" -generic-boot IP.BIN -full-iso9660-filenames -o J:\MULTIB\SoundPlayer.ISO cd

i've never used genisoimage , also just be sure the start address in the ip.bin is the same as your binary start address
 

antime

Extra Hard Mid Boss
genisoimage is a fork of mkisofs, created because of licensing issues with cdrtools.
 
Top