; Initialization and setup routines for the second background
_InitBG1
                          jsr   _ApplyBG1YPos
                          jsr   _ApplyBG1XPos
                          rts

; Copy a binary image data file into BG1.  Assumes the file is the correct size (328 x 208)
;
; A=low word of picture address
; X=high word of pixture address
; Y=high word of BG1 bank
_CopyBinToBG1
:src_width                equ   tmp6
:src_height               equ   tmp7
:src_flags                equ   tmp9

                          clc
                          adc   #8                        ; Advance over the header
                          pha

                          lda   #164
                          sta   :src_width
                          lda   #208
                          sta   :src_height
                          lda   #COPY_PIC_NORMAL
                          sta   :src_flags

                          pla
                          jmp   _CopyToBG1

; Reset the BG1 Y-table depending on the rendering mode
;
; A = mode
;     0 = default   (base = $1800, stride = 256)
;     1 = scanline  (base = $0, stride = 327)
_ResetBG1YTable
:base    equ  tmp0
:stride  equ  tmp1
                          cmp   #1                 ; scanline mode?
                          bne   :default
                          lda   #0
                          sta   :base
                          lda   #327
                          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)
;
; A=low word of picture address
; X=high word of pixture address
; Y=high word of BG1 bank
_CopyPicToBG1
:src_width                equ   tmp6
:src_height               equ   tmp7
:src_stride               equ   tmp8
:src_flags                equ   tmp9

                          pha
                          lda    #160
                          sta    :src_width
                          sta    :src_stride
                          lda    #200
                          sta    :src_height
                          lda    #COPY_PIC_NORMAL
                          sta    :src_flags
                          pla
                          jmp    _CopyToBG1

; Generic routine to copy image data into BG1
_CopyToBG1
:srcptr                   equ   tmp0
:line_cnt                 equ   tmp2
:dstptr                   equ   tmp3
:col_cnt                  equ   tmp5
:src_width                equ   tmp6
:src_height               equ   tmp7
:src_stride               equ   tmp8
:src_flags                equ   tmp9
:dstptr2                  equ   tmp10

; scanline mode is tricky -- there's not enough space to make two full copies of a 328x200 bitmap buffer, but we can 
; *barely* fit a (164 + 163) x 200 buffer.  And, since the zero offset could use either end, this covers all of the cases.

                          sta   :srcptr
                          stx   :srcptr+2
                          sty   :dstptr+2                 ; Everything goes into this bank
                          sty   :dstptr2+2

; "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 328x200 bitfield with each horizontal line doubled

                          lda   :src_flags
                          cmp   #COPY_PIC_NORMAL
                          bne   *+5
                          jmp   :_CopyToBG1Normal

                          cmp   #COPY_PIC_SCANLINE
                          bne   *+5
                          jmp   :_CopyToBG1SCanline

                          rts                             ; Flag do not match a known copy mode

:_CopyToBG1SCanline
                          lda   #0                        ; Start a byte 1 because odd offsets might go back 1 byte and don't want to wrap around
                          sta   :dstptr
                          clc
                          adc   #164                      ; The first part is 1-byte short, the second part is a full 164 bytes
                          sta   :dstptr2

                          lda   :src_width
                          min   #164
                          sta   :src_width

                          lda   :src_height
                          min   #200
                          sta   :src_height

                          stz   :line_cnt
:rloop
                          ldy   #0                        ; move forward in the image data and image data
; Handle first word as a special case

                          lda   [:srcptr],y
                          sta   [:dstptr2],y              ; copy directly into the 164-byte buffer
                          iny
                          xba
                          sep   #$20
                          sta   [:dstptr],y               ; only copy the high byte because the previous line occupies the low byte
                          rep   #$20
                          iny

