Files
Sprinter-SDCC/docs/samples/balls/balls.asm
T
snark13 95c22be9bd libbgi: скролл-примитивы + --w3 + отчёт раскладки памяти
Скролл региона video->video (неактивная страница -> активная, банк 0x50:
копия = скролл + heal цели):
- gfx_scroll_h / _bgi_scroll_rows_raw — горизонтальный, построчно без
  страйдов (~54Т/строку), DI/EI бандами по 16 строк, h=0=>256;
- gfx_scroll_v / _bgi_scroll_cols_raw — верт. И/ИЛИ гориз. за один проход
  без буфера (колонка = accel-burst LD A,A, STOP между read/write делает
  промежуточный OUT Port_Y безопасным), банды по 16 колонок;
- _gfx_addr_shadow_base (адрес неактивной страницы) + gfx_rect_t.
Пример examples/scroll.

check_banks.py + sprinter-cc: отчёт раскладки памяти для ЛЮБОЙ модели
(W1/W2 код/данные, остаток кучи/стека, W3 при --w3, банки при --bank),
не только при --bank.  Док docs/memory-management.md §10.

--w3 (резидентный код окна W3) + сопутствующее: crt0_banked W3_RESIDENT,
mkexe -W, tests/w3probe.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:38:00 +03:00

721 lines
10 KiB
NASM

