Unify OPL4 loading and fix progress page corruption

This commit is contained in:
2026-10-04 22:09:06 +03:00
parent bafb2f369c
commit f28caf5cd0
6 changed files with 242 additions and 335 deletions
+82 -1
View File
@@ -15,6 +15,20 @@ OPL_WAVE_DAT EQU #7F
PORT_SYSCONF EQU #20AF ; System Config (turbo bits [1:0]), see isr.s
TURBO_14MHZ EQU #02
; ── Блок параметров прогресс-бара ───────────────────────────────────
; Основная память плагина (Win2) на время работы загрузчика отключена —
; здесь стоит страница 5, — поэтому ifl_pb_* прочитать неоткуда. main.c
; кладёт нужное сюда ДО вызова, замапив страницу 5 в Win3 (адреса ниже
; фиксированы намеренно: #9802..#9806, их знает load_large_opl4()).
; Точка входа остаётся #9800, поэтому первым стоит перепрыг блока.
JR opl4_large_entry ; #9800
pb_text_pg: DB 0 ; #9802 физ. страница текстового экрана
pb_ptr: DW 0 ; #9803 текущая ячейка атрибутов (окно-отн.)
pb_green: DB 0 ; #9805 цвет закрашенной части
pb_step: DB 0 ; #9806 прибавка к аккумулятору за страницу
pb_left: DB 0 ; #9807 сколько ячеек ещё можно закрасить
pb_acc: DB 0 ; #9808 аккумулятор Брезенхэма (шкала — 64)
; Return: A bit 0..6 = compacted 16K page count (0 = reject),
; A bit 7 = ROM-image flag,
; H = first VPL page for the unread tail,
@@ -502,6 +516,17 @@ compact_and_patch:
ld a,(dst_page)
inc a
ld (dst_page),a
; Дальше копировать нечего, как только приёмник добрал до
; result_pages — это весь сжатый поток вместе с GD3. Без этой
; проверки цикл всегда шёл до 64-й страницы и для небольшого
; файла перемалывал сотни килобайт мусора за концом данных.
; (Для большого файла не срабатывает: там исходные страницы
; кончатся раньше, хвост дочитывается уже после возврата.)
push hl
ld hl,result_pages
cp (hl)
pop hl
jr nc,.copy_done
add a,#20
ld bc,PORT_W0
out (c),a
@@ -514,6 +539,10 @@ compact_and_patch:
ld (copy_src_page),a
cp 64
jr z,.copy_done
push de
call pb_tick ; фаза сжатия: продолжаем ту же шкалу
pop de
ld a,(copy_src_page)
add a,#20
ld bc,PORT_W3
out (c),a
@@ -596,7 +625,7 @@ next_src_page:
call map_vpl
ld hl,#C000
ld (src_ptr),hl
ret
jp pb_tick ; фаза заливки: одна страница -> шаг бара
len_is_zero:
ld hl,block_len
@@ -639,6 +668,58 @@ sub_len_bc:
ld (block_len+2),hl
ret
; ── Прогресс-бар ────────────────────────────────────────────────────
; Обе фазы загрузчика идут по страницам мегабуфера монотонно 0 -> 64:
; заливка двигает src_page от 0 до конца блоков, копирование продолжает
; с того же места до 64. Поэтому шкала фиксированная (64), и хватает
; одного счётчика Брезенхэма без умножения и деления.
; Вызывается из next_src_page и из цикла копирования; регистры не портит.
pb_tick:
push af
push bc
push hl
ld a,(pb_step)
ld hl,pb_acc
add a,(hl)
ld (hl),a
.spill: cp 64
jr c,.done
sub 64
ld (pb_acc),a
ld a,(pb_left)
or a
jr z,.done ; бар уже закрашен до конца
call pb_paint
ld a,(pb_acc)
jr .spill
.done: pop hl
pop bc
pop af
ret
; Закрасить одну ячейку. Текстовый экран временно подставляем в Win0.
; PORT_W0 — write-only на реальном TSConf (и не обязан возвращать ранее
; записанное значение в эмуляторе), поэтому восстанавливать страницу через
; IN нельзя. Номер приёмника нам и так известен: #20 + dst_page. Во время
; заливки dst_page=0 и Win0 не используется, а во время копирования это
; всегда текущая страница назначения.
pb_paint:
ld bc,PORT_W0
ld a,(pb_text_pg)
out (c),a
ld hl,(pb_ptr)
ld a,(pb_green)
ld (hl),a ; Win0 начинается с #0000 — смещение и есть адрес
inc hl
ld (pb_ptr),hl
ld hl,pb_left
dec (hl)
ld a,(dst_page)
add a,#20
ld bc,PORT_W0
out (c),a
ret
chip_wait:
in a,(OPL_STAT)
rrca