IMPORTANT: The Makefile structure has recently been updated, moving many of the gritty details into a new file - Makerules, with a much simplified individual Makefile for each project. The Makerules file now also supports two compilers (m68k-atari-mint, m68k-ataribrown-elf) via switches.
The Makefile used by demos/ may include some additional rules for collating data such as music, sample WAVs etc. These extra rules are project-specific. The tutorials will tend not to need them.
First we select an assembler. This will be RMAC. This is provided in the bin/ directory of AGT. Note that
agtcut requires RMAC for one of its sprite generator modes (EMX), so it should be installed/present for that to work at all.
Next we select a compiler toolchain. The default is 'no' which selects Vincent's MiNT GCC 4.6.4 (m68k-atari-mint). There are however several advantages to prefer the alternative BrownELF GCC 6.2 (m68k-ataribrown-elf). These will be documented elsewhere. Since you're more likely to have Vincent's compiler installed, you'll probably need to stick with the default (until you install BrownELF!).
Next we specify if using a
minimal C/C++ library - or MiNTlib. Prefer
minimal for small binaries. MiNTlib however does provide some extra stuff that can help when generating data tables, writing log files etc. so support is kept for these reasons. Generally you'd want 'release' quality code to use the
minimal option and it's often easier to start as you mean to continue!
Next is the build configuration.
release is what you might expect - full optimisation, no error checking, most messages suppressed, no symbols, trim all junk, pack it... full speed ahead.
testing is effectively an optimised release build while retaining symbols, messages and certain error checking functions.
debug is more extreme with full debugging info and optimisation suppressed. In practice
testing is the most appropriate mode for development.
Note: If you are trying to debug via the log/console and not seeing your messages, ensure you have configured to 'testing' build mode, and that either Steem or Hatari logging features are also enabled in the Makefile and emulator side (especially for Hatari, which needs --natfeats=yes). The builtin AGT console will also record prints, but will only work if it is enabled in the Makefile.
Then choose between packed or unpacked executable. When testing stuff it's not necessary to pack. When debugging it's positively unhelpful. It can however be handy when remote-testing on HW using floppy emulation with limited space. We'll turn it off for now.
Note that packing only occurs in
debug will skip packing even if it is turned on.
Next we tell make where the agt/ root dir is relative to this project. In our case that is just two directories up:
AGTROOT = ../..
You need a way to test the program you're building. Chances are you're using an emulator like STEEM or Hatari. The following settings let you specify where to put the test program for auto-starting. If you enable this setting the program will end up in: <EMULATOR_GEMDOS_DIR>/auto/<name.prg>
We configure it to go in ./auto/
TEST_EMULATOR=yes EMULATOR_GEMDOS_DIR = .
There are some extra settings specific to Hatari which provide symbols and virtual debug messages (via a Hatari feature called 'natfeats'). We'll cover that in a later tutorial.
You will find the stack size defined at 16k. Simple programs don't need that much, but its a reasonable default. Consequences of setting it too low are ...usually bad, so don't optimise it until you're very sure you know how much is needed. Hint: resource-loading/data-parsing tend to us a deeper stack than the game mainloop so any attempt at measurement should be done carefully. If e.g. complex script/token parsing code is added to a project this figure may even need to be raised.
STACKSIZE = 16384
Next you will see COMPILERDEFS which lets you specify all the configuration switches you wish to apply to both the AGT library code and the program itself.
Note that AGT needs rebuilt if these are changed - one of the reasons its compiled directly into the project instead of precompiled into a library first. Precompiling would result in more (or more complicated) makefiles, more to keep track of and more sources of problems if you're not used to it. You can always implement this change yourself when you build your own project with a custom makefile.
There are many optional settings, but a few are currently essential:
# engine configuration COMPILERDEFS += \ -DAGT_CONFIG_WORLD_XMAJOR \
One of these
AGT_CONFIG_WORLD_XMAJOR optimises AGT's game layers to assume X or Y axis is dominant in the game world. For a vertical scroller, you'd select YMAJOR. If using 8-way scroll, or just uncertain, stick with XMAJOR. AGT will not link properly without one of these switches. More on this later.
Other settings are optional e.g. to control debugging features.
# dev/debug tweaks COMPILERDEFS += \ -DAGT_CONFIG_SAFETY_CHECKS \ -DAGT_CONFIG_DEBUG_CONSOLE \ # -DAGT_CONFIG_DEBUGDRAW \ # -DAGT_CONFIG_STEEM_DEBUG \ # -DTIMING_RASTERS -DTIMING_RASTERS_MAIN \ # -DUSE_MEMTRACE \
*Note: For the unwary - the '\' means 'continue line' for
make, allowing a single line of syntax to be spread over several - and another thing that can easily get lost or messed up with trailing whitespace when editing makefiles. The # symbols denotes a comment, and used here to disable settings. Don't add # comments in the middle of a sequence of '\' continued lines! Keep comments together beyond the last real line. *
Next we have a list of additional objects (i.e. sourcefiles) which we want to add to the project, beyond the primary <projectname>.cpp where the program entrypoint is. Additional sourcefiles let you break the project up into aspects e.g. world, entities, levels, data/asset stuff. Alternatively you can drop all the code into the main <projectname>.cpp if you prefer. Most of the demos are single-sourcefile.
PROJECT_O = \
Next we define a list of top-level 'prerequisites' for the project. This specifies which programs or components need to be compiled or built from other things. The component names are arbitrary - you can choose them to suit. In this case we have three components - tutorial No.5 produces three different .tos files.
# rule to build programs all: tutorial_5a tutorial_5b tutorial_5c
Last we define the prerequisites for each .tos file to be produced. This usually consists of the AGT library and the tutor5a binary itself, although it may include other things e.g. a rule to prepare extra data where needed.
tutorial_5a: AGLIB=$(AGLIB_STE) tutorial_5a: $(AGLIB_STE) tutor5a.$(EXT) tutorial_5b: AGLIB=$(AGLIB_STE) tutorial_5b: $(AGLIB_STE) tutor5b.$(EXT) tutorial_5c: AGLIB=$(AGLIB_STE) tutorial_5c: $(AGLIB_STE) tutor5c.$(EXT)
Here, 'tutorial_5a' is an arbitrary name for the 'target' program. 'all' is one of make's builtin targets (the default one) and we define it as depending on our 'tutorial_5a' target. So 'make' or 'make all' will build our tutorial_5a target and whatever it is defined as needing.
We define 'tutorial_5a' as depending on (and configured to use) the STE variant on the AGT library code
$(AGLIB_STE) - which it will compile, and also depending on 'tutor5a.tos' - which it also has to find a way to produce using separate rules.
IMPORTANT: A build rule kept in Makerules specifies that ???.tos can be built from ???.cpp. And we provide 'tutor5a.cpp' which covers this nicely. In other words - the tutor5a.tos name given here infers the tutor5a.cpp name is expected as the primary sourcefile in the project.
There is no additional (e.g. sound) data here so we can ignore that side of things until later.
To compile the tutorial we simply invoke:
> make clean; make
If you're not used to makefiles, perhaps coming from a Devpac/68k universe, be aware that make is super strict about things like whitespace or newlines in the wrong place. If your makefile starts reporting obscure errors without any meaningful edits, check for trailing whitespace or accidental blank lines between important items. Keep regular backups of recent working versions.