I built a Go runtime that runs on the Sega Dreamcast, the 1999
console with 16MB RAM and a 200MHz SH4 CPU.
You can write games in Go with goroutines, channels, garbage collection,
and all the language features you'd expect. It compiles using gccgo and
runs on real hardware or emulators.
The project includes 3 game examples Pong, Breakout and Platformer, input handling, audio support, and integrates with KallistiOS (the Dreamcast homebrew SDK).
I just wanted to say how impressive your documentation is. I expected an average readme.md, but not only is your readme great (the performance table is wonderful), but the full documentation is awesome. It pretty much answers all questions I had. Nice job! I wish all projects were like this.
Hey panos! I only had a short look at this for now, and it looks impressive! I'll have to dust off my Dreamcast and get this running.
I looked at gccgo when porting the runtime to n64, but at the time it wasn't updated since go1.18. Can we use Go Generics on the Dreamcast? I see that gccgo is obviously needed to support SH4.
> Replaces the standard Go runtime with one designed for the Dreamcast's constraints: memory 16MB RAM, CPU single-core SH-4, no operating system.
24 total megabytes, with an M, of memory between system and video (another 8 there), single core 200mhz CPU, graphics chip runs at 100mhz. Shenmue runs on it.
Could implement a custom Teams client on top of that. My biggest concern would be TLS and media decoding, but could just proxy the traffic and roll a text only client.
I mucked about with Microsoft Graph a bit before, didn't seem too bad.
It runs fine. It is perhaps a bit pricey for a 200MHz system, I'd certainly focus on having only a few of them and doing most of my work by looping over some sort of user-defined tasklet (or, in other words, "standard game architecture"), but it's not like Go requires multiple CPUs to work at all.
I didn't say it would not run and I am happy that Go is being used in gaming like this. But it's like buying a Koenigsegg and using to to drive into your near by grocery store as concurrency is at the heart of Go and having it run on a single core, or rather, i assume, thread, is not the best use case for it.
I'm actually not a big fan of people who recite "concurrency is not the same as parallelism" like a mantra because I don't think it's anywhere near as orthogonal as those people think. But then, that's also largely because multicore is the norm now, rather than some bizarre exception. In a single core case, it is still true. Goroutines are just a different way of achieving async functionality, in a way probably a lot more convenient than the actual code of the time had, albeit at a bit of a performance penalty.
There was a period of time towards the beginning of Go when you could get some small performance advantages for certain tasks by locking the runtime to one goroutine at a time. They've long since addressed that, but there was a time when there were people writing Go code and deliberately limiting it to one execution context at a time.
"concurrency is not the same as parallelism" is a "mantra" exactly because most people are unable to distinguish between them and/or understand the meaning. maybe not nowadays, but go back a decade and that was definitely the case.
Many thanks @dontaj much appreciated, indeed documenting the process felt like another project of its own, so I am very happy to hear that! The effective dreamcast Go was inspired from the old time classic https://go.dev/doc/effective_go :D
If someone is interested in running golang projects on niche hardware perhaps, one pro tip I can suggest but there is way to convert golang 100% into wasm (no js shim or anything required) and the only thing you would need is a wasm library
Although the way I did it is going into the gotip folder and then the binary folder which would contain the go compiler binary and then just use that path with
Note that I forgot the exact path but it was similar to this but the point being that its super easy and simple :)
I tried to do it and I can tell you that it works and it works for even the most latest versions of golang, all you need is a wasmengine which I suppose can be ubiquitous.
I have built a solution where golang code gets converted to wasm and then we run a ssh server which then runs that wasm all in sandbox to create sandboxed mini golang servers :p I really love it although its a more so prototype than anything
Looks like this is available (since Go 1.21 [0]), so no need to build from source anymore. Just did a quick 'hello world' test to verify and it worked:
GOOS=wasip1 GOARCH=wasm go build -o main.wasm main.go
wasmtime main.wasm
If you're interested in wasm/wasi and niche hardware with Go, you should check out TinyGo [1] if you haven't already.
Oh wow thanks for telling me, looks like I was using gotip/ source go for no reason but thanks for telling me this, this actually really simplifies a lot of things :p
Tinygo is really awesome but I have heard that it has its differences so software written for golang won't really work ootb on tinygo and tinygo is really fascinating project too!
I have a question but is it possible to create golang compiler itself within wasm itself. I tried doing it but it didn't really work out but I am curious if someone has thought of doing something like this or has already done it?
Nice project! Having just 16Mb of RAM does indeed sound like a real challenge for stock Go (not the TinyGo variant)! Even hello world is a couple megs, although I imagine Dreamcast isn't 64-bit, so the instructions are probably much shorter. Interesting to see anything written in it :)
> Who is this for?
> ...
> Anyone who enjoys the challenge of severe constraints
Remembering what a powerhouse the Dreamcast was when it came out, and how amazing games like Soul Caliber and Shenmue looked, it's hard to think of the Dreamcast hardware as "severely contained".
I find it a bit weird that I find it intuitive how things like the Super Nintendo did their work, and how modern games and systems work, but comparing the hardware specs of the Dreamcast/PS2/XBox/Gamecube era to the best of their output is where my intuition struggles the most. Not that the games of the era stand up to modern stuff, even when upscaled and texture-packed etc. in an emulator, but how they did it with so little oomph still amazes me.
yeah, been there, nostalgia hits hard. Dreamcast was a beast of its era, it even had Ethernet! Even the VMU was something extraordinary! Too bad SEGA had to cancel it :(
This is incredibly cool! How do you think these modern language features would have affected Dreamcast development back in the day? (I have no idea of how difficult the console was to develop.)
It was a dream relative to anything else on the market (until 2001, when the Xbox and GameCube were released), made even easier for some titles due to the optional Windows CE SDK. You still needed to do a fair bit of SuperH assembly programming to get reasonable graphics performance, but it was nothing like the nightmarish complexity of the PS2, despite having half the RAM. It's still one of the more popular homebrew targets.
I think Lua (yes you can code Dreamcast games with it) would be really awesome for kids, being able to make their own games, given the language is simple, like Python. But in general, for serious stuff C/C++ is still the preferred way.
I am using sh-elf-gccgo (GCC) 15.1.0 which is ok-ish I guess. But in general gccgo tries to be close to Go, but they do not implement all the features. e.g. generics are still missing for example.
problem is TinyGo uses LLVM, which doesn't support SH-4. The only reason I went with gccgo is due to SH4 target. In any case, I learned a ton of things doing this project :D
I built a Go runtime that runs on the Sega Dreamcast, the 1999 console with 16MB RAM and a 200MHz SH4 CPU.
You can write games in Go with goroutines, channels, garbage collection, and all the language features you'd expect. It compiles using gccgo and runs on real hardware or emulators.
The project includes 3 game examples Pong, Breakout and Platformer, input handling, audio support, and integrates with KallistiOS (the Dreamcast homebrew SDK).
* Star Here: https://github.com/drpaneas/godc * Documentation: https://drpaneas.github.io/libgodc/ * Video Tutorial: https://youtu.be/ahMl0fUvzVA
Happy to answer any questions about the implementation!
I just wanted to say how impressive your documentation is. I expected an average readme.md, but not only is your readme great (the performance table is wonderful), but the full documentation is awesome. It pretty much answers all questions I had. Nice job! I wish all projects were like this.
I also dig the documentation / book styling.
thanks @danhau, much appreciated, indeed documenting the process felt like another project of its own, so I am very happy to hear that :D
Hey panos! I only had a short look at this for now, and it looks impressive! I'll have to dust off my Dreamcast and get this running.
I looked at gccgo when porting the runtime to n64, but at the time it wasn't updated since go1.18. Can we use Go Generics on the Dreamcast? I see that gccgo is obviously needed to support SH4.
Hey Timur, long time no see, I hope all is going well :) No, you cannot use generics, they are not yet supported by gccgo.
This is a beautiful thing to exist. Much respect for building this.
You've made my entire WEEK! Thank you!
You've put a smile on my face reading your comment, thank you for your feedback, happy holidays :D
This is kind of cool, kudos for the effort.
you're very welcome :D Thanks!
> Replaces the standard Go runtime with one designed for the Dreamcast's constraints: memory 16MB RAM, CPU single-core SH-4, no operating system.
24 total megabytes, with an M, of memory between system and video (another 8 there), single core 200mhz CPU, graphics chip runs at 100mhz. Shenmue runs on it.
Glares at Teams.
I really don't get how Teams gets developed, not even the worst offshoring projects I have been part of, have reached so low in quality.
It baffles me that Microsoft can build an entire OS, and build and rebuild GUI stacks, and they couldn't build the Teams UI using C#???
Microsoft applications always look and behave as if they were ported to windows...
They needed true cross-platform consistence, so it had to be equally terrible everywhere.
If they built Teams with a C# UI framework, it'd have to be rebuilt 4 times by now.
They already had to rebuild it once because it was in angularjs lol
Maybe they know they’re going to do it badly and it will tarnish C#’s reputation.
Would happily take work chat, video conferencing in network-enabled Shenmue over Teams, Slack any day
As long as you don't work in the shipping industry. I hear it's next to impossible to get hold of any sailors over Shenmue
Could implement a custom Teams client on top of that. My biggest concern would be TLS and media decoding, but could just proxy the traffic and roll a text only client.
I mucked about with Microsoft Graph a bit before, didn't seem too bad.
> CPU single-core
This does not fare well for Go though.
It runs fine. It is perhaps a bit pricey for a 200MHz system, I'd certainly focus on having only a few of them and doing most of my work by looping over some sort of user-defined tasklet (or, in other words, "standard game architecture"), but it's not like Go requires multiple CPUs to work at all.
I didn't say it would not run and I am happy that Go is being used in gaming like this. But it's like buying a Koenigsegg and using to to drive into your near by grocery store as concurrency is at the heart of Go and having it run on a single core, or rather, i assume, thread, is not the best use case for it.
I'm actually not a big fan of people who recite "concurrency is not the same as parallelism" like a mantra because I don't think it's anywhere near as orthogonal as those people think. But then, that's also largely because multicore is the norm now, rather than some bizarre exception. In a single core case, it is still true. Goroutines are just a different way of achieving async functionality, in a way probably a lot more convenient than the actual code of the time had, albeit at a bit of a performance penalty.
There was a period of time towards the beginning of Go when you could get some small performance advantages for certain tasks by locking the runtime to one goroutine at a time. They've long since addressed that, but there was a time when there were people writing Go code and deliberately limiting it to one execution context at a time.
"concurrency is not the same as parallelism" is a "mantra" exactly because most people are unable to distinguish between them and/or understand the meaning. maybe not nowadays, but go back a decade and that was definitely the case.
Wouldn't it suit Go over some other architecture, because of goroutines being in userspace, the single CPU is effectively multithreaded when using Go
Most Go code on Kubernetes runs on a single core.
Paging Mythbusters
Huh?
The "Effective Dreamcast Go" docs on this are fantastically well written. I've read much worse docs from major corporations.
Many thanks @dontaj much appreciated, indeed documenting the process felt like another project of its own, so I am very happy to hear that! The effective dreamcast Go was inspired from the old time classic https://go.dev/doc/effective_go :D
If someone is interested in running golang projects on niche hardware perhaps, one pro tip I can suggest but there is way to convert golang 100% into wasm (no js shim or anything required) and the only thing you would need is a wasm library
You have to use golang from source (see the stackoverflow page https://stackoverflow.com/questions/76087007/golang-to-wasm-... )
go install golang.org/dl/gotip@latest gotip download GOOS=wasip1 GOARCH=wasm gotip build -o main.wasm
Although the way I did it is going into the gotip folder and then the binary folder which would contain the go compiler binary and then just use that path with
GOOS=wasip1 GOARCH=wasm ~/sdk/gotip/bin/go build -o main.wasm
Note that I forgot the exact path but it was similar to this but the point being that its super easy and simple :)
I tried to do it and I can tell you that it works and it works for even the most latest versions of golang, all you need is a wasmengine which I suppose can be ubiquitous.
I have built a solution where golang code gets converted to wasm and then we run a ssh server which then runs that wasm all in sandbox to create sandboxed mini golang servers :p I really love it although its a more so prototype than anything
Looks like this is available (since Go 1.21 [0]), so no need to build from source anymore. Just did a quick 'hello world' test to verify and it worked:
If you're interested in wasm/wasi and niche hardware with Go, you should check out TinyGo [1] if you haven't already.[0] https://go.dev/blog/wasi
[1] https://tinygo.org/docs/guides/webassembly/wasi/
Oh wow thanks for telling me, looks like I was using gotip/ source go for no reason but thanks for telling me this, this actually really simplifies a lot of things :p
Tinygo is really awesome but I have heard that it has its differences so software written for golang won't really work ootb on tinygo and tinygo is really fascinating project too!
I have a question but is it possible to create golang compiler itself within wasm itself. I tried doing it but it didn't really work out but I am curious if someone has thought of doing something like this or has already done it?
Nice project! Having just 16Mb of RAM does indeed sound like a real challenge for stock Go (not the TinyGo variant)! Even hello world is a couple megs, although I imagine Dreamcast isn't 64-bit, so the instructions are probably much shorter. Interesting to see anything written in it :)
Thanks :D How about porting Diablo? https://x.com/PanosGeorgiadis/status/2005692695402955143
> Who is this for? > ... > Anyone who enjoys the challenge of severe constraints
Remembering what a powerhouse the Dreamcast was when it came out, and how amazing games like Soul Caliber and Shenmue looked, it's hard to think of the Dreamcast hardware as "severely contained".
I find it a bit weird that I find it intuitive how things like the Super Nintendo did their work, and how modern games and systems work, but comparing the hardware specs of the Dreamcast/PS2/XBox/Gamecube era to the best of their output is where my intuition struggles the most. Not that the games of the era stand up to modern stuff, even when upscaled and texture-packed etc. in an emulator, but how they did it with so little oomph still amazes me.
For anyone interested in the general topic, highly recommend https://en.wikipedia.org/wiki/Racing_the_Beam
yeah, been there, nostalgia hits hard. Dreamcast was a beast of its era, it even had Ethernet! Even the VMU was something extraordinary! Too bad SEGA had to cancel it :(
This is incredibly cool! How do you think these modern language features would have affected Dreamcast development back in the day? (I have no idea of how difficult the console was to develop.)
It was a dream relative to anything else on the market (until 2001, when the Xbox and GameCube were released), made even easier for some titles due to the optional Windows CE SDK. You still needed to do a fair bit of SuperH assembly programming to get reasonable graphics performance, but it was nothing like the nightmarish complexity of the PS2, despite having half the RAM. It's still one of the more popular homebrew targets.
I think Lua (yes you can code Dreamcast games with it) would be really awesome for kids, being able to make their own games, given the language is simple, like Python. But in general, for serious stuff C/C++ is still the preferred way.
I love this. The documentation is great and I've even learned a thing or two about golang from it! The logo makes me want to port Icy Tower to DC.
thanks @rpastuszak, much appreciated :D
I thought that gccgo supports only some old go version? Or subset of features? I will need to refresh my memory for sure
I am using sh-elf-gccgo (GCC) 15.1.0 which is ok-ish I guess. But in general gccgo tries to be close to Go, but they do not implement all the features. e.g. generics are still missing for example.
It appears stale to me, there seems no one is driving it any longer, and Ian Lance Taylor has moved on anyway.
Maybe eventually the same can be tried with TinyGo, just as an idea.
problem is TinyGo uses LLVM, which doesn't support SH-4. The only reason I went with gccgo is due to SH4 target. In any case, I learned a ton of things doing this project :D
amazing work! The "book" documentation is better than most of the books I have read and paid this year! Kudos!
glad to hear that tasa
Great stuff!
Thanks Kosta <3
this is incredible
thanks @steeve :D
[dead]