device zxspectrum128
;; temp pages:
splash_gfx_page equ #20
Gfx_vid_page equ #c0
menu_gfx_page equ #d0
highlight_menu_page equ #d1
Text_page equ #d8
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
music_players_page equ 3
music_page equ #1d ; 2 pages for music
list_ram_page equ #1f
download_page equ #20 ; allocate #28 pages for 640rb TRD
get_buffer equ #4000
window_height equ #0d
window_start_Yl equ #0100
window_start_Y equ high window_start_Yl
bigbuff equ #c000
download_sites equ 1
gfx_sites equ 2
music_sites equ 3
press_sites equ 4
highlight_size equ 1408
search_textpage_adr equ #0108
do_nothing equ 0
view_downloaded_list equ 1
view_text equ 2
save_file equ 3
play_music equ 4
view_gfx equ 5
start_paging_page equ 1
analizator_screen_adr equ #c2e0-4
progress_bar_screen_adr equ #0012
cable_zifi=0 ; 1 - Cable version, 0 - wifi version
org #8000
start
// call write_rtc
ld sp,#bfff
call all_init
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
; 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
ELSE
call init_zifi
ENDIF
call set_Textpage ; set_download_dir leaves PAGE0 on the SD driver page, not Text_page
ld hl,zifi_ready_msg
ld b,1
call zifi_echo
ld a,1
ld (zifi_ready),a ; enable menu tabs only after all initialization above
ld a,(mouse_button)
cpl
and #f0
ld (wheel_old+1),a
main
sites_sw ld a,0
or a
call nz,sites_list ; показать список сайтов для раздела
load_sw ld a,0
or a
jp z,main_ex
call modem_load_file
ld a,(do_after_load+1)
cp save_file
jr c,do_after_load
call create_filename
do_after_load ld a,0
cp save_file
jr c,1f
push af
call save_downloaded_file
pop af
1 cp view_downloaded_list
call z,create_link_list
cp view_text
call z,text_view
cp play_music
call z,music_loaded
cp view_gfx
call z,view_image
main_ex call wait_frame
; 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
do_start_music ld a,1
or a
call z,music_init
; off music before loading new music file
do_init_music ld a,0
or a
jr z,main
call music_init
xor a
ld (music_sw+1),a
ld (is_music_play+1),a
ld (do_init_music+1),a
jp main
wifi_connected db 'Connected succefully',0,0
wifi_try_connect db #0d,#0a,'Try connect to Access point',0,0
zifi_ready_msg db 'ZiFi is ready.',0,0
create_filename ; and check extension for scl scr sxg others
ld hl,modem_command+5 ; without GET
ld a,#0d
1 cpi
jr nz,1b ; HTTP/1.0#0d
ld bc,11+2
sbc hl,bc
1 ld (ix+thread.file_ext),hl ;find file extension
dec hl
1 ld a,(hl) ; check \ / : * ? " < > |
cp "\\"
jr z,1f
cp "/"
jr z,1f
cp ":"
jr z,1f
cp "*"
jr z,1f
cp "?"
jr z,1f
dec hl
jr 1b
1
inc hl
ld de,FILE_NAME ; file_name create
ld b,48 ; FILE_NAME is exactly 48 bytes - never write past it
2 ld a,(hl)
cp ' '
jr z,1f
ld (de),a
inc hl
inc de
djnz 2b ; ran out of room - stop here and null-terminate below
1
xor a
ld (de),a
ld a,(ix+thread.page) ; check unzip extension
call set_page1
ld hl,(ix+thread.adress)
ld a,"."
cp (hl)
ret nz
inc hl
1 dec de
ld a,(de)
cp '.'
jr nz,1b
inc de
ld b,3
1 ld a,(hl)
ld (de),a
inc hl
inc de
djnz 1b
xor a
ld (de),a
ld (ix+thread.adress),hl
; all lenght - 4bytes of extension
ld a,(ix+thread.full_len_high) ; a - high 16bit lenght
ld hl,(ix+thread.full_len) ; hl - low 16bit lenght
ld de,4
or a
sbc hl,de
sbc a,0
ld (ix+thread.full_len_high),a ; a - high 16bit lenght
ld (ix+thread.full_len),hl ; hl - low 16bit lenght
ret
/*
Address Mode Name Description
0x00EF..0xBFEF R DR Data register. Get byte from input FIFO. Input FIFO must not be empty (IFR > 0).
0x00EF..0xBFEF W DR Data register. Put byte into output FIFO. Output FIFO must not be full (OFR > 0).
Address Mode Name Description
0xC0EF R IFR Input FIFO Used Register. 0 - input FIFO is empty, 255 - input FIFO is full.
0xC1EF R OFR Output FIFO Free Register. 0 - output FIFO is full, 255 - output FIFO is empty.
Address Mode Name Description
0xC7EF W CR Command register. Command set depends on API mode selected.
*/
modem_load_file
xor a
ld (pause_music+1),a
ld l,a
ld h,a
ld ix,read_threads
ld (ix+thread.full_len),hl
ld (ix+thread.full_len_high),a
ld a,(do_after_load+1)
cp play_music
jr nz,1f
ld a,(is_music_play+1)
or a
jr z,1f
call set_music_pages
call music_player_mute
call restore_music_pages
xor a
ld (music_sw+1),a
ld (is_music_play+1),a
ld (do_init_music+1),a
1
; show link
; ld hl,cmd_conn2site_adr
; ld de,#1e00 ; show link
; call show_line_get_buffer
; ld hl,modem_command
; ld de,#1000 ; show link
; call show_line_get_buffer
load_ram_page ld a,0
ld (clr_load_mem1+1),a
ld (clr_load_mem2+1),a
call set_page3
call off_int_dma
ld hl,0
ld (#c000),hl
ld hl,clr_load_mem
call set_ports
ld de,download_icon
call set_icon
ld hl,cancel_icon_copy
call set_ports
call on_int_dma
ld hl,progress_bar_screen_adr-1
ld (progress_bar+1),hl
ld b,4
call view_progress_bar
; добавляем строку поиска первой и устанавливаем адрес загрузки после неё
ld hl,#0000 ; main download adress
ld a,(do_after_load+1)
cp view_downloaded_list
jr nz,1f
ld a,download_page
call set_page0_lite
ld de,0
ld bc,list_search_db_end-list_search_db
ld hl,list_search_db
ldir
ex de,hl ; download adress for lists. after "Search:"
1 ld (zipd_adr+1),hl
; snapshot load_ram_page NOW, before the (possibly multi-second)
; network receive below -- see saved_thread_page's own comment for why
; re-reading load_ram_page AFTER the call is wrong.
ld a,(load_ram_page+1)
ld (saved_thread_page),a
IF cable_zifi
ld a,(load_ram_page+1)
ld hl,modem_command
call psb_get
ELSE
call zifi_get
ENDIF
; bc: hl - lenght of readed data
ld ix,read_threads
ld a,c
ld (ix+thread.full_len_high),a ; bc - high 16bit lenght
ld (ix+thread.full_len),hl ; hl - low 16bit lenght
or h
or l
jr nz,1f
; ld a,do_nothing
ld (do_after_load+1),a ; do NOTHING
1 xor a
ld (ix+thread.num),a
ld a,(saved_thread_page)
ld (ix+thread.page),a
call set_page1
ld hl,status_copy ; clear statusbar gfx
call set_ports
xor a
ld (load_sw+1),a
/* IF !cable_zifi */
ld hl,get_buffer
ld (ix+thread.adress),hl ; Wifi adress without headers
/*
ELSE
call find_0d0a ; Fined header end and skip for Cable ver
ld (ix+thread.adress),hl
ld de,get_buffer
or a
sbc hl,de
ex de,hl
ld hl,(ix+thread.full_len)
sbc hl,de
ld (ix+thread.full_len),hl ; hl - low 16bit lenght
ENDIF
*/
ld a,(do_after_load+1)
cp view_downloaded_list
ret nz
call off_int_dma
ld hl,link_page_copy ; copy donwloaded list to list_page
call set_ports
jp on_int_dma
zifi_get call wait_frame
ld a,dl_timeout_quanta ; fresh inactivity budget for this connection attempt
ld (dl_timeout_left),a
ld a,(load_ram_page+1)
ld (zipd_page+1),a
call set_page0
inc a
call set_page1
ld hl,0
ld (readed_len_low+1),hl
ld hl,cmd_conn2site ; AT+CIPSTART - connect to site
call zifi_send_raw ; response is polled below; do not enter fifo_inir's hidden wait
ld de,str_error
call buffer_cmp
jr nz,zg_ok
ld hl,cmd_cipclose
call zifi_send_raw
1 ld de,str_ok
call buffer_cmp
jr z,zifi_get
call poll_input_fifo
call wait_frame
jr 1b
zg_ok ld b,250 ; up to ~5s for a TLS connect reply, without a hidden FIFO wait
zg_ok_wait ld de,str_ok
call buffer_cmp
jr z,zg_ok_done
push bc
call poll_input_fifo
call wait_frame
pop bc
djnz zg_ok_wait
jr zifi_get ; still no OK - start the whole connection attempt over
zg_ok_done
1 ld hl,cmd_cipsend ; AT+CIPSEND=,
call zifi_send_raw
2 call poll_input_fifo
ld de,str_ok
call buffer_cmp
jr z,1f
call wait_frame
jr 2b
1 ld a,(hl)
inc hl
cp #ff
jr z,2b
cp ">"
jr nz,1b
; send http request
ld hl,modem_command
call zifi_send_raw
1
call zifi_getchar
cp "O"
jr nz,1b
call zifi_getchar
cp "K"
jr nz,1b
// receive header
first_ipd
call reread_ipd
2
call read_fifo_char
dec hl
cp #0d
jr nz,2b
call read_fifo_char
dec hl
cp #0a
jr nz,2b
call read_fifo_char
dec hl
cp #0d
jr nz,2b
call read_fifo_char
dec hl
cp #0a
jr nz,2b
// header skipped
ld a,h
or l
jr z,read_all_ipds
ld (zipd_full_len+1),hl
jr zipd_adr
// receive data
read_all_ipds call reread_ipd
zipd_adr ld hl,#0000
zipd_full_len ld de,0 ; ipd len
p231 ld bc,zifi_input_fifo_status
1 in a,(c)
or a ; 0 - input FIFO is empty,
jr z,1b
p232 cp 0xbf ;
jr c,p233 ;
ld a,0xbf ; д
p233 ld c,a ; о
ld a,d ; л
or a ; г
jr nz,p234 ; о
ld a,e ;
cp c ; з
jr nc,p234 ; а
ld c,e ; п
p234 ex de,hl ; р
xor a ; я
ld b,a ; г
sbc hl,bc ; а
ex de,hl ; е
ld b,c ; м
ld c,0xef ;
inir ; и быстро едем
ld a,d
or e
jr nz,p231
ld a,h
cp #40
jr c,1f
zipd_page ld a,0
inc a
ld (zipd_page+1),a
call set_page0
inc a
call set_page1
ld a,h
sub #40
ld h,a
1 ld (zipd_adr+1),hl
ld hl,(zipd_full_len+1)
ld b,h
readed_len_low ld de,0
add hl,de
ld (readed_len_low+1),hl
jr nc,1f
readed_len_high ld a,0
inc a
ld (readed_len_high+1),a
1
call view_progress_bar
jp read_all_ipds
read_fifo_char ld bc,zifi_input_fifo_status ; ждём прихода данных в фифо
3 in a,(c)
jr z,3b ; 0 - input FIFO is empty,
ld b,0
in a,(c)
ret
reread_ipd ;ld a,3
; out (#fe),a
ld e,#ff
ld hl,output_buff
call rdipd
; xor a
; out (#fe),a
ld de,CLOSED
call buffer_cmp
; or a ; CLOSED, exit
jp z,zifi_read_ipd_ex
ld de,str_ipd
call buffer_cmp
; cp low output_buff+#bf
jr nz,reread_ipd
ex de,hl
call count_ipd_lenght ; in HL - lenght of ipd packet
ld (zipd_full_len+1),hl
ret
zifi_read_ipd_ex
pop af
ld a,(readed_len_high+1)
ld c,a
ld hl,(readed_len_low+1)
ret
rdipd: call zifi_getchar
jr z,rdipd
ld (hl),a
inc hl
cp ':'
ret z
cp #0a
ret z
jr rdipd
zifi_getchar:
call zifi_input_fifo_check
or a
jr z,zifi_getchar
; ld bc,0xc0ef
; in a,(c)
; jr z,zifi_getchar
ld b,0
in a,(c)
dec b
ret
wifi_cancel_download_ex
ld sp,#bfff
xor a
ld (load_sw+1),a
ld (wifi_cancel_download+1),a
ld hl,status_copy ; clear statusbar gfx
call set_ports
jp main
; same hard unwind as above, but leaves load_sw alone - timeout_next_track
; already set it to 1 so main picks up and starts loading the next track
dl_timeout_advance_ex
ld sp,#bfff
xor a
ld (wifi_cancel_download+1),a
ld hl,status_copy ; clear statusbar gfx
call set_ports
jp main
; same hard unwind again, but re-arms load_sw for the SAME target (parse_url
; already built the request - just resend it) instead of cancelling/skipping
dl_timeout_retry_ex
ld sp,#bfff
xor a
ld (wifi_cancel_download+1),a
ld a,1
ld (load_sw+1),a
ld hl,status_copy ; clear statusbar gfx
call set_ports
jp main
dl_timeout_quanta equ 2 ; ~5s per quantum (256 frames @ 50Hz) - 2 quanta = ~10s of silence
dl_timeout_left db 0
dl_retries_max equ 3 ; retry the same request this many times before giving up on it
dl_retries_left db dl_retries_max
music_skip_chain_max equ 8 ; give up after this many consecutive dead tracks
music_skip_chain_left db music_skip_chain_max
; called when a download times out while loading a music track - advances
; autoplay_num and starts loading the next track instead of just cancelling
timeout_next_track
ld a,(sum_list_lines+1)
dec a
ld c,a
ld a,(autoplay_num+1)
inc a
cp c
jr c,1f
ld a,1
1 ld (autoplay_num+1),a
call calc_link_num
ld a,list_ram_page
call set_page1
ld h,(ix+4)
ld l,(ix+3)
call parse_url
ld a,1
ld (load_sw+1),a
ret
count_ipd_lenght
ld hl,0 ; count lenght
; ld de,strbuff+7
cil1 ld a,(de)
inc de
cp ':'
ret z
sub 0x30
ld c,l
ld b,h
add hl,hl
add hl,hl
add hl,bc
add hl,hl
ld c,a
ld b,0
add hl,bc
jr cil1
ss_cmp ld hl,output_buff
ss_cm1 ld a,(de)
or a
ret z
inc de
cpi
jr z,ss_cm1
ret
/*
ld a,3
out (#fe),a
ld de,#c000
; call read_idp_packet
read_idp_packet push de
ld e,#ff ; lenght
xor a
out (#fe),a
call read_pack
ld c,a
ld hl,output_buff
ld b,l
pop de
ldir
ld a,4
out (#fe),a
ld a,d
cp #d0
jr nz,read_idp_packet
nop
nop
ret
*/
read_pack
ld bc,zifi_input_fifo_status ; ждём прихода данных в фифо
ld hl,0
1 dec hl
ld a,h
or a
jp z,zifi_read_ipd_ex
in a,(c)
or a ; 0 - input FIFO is empty,
jr z,1b
ld hl,output_buff ; in E - lenght
read_pack_proc cp 0xbf
jr c,1f
ld a,0xbf
1 ld b,a
ld a,d
or a
jr nz,1f
ld a,b
cp e
jr c,1f
ld b,e
1 ld a,b
push af
2 in a,(c)
ld (hl),a
inc l
djnz 2b
; di
; inir
; ei
; push af
ret
; Read pending ESP bytes only when FIFO already contains data. fifo_inir
; otherwise calls zifi_input_fifo_check, which may wait 256 frames and used to
; let the start-up splash show through while an NTP server was silent.
; BC is preserved because callers can use it as a retry counter.
poll_input_fifo push bc
ld bc,zifi_input_fifo_status
in a,(c)
or a
jr z,.done
call fifo_inir
.done pop bc
ret
fifo_inir push de
call zifi_input_fifo_check
ld hl,output_buff ; read data from fifo, count: #bf
push hl
ld bc,zifi_data_reg
inir
pop hl
pop de
ret
zifi_send call zifi_send_raw
zifi_check_receive_command jp fifo_inir
zifi_send_echo push hl
ld b,1
call zifi_echo
pop hl
call zifi_send
1 ld a,(hl)
inc hl
cp #0d+1
jr c,1b
dec hl
ld b,3
zifi_echo ld de,#1000
call print
ld a,d
cp 24
jr c,1f
ld hl,text_up_copy
call set_ports
ld hl,24*256
call clear_text_line
ld a,22
1 ld (zifi_echo+2),a
ret
print ld a,(hl)
cp #ff
ret z
ld a,b
or a
jr nz,1f
ld b,1
1 push de
print1 ld a,(hl)
inc hl
cp #0d+1
jr c,print2
ld (de),a
inc de
jr print1
print2 ld a,(hl)
cp #0d+1
jr nc,1f
inc hl
1 pop de
inc d
djnz print
ret
zifi_send_raw call check_output_fifo_status
call clear_output_fifo
push hl
ld hl,output_buff
ld de,output_buff+1
ld bc,#ef
ld (hl),l
ldir
pop hl
ld bc,zifi_data_reg
1 ld a,(hl)
or a
ret z
out (c),a
inc hl
jr 1b
zifi_input_fifo_check
ld bc,zifi_input_fifo_status ; ждём прихода данных в фифо
ld e,0
3 in a,(c)
or a ; 0 - input FIFO is empty,
jr z,1f
push af
ld a,dl_timeout_quanta ; got data - reset the inactivity timeout
ld (dl_timeout_left),a
pop af
ret
1
wifi_cancel_download ld a,0
or a
jp nz,wifi_cancel_download_ex
call wait_frame
dec e
jr nz,3b
; one ~5s quantum (256 frames @ 50Hz) passed with nothing from the server at all
ld a,(dl_timeout_left)
dec a
ld (dl_timeout_left),a
jr nz,error ; still have quanta left - flash the border and keep waiting
; timed out - retry the same request a few times before giving up on it
ld a,(dl_retries_left)
or a
jr z,dl_timeout_no_more_retries
dec a
ld (dl_retries_left),a
jp dl_timeout_retry_ex
dl_timeout_no_more_retries
ld a,(do_after_load+1)
cp play_music
jr nz,dl_timeout_giveup
ld a,(music_skip_chain_left)
or a
jr z,dl_timeout_giveup ; skipped too many dead tracks in a row - stop trying
dec a
ld (music_skip_chain_left),a
call timeout_next_track
jp dl_timeout_advance_ex
dl_timeout_giveup
jp wifi_cancel_download_ex
error ld a,2
out (#fe),a
ret
clear_output_fifo ld a,cmd_clear_output_fifo
call zifi_out_command
check_output_fifo_status
ld bc,zifi_output_fifo_status
cofs in a,(c)
or a
jr z,cofs ; 0 - output FIFO is full
ret
clear_input_fifo ld a,cmd_clear_input_fifo
call zifi_out_command
ld bc,zifi_input_fifo_status
clear_input_fifo1 in a,(c)
or a
jr nz,clear_input_fifo1 ;0 - input FIFO is empty
ret
zifi_out_command ld bc,zifi_command_reg
out (c),a
ret
zifi_command_result ld bc,zifi_error_reg
in a,(c)
ret
downloaded_len db "Content-Length: ",0
CLOSED db "CLOSED",#0d,#0a,0
;wifi_disconnect db "WIFI DISCONNECT",#0d,#0a,0
buffer_cmp ld hl,output_buff
data_cmp ld (buffer_cmp_start+1),de
ld c,low output_buff+#bf
buffer_cmp_start
ld de,0
buffer_cmp0 ld a,(de)
cp (hl)
jr z,buffer_cmp1
ld a,l
cp c
jr z,buffer_cmp_notfound
inc hl
jr buffer_cmp0
buffer_cmp_notfound
or a
ret
buffer_cmp1 inc de
inc hl
ld a,(de)
or a
ret z
cp (hl)
jr nz,buffer_cmp_start
jr buffer_cmp1
set_icon ld a,e
ld (status_icon_copy+1),a
ld a,d
ld (status_icon_copy+3),a
ld hl,status_icon_copy
jp set_ports
wait call wait_frame
djnz wait
ret
view_progress_bar
ld a,b
or a
ret z
push hl
push bc
push bc
ld a,Vid_page+9
call set_page0_lite
pop bc
progress_bar ld hl,0
inc hl
bit 7,l
jr z,1f
ld l,low progress_bar_screen_adr
ld a,(progress_bar_color+1)
xor #18
ld (progress_bar_color+1),a
1 ld (progress_bar+1),hl
progress_bar_color
ld a,#74
ld (hl),0
inc h
inc h
dup 3
ld (hl),a
; inc l
; ld (hl),a
; dec l
inc h
inc h
edup
ld (hl),0
inc h
inc h
djnz progress_bar
call restore_page0
pop bc
pop hl
ret
/*
+#0000 #04 #7f+"SXG" - 4 байта сигнатура, что это формат файла SXG
+#0004 #01 1 байт версия формата
+#0005 #01 1 байт цвет фона (используется для очистки)
+#0006 #01 1 байт тип упаковки данных (#00 - данные не пакованы)
+#0007 #01 1 байт формат изображения (1 - 16ц, 2 - 256ц)
+#0008 #02 2 байта ширина изображения
+#000a #02 2 байта высота изображения
(далее указываются смещения, для того, что бы можно было расширить заголовок)
+#000c #02 смещение от текущего адреса до начала данных палитры
+#000e #02 смещение от текущего адреса до начала данных битмап
Собственно начало данных палитры +#0010 #0200 512 байт палитра
и начало данных битмап +#0210 #xxxx данные битмап
*/
init_view_image
ld hl,int_gfx_view
ld (#beff),hl
xor a
ld bc,VSINTL
out (c),a
inc b
out (c),a
jp wait_frame
view_image ld ix,read_threads
ld a,(ix+thread.page)
call set_page1
ld a,Gfx_vid_page
call set_page3
ld hl,(ix+thread.file_ext)
inc hl
ld a,"x" ; sxg / scr
cpi
jr z,view_sxg_image
ld a,"r"
cpi
ret nz
view_scr_image
ld hl,(ix+thread.adress)
ld de,#c000
ld bc,#1b00
ldir
call init_view_image
xor a
ld (gfx_vmode+1),a
ld (gfx_border+1),a
ld a,#0f
ld (gfx_vpal+1),a ; palsel
jp show_gfx
; ----- SXG viewer -------------
view_sxg_image call init_view_image
ld hl,(ix+thread.adress)
ld de,5
add hl,de
push hl
ld a,(hl) ; background? #4005
ld l,a
ld h,a
ld (gfx_border+1),a
ld (#c000),hl
ld hl,clr_gfx_screen
call set_ports
ld b,#28
ld a,#ff
out (c),a
ld b,#27
ld a,%00000100
OUT (C),a
call dma_stats
pop hl
inc hl
inc hl ; #4007
; push af
; ld (clrColor+1),a
; ld a,(hl) ; Тип упаковки данных (#00 - не пакованы)
ld a,(hl) ; Video color mode
ld c,a
inc hl
cp 2
; 16c mode
ld b,DMA_RAM + DMA_DALGN ; dma mode
ld a,1 ; high byte pal adress
ld de,#0f08 ; 32byte for pal dma send, 8 for palsel
jr nz,3f
xor a
ld b,DMA_RAM + DMA_DALGN + DMA_ASZ
ld de,#ff00
3 ld (view_image_pals_vpal_adr+1),a
ld (color_type+1),a
ld a,b
ld (gfx_copy_type+1),a
ld (gfx_copy_t2+1),a
ld a,e
ld (gfx_vpal+1),a
ld a,d
ld (view_image_pals_vpal+1),a
or a
rl e
rl e
rl e
rl e
ld a,e
ld (gfx_border+1),a
/*
ld (imageMode),a
push hl
call setImageMode
pop hl
cp #ff ; error -> exit
ret z
*/
ld e,(hl) ; Width 0-512
inc hl
ld d,(hl)
inc hl
ld a,VID_360X288
or c
ld (gfx_vmode+1),a
push hl
push bc
ld hl,360
or a
sbc hl,de
srl l
xor a
sub l
or a
jr z,1f
ld bc,GXOFFSL
out (c),a
inc b
ld a,1
out (c),a
1 pop bc
pop hl
/*
; #168 - 360; #140 - 320; #100- 256
ld a,#68
cp e
jr nz,1f
ld a,VID_360X288
jr 2f
1
; ld a,#40
; cp e
; jr nz,
ld a,VID_320X240 ; standart resolution
2 or c
ld (gfx_vmode+1),a
*/
srl d
rr e
color_type ld a,0
or a
jr z,4f
srl d
rr e ; Width 0-512 /4
4 ld a,e
dec a
ld (gfx_copy_w+1),a
ld e,(hl) ; Height 0-512
inc hl
ld d,(hl)
inc hl
push hl
ld hl,288
or a
sbc hl,de
srl l
xor a
sub l
or a
jr z,1f
ld bc,GYOFFSL
out (c),a
inc b
ld a,1
out (c),a
1 pop hl
bit 0,d
jr z,1f
ld a,#ff
jr 2f
1 xor a
dec e
2 ld (gfx_copy_h+1),a
dec e
ld a,e
ld (gfx_copy_h2+1),a
ld c,(hl) ; Указатель (смещение) на начало данных палитры
inc hl
ld b,(hl)
inc hl
push hl
add hl,bc ; Начало данных палитры
ld a,l
ld (view_image_pals+1),a
ld a,h
ld (view_image_pals+3),a
ld hl,view_image_pals
call set_ports
;gPalNum ld b,#01 ; Номер экрана для кого грузить палитру
; ld a,setGfxPalette
; call cliKernel
pop hl
ld c,(hl) ; Указатель (смещение) на начало данных bitmap
inc hl
ld b,(hl)
inc hl
add hl,bc ; Начало данных bitmap
ld a,l
ld (gfx_copy+1),a
ld a,h
ld (gfx_copy+3),a
ld hl,gfx_copy
call set_ports
gfx_copy_h2 ld a,0
ld b,#28
out (c),a
dec b
gfx_copy_t2 ld a,DMA_RAM + DMA_DALGN
out (c),a
call dma_stats
show_gfx call wait_frame
gfx_vmode ld a,0
ld bc,VCONFIG
out (c),a
ld b,high PALSEL
gfx_vpal ld a,#08
out (c),a
ld b,high TSCONFIG
ld a,0
out (c),a
ld b,high BORDER
gfx_border ld a,0
out (c),a
ld a,Gfx_vid_page
ld b,high VPAGE
out (c),a
call pause
LD BC,#FADF
3 IN A,(C) ;читаем порт кнопок
and 3
cp 3
jr z,3b
call pause
ld hl,int_main
ld (#beff),hl
xor a
ld bc,GXOFFSL
out (c),a
inc b
out (c),a
inc b
out (c),a
inc b
out (c),a
ld b,high TSCONFIG
ld a,TSU_SEN
out (c),a
ld hl,all_pals
call set_ports
ld hl,zx_pals
jp set_ports
pause ld b,#0a
call wait_frame
djnz $-3
ret
text_view
; main_list_url
ld a,download_page
call set_page1
text_view_in xor a
ld (lmb_click_sw+1),a
ld (do_after_load+1),a
inc a
ld (text_scroll+1),a
call set_text_colors
xor a
call set_page3
call set_Textpage
call parse_text
; ld hl,(ix+thread.adress)
; ld ix,#c000;2 ; text line buffer adresses
; ld (ix+0),l
; ld (ix+1),h
ld hl,#c000
ld de,window_start_Yl ; text page
ld b,window_height*4 ; rows
call show_text_line
ld hl,window_height*2
ld (text_up_line_adr+1),hl
ld a,l
ld (text_up+1),a
ret
parse_text ld de,(ix+thread.adress)
ld hl,#c000 ; text line buffer adresses
ld b,download_page
parse_text0 ld c,0
ld (hl),e
inc hl
ld (hl),d
inc hl
ld (hl),b
inc hl
parse_text1 ld a,(de)
or a
jr z,parse_text_ex
cp #ff
jr z,parse_text_ex
cp #0d
jr nz,parse_text2
inc de
inc de
jr parse_text4
parse_text2 inc de
bit 7,d
jr z,parse_text3
ld d,#40
inc b
ld a,b
push bc
call set_page1
pop bc
parse_text3 inc c
ld a,c
cp 80
jr nz,parse_text1
parse_text4 ld (hl),c
inc hl
jr parse_text0
parse_text_ex xor a
ld (hl),a
inc hl
ld (hl),a
ret
/*
ld de,window_start_Yl ; text page
ld bc,(window_height*2)*256+80 ; rows col, chars in row
call show_text_line
*/
show_text_line ld (show_text_line_adr+1),de
show_text_line1 ld e,(hl)
inc hl
ld d,(hl)
inc hl
ld a,d
or e
ret z
ld a,(hl)
inc hl
push bc
call set_page1
ld c,(hl)
inc hl
ld a,c
or a
jr z,show_text_line2
push hl
ex de,hl
show_text_line_adr
ld de,0
ld a,d
ld b,0
ldir
inc a
ld (show_text_line_adr+2),a
pop hl
show_text_line2 pop bc
djnz show_text_line1
ld a,1
ret
/*
show_text_line ld a,(hl)
or a
ret z
cp #ff
ret z
cp #0d
jr nz,text_view2
inc hl
inc hl
text_nl ld a,0
or a
jr z,text_nl2
inc ix
inc ix
ld (ix+0),l
ld (ix+1),h
text_nl2 inc d
ld e,0
ld c,80
dec b
jr nz,show_text_line
ld a,1
or a
ret
text_view2 ld (de),a
inc hl
inc de
dec c
jr z,text_nl
jr show_text_line
*/
text_up ld a,1
or a
ret z
ld a,download_page
call set_page1
ld hl,text_up_copy
call set_ports
ld hl,window_start_Yl+((window_height-1)*2*256)
push hl
call clear_text_line
pop de
; ld a,1
; ld (text_nl+1),a
text_up_line_adr
ld hl,0
add hl,hl
add hl,hl
ld a,h
add #c0
ld h,a
push hl
ld hl,(text_up_line_adr+1)
inc hl
inc hl
ld (text_up_line_adr+1),hl
xor a
call set_page3
call set_Textpage_lite
pop hl
ld bc,2*256+80 ; rows col, chars in row
call show_text_line
or a
ld (text_up+1),a
ret
text_down ld hl,(text_up_line_adr+1)
ld de,window_height*2
or a
sbc hl,de
jr nz,1f
; cp window_height*2
; jr nz,1f
xor a
ret
1 ld hl,(text_up_line_adr+1)
dec hl
dec hl
ld (text_up_line_adr+1),hl
or a
sbc hl,de
add hl,hl
add hl,hl
ld a,h
or #c0
ld h,a
push hl
ld a,download_page
ld (text_up+1),a
call set_page1
call text_dma_down
xor a
call set_page3
call set_Textpage_lite
pop hl
ld de,window_start_Yl
ld b,2 ; rows
jp show_text_line
text_dma_down ld hl,text_down_copy
call set_ports
ld d,window_start_Y+window_height*2-4
ld e,window_start_Y+window_height*2-2
ld a,window_height*2-1
td1 exa
ld b,high DMASADDRH
out (c),d
ld b,high DMADADDRH
out (c),e
dec d
dec e
; dec d
; dec e
ld b,#27
ld a,DMA_RAM
out (c),a
call dma_stats
exa
dec a
jr nz,td1
call set_Textpage_lite
ld hl,#180
ld a,7
ld (hl),a
inc l
jr nz,$-2
jp restore_page0
; in hl - adress:
; http://zxaaa.untergrund.net/get.php?f=DEMO6/a_brief_history_of_vacuum_cleaner_nozzle_attachments.zip
parse_url
ld a,dl_retries_max ; a fresh target - reset the retry budget
ld (dl_retries_left),a
; detect http:// vs https:// (5th char: ':' for http, 's'/'S' for https)
push hl
ld bc,4
add hl,bc
ld a,(hl)
pop hl
or #20 ; fold to lowercase
cp "s"
jr z,pu_https
pu_http ld a,"T"
ld (cmd_conn2site_type+0),a
ld a,"C"
ld (cmd_conn2site_type+1),a
ld a,"P"
ld (cmd_conn2site_type+2),a
ld de,create_link_suffix_http
ld (create_link1+1),de
ld de,7
ld (create_link1+4),de
jr pu_scheme_done
pu_https ld a,"S"
ld (cmd_conn2site_type+0),a
ld (cmd_conn2site_type+1),a
ld a,"L"
ld (cmd_conn2site_type+2),a
ld de,create_link_suffix_https
ld (create_link1+1),de
ld de,8
ld (create_link1+4),de
pu_scheme_done ld de,cmd_conn2site_adr
pu1 ld a,(hl) ; http://
inc hl
cp "/"
jr nz,pu1
inc hl ; /
ld bc,"//"
ld (host_url+1),hl
call find_copy_char
inc hl
ld (file_url+1),hl
; ld c,#0d
; call find_copy_char
create_link1 ld hl,create_link_suffix_http
ld bc,7
ldir
ld hl,modem_command
ld (hl),"G"
inc hl
ld (hl),"E"
inc hl
ld (hl),"T"
inc hl
ld (hl)," "
inc hl
ld (hl),"/"
inc hl
ex hl,de
file_url ld hl,0
ld bc,#0d0a
call find_copy_char
ld hl,http_part1
ld bc,http_part2-http_part1
ldir
host_url ld hl,0
ld bc,"//"
call find_copy_char
ld a,13
ld (de),a
inc de
ld a,10
ld (de),a
inc de
ld hl,http_part2
ld bc,http_part3-http_part2
ldir
; dec de
ex de,hl
ld de,modem_command
or a
sbc hl,de
; inc hl
ld de,url_len
ld bc,-1000
call Num1
cp "0"
jr z,1f
ld (de),a
inc de
1 ld bc,-100
call Num1
ld (de),a
inc de
1 ld c,-10
call Num1
ld (de),a
inc de
1 ld c,-1
call Num1
ld (de),a
inc de
ld a,#0d
ld (de),a
inc de
ld a,#0a
ld (de),a
inc de
xor a
ld (de),a
ret
Num1: ld a,'0'-1
Num2: inc a
add hl,bc
jr c,Num2
sbc hl,bc
ret
find_copy_char ld a,(hl)
cp c
ret z
cp b
ret z
ld (de),a
inc hl
inc de
jr find_copy_char
create_link_suffix_http
db #22,",80",13,10,0
create_link_suffix_https
db #22,",443",13,10,0
copy_ini ld a,(hl)
cp #0d+1
ret c
ld (de),a
inc hl
inc de
jr copy_ini
cp_ini ld a,(de)
or a
jr z,cp_ini1
cp (hl)
jr nz,error_ini
inc hl
inc de
jr cp_ini
cp_ini1 inc de
cp_ini2 ld a,(hl)
cp #20
ret nz
inc hl
jr cp_ini2
error_ini ld a,2
out (#fe),a
pop hl
call set_Textpage
ld hl,error_ini_text
ld b,1
call zifi_echo
ei
jr $
ini_db db "SSID:",0
db "password:",0
ini_db_time db "time:",0
error_ini_text db "Error parsing ini file",0
site_list dw download_site_list,gfx_site_list,music_site_list,press_site_list
download_site_list
db "Games: vtrd.in ",#0d,#0a, "http://ex.vtrd.in/vt/export.php?t=g",#0d,#0a, save_file,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db "Games: prods.tslabs.info - ZX Enhanced",#0d,#0a, "https://prods.tslabs.info/prods_zifi.php?t=2",#0d,#0a, save_file,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db "Demos: bbb.retroscene.org",#0d,#0a, "https://bbb.retroscene.org/zxn_zifi.php?t=0",#0d,#0a, save_file,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " Classic demos",#0d,#0a, "https://bbb.retroscene.org/zxn_zifi.php?t=1",#0d,#0a, save_file,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " Most liked",#0d,#0a, "https://bbb.retroscene.org/zxn_zifi.php?t=2",#0d,#0a, save_file,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " Most favorited",#0d,#0a, "https://bbb.retroscene.org/zxn_zifi.php?t=3",#0d,#0a, save_file,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " ZX Enhanced",#0d,#0a, "https://bbb.retroscene.org/zxn_zifi.php?t=4",#0d,#0a, save_file,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db "Demo Packs: vtrd.in",#0d,#0a, "http://ex.vtrd.in/vt/export.php?t=d",#0d,#0a, save_file,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db "Demos: prods.tslabs.info - ZX Enhanced",#0d,#0a, "https://prods.tslabs.info/prods_zifi.php?t=1",#0d,#0a, save_file,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db "Demos: pouet.net - ZX Spectrum",#0d,#0a, "http://zifi.vtrd.in/pouet.php?src=pouet_zx",#0d,#0a, save_file,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db "Demos: pouet.net - ZX Enhanced",#0d,#0a, "http://zifi.vtrd.in/pouet.php?src=pouet_zxe",#0d,#0a, save_file,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db "System: vtrd.in",#0d,#0a, "http://ex.vtrd.in/vt/export.php?t=s",#0d,#0a, save_file,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db #00
gfx_site_list db "Graphics: zxart.ee",#0d,#0a, "http://zxart.ee/zxnet/?a=g",#0d,#0a, view_gfx,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " Most popular",#0d,#0a, "http://zxart.ee/zxnet/?a=g&o=p",#0d,#0a, view_gfx,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " Top-rated",#0d,#0a, "http://zxart.ee/zxnet/?a=g&o=r",#0d,#0a, view_gfx,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " First places",#0d,#0a, "http://zxart.ee/zxnet/?a=g&o=w",#0d,#0a, view_gfx,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " Top of last year published",#0d,#0a, "http://zxart.ee/zxnet/?a=g&o=y",#0d,#0a, view_gfx,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " - Multicolour graphic & Timex",#0d,#0a, "http://zxart.ee/zxnet/?a=g&t=multi",#0d,#0a, view_gfx,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " - Colorful pictures",#0d,#0a, "http://zxart.ee/zxnet/?a=g&t=color",#0d,#0a, view_gfx,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " - Lowres graphics",#0d,#0a, "http://zxart.ee/zxnet/?a=g&t=lowres",#0d,#0a, view_gfx,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " - Pixel graphics",#0d,#0a, "http://zxart.ee/zxnet/?a=g&t=pixel",#0d,#0a, view_gfx,download_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db #00
music_site_list db "Music database: zxart.ee",#0d,#0a, "http://zxart.ee/zxnet/?a=m",#0d,#0a, play_music,music_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " Most popular",#0d,#0a, "http://zxart.ee/zxnet/?a=m&o=p",#0d,#0a, play_music,music_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " Top-rated",#0d,#0a, "http://zxart.ee/zxnet/?a=m&o=r",#0d,#0a, play_music,music_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " First places",#0d,#0a, "http://zxart.ee/zxnet/?a=m&o=w",#0d,#0a, play_music,music_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " Top of last year published",#0d,#0a, "http://zxart.ee/zxnet/?a=m&o=y",#0d,#0a, play_music,music_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db " --+ TurboSound Music +--",#0d,#0a, "http://zxart.ee/zxnet/?a=m&f=ts",#0d,#0a, play_music,music_page,#0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db #00
press_site_list db "Hype: hype.retroscene.org",#0d,#0a, "http://zifi.vtrd.in/get.php?src=hype",#0d,#0a, view_text,download_page, #0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db "Emags: vtrd.in", #0d,#0a, "http://ex.vtrd.in/vt/export.php?t=p",#0d,#0a, save_file,download_page, #0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db "Z80 Telegram Log", #0d,#0a, "http://zifi.vtrd.in/tlg.php",#0d,#0a, view_text,download_page, #0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db "IRC Logs", #0d,#0a, "http://irclog.dimkam.ru/zifi.php?src=z80",#0d,#0a, view_downloaded_list,download_page, #0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db "RSS Channels", #0d,#0a, "http://irclog.dimkam.ru/zrss.php",#0d,#0a, view_text,download_page, #0d,#0a, " ",#0d,#0a, " ",#0d,#0a
db #00
hl_menu_src db #1a,0
db #1b,0
hl_menu_desc db #1d,0
db #1e,0
db #1c,highlight_menu_page
db #1f,Vid_page
db #26,88/2-1
db #28,16-1
db #27,DMA_RAM + DMA_DALGN +DMA_ASZ
db #ff
hl_menu_adr dw 0,#c000+88
dw highlight_size,#e000+88
dw highlight_size*2,#c000+88+88+8
dw highlight_size*3,#e000+88+88+8
sites_list dec a ; highlight menu gfx
push af
add a,a
add a,a
ld l,a
ld h,0
ld de,hl_menu_adr
add hl,de
ld de,hl_menu_src+1
ld b,4
1 ld a,(hl)
ld (de),a
inc hl
inc de
inc de
djnz 1b
ld hl,menu_copy
call set_ports
ld hl,hl_menu_src
call set_ports
ld a,download_page
ld (load_ram_page+1),a
xor a
ld (scroll_sw+1),a ; switch off mouse scrolls
call set_text_colors
; clear text screen
pop af
add a,a
ld l,a
ld h,0
ld de,site_list
add hl,de
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
push hl
ld de,link_adreses
call parse_get
ld a,c
ld (all_lines_counter+1),a
ld (sum_list_lines+1),a
ld ix,link_adreses
ld b,a
dec b
pop hl
ld de,window_start_Yl
2 push bc
call show_line_get_buffer
pop bc
djnz 2b
xor a
ld (sites_sw+1),a
ld (click_offset+1),a ; GYOFFSL =0
ld (show_now_play_link+1),a
ld a,view_downloaded_list
ld (do_after_load+1),a
ret
set_text_colors
call off_int_dma
call set_Textpage
ld hl,0
ld (#0000),hl
ld hl,clr_text_screen
call set_ports
ld hl,#0080
set_text_colors_color
ld a,#07
1 ld (hl),a
inc l
jr nz,1b
ld l,#80
inc h
bit 5,h
jr z,1b
jp on_int_dma
create_link_list
ld a,1
ld (scroll_sw+1),a
xor a
ld (text_scroll+1),a
ld (link_num+1),a
ld (click_offset+1),a
ld hl,(ix+thread.adress)
push hl
ld de,link_adreses
call parse_get
ld a,c
ld (sum_list_lines+1),a
cp window_height ; check num of prods < window list for scrolls
jr nc,1f
xor a
jr 2f
1 sub window_height
2 ld (all_lines_counter+1),a
ld a,c
call set_text_colors
ld ix,link_adreses
pop hl
ld de,window_start_Yl
ld b,window_height
2 push bc
call show_line_get_buffer
pop bc
djnz 2b
do_after_link_list ld a,0 ; действие после загрузки
ld (do_after_load+1),a
ld c,0
cp play_music
jr nz,1f
ld c,1
1 ld a,c
ld (autoplay+1),a
loadpage_after_link_list ld a,0 ; страница для загрузки прода данного раздела
ld (load_ram_page+1),a
xor a
ld (load_sw+1),a
ret
find_0d0a ld hl,get_buffer
find_0d0a_hl
ss_cm4 ld a,#0d
ss_cm3 cpi
jr nz,ss_cm3
ld a,#0a
cpi
jr nz,ss_cm4
ld a,#0d
cpi
jr nz,ss_cm4
ld a,#0a
cpi
jr nz,ss_cm4
ret
/*
ld hl,get_buffer
ld de,link_adreses
; 0 - number of link
; 1,2 - adress of link name
; 3,4 - adress of link url
; 5 - count of chars date+author lenght
*/
list_up
text_scroll ld a,0
or a
jp nz,text_up
link_num ld a,0
all_lines_counter
cp 0
ret z
inc a
ld (link_num+1),a
add window_height-1
call calc_link_num
ld hl,text_up_copy
call set_ports
ld hl,window_start_Yl+((window_height-1)*2*256)
push hl
call clear_text_line
pop de
ld l,(ix+1)
ld h,(ix+2)
call show_line_get_buffer
ld a,1
ret
calc_link_num ld l,a
ld h,0
add hl,hl
push hl
add hl,hl
pop de
add hl,de
ex de,hl
ld ix,link_adreses
add ix,de
ret
list_down ld a,(text_scroll+1)
or a
jp nz,text_down
ld a,(link_num+1)
or a
ret z
dec a
ld (link_num+1),a
call calc_link_num
call text_dma_down
/*
ld hl,get_buffer
ld de,link_adreses
; 0 - number of link
; 1,2 - adress of link name
; 3,4 - adress of link url
; 5 - count of chars date+author lenght
*/
down_link
ld hl,window_start_Yl
push hl
call clear_text_line
pop de
ld l,(ix+1)
ld h,(ix+2)
call show_line_get_buffer
ld a,1
ret
; ------- page 0
set_Textpage_lite
ld a,Text_page
jr set_page0_lite
set_Textpage ld a,Text_page
jr set_page0
set_page0 ld (restore_page0+1),a
set_page0_lite ld bc,PAGE0
out (c),a
ret
restore_page0 ld a,0
jr set_page0_lite
; ------- page 1
set_buffer_page ld a,list_ram_page
set_page1 ld (restore_page1+1),a
set_page1_lite ld bc,PAGE1
out (c),a
ret
restore_page1 ld a,0
jr set_page1_lite
; ------- page 3
set_page3 ld (restore_page3+1),a
set_page3_lite ld bc,PAGE3
out (c),a
ret
restore_page3 ld a,0
jr set_page3_lite
set_music_pages ld a,music_page
call set_page0
inc a
call set_page1
ld a,music_players_page
jp set_page3
restore_music_pages
xor a
call set_page0
ld a,list_ram_page
jp set_page1
/*
set_music_pages ld a,(restore_page0+1)
ld (rest_p0+1),a
ld a,(restore_page1+1)
ld (rest_p1+1),a
ld a,(restore_page3+1)
ld (rest_p3+1),a
ld a,music_page
call set_page0
inc a
call set_page1
ld a,music_players_page
jp set_page3
restore_music_pages
rest_p0 ld a,0
call set_page0
rest_p3 ld a,0
call set_page3
rest_p1 ld a,list_ram_page
jp set_page1
*/
set_music_pages_lite
ld a,music_page
call set_page0_lite
inc a
call set_page1_lite
ld a,music_players_page
jp set_page3_lite
restore_music_pages_lite
call restore_page0
call restore_page1
jp restore_page3
/*
ld hl,get_buffer
ld de,link_adreses
; 0 - number of link
; 1,2 - adress of link name
; 3,4 - adress of link url
; 5 - type of a site_list
*/
parse_get
call set_buffer_page
ld c,1
parse_get1 ld a,(hl)
cp #0a
jr c,parse_get_ex
cp #0d
jr z,parse_get_ex
ld a,c
ld (de),a ; number of link
inc de
call save_parsed ; adress of link name
call scan_0d
call save_parsed ; adress of link url
call scan_0d ; date adr
call scan_0d ; author
call scan_0d ; city
inc de
call scan_0d ; next record
inc c
jr parse_get1
parse_get_ex ld a,c
ld (de),a ; number of link
inc de
save_parsed ld a,l
ld (de),a ; adress of link adress
inc de
ld a,h
ld (de),a
inc de
ret
scan_0d ld a,(hl)
inc hl
cp #0a
jr nz,scan_0d
; inc hl ; #0a
ret
clear_text_line ld d,h
inc d
ld e,l
call set_Textpage_lite
xor a
ld b,#80
1 ld (hl),a
ld (de),a
inc l
inc e
djnz 1b
jp restore_page0
show_line_get_buffer
call set_Textpage_lite
ld a,list_ram_page
call set_page1_lite
ld a,(hl) ; end of list
or a
jp z,slgb_ex
push de
ld a,6+8
call drawString ; name
call scan_0d ; propusk: links
ld a,(hl)
cp #0b ; пропуск всех пустых строк сразу (для списка ссылок раздела и поиска)
jr nc,show_get_buf4
or a
jr z,show_get_buffer_ex
call scan_0d
call scan_0d
call scan_0d
jr show_get_buffer_ex+3
; echo $x++.'.'.$lx['title']."\r\n
; $lx['url']."\r\n"
; $lx['year']."\r\n".
; substr($authors,0,-1)."\r\n";
; addslashes($lx['city'])."\r\n";
show_get_buf4 ld (show_year_adr+1),hl ; store "year"
call scan_0d
ld (show_author_adr+1),hl ; store "authors"
call scan_0d
; ld (show_city_adr+1),hl ; store "city"
call scan_0d
ld (show_get_buffer_ex+1),hl
show_author_adr ld hl,0
ld a,(hl) ; check "by author"
cp #0e
jr c,1f
push hl
ld hl,by_db ; by
ld a,4
call drawString
pop hl
ld a,4+8 ; authors
call drawString
1
show_year_adr ld hl,0 ; year
ld a,(hl) ; check "year"
cp #0e
jr c,1f
ld a,","
ld (de),a
inc de
inc de
ld a,4
call drawString
1
show_get_buffer_ex
ld hl,0
ld de,6
add ix,de
pop de
inc d
inc d
slgb_ex call restore_page0
jp restore_page1
by_db db " by ",#0a
drawString ; de: screen adress in tiles
; hl: string
ld (char_color+1),a
ld a, 80
ld (charz+1), a
push de
exx
pop hl
set 7,l
exx
dStr1 ld a,(hl)
cp #0a
jr z,dStr2
cp #0d
jr z,dStr3
ld (de),a
inc e
exx
char_color ld (hl),0
inc l
exx
inc hl
charz ld a, 0
dec a
ret z
ld (charz+1), a
jr dStr1
dStr3 inc hl
dStr2 inc hl ; #0a
ret
wait_frame ld a,(frame+1)
or a
jr z,wait_frame
xor a
ld (frame+1),a
ret
int_gfx_view push af,hl,de,bc,ix
ld a,(frame+1)
inc a
ld (frame+1),a
ld a,(music_sw+1)
or a
call nz,pt_play
pop ix,bc,de,hl,af
ei
ret
int_main push af,hl,de,bc,ix,iy
; 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
push hl,de,bc
exx
exa
push af
exa
xor a
ld b,high GYOFFSL
out (c),a
inc b
out (c),a
call set_256c_mode
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_ex_regs
; Foreground screen updates and the SD driver share the single TS-Conf
; DMA register set with mouse sprite uploads. Never interrupt a DMA
; programming sequence with another one.
ld a,(dma_busy)
or a
jr nz,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_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
exx
pop bc,de,hl
exx
pop iy,ix,bc,de,hl,af
ei
ret
int_text_cor push af
push hl
push bc
ld hl,56+4*8
ld bc,VSINTL
out (c),l
ld b,high VSINTH
out (c),h
ld hl,int_text_on
ld (#beff),hl
xor a
ld (int_text_cor_ex+1),a
ei
int_text_cor_ex ld a,0
or a
jr z,int_text_cor_ex
pop bc
pop hl
pop af
ret
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 hl,47+240-1-2
ld de,int_text_ofcor
jp int_ex
int_text_ofcor push af
push hl
push bc
ld hl,47+240
ld bc,VSINTL
out (c),l
ld b,high VSINTH
out (c),h
ld hl,int_text_off
ld (#beff),hl
xor a
ld (int_text_ofcor_ex+1),a
ei
int_text_ofcor_ex ld a,0
or a
jr z,int_text_ofcor_ex
pop bc
pop hl
pop af
ret
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
ld a,(save_mode+1)
or a
jr z,int_ex3
enter_search_sw ld a,0
or a
call nz,enter_search
int_ex3 ld hl,0
ld de,int_main
ld a,1
ld (int_text_ofcor_ex+1),a
jp int_ex
pt_play call set_music_pages_lite
call music_player_play
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
jr z,autoplay
ld a,(current_list_page+1)
mus_link_page cp 0
jr nz,autoplay
show_now_play_cnt
ld a,0
inc a
and 7
ld (show_now_play_cnt+1),a
jr nz,autoplay
call set_Textpage_lite
ld a,(link_num+1)
ld c,a
ld a,(autoplay_num+1)
sub c
cp #0f
jr nc,autoplay
add a,a
inc a
ld h,a
ld l,#80
ld b,80
1 ld a,(hl)
xor #08
ld (hl),a
inc l
djnz 1b
autoplay ld a,1
or a
jr z,pt_play_ex
ld a,(music_setup_vars)
bit 7,a
jr z,pt_play_ex
; loop is passed
ld a,(sum_list_lines+1)
dec a
ld c,a
autoplay_num ld a,0
inc a
cp c
jr c,1f
ld a,1
1 ld (autoplay_num+1),a
call calc_link_num
ld a,list_ram_page
call set_page1
ld h,(ix+4)
ld l,(ix+3)
call parse_url
ld a,1
ld (load_sw+1),a
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);
;set bit1 for PT2 and reset for PT3 before
;calling INIT;
;bits2-3: %00-ABC, %01-ACB, %10-BAC (optional);
;bits4-5: %00-no TS, %01-2 modules TS, %10-
;autodetect PT3 TS-format by AlCo (PT 3.7+);
;Remark: old PT3 TS-format by AlCo (PT 3.6) is not
;documented and must be converted to new standard.
;bit6 is set each time, when loop point of 2nd TS
;module is passed (optional).
;bit7 is set each time, when loop point of 1st TS
;or of single module is passed (optional).
*/
set_256c_mode
ld bc,VCONFIG
ld a,VID_256C+VID_320X240 ;VID_NOGFX+
out (c),a
ld b,high VPAGE
ld a,Vid_page
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
ld a,#0a
dec a
ld (link_highlight_view+1),a
ret nz
1 ld a,(link_highlight+1)
ld d,a
ld a,Text_page
call set_page3_lite
ld e,#80
ld hl,highlight_colors_buff
ld bc,80
ldir
xor a
ld (link_highlight+1),a
ld a,#0a
ld (link_highlight_view+1),a
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 ; wait for the fill before drawing over it
ld hl,ay_volume
push hl
ld b,3
2 ld a,(hl)
or a
jr z,1f
dec (hl)
1 inc hl
djnz 2b
ld hl,ay_volume
ld de,#0308
ma1 LD BC, #FFFD
OUT (C), e
IN A, (C)
and #0f
cp (hl)
jr c,1f
ld (hl),a
1 inc hl
inc e
dec d
jr nz,ma1
pop de
ld hl,analizator_screen_adr
ld c,3
ma3 ld a,(de)
inc a
inc de
add a,a
ld b,a
add #40
ma2 ld (hl),a
inc hl
djnz ma2
ld l,low analizator_screen_adr
inc h
inc h
dec c
jr nz,ma3
xor a
ld (analyzer_active),a
jp restore_page3
ay_volume ds 3
analyzer_active db 0
dma_busy db 0
/*
1 D0 - левая кнопка
2 D1 - правая кнопка
4 D2 - средняя кнопка
#10-#f0
D4-D7 - wheel
*/
mouse_buttons
scroll_sw ld a,0
or a
jr z,lmb_old
wheel_old ld c,#f0
ld a,(mouse_button)
cpl
and #f0
cp c
jr z,lmb_old
ld (wheel_old+1),a
sub c
jp m,list_up
jp nc,list_down
jp p,list_down
jp list_up
/*
jp m,list_down
jp nc,list_up
jp p,list_up
jp list_down
*/
lmb_wait equ #c
lmb_old ld a,(mouse_button)
cpl
and 1
cp 1 ; lmb pressed
jp nz,lmb_release
lmb_counter ld a,0
inc a
cp lmb_wait
jr z,drag_start
jr nc,lmb_drag
ld (lmb_counter+1),a
ret
drag_start ld (lmb_counter+1),a
ld a,(mouse_y)
ld (drag_start_pos+1),a ; begin pos of drag
ld (lmb_line_cnt+1),a
ld (lmb_old_line_cnt+1),a
ret
lmb_drag ld a,1
or a
ret z
ld a,(scroll_sw+1)
or a
ret z
lmb_line_cnt ld e,0 ; current point of prirost + y_coord
lmb_old_line_cnt
ld d,0 ; old point of prirost + y_coord
ld a,(mouse_y)
drag_start_pos sub 0 ; begin pos of drag
ld l,a
ld h,high mouse_step
ld a,e
add (hl) ; prirost
ld e,a
ld (lmb_line_cnt+1),a
sub d
jp m,ld10
cp #10
jr c,ld2
jr ld01
ld10 cp #f0
jr nc,ld2
neg
sub #10
add e
; ld a,e
ld (lmb_old_line_cnt+1),a
call list_down
jr nz,ld2
ld (lmb_drag+1),a
ld (click_offset+1),a
jr ex_no_offset
; +
ld01 ld a,e
ld (lmb_old_line_cnt+1),a
call list_up
jr nz,ld2
xor a
ld (lmb_drag+1),a
ld (click_offset+1),a
jr ex_no_offset
ld2 ld a,(lmb_old_line_cnt+1)
ld c,a
ld a,(lmb_line_cnt+1)
sub c
and #0f
ld (click_offset+1),a
ex_no_offset ld a,#02
jp lmb_ex2
lmb_release
ld a,(lmb_counter+1)
or a
jp z,lmb_ex
cp lmb_wait-1
jp nc,lmb_ex
ld a,(mouse_y)
cp 4*8
jp c,menu_click
cp 240-8
jp nc,status_click
lmb_click_sw ld a,1
or a
jp z,lmb_ex
ld a,(mouse_y)
sub 4*8 ; Y offset from menu
click_offset add 0 ; mouse Y offset 0-15
srl a
srl a
srl a
srl a
ld c,a
sum_list_lines ld a,0
dec a
ld b,a
cp c
jp z,lmb_ex
jp c,lmb_ex
ld a,c
; save txt colors buffer
push bc
add a,a
inc a
add #c0
ld (link_highlight+1),a
ld h,a
ld a,Text_page
call set_page3_lite
ld l,#80
ld de,highlight_colors_buff
ld bc,80
ldir
ld l,#80
ld a,#0f
1 ld (hl),a
inc l
jr nz,1b
call restore_page3
pop bc
ld a,(link_num+1)
add c
cp b ; all links counter
jp z,lmb_ex
ld c,a
or a
jr nz,1f
ld a,(do_after_load+1)
cp view_downloaded_list
jr z,1f
ld a,1 ; start enter search word
ld (enter_search_sw+1),a
call set_Textpage_lite
ld hl,search_textpage_adr
ld (search_input_adress+1),hl
ld a,"_"
ld (hl),a
inc l
xor a
ld b,#40
ld (hl),a
inc l
djnz $-2
ld hl,highlight_colors_buff+7
ld b,#40
ld a,7
2 ld (hl),a
inc l
djnz 2b
jp lmb_ex
1 ld a,(do_after_load+1)
cp play_music
jr nz,1f
ld a,c
ld (autoplay_num+1),a
ld a,(current_list_page+1)
ld (mus_link_page+1),a
ld (show_now_play_link+1),a
1 ld a,c
call calc_link_num
ld a,list_ram_page
call set_page1
ld h,(ix+4)
ld l,(ix+3)
ld (main_list_url+1),hl
ld a,(do_after_link_list+1) ; проверка на текст и установка нового пейджинга
cp view_text
jr nz,1f
call parse_url
jr main_list_url ; paging for text files
1 push hl
cp save_file ; проверка на файло для закачки
jr nz,not_unzip
; проверка на zip
ld de,zip_url_buffer_data
ld bc,#0d0a
call find_copy_char
ld a,#0d
ld (de),a
ld hl,zip_url_buffer
not_unzip call parse_url
pop hl
call scan_0d
ld a,(hl) ; проверка на клик по списку сайтов в разделе
cp #0d
jr nc,1f
ld (do_after_link_list+1),a ; тип действия для данного сайта
inc hl
ld a,(hl) ; пага загрузки для данного сайта
ld (loadpage_after_link_list+1),a
ld h,(ix+4)
ld l,(ix+3)
ld (main_site_url+1),hl
main_list_url ld hl,0
ld (current_list_url+1),hl
ld bc,#0d0d
ld de,current_paging_url
call find_copy_char
ex de,hl
ld (hl),"&"
inc hl
ld (hl),"p" ; page num
inc hl
ld (hl),"="
inc hl
ld (current_paging_page+1),hl
ld (hl),"0"
inc hl
ld (hl),"2"
inc hl
ld (hl),#0d
ld a,start_paging_page
ld (current_list_page+1),a
1 ld a,1
ld (load_sw+1),a
lmb_ex
ld a,1
ld (lmb_drag+1),a
dec a
ld (lmb_counter+1),a
lmb_ex2 ld (mouse_spr+4),a
ret
status_click
ld hl,(current_list_url+1)
ld a,h
or l
or a
jr z,lmb_ex ; url with link list not loaded
call mouse_x_div8
cp #10
jr c,lmb_ex
cp #12
jr c,cancel_download
cp #19
jp z,music_play
cp #1a
jp z,music_stop
ld c,a
ld a,(load_sw+1) ; 1-load now, check for download now
or a
jr nz,lmb_ex
ld a,c
cp #21
jp z,first_page
cp #22
jp z,page_back
cp #27
jp z,page_forward
jr lmb_ex
cancel_download ld a,1
if cable_zifi=1
ld (uart.cable_cancel_download+1),a
else
ld (wifi_cancel_download+1),a
endif
jr lmb_ex
first_page
current_list_url
ld hl,0
call parse_url
ld a,start_paging_page
ld (current_list_page+1),a
paging_page_ex ld a,1
ld (load_sw+1),a
ld a,view_downloaded_list
ld (do_after_load+1),a
ld a,download_page
ld (load_ram_page+1),a
jp lmb_ex
page_back ld a,(current_list_page+1)
dec a
cp start_paging_page-1 ; p=1
jp z,lmb_ex
ld (current_list_page+1),a
jr current_list_page_count
page_forward
current_list_page
ld a,0
inc a
ld (current_list_page+1),a
current_list_page_count
ld l,a
ld h,0
current_paging_page
ld de,0
ld bc,-10
call Num1
ld (de),a
inc de
ld c,-1
call Num1
ld (de),a
ld hl,current_paging_url
call parse_url
jr paging_page_ex
music_loaded ld a,1
ld (music_play+1),a
ld a,music_skip_chain_max ; a track made it through - reset the dead-track counter
ld (music_skip_chain_left),a
xor a
ld (is_music_play+1),a
ld hl,(ix+thread.adress)
; res 7,h
res 6,h
ld (music_adr+1),hl
music_play ld a,0 ; music is loaded?
or a
jp z,lmb_ex
is_music_play ld a,0 ; music is inited, check pause/play
or a
jr nz,pause_music
ld (do_start_music+1),a
jp lmb_ex
music_stop ld a,(music_play+1)
or a
jp z,lmb_ex
ld (do_init_music+1),a
jp lmb_ex
music_init call set_music_pages
music_adr ld hl,0
call music_player_init
; call music_player_mute
call restore_music_pages
; ld hl,SETUP
; res 0,(hl) ; loop mode
ld a,1
ld (music_sw+1),a
ld (is_music_play+1),a
ld (do_start_music+1),a
ret
pause_music ld a,0
cpl
ld (pause_music+1),a
or a
jr nz,pause_music1
ld a,1
ld (music_sw+1),a
jp lmb_ex
pause_music1 xor a
ld (music_sw+1),a
call set_music_pages
call music_player_mute
call restore_music_pages
jp lmb_ex
menu_click ld a,(zifi_ready)
or a
jp z,lmb_ex ; Wi-Fi/NTP/download directory initialization still running
ld a,(mouse_y)
srl a
srl a
srl a
srl a
ld c,a
ld a,(load_sw+1) ; 1-load now, check for download now
or a
jp nz,lmb_ex
ld a,c
call mouse_x_div8
cp 11
jp c,lmb_ex
cp 29
jp nc,lmb_ex ; empty left/right menu
cp 21 ; download / graphics
jr c,menu_first
cp 23 ; music/press
jp c,lmb_ex ; subdivider
menu_two ld a,c
or a
jr nz,menu_two_gfx
ld a,music_sites
menu_sw ld (sites_sw+1),a
ld a,download_page
ld (load_ram_page+1),a
xor a
ld (link_num+1),a
inc a
ld (lmb_click_sw+1),a
xor a
ld (do_after_link_list+1),a ; тип действия для данного сайта
jp lmb_ex
menu_two_gfx ld a,press_sites
jr menu_sw
menu_first ld a,c
or a
jr nz,menu_first_music
ld a,download_sites
jr menu_sw
menu_first_music
ld a,gfx_sites
jr menu_sw
mouse_x_div8
ld hl,(mouse_x)
or a
srl h
rr l
srl h
rr l
srl h
rr l
ld a,l
ret
key_wait equ #07
enter_search ld a,1
dec a
ld (enter_search+1),a
ret nz
inc a
ld (enter_search+1),a
call Read_Keyboard
or a
ret z
cp enter
jr nz,es1
xor a ; press ENTER
ld (enter_search_sw+1),a
ld hl,search_textpage_adr
ld (search_input_adress+1),hl
main_site_url ld hl,0
ld bc,#0d0d
ld de,search_url
push de
call find_copy_char
ex de,hl
ld (hl),"&"
inc hl
ld (hl),"s" ; page num
inc hl
ld (hl),"="
inc hl
ex de,hl
ld hl,search_textpage_adr
call copy_ini
dec de
ld a,#0d
ld (de),a
pop hl
ld (main_list_url+1),hl
ld a,view_downloaded_list
ld (do_after_load+1),a
ld a,download_page; list_ram_page
ld (load_ram_page+1),a
call parse_url
jp main_list_url ; готовим строку поиска
es1 cp del
jr nz,es2
ld hl,(search_input_adress+1)
ld a," "
ld (hl),a
dec l
ld a,l
cp #08 ; начало строки поиска - 1
jr nc,search_input_adress2
ld hl,search_textpage_adr
jr search_input_adress2
es2 cp #20
ret c
push af
call set_Textpage_lite
pop af
search_input_adress
ld hl,search_textpage_adr
ld (hl),a
inc l
ld a,l
cp #08+32
ret z
search_input_adress2
ld (search_input_adress+1),hl
search_input_adress3
ld a,"_"
ld (hl),a
ld a,key_wait
ld (enter_search+1),a
ret
mouse_proc call mouse_buttons
call mouse_pos
ld a,(mouse_y)
ld (mouse_spr),a ; Y
cp 8
jr nc,mouse_margin_y
ld de,#fff8
ld b,d
ld c,e
jr mouse_mrg_y_top
mouse_margin_y cp 240-16
jr c,mouse_margin_y_ex
ld de,#0118
ld bc,#0008
mouse_mrg_y_top ld hl,0
add hl,bc
ld a,h
cp d
jr nz,mouse_mrg_y_top2
ld a,l
cp e
jr z,mouse_margin_y_ex
mouse_mrg_y_top2
ld (mouse_mrg_y_top+1),hl
mouse_margin_y_ex
ld hl,(mouse_x)
ld bc,8
sub hl,bc
jr nc,mouse_margin_x
ld bc,#f8f8
jr mouse_mrg_x_top
mouse_margin_x ld hl,(mouse_x)
ld bc,320-16
sub hl,bc
jr c,mouse_margin_x_ex
ld bc,#c808
mouse_mrg_x_top ld a,0
add c
cp b
jr z,mouse_margin_x_ex
ld (mouse_mrg_x_top+1),a
mouse_margin_x_ex
ld hl,(mouse_x)
ld a,l
ld (mouse_spr+2),a ; X
ld a,(mouse_spr+3)
and #fe
or h
ld (mouse_spr+3),a
mouse_show_sw ld a,0
or a
ret nz
ld hl,sprites
jp set_ports
/*
D0 - левая кнопка
D1 - правая кнопка
D2 - средняя кнопка
D4-D7 - wheel
Standard Kempston Mouse
#FADF - buttons
#FBDF - X coord
#FFDF - Y coord
*/
mouse_pos
LD BC,#FADF
IN A,(C) ;читаем порт кнопок
key_in ld (mouse_button),a
LD BC,#FBDF
IN A,(C)
MOUSE11 LD d,0
LD (MOUSE11+1),A
sub d
CALL NZ,MOUSE_X_vector
LD B,#FF
IN A,(C)
; call key_scan
MOUSE12 LD D,0
LD (MOUSE12+1),A
SUB D
CALL NZ,MOUSE_Y_vector
RET
MOUSE_X_vector JP M,MOUSE35 ; Sign Negative (M)
ld e,a
ld d,0
ld hl,(mouse_x)
add hl,de
ld (mouse_x),hl
ld de,320
sub hl,de
ret c
1 ld hl,320-1
jr 1f
MOUSE35 neg
ld e,a
ld d,0
or a
ld hl,(mouse_x)
sub hl,de
jr nc,1f
ld hl,0
1 ld (mouse_x),hl
RET
MOUSE_Y_vector
JP M,MOUSE45
ld e,a
ld d,0
or a
ld hl,(mouse_y)
sub hl,de
jr nc,2f
ld hl,0
2 ld (mouse_y),hl
ret
MOUSE45
neg
ld e,a
ld d,0
ld hl,(mouse_y)
add hl,de
ld (mouse_y),hl
ld de,240
sub hl,de
ret c
ld hl,240-1
jr 2b
koorp ld a,c
and #18
; or #c0
ld h,a
ld a,c
and #07
rrca
rrca
rrca
add a,b
ld l,a
ret ; 14 байт, 53 такта
im2_init
xor a
ld bc,HSINT
out (c),a
ld bc,VSINTL
out (c),a
ld bc,VSINTH
out (c),a
ld e,4
ld b,high GXOFFSL
call fill_ports
ld e,7
ld b,high T0XOFFSL
call fill_ports
call spr_off
ld a,#be
ld i,a
ld hl,int_gfx_view
ld (#beff),hl
im 2
ret
fill_ports out (c),a
inc b
dec e
jr nz,$-4
ret
Read_Keyboard LD HL,Keyboard_Map ; Point HL at the keyboard list
LD D,8 ; This is the number of ports (rows) to check
LD C,#FE ; C is always FEh for reading keyboard ports
Read_Keyboard_0 LD B,(HL) ; Get the keyboard port address from table
INC HL ; Increment to list of keys
IN A,(C) ; Read the row of keys in
AND #1F ; We are only interested in the first five bits
LD E,5 ; This is the number of keys in the row
Read_Keyboard_1 SRL A ; Shift A right; bit 0 sets carry bit
JR NC,Read_Keyboard_2 ; If the bit is 0, we've found our key
INC HL ; Go to next table address
DEC E ; Decrement key loop counter
JR NZ,Read_Keyboard_1 ; Loop around until this row finished
DEC D ; Decrement row loop counter
JR NZ,Read_Keyboard_0 ; Loop around until we are done
AND A ; Clear A (no key found)
RET
Read_Keyboard_2
ld a,(hl)
cp "0"
ret nz
ld bc,#fefe
in a,(c)
bit 0,a
ld a,(hl)
ret nz
ld a,del
RET
/*
ld d,0
ld bc,#fefe ; check for CAPS SHIFT
in a,(c)
bit 4,a
jr nz,1f
ld d,#30
1 ld a,d
add e
*/
Keyboard_Map:
DB #FB,"q","w","e","r","t"
DB #F7,"1","2","3","4","5"
DB #EF,"0","9","8","7","6"
DB #DF,"p","o","i","u","y"
DB #BF,enter,"l","k","j","h"
DB #7F," ",sym,"m","n","b"
DB #FD,"a","s","d","f","g"
DB #FE,caps,"z","x","c","v"
caps equ #01
sym equ #02
enter equ #0d
del equ #0c
/*
Рассмотрим рисунок клавиатуры:
N:БИТA| 0| 1| 2| 3| 4| 4| 3| 2| 1| 0|
------+--+--+--+--+--+--+--+--+--+--+ N_
N_ 3 | 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| 4 П
П +--+--+--+--+--+--+--+--+--+--+ О
О 2 | Q| W| E| R| T| Y| U| I| O| P| 5 Л
Л +--+--+--+--+--+--+--+--+--+--+ У
У 1 | A| S| D| F| G| H| J| K| L|ENT 6 Р
Р +--+--+--+--+--+--+--+--+--+--+ Я
Я 0 |CS| Z| X| C| V| B| N| M|SS|SPC 7 Д
Д +--+--+--+--+--+--+--+--+--+--+ А
А
3-#F7 4-#EF
2-#FB 5-#DF
1-#FD 6-#BF
0-#FE 7-#7F
*/
fill_menu push bc
fill_menu1 ld (hl),e
inc l
ld (hl),d
inc l
djnz fill_menu1
inc h
ld l,b
pop bc
dec c
jr nz,fill_menu
ret
all_init di
ld bc,MEMCONFIG
ld a,%00001110
out (c),a
xor a
call set_page0
call im2_init
call mouse_pos
ld bc,PAGE3
ld a,Vid_page
out (c),a
ld hl,#0000 ;1111 - white
ld (#c000),hl
ld hl,init_ts
call set_ports
ld hl,all_pals
call set_ports
ld hl,splash_copy
jp set_ports
gfx_init ; The splash is useful only during the initial delay. Clear its
; backing 256-colour pages before installing the normal UI, so a late
; or missed text raster can reveal only black, never the old banner.
ld hl,clr_gfx256_screen
call set_ports
ld hl,cursor_copy
call set_ports
ld hl,menu_copy
call set_ports
ld hl,status_copy
call set_ports
ld hl,mouse_step
xor a
1 ld b,4
ld (hl),a
inc l
djnz $-2
ld (hl),a
inc a
2 inc l
bit 7,l
jr z,1b
ld l,#80
ld d,h
ld e,#80
3 ld a,(hl)
neg
ld (de),a
inc e
dec l
jr nz,3b
xor a
ld (lmb_click_sw+1),a
ret
init_ts db #20,6
db high BORDER,GFX_BORDER ; border
db high SGPAGE, Sprite_page
db high CacheConfig,#0c ; cache for #8000 - #c000
clr_gfx256_screen
defb #1a,0 ;
defb #1b,0 ;
defb #1c,Vid_page ;
defb #1d,0 ;
defb #1e,0 ;
defb #1f,Vid_page ;
defb #26,#ff ;
defb #28,#ff ;
defb #27,%00000100
db #ff
clr_load_mem defb #1a,0 ;
defb #1b,0 ;
clr_load_mem1 defb #1c,0 ;
defb #1d,0 ;
defb #1e,0 ;
clr_load_mem2 defb #1f,0 ;
defb #26,#ff ;
defb #28,32-1 ;
defb #27,%00000100
db #ff
gfx_copy db #1a,0
db #1b,0 ;#0210 - данные битмап
db #1c,download_page
db #1d,0
db #1e,0
db #1f,Gfx_vid_page
gfx_copy_w db high DMALEN,0
gfx_copy_h db high DMANUM,0
gfx_copy_type db #27,DMA_RAM + DMA_DALGN;+DMA_ASZ
db #ff
view_image_pals
db #1a,0
db #1b,0
db #1c,download_page
db #1d,0
view_image_pals_vpal_adr
db #1e,1
db #1f,0
view_image_pals_vpal
db #26,#1f
db #28,0
db #27,#84
db #ff
clr_gfx_screen
defb #1a,0 ;
defb #1b,0 ;
defb #1c,Gfx_vid_page ;
defb #1d,0 ;
defb #1e,0 ;
defb #1f,Gfx_vid_page ;
defb #26,#ff ;
defb #28,#ff ;
defb #27,%00000100
db #ff
clr_analizator defb #1a,low analizator_screen_adr ;
defb #1b,high analizator_screen_adr ;
defb #1c,Vid_page+9
defb #1d,low analizator_screen_adr ;
defb #1e,high analizator_screen_adr ;
defb #1f,Vid_page+9
defb high DMALEN ,#f ;
defb high DMANUM,3-1 ;
defb #27,DMA_FILL+DMA_ASZ+DMA_DALGN
db #ff
clr_text_screen
defb #1a,0 ;
defb #1b,0 ;
defb #1c,Text_page ;
defb #1d,0 ;
defb #1e,0 ;
defb #1f,Text_page ;
defb #26,#ff ;
defb #28,32-1 ;
defb #27,%00000100
db #ff
link_page_copy db #1a,0
db #1b,0
db #1c,download_page
db #1d,0
db #1e,0
db #1f,list_ram_page
db #26,#ff
db #28,32-1
db #27,DMA_RAM
db #ff
cursor_copy db #1a,low cursor_adr
db #1b,high cursor_adr
db #1c,cursor_page
db #1d,0
db #1e,0
db #1f,Sprite_page
db #26,32/4-1
db #28,16-1
db #27,DMA_RAM + DMA_DALGN
db #ff
menu_copy db #1a,0
db #1b,0
db #1c,menu_gfx_page
db #1d,0
db #1e,0
db #1f,Vid_page
db #26,320/2-1
db #28,32-1
db #27,DMA_RAM + DMA_DALGN +DMA_ASZ
db #ff
splash_copy db #1a,0
db #1b,0
db #1c,splash_gfx_page
db #1d,40
db #1e,0
db #1f,Vid_page+2
db #26,240/2-1
db #28,109-1
db #27,DMA_RAM + DMA_DALGN +DMA_ASZ
db #ff
status_copy db #1a,0
db #1b,#28
db #1c,menu_gfx_page
db #1d,0
db #1e,#3e-2
db #1f,Vid_page+8
db #26,320/2-1
db #28,9-1
db #27,DMA_RAM + DMA_DALGN +DMA_ASZ
db #ff
status_icon_copy
db #1a,0
db #1b,0
db #1c,2
db #1d,4
db #1e,#3e-2
db #1f,Vid_page+8
db #26,10/2-1
db #28,9-1
db #27,DMA_BLT + DMA_DALGN +DMA_ASZ
db #ff
cancel_icon_copy
db #1a,low cancel_icon
db #1b,high cancel_icon
db #1c,2
db #1d,4+4+128
db #1e,#3e-2
db #1f,Vid_page+8
db #26,8/2-1
db #28,7-1
db #27,DMA_BLT + DMA_DALGN +DMA_ASZ
db #ff
sprites db #1a,low spr_db
db #1b,high spr_db
db #1c,2
db #1d,0
db #1e,2
db #1f,0
db #26,#ff
db #28,0
db #27,DMA_RAM_SFILE
db #ff
all_pals
db #1a,low all_pal_bin
db #1b,high all_pal_bin
db #1c,2
db #1d,0
db #1e,0
db #1f,0
db #26,(256/2)-1
db #28,0
db #27,#84
db #ff
zx_pals
; db #1a,low all_pal_bin
; db #1b,high all_pal_bin
; db #1c,2
db #1d,#e0
db #1e,1
db #1f,0
db #26,#0f
db #28,0
db #27,#84
db #ff
text_up_copy db #1a,0
db #1b,window_start_Y+2
db #1c,Text_page
db #1d,0
db #1e,window_start_Y
db #1f,Text_page
db #26,#80-1
db #28,window_height*2-1 ;-1
db #27,DMA_RAM
db #ff
text_down_copy db #1a,0 ;low #c000+window_height*2*256
db #1c,Text_page
db #1d,0 ;low #c200+window_height*2*256
db #1f,Text_page
db #26,#7f
db #28,0
db #ff
/*include "../includes.asm"
include "../tsconfig.asm"*/
include "includes.asm"
include "tsconfig.asm"
mouse_button db 0
zifi_ready db 0
/*
D0 - левая кнопка
D1 - правая кнопка
D2 - средняя кнопка
*/
mouse_x dw 0
mouse_y dw 0
; l - X, h- Y
mouse_map dw 0
mouse_switch db 0
ALIGN 2
spr_db
DB 0
DB %01000000 ; leap
DB 0
DB %00010000
DB 0
DB %11100000
DB 0
DB %01000000 ; leap
DB 0
DB %00010000
DB 0
DB %11100000
mouse_spr
db 0 ;y
db SP_SIZE16+SP_ACT
db #0 ;x
db SP_SIZE16
db #0
db Mouse_pal_num+#00
/*
; show text
txt_spr
db 240-96-16;+16 ;y
db SP_SIZE16+SP_ACT
db #0 ;x
db SP_SIZE64
db #00
db #ef
db 240-96-16;+16 ;y
db SP_SIZE16+SP_ACT
db #0+64 ;x
db SP_SIZE64
db #08
db #ef
*/
DB 0 ;exit
DB %01000000 ; leap
DB 0
DB %00010000
DB 0
DB %11100000
spr_db_end
; init esp8266
cmd_at: defb "ATE0",13,10,0
cmd_gmr: defb "AT+GMR",13,10,0 ; 3. AT+GMR – View version info
;This AT command is used to check the version of AT commands and SDK that you are using, the type of which is "executed".
cmd_uart db "AT+UART_CUR=115200,8,1,0,3",13,10,0
cmd_cwmode: defb "AT+CWMODE_DEF=1",13,10,0 ; Wi-Fi default mode(sta/AP/sta+AP) Save to Flash
cmd_cipmux db "AT+CIPMUX=0",13,10,0 ; Выбрать режим одиночного или множественных подключений
cmd_cwautoconn: defb "AT+CWAUTOCONN=0",13,10,0 ; Connect to AP automatically when power on
cmd_cwqap: defb "AT+CWQAP",13,10,0 ; Disconnect from AP
cmd_cwlap: defb "AT+CWLAP",13,10,0 ; Lists available APs
cmd_cwjap: defb "AT+CWJAP_CUR=",0x22 ; Connect to AP, won’t save to Flash
cmd_cwjap_pass ds 100
; defb "wifitest123" ; SSID
; defb 0x22,0x2c,0x22
; defb "ZXSpectrumForeverHelloEverybody321" ; password
cmd_cipsta: defb "AT+CIPSTA?",13,10,0 ; AT+CIPSTA – Set IP address of station
cmd_cipclose db "AT+CIPCLOSE",13,10,0
; load data from server
cmd_conn2site defb "AT+CIPSTART="
;cmd_conn2site_task_num db "0,"
db 0x22
cmd_conn2site_type db "TCP" ; patched to "SSL" for https:// by parse_url
db 0x22,",",0x22
;AT+CIPSTART – Establish TCP connection or UDP transmission
;AT+CIPMODE – Set transfer mode ------!!!------
; UART-WiFi passthrough mode (transparent transmission) can only be enabled in TCP single
; connection mode or UDP of which remote IP and port won’t change (parameter is 0
; when using command “AT+CIPSTART” to create a UDP transmission) .
cmd_conn2site_adr ds #40 ; defb "zxart.ee" ; site
; defb 0x22,",80",13,10
cmd_cipsend db "AT+CIPSEND="
;download_task_num db "0,"
url_len ds 6
db 0
str_ok: defb "OK",13,0
str_already_con:defb "ALREADY CONNECT",13,0
str_error: defb "ERROR",13,0
str_fail: defb "FAIL",13,0
str_send_ok: defb "SEND OK",13,0
str_ipd db "+IPD,",0
current_load_page db 0
http_part1 db " HTTP/1.0",13,10 ;size=123
db "Host: " ;zxart.ee",13,10
http_part2 db "User-Agent: ZiFi (ZX Evo)",13,10 ; show off ;)
db "Accept: */*",13,10
db "Connection: close",13,10,13,10
http_part3
zip_url_buffer db "http://zifi.vtrd.in/unzipremote.php?f="
zip_url_buffer_data ds 256
list_search_db
db "Search:"
dup 5
db #0a
edup
list_search_db_end
align 256
all_pal_bin incbin "_spg/menu.tga.pal"
incbin "_spg/pal_zx.tga.pal"
search_url ds 64
align 256
mouse_step ds 256
parsed_link ds #080
modem_command ds 256+128
current_paging_url ds 150
sd_init
call init_sd_card
CALL DOS_SWP; DEPACK Driver
CALL DEV_INI
JP NZ,ER0
CALL HDD
JP NZ,ER1
CALL SETROOT; SET ROOT DIR
jp sd_exit
/*
[17:37:51] Koshi: ну вначале зайди в папко
[17:37:55] Koshi: где файло настроек
[17:38:02] Koshi: чтобы зайти в папко ннадо сделать
[17:38:08] Koshi: LD HL,DIR1
CALL FENTRY
[17:38:13] Koshi: затем CALL SETDIR
[17:38:35] Koshi: затем запустить LD HL,FILE_INI:CALL FENTRY
[17:38:40] Koshi: и тока потом уже можна LOAD512
[17:38:48] Koshi: если конечно файл нашелся
[17:39:23] Koshi: FENTRY ищет файлы/каталоги
[17:39:29] Koshi: и выдает длину оных в ответ
[17:39:43] Koshi: плюс позиционирует на них
[17:39:58] Koshi: но LOAD512 сразу после FENTRY, када искали дир
[17:40:03] Koshi: буит читать САМ дир
[17:40:10] Koshi: аля содержимое низкоуровневое дира
[17:40:20] Koshi: чтобы перейти на дир
[17:40:23] Koshi: надо сетнуть его
[17:40:26] Koshi: и потом уже в НЕМ
[17:40:28] Koshi: искать файло
[17:40:34] Koshi: по то му же FENTRY
*/
; on_int_dma/off_int_dma bracket EVERY SD operation (init_sd_card at
; the start, sd_exit at the end -- see their own call sites) -- but
; save_mode alone doesn't cover everything: int_main's pt_play (~line
; 2350) is gated by its OWN SEPARATE music_sw flag, not save_mode, and
; unconditionally repages PAGE0/PAGE1/PAGE3 for the music player
; (set_music_pages_lite) on every single interrupt a track is playing.
; PAGE0 changing mid-execution while our SD driver code is running
; FROM slot 0 (page #0F) crashes the instant the interrupt returns;
; PAGE3 changing mid-LOAD512/SAVE512 silently swaps the transfer's
; real source/dest for whatever the music player last pointed it at.
; wrap_load512/wrap_save512's own di/ei (zc_sd_driver.asm) only
; protects against the CRASH by blocking ALL interrupts for the whole
; multi-block transfer -- but that STARVES pt_play for however long
; the transfer takes (can be several video frames for a large file),
; which is exactly why music glitches/goes to noise and the screen
; flickers when switching tracks during any SD activity: pt_play
; simply never gets to run its own per-frame update while we're mid-
; transfer, then resumes abruptly once di/ei lets it back in. Clearing
; music_sw here too (not just save_mode) means pt_play's own "call
; nz,pt_play" check skips it ENTIRELY during SD operations -- a clean
; pause instead of a starve-then-jump-back-in glitch -- confirmed as
; the real cause of "noise mixed with melody" persisting even after
; the SAVE512 addressing fix (which was a real, separate bug, but not
; the only one). See [[project-zifi-custom-sd-driver]].
; music_sw_saved: off_int_dma saves music_sw's real value here (which
; may already be 0 if the user paused music) before forcing it off, so
; on_int_dma can RESTORE that instead of blindly forcing it back to 1
; -- otherwise an SD operation happening while music is paused would
; incorrectly un-pause it.
music_sw_saved db 0
on_int_dma ld a,1
ld (save_mode+1),a
ld a,(music_sw_saved)
ld (music_sw+1),a
ret
off_int_dma ld a,(music_sw+1)
ld (music_sw_saved),a
xor a
ld (save_mode+1),a
ld (music_sw+1),a
ret
save_downloaded_file ; ld de,10884 ; file lenght
call init_sd_card
ld de,disk_icon
call set_icon
ld ix,read_threads
ld de,(ix+thread.full_len)
ld hl,FILE+1
ld (hl),e
inc hl
ld (hl),d
inc hl
ld a,(ix+thread.full_len_high)
ld (hl),a
; ld (save_over_64+1),a
; ld c,a
ex de,hl
ld d,0
ld e,a
call DEL512 ;расчёт длины в секторах: i:[DE,HL]/512
/*
ld a,e
or a
jr z,1f
inc d
1 bit 0,d
jr z,1f
inc d
1 srl c
rr d ; d= sectors (512bytes)
*/
push hl
;Create File (flag,size,name,0):
LD HL,FILE
CALL MKFILE
pop bc ; bc= num sectors
JP Z,1f
;File Creation Failed
/*
[15:50:27] Way Be: если файло есть, то ;File Creation Failed получаем, так?
[15:50:55] Koshi: и смотрим в A код ошибке
[15:51:01] Koshi: если 3 - то имя уже занято
;i: HL - flag(1),ln(4),name(1-255),0
; NZ - ERROR (NO ENOUGHT SPACE)
; A: 1 - ln not valid
; 2 - index fatality
; 3 - ln already exists
; 255 - unknown error
; Z - SUCCESS
MKFILE EQU CORE+57
*/
cp 3
jr z,2f
cp 4
jr z,2f
LD A,5:OUT (254),a
jr 2f
1
; check size>64kb
/*
save_over_64 ld a,0
or a
jr z,save_64
*/
ld a,b
or a
jr z,save_64
;Save data into new file >128kb:
ld a,c
push af
ld c,(ix+thread.page)
ld hl,(ix+thread.adress)
ld a,b
3 push af
ld b,#80
call SAVE512
ld b,#80
call SAVE512
pop af
dec a
jr nz,3b
pop af
or a
jr z,3f
ld b,a
jr 2f
;Save data into new file <128kb:
save_64 ld b,c
ld c,(ix+thread.page)
ld hl,(ix+thread.adress)
2 call SAVE512
3
/*
[11:50:29] Koshi: просто пишешь до посинения
[11:50:35] Koshi: пока цепочка не кончиццо
[11:50:59] Koshi: када цепочки конец - сейв512 и лоад512 выдадут в А=#0F
*/
ld hl,status_copy ; clear statusbar gfx
call set_ports
jp sd_exit
DEL512 ;i:[DE,HL]/512
LD A,L,L,H,H,E,E,D,D,0
LD BC,1:OR A:CALL NZ,ADD4B
LD A,2
DELITX2 ;i:[DE,HL]/A
; A - Power of Two
; o:[DE,HL]
CP 2:RET C
LD C,0
SRL A
L33T SRL D:RR E,H,L,C
SRL A:JR NC,L33T
LD A,C:OR A:RET Z
LD BC,1:CALL ADD4B
RET
ADD4B ADD HL,BC:RET NC:INC DE
RET
; читаем настройки:
load_ini
call init_sd_card
LD HL,DIR_zifi
CALL FENTRY
CALL SETDIR
LD HL,FILE_INI
CALL FENTRY
JP Z,ini_not_found
LD C,download_page ; page ini
LD HL,#4000 ; LOAD512 uses the SAME slot-1/direct-
; address convention as SAVE512 -- see
; zc_sd_driver_body.asm's core_load512
; comment for why this changed from
; #0000/PAGE3
LD B,#32
CALL LOAD512
CALL SETROOT; возвращаемся в коневой
call sd_exit
parse_ini ld a,download_page
call set_page1
ld hl,#4000
IF !cable_zifi
ld de,ini_db
call cp_ini
push hl
call find_next_line
call cp_ini
ld (pass_ini+1),hl
ssid_ini pop hl
ld de,cmd_cwjap_pass
call copy_ini
ex de,hl
ld bc,#222c
ld (hl),b
inc hl
ld (hl),c
inc hl
ld (hl),b
inc hl
ex de,hl
pass_ini ld hl,0
call copy_ini
ex de,hl
ld (hl),#22
inc hl
ld (hl),13
inc hl
ld (hl),10
inc hl
ld (hl),13
inc hl
ld (hl),10
inc hl
ld (hl),0
ex de,hl
call find_next_line
ENDIF
IF cable_zifi
2 ld a,(hl)
cp "t"
jr z,1f
inc hl
jr 2b
1
ENDIF
ld de,ini_db_time
call cp_ini
cp "n"
ret z ; time will not updated
ld (update_rtc_sw+1),a ; set on update time
cp "0"
jr c,1f
cp "9"
jr c,2f
1 cp "+" ; set +/- gmt time
jr nz,gmt_minus
inc hl
2 call get_gmt
ld (gmt_time+1),a
ret
gmt_minus cp "-"
ret nz
inc hl
call get_gmt
neg
ld (gmt_time+1),a
ret
get_gmt ld b,(hl)
inc hl
ld a,(hl)
cp #2f
jr c,1f
ld a,b ; tens digit (first char) *10 ...
and #0f
add a
ld c,a
add a
add a
add c
ld c,a
ld a,(hl) ; ... + ones digit (second char)
and #0f
add c
ret
1 ld a,b
and #0f
ret
find_next_line
ld a,(hl)
cp #0d+1
jr c,1f
inc hl
jr find_next_line
1 inc hl
ld a,(hl)
cp #0d+1
ret nc
inc hl
ret
ini_not_found
call set_Textpage
ld hl,ini_not_found_msg
ld b,1
call zifi_echo
jr $
ini_not_found_msg db ' Error: zifi.ini not found',0,0
/*
читаем настройки:
LD HL,DIR_INI
CALL FENTRY
CALL SETDIR
LD HL,FILE_INI
CALL FENTRY
LD C,0
LD HL,0
LD B,X
CALL LOAD512
CALL SETROOT; возвращаемся в коневой
*/
;CALL VYGREB; Выгребаем каталог, чисто по приколу
;LD HL,FILENAM ; ищем файл
;CALL FENTRY:JP Z,ER2
;LD HL,#1000,C,#02 ; читаем файл (1 блок, 512 байт)
;LD B,1:CALL LOAD512
; переходим в папку downloads/
set_download_dir
call init_sd_card
call SETROOT
LD HL,DIR_download
CALL FENTRY
jr nz,current_dir ; Set DIR found by FENTRY active
LD HL,DIR_download+1
CALL MKDIR
JR Z,set_download_dir
JP ER3
current_dir call SETDIR ; we in "download" dir
LD HL,DIR_date ; check current date dir
CALL FENTRY
jr nz,sd_exit_date ; Set DIR found by FENTRY active
LD HL,DIR_date+1
CALL MKDIR
JR Z,current_dir
jr sd_exit
init_sd_card call off_int_dma
ld a,sd_driver_page
jp set_page0
sd_exit_date call SETDIR
sd_exit call on_int_dma
xor a
jp set_page0
; Standard ESP-AT SNTP commands (work on stock ESP-AT firmware, not just ours):
; AT+CIPSNTPCFG=1,0,"pool.ntp.org" - enable SNTP, UTC, one public server
; AT+CIPSNTPTIME? -> +CIPSNTPTIME:Www Mmm dd hh:mm:ss yyyy
; The reply is UTC asctime() text; gmt_time (below) applies the "time:" offset
; from zifi.ini same as before. SNTP syncs in the background after CFG, so
; CIPSNTPTIME? may still report the 1970 epoch placeholder for a moment -
; sntp_outer_left bounds how long we wait for a real value before giving up.
; update_rtc_sw/gmt_time are patched by parse_ini from the "time:" line in zifi.ini.
update_rtc_sw ld a,0 ; do we need to sync the RTC at all? (patched: 0 = "none")
cmd_sntp_cfg db 'AT+CIPSNTPCFG=1,0,"pool.ntp.org"',13,10,0
cmd_sntp_time db "AT+CIPSNTPTIME?",13,10,0
str_sntp_time db "+CIPSNTPTIME:",0
str_epoch_year db "1970"
sntp_outer_left db 0
sntp_reply_left db 0
month_names db "JanFebMarAprMayJunJulAugSepOctNovDec"
; Five bounded attempts. On final failure CF=1; caller deliberately falls
; back to rtc_read_date so downloads still work with no network time.
ntp_sync_rtc ld b,5
.retry push bc
call ntp_sync_rtc_once
pop bc
ret nc
djnz .retry
scf
ret
ntp_sync_rtc_once
call clear_input_fifo ; drop stale bytes before reading the reply
ld hl,cmd_sntp_cfg
call zifi_send_raw ; the bounded loop below owns reception
ld a,50 ; one-second, frame-based timeout for CIPSNTPCFG's OK
ld (sntp_reply_left),a
sntp_cfg_wait ld de,str_ok
call buffer_cmp
jr z,sntp_cfg_ok
call poll_input_fifo ; never call the blocking FIFO waiter while NTP is silent
call wait_frame
ld hl,sntp_reply_left
dec (hl)
jr nz,sntp_cfg_wait
scf
ret ; module didn't even accept the config - give up
sntp_cfg_ok
ld a,15
ld (sntp_outer_left),a
sntp_query call clear_input_fifo ; give the background sync a bit of real time each round
ld hl,cmd_sntp_time
call zifi_send_raw
ld a,50 ; one-second, frame-based timeout for THIS reply
ld (sntp_reply_left),a
sntp_query_wait ld de,str_sntp_time
call buffer_cmp
jr z,sntp_have_line
call poll_input_fifo
call wait_frame
ld hl,sntp_reply_left
dec (hl)
jr nz,sntp_query_wait
scf
ret ; module never answered the query at all - give up
sntp_have_line ; hl -> start of "Www Mmm dd hh:mm:ss yyyy" (buffer_cmp leaves it there)
push hl
ld de,20
add hl,de
ld de,str_epoch_year
ld b,4
sntp_epoch_chk ld a,(de)
cp (hl)
jr nz,sntp_real_time
inc hl
inc de
djnz sntp_epoch_chk
pop hl ; still the 1970 placeholder - SNTP hasn't synced yet
ld a,(sntp_outer_left)
dec a
ld (sntp_outer_left),a
jr z,sntp_no_sync
ld b,50 ; ~1s before asking again
call wait
jr sntp_query
sntp_no_sync scf
ret ; this attempt exhausted its bounded epoch wait
sntp_real_time pop hl ; hl -> string start, this is a real time now
push hl
call sntp_validate_reply
pop hl
jr nc,.valid
scf ; malformed reply: leave RTC untouched, let outer 5-attempt loop retry
ret
.valid
; register b
ld d,#0b
ld e,#82
call rtc_write_reg
; day of week (3-letter name, offset 0..2), 0=Sunday
push hl
push hl
pop ix
call day_of_week_index ; -> a = 0-6, 0=Sunday
pop hl
ld d,#06
ld e,a
call rtc_write_reg
; year (last 2 of the 4 digits, offset 20..23)
push hl
ld de,22
add hl,de
call code_time_rtc
ld d,#09
ld e,a
call rtc_write_reg
pop hl
; month (3-letter name, offset 4..6)
push hl
ld de,4
add hl,de
push hl
pop ix
call month_to_bcd ; -> a = BCD month
pop hl
ld d,#08
ld e,a
call rtc_write_reg
; date of the month (offset 8..9, space-padded for single digits - and0
; code_time_rtc's "and #0f" happens to treat a leading space as digit 0)
push hl
ld de,8
add hl,de
call code_time_rtc
ld d,#07
ld e,a
call rtc_write_reg
pop hl
; hours (offset 11..12), adjusted by the configured GMT offset
push hl
ld de,11
add hl,de
ld a,(hl)
and #0f
add a
ld e,a
add a
add a
add e
ld e,a
inc hl
ld a,(hl)
and #0f
add e
inc hl
ld e,0 ; calculate time with gmt offset, signed (-2 = #fe, +2 = 2 )
gmt_time add 0
jp m,3f
cp 24
jr c,1f
jr nc,1f
add 24
jr 2f
3 add 24
1 cp 24
jr c,2f
sub 24
2
4 cp 10
jr c,1f
sub 10
inc e
jr 4b
1 or a
rl e
rl e
rl e
rl e
or e
ld d,#04
ld e,a
call rtc_write_reg
pop hl
; minutes (offset 14..15)
push hl
ld de,14
add hl,de
call code_time_rtc
ld d,#02
ld e,a
call rtc_write_reg
pop hl
; seconds (offset 17..18)
push hl
ld de,17
add hl,de
call code_time_rtc
ld d,#00
ld e,a
call rtc_write_reg
pop hl
; register b
ld d,#0b
ld e,#02
call rtc_write_reg
ld hl,ntp_synced_msg
ld b,1
call zifi_echo
xor a ; NC = NTP date was written to RTC
ret
; Validate the complete ESP-AT asctime() payload before changing the RTC.
; This rejects partial/garbled FIFO replies such as a year "20F0". A bad
; reply is retryable; it must never turn into a believable but wrong folder.
; in: HL -> "Www Mmm dd hh:mm:ss yyyy"; out: NC = valid, C = invalid.
sntp_validate_reply
push hl
; Exact day-of-week and month names.
push hl
pop ix
call day_of_week_index
jr c,.bad
pop hl
push hl
ld de,4
add hl,de
push hl
pop ix
call month_to_bcd
jr c,.bad
pop hl
; Day: a space is allowed only for 1..9, otherwise it is 01..31.
push hl
ld de,8
add hl,de
call sntp_day_bcd
jr c,.bad
cp #01
jr c,.bad
cp #32
jr nc,.bad
pop hl
; Hours/minutes/seconds must be strict decimal pairs in their ranges.
push hl
ld de,11
add hl,de
call sntp_bcd2
jr c,.bad
cp #24
jr nc,.bad
pop hl
push hl
ld de,14
add hl,de
call sntp_bcd2
jr c,.bad
cp #60
jr nc,.bad
pop hl
push hl
ld de,17
add hl,de
call sntp_bcd2
jr c,.bad
cp #60
jr nc,.bad
pop hl
; RTC holds a two-digit year, but accept only a real 20xx date (2020-2099).
push hl
ld de,20
add hl,de
ld a,(hl)
cp "2"
jr nz,.bad
inc hl
ld a,(hl)
cp "0"
jr nz,.bad
inc hl
call sntp_bcd2
jr c,.bad
cp #20
jr c,.bad
pop hl
or a
ret
.bad pop hl
scf
ret
; Strict decimal pair at HL -> BCD. HL is left after the two characters.
sntp_bcd2 ld a,(hl)
sub "0"
jr c,.bad
cp 10
jr nc,.bad
rlca
rlca
rlca
rlca
ld b,a
inc hl
ld a,(hl)
sub "0"
jr c,.bad
cp 10
jr nc,.bad
or b
or a
ret
.bad scf
ret
; Day accepts the ESP's space-padded single-digit form (" 5") too.
sntp_day_bcd ld a,(hl)
cp " "
jr nz,sntp_bcd2
inc hl
ld a,(hl)
sub "1"
jr c,.bad
cp 9
jr nc,.bad
inc a
or a
ret
.bad scf
ret
; in: ix -> 3-letter month name (e.g. from CIPSNTPTIME's reply)
; out: a = BCD month 01-12; C set if the name is not an English month.
month_to_bcd ld hl,month_names
ld c,1
mtb_loop ld a,(ix+0)
cp (hl)
jr nz,mtb_next
inc hl
ld a,(ix+1)
cp (hl)
jr nz,mtb_rewind1
inc hl
ld a,(ix+2)
cp (hl)
jr z,mtb_found
dec hl
mtb_rewind1 dec hl
mtb_next ld de,3
add hl,de
ld a,c
cp 12
jr z,mtb_notfound
inc c
jr mtb_loop
mtb_notfound scf
ret
mtb_found ld a,c
cp 10
jr c,mtb_done
sub 10
add a,#10
mtb_done or a
ret
; in: ix -> 3-letter day-of-week name (e.g. from CIPSNTPTIME's reply)
; out: a = 0-6, 0=Sunday (clobbers af,bc,de,hl); C set if not found
day_of_week_index
ld hl,dow_names
ld c,0
dow_loop ld a,(ix+0)
cp (hl)
jr nz,dow_next
inc hl
ld a,(ix+1)
cp (hl)
jr nz,dow_rewind1
inc hl
ld a,(ix+2)
cp (hl)
jr z,dow_found
dec hl
dow_rewind1 dec hl
dow_next ld de,3
add hl,de
ld a,c
cp 6
jr z,dow_notfound
inc c
jr dow_loop
dow_notfound scf
ret
dow_found ld a,c
or a
ret
dow_names db "SunMonTueWedThuFriSat"
ntp_synced_msg db "Time synced via NTP.",0,0
; One RTC register per atomic section. The old single DI around the whole
; NTP conversion suppressed the raster chain and exposed splash_copy.
; D = CMOS register, E = value for write; clobbers AF/BC/DE.
rtc_write_reg di
ld bc,#eff7
in a,(c)
or #80
out (c),a
ld a,d
ld b,#df
out (c),a
ld a,e
ld b,#bf
out (c),a
ld bc,#eff7
in a,(c)
and #7f
out (c),a
ei
ret
; A = CMOS register, returns A = value; preserves DE, clobbers BC.
rtc_read_reg push de
di
ld e,a
ld bc,#eff7
in a,(c)
or #80
out (c),a
ld a,e
ld b,#df
out (c),a
ld b,#bf
in a,(c)
ld e,a
ld bc,#eff7
in a,(c)
and #7f
out (c),a
ld a,e
pop de
ei
ret
; Reads the current date straight back off the RTC chip into DIR_date, as
; "20YY_MM_DD" - used to name the downloads/ folder. Works regardless of
; whether "time:" is "none" or the NTP sync above failed: the chip keeps
; ticking on its own battery either way, so this is the one source of truth.
rtc_read_date
ld de,DIR_date+1
ld a,"2"
ld (de),a
inc de
ld a,"0"
ld (de),a
inc de
; year
ld a,#09
call rtc_read_reg
call bcd_to_ascii
ld a,"_"
ld (de),a
inc de
; month
ld a,#08
call rtc_read_reg
call bcd_to_ascii
ld a,"_"
ld (de),a
inc de
; date of the month
ld a,#07
call rtc_read_reg
call bcd_to_ascii
ret
bcd_to_ascii ; in: a = BCD byte, de = destination; writes 2 ASCII digits, advances de
push af
rra
rra
rra
rra
and #0f
add "0"
ld (de),a
inc de
pop af
and #0f
add "0"
ld (de),a
inc de
ret
code_time_rtc ld a,(hl)
and #0f
rla
rla
rla
rla
ld e,a
inc hl
ld a,(hl)
and #0f
or e
inc hl
ret
;---------------------------------------
/*
VYGREB LD DE,#8000
VYG CALL NXTETY:RET Z
LD A,D:CP #C0:RET NC
JR VYG
*/
;---------------------------------------
ER0 ;Device not found
; (SD Card NOT ready!)
LD A,1:OUT (254),a
JP sd_exit
;-------
ER1 ;FAT32 NOT FOUND
LD A,2:OUT (254),a
JP sd_exit
;-------
ER2 ;File NOT FOUND
LD A,3:OUT (254),a
JP sd_exit
;-------
ER3 ;Dir Creation Failed
LD A,4:OUT (254),a
JP sd_exit
;-------
ER4 ;File Creation Failed
/*
[15:50:27] Way Be: если файло есть, то ;File Creation Failed получаем, так?
[15:50:55] Koshi: и смотрим в A код ошибке
[15:51:01] Koshi: если 3 - то имя уже занято
*/
LD A,5:OUT (254),a
JP sd_exit
;---------------------------------------
/*
FILENAM DB #00; 0 - file, 1 - DIR
DB "WC_History.txt",0
*/
FILE DB #00; flag
; DW #1000,#0000;length - 4kb
DW #0000,#0000;length
FILE_NAME ds 48
db 0
/*
[14:12:36] Koshi: младший, старший вестимо
[14:12:42] Way Be: ок
[14:12:46 | Змінено в 14:12:49] Koshi: #0000 1000 = 4кб
[14:13:03] Koshi: в примере же написано
*/
FILE_INI DB #00; 0 - file, 1 - DIR
DB "zifi.ini",0
DIR_zifi DB #10
DB "zifi",0
DIR_download DB #10
DB "downloads",0
DIR_date DB #10
DB "00_00_0000",0
;---------------------------------------
CORE EQU #2002
DEV_INI EQU CORE+3
HDD EQU CORE+9
;-------
;i: CHL - Addres
; B - lenght (512b blocks)
;o: CHL - New Value
; A - EndOfChain (#0F)
LOAD512 EQU CORE+21
;i: CHL - Addres
; B - lenght
;o: CHL - New Value
; A - EndOfChain (#0F)
SAVE512 EQU CORE+24
DOS_SWP EQU CORE+27
;i: HL - flag(1),ln(4),name(1-255),0
; NZ - ERROR (NO ENOUGHT SPACE)
; A: 1 - ln not valid
; 2 - index fatality
; 3 - ln already exists
; 255 - unknown error
; Z - SUCCESS
MKFILE EQU CORE+57
;i: HL - DirName(1-255,0)
;o: NZ - ERROR
; A: 1 - ln not valid
; 2 - index fatality
; 3 - ln already exists
; 255 - unknown error
; Z - SUCCESS
MKDIR EQU CORE+60
;i: HL - flag(1),name(1-255),0
;o: Z - NOT FOUND
; NZ - FILE DELETED
DELFL EQU CORE+63
;i: HL - flag(1),oldname(1-255),0
; DE - newname(1-255),0
;o: Z - NOT FOUND
; NZ - SUCCESS
RENAM EQU CORE+66
;Search for entry in current DIR
;i: HL - flag(1),name(1-255),0
;o: Z - NOT FOUND
; NZ - [DE,HL] - file length
; SEEK0 is automatically called
FENTRY EQU CORE+78
;Seek/Skip N sectors
;i: B - Number of sectors to process
LOADNON EQU CORE+84
;GetNextEntryFromActiveDir
;i: DE - Addres
;o: DE - New Value
; Z - EndOfDir
; NZ - OK
;
;STRUCTURE:
;fclus(4),size(4),date(2),time(2),
;!flag(1),name(1-255),#00
NXTETY EQU CORE+87
;Set DIR found by ENTRY active
SETDIR EQU CORE+93
;Set ROOT DIR active
SETROOT EQU CORE+96
SEEK0 EQU CORE+99
zifi_command_reg equ #C7EF
zifi_error_reg equ #C7EF
zifi_data_reg equ #BFEF
zifi_input_fifo_status equ #C0EF
zifi_output_fifo_status equ #C1EF
cmd_clear_input_fifo equ 1
cmd_clear_output_fifo equ 2
struct thread
num byte ; num thread -1
len word ; current ipd lenght
adress word ; current adress
page byte ; current page
file_ext word ; file name adress
full_len word ; lenght of file
full_len_high byte ;
ends
read_threads thread;ds 6*5
db #ff
; modem_load_file's own private snapshot of load_ram_page, captured
; right before starting the actual network receive (zifi_get/psb_get)
; -- NOT the same as re-reading load_ram_page after the call returns.
; load_ram_page is a single shared global, written from several other
; places (catalog-link clicks, pagination, menu navigation -- see
; loadpage_after_link_list and the download_page writers). zifi_get can
; run for several seconds (WiFi connect/TLS handshake/HTTP wait, many
; wait_frame-yielded interrupt frames), during which the interrupt-
; driven UI can process a DIFFERENT click that overwrites load_ram_page
; before zifi_get returns. Re-reading load_ram_page at that point (the
; old code) stamps thread.page with whatever category was clicked LAST,
; not the one this download actually used. This is a real, still-latent
; hazard (kept as a defensive fix), but turned out NOT to be the cause
; of "every download saves as identical garbage" -- that bug was a
; stale IX left behind by MKFILE (see the wrap_* comment in
; zc_sd_driver.asm), which made save_64 read (ix+thread.page)/(ix+
; thread.adress) from the wrong memory entirely, regardless of what
; read_threads itself held. See [[project-zifi-custom-sd-driver]]
; (2026-09-09).
saved_thread_page db 0
init_zifi
call set_Textpage
ld bc,0xc7ef
ld de,0xfff1
out (c),e ;Set API mode 1
out (c),d ;Get Version
in a,(c)
cp 0xff
jp z,nozifi
ld a,0x01
out (c),a ;Clear RX FIFO
ld hl,cmd_at
call zifi_send
;ld hl,cmd_uart
; call zifi_send
ld hl,cmd_gmr
call zifi_send_echo
ld hl,cmd_cwmode
call zifi_send
ld hl,cmd_cwautoconn
call zifi_send
ld hl,cmd_cipmux
call zifi_send
; ld hl,cmd_cwqap ; Disconnect from AP
; call zifi_send
; ld b,25
; call wait
; call zifi_check_receive_command
; ret
ld a,wifi_connect_retries_max
ld (wifi_connect_retries_left),a
; wifi_connect_retry: (re)send AT+CWJAP_CUR and wait for "OK" -- up to
; wifi_connect_quanta quanta (~256 frames/quantum, ~5s each) per
; attempt, up to wifi_connect_retries_max attempts total. Was an
; unconditional "jr nz,2b" with NO timeout at all -- a real ESP module
; that never answers (bad credentials, out of range, module wedged)
; hung here forever with zero feedback. See [[project-zifi-custom-sd-driver]].
wifi_connect_retry
ld hl,wifi_try_connect
ld b,2
call zifi_echo
ld hl,cmd_cwjap ; AT+CWJAP_CUR . Connect to AP, for current
call zifi_send
ld a,wifi_connect_quanta
ld (wifi_connect_quantum_left),a
wifi_connect_quantum
xor a
ld (wifi_connect_frame_left),a ; 0 wraps to 256 via dec below
wifi_connect_poll
; NOT "call zifi_check_receive_command" -- that goes through
; zifi_input_fifo_check, which BLOCKS INTERNALLY for up to
; 256 frames (its own "call wait_frame / dec e / jr nz,3b")
; whenever the FIFO is empty, only returning immediately
; when data IS already waiting. With nothing new arriving,
; nearly every call to it here would burn a full internal
; 256-frame wait BEFORE this loop's own frame counter even
; gets to react -- confirmed live (wifi_connect_frame_left
; stayed frozen for 6500+ frames: this loop's "iterations"
; were each secretly taking up to 256 frames on their own).
; It also drives zifi_input_fifo_check's OWN separate
; download-timeout/retry state (dl_timeout_left etc, meant
; for actual file downloads, not this WiFi-connect wait) --
; that's what caused the red border flashes. Doing our own
; quick, non-blocking FIFO peek here avoids both problems:
; only call the (bulk-read) fifo_inir when data is actually
; present, so it never falls into the internal wait either.
ld bc,zifi_input_fifo_status
in a,(c)
or a
jr z,wifi_connect_nodata
call fifo_inir
ld de,str_ok
call buffer_cmp
jr z,wifi_connect_ok
wifi_connect_nodata
call wait_frame
ld hl,wifi_connect_frame_left
dec (hl)
jr nz,wifi_connect_poll
ld a,(wifi_connect_quantum_left)
dec a
ld (wifi_connect_quantum_left),a
jr nz,wifi_connect_quantum
; this attempt's quanta are exhausted -- retry if any left
ld a,(wifi_connect_retries_left)
dec a
ld (wifi_connect_retries_left),a
jr nz,wifi_connect_retry
; out of retries -- give up with a real message instead of
; hanging silently forever
ld hl,wifi_connect_failed_msg
ld b,1
call zifi_echo
jr $
wifi_connect_ok
ld hl,wifi_connected
call zifi_echo
ld a,(update_rtc_sw+1) ; "time:" in zifi.ini not "none"?
or a
call nz,ntp_sync_rtc
call rtc_read_date ; name downloads/ from the RTC chip either way
call set_download_dir
ret
wifi_connect_quanta equ 4 ; ~5s/quantum * 4 = ~20s per attempt
wifi_connect_retries_max equ 5
wifi_connect_frame_left db 0
wifi_connect_quantum_left db 0
wifi_connect_retries_left db 0
wifi_connect_failed_msg db #0d,#0a,'WiFi connect failed',0,0
; ld b,25
; call wait
; ld hl,cmd_cipsta ; is Set IP address of station ?
; call zifi_send
; call zifi_check_receive_command
; ret
/*
ld b,25
call wait
ret
*/
zifi_error
ret
nozifi ld hl,conf_not_found_msg
ld b,1
call zifi_echo
jr $
conf_not_found_msg
db "Error: Please update TS Conf.",0,0
zifi_not_found_msg
db "Error: ZiFi ESP8266 module not found.",0,0
/*
Address Mode Name Description
0x00EF..0xBFEF R DR Data register (ZIFI or RS232).
Get byte from input FIFO.
Input FIFO must not be empty (xx_IFR > 0).
0x00EF..0xBFEF W DR Data register (ZIFI or RS232).
Put byte into output FIFO.
Output FIFO must not be full (xx_OFR > 0).
Address Mode Name Description
0xC0EF R ZF_IFR ZIFI Input FIFO Used Register. Switch DR to ZIFI FIFO.
0 - input FIFO is empty, 191 - input FIFO contain 191 or more bytes.
0xC1EF R ZF_OFR ZIFI Output FIFO Free Register. Switch DR to ZIFI FIFO.
0 - output FIFO is full, 191 - output FIFO free 191 or more bytes.
0xC2EF R RS_IFR RS232 Input FIFO Used Register. Switch DR to RS232 FIFO.
0 - input FIFO is empty, 191 - input FIFO contain 191 or more bytes.
0xC3EF R RS_OFR RS232 Output FIFO Free Register. Switch DR to RS232 FIFO.
0 - output FIFO is full, 191 - output FIFO free 191 or more bytes.
Address Mode Name Description
0xC7EF W CR Command register. Command set depends on API mode selected.
All mode commands:
Code Command Description
000000oi Clear ZIFI FIFOs
i: 1 - clear input ZIFI FIFO,
o: 1 - clear output ZIFI FIFO.
000001oi Clear RS232 FIFOs
i: 1 - clear input RS232 FIFO,
o: 1 - clear output RS232 FIFO.
11110mmm Set API mode or disable API:
0 API disabled.
1 transparent: all data is sent/received to/from external UART directly.
2..7 reserved.
11111111 Get Version Returns highest supported API version. ER=0xFF - no API available.
Address Mode Name Description
0xC7EF R ER Error register - command execution result code. Depends on command issued.
All mode responses:
Code Description
0x00 OK - no error.
0xFF REJ - command rejected.
--------------------------------------------------------------------------------
Until initialization sequence performed API is disabled and the only command recognized is 'Set API mode'.
Initialization sequence:
- Send 'Set API mode = 1' command,
- Send 'Get Version' command,
- Read highest supported API mode from ER,
- Select desired API mode.
zifi_init:
; select API mode 1
ld bc, 0xC7EF
ld a, 0xF1
out (c), a
; get highest supported API mode
ld a, 0xFF
out (c), a
in a, (c)
; select desired API mode, if need
ld a, mode ; possible values are 0xF2..0xF7
out (c), a
*/
;; PSB com driver ---------------------------------
IF cable_zifi
include "_rs232/sockets.mac"
psb_start jp init
psb_get jp get
init
;init uart
ld hl,1 ;BaudRate = 115200 / divfq;
call uart.SetBaud
;init uart
ld a,uart.WLSB1+uart.WLSB0 ;8 bit word, no parity
call uart.SetLineControl
ret
; BUFFER equ 0
; BUFFER_SIZE equ 1
GET_HDR dw 0
GET_HDR_LEN dw 0
GET_PAGE db 0
host_addr_len dw 0
host_addr dw 0
;in:
;a=page
;hl=get hdr
;out:
;a=0 - ok
;hl=len_l
;bc=len_h
get
ld (GET_HDR),hl
ld (GET_PAGE),a
;get host name
g1 ld a,(hl)
or a:jp z,get_err
cp 'H':jr z,get_h1
inc hl:jr g1
get_h1 inc hl
ld a,(hl):cp 'o':jr nz,g1:inc hl
ld a,(hl):cp 's':jr nz,g1:inc hl
ld a,(hl):cp 't':jr nz,g1:inc hl
ld a,(hl):cp ':':jr nz,g1:inc hl
ld a,(hl):cp ' ':jr nz,g1:inc hl
ld (host_addr),hl
ld bc,0
gh1 ld a,(hl):cp 13:jr z,ghe
cp ":":jr z,ghe
cp "/":jr z,ghe ;?
inc hl,bc:jr gh1
ghe ld (host_addr_len),bc
;get HDR len
g2 ld a,(hl)
or a:jr z,g3
inc hl:jr g2
g3 ld de,(GET_HDR):or a:sbc hl,de:ld (GET_HDR_LEN),hl
;gethostbyname
ld hl,(host_addr),bc,(host_addr_len)
call sockets.gethostbyname
or a:jp nz,get_err
ld (server_addr),hl,(server_addr+2),bc
;create socket
socket AF_INET,SOCK_STREAM,0
cp INVALID_SOCKET:jp z,get_err
ld (fd),a
;bind my socket
bind fd,my_addr
or a:jp nz,get_err
;connect to host
connect fd,server_addr
or a:jp nz,get_err
;send HTTP request
send fd,(GET_HDR),(GET_HDR_LEN)
or a:jr nz,get_err
ld ix,0 ;full pages got
ld hl,(zipd_adr+1) ; #c000 ----------- !!!!!!!!!! align 2 fix ------------------
set 7,h
set 6,h
xor a
ld (sockets.recv_skip_header+1),a
get_loop
ld a,(GET_PAGE)
call set_page3
ld de,#0000:ex de,hl:or a:sbc hl,de:ex de,hl ;de=len,hl=start
;recv data
; recv fd,BUFFER,BUFFER_SIZE
push hl
ld b,d,c,e
ld a,(fd)
call sockets.recv
pop hl
or a:jr nz,get_end
; ld a,b:or c:jr z,get_end
call view_progress_bar
add hl,bc
ld a,h
or a
jr nz,get_loop
ld hl,GET_PAGE:inc (hl)
ld hl,#c000
inc ixl
jr get_loop
get_end ;res 6,h:res 7,h
ld a,h
and #3f
ld h,a
ld de,0,b,0,c,ixl
srl c:rr d:rr e
srl c:rr d:rr e
add hl,de ;bc:hl=len
get_e ld a,(fd):cp #ff:jr z,noclose
push hl,bc
;close socket
close fd
pop bc,hl
noclose ld a,#ff,(fd),a
xor a
ret
get_err call get_e
inc a
ret
cable_cancel_download_ex
ld sp,#bfff
xor a
ld (uart.cable_cancel_download+1),a
ld (load_sw+1),a
close fd
call noclose
ld hl,status_copy ; clear statusbar gfx
call set_ports
jp main
;-----------------------------------------------------------
fd db #ff ;socket fd
my_addr db 0,0,0,0:dw 0 ;my ip+port
server_addr db 93,158,134,3:dw 80
;code
include "_rs232/uart.a80"
include "_rs232/sockets.a80"
; PSB com driver ---------------------
ENDIF
align 2
download_icon incbin "_spg/download.tga.pix"
disk_icon incbin "_spg/disk.tga.pix"
cancel_icon incbin "_spg/X.tga.pix"
highlight_colors_buff ds 80
link_adreses ds 101*6
align 256
output_buff ds #100
end
music_player equ #c000
music_player_init equ @music_player+3
music_player_play equ @music_player+5
music_player_mute equ @music_player+8
music_setup_vars equ music_player+#55
/*
; uni player
org #c000
music_player INCLUDE "_pt\ptx.asm"
music_player_init equ @music_player+3
music_player_play equ @music_player+5
music_player_mute equ @music_player+8
music_setup_vars equ music_player+#55
music_players_end
SAVEBIN "_spg/ptplay.bin",music_player, music_players_end-music_player
*/
LABELSLIST "_spg/zifi.l"
IF cable_zifi
SAVEBIN "_spg/zifi_rs.bin",start, end-start
ELSE
SAVEBIN "_spg/zifi.bin",start, end-start
ENDIF