:cloop
                          lda   [:srcptr],y
                          sta   [:dstptr],y
                          sta   [:dstptr2],y

                          iny
                          iny

                          cpy   :src_width
                          bcc   :cloop

                          lda   :dstptr
                          clc
                          adc   #327
                          sta   :dstptr
                          adc   #164
                          sta   :dstptr2

                          lda   :srcptr
                          clc
                          adc   :src_stride
                          sta   :srcptr

                          inc   :line_cnt
                          lda   :line_cnt
                          cmp   :src_height
                          bcc   :rloop
                          rts

:_CopyToBG1Normal
                          stz   :line_cnt
:rloop2
                          lda   :line_cnt                 ; get the pointer to the code field line
                          asl
                          tax

                          lda   BG1YTable,x
                          sta   :dstptr
                          clc
                          adc   #164
                          sta   :dstptr2

                          ldy   #0                        ; move forward in the image data and image data
:cloop2
                          lda   [:srcptr],y
                          sta   [:dstptr],y

                          iny
                          iny

                          cpy   :src_width
                          bcc   :cloop2

                          ldy   #0
                          lda   [:dstptr],y               ; Duplicate the last couple of words in the extra space at the end of the line
                          sta   [:dstptr2],y

                          ldy   #2
                          lda   [:dstptr],y
                          sta   [:dstptr2],y

                          lda   :srcptr
                          clc
                          adc   :src_stride
                          sta   :srcptr

                          inc   :line_cnt
                          lda   :line_cnt
                          cmp   :src_height
                          bcc   :rloop2
                          rts

