Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
software:upi_conventions [2016/06/14 09:16]
ex_writer [User-Defined Subroutines]
software:upi_conventions [2016/06/14 10:45] (current)
ex_writer [Example: Space Fortress User Subroutine]
Line 1: Line 1:
-====== UPI Conventions ======+====== UPI Procedures & Conventions ======
  
-Bally Arcade ​system subroutines are called by executing ​RST 38H instructionfollowed by one or more parameters. The first parameter ​is a byte defining which subroutine ​to executewhether or not additional parameters for that subroutine follow this parameterand an indicator bit used for calling ​user-defined subroutines.+The User Program Interface (UPI) is a set of procedures and conventions used by cartridges to access the facilities provided by the Bally Arcade. By adhering to these conventions, ​cartridge will be system independentallowing improvements to be made to later version of the system and onboard games while maintaining upward compatibility. 
 + 
 +The basic rule for using the UPI is: with exception ​to the system [[:​glossary#​d|dope]] vectorno cartridge should ever address system ROM directlynor expect a given memory cell to always equal a certain value. 
 + 
 +The mechanism ​for calling ​a system routine is:
  
-=== Example === 
 <code z80> <code z80>
-RST     38H     ; call subroutine +        ​RST     56 
-DB      ​81      ; type, subroutine ​#option +        DB      ​(type + routine ​option)
-DB      30      ; passed parameter+
 </​code>​ </​code>​
  
-The first byte executes the subroutine ​call. The second byte is the first parameter. It breaks ​into the following segments (bits read right-to-left):+The system routine ​call breaks ​down as follows:
  
 +  * The RST instruction ($38/56) initiates the system routine call. 
 +  * The parameter byte comprises three parts (read right-to-left):  ​
 +    * The option bit (0) specifies how arguments are being passed to the system routine. If 0, the arguments are presumed to exist in CPU registers; if 1, the arguments are presumed to follow inline after the parameter byte. These arguments are loaded into the [[#context block]] automatically (i.e., "​sucked"​) before the called routine is entered. (The arguments required by each system routine are given in the routine'​s description section.)
 +    * The routine number is an even number specifying which subroutine to transfer to. (Symbolic identifiers,​ which are equated to routine numbers, are provided in HVGLIB.) ​
 +    * The type bit (7) indicates whether the user is calling a standard subroutine (0) or a [[#​user-defined subroutine]] (1).
 +
 +All UPI routines are [[:​glossary#​r|reentrant]].
 +    ​
 +=== UPI Parameter Byte Summary ===
 ^ Bit(s) ^ Function ^ Options ^ ^ Bit(s) ^ Function ^ Options ^
 | 0 | Option | 0 = no parameters follow; 1 = parameters follow in subsequent bytes | | 0 | Option | 0 = no parameters follow; 1 = parameters follow in subsequent bytes |
 | 1–6 | Subroutine number (always even) to transfer to | | | 1–6 | Subroutine number (always even) to transfer to | |
-| 7 | Subroutine type | 0 = standard subroutine; 1 = user-defined subroutine | +| 7 | Subroutine type | 0 = standard subroutine; 1 = user-defined subroutine |  
- +==== Example: Calling PAWS with a Parameter ==== 
-The option bit (0) specifies how arguments are passed to the system routine. If option = 0the arguments are presumed to exist in CPU registers; if option = 1the arguments are taken to follow in subsequent bytes. These arguments are loaded into the CPU registers automatically before the called routine is entered. (The argument(s) required by each system routine are given in the system routine description sections.)+<code z80> 
 +        RST     ​38H ​    ; call subroutine 
 +        DB      81      ; parameter byte (typesubroutine #option) 
 +        DB      30      ; passed parameter 
 +</​code>​
  
 In the example above, the first parameter byte 81 expands to 01010001B. Bit 0 is 1, indicating that parameters will follow this byte. Bits 1–6, 101000B, indicate subroutine $50 (80D). Bit 7 is set to 0, indicating that this is a standard subroutine call. In the example above, the first parameter byte 81 expands to 01010001B. Bit 0 is 1, indicating that parameters will follow this byte. Bits 1–6, 101000B, indicate subroutine $50 (80D). Bit 7 is set to 0, indicating that this is a standard subroutine call.
Line 23: Line 38:
 According to the [[:system routines#​onboard subroutines]] list, subroutine 80 is [[system routines:​human interface#​paws|PAWS]],​ which waits for a user-defined number of interrupts, then returns. It requires one parameter, the number of interrupts, to be passed in register B. So the third byte in the example above is passing 30 to B, requesting a 30-interrupt pause. According to the [[:system routines#​onboard subroutines]] list, subroutine 80 is [[system routines:​human interface#​paws|PAWS]],​ which waits for a user-defined number of interrupts, then returns. It requires one parameter, the number of interrupts, to be passed in register B. So the third byte in the example above is passing 30 to B, requesting a 30-interrupt pause.
  
-For standard subroutines, ​programmers ​do not need to list the verbose RST call as illustrated in the example above. Instead, [[software:​HVGLIB]] provides a list of symbolic identifiers for each system subroutine. Those identifiers are then invoked using the SYSTEM and SYSSUK calls. +For standard subroutines, ​users do not need to list the verbose RST call as illustrated in the example above. Instead, [[software:​HVGLIB]] provides a list of symbolic identifiers for each system subroutine. Those identifiers are then invoked using the SYSTEM and SYSSUK calls. 
-===== SYSTEM ​and SYSSUK =====+===== SYSTEM ​SYSSUK =====
  
 The Bally Arcade uses two labels, SYSTEM and SYSSUK, to call system routines. Internally, both labels are represented by $FF, the "​system sentinel"​ byte that readies the Arcade for a system routine number in the following byte. Their difference lies in how arguments are passed to the requested system routine.  ​ The Bally Arcade uses two labels, SYSTEM and SYSSUK, to call system routines. Internally, both labels are represented by $FF, the "​system sentinel"​ byte that readies the Arcade for a system routine number in the following byte. Their difference lies in how arguments are passed to the requested system routine.  ​
Line 31: Line 46:
  
 <code z80> <code z80>
-LD         ​B,​30 +        ​LD         ​B,​30 
-SYSTEM ​    PAWS+        SYSTEM ​    PAWS
 </​code>​ </​code>​
  
Line 38: Line 53:
  
 <code z80> <code z80>
-SYSSUK ​    ​PAWS +        ​SYSSUK ​    ​PAWS 
-DB         30+        DB         30
 </​code>​ </​code>​
  
Line 71: Line 86:
  
  
-===== System Routine ​Format ​=====+===== System Routine ​Conventions ​=====
 A system routine is coded like a conventional machine language subroutine, except that output parameters are not passed through registers but through the context block. A system routine is coded like a conventional machine language subroutine, except that output parameters are not passed through registers but through the context block.
  
-The context block is created by the RST 56 call. The user's register set (AF, BC, DE, HL, IX, IY) is pushed onto the stack. Register IY is set to point at this stack frame. Thus a copy of the input arguments exists in RAM, which the system routine may refer to as needed. These arguments are also present in the registers when the system routine is entered, so it is only necessary to refer to the context block when one has clobbered an input argument.+The context block is created by the RST $38/56 call. The user's register set (AF, BC, DE, HL, IX, IY) is pushed onto the stack. Register IY is set to point at this stack frame. Thus a copy of the input arguments exists in RAM, which the system routine may refer to as needed. These arguments are also present in the registers when the system routine is entered, so it is only necessary to refer to the context block when one has clobbered an input argument.
  
 An output argument is returned to the caller by setting it in the context block. If a register was changed, but the associated cell in the context block was not, then the register will have its old value on return. Thus a system routine is free to use any of the registers it needs without worrying about saving and restoring. The user can also assume that no registers will change except those defined as returning an output argument. An output argument is returned to the caller by setting it in the context block. If a register was changed, but the associated cell in the context block was not, then the register will have its old value on return. Thus a system routine is free to use any of the registers it needs without worrying about saving and restoring. The user can also assume that no registers will change except those defined as returning an output argument.
Line 99: Line 114:
 <​code>​(INDEX),​ IXL, IXH, E, D, C, B, A, L, H</​code>​ <​code>​(INDEX),​ IXL, IXH, E, D, C, B, A, L, H</​code>​
  
-Registers that are not defined as containing output parameters will not change. ​ 
- 
-All UPI routines are [[:​glossary#​r|reentrant]]. 
  
 ===== User-Defined Subroutines ===== ===== User-Defined Subroutines =====
Line 107: Line 119:
 <WRAP todo>​Section needs clarification.</​WRAP>​ <WRAP todo>​Section needs clarification.</​WRAP>​
  
-The UPI has been extended to support user-defined system routines. If the interpreter encounters a negative call index (i.e., ​bit 7 of the subroutine number ​is set), and "suck inline"​ is optioned, the user's macro routine address table (USERMT) and argument table (UMARGT) are used. The User Macro Routine Argument Table (UMARGT) is indexed for a parameter mask. The address of this table is assumed to be in (UMARGT),​(UMARGT+1). This pointer should point 64 bytes before the first real entry.+The UPI has been extended to support user-defined system routines. If the UPI parameter byte's type bit (7is set (or the byte's value is $80–$FF), and "suck inline"​ is optioned, the user's macro routine address table (USERMT) and argument table (UMARGT) are used. The User Macro Routine Argument Table (UMARGT) is indexed for a parameter mask. The address of this table is assumed to be in (UMARGT),​(UMARGT+1). This pointer should point 64 bytes before the first real entry.
  
-=== Example === +---- 
-<​code ​z80+ 
-     ​LD        HL,​USERMT-64 ​    ​; WHERE USERMT POINTS AT +From system BIOS: 
-     ​LD        (UMARGT),HL+ 
 +<​code>​The UPI has been extended to support user-supplied routines. ​ 
 +If the call index provided is negative [or from $ff through $80]  
 +then the users dispatch table pointer (USERTB) is used [also UMARGT].  
 +Note that the sign bit isn't zapped before being used as an index,  
 +this means that the users dispatch table pointer should point  
 +128 bytes before the first entry.</​code>​ 
 + 
 +Also: 
 + 
 +<​code>​ 
 +THE UPI HAS BEEN EXTENDED TO PROVIDE USER PROVIDED 
 +  ;  SYSTEM ROUTINES. IF A NEGATIVE CALL INDEX IS ENCOUNTERED 
 +  ;  BY THE INTERPRETER,​ AND 'SUCK INLINE'​ IS OPTIONED, THE 
 +  ;  USER MACRO ROUTINE ARGUMENT TABLE IS INDEXED FOR A 
 +  ;  PARAMETER MASK.  THE ADDRESS OF THIS TABLE IS ASSUMED 
 +  ;  TO BE IN (UMARGT),​(UMARGT+1). ​ THIS POINTER SHOULD 
 +  ;  POINT 64 BYTES BEFORE THE FIRST REAL ENTRY. 
 +  ;  I.E. LD      HL,​USERMT-64 ​ ; WHERE USERMT POINTS AT the USER's Macro Table 
 +  ; ​      LD      (UMARGT),HL
 </​code>​ </​code>​
 +
 +----
  
 The user must set up the subroutine as follows: The user must set up the subroutine as follows:
  
 ^ Location ^ Function ^ ^ Location ^ Function ^
-| 4FFB/4FFC | (Base address of register load specifications) - 40H | +| 4FFB/​4FFC ​(UMARGT) ​| (Base address of register load specifications) - 40H (64D) 
-| 4FFD/4FFE | (Base address of subroutine jump table) - 80H |+| 4FFD/​4FFE ​(USERTB) ​| (Base address of subroutine jump table) - 80H (128D) ​|
  
 The user is responsible for storing the addresses of these tables into dedicated system RAM cells. The user is responsible for storing the addresses of these tables into dedicated system RAM cells.
Line 162: Line 195:
  
 ; [...] ; [...]
 +        LD      HL,$1FA7
 +        LD      ($4FFD),​HL ​     ; $4FFD is USER Table Base + routine = JumP address
 +        LD      HL,​$1FE9 ​  
 +        LD      ($4FFB),​HL ​     ; $4FFB is User Mask ARGument Table + (routine / 2)
 +        LD      A,R
 +        AND     $1C
 +        LD      ($4F2A),A
 +L2FEE   ​LD ​     HL,​L2FEE ​       ; $2FEE is current program counter address ​
 +        PUSH    HL
 +        EI 
  
 ;  Call User's Macro Subroutine $80 ;  Call User's Macro Subroutine $80