Executables - jedimatt42/fcmd GitHub Wiki

Executables

Command executables

Command executables are program images designed to co-operate with the environment setup by Force Command. Force Command API will be available to these executables so they can use the same terminal input/output and leverage the disk io and other features built into Force Command.

They should be AORG 0xA000 binaries (including the header), and can use the upper 24K memory expansion fully.

The 6 byte program header is different:

Force Command may itself use SAMS, so executables must cooperate by allocating pages through the API. Both load types, Simple Image and SAMS Image will allocate loaded pages into SAMS. If SAMS is not present, or not enough pages remain, then SAMS Image programs will fail to load.

Executable Image Loading

The first word flags the file as a Force Command program. It must have the value: 0xFCFC

The second word should be set to the number of sequential SAMS 4K pages to load. If this is 0x0000, then 6 pages are allocated and filled into the upper memory expansion. If no SAMS is present, then those 6 pages are already there by virtue of the stock 32k expansion.

The third word is the return flag. If the value is 0xFCFC then Force Command will not reset the screen when the program returns.

The fourth word is the start address. Force Command will branch and link BL to this address. Register usage is the same for Simple Image Load Type. This address must be within the first 8K if SAMS pages are specified.

Note: the header is loaded into 0xA000 along with the rest of the executable binary.

Executable Memory usage

register purpose
R1 address of command arguments, & return code
R10 gcc stack
R11 return address to Force Command
WP 0x8300

Executables may use any of scratchpad register workspace 0x8300-0x831F. Disk IO routines internal for ForceCommand will also use scratchpad >8320 - >832F for additional info pointer in Level 2 IO routines. 0x83A0 to 0x83AA are also used by DSR calls. GPLWS 0x83E0 - 0x83FF may also be used by some Force Command routines.

Upon return to Force Command, an executable must return to the address in R11 when the command was entered. R10, the stack pointer, must be equal to the same value on entry as well.

If only 32K expansion memory is available, then only one executable program may be loaded, meaning the API fc_exec may not be used to run other executables. Only executables with a SAMS page count of 0 in the header will be executed.

If SAMS is present, then executables may load other executables with the fc_exec command. When this happens, new pages are allocated, and mapped in. When the executable returns to Force Command or a prior executable the pages are freed, and the previous set of pages are mapped back in.

If the executable sets the SAMS page count in the header, then the specified number of 4k pages will be loaded into SAMS sequentially from the executable file.

Use the following macro to declare a function:

FC_SAMS_BANKED(bank_id, returntype, function_name, param_signature, param_list)

or

FC_SAMS_VOIDBANKED(bank_id, function_name, param_signature, param_list)

Example:

FC_SAMS_BANKED(0, int, refresh_title_screen, (int bgcolor, int fgcolor), (bgcolor, fgcolor));

An inline wrapper will be created to use for banked switch calls, or the optimizer will remove the overhead if calling from the same bank.

int refresh_title_screen(int bgcolor, int fgcolor);

Your actual function should be declared with the FC_SAMS macro that puts a bank based prefix on the function name.

Bank switching will use a trampoline routine in the cartridge rom bank 0. Calling the functions with the bank_ prefix will allow normal calling. You will have to define MYBANK in your calling context so the call can capture what bank to return to when the routine is done.

These routines will assume that the code in the executable is designed to load as overlay from >A000 - >BFFF, an 8K chunk. When paging, 2 consecutive pages will be mapped. >C000 -> >FFFF are left untouched.

Attention: bank_ids are 0 based 8K chunks of your binary's .text segment. The SAMS page count in the header is the count of 4K pages required. So, the header is your maximum bank_id * 2.

SAMS executables should link .text segments/code into >A000 - >BFFF, .data and .bss segments should be linked into the remaining 16k at >C000. The loader will complete with the first 2 pages mapped into >A000, and the last 4 pages mapped into >C000

There are example programs with Makefiles and linkfiles setup for gcc. Examples

Force Command API

There are over 90 functions in the ForceCommand cartridge directly accessible to your executables.

The indirection handle for the API will be placed in lower expansion memory at 0x2000. You can call Force Command API functions by placing the arguments sequentially in registers from R1 up to however many arguments are required. R10 should be set to a stack pointer that can be used by the functions. When called, an executable inherits a valid value for R10. Set R0 to the index of the API to call, and BL @>2000.

See examples folder for API guidance by language.

For GCC, there are inline function stubs that can be included and then called. For TMS9900 assembly, the API reference included the API_ID that goes in R0 for each function.

Further API documentation is here: