WIP of BG1 scanline effects

A static BG1 is stable with BG0 offset values.  A seam in BG1
needs to be closed up by taking into account the BG1XOrigin value
when setting the :shift_value.

Also, several routines were hard-coded for the scanline case.  These
hanges need to be reverted and properly parametereized.
This commit is contained in:
Lucas Scharenbroich 2023-03-10 15:50:42 -06:00
parent 5cfefc350c
commit 9021ee4506
4 changed files with 403 additions and 20 deletions

View File

@ -41,6 +41,7 @@ appTmp0 equ 28
seg1x equ 30 seg1x equ 30
seg2x equ 32 seg2x equ 32
seg3x equ 34 seg3x equ 34
seg4x equ 36 ; BG1 x-pos
phk phk
plb plb
@ -51,9 +52,15 @@ seg3x equ 34
_MTStartUp ; GTE requires the miscellaneous toolset to be running _MTStartUp ; GTE requires the miscellaneous toolset to be running
lda #ENGINE_MODE_USER_TOOL ; Engine in Fast Mode as a User Tool lda #ENGINE_MODE_USER_TOOL+ENGINE_MODE_TWO_LAYER ; Engine in Fast Mode as a User Tool
jsr GTEStartUp ; Load and install the GTE User Tool jsr GTEStartUp ; Load and install the GTE User Tool
; Initialize the graphics screen playfield
pea #160
pea #200
_GTESetScreenMode
; Load a tileset ; Load a tileset
pea 0 pea 0
@ -67,6 +74,9 @@ seg3x equ 34
pea #TileSetPalette pea #TileSetPalette
_GTESetPalette _GTESetPalette
pea $0
_GTEClearBG1Buffer
; Set up our level data ; Set up our level data
; jsr BG0SetUp ; jsr BG0SetUp
@ -76,7 +86,13 @@ seg3x equ 34
pea App_TileMapBG0+{10*416} pea App_TileMapBG0+{10*416}
_GTESetBG0TileMapInfo _GTESetBG0TileMapInfo
stz seg1x
stz seg2x
stz seg3x
stz seg4x
jsr SetLimits jsr SetLimits
jsr DoLoadBG1
; Initialize local variables ; Initialize local variables
@ -315,6 +331,14 @@ IncRanges
bcc *+5 bcc *+5
lda #0 lda #0
sta seg3x sta seg3x
bit #1
bne :out
lda seg4x
inc
cmp #160
bcc *+5
lda #0
sta seg4x
:out :out
rts rts
@ -348,7 +372,13 @@ SetOffsets
lda seg2x lda seg2x
jsr SetOffset2 jsr SetOffset2
lda seg3x lda seg3x
jmp SetOffset3 jsr SetOffset3
pei seg4x
pea 0
_GTESetBG1Origin
rts
SetOffset1 SetOffset1
ldx #120 ldx #120
@ -408,6 +438,24 @@ _InitRange
:done :done
rts rts
; Load a binary file in the BG1 buffer
DoLoadBG1
jsr AllocBank ; Alloc 64KB for Load/Unpack
sta BankLoad ; Store "Bank Pointer"
ldx #BG1DataFile ; Load the background file into the bank
jsr LoadFile
pea #164 ; Fill everything
pea #200
pea #256
lda BankLoad
pha
pea $0000
pea $0000 ; default flags
_GTECopyPicToBG1
rts
BG1DataFile strl '1/bg1.bin'
BG0Offsets ds 416 BG0Offsets ds 416
PUT ../StartUp.s PUT ../StartUp.s

View File

@ -156,8 +156,16 @@ _DoOverlay
; Use the per-scanline tables to set the screen. This is really meant to be used without the built-in tilemap ; Use the per-scanline tables to set the screen. This is really meant to be used without the built-in tilemap
; support and is more of a low-level way to control the background rendering ; support and is more of a low-level way to control the background rendering
_RenderScanlines _RenderScanlines
lda BG1YTable ; Make sure we're in the right mode
cmp #$00A0
beq :ytbl_ok
lda #1
jsr _ResetBG1YTable
lda BG1YTable
:ytbl_ok
jsr _ApplyBG0YPos ; Set stack addresses for the virtual lines to the physical screen jsr _ApplyBG0YPos ; Set stack addresses for the virtual lines to the physical screen
jsr _ApplyBG1YPos ; Set the y-register values of the blitter jsr _ApplyScanlineBG1YPos ; Set the y-register values of the blitter
; _ApplyBG0Xpos need to be split because we have to set the offsets, then draw in any updated tiles, and ; _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. ; finally patch out the code field. Right now, the BRA operand is getting overwritten by tile data.
@ -170,6 +178,7 @@ _RenderScanlines
; jsr _ApplyTiles ; This function actually draws the new tiles into the code field ; jsr _ApplyTiles ; This function actually draws the new tiles into the code field
jsr _ApplyScanlineBG0XPos ; Patch the code field instructions with exit BRA opcode jsr _ApplyScanlineBG0XPos ; Patch the code field instructions with exit BRA opcode
jsr _ApplyScanlineBG1XPos
jsr _BuildShadowList ; Create the rages based on the sorted sprite y-values jsr _BuildShadowList ; Create the rages based on the sorted sprite y-values

