+ A16
+ stz nframe
+mainloop:
+ lda nframe
+ lsr
+ lsr
+ sta anim
+ inc nframe
+ A8
+
+ stz ncol
+@cloop:
+ lda anim
+ clc
+ adc ncol
+ asl
+ tax
+ lda sintab,x
+ sec
+ sbc #128
+ asr
+ asr
+ asr
+
+ ldx ncol
+ bne @per_tile_offs
+ ; global scroll for the first column
+ sta vscroll
+ bra @end
+
+@per_tile_offs:
+ pha
+ lda ncol
+ asl
+ tax ; x = ncol << 1
+ pla
+ sta shadow_voffs,x
+ inx
+ lda #$20
+ sta shadow_voffs,x
+@end:
+ inc ncol
+ lda ncol
+ and #$1f
+ bne @cloop
+
+ ; wait for vblank, and DMA the table to vmem
+ wait_vblank
+ fblank 1
+ lda vscroll
+ sta REG_BG1VOFS
+ stz REG_BG1VOFS
+ lda #(vmem_voffs_offs & $ff)
+ sta REG_VMADDL
+ lda #(vmem_voffs_offs >> 8)
+ sta REG_VMADDH
+ setreg REG_MDMAEN, 0
+ setreg REG_DMAP(0), $01 ; A->B words at X,X+1, A inc
+ setreg REG_BBAD(0), REG_VMDATAL & $ff ; write to VMDATAL,VMDATAH
+ setreg REG_A1TL(0), shadow_voffs
+ setreg REG_A1TH(0), 0
+ setreg REG_A1B(0), 0
+ setreg REG_DASL(0), 64
+ setreg REG_DASH(0), 0
+ setreg REG_DASB(0), 0
+ setreg REG_MDMAEN, 1 ; enable DMA channel 0
+ fblank 0
+ A16
+ jmp mainloop
+
+ ; copy_vmem(vmem_offset, src, num_bytes)