_SetBG1XPos
                          cmp   BG1StartX
                          beq   :out                      ; Easy, if nothing changed, then nothing changes

                          ldx   BG1StartX                 ; Load the old value (but don't save it yet)
                          sta   BG1StartX                 ; Save the new position

                          lda   #DIRTY_BIT_BG1_X
                          tsb   DirtyBits                 ; Check if the value is already dirty, if so exit
                          bne   :out                      ; without overwriting the original value

                          stx   OldBG1StartX              ; First change, so preserve the value
:out                      rts

_SetBG1YPos
                          cmp   BG1StartY
                          beq   :out                      ; Easy, if nothing changed, then nothing changes

                          ldx   BG1StartY                 ; Load the old value (but don't save it yet)
                          sta   BG1StartY                 ; Save the new position

                          lda   #DIRTY_BIT_BG1_Y
                          tsb   DirtyBits                 ; Check if the value is already dirty, if so exit
                          bne   :out                      ; without overwriting the original value

                          stx   OldBG1StartY              ; First change, so preserve the value
:out                      rts


; Everytime either BG1 or BG0 X-position changes, we have to update the direct page values.  We 
; *could* do this by adjusting the since the address offset, but we have to change up to 200 values
; when the vertical position changes, and only 41 when the horizontal value changes.  Plus
; these are all direct page values
;
; Note: This routine can be optimized as an unrolled loop of PEI instructions
_ApplyBG1XPosPre
                          lda   BG1StartX                 ; This is the starting byte offset (0 - 163)
                          jsr   Mod164
                          sta   BG1StartXMod164
                          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
                          lda   #0
:loop
                          sta   00,x                      ; store the value
                          inc
                          inc
                          cmp   #164
                          bcc   *+5
                          sbc   #164

                          inx
                          inx
                          cpx   #164
                          bcc   :loop

                          pld
                          rts

_ApplyBG1XPos
                          lda   #162
                          sec
                          sbc   StartXMod164              ; Need to compensate for both BG0 and BG1 positions
                          bpl   *+6
                          clc
                          adc   #164
                          clc
                          adc   BG1StartXMod164
                          cmp   #164
                          bcc   *+5
                          sbc   #164
                          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   #162
                          tya
:loop
                          sta   00,x                      ; store the value
                          dec
                          dec
                          bpl   :nowrap
                          clc
                          adc   #164

:nowrap
                          dex
                          dex
                          bpl   :loop
                          pld
                          rts

_ClearBG1Buffer
                          phb
                          pha
                          sep   #$20
                          lda   BG1DataBank
                          pha
                          plb
                          rep   #$20

                          pla
                          ldx   #0
:loop
                          sta:  $0000,x
                          inx
                          inx
                          cpx   #0
                          bne   :loop

                          plb
                          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
:ptr2               equ   tmp8
: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

                    lda   BG1StartXMod164Tbl
                    sta   :ptr2
                    lda   BG1StartXMod164Tbl+2
                    sta   :ptr2+2
                    ora   :ptr2

                    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
                    clc
                    adc   BG1StartXMod164
                    cmp   #164+1
                    bcc   *+5
                    sbc   #164
                    sta   :shift_value               ; Base shift value

                    cmp   #165
                    bcc   *+4
                    brk   $04

                    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
                    CopyBG1YTableToBG1Addr4 :shift_value;blttmp

                    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
; value in all of the code fields (within the visible screen)
_ApplyBG1YPos
:virt_line                equ   tmp0
:lines_left               equ   tmp1
:draw_count               equ   tmp2
:ytbl_idx                 equ   tmp3

                          phb                             ; Save the bank

                          lda   BG1StartY
                          jsr   Mod208
                          sta   BG1StartYMod208
                          sta   :ytbl_idx                 ; Start copying from the first entry in the table

                          lda   StartYMod208              ; This is the base line of the virtual screen
                          sta   :virt_line                ; Keep track of it

                          lda   ScreenHeight
                          sta   :lines_left

:loop
                          lda   :virt_line
                          asl
                          tax
                          ldal  BTableLow,x               ; Get the address of the first code field line
                          tay

                          sep   #$20
                          ldal  BTableHigh,x
                          pha                             ; push the bank on the stack
                          plb
                          rep   #$20

                          lda   :virt_line
                          and   #$000F
                          eor   #$FFFF
                          inc
                          clc
                          adc   #16
                          min   :lines_left

                          sta   :draw_count               ; Do this many lines
                          asl
                          tax

                          lda   RenderFlags
                          bit   #RENDER_BG1_HORZ_OFFSET   ; Are we using horizontal displacement?
                          beq   :no_displacement

                          lda   :ytbl_idx                 ; Read from this location in the BG1YTable
                          asl
                          jsr   CopyBG1YTableToBG1Addr2
                          bra   :next_step

:no_displacement
                          lda   :ytbl_idx                 ; Read from this location in the BG1YTable
                          asl
                          jsr   CopyBG1YTableToBG1Addr    ; or CopyBG1YTableToBG1Addr2

:next_step
                          lda   :virt_line                ; advance to the virtual line after the segment we just
                          clc                             ; filled in
                          adc   :draw_count
                          sta   :virt_line

                          lda   :ytbl_idx                 ; advance the index into the YTable
                          adc   :draw_count
                          sta   :ytbl_idx

                          lda   :lines_left               ; subtract the number of lines we just completed
                          sec
                          sbc   :draw_count
                          sta   :lines_left

                          jne   :loop

                          plb
                          rts

; Unrolled copy routine to move BG1YTable entries into BG1_ADDR position.
;
; A = index into the BG1YTable array (x2)
; Y = starting line * $1000
; X = number of lines (x2)
CopyBG1YTableToBG1Addr
                          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
                          bra   :x15
:do14                     tax
                          bra   :x14
:do13                     tax
                          bra   :x13
:do12                     tax
                          bra   :x12
:do11                     tax
                          bra   :x11
:do10                     tax
                          bra   :x10
:do09                     tax
                          bra   :x09
:do08                     tax
                          bra   :x08
:do07                     tax
                          bra   :x07
:do06                     tax
                          bra   :x06
:do05                     tax
                          bra   :x05
:do04                     tax
                          bra   :x04
:do03                     tax
                          bra   :x03
:do02                     tax
                          bra   :x02
:do01                     tax
                          bra   :x01
:do16                     tax
                          ldal  BG1YTable+30,x
                          sta   BG1_ADDR+$F000,y
:x15                      ldal  BG1YTable+28,x
                          sta   BG1_ADDR+$E000,y
:x14                      ldal  BG1YTable+26,x
                          sta   BG1_ADDR+$D000,y
:x13                      ldal  BG1YTable+24,x
                          sta   BG1_ADDR+$C000,y
:x12                      ldal  BG1YTable+22,x
                          sta   BG1_ADDR+$B000,y
:x11                      ldal  BG1YTable+20,x
                          sta   BG1_ADDR+$A000,y
:x10                      ldal  BG1YTable+18,x
                          sta   BG1_ADDR+$9000,y
:x09                      ldal  BG1YTable+16,x
                          sta   BG1_ADDR+$8000,y
:x08                      ldal  BG1YTable+14,x
                          sta   BG1_ADDR+$7000,y
:x07                      ldal  BG1YTable+12,x
                          sta   BG1_ADDR+$6000,y
:x06                      ldal  BG1YTable+10,x
                          sta   BG1_ADDR+$5000,y
:x05                      ldal  BG1YTable+08,x
                          sta:  BG1_ADDR+$4000,y
:x04                      ldal  BG1YTable+06,x
                          sta   BG1_ADDR+$3000,y
:x03                      ldal  BG1YTable+04,x
                          sta   BG1_ADDR+$2000,y
:x02                      ldal  BG1YTable+02,x
                          sta   BG1_ADDR+$1000,y
:x01                      ldal  BG1YTable+00,x
                          sta:  BG1_ADDR+$0000,y
: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                      <<<

; Copy routine to move BG1YTable entries into BG1_ADDR position with an additional
; shift on every line form the user-provided BG1StartXMod164Tbl.
;
; A = index into the BG1YTable array (x2)
; Y = starting line * $1000
; X = number of lines (x2)
;
; ]1 = constant shift value
; ]2 = temp storage space
CopyBG1YTableToBG1Addr4   mac
                          phy                             ; save the registers
                          phx
                          phb
                          pha
                          jsr   _SetDataBank              ; Set to toolbox data bank

                          clc
                          lda   1,s                       ; virtual_index_x2
                          adc   BG1StartXMod164Tbl        ; Get the starting address in the array for this chunk
                          tay

                          lda   BG1StartXMod164Tbl+1      ; Set the bank to the array location
                          pha
                          plb
                          plb

                          pla                             ; POp back the original value 
                          ApplyBG1ModXToShift ]1;]2       ; Copy the array into direct page storage and apply the shift

                          plb                             ; Restore the code field bank
                          plx                             ; x is used directly in this routine
                          ply
                          ApplyBG1ShiftToCode ]2
                          <<<

