This is the Amiga Development blog of Steffest.
I'm a webdeveloper but have zero experience in C or developing for the Amiga.
These are my notes of the journey into Amiga dev-land.
New intermediate goal: creating a demo that runs on a standard Amiga 500.
This means kickstart 1.3 is back in the picture.
First step: let there be music!
Most of the mod-player libraries I tried won't work on KS1.3, but then I found the awesome (and very recent) PTPlayer, made by PHX in Assembler.
It's not entirely system friendly, but for a demo, that'll do.
That was - again - a steep hill to climb: figuring out how the compile the library and use it from a C program.
The compiler started throwing weird stuff around like FAR and NEAR data descrepencies and what not. Errr... Whut ?
But after my usual approach: keep banging on things untill it works - I ended up with something that worked and that didn't look all that bad.
Code here on Github.
It's a small wrapper function that enables me to just write
and be done with it.
If you want to target 1.3 and want to be system-friendly: Stingray has patched the PTReplay.library to work with 1.3. Awesome!
Today I compiled my first program written in Assembler.
Even though it was only a few lines, it felt like a major victory :-)
It started with a desire to understand exactly how a CPU works, with registers and addresses and bytecode instructions etc.
(Maybe I'm still dreaming of writing my own emulator one day, haha )
There are lots of tutorials. The Photon one is famous.
I also found this one very nice, especially for total beginners like me.
I tried several different Assemblers.
Ok, so it's clear that I don't have the patience anymore to use the native "IDE editors" dcirectly on the Amiga. I'm not that masochistic.
writing code, I'll do on a modern machine, but maybe the compilation and linking step will remain on the amiga.
(Maybe ... VASM and VLINK seems like a really nice tool that produces tiny binaries, so ...)
Ah ... and there are also Amiga ports of Vasm and Vlink (they are included in the VBCC package)
Lots of the Amiga Assembly examples are not system friendly though...
I mean: they are super interesting to see how exactly the Amiga works (like "write to that memory addres to change color 1" , "read that memory address to check the joystick button" ...)
But I don't know if I want to go there.
Doing system-friendly stuff certainly is possible, but why do that in assembler?
In the end- it's of course perfectly viable to mix assembler and C, creating linkable objects in one or the other, and combine them in 1 executable.
Check out ASM-Two - seems like a nice package for basic amigas( it doesn't support 020 oir higher CPUs, but still)
And this is a nice thread with valuable info. (Look who started it :-) Hi Guy! )
Confession: I'm one of those guys that like to reinvent the wheel.
Because the wheel you have made yourself is always rounder than any other wheel in the world, right?
I also know that "reinventing the wheel" often is the result of 2 things
So... After my little "button" class I decided to give existing Amiga GUI frameworks another chance, because I had the feeling I was trying to solve a problem that was solved at least a dozen times before.
The one Gui framework in the Amiga world that is impossible to miss is - of course - MUI: the Magical user interface.
And from a developer perspective, I now know why.
It is simply really really well made.
No wonder it's the default, and it's even supported out of the box on OS4 and Morphos.
So - unless you're targeting kickstart 1.3 - you would be a fool not to use it, right?
To use it as C developer, you need the C includes you can find here.
All the examples includes are made to be compiled on Sas/C so - indeed - they work out of the box. How nice is that!?!
Very very very nice and super easy to use ...
I still have this nagging aversion of "dependencies" in your software, but is there any OS3 user that doesn't have MUI installed? Don't think so...
Note to self: about those "includes" in C: is there any way to keep track of where they come from, maybe by putting them in seperate include folders?
Now I just copy the MUI include files to my main C include folder and it magically works (See what I did there? :-) ) but what If I want to compile my program in 10 years on a new system? how would I know what includes I need exactly?
Poking around the MUI example files I found something very striking ... the "KnobsControl" class.
On the left is the MUI knobs control class, on the right is the knob and number-display I made for BassoonTracker.
Isn't the resemblance striking, especially with those orange numbers in the rounded box?
I honestly can't remember seeing that MUI knob control anywhere before, so let's put this down to a case of "Great minds think alike" shall we? :-)
Ok... so this happened
Image: Amiga X5000
The Amiga X5000 - most powerful Amiga you can actually buy new anno 2021.
Lovely machine - certainly the fastest Amiga I ever used. it's a 2Ghz PPC processor with 2GB of Ram.
Doesn't run Classic OS3 of course - so enter OS4!
Hmm... I really want to love this machine, but it saddens me to say that OS4 is a bit... erm... crap.
MorphOS also runs on the machine though, and that's one snappy and polished OS!
Well, let's at least TRY to give OS4 some love.
I was pleased to see my little system-friendly UI programs run out-of-the-box on it.
Must be some on the fly CPU emulation to translate 68k binaries to PPC?
Yes, OS4 has Petunia and MorhOS has Trance (So I learned)
With some careful planning, it doesn't seem too far fetched to produce 1 single binary that works on all these systems.
I wonder if I can use stuff like network libraries and AHI etc.
-> to check out!
While I was fiddling with C again, I made an attempt to a more "structured" approach.
Just a simple button-example, but the goal was to find a coding structure that works for me and that I can use as scaffolding to build upon.
I have totally no idea if this is "how you're supposed to do it" but it works, I can wrap my head around it and it feels right.
So I got myself a Rasberry Pi 4
I love it!
At first I was not impressed at all as it was very slow with the default raspian Linux, but then I tried DietPi - much better!
(And ofcourse Amiberry is also kind of cool)
I did have to fiddle a lot to get everything up and running though.
My main problem was that VNC did not work when no monitor was attached to the PI.
It worked fine when you connect a monitor, boot DietPi and disconnect te monitor, but not in complete headless mode.
after a loooooooon evening of trying and googling I finally found this post and this explanation.
So it's a bug in vncserver. The workaround that did the trick for me was to set the "view only" password as the normal password using vncpasswd.
When running headless, the VNC settings are in /DietPi/dietpi.txt - edit that to set the resolution and the screen ID (to 0 for easy of use): the config is in the main /DietPi/dietpi.txt
Then execute a "vncserver start" and a "vncserver stop"
More: the ssh client on the Amiga is to old I guess, but telnet works (I had to install the telnet deamon on the Pi).
to start Chromium with fullscreen enabled: chromium-browser --start-fulscreen (then F11, which is a bit annoying as the Amiga keyboard only goes to F10 :-))
More to come!
After a hiatus I pickud up the Amiga-C-Compiler again.
One of the building blocks of many of my projects is the web: doing a HTTP request, parsing results, use them.
Once an application is "connected" in that way, it usually becomes so much more powerfull.
That's the same for the hardware.
I long thought networking on the Amiga was a gimmick, on of those "because-you-can" things that you fiddle with, get it working and hardly use after that.
But after you walked the upgrade-your-amiga-to-beast-mode path, networking is the main component that makes an Amiga fun to use.
Things like Samba shares, VNC, Synergy, streaming audio players, ... are just AWESOME on a high-spec amiga.
So today I finally managed to compile a program that does HTTP requests.
Yay, it even handles large binary files pretty well.
That was a nice deep dive on how HTTP works exactly on top of TCP/IP.
I had to hunt for the correct include header files a lot, but I finally found them in the OS4 SDK at the Hyperion site. (It's in base.lha -> include -> netinclude)
Who knew OS4 would come in handy, right? Thank you Hyperion for still providing that kind of stuff.
Extract the files somewhere and include them in the compiler like
(where NETINCLUDE: is an assign the the location where you extracted the SDK)
Another resource I found very usefull was http://amigadev.elowar.com/ that has a hyperlinked copy of the Amiga RKM with lots of examples in C and the Amiga developer CD 2.1
So the next step: My program needs an interface!
At first sight that seems a bit messy on the Amiga ... you have GadTools , Boopsi, MUI classes,...
Seems like a LOT of boilerplate and hoops to jump through just to get some UI elements in the screen.
After all ... a button is just a rectangle with a label that should trigger some code when you click on it.
I think it was part of some presentation by FarbRausch where Chaos (I think) was giving some advice on coding.
If I look back on that, that talk had a great impact on the way I work now.
One advice was "build your own tools" , another advice was "build your own user interface system".
That seems like a really weird advice. Why reinvent the wheel, right?
The line of thinking was that - unless you build something very generic - you spend/loose a lot of time battling other peoples framework to do exactly what you want.
All those "generic UI systems" come with a lot of overhead and stuff you don't need, exactly because they aim to be ... well ... generic.
That's also what I did with Bassoontracker: just build your own UI library that does EXACTLY what you want without overhead.
I guess that's also a nice approach for Amiga applications.
In the end I think I want something like AmigaAmp, or the "Empy" skin of Eagleplayer where clearly the custom UI is a huge reason why these programs or fun to use.
That being said: If I ever go MUI - this resource seems very interesting.
And for GadTools: here's a list of useful demo/tuturial code
So this was released:
It's a plugin for Visual Studio Code that offers a complete and integrated Amiga Dev toolchain out of the box.
Including remote debugging and the whole shebang.
That's impressive .. and VERY comfortable I must say.
Just fire up VSCode, init a new Amiga project, hit F5 to run it and suddenly a virtual Amiga spins up, running your compiled code and offering a very cool remote debugging bridge right into your IDE.
It uses GCC to (cross) compile.
The IDE is the most important piece of the work flow for me. It's where you write your code and it just have to feel right.
For that reason, editing or writing code on the Amiga is a no go: there simply is no editor on the Amiga that even comes close to modern tools available today on windows/Mac/Linux.
My personal preference still are the JetBrains tools: IntelliJ, WebStom, CLion, PHPStorm ... These guys really understand the process of developing code.
They are not free but IMHO opinion totally worth it.
The other rising star is Visual Studio Code (not to be confused with the heavy weight Visual Studio)
It's biggest strenght is that it's free.
It's fast, lightweight and extensible.
Good job, Microsoft!
Nervertheless... crosscompiling ... for some reason I still don't like it. Mainly because I switch systems/OS all the time and I like my tools to be completely platform independent.
VSCode is, but Bartmans toolchain is not (yet).
Having a light virtual Amiga around with Sas/C ready to roll feels more comfortable and more "in control" then a magically crosscompile toolchain.
Maybe I just have to dig in Bartmans tools some more to see how they work exactly.
Someone on the EAB board mentioned "Gamesmith Development System"
Normally I don't want to use "Frameworks" because I like to dig into it myself, but seeing I was having a hard time getting any kind of graphic performance out of my own code I decided to take a look.
I'm glad I did - it looks like it is the perfect "middleware" between high level C drawing function and the raw amiga specific stuff.
It's a library written in Assembler and C that exposes some basic graphic and audio functions to any other language that can load external libraries.
It comes with both a C and a Assemler compiler, but it also works with Sas/C
It was a commercial product but apparently it's in the public domain now.
I found the download here and the manual here.
The installation barfed on the final steps on my system, so I had to complete it manually: assign the GameSmith: path to the installation dir and rename the correct header file for use with Sas/C.
Some of the examples even are very "bunnymark" like so that looks really promising.
Gamesmith includes some "link" files you can excute, but I could not get them to work.
According to the Sas/C user guide you don't really need to do the compiling and linking in 2 steps, you can just use the sc command with the "link" parameter to do everyrthing in 1 step.
You can use the "lib" parameter to define the include libraries.
So to compile the example it would be "sc file.c link lib GameSmith:GameSmith.lib to file"
Awesome. Gamesmith includes lot's of stuff I don't really need, I guess, but the base seems really really promising: fast and easy to integrate.
Let's give it a try.
I started writing my own chunky versus planar rountine but ofcourse somebody already did that.
I found this totally execellent package at Aminet: GetImage: http://aminet.net/package/dev/c/GetImage
This takes an image (or multiple image inside a Dpaint Brush) and converts it to a C Image data structure ready to by used.
I you're starting with a .png file you can use e.g. Personal Paint to convert it to an DPaint brush.
On the amiga we can include this file and avoid having to do any (slow) chunky/planar conversions, on other platforms we can just include the original .png file.
The trouble with stackoverflow is that is is an ungooglable error :-)
But lucky I found this:
I often see people define arrays of large size as local vars in a function, and they are unaware that this ends up in stack space.
Indeed! I tumbled into that booby trap also.
Note to self: define large data arrays as const outside any function.
It appears that GCC includes the standard C libraries libnix which defaults to V37 of Amiga libraries.
This makes it pretty hard to target kickstart 1.3 amigas as v37 was included with kickstart 2.04 ...
You can avoid this by using the -nostdlib flag but this opens a whole can of worms (no reference to __main, no reference to atexit ....)
So as a general rule: If you want to target kickstart 1.3 or lower: avoid GCC, use VBCC or SAS/C instead.
For cross-compilation with GCC, like this one , you can target kichstart 1.3:
m68k-amigaos-gcc test.cpp -mcrt=nix13
Ok: Baby steps
Let's get the basics first: opening screens and windows, displaying something on the screen.
I've made a new repo on Github collecting all small examples.
If there are no building instructions you can compile them with:
Let's not worry about portabilty at this point. The first goal is to get a program running that
Some interesting resources:
And some reading:
Don't you love the internet!
It seems there are 4 main options for Amiga C compilers
After some fiddling I decided to go with GCC 2.95 on the amiga.
Would there be any performance differences in the final binary when using different compilers? To test.
After some time I forgot how to get a SAS/C environment up and running when you start with a fresh Amiga system, so here's a reminder for myself.
SAS/C needs some assigns:
In my case that adds to
ASSIGN SC: DH1:sc
ASSIGN LIB: DH1:sc/lib
ASSIGN INCLUDE: DH1:sc/include
ASSIGN CXXINCLUDE: DH1:sc/cxxinclude
PATH DH1:sc/c ADD
then use mkmk to generate a smakefile and smake to compile it
Should I setup 1 dev environment so I can compile everything one the same platform?
This might seem the most logical setup but maybe not:
Allthough there are some really interesting setup to compile amiga binaries on osX, widows and Linux, I ended up setting up a compiler on the amiga itself.
On the emulated amiga, I use a virtual harddisk that resides on Dropbox.
So whatever system I'm using, when I fire up an emulated amiga, it will always be the exact same setup on everyplatform because the hard disk file is synced.
Even more: after setup, I can just dump the content of the virtual harddisk onto a CF-card, pop it into a real amiga and BAM! everything is up and running there also (try doing THAT with a windows PC!)
All the source files are on Dropbox too, available both local and on the emulated amiga.
I can still use my editor of choice (Jetbrains FTW!) and compile it on the amiga.
If I'm REALLY eager, I can even run the virtual amiga on my Android phone - with the exact same virtual harddisk - and compile from there (OK, not very practical, but it's possible)
So let's keep Amiga compiling on the Amiga.
We'll worry about mobile later.
Of course, chasing the cross-platform dream is nothing new in the C-world.
There are lot's of examples out there and one that is particularly close to my own personal interest is "Emerald X11" by David Tritscher.
It's plain C, has full source code and is already targeted towards multiple platfoms, including amiga.
Emscripten really is a very cool tool.
It's well documented and very easy to setup.
The hardest part is converting endless loops in C.
the Emerald X11 code has lot's stuff like.
input = readInput();
if (input>0) break;
Instead, everything is event driven.
For games and other graphical stuff, there's usually a single function called by requestAnimationFrame to keep the UI in sync with the screen refresh rate.
This means that you have to transform these c loops to functions that gets called 60 times a second using emscripten_set_main_loop.
As I'm starting from scratch, this is just something I need to be aware of from the start.
The source of Emerald X11 is very structured.
It's a perfect example how to structure your code towards multiple compile targets.
There are usually the same kind of platform specific components needed in most types of software:
The goal is to wrap each of those components in a generic function that we can swap with another implementation when compiling for a platform.
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.fillStyle = "black";
var playerImage = new Image();
playerImage.src = "playerWalk.png";
var audio = document.getElementById("audio");
audio.src = "audio/walk.wav";
but wrap everything in generic function like
So you can write the entire game logic in C, controlled by a single "timer" function and do the platform specific implementation per platform.
An obvious no-brainer really - but still good to get clear from the start.
The web part of the project is covered. let's focus on the Amiga!
A new blog ...
I don't know anything about C.
Compiling a C program for me in the past was something like
However ... as my interesting in all things computing expands, and one goes of to explore new systems, new OSses, new hardware, retro hardware, then one also discovers the itch to write some code for that platform.
Almost: it runs on any modern platform but it's complety useless on retro platforms like my first true love: the Amiga.
Of course, die-hard amiga developers work directly in assembly, but let's keep it somewhat portable and develop a new skillset that is usefull for the future.
Enter C - the one universal language that is truely present on all platforms.
(Ok, I know maybe Pascal could also be a fit, but ... maybe later)
To create a simple game from the same source files for these completely different target platforms, both retro and modern.
This blog is a log of my findings.
To document the process from a total C-noob to a true cross-platform single-source app.
Let's do this!