Calling Conventions

From Intellivision Wiki
Jump to: navigation, search

The Intellivision's Executive ROM adopted a set of coding conventions that make it easy for software written by different people to interoperate.

The most important convention is the method by which one function invokes another. Most of the Mattel game software seems to follow the convention below, at least approximately. SDK-1600 and other contemporary software uses similar conventions.

  • Return address is in R5. This is so common that AS1600 provides these aliases:
    • "CALL" for "JSR R5"
    • "BEGIN" for "MVO@ R5, R6".
    • "RETURN" for "MVI@ R6, R7".
  • Non-pointer arguments typically in R0, R1, with results in R2. (Or, it's sometimes rotated: inputs in R1, R2, output in R0.)
  • Pointer arguments (especially arrays) start with R4
  • Fixed data blocks sometimes appear immediately after a JSR instruction

The last bullet is probably the most subtle one. The JSR instruction puts its return address in one of R4, R5, or R6. R4 and R5 are auto-incrementing pointer registers when used with Indirect Mode accesses. So, a common idiom developed in the Intellivision world: If a given function takes a fixed block of data, that block of data can be placed immediately after the JSR instruction. The function would then read the data, leaving R5 pointing just after the data block. When it's done, it can then return just after the data.

Games commonly use this technique to draw text on the screen. EXEC based games apparently also use this technique to play songs.

The example below shows a simple "PRINT" function that prints a string to the display, followed by code which invokes it. The example isn't optimized.

PRINT:    ; prints the NUL terminated string after the JSR instruction
          ; Expects address to display at in first word
          ; Expects "format word" in next word (this gets ADDed to each character to set colors, etc.)
          ; Expects string in subsequent words
MVI@ R5, R4  ; get address to display at MVI@ R5, R3  ; get "format word" SUBI #$20, R3  ; ASCII adjust the format word
loop: MVI@ R5, R0  ; get a character SLL R0, 2  ; shift card # into position SLL R0, 1  ; (See STIC for information on card format) BEQ done  ; if character was a NUL, leave. ADDR R3, R0  ; add in format word. This adjusts for ASCII to card# offset and sets color. MVO@ R0, R4  ; write it to the screen B loop  ;
done: JR R5  ; return just after the string

EXAMPLE: JSR R5, PRINT DECLE $0200  ; upper left hand corner DECLE $0007  ; White STRING "Hello World!", 0  ; String to print  ; the PRINT function returns here.