mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2024-11-26 07:49:17 +00:00
143 lines
5.3 KiB
ArmAsm
143 lines
5.3 KiB
ArmAsm
; Renders a frame of animation
|
|
;
|
|
; The rendering engine is built around the idea of compositing all of the moving components
|
|
; on to the Bank 01 graphics buffer and then revealing everything in a single, vertical pass.
|
|
;
|
|
; If there was just a scrolling screen with no sprites, the screen would just get rendered
|
|
; in a single pass, but it gets more complicated with sprites and various effects.
|
|
;
|
|
; Here is the high-level pipeline:
|
|
;
|
|
; 1. Identify row ranges with effects. These effects can be sprites or user-defined overlays
|
|
; 2. Turn shadowing off
|
|
; 3. Render the background for each effect row range (in any order)
|
|
; 4. Render the sprites (in any order)
|
|
; 5. Turn shadowing on
|
|
; 6. Render the background for each non-effect row, a pei slam for sprite rows, and
|
|
; the user-defined overlays (in sorted order)
|
|
;
|
|
; As a concrete example, consider:
|
|
;
|
|
; Rows 0 - 9 have a user-defined floating overlay for a score board
|
|
; Rows 10 - 100 are background only
|
|
; Rows 101 - 120 have one or more sprites
|
|
; Rows 121 - 140 are background only
|
|
; Rows 141 - 159 have a user-defined solid overlay for an animated platform
|
|
;
|
|
; A floating overlay means that some background data bay show through. A solid overlay means that
|
|
; the user-defined data covers the entire scan line.
|
|
;
|
|
; The renderer would proceed as:
|
|
;
|
|
; - shadow off
|
|
; - render_background(0, 10)
|
|
; - render_background(101, 121)
|
|
; - render_sprites()
|
|
; - shadow_on
|
|
; - render_user_overlay_1()
|
|
; - render_background(10, 101)
|
|
; - pei_slam(101, 121)
|
|
; - render_background(121, 141)
|
|
; - render_user_overlay_2()
|
|
;
|
|
; Generally speaking, a PEI Slam is faster that trying to do any sort of dirty-rectangle update by
|
|
; tracking sprinte bounding boxes. But, if an application would benefit from skipping some background
|
|
; drawing on sprite rows, that can be handled by using the low level routines to control the left/right
|
|
; edges of the rendered play field.
|
|
|
|
|
|
; The render function is the point of committment -- most of the APIs that set sprintes and
|
|
; update coordinates are lazy; they simply save the value and set a dirty flag in the
|
|
; DirtyBits word.
|
|
;
|
|
; This function examines the dirty bits and actually performs the work to update the code field
|
|
; and internal data structure to properly render the play field. Then the update pipeline is
|
|
; executed.
|
|
Render ENT
|
|
phb
|
|
phk
|
|
plb
|
|
jsr _Render
|
|
plb
|
|
rtl
|
|
|
|
; TODO -- actually check the dirty bits and be selective on what gets updated. For example, if
|
|
; only the Y position changes, then we should only need to set new values on the
|
|
; virtual lines that were brought on screen. If the X position only changes by one
|
|
; byte, then we may have to change the CODE_ENTRY values or restore/set new OPCODE
|
|
; values, but not both.
|
|
|
|
; It's important to do _ApplyBG0YPos first because it calculates the value of StartY % 208 which is
|
|
; used in all of the other loops
|
|
_Render
|
|
jsr _ApplyBG0YPos ; Set stack addresses for the virtual lines to the physical screen
|
|
jsr _ApplyBG1YPos
|
|
|
|
; _ApplyBG0Xpos need to be split because we have to set the offsets, then draw in any updated tiles, and
|
|
; finally patch out the code field. Right now, the BRA operand is getting overwritten by tile data.
|
|
jsr _ApplyBG0XPosPre
|
|
jsr _ApplyBG1XPosPre
|
|
|
|
jsr _RenderSprites ; Once the BG0 X and Y positions are committed, update sprite data
|
|
|
|
jsr _UpdateBG0TileMap ; and the tile maps. These subroutines build up a list of tiles
|
|
jsr _UpdateBG1TileMap ; that need to be updated in the code field
|
|
|
|
jsr _ApplyTiles ; This function actually draws the new tiles into the code field
|
|
|
|
jsr _ApplyBG0XPos ; Patch the code field instructions with exit BRA opcode
|
|
jsr _ApplyBG1XPos ; Update the direct page value based on the horizontal position
|
|
|
|
; The code fields are locked in now and ready to be rendered
|
|
|
|
jsr _ShadowOff
|
|
|
|
; Shadowing is turned off. Render all of the scan lines that need a second pass. One
|
|
; optimization that can be done here is that the lines can be rendered in any order
|
|
; since it is not shown on-screen yet.
|
|
|
|
; ldx #0 ; Blit the full virtual buffer to the screen
|
|
; ldy #8
|
|
; jsr _BltRange
|
|
|
|
; Turn shadowing back on
|
|
|
|
jsr _ShadowOn
|
|
|
|
; Now render all of the remaining lines in top-to-bottom (or bottom-to-top) order
|
|
|
|
lda ScreenY0 ; pass the address of the first line of the overlay
|
|
clc
|
|
adc #0
|
|
asl
|
|
tax
|
|
lda ScreenAddr,x
|
|
clc
|
|
adc ScreenX0
|
|
; jsl Overlay
|
|
|
|
ldx #0 ; Blit the full virtual buffer to the screen
|
|
ldy ScreenHeight
|
|
jsr _BltRange
|
|
|
|
; ldx #0
|
|
; ldy ScreenHeight
|
|
; jsr _BltSCB
|
|
|
|
lda StartY ; Restore the fields back to their original state
|
|
ldx ScreenHeight
|
|
jsr _RestoreBG0Opcodes
|
|
|
|
lda StartY
|
|
sta OldStartY
|
|
lda StartX
|
|
sta OldStartX
|
|
|
|
lda BG1StartY
|
|
sta OldBG1StartY
|
|
lda BG1StartX
|
|
sta OldBG1StartX
|
|
|
|
stz DirtyBits
|
|
rts
|