From b29d344150f3150e9a355454e78fee5c165e90b3 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 13 Sep 2026 21:08:29 +0300 Subject: [PATCH] Fix raster transitions and analyzer page mapping --- README.md | 1 - _spg/ZIFI/zifi.spg | Bin 44544 -> 44544 bytes zifi.asm | 149 ++++++++++++++++++++++++++++----------------- 3 files changed, 94 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 314052c..b1cc81d 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,5 @@ AT+CIPSNTPTIME? — получить текущее врем **Заменил драйвер SD-карты.** Штатный `_sd/WDFCVBI2.COD` (закрытый бинарник без исходников, автор — "Hacker VBI") был заменён на собственный, открытый SD/FAT32-драйвер (`_sd/zc_sd_driver.asm` + `_sd/zc_sd_driver_body.asm`) — реализует те же ~15 функций CORE-таблицы, которые реально использует ZiFi. Заодно исправлена и порча имён папок на FAT32 (короткие имена 8.3 иногда совпадали с уже существующей записью в каталоге). Подробнее — `_sd/README.md`. -**Известная нерешённая мелочь:** курсор мыши (аппаратный спрайт TSU) обрывается по фиксированной строке экрана прямо над нижней панелью управления — похоже на границу, завязанную на тайминг переключения видеорежима или на аппаратный бордюр, а не на что-то, что двигается вместе с содержимым панели. Я не нашёл способ поправить это без риска сломать что-то ещё, оставил как есть. diff --git a/_spg/ZIFI/zifi.spg b/_spg/ZIFI/zifi.spg index ccd5da01f9fc7748762856113eb083e499a7e5ab..0ae74153482b50e2acc8d37713d8f9f2bc5f45e4 100644 GIT binary patch delta 6397 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 WNO2ze36AshLP$Ob2j@Np?))D%>u{a` diff --git a/zifi.asm b/zifi.asm index 89c921e..4e7ac01 100644 --- a/zifi.asm +++ b/zifi.asm @@ -10,6 +10,11 @@ Vid_page equ #e0 Sprite_page equ #f0 Mouse_pal_num equ #f0 +; BORDER is sampled immediately by the FPGA, unlike VCONFIG/VPAGE which are +; latched at the following line start. Keep one palette index for the whole +; frame: #00 is black in both the 256c palette and text GPAL (#F0). +GFX_BORDER equ #00 + sd_driver_page equ #0f cursor_adr equ #c000 cursor_page equ #10 @@ -52,15 +57,30 @@ start // call write_rtc ld sp,#bfff call all_init - call set_256c_mode + call set_256c_mode + ; TSCONFIG (sprite engine) and PALSEL set EXACTLY ONCE, here -- + ; see set_256c_mode's comment. #3f = GPAL=15/T0PAL=3/T1PAL=0; + ; confirmed by the sibling fork's own author: writing PALSEL + ; mid-frame (from the raster interrupt handlers, every mode + ; switch) is the actual root cause of the cursor-cutoff bug. + ld bc,TSCONFIG + ld a,TSU_SEN + out (c),a + ld bc,PALSEL + ld a,#3f + out (c),a call sd_init ei ld b,60 call wait - ld hl,int_main - ld (#beff),hl - call gfx_init + ; Do not expose the raster handler before Text_page has been cleared: + ; otherwise a frame can display the loader's leftover RAM contents. + di + call gfx_init call set_text_colors + ld hl,int_main + ld (#beff),hl + ei call load_ini IF cable_zifi call psb_start @@ -106,14 +126,12 @@ do_after_load ld a,0 main_ex call wait_frame - ld a,(music_sw+1) ; music-playing UI bits (now-playing blink, volume-bar - or a ; analyzer) done here in the foreground, frame-synced, - jr z,skip_music_ui ; instead of inside the raster-critical interrupt chain - call show_now_play_link + ; The analyzer runs outside the raster IRQ: its variable-height bars are + ; too long for the line-287 handler. analyzer_active makes pt_play + ; restore PAGE3 back to this routine if an IRQ occurs meanwhile. ld a,(save_mode+1) or a call nz,music_analizator -skip_music_ui do_start_music ld a,1 or a @@ -2217,7 +2235,9 @@ int_gfx_view push af,hl,de,bc,ix ret int_main push af,hl,de,bc,ix,iy - ld a,#34 + ; Line 0 is in vertical blanking. Restore the single black border here, + ; never during the text/graphics transition lines. + ld a,GFX_BORDER ld bc,BORDER out (c),a exx @@ -2236,24 +2256,37 @@ frame ld a,0 inc a ld (frame+1),a + ; Arm the text-mode raster chain before potentially long mouse/list + ; processing. A CPU screen copy can take longer than the 84 raster lines + ; before the text area; delaying this setup exposes the 256c page for one + ; frame. + ld hl,56+4*8-4 + ld bc,VSINTL + out (c),l + ld b,high VSINTH + out (c),h + ld hl,int_text_cor + ld (#beff),hl + ei + save_mode ld a,1 or a - jr z,int_ex2 + jr z,int_ex_regs mouse_sw ld a,1 or a call nz,mouse_proc link_highlight ld a,0 or a call nz,link_highlight_view + jr int_ex_regs -int_ex2 ld hl,56+4*8-4 - ld de,int_text_cor int_ex ld bc,VSINTL out (c),l ld b,high VSINTH out (c),h ex de,hl ld (#beff),hl +int_ex_regs exa pop af exa @@ -2285,32 +2318,27 @@ int_text_cor_ex ld a,0 pop af ret -int_text_on push af,hl,de,bc,ix,iy -txt_border ld a,#f0 - ld bc,BORDER +int_text_on push af,hl,de,bc + ; VCONFIG, VPAGE and GYOFFS are latched on the next line start; + ; program them first. BORDER is intentionally not touched here. + ld a,(click_offset+1) + ld bc,GYOFFSL out (c),a + ld b,high VCONFIG + ld a,VID_TEXT+VID_320X240 + out (c),a + ld b,high VPAGE + ld a,Text_page + out (c),a + ld a,#3f + ld (int_text_cor_ex+1),a + push ix,iy exx push hl,de,bc exx exa push af exa - ld a,(click_offset+1) - ld b,high GYOFFSL - out (c),a - ld b,high VCONFIG - ld a,VID_TEXT+VID_320X240 - out (c),a -; ld b,high TSCONFIG -; ld a,TSU_SEN -; out (c),a - ld b,high VPAGE - ld a,Text_page - out (c),a - ld b,high PALSEL - ld a,#3f - out (c),a - ld (int_text_cor_ex+1),a ld hl,47+240-1-2 ld de,int_text_ofcor jp int_ex @@ -2336,22 +2364,22 @@ int_text_ofcor_ex ld a,0 pop af ret -int_text_off push af,hl,de,bc,ix,iy - ld a,#34 - ld bc,BORDER - out (c),a - exx - push hl,de,bc - exx - exa - push af - exa +int_text_off push af,hl,de,bc + ; The mode registers are latched on the next line start. BORDER is + ; deliberately unchanged here: it must stay constant over the frame. call set_256c_mode ld hl,47+240 ; was 47+240-1 - bottom panel sat a couple pixels too low ld b,high GYOFFSL out (c),l inc b out (c),h + push ix,iy + exx + push hl,de,bc + exx + exa + push af + exa music_sw ld a,0 or a call nz,pt_play @@ -2359,7 +2387,6 @@ music_sw ld a,0 ld a,(save_mode+1) or a jr z,int_ex3 - enter_search_sw ld a,0 or a call nz,enter_search @@ -2372,8 +2399,14 @@ int_ex3 ld hl,0 pt_play call set_music_pages_lite call music_player_play - jp restore_music_pages_lite ; the link-blink/autoplay tail (show_now_play_link) - ; is now called separately from the main loop, not from here + jp show_now_play_link +pt_play_restore_pages + call restore_music_pages_lite + ld a,(analyzer_active) + or a + ret z + ld a,Vid_page+9 + jp set_page3_lite show_now_play_link ld a,0 or a @@ -2432,7 +2465,7 @@ autoplay_num ld a,0 call parse_url ld a,1 ld (load_sw+1),a -pt_play_ex jp restore_music_pages_lite ; autoplay may have re-pointed page1 itself above - restore again +pt_play_ex jp pt_play_restore_pages ; autoplay may have re-pointed page1 itself above - restore again /* SETUP DB 0 ;set bit0, if you want to play without looping ;(optional); @@ -2456,12 +2489,14 @@ set_256c_mode ld b,high VPAGE ld a,Vid_page out (c),a - ld b,high PALSEL - xor a - out (c),a - ld b,high TSCONFIG - ld a,TSU_SEN - out (c),a + ; TSCONFIG and PALSEL NOT touched here -- both written exactly + ; once at program start instead (see "start"). This procedure + ; runs from the raster interrupt handlers (int_main, + ; int_text_off) every single frame; the sibling fork's own + ; author confirmed writing PALSEL mid-frame is the real cause + ; of the cursor-cutoff bug (TSCONFIG has the same hazard: + ; re-asserting the sprite engine mid-scanline blanks the + ; cursor sprite on that line). ret link_highlight_view @@ -2485,14 +2520,15 @@ link_highlight_view jp restore_page3 music_analizator + ld a,1 + ld (analyzer_active),a ld a,Vid_page+9 call set_page3_lite ld hl,0 ld (analizator_screen_adr),hl ld hl,clr_analizator - call set_ports ; clear video mem - wait for the DMA fill to finish - ; before the CPU draws bars into the same area below + call set_ports ; wait for the fill before drawing over it ld hl,ay_volume push hl @@ -2535,8 +2571,11 @@ ma2 ld (hl),a inc h dec c jr nz,ma3 + xor a + ld (analyzer_active),a jp restore_page3 ay_volume ds 3 +analyzer_active db 0 @@ -3420,7 +3459,7 @@ gfx_init ld hl,cursor_copy ret init_ts db #20,6 - db high BORDER,#f0 ; border + db high BORDER,GFX_BORDER ; border db high SGPAGE, Sprite_page db high CacheConfig,#0c ; cache for #8000 - #c000