Look-up Tables

From MegaDrive Wiki
Revision as of 10:29, 16 March 2015 by Tristanseifert (talk | contribs) (7 revisions imported)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Look-up tables are used often in Mega Drive programmes and even outside of the Mega Drive to either accelerate some operation, or to provide an easy way to store information that may need to be accessed by an index. An example of this could be found in a game's sound driver — instead of having to give it a pointer to the song or sound effect every time you want to play it, instead you could provide an index into a table, from which it would lift the appropriate address.

Magic Jump

A "magic jump" is a kind of dynamic jump where you load an index into a register, call the subroutine, and then put a jump table immediately after the routine. The program then jumps to the chosen routine. <source lang="asm" line="GESHI_FANCY_LINE_NUMBERS"> Magic_JMP:

==============================================================================
INPUT
d7.13-0 = Jump Index
==============================================================================
	move.l	(a7)+,a6	; Pull address from stack.
	lsl.w	#2,d7		; Index --> 16-bit Offset.
	move.l	0(a6,d7.w),a6	; Get jump address.
	lsr.w	#2,d7		; Restore Index.
	jmp	(a6)

</source>

This routine accepts a 14-bit jump index in register d7. The address to jump to ends up in register a6. Each entry in the jump table is 32-bits long. For example: <source lang="asm" line="GESHI_FANCY_LINE_NUMBERS"> jsr Magic_JMP dc.l $1000, $2000, $3000, $4000 </source>

  • If d7 = 0, it jumps to $001000.
  • If d7 = 1, it jumps to $002000.
  • If d7 = 2, it jumps to $003000.
  • If d7 = 3, it jumps to $004000.

Magic Branch

A "magic branch" is similar to the magic jump, except the pointers are relative instead of absolute. The value of the pointer is added to the address of the first entry into the table. To use, load an index into a register, call the subroutine, and then put a jump table immediately after the routine, just like before. The program then jumps to the chosen routine. <source lang="asm" line="GESHI_FANCY_LINE_NUMBERS"> Magic_BRA:

==============================================================================
INPUT
d7.13-0 = Jump Index
==============================================================================

move.l (a7)+,a6 ; Pull address from stack. move.w sr,-(a7) ; Save SR. add.w d7,d7 ; Index --> 16-bit Offset. add.w 0(a6,d7.w),a6 ; Get jump address. lsr.w #1,d7 ; Restore Index. move.w (a7)+,sr ; Restore SR. jmp (a6) </source>

This routine accepts a 15-bit jump index in register d7. The address to jump to ends up in register a6. Each entry in the jump table is 16-bits long, and the values are signed, making the branch range from -32,768 to +32,767 bytes. For example: <source lang="asm" line="GESHI_FANCY_LINE_NUMBERS"> jsr Magic_BRA dc.l $1000, $F000, $7000 </source> Assume that the jsr instruction appears at ROM address $007A24. Since a JSR is 6 bytes long, the address $007A24 + $6 = $007A2A is pushed onto the stack. Therefore, all addresses are relative to $007A2A.

  • If d7 = 0, it jumps to $007A2A + $1000 = $008A2A.
  • If d7 = 1, note that $F000 = -$1000. $007A2A - $1000 = $006A2A.
  • If d7 = 2, it jumps to $007A2A + $7000 = $00EA2A.