Back in 2010 I tried to implement double buffering on a pcw, I came up with this solution:
;; double buffer on pcw
org &8000
nolist
di
ld a,&c3
ld (&0038),a
ld hl,int1
ld (&0039),hl
ei
;; page 0,1 is screen 1 (9k free in page 1)
;; page 2,3 is screen 2 (9k free in page 3)
;; page 2 temporarily used to setup roller tables
ld a,roller_base1
ld (roller_base),a
ld a,screen_ram_base2
ld (screen_ram_base),a
call screen_set
;; table 1 at &0000 in block 4
;; table 2 at &0400 in block 4
;; 15872 bytes free here
;; 23040 bytes per screen with 256 lines
;; 46080 bytes for all screens
roller_table_page equ 1
;; 512 multiple within offset
roller_table_offs1 equ 30
roller_table_offs2 equ 31
;; roller table in page 4
roller_base1 equ (roller_table_page*32)+roller_table_offs1
roller_base2 equ (roller_table_page*32)+roller_table_offs2
roller_swap equ roller_base1 xor roller_base2
screen_ram_base1 equ 0
screen_ram_base2 equ 2
screen_ram_base_swap equ screen_ram_base1 xor screen_ram_base2
ld a,roller_table_page or &80
out (&f2),a
;; roller ram 1
;; page 0/1
ld ix,&8000+(roller_table_offs1*512)
ld hl,&0000+(screen_ram_base1*8192)
ld b,0
rr1:
ld (ix+0),l
ld (ix+1),h
inc ix
inc ix
call scr_next_line_normal_rr
djnz rr1
;; roller ram 2
;;
;; page 2/3
ld ix,&8000+(roller_table_offs2*512)
ld hl,&0000+(screen_ram_base2*8192)
ld b,0
rr2:
ld (ix+0),l
ld (ix+1),h
inc ix
inc ix
call scr_next_line_normal_rr
djnz rr2
int1:
push af
in a,(&f8)
bit 6,a
jr z,int1_nv
call screen_set
int1_nv
pop af
ei
reti
screen_set:
;; swap base
ld a,(roller_base)
xor roller_swap
ld (roller_base),a
out (&f5),a
;; toggle screen ram base
ld a,(screen_ram_base)
xor screen_ram_base_swap
ld (screen_ram_base),a
or &80
out (&f0),a
inc a
out (&f1),a
ret
roller_base:
defb 0
screen_ram_base
defb 0
line_length_bytes equ 720
line_length_bytes_minus_8 equ line_length_bytes-8
line_length_bytes_rr equ 720/16
line_length_bytes_minus_8_rr equ line_length_bytes_rr-8
;; this gets next line based on byte address
;; ok for sprites not ok for roller ram
;;
;; 0 8 16 24 32... 89
;; 1 9
;; 2
;; 7
;; 720
scr_next_line_normal:
inc l
ld a,l
and &7
ret nz
ld a,l
add a,line_length_bytes_minus_8 AND 255
ld l,a
ld a,h
adc a,line_length_bytes_minus_8/256
ld h,a
ret
scr_next_line_normal_rr:
inc l
ld a,l
and &7
ret nz
ld a,l
add a,line_length_bytes_minus_8_rr AND 255
ld l,a
ld a,h
adc a,line_length_bytes_minus_8_rr
ld h,a
ret
I'm not sure the code builds.
I setup 2 "roller ram display lists" which I switched.