Developing Prototype 1 for Amiga on PC using a mixture of C and 68k assembly
This text summarizes the tools and workflows that we used during the development of our Amiga demo Prototype 1, which was released at Breakpoint 2010.
Introduction
The development of Prototype 1 implicated programmers with different backgrounds ranging from high-level C/C++ engine coding to low-level Motorola 68k assembly coding. Hence we decided to devise a tool-chain that supported mixing C and assembly, which didn’t break backward compatibility, and which worked under WinUAE. C should be used for higher development speed of the 3D engine and some effects, while assembly should be used for time-critical parts like texture-mapping inner-loops, chunky to planar conversion, and also some effects.
Mixing C and assembly requires the use of a linker. While this might seem commonplace for the C coder, it is not necessarilly so for the Amiga assembly coder, who might be used to assemblers that directly generate executeable code and which are not useable for generating the required linkable object code. ASM-One and its derivates are popular examples of such assemblers, and I personally like them a lot. But while I previously used ASM-One as my main assembler IDE, it only played a secondary role in this development process. ASM-One has only been used for two tasks: for porting Optima’s effects to the WickedOS demo system, and for fine-tuning the pure assembly effects due to its short turn-around times. Those effects where later assembled to executable code using Devpac and called in the demo via a plug-in interface that is part of the demo system. WickedOS has also been used for handling hardware-hitting screenmodes, vertical blanc interrupts, and for providing timing facilities.
A look at the tools
The look for an alternative assembler provided two main options, vasm and Devpac, while Maxon ASM, PhxAss, and Optimizing Macro Assembler were briefly considered and then excluded for various reasons.
- Devpac is apparantly the best and most professional assembler on Amiga IMHO. I actually always made sure that my demo-system was compatible with Devpac, but I just never used its linkable code option.
- vasm is the assembler in the vbcc package, where it compiles the C compiler output into linkable object code. vasm supersedes PhxAss and provides a Devpac compatibility mode.
Unfortunately some of our code didn’t assemble with vasm and so we were forced to use Devpac. As Devpac is an Amiga application this meant that the tool-chain had to run under AmigaOS, i.e. in the emulator, which increased overall turn-around times.
As a compiler we used vbcc, which looked promising, seemed to be optimizing well, and had been recommended to me by Kalms at the previous Breakpoint. Using vbcc meant that we were going to programm in C99 instead of C++, which also matched Hellfire’s intent of avoiding the overhead of C++ object handling for performance reasons.
Linking was done via vlink, which is also part of the vbcc package. vlink effortlessly linked object files generated by vasm and Devpac, and so it was a clear choice.
Finally, an Amiga version of GNU Make was used to generate the executable-file of the demo.
Development workflow
Development was done on a PC, the real Amiga was only used for testing. This was for productivity reasons, as it meant that we could use modern IDE’s on big monitors, and powerful CPU’s to decrease the significant compile-times. If I remember it correctly, the demo would have taken about 20 minutes to build from scratch on the Amiga 4060 shown below.
We set up identical tool-chains on both development machines with WinUAE, vbcc, and the source folder being at the same locations. WinUAE mounted the source folder from the PC filesystem. This meant that we could use proper text-editors and version management tools for developing the Amiga sources. Using this basis we we then worked from two sides:
- Hellfire programmed the 3D engine and some effects in Visual Studio on a PC, not even using WinUAE most of the time. To facilitate this workflow he wrote display-functions that were plug-in compatible to WickedOS, so they would later link without problems.
- I took care of the build process in WinUAE and made sure that everything worked together as a demo. This was mostly done in Ultraedit, with frequent builds in WinUAE. But when integrating Optima’s sources I also came to use ASM-One again 🙂
Discussion
The resulting control-flow in the program simply begins with startup-code from C (startup.o) calling the main() function. After some initialisation the system is disabled by calling an assembly function that contains the INITWOS macro from WickedOS. This function also installs the interrupt handlers, starts the music, and then jumps to the mainDemo() function which calls all effects one after another. Upon leaving mainDemo() the system is restored and control returns to main(), which just exits the program. While this seems straight forward in retrospect, I initially considered inverting the mechanism and calling all C-code via the run-time plug-in mechanism I devised for the demo system a long time ago. I am glad that we didn’t do it that way as it probably would have brought us all sorts of trouble.
Our tool-chain can still be much improved. First and foremost we will have to make the AmigaOS-based build process completely optional to decrease the important turn-around time. Although the build process worked nicely, it was just too slow, even in a JIT-enabled WinUAE on a fast PC. Two steps are required for us to completely switch to cross-compilation:
- make all our hand-crafted code compatible with vasm
- have same versions of vbcc/vasm/vlink on PC and Amiga.
Both steps are relatively small, but they were low on our list and were just skipped. The former should be facilitated by exploring vbcc’s Devpacs-compatibility mode a bit further. The latter could be a bit fiddly, as Frank Wille, the maintainer of vbcc/vasm/vlink for Amiga, is not maintaing a Windows installation for himself. Therefore Amiga and PC versions tend to be a bit out of sync. Maybe recent efforts such as Kusma’s “amiga-dev” could help in maintaining identical PC and Amiga versions of the tool chain?
Regarding the age-old argument that Amiga demos should be coded in pure assembly for performance reasons, I can only describe this as obsolete for various reasons when targetting “high-end” Amigas with 68060 CPU. First, the implied theoretical advantage of higher machine performance is outweigh be the improved programmers performance when coding in a language like C, which helps optimizing on a higher level by testing different ideas and implementations. And seeing Hellfire crank out the 3D engine and its related tools in no time was surely an experience that supported this position. Second, we released another demo, which would probably not have happened otherwise. Moreover, most of the chart-topping demos in recent years on Amiga (on PC anyways) were build with the help of C-compilers (TBL, Ephidrena, Elude, …). Third, those compilers are really good, e.g. I spent an evening to convert one of the more complex texture mappers (that used more variables than available registers) to hand-crafted assembly just to arrive at the conclusion that I didn’t gain any speed! This can also be seen in support of Michael Abrash statement that “the best optimizer is between your ears” (chapter 1 in his “Graphics programming” book), meaning that you shouldn’t revert to using assembly language, or any other particular technique, as the only way of optimizing, but rather optimize your overall design. Taking this even further, I recently found a nice article by Niklaus Wirth – the father of Pascal and many other languages – who reported that for implementing their first Pascal system using assembly was “considered dishonorable”. This was in 1969, so I reckon it is time to catch-up.
What remains to be done for the next demo are general code optimisations, and maybe also getting the profiler vprof to work with our system. Furthermore we might also want to reassess our initial decision against C++.
Conclusion
Not diminishing the fun I had hacking on my Amiga back in the day, I am glad that we didn’t do a 100% assembly demo this time. By making our system work with a fair mix of C and 68k assembly, we harnessed the potentials of the different coders, and came to present a demo in-time (*cough*) for the last Breakpoint, which was the main point anyway.
Acknowledgements
A big thank you to our artists Muffler and JCS, for their awesome work on the audio-visual side! Big thanks also to Hellfire and Optima for writing all the effects – in the end I only had to put things together.
Thanks to Loaderror and Kalms for sharing their ADPCM players with us, and esp. to Kalms for premium support when the deadline approached. Many thanks also to Phoenix (Frank Wille) for his great tools and friendly support. And to Wayne and Britelite for testing the final version when our hardware was broken.
Links
Please feel free to leave a comment. For ranting about the demo itself, please go to Pouet or Amiga Demoscene Archive (if available). And for watching either run it from the executable, or refer to the capture on YouTube: Haujobb – Prototype 1 [Amiga]