; Unrolled copy routine to move BG1YTable entries into BG1_ADDR position with an additional
; shift on every line.  This has to be split into two 
;
; A = index into the BG1YTable array (x2)
; Y = starting line * $1000
; X = number of lines (x2)
CopyBG1YTableToBG1Addr2
                          phy                             ; save the registers
                          phx
                          phb
                          pha
                          jsr   _SetDataBank              ; Set to toolbox data bank

                          pla
                          ldy   BG1OffsetIndex            ; Get the offset and save the values
                          jsr   SaveBG1OffsetValues

                          plb
                          plx                             ; x is used directly in this routine
                          ply
                          jmp   ApplyBG1OffsetValues

SaveBG1OffsetValues
                          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
                          bra   :x15
:do14                     tax
                          bra   :x14
:do13                     tax
                          bra   :x13
:do12                     tax
                          bra   :x12
:do11                     tax
                          bra   :x11
:do10                     tax
                          bra   :x10
:do09                     tax
                          bra   :x09
:do08                     tax
                          bra   :x08
:do16                     tax
                          lda   BG1YTable+30,x
                          adc   BG1YOffsetTable+30,y
                          sta   BG1YCache+30
:x15                      lda   BG1YTable+28,x
                          adc   BG1YOffsetTable+28,y
                          sta   BG1YCache+28
:x14                      lda   BG1YTable+26,x
                          adc   BG1YOffsetTable+26,y
                          sta   BG1YCache+26
