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>
This commit is contained in:
2026-07-23 19:38:00 +03:00
parent d1bc97c589
commit 95c22be9bd
46 changed files with 4125 additions and 133 deletions
Binary file not shown.
+721
View File
@@ -0,0 +1,721 @@
;-------------------------------------------------------------------------------
; 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
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.
+58
View File
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
+38
View File
@@ -0,0 +1,38 @@
Демка была написана как альтернатива аналогичной на evo-sdk (язык C) для zx-evo,
но написано на асме. При этом так же пока писал, разбирался в особенностях работы
графических режимов. Содержание архива:
balls.asm - исходник
dss.inc - различные константы
head.inc - заголовок для формирования exe файла
misc.inc - некоторые "прочие" процедурки.
math.inc - математика, причём тормозная (сдёрнутая из исходника либы для HTC)
make.bat - собиралка. Использование как make src_name.
sjasm.exe - компилятор. Этот меня устраивает.
balls.exe - основной exeшник. На экране 32 шарика.
balls64.exe - 64 шарика.
balls128.exe - 128 шариков.
balls225.exe - 225 шариков.
balls.ect - файл с палитрой для шариков. Хранится в формате 32бита. Выдернуто
из заголовка для bmp шариков.
balls.spr - собсвтенно файл с шариками (спрайты). Ранее это был обычный bmp.
bgspr.act - палитра для фоновой картинка. Так же 32бита выдернутые из bmp.
bgspr.spr - фоновая картинка, тоже бывшая bmp.
Спрайт шариков имеет разрешение 64*16 (т.е. 4 шарика в линию, каждый шарик
16*16), каждый шарик по 32 цвета, т.е. сама картнка с шариками 128 цветов.
Фоновая картинка имеет разрешение 320*256, 128 цветов.
Чтобы получить эти файлы я в фотошопе что нужно было вырезал, отмасштабировал,
"перецветовал" в 8бит на точку, 128 цветов. Шарики собирал по отдельности из
фоновой картинки (просто вырезал из оригинального файла "молекулы", масштабировал,
собирал в одну картинку и потом извращался с цветами. Потом выдернул палитру
через winhex для шариков и фона из их bmp файлов, а из самих bmp потом вырезал
весь заголовок, оставив только данные спрайтов.
Можно спокойно подсунуть свои спрайты фона и шариков.
В демке есть процедура переиндексирования цветов. Первым файлом загружается
фоновая картинка и палитра. Цвета в файле имеют индексы от 0 до 7fh.
Шарики загружаются уже после. Поскольку палитра 256 цветов, а первые 128 уже
заняты под фон, то после загрузки спрайта шариков я делаю переиндексацию. Просто
по всему размеру файла если цвет != 0xff, тогда цвет +=128.
за тормоза в математике сильно не пинать!!!
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

File diff suppressed because one or more lines are too long
+68
View File
@@ -0,0 +1,68 @@
;-------------------------
;dss functions defines
;file functions
fopen equ 11h
fclose equ 12h
fread equ 13h
fwrite equ 14h
move_fp equ 15h
fgetattr equ 16h
fgetdt equ 17h
fsetdt equ 18h
fcreate equ 0ah
fcreaten equ 0bh
chdir equ 1dh
curdir equ 1eh
;memory functions
setwin1 equ 39h
getmem equ 3dh
setmem equ 3fh
freemem equ 3eh
;keyb functions
waitkey equ 30h
scankey equ 31h
quit equ 41h
getarg equ 43h
;vmode functions
setvmode equ 50h
getvmode equ 51h
selvpage equ 54h
;screen and text functions
pchar equ 5bh
pchars equ 5ch
;other
getver equ 0
;end dss defines
;-------------------------
;hardware defines
port_y equ 89h ;port for Y coord
_320p equ 81h ;320 pixels mode
rgmod equ 0c9h
border equ 0feh
rgscr equ 0e9h
rgacc equ 0a9h
norm_scr equ 50h
;trans_scr equ 54h
trans_scr equ 00001000b
tmp_scr equ 00000100b
e_cache equ 0fbh
d_cache equ 7bh
sys_port3c equ 3ch
sys_port7c equ 7ch
cpu_w0 equ 82h ;cpu window 0 = addr 0000h
cpu_w1 equ 0a2h ;... 1 = 4000h
cpu_w2 equ 0c2h ;... 2 = 8000h
cpu_w3 equ 0e2h ;... 3 = 0c000h
;end hardware defines
;-------------------------
;characters
cr equ 0dh
lf equ 0ah
tab equ 9
space equ 20h
;------------------------
+20
View File
@@ -0,0 +1,20 @@
; .Z80
; ASEG
; org 100h
org 8100h-512
db "EXE"
db 0
dw 200h
dw 0
dw 0
dw 0
dw 0
dw 0
dw entry
dw entry
dw 0bfffh
ds 490
; .PHASE 8100h
+20
View File
@@ -0,0 +1,20 @@
@echo off
if "%1" == "" goto error
if EXIST %1.exe (
del %1.exe
)
sjasm.exe -L %1.asm %1.exe %1.lst
if errorlevel 1 goto ERR
echo Ok!
goto END
:ERR
del %1.exe
pause
echo ®è¨¡ª¨ ª®¬¯¨«ï樨...
goto END
:error
echo usage: make sourcefile
:END
+89
View File
@@ -0,0 +1,89 @@
;Input: H = Multiplier, E = Multiplicand, L = 0, D = 0
;Output: HL = Product
mul8_8: ld b,7
sla h ; optimised 1st iteration
jr nc,$+3
ld l,e
.loop: add hl,hl ; unroll 7 times
jr nc,$+3 ; ...
add hl,de ; ...
djnz .loop
ret
lmod: call ldiv
ex de,hl
ret
ldiv: xor a
ex af,af'
ex de,hl
jr dv1
adiv: ld a,h
xor d ;set sign flag for quotient
ld a,h ;get sign of dividend
ex af,af'
call negif
ex de,hl
call negif
dv1: ld b,1
ld a,h
or l
ret z
dv8: push hl
add hl,hl
jr c,dv2
ld a,d
cp h
jr c,dv2
jp nz,dv6
ld a,e
cp l
jr c,dv2
dv6: pop af
inc b
jp dv8
dv2: pop hl
ex de,hl
push hl
ld hl,0
ex (sp),hl
dv4: ld a,h
cp d
jr c,dv3
jp nz,dv5
ld a,l
cp e
jr c,dv3
dv5: sbc hl,de
dv3: ex (sp),hl
ccf
adc hl,hl
srl d
rr e
ex (sp),hl
djnz dv4
pop de
ex de,hl
ex af,af'
call m,negat
ex de,hl
or a ;test remainder sign bit
call m,negat
ex de,hl
ret
negif: bit 7,h
ret z
negat: ld b,h
ld c,l
ld hl,0
or a
sbc hl,bc
ret
+113
View File
@@ -0,0 +1,113 @@
; îáùàÿ ïðîöåäóðà âûõîäà.
; â A ïîìåñòèòü êîä âîçâðàòà.
; Åñëè áûëà îøèáêà, òî ëó÷øå -1 (255)
; Åñëè îøèáêè íåáûëî, òî 0.
quit0: pop ix
ld b,a
ld c,quit
rst 10h
jp $ ; çàãëóøêà
;-[]------------------------------------------------------------
; misc procedures and functions...
;---------------------------------------------------------------
open: ld a,1
ld c,fopen
rst 10h
ret
close: ld c,fclose
rst 10h
ret
read: ld c,fread
rst 10h
ret
;dir_ret: ld hl,cur_dir
; ld c,chdir
; rst 10h
; ret
gmem: ld c,getmem
ld b,1
rst 10h
ret
; ïðîöåäóðà ñîõðàíåíèÿ ñòðàíèöû â óêàçííîì îêíå.
; C = îêíî (ïîðò)
; HL = êóäà ñîõðàíÿòü.
save_pg: in a,(c)
ld (hl),a
ret
; ïðîöåäóðà âîññòàíîâëåíèÿ ñòðàíèöû â óêàçííîì îêíå.
; C = îêíî (ïîðò)
; HL = îò êóäà âîññòàíîâèòü.
restore_pg: ld a,(hl)
out (c),a
ret
; îáðàáîòêà îøèáêè îòêðûòèÿ ôàéëà
open_err:
ld hl,open_err_str
ld c,pchars
rst 10h
.err_file: ld hl,0
ld c,pchars
rst 10h
ld hl,crlf0
ld c,pchars
rst 10h
ld a,-1
jp quit0
; îáðàáîòêà îøèáêè ÷òåíèÿ ôàéëà
rd_err:
ld hl,read_err_str
ld c,pchars
rst 10h
.err_file: ld hl,0
ld c,pchars
rst 10h
ld hl,crlf0
ld c,pchars
rst 10h
ld a,-1
jp quit0
; îáðàáîòêà îøèáêè çàïðîñà ïàìÿòè
gmem_err: ld hl,gmem_err_str
ld c,pchars
rst 10h
ld a,-1
jp quit0
; îáðàáîòêà îøèáêè îòêðûòèÿ âèäåîðåæèìà
vm_err: ld hl,vm_err_str
ld c,pchars
rst 10h
jp quit0
IFDEF debug
debug_print: ld c,pchars
rst 10h
ret
ENDIF
; îáðàáîòêà îøèáêîê òîêåíîâ
;tok_err:
; ld hl,token_err_str
; ld c,pchars
; rst 10h
;.token_ptr: ld hl,0
; ld c,pchars
; rst 10h
; ld hl,crlf0
; ld c,pchars
; rst 10h
; ld a,-1
; jp quit0
Binary file not shown.