aboutsummaryrefslogtreecommitdiff
path: root/examples/graphics/tilesasm/drawtiles.s
diff options
context:
space:
mode:
Diffstat (limited to 'examples/graphics/tilesasm/drawtiles.s')
-rw-r--r--examples/graphics/tilesasm/drawtiles.s272
1 files changed, 0 insertions, 272 deletions
diff --git a/examples/graphics/tilesasm/drawtiles.s b/examples/graphics/tilesasm/drawtiles.s
deleted file mode 100644
index 15a0707..0000000
--- a/examples/graphics/tilesasm/drawtiles.s
+++ /dev/null
@@ -1,272 +0,0 @@
-#
-# LibPSn00b Example Programs
-#
-# Drawing Tile-maps with Assembler Routines
-# 2022 Meido-Tek Productions / PSn00bSDK Project
-#
-# Example by John "Lameguy" Wilbert Villamor (Lameguy64)
-#
-# This file contains the assembler routine DrawTiles which can be called from
-# a C or C++ compiled module. The routine makes use of constants and assembler
-# macros written in the GNU GAS syntax.
-#
-# Assembler routines called from C-language modules can freely use registers
-# $v0-$v1, $at, $a0-$a3, $t0-$t9 without preserving through stack. Registers
-# $s0-$s9, $gp and $fp must be preserved through stack before returning and
-# registers $k0-$k1 should not be used for obvious reasons (kernel registers).
-# $sp and $ra is used as stack pointer and return address respectively.
-# $0 or $zero is constantly zero.
-#
-# A C caller always passes arguments as 32-bit values on registers $a0 to $a3
-# regardless of the data type specified in the function's C declaration.
-# Additional arguments are stored in the stack 16 bytes relative to the stack
-# pointer ($sp). To get around the stack being modified in different parts of
-# a larger routine the stack pointer would be copied to the frame pointer ($fp)
-# and the previous value of the frame pointer would be pushed into stack. This
-# way additional arguments may be read anywhere starting from $fp+20 instead.
-#
-.set noreorder # Disable GAS' annoying nop insertion
-
-.equ db, 1 # Constants for "emulating" SNASM style structs
-.equ dh, 2
-.equ dw, 4
-
-#
-# TILEDEF struct
-#
- rs=0 # rs is used to emulate SNASM style structs
-.equ TILEDEF_uv , rs # Tile texture coordinate
- rs=rs+dh
-.equ TILEDEF_clut , rs # Tile CLUT
- rs=rs+dh
-.equ TILEDEF_pad , rs # Padding
- rs=rs+dh
-.equ TILEDEF_tpage , rs # Tile tpage
- rs=rs+dh
-.equ TILEDEF_len , rs # Entry length
-
-#
-# TILEINFO struct (to use as offsets)
-#
- rs=0
-.equ TILEINFO_window_x , rs # \
- rs=rs+dh # - Window coordinates
-.equ TILEINFO_window_y , rs # /
- rs=rs+dh
-.equ TILEINFO_window_w , rs # \
- rs=rs+dh # - Window size
-.equ TILEINFO_window_h , rs # /
- rs=rs+dh
-.equ TILEINFO_tiles , rs # Pointer to TILEDEF entries
- rs=rs+dw
-.equ TILEINFO_mapdata , rs # Pointer to map data
- rs=rs+dw
-.equ TILEINFO_map_w , rs # Map width in tile units
- rs=rs+dh
-.equ TILEINFO_map_h , rs # Map height in tile units
- rs=rs+dh
-
-#
-# TILEPKT struct
-#
- rs=0
-.equ TILEPKT_tag , rs # Primitive tag
- rs=rs+dw
-.equ TILEPKT_tpage , rs # tpage packet
- rs=rs+dw
-.equ TILEPKT_rgbc , rs # Tile color
- rs=rs+dw
-.equ TILEPKT_x , rs # Tile screen coordinates
- rs=rs+dh
-.equ TILEPKT_y , rs
- rs=rs+dh
-.equ TILEPKT_uv , rs # Tile texture coordinates
- rs=rs+dh
-.equ TILEPKT_clut , rs # Tile CLUT
- rs=rs+dh
-.equ TILEPKT_len , rs # Packet length
-
-# addprim Macro
-#
-# Registers a primitive to a ordering table entry.
-#
-# Arguments:
-# ot - Register name of pointer to ordering table entry
-# pri - Pointer to a primitive packet
-# len - Size of packet in long words (specify as 0xnn00, ie. 0x2000)
-#
-# Destroys:
-# at, v0, v1
-#
-.macro addprim ot,pri,len
- .set noat
- lw $v0, 0(\ot) # Get OT entry
- lui $at, 0x00ff # Mask out the packet length field
- or $at, 0xffff
- and $v0, $at
- lui $v1, \len # Merge packet length
- or $v1, $v0
- sw $v1, 0(\pri) # Store updated OT entry to packet
- lw $v0, 0(\ot) # Get OT entry
- and \pri, $at # Mask out last 8-bits of packet address
- lui $at, 0xff00 # Mask out OT entry's address
- and $v0, $at
- or $v0, \pri # Merge packet address to OT entry
- sw $v0, 0(\ot) # Store updated OT entry
- .set at
-.endm
-
-#
-# Start of text section
-#
-.section .text
-
-# DrawTiles Function
-#
-# Renders a tilemap by generating TILEPKT primitives (combined SPRT_16 and
-# DR_TPAGE primitives) and registering it to the specified ordering table.
-# The drawing region, tile definitions and the tilemap are specified through
-# a TILEINFO struct.
-#
-# C Declaration:
-# extern u_char *DrawTiles(int scroll_x, int scroll_y,
-# TILEINFO *info, long *ot, u_char *pri);
-#
-# Arguments:
-# scroll_x - X scrolling offset of tile-map
-# scroll_y - Y scrolling offset of tile-map
-# info - Pointer to a TILEINFO struct
-# ot - Pointer to a ordering table entry
-# pri - Pointer to next primitive (placed in stack)
-#
-# Returns:
-# New next primitive pointer value.
-#
-.global DrawTiles # Declare symbol as global
-.type DrawTiles, @function # Declare it as a function
-DrawTiles: # Symbol label of function
-
- addiu $sp, -4 # Push frame pointer (fp) to stack
- sw $fp, 0($sp)
- move $fp, $sp # Copy stack pointer (sp) to fp
-
- # Register reference:
- #
- # t0 - Packet address
- # t1 - Map data address
- # t2 - Tile X offset
- # t3 - Tile Y offset
- # t4 - Tile X coordinate backup
- # t5 - Tile X loop counter
- # t6 - Number of tiles to sort per row
- # t7 - Number of tile rows to sort
-
- lhu $t6, TILEINFO_window_w($a2) # Calculate size of window in tiles
- lhu $t7, TILEINFO_window_h($a2)
- addi $t6, 15 # So the result will be rounded-up
- addi $t7, 15
- srl $t6, 4 # Effectively divide by 16
- srl $t7, 4
-
- lw $t0, 20($sp) # Obtain next primitive pointer
-
- srl $t2, $a0, 4 # Compute map offset in tile units
- srl $t3, $a1, 4
-
- bgez $a0, .Lno_neg_clip_X # Negative X clip test
- sub $v0, $0 , $a0
- move $t2, $0 # Force tile offset to zero
- add $v0, 15 # Reduce number of tile columns
- srl $v0, 4
- sub $t6, $v0
-.Lno_neg_clip_X:
- lhu $v1, TILEINFO_map_w($a2) # Positive X clip test
- add $v0, $t2, $t6
- addi $v0, 1
- blt $v0, $v1, .Lno_pos_clip_X
- nop
- sub $v0, $v1 # Compute how many tiles to clip
- sub $t6, $v0 # Reduce number of tile columns
-.Lno_pos_clip_X:
- bgez $a1, .Lno_neg_clip_Y # Negative Y clip test
- sub $v0, $0 , $a1
- move $t3, $0
- add $v0, 15
- srl $v0, 4
- sub $t7, $v0
-.Lno_neg_clip_Y:
- lhu $v1, TILEINFO_map_h($a2) # Positive Y clip test
- add $v0, $t3, $t7
- addi $v0, 1
- blt $v0, $v1, .Lno_pos_clip_Y
- nop
- sub $v0, $v1
- sub $t7, $v0
-.Lno_pos_clip_Y:
- bltz $t6, .Lno_draw # Exit when no tiles to draw
- nop
- bltz $t7, .Lno_draw
- nop
-
- lh $v0, TILEINFO_window_x($a2) # Compute pixel coordinates for
- sub $a0, $v0, $a0 # tiles based on the scroll offset
- sll $v0, $t2, 4
- add $a0, $v0
- lh $v0, TILEINFO_window_y($a2)
- sub $a1, $v0, $a1
- sll $v0, $t3, 4
- add $a1, $v0
- move $t4, $a0
- sll $t2, 1
-
-.Lloop_y: # Begin of tile row loop
- lhu $v0, TILEINFO_map_w($a2) # Get width of tilemap
- move $t5, $t6 # n tiles to draw row
- mult $t3, $v0 # Multiply Y offset by map width
- lw $t1, TILEINFO_mapdata($a2) # Get tilemap address
- nop
- addu $t1, $t2 # Add X offset to address
- mflo $v0 # Get Y offset result
- sll $v0, 1 # Multiply by two
- addu $t1, $v0 # Add to tile address
-
-.Lloop_x: # Begin of tile column loop
- lhu $v1, 0($t1) # Load tile index
- addiu $t1, 2 # Advance to next tile
- beq $v1, 0xFFFF, .Lskip_tile # Skip tile if index is 0xFFFF
- nop
- lw $v0, TILEINFO_tiles($a2) # Get pointer to TILEDEF entries
- sll $v1, 3 # Multiply by 8 (size of TILEDEFs)
- addu $v1, $v0 # Adjust to tiledefs pointer
- lw $v0, TILEDEF_uv($v1) # Obtain UV+CLUT
- lhu $v1, TILEDEF_tpage($v1) # Obtain tpage
- sw $v0, TILEPKT_uv($t0) # Start constructing packet
- lui $v0, 0xE100 # tpage packet code
- or $v0, $v1 # Merge tpage bits
- sw $v0, TILEPKT_tpage($t0)
- sh $a0, TILEPKT_x($t0) # Set tile screen coords
- sh $a1, TILEPKT_y($t0)
- li $v0, 0x7C7F7F7F # Packet code and color
- sw $v0, TILEPKT_rgbc($t0)
- addprim $a3, $t0, 0x0400 # Register to OT
- addiu $t0, TILEPKT_len # Advance packet pointer
-.Lskip_tile:
- addi $t5, -1 # Decrement and continue iterating
- bgez $t5, .Lloop_x # if non-zero
- addiu $a0, 16 # Advance X tile coordinate
-
- move $a0, $t4 # Restore tile X coordinate
- addi $t3, 1 # Increment Y offset
- addi $t7, -1 # Decrement and continue iterating
- bgez $t7, .Lloop_y # if non-zero
- addiu $a1, 16 # Advance Y tile coordinate
-
-.Lno_draw:
-
- move $v0, $t0 # Set packet pointer as return value
-
- lw $fp, 0($sp) # Restore frame pointer and return
- jr $ra
- addiu $sp, 4
- # DrawTiles
- \ No newline at end of file