:x13                      lda   BG1YTable+24,x
                          adc   BG1YOffsetTable+24,y
                          sta   BG1YCache+24
:x12                      lda   BG1YTable+22,x
                          adc   BG1YOffsetTable+22,y
                          sta   BG1YCache+22
:x11                      lda   BG1YTable+20,x
                          adc   BG1YOffsetTable+20,y
                          sta   BG1YCache+20
:x10                      lda   BG1YTable+18,x
                          adc   BG1YOffsetTable+18,y
                          sta   BG1YCache+18
:x09                      lda   BG1YTable+16,x
                          adc   BG1YOffsetTable+16,y
                          sta   BG1YCache+16
:x08                      lda   BG1YTable+14,x
                          adc   BG1YOffsetTable+14,y
                          sta   BG1YCache+14
:x07                      lda   BG1YTable+12,x
                          adc   BG1YOffsetTable+12,y
                          sta   BG1YCache+12
:x06                      lda   BG1YTable+10,x
                          adc   BG1YOffsetTable+10,y
                          sta   BG1YCache+10
:x05                      lda   BG1YTable+08,x
                          adc   BG1YOffsetTable+08,y
                          sta   BG1YCache+08
:x04                      lda   BG1YTable+06,x
                          adc   BG1YOffsetTable+06,y
                          sta   BG1YCache+06
:x03                      lda   BG1YTable+04,x
                          adc   BG1YOffsetTable+04,y
                          sta   BG1YCache+04
:x02                      lda   BG1YTable+02,x
                          adc   BG1YOffsetTable+02,y
                          sta   BG1YCache+02
:x01                      lda   BG1YTable+00,x
                          adc   BG1YOffsetTable+00,y
                          sta   BG1YCache+00
:none                     rts
:do07                     tax
                          bra   :x07
:do06                     tax
                          bra   :x06
:do05                     tax
                          bra   :x05
:do04                     tax
                          bra   :x04
:do03                     tax
                          bra   :x03
:do02                     tax
                          bra   :x02
:do01                     tax
                          bra   :x01


ApplyBG1OffsetValues
                          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
:do16                     ldal  BG1YCache+30
                          sta   BG1_ADDR+$F000,y
:do15                     ldal  BG1YCache+28
                          sta   BG1_ADDR+$E000,y
:do14                     ldal  BG1YCache+26
                          sta   BG1_ADDR+$D000,y
:do13                     ldal  BG1YCache+24
                          sta   BG1_ADDR+$C000,y
:do12                     ldal  BG1YCache+22
                          sta   BG1_ADDR+$B000,y
:do11                     ldal  BG1YCache+20
                          sta   BG1_ADDR+$A000,y
:do10                     ldal  BG1YCache+18
                          sta   BG1_ADDR+$9000,y
:do09                     ldal  BG1YCache+16
                          sta   BG1_ADDR+$8000,y
:do08                     ldal  BG1YCache+14
                          sta   BG1_ADDR+$7000,y
:do07                     ldal  BG1YCache+12
                          sta   BG1_ADDR+$6000,y
:do06                     ldal  BG1YCache+10
                          sta   BG1_ADDR+$5000,y
:do05                     ldal  BG1YCache+08
                          sta:  BG1_ADDR+$4000,y
:do04                     ldal  BG1YCache+06
                          sta   BG1_ADDR+$3000,y
:do03                     ldal  BG1YCache+04
                          sta   BG1_ADDR+$2000,y
:do02                     ldal  BG1YCache+02
                          sta   BG1_ADDR+$1000,y
:do01                     ldal  BG1YCache+00
                          sta:  BG1_ADDR+$0000,y
:none                     rts

; Apply the per-scanline shift from the BG1StartXMod164Tbl pointer. Save the relevant values to the
; direct page since the array could be in any bank.
;
; This does bounds checking to make sure the shift value remains in the valid range
;
; ]1 = source array offset
; ]2 = constant shift value
; ]3 = destination address
_BG1ShiftTemplate         mac
                          lda   ]1,y                          ; Load the value from the array
                          adc   ]2                            ; Add to the direct page shift_value
                          cmp   #165                          ; If below this value, we're good
                          bcc   *+6
                          sbc   #164
                          clc
                          adcl  BG1YTable+]1,x
                          sta   ]3+]1
                          <<<