View File

@ -500,6 +500,7 @@ _TSCopyPicToBG1
:src_width equ tmp6 :src_width equ tmp6
:src_height equ tmp7 :src_height equ tmp7
:src_stride equ tmp8 :src_stride equ tmp8
:src_flags equ tmp9
lda :width,s lda :width,s
sta :src_width sta :src_width
@ -509,7 +510,8 @@ _TSCopyPicToBG1
sta :src_stride sta :src_stride
ldy BG1DataBank ; Pick the target data bank ldy BG1DataBank ; Pick the target data bank
; lda :flags,s lda :flags,s
sta :src_flags
; bit #$0001 ; bit #$0001
; beq *+4 ; beq *+4
; ldy BG1AltBank ; ldy BG1AltBank

View File

@ -12,6 +12,7 @@ _InitBG1
_CopyBinToBG1 _CopyBinToBG1
:src_width equ tmp6 :src_width equ tmp6
:src_height equ tmp7 :src_height equ tmp7
:src_flags equ tmp9
clc clc
adc #8 ; Advance over the header adc #8 ; Advance over the header
@ -21,10 +22,46 @@ _CopyBinToBG1
sta :src_width sta :src_width
lda #208 lda #208
sta :src_height sta :src_height
stz :src_flags
pla pla
jmp _CopyToBG1 jmp _CopyToBG1
; Reset the BG1 Y-table depending on the rendering mode
;
; A = mode
; 0 = default (base = $1800, stride = 256)
; 1 = scanline (base = $A0, stride = 324)
_ResetBG1YTable
:base equ tmp0
:stride equ tmp1
cmp #1 ; scanline mode?
bne :default
lda #$A0
sta :base
lda #324
sta :stride
bra :begin
:default
lda #$1800
sta :base
lda #256
sta :stride
:begin
ldx #0
lda :base
:loop
sta BG1YTable,x
sta BG1YTable+{208*2},x
clc
adc :stride
inx
inx
cpx #{208*2}
bcc :loop
rts
; Copy a IIgs $C1 picture into BG1. Assumes the file is the correct size (320 x 200) ; Copy a IIgs $C1 picture into BG1. Assumes the file is the correct size (320 x 200)
; ;
@ -35,6 +72,7 @@ _CopyPicToBG1
:src_width equ tmp6 :src_width equ tmp6
:src_height equ tmp7 :src_height equ tmp7
:src_stride equ tmp8 :src_stride equ tmp8
:src_flags equ tmp9
pha pha
lda #160 lda #160
@ -43,6 +81,7 @@ _CopyPicToBG1
lda #200 lda #200
sta :src_height sta :src_height
pla pla
stz :src_flags
jmp _CopyToBG1 jmp _CopyToBG1
; Generic routine to copy image data into BG1 ; Generic routine to copy image data into BG1
@ -54,39 +93,52 @@ _CopyToBG1
:src_width equ tmp6 :src_width equ tmp6
:src_height equ tmp7 :src_height equ tmp7
:src_stride equ tmp8 :src_stride equ tmp8
:src_flags equ tmp9
:dstptr2 equ tmp10
sta :srcptr sta :srcptr
stx :srcptr+2 stx :srcptr+2
sty :dstptr+2 ; Everything goes into this bank sty :dstptr+2 ; Everything goes into this bank
sty :dstptr2+2
lda #$00A0
sta :dstptr
clc
adc #164 ; leave a 4-byte gap in the middle
sta :dstptr2
; "Normal" BG1 mode as a stride of 164 bytes and mirrors the BG0 size (328 x 208)
; In "Scanline" mode, the BG1 is treated as a 320x200 bitfield with each horizontal line doubled
lda :src_width
min #160
sta :src_width
lda :src_height
min #200
sta :src_height
stz :line_cnt stz :line_cnt
:rloop :rloop
lda :line_cnt ; get the pointer to the code field line
asl
tax
lda BG1YTable,x
sta :dstptr
ldy #0 ; move forward in the image data and image data ldy #0 ; move forward in the image data and image data
:cloop :cloop
lda [:srcptr],y lda [:srcptr],y
sta [:dstptr],y sta [:dstptr],y
sta [:dstptr2],y
:skip
iny iny
iny iny
cpy :src_width cpy :src_width
bcc :cloop bcc :cloop
ldy #164 lda :dstptr
lda [:srcptr] ; Duplicate the last couple of words in the extra space at the end of the line clc
sta [:dstptr],y adc #324
sta :dstptr
ldy #2 adc #164
lda [:srcptr],y sta :dstptr2
ldy #166
sta [:dstptr],y
lda :srcptr lda :srcptr
clc clc
@ -140,6 +192,34 @@ _ApplyBG1XPosPre
sta BG1StartXMod164 sta BG1StartXMod164
rts rts
; Save as _ApplyBG1XPos, but we pretend that StartXMod164 is always zero and deal with the per-line offset adjustment in
; _ApplyScanlineBG1YPos. The tweak here is that the buffer is only 160 bytes wide in scanine mode, instead of 164 bytes wide
_ApplyScanlineBG1XPos
lda BG1StartXMod164 ; How far into the BG1 buffer is the left edge?
tay
phd ; save the direct page because we are going to switch to the
lda BlitterDP ; blitter direct page space and fill in the addresses
tcd
ldx #0
tya
:loop
sta 00,x ; store the value
inc
inc
cmp #164
bcc *+5
sbc #164
inx
inx
cpx #164
bcc :loop
pld
rts
_ApplyBG1XPos _ApplyBG1XPos
lda #162 lda #162
sec sec
@ -196,6 +276,155 @@ _ClearBG1Buffer
plb plb
rts rts
; Variation to take care of horizontal adjustments within the BG1 buffer to compensate for the
; per-scanline BG0 displacement. It is up to the caller to manage the memeory layout to make
; this visually work.
;
; In the scanline mode we have to be able to adjust the base address of each BG1 line up to
; a full screen, so scanline mode treats bank as a 640x200 pixel bitmap (64000 byte).
;
; This is just a limitation of scanline displacement mode that there is no extra vertical space.
_ApplyScanlineBG1YPos
:stk_save equ tmp0
:virt_line_x2 equ tmp1
:lines_left_x2 equ tmp2
:draw_count_x2 equ tmp3
:ytbl_idx_x2 equ tmp4
:shift_value equ tmp5
; Avoid local var collision
:ytbl_idx_pos_x2 equ tmp10
:virt_line_pos_x2 equ tmp11
:total_left_x2 equ tmp12
:current_count_x2 equ tmp13
:ptr equ tmp14
lda StartXMod164Tbl
sta :ptr
lda StartXMod164Tbl+2
sta :ptr+2
ora :ptr
lda BG1StartY
jsr Mod208
sta BG1StartYMod208
asl
sta :ytbl_idx_pos_x2 ; Start copying from the first entry in the table
lda StartYMod208 ; This is the base line of the virtual screen
asl
sta :virt_line_pos_x2
tay
lda ScreenHeight
asl
sta :total_left_x2
:loop0
lda [:ptr],y
tax
and #$FF00 ; Determine how many sequential lines have this mod value
xba
inc
asl
min :total_left_x2 ; Don't draw more than the number of lines that are left to process
sta :current_count_x2 ; Save a copy for later
sta :lines_left_x2 ; Set the parameter
lda :ytbl_idx_pos_x2 ; Set the parameter
sta :ytbl_idx_x2
sty :virt_line_x2 ; Set the parameter
txa ; Put the X mod 164 value in the offset value
and #$00FF
sta :shift_value
jsr :_ApplyConstBG1YPos ; Shift this range by a constant amount
clc
lda :virt_line_pos_x2
adc :current_count_x2
cmp #208*2 ; Do the modulo check in this loop
bcc *+5
sbc #208*2
sta :virt_line_pos_x2
tay
clc
lda :ytbl_idx_pos_x2
adc :current_count_x2
sta :ytbl_idx_pos_x2
lda :total_left_x2
sec
sbc :current_count_x2
sta :total_left_x2
bne :loop0
rts
:_ApplyConstBG1YPos
lda #164
sec
sbc :shift_value
; bpl *+6
; clc
; adc #160
; clc
; adc :shift_value
sta :shift_value
; cmp #160
; beq *+4
; brk $55
phb ; Save the existing bank
tsc
sta :stk_save
:loop
ldx :virt_line_x2
ldal BTableHigh,x ; Get the bank
pha
plb
ldal BTableLow,x ; Get the address of the first code field line
tay
txa ; Calculate number of lines to draw on this iteration
and #$001E
eor #$FFFF
sec
adc #32
min :lines_left_x2
sta :draw_count_x2
tax
lda :ytbl_idx_x2 ; Read from this location in the BG1YTable
clc
CopyBG1YTableToBG1Addr3 :shift_value
; jsr CopyBG1YTableToBG1Addr
lda :virt_line_x2 ; advance to the virtual line after
adc :draw_count_x2 ; filled in
sta :virt_line_x2
lda :ytbl_idx_x2
adc :draw_count_x2
sta :ytbl_idx_x2
lda :lines_left_x2 ; subtract the number of lines we just completed
sec
sbc :draw_count_x2
sta :lines_left_x2
jne :loop
lda :stk_save
tcs
plb
rts
; Everytime either BG1 or BG0 Y-position changes, we have to update the Y-register ; Everytime either BG1 or BG0 Y-position changes, we have to update the Y-register
; value in all of the code fields (within the visible screen) ; value in all of the code fields (within the visible screen)
_ApplyBG1YPos _ApplyBG1YPos
@ -353,8 +582,103 @@ CopyBG1YTableToBG1Addr
sta: BG1_ADDR+$0000,y sta: BG1_ADDR+$0000,y
:none rts :none rts
; Unrolled copy routine to move BG1YTable entries into BG1_ADDR position
; with a constant shift applied
;
; A = index into the BG1YTable array (x2)
; Y = starting line * $1000
; X = number of lines (x2)
; ]1 = offset
CopyBG1YTableToBG1Addr3 mac
jmp (tbl,x)
tbl da none
da do01,do02,do03,do04
da do05,do06,do07,do08
da do09,do10,do11,do12
da do13,do14,do15,do16
do15 tax
jmp x15
do14 tax
jmp x14
do13 tax
jmp x13
do12 tax
jmp x12
do11 tax
jmp x11
do10 tax
jmp x10
do09 tax
jmp x09
do08 tax
jmp x08
do07 tax
jmp x07
do06 tax
jmp x06
do05 tax
jmp x05
do04 tax
jmp x04
do03 tax
jmp x03
do02 tax
jmp x02
do01 tax
jmp x01
do16 tax
ldal BG1YTable+30,x
adc ]1
sta BG1_ADDR+$F000,y
x15 ldal BG1YTable+28,x
adc ]1
sta BG1_ADDR+$E000,y
x14 ldal BG1YTable+26,x
adc ]1
sta BG1_ADDR+$D000,y
x13 ldal BG1YTable+24,x
adc ]1
sta BG1_ADDR+$C000,y
x12 ldal BG1YTable+22,x
adc ]1
sta BG1_ADDR+$B000,y
x11 ldal BG1YTable+20,x
adc ]1
sta BG1_ADDR+$A000,y
x10 ldal BG1YTable+18,x
adc ]1
sta BG1_ADDR+$9000,y
x09 ldal BG1YTable+16,x
adc ]1
sta BG1_ADDR+$8000,y
x08 ldal BG1YTable+14,x
adc ]1
sta BG1_ADDR+$7000,y
x07 ldal BG1YTable+12,x
adc ]1
sta BG1_ADDR+$6000,y
x06 ldal BG1YTable+10,x
adc ]1
sta BG1_ADDR+$5000,y
x05 ldal BG1YTable+08,x
adc ]1
sta: BG1_ADDR+$4000,y
x04 ldal BG1YTable+06,x
adc ]1
sta BG1_ADDR+$3000,y
x03 ldal BG1YTable+04,x
adc ]1
sta BG1_ADDR+$2000,y
x02 ldal BG1YTable+02,x
adc ]1
sta BG1_ADDR+$1000,y
x01 ldal BG1YTable+00,x
adc ]1
sta: BG1_ADDR+$0000,y
none <<<
; Unrolled copy routine to move BG1YTable entries into BG1_ADDR position with an additional ; Unrolled copy routine to move BG1YTable entries into BG1_ADDR position with an additional
; shift. This has to be split into two ; shifton every line. This has to be split into two
; ;
; A = index into the BG1YTable array (x2) ; A = index into the BG1YTable array (x2)
; Y = starting line * $1000 ; Y = starting line * $1000