;-------------------------------------------------------------------------------
; Balls mini-demo
; (c) Sayman 2015
;-------------------------------------------------------------------------------
; ïðîöåäóðà ìîäóëÿ ñîâñåì íå îïòèìàëüíà, âçÿòà èç èñõîäíèêà áèáëèîòåêè C.
;-------------------------------------------------------------------------------
tbuf_addr: equ 4000h
screen_addr: equ 0xc000
balls_pgn equ 1
bgspr_pgn equ 6
savescr_pgn equ 6
tbuf_pgn equ 1
MAX_BALLS equ 32 ; ïðè 96 øàðèêàõ ñòðóêòóðà balls_cfg áóäåò 576 áàéò
balls_pal_size equ 128
bgspr_pal_size equ 128
balls_struct:
.x equ 0 ; u16_t
.y equ 2 ; u8_t
.dx equ 3 ; i8_t
.dy equ 4 ; i8_t
.radius equ 5 ; u8_t
balls_struct_bkp:
.x equ 0 ; u16_t
.y equ 2 ; u8_t
include "dss.inc"
include "head.inc"
entry: push ix
call init
call read_bgspr
ld a,(pg_tbl.tbuf)
out (cpu_w1),a
ld a,(tmp_hndl)
call close
call read_bgpal
call read_balls_spr
call read_balls_pal
call vinit
call balls_reindex
call balls_init
call draw_bgspr
call CopySCR_1to2
ld a,0xc0
out (port_y),a
ld a,(pg_w3)
out (cpu_w3),a
call balls_main
sub a
jp quit0
include "misc.asm"
include "math.inc"
rand16 ld de,.seed ; Seed is usually 0
ld a,d
ld h,e
ld l,253
or a
sbc hl,de
sbc a,0
sbc hl,de
ld d,0
sbc a,d
ld e,a
sbc hl,de
jr nc,.rand
inc hl
.rand ld (rand16+1),hl
ret
.seed: dw 0
inc_pg1: ld a,(ix)
out (cpu_w1),a
inc ix
ret
inc_pg3: ld a,(ix)
out (cpu_w3),a
inc ix
ret
init: ld c,balls_pgn
ld hl,pg_tbl.balls
.loop0: push bc
push hl
call gmem
pop hl
pop bc
jp c,gmem_err
ld (hl),a
inc hl
dec c
jr nz,.loop0
ld c,bgspr_pgn
.loop1: push bc
push hl
call gmem
pop hl
pop bc
jp c,gmem_err
ld (hl),a
inc hl
dec c
jr nz,.loop1
ld c,savescr_pgn
.loop2: push bc
push hl
call gmem
pop hl
pop bc
jp c,gmem_err
ld (hl),a
inc hl
dec c
jr nz,.loop2
ld c,tbuf_pgn
.loop3: push bc
push hl
call gmem
pop hl
pop bc
jp c,gmem_err
ld (hl),a
inc hl
dec c
jr nz,.loop3
ex af,af
in a,(cpu_w1)
ld (pg_w1),a
in a,(cpu_w3)
ld (pg_w3),a
in a,(port_y)
ld (old_y),a
ex af,af
out (cpu_w1),a
ret
set_scr_w3: out (cpu_w3),a
ret
set_scr_w1: out (cpu_w1),a
ret
vinit: ld a,81h
ld bc,50h
rst 10h
call cls
call set_global_pal
call CopySCR_1to2
ld a,norm_scr
call set_scr_w3
ret
CopySCR_1to2: sub a
out (port_y), a
ld hl, 0xc000
ld de, 0xc140
ld bc, 320
ld d, d
ld a, 0 ; 256 bytes
ld a, a
; ldir
.loop: REPT 64
ldi
ENDM
jp pe,.loop
ld b, b
ld hl, 0xc3E0
ld de, 0xc3E4
; ld bc, 0004h
ld a, a
ldi
ldi
ldi
ldi
; ldir
ld b, b
ret
cls: ld hl,0xc3E0
ld de,0
ld d,d
ld a,0
ld b,b
ld b,4
.loop1: ld a,d
out (port_y),a
ld e,e
ld (hl),e
ld b,b
inc hl
djnz .loop1
ld hl,0xc000
ld de,0
ld bc,320
ld d,d
ld a,0
ld b,b
.loop2: ld a,d
out (port_y),a
ld e,e
ld (hl),e
ld b,b
inc hl
dec bc
ld a,b
or c
jr nz,.loop2
ret
set_global_pal: ld bc,0ffa4h
ld hl,pal
ld de,0
sub a
rst 8
ret
read_bgspr: ld hl,data_files.bgspr
push hl
call open
pop hl
ld (open_err.err_file+1),hl
jp c,open_err
ld (rd_err.err_file+1),hl
ld (tmp_hndl),a
ld ix,pg_tbl.bgspr
.loop: call inc_pg1
ld a,(tmp_hndl)
ld hl,tbuf_addr
ld de,16320
push ix
call read
pop ix
jp c,rd_err
or a
ret nz
jr .loop
read_bgpal: ld hl,data_files.bgpal
push hl
call open
pop hl
ld (open_err.err_file+1),hl
jp c,open_err
ld (rd_err.err_file+1),hl
ld (tmp_hndl),a
ld hl,pal
ld de,bgspr_pal_size*4
call read
jp c,rd_err
ld a,(tmp_hndl)
call close
ret
read_balls_spr: ld hl,data_files.balls
push hl
call open
pop hl
ld (open_err.err_file+1),hl
jp c,open_err
ld (rd_err.err_file+1),hl
ld (tmp_hndl),a
ld hl,balls_spr
ld de,1024
call read
jp c,rd_err
ld a,(tmp_hndl)
call close
ret
read_balls_pal: ld hl,data_files.balls_pal
push hl
call open
pop hl
ld (open_err.err_file+1),hl
jp c,open_err
ld (rd_err.err_file+1),hl
ld (tmp_hndl),a
ld hl,pal+bgspr_pal_size*4
ld de,balls_pal_size*4
call read
jp c,rd_err
ld a,(tmp_hndl)
call close
ret
balls_reindex: ld hl,balls_spr
ld c,128
ld de,1024
.loop0: ld a,(hl)
inc a
jr z,.loop1
dec a
add a,c
ld (hl),a
.loop1: inc hl
dec de
ld a,e
or d
jr nz,.loop0
ret
balls_init: ld hl,balls_cfg
ld de,balls_cfg+1
ld bc,MAX_BALLS*6
xor a
ld (hl),a
ldir
ld hl,balls_bkp
ld de,balls_bkp+1
ld bc,MAX_BALLS*3
xor a
ld (hl),a
ldir
ld iy,MAX_BALLS
ld ix,balls_cfg
.loop0: ld de,320-16 ; ðàçìåðû êàæäîãî øàðèêà 16íà16
push de
call rand16 ; áåð¸ì ñëó÷àéíóþ êîîðäèíàòó X
pop de
inc hl
push de
call lmod
pop de
ex de,hl
.next0: ld (ix+balls_struct.x),e
ld (ix+balls_struct.x+1),d
ld de,256-16
push de
call rand16
pop de
inc hl
push de
call lmod
pop de
ex de,hl
.next1: ld (ix+balls_struct.y),e
call rand16
ld a,l
and 1
jr nz,.next2
ld a,-1
.next2: ld (ix+balls_struct.dx),a
call rand16
ld a,l
and 1
jr nz,.next3
ld a,-1
.next3: ld (ix+balls_struct.dy),a
ld de,6
add ix,de
dec iy
ld a,iyl
or iyh
jr nz,.loop0
ret
draw_bgspr: ld ix,pg_tbl.bgspr
call inc_pg1
ld hl,tbuf_addr
ld c,51
ld a,0
.loop: ld de,screen_addr
out (port_y),a
ex af,af
di
ld d,d
ld a,0
ld l,l
ld a,(hl)
ld (de),a
ld b,b
inc h
inc d
ld d,d
ld a,64
ld l,l
ld a,(hl)
ld (de),a
ld b,b
ld a,64
add a,l
ld l,a
adc a,h
sub l
ld h,a
dec c
call z,nextpage
ex af,af
inc a
jr nz,.loop
ei
halt
di
ret
nextpage: call inc_pg1
ld hl,tbuf_addr
ld c,51
ret
balls_main:
.loop1: ld iy,MAX_BALLS
ld ix,balls_cfg
call save_coords
push ix
push iy
.loop0: ld e,(ix+balls_struct.x)
ld d,(ix+balls_struct.x+1)
ld hl,320-16
call check_x
ld c,(ix+balls_struct.y)
ld hl,256-16
call check_y
ld a,(ix+balls_struct.dx)
ld h,0
ld l,a
rlca
jr nc,.a1
dec h
.a1: rrca
add hl,de
ex de,hl
ld (ix+balls_struct.x),e
ld (ix+balls_struct.x+1),d
ld a,(ix+balls_struct.dy)
add a,c
ld (ix+balls_struct.y),a
ld de,6
add ix,de
dec iy
ld a,iyl
or iyh
jr nz,.loop0
pop iy
pop ix
ld a,norm_scr|trans_scr|tmp_scr
call set_scr_w3
.loop2: ld hl,balls_spr
ld a,iyl
and 3
ld e,(ix+balls_struct.x)
ld d,(ix+balls_struct.x+1)
ld c,(ix+balls_struct.y)
call draw_balls
ld de,6
add ix,de
dec iy
ld a,iyl
or iyh
jr nz,.loop2
ei
halt
di
in a,(rgmod)
and 1
xor 1
out (rgmod),a
ld a,norm_scr
call set_scr_w3
ld iy,MAX_BALLS
ld ix,balls_bkp
.loop3: ld e,(ix+balls_struct.x)
ld d,(ix+balls_struct.x+1)
ld c,(ix+balls_struct.y)
call restore_bg
ld de,3
add ix,de
dec iy
ld a,iyl
or iyh
jr nz,.loop3
.blah: call check_key
jr c,._ret_
jp .loop1
._ret_: ret
save_coords: push ix
push iy
ld hl,balls_bkp
.loop: ld e,(ix+balls_struct.x)
ld d,(ix+balls_struct.x+1)
ld c,(ix+balls_struct.y)
ld (hl),e
inc hl
ld (hl),d
inc hl
ld (hl),c
inc hl
ld de,6
add ix,de
dec iy
ld a,iyh
or iyl
jr nz,.loop
pop iy
pop ix
ret
restore_bg:
in a,(rgmod)
or a
ld a,0xc0
jr nz,.restore_to_0
ld a,0xc1
jr .restore_to_1
.restore_to_0: add a,d
ld d,a
ld h,d
ld l,e
jr .restore
.restore_to_1: add a,d
ld d,a
ld a,0x40
add a,e
ld e,a
adc a,d
sub e
ld d,a
ld h,d
ld l,e
.restore: ld a,c
out (port_y),a
ld b,16
di
.loop: ld d,d
ld a,16
ld l,l
ld a,(hl)
ld (de),a
ld b,b
in a,(port_y)
inc a
out (port_y),a
djnz .loop
ret
draw_balls: ld b,a
in a,(rgmod)
or a
ld a,0xc1
jr z,.draw_to_1 ; åñëè âêëþ÷¸í 0é ýêðàí, ðèñóåì íà 1é
ld a,0xc0 ; èíà÷å (1é) ðèñóåì â 0é
.draw_to_0: add a,d
ld d,a
jr .draw
.draw_to_1: add a,d
ld d,a
ld a,0x40
add a,e
ld e,a
adc a,d
sub e
ld d,a
.draw: ld a,b
add a,a
add a,a
add a,a
add a,a
add a,l
ld l,a
adc a,h
sub l
ld h,a ; íîìåð ñïðàéòà*256 = àäðåñ ñïðàéòà â êàðòèíêå
ld a,c
out (port_y),a
ld b,16
di
.loop:
ld d,d
ld a,16
ld l,l
ld a,(hl)
ld a,a
ld (de),a
ld b,b
ld a,c
out (port_y),a
ld a,l
add a,64
ld l,a
ld a,0
adc a,h
ld h,a
inc de
djnz .loop
ret
check_x: ld a,e
or d
jr z,.next0
sbc hl,de
jr z,.next1
jr c,.next1
ret
.next0: ld a,1
ld (ix+balls_struct.dx),a
ret
.next1: ld a,-1
ld (ix+balls_struct.dx),a
ret
check_y: ld a,c
or a
jr z,.next0
ld a,l
sub c
jr z,.next1
jr c,.next1
ret
.next0: ld a,1
ld (ix+balls_struct.dy),a
ret
.next1: ld a,-1
ld (ix+balls_struct.dy),a
ret
sync: ei
halt
di
ret
check_key: push hl
push de
push bc
push ix
push iy
ld c,scankey
rst 10h
pop iy
pop ix
pop bc
pop de
pop hl
xor 1bh ; êîä Esc...
ret nz
.esc: scf
ret
pg_tbl:
.balls: db 0
.bgspr: ds 6
.savescr: ds 6
.tbuf: db 0
pg_w0: db 0
pg_w1: db 0
pg_w2: db 0
pg_w3: db 0
old_y: db 0
data_files:
.balls: db "balls.spr",0
.balls_pal: db "balls.act",0
.bgspr: db "bgspr.spr",0
.bgpal: db "bgspr.act",0
tmp_hndl: db 0
open_err_str: db "Can't open file ",0
read_err_str: db "Failed to read file ",0
gmem_err_str: db "PANIC: Can not allocate memory!",cr,lf,0
vm_err_str: db "PANIC: Unable to set videomode!",cr,lf,0
crlf0: db " ",cr,lf,0
pal: equ ($/80h)*80h+80h
balls_spr: equ ((pal+1024)/80h)*80h+80h
balls_cfg: equ ((balls_spr+1024)/80h)*80h+80h
balls_bkp: equ (((balls_cfg)+6*MAX_BALLS)/80h)*80h+80h