AToX                      mac
                          tax
                          brl   ]1
                          <<<

ApplyBG1ModXToShift       mac
                          jmp   (agmxts_tbl,x)
agmxts_tbl                da    none
                          da    do01,do02,do03,do04
                          da    do05,do06,do07,do08
                          da    do09,do10,do11,do12
                          da    do13,do14,do15,do16
do16                      AToX  o16
do15                      AToX  o15
do14                      AToX  o14
do13                      AToX  o13
do12                      AToX  o12
do11                      AToX  o11
do10                      AToX  o10
do09                      AToX  o09
do08                      AToX  o08
do07                      AToX  o07
do06                      AToX  o06
do05                      AToX  o05
do04                      AToX  o04
do03                      AToX  o03
do02                      AToX  o02
do01                      AToX  o01

o16                       _BG1ShiftTemplate 30;]1;]2
o15                       _BG1ShiftTemplate 28;]1;]2
o14                       _BG1ShiftTemplate 26;]1;]2
o13                       _BG1ShiftTemplate 24;]1;]2
o12                       _BG1ShiftTemplate 22;]1;]2
o11                       _BG1ShiftTemplate 20;]1;]2
o10                       _BG1ShiftTemplate 18;]1;]2
o09                       _BG1ShiftTemplate 16;]1;]2
o08                       _BG1ShiftTemplate 14;]1;]2
o07                       _BG1ShiftTemplate 12;]1;]2
o06                       _BG1ShiftTemplate 10;]1;]2
o05                       _BG1ShiftTemplate 8;]1;]2
o04                       _BG1ShiftTemplate 6;]1;]2
o03                       _BG1ShiftTemplate 4;]1;]2
o02                       _BG1ShiftTemplate 2;]1;]2
o01                       _BG1ShiftTemplate 0;]1;]2
none                      <<<

; After the values are saved, the data bank can be repointed at the current code bank and the values copied in
; from the direct page
;
; ]1 = offset in temp buffer
; ]2 = address of temp buffer
; ]3 = 4k offset in code buffer
_BG1ShiftToCodeTemplate   mac
                          lda   ]2+]1
                          sta:  BG1_ADDR+]3,y
                          <<<

ApplyBG1ShiftToCode       mac
                          jmp   (abstc_tbl,x)
abstc_tbl                 da    none
                          da    do01,do02,do03,do04
                          da    do05,do06,do07,do08
                          da    do09,do10,do11,do12
                          da    do13,do14,do15,do16
do16                     _BG1ShiftToCodeTemplate 30;]1;$F000
do15                     _BG1ShiftToCodeTemplate 28;]1;$E000
do14                     _BG1ShiftToCodeTemplate 26;]1;$D000
do13                     _BG1ShiftToCodeTemplate 24;]1;$C000
do12                     _BG1ShiftToCodeTemplate 22;]1;$B000
do11                     _BG1ShiftToCodeTemplate 20;]1;$A000
do10                     _BG1ShiftToCodeTemplate 18;]1;$9000
do09                     _BG1ShiftToCodeTemplate 16;]1;$8000
do08                     _BG1ShiftToCodeTemplate 14;]1;$7000
do07                     _BG1ShiftToCodeTemplate 12;]1;$6000
do06                     _BG1ShiftToCodeTemplate 10;]1;$5000
do05                     _BG1ShiftToCodeTemplate 8;]1;$4000
do04                     _BG1ShiftToCodeTemplate 6;]1;$3000
do03                     _BG1ShiftToCodeTemplate 4;]1;$2000
do02                     _BG1ShiftToCodeTemplate 2;]1;$1000
do01                     _BG1ShiftToCodeTemplate 0;]1;$0000
none                     <<<