Subversion Repositories NedoOS

Rev

Rev 2423 | Blame | Compare with Previous | Last modification | View Log | Download

  1.         DEVICE ZXSPECTRUM128
  2.         include "../_sdk/sys_h.asm"
  3.         include "playerdefs.asm"
  4.  
  5. NUM_PLAYERS = 6
  6. SFN_SIZE = 13
  7. FILE_DATA_SIZE = 52 ;keep in sync with getfiledataoffset
  8. FILE_DISPLAY_INFO_OFFSET = 0
  9. FILE_DISPLAY_INFO_SIZE = 38
  10. FILE_NAME_OFFSET = FILE_DISPLAY_INFO_OFFSET+FILE_DISPLAY_INFO_SIZE
  11. FILE_NAME_SIZE = SFN_SIZE
  12. FILE_ATTRIB_OFFSET = FILE_NAME_OFFSET+FILE_NAME_SIZE
  13. FILE_ATTRIB_SIZE = 1
  14. BROWSER_FILE_COUNT = 162
  15. PLAYLIST_FILE_COUNT = 40
  16. FILE_LINE_COUNT = 22
  17. FILES_WINDOW_X = 0
  18. FILE_ATTRIB_MUSIC = 255
  19. FILE_ATTRIB_PARENT_DIR = 0
  20. FILE_ATTRIB_DRIVE = 1
  21. FILE_ATTRIB_FOLDER = 2
  22. PLAYLIST_VERSION = 1
  23. STARTUP_CODE_ADDR = 0x8000
  24. STACK_ADDR = 0x4000
  25.  
  26.         org PROGSTART
  27.  
  28. mainbegin
  29.         ld sp,STACK_ADDR
  30.         OS_HIDEFROMPARENT
  31.         jp startplayer
  32.  
  33. drawprogress
  34.         ld a,(.pos)
  35.         inc a
  36.         ret z
  37. .color=$+1
  38.         ld de,COLOR_PANEL_DIR
  39.         OS_SETCOLOR
  40. .pos=$+1
  41.         ld de,0x0b08
  42.         OS_SETXY
  43. .counteraddr=$+1
  44.         ld hl,0
  45.         ld a,(hl)
  46.         ld (musicprogress),a
  47.         ld c,a
  48.         or a
  49.         jr z,.drawremaining
  50.         ld b,a
  51. .drawdoneloop
  52.         push bc
  53.         ld a,178
  54.         PRCHAR
  55.         pop bc
  56.         djnz .drawdoneloop
  57. .drawremaining
  58.         ld a,64
  59.         sub c
  60.         ret z
  61.         ld b,a
  62. .drawremainingloop
  63.         push bc
  64.         ld a,176
  65.         PRCHAR
  66.         pop bc
  67.         djnz .drawremainingloop
  68.         ret
  69.  
  70. drawprogressincremental
  71. ;out: a = number of ticks until the next draw
  72.         ld a,(drawprogress.pos)
  73.         inc a
  74.         ret z
  75.         ld hl,(drawprogress.counteraddr)
  76.         ld d,(hl)
  77.         ld hl,musicprogress
  78.         ld e,(hl)
  79.         ld a,d
  80.         sub e
  81.         ret z
  82.         ld (hl),d
  83.         push af
  84.         ld a,e
  85.         ld de,(drawprogress.pos)
  86.         add e
  87.         ld e,a
  88.         OS_SETXY
  89.         ld de,(drawprogress.color)
  90.         OS_SETCOLOR
  91.         pop bc
  92. .drawloop
  93.         push bc
  94.         ld a,178
  95.         PRCHAR
  96.         pop bc
  97.         djnz .drawloop
  98.         ld a,30
  99.         ret
  100.  
  101. drawprogresscallback
  102. ;out: zf=0 if ESC was pressed, zf=1 otherwise
  103. .func=$+1
  104.         call drawprogress
  105.         ld hl,drawprogressincremental
  106.         ld (.func),hl
  107.         OS_GETKEY
  108.         sub key_esc
  109.         cp 1
  110.         sbc a,a
  111.         ret
  112.  
  113. startplayer
  114.         ld hl,startupcode
  115.         ld de,STARTUP_CODE_ADDR
  116.         ld bc,startupcodesize
  117.         ldir
  118.         call startup
  119. ;load players from low memory
  120.         call loadplayers
  121.         jp nz,printerrorandexit
  122. ;       YIELDGETKEYLOOP
  123. ;init panels   
  124.         ld ix,browserpanel
  125.         call clearpanel
  126.         ld ix,playlistpanel
  127.         call clearpanel
  128.         or 255 ;set zf=0
  129.         call setcurrentpanel
  130.         ld de,defaultplaylistfilename
  131.         call loadplaylist
  132.         ld hl,mainmsgtable
  133.         ld (currentmsgtable),hl
  134.         call processcommandline
  135. playloop
  136. isplaying=$+1
  137.         ld a,0
  138.         or a
  139.         jr z,checkmsgs
  140.         call musicplay
  141.         call z,playnextfile
  142. checkmsgs
  143.         OS_GETKEY
  144.         call tolower
  145.         ld hl,playloop
  146.         push hl
  147. currentmsgtable=$+1
  148.         ld hl,mainmsgtable
  149.         ld de,3
  150.         ld b,(hl)
  151.         inc hl
  152. checkmsgloop
  153.         cp (hl)
  154.         jr z,processmsg
  155.         add hl,de
  156.         djnz checkmsgloop
  157.         ret
  158.  
  159. processmsg
  160.         inc hl
  161.         ld e,(hl)
  162.         inc hl
  163.         ld d,(hl)
  164.         ex de,hl
  165.         jp (hl)
  166.  
  167. printerrorandexit
  168.         call print_hl
  169.         ld hl,pressanykeystr
  170.         call print_hl
  171.         YIELDGETKEYLOOP
  172.         QUIT
  173.  
  174. processcommandline
  175.         ld hl,COMMANDLINE
  176.         call skipword_hl
  177.         call skipspaces_hl
  178.         ld a,(hl)
  179.         or a
  180.         call nz,setcurrentfolder
  181.         push hl
  182.         call changetocurrentfolder
  183.         call createfileslist
  184.         pop de
  185.         ld a,(de)
  186.         or a
  187.         call nz,findfile
  188.         ld (browserpanel.currentfileindex),a
  189.         push af
  190.         call drawui
  191.         pop af
  192.         call c,startplaying
  193.         ld hl,COMMANDLINE
  194.         ld (hl),'g'
  195.         inc hl
  196.         ld (hl),'p'
  197.         inc hl
  198.         ld (hl),0
  199.         ret
  200.  
  201. mainmsgtable
  202.         db (mainmsghandlers_end-mainmsghandlers_start)/3
  203. mainmsghandlers_start
  204.         db 0             : dw mainidle
  205.         db key_redraw    : dw redraw
  206.         db key_up        : dw goprevfile
  207.         db key_down      : dw gonextfile
  208.         db key_enter     : dw startplaying
  209.         db key_esc       : dw confirmplayerexit
  210.         db ' '           : dw addtoplaylist
  211.         db key_tab       : dw switchpanels
  212.         db key_backspace : dw clearplaylist
  213.         db key_home      : dw gotop
  214.         db key_end       : dw golastfile
  215.         db key_left      : dw gopageup
  216.         db key_right     : dw gopagedown
  217.         db key_pgup      : dw gopageup
  218.         db key_pgdown    : dw gopagedown
  219.         db 's'           : dw onhotkeyS
  220.         db 'o'           : dw onhotkeyO
  221. mainmsghandlers_end
  222.  
  223. playmsgtable
  224.         db (playmsghandlers_end-playmsghandlers_start)/3
  225. playmsghandlers_start
  226.         db 0             : dw playnokeypressed
  227.         db key_redraw    : dw redraw
  228.         db ' '           : dw playnextfile
  229.         db key_esc       : dw stopplaying
  230. playmsghandlers_end
  231.  
  232. mainidle
  233.         YIELD
  234.         YIELD
  235.         YIELD
  236.         YIELD
  237.         ld a,(COMMANDLINE+2)
  238.         or a
  239.         ret z
  240. gotcommandline
  241.         call turnturboon
  242.         or 255 ;set zf=0
  243.         call setcurrentpanel
  244.         jp processcommandline
  245.  
  246. playnokeypressed
  247. .progressupdatecounter=$+1
  248.         ld a,0
  249.         dec a
  250.         call z,drawprogressincremental
  251.         ld (.progressupdatecounter),a
  252. .playtimeupdatecounter=$+1
  253.         ld a,1
  254.         dec a
  255.         call z,drawplaytimeincremental
  256.         ld (.playtimeupdatecounter),a
  257.         ld a,(COMMANDLINE+2)
  258.         or a
  259.         ret z
  260.         call stopplaying
  261.         jr gotcommandline
  262.  
  263. gotop   ld ix,(currentpaneladdr)
  264.         xor a
  265.         ld (ix+PANEL.currentfileindex),a
  266.         ld (ix+PANEL.firstfiletoshow),a
  267.         jp drawcurrentpanelfilelist
  268.  
  269. markplaylistdirty
  270.         ld a,255
  271.         ld (playlistchanged),a
  272.         ret
  273.  
  274. clearplaylist
  275.         call markplaylistdirty
  276.         ld ix,playlistpanel
  277.         call clearpanel
  278.         jp drawplaylistwindow
  279.  
  280. setnextfileindexandwrap
  281.         ld ix,(currentpaneladdr)
  282.         call setnextfileindex
  283.         ret c
  284.         ld (ix+PANEL.currentfileindex),0
  285.         ld (ix+PANEL.firstfiletoshow),0
  286.         ret
  287.  
  288. playnextfile
  289.         call setnextfileindexandwrap
  290.         jp c,startplaying
  291.         ld hl,(currentpaneladdr)
  292.         ld de,PANEL.fileslist+FILE_ATTRIB_OFFSET
  293.         add hl,de
  294.         ld e,FILE_DATA_SIZE
  295. .wraploop
  296.         ld a,(hl)
  297.         cp FILE_ATTRIB_MUSIC
  298.         jp z,startplaying
  299.         add hl,de
  300.         inc (ix+PANEL.currentfileindex)
  301.         jr .wraploop
  302.  
  303. switchpanels
  304.         ld a,(browserpanel.isinactive)
  305.         or a
  306. setcurrentpanel
  307.         ld a,255
  308.         ld (browserpanel.isinactive),a
  309.         ld (playlistpanel.isinactive),a
  310.         call nz,getbrowserpanelparams
  311.         call z,getplaylistpanelparams
  312.         ld (currentpaneladdr),ix
  313.         ld (currentpanelpos),de
  314.         ld (ix+PANEL.isinactive),0
  315.         call drawbrowserfileslist
  316.         jp drawplaylistfileslist
  317.  
  318. addtoplaylist
  319.         call markplaylistdirty
  320.         ld a,(browserpanel.isinactive)
  321.         or a
  322.         jr nz,removefromplaylist
  323.         ld hl,currentfolder
  324.         ld de,fullpathbuffer
  325.         call strcopy_hltode
  326.         ld a,'/'
  327.         ld (de),a
  328.         inc de
  329.         push de
  330.         ld a,(browserpanel.currentfileindex)
  331.         call getfiledataoffset
  332.         ld de,browserpanel.fileslist+FILE_ATTRIB_OFFSET
  333.         add hl,de
  334.         ld a,(hl)
  335.         ld de,FILE_NAME_OFFSET-FILE_ATTRIB_OFFSET
  336.         add hl,de
  337.         pop de
  338.         cp FILE_ATTRIB_MUSIC
  339.         ret nz
  340.         call strcopy_hltode
  341.         ld hl,fullpathbuffer+FILE_DATA_SIZE-2
  342.         sub hl,de
  343.         ret c
  344.         jr z,skippadding
  345.         ld bc,hl
  346.         ld hl,de
  347.         inc de
  348.         ldir
  349.         dec de
  350. skippadding
  351.         inc de
  352.         ld a,255
  353.         ld (de),a
  354.         ld hl,playlistpanel.filecount
  355.         ld a,(hl)
  356.         cp PLAYLIST_FILE_COUNT
  357.         ret nc
  358.         inc (hl)
  359.         call getfiledataoffset
  360.         ld de,playlistpanel.fileslist
  361.         add hl,de
  362.         ex de,hl
  363.         ld hl,fullpathbuffer
  364.         ld bc,FILE_DATA_SIZE
  365.         ldir
  366.         jp drawplaylistfileslist
  367.  
  368. removefromplaylist
  369.         ld a,(playlistpanel.filecount)
  370.         or a
  371.         ret z
  372.         dec a
  373.         jp z,clearplaylist
  374.         ld (playlistpanel.filecount),a
  375.         ld b,a
  376.         ld a,(playlistpanel.currentfileindex)
  377.         cp b
  378.         jr nz,.movetail
  379.         dec a
  380.         ld (playlistpanel.currentfileindex),a
  381.         jp drawplaylistwindow
  382. .movetail
  383.         call getfiledataoffset
  384.         ld de,playlistpanel.fileslist
  385.         add hl,de
  386.         ex de,hl
  387.         ld hl,playlistpanel.fileslist+FILE_DATA_SIZE*(PLAYLIST_FILE_COUNT-1)
  388.         sub hl,de
  389.         ld bc,hl
  390.         ld hl,FILE_DATA_SIZE
  391.         add hl,de
  392.         ldir
  393.         jp drawplaylistwindow
  394.  
  395. exitplayer
  396.         call unloadplayers
  397.         QUIT
  398.  
  399. confirmplayerexit
  400.         OS_SETSYSDRV
  401.         call savedefaultplaylist
  402.         call changetocurrentfolder
  403.         ld hl,confirmexitmsgtable
  404.         ld (currentmsgtable),hl
  405.         ld hl,confirmexitui
  406.         ld (drawdialog.uiaddr),hl
  407.         jp drawdialog
  408.  
  409. cancelplayerexit
  410.         ld hl,mainmsgtable
  411.         ld (currentmsgtable),hl
  412.         ld hl,0
  413.         ld (drawdialog.uiaddr),hl
  414.         jp drawui
  415.  
  416. confirmexitmsgtable
  417.         db (confirmexitmsghandlers_end-confirmexitmsghandlers_start)/3
  418. confirmexitmsghandlers_start
  419.         db 0             : dw mainidle
  420.         db key_redraw    : dw redraw
  421.         db 'y'           : dw exitplayer
  422.         db 'n'           : dw cancelplayerexit
  423.         db key_esc       : dw cancelplayerexit
  424. confirmexitmsghandlers_end
  425.  
  426. CONFIRM_EXIT_WINDOW_X = 17
  427. CONFIRM_EXIT_WINDOW_Y = 8
  428.  
  429. confirmexittext1str db "Нажмите RSHIFT+ENTER, чтобы свернуть плеер",0
  430. confirmexittext2str db "и вернуться к нему без долгого перезапуска.",0
  431. confirmexittext3str db "Exit the player instead? (Y/N)",0
  432.  
  433. confirmexitui
  434.         CUSTOMUISETCOLOR ,40
  435.         CUSTOMUIDRAWWINDOW ,CONFIRM_EXIT_WINDOW_X,CONFIRM_EXIT_WINDOW_Y,45,6
  436.         CUSTOMUIPRINTTEXT ,CONFIRM_EXIT_WINDOW_X+2,CONFIRM_EXIT_WINDOW_Y+2,confirmexittext1str
  437.         CUSTOMUIPRINTTEXT ,CONFIRM_EXIT_WINDOW_X+2,CONFIRM_EXIT_WINDOW_Y+3,confirmexittext2str
  438.         CUSTOMUIPRINTTEXT ,CONFIRM_EXIT_WINDOW_X+8,CONFIRM_EXIT_WINDOW_Y+5,confirmexittext3str
  439.         CUSTOMUIDRAWEND
  440.  
  441. drawdialog
  442. .uiaddr=$+2
  443.         ld ix,0
  444.         ld a,ixh
  445.         or ixl
  446.         ret z
  447.         jp drawcustomui
  448.  
  449. unloadplayers
  450.         ld hl,playerpages
  451.         ld a,(playercount)
  452.         ld b,a
  453. playerdeinitloop
  454.         push bc
  455.         push hl
  456.         ld a,(hl)
  457.         ld (.playerpage),a
  458.         SETPG4000
  459.         call playerdeinit
  460. .playerpage=$+1
  461.         ld e,0
  462.         OS_DELPAGE
  463.         pop hl
  464.         pop bc
  465.         inc hl
  466.         djnz playerdeinitloop
  467.         ret
  468.  
  469. savedefaultplaylist
  470. playlistchanged=$+1
  471.         ld a,0
  472.         or a
  473.         ret z
  474.         xor a
  475.         ld (playlistchanged),a
  476.         ld de,defaultplaylistfilename
  477. saveplaylist
  478. ;de = filename
  479.         ld a,255
  480.         ld (playlistpanel.isinactive),a
  481.         push de
  482.         call openstream_file
  483.         pop de
  484.         or a
  485.         jr z,.openedfile
  486.         OS_CREATEHANDLE
  487.         or a
  488.         ret nz
  489.         ld a,b
  490.         ld (filehandle),a
  491. .openedfile
  492.         ld a,(filehandle)
  493.         ld b,a
  494.         ld de,playlistdatastart
  495.         ld hl,playlistdatasize
  496.         OS_WRITEHANDLE
  497.         call closestream_file
  498.         xor a
  499.         ret
  500.  
  501. onhotkeyS
  502.         ld de,playlistfilename
  503.         call saveplaylist
  504.         ld de,playlistfilename
  505.         jp createfilelistandchangesel
  506.  
  507. onhotkeyO
  508.         call setsharedpages
  509.         ld hl,runoptionsode
  510.         ld de,STARTUP_CODE_ADDR
  511.         ld bc,runoptionsodesize
  512.         ldir
  513.         jp runoptions
  514.  
  515. startplaying
  516.         call stopplaying
  517.         ld ix,(currentpaneladdr)
  518.         ld a,(ix+PANEL.filecount)
  519.         or a
  520.         ret z
  521.         ld a,(ix+PANEL.currentfileindex)
  522.         call getfiledataoffset
  523.         ld a,ixl
  524.         add PANEL.fileslist+FILE_ATTRIB_OFFSET
  525.         ld e,a
  526.         adc a,ixh
  527.         sub e
  528.         ld d,a
  529.         add hl,de
  530.         ld a,(hl)
  531.         cp FILE_ATTRIB_PARENT_DIR
  532.         jp z,changetoparentdir
  533.         cp FILE_ATTRIB_FOLDER
  534.         jp z,changetofolder
  535.         cp FILE_ATTRIB_DRIVE
  536.         jp z,changedrive
  537.         cp FILE_ATTRIB_MUSIC
  538.         ret nz
  539.         ld a,(browserpanel.isinactive)
  540.         or a
  541.         ld de,FILE_NAME_OFFSET-FILE_ATTRIB_OFFSET
  542.         jr z,$+5
  543.         ld de,FILE_DISPLAY_INFO_OFFSET-FILE_ATTRIB_OFFSET
  544.         add hl,de
  545.         ld (.filename),hl
  546.         call getfileextension
  547.         ld (.filext2),de
  548.         ld (.filext1),bc
  549.         call isfileplaylist
  550.         jp z,.loadplaylist
  551.         call findsupportedplayer
  552.         jp nz,drawerrorwindow
  553.         ld hl,0
  554.         ld (devicemask),hl
  555.         ld (ERRORSTRINGADDR),hl
  556.         call drawplayer
  557.         ld hl,drawprogress
  558.         ld (drawprogresscallback.func),hl
  559. .filext1=$+1
  560.         ld bc,0
  561. .filext2=$+1
  562.         ld de,0
  563. .filename=$+1
  564.         ld hl,0
  565.         call musicload
  566.         jp nz,drawerrorwindow
  567.         ld (devicemask),hl
  568.         ld hl,playmsgtable
  569.         ld (currentmsgtable),hl
  570. ;init timer
  571.         OS_GETTIMER
  572.         ld (getplaytimestring.starttime),hl
  573.         ld hl,playtimestr
  574.         ld b,6
  575.         ld (hl),0
  576.         inc hl
  577.         djnz $-3
  578. ;skip drawplayerwindow and redraw the rest of player UI
  579.         ld a,1
  580.         ld (isplaying),a
  581.         ld a,0xc9 ;ret opcode
  582.         ld (drawplayerwindow),a
  583.         call drawplayer
  584.         xor a
  585.         ld (drawplayerwindow),a
  586.         ret
  587. .loadplaylist
  588.         ld de,(.filename)
  589.         call loadplaylist
  590.         call drawplaylistwindow
  591.         xor a
  592.         call setcurrentpanel
  593.         jp startplaying
  594.  
  595. changedrive
  596.         ld de,FILE_NAME_OFFSET-FILE_ATTRIB_OFFSET
  597.         add hl,de
  598.         push hl
  599.         ld de,(currentfolder)
  600.         push de
  601.         ld de,currentfolder
  602.         ldi
  603.         ldi
  604.         call changetocurrentfolder
  605.         pop hl
  606.         pop de
  607.         jp z,createfilelistandchangesel
  608.         ld (currentfolder),hl
  609.         ret
  610.  
  611. changetoparentdir
  612.         ld hl,currentfolder
  613.         ld c,'/'
  614.         call findlastchar ;out: de = after last slash or start
  615.         push de
  616.         dec de
  617.         xor a
  618.         ld (de),a
  619.         call changetocurrentfolder
  620.         pop de
  621.         jp createfilelistandchangesel
  622.  
  623. createfilelistandchangesel
  624. ;de = selection filename
  625.         push de
  626.         call createfileslist
  627.         pop de
  628.         call findfile
  629.         ld (browserpanel.currentfileindex),a
  630.         sub FILE_LINE_COUNT-1
  631.         jp c,drawbrowserwindow
  632.         ld hl,browserpanel.firstfiletoshow
  633.         cp (hl)
  634.         jp c,drawbrowserwindow
  635.         ld (hl),a
  636.         jp drawbrowserwindow
  637.  
  638. changetofolder
  639.         ld de,FILE_NAME_OFFSET-FILE_ATTRIB_OFFSET
  640.         add hl,de
  641.         ld de,currentfolder-1
  642. .findzeroloop
  643.         inc de
  644.         ld a,(de)
  645.         or a
  646.         jr nz,.findzeroloop
  647.         ld a,'/'
  648.         ld (de),a
  649.         inc de
  650.         call strcopy_hltode
  651.         call changetocurrentfolder
  652.         call createfileslist
  653.         xor a
  654.         ld (browserpanel.currentfileindex),a
  655.         jp drawbrowserwindow
  656.  
  657. stopplaying
  658.         ld a,(isplaying)
  659.         or a
  660.         ret z
  661.         call musicunload
  662.         ld hl,mainmsgtable
  663.         ld (currentmsgtable),hl
  664.         xor a
  665.         ld (isplaying),a
  666.         jp drawui
  667.  
  668. setnextfileindex
  669. ;ix = current panel
  670. ;out: cf=0 if at the end of file list, c1=1 otherwise
  671.         ld a,(ix+PANEL.currentfileindex)
  672.         inc a
  673.         cp (ix+PANEL.filecount)
  674.         ret nc
  675.         ld (ix+PANEL.currentfileindex),a
  676.         sub FILE_LINE_COUNT-1
  677.         ret c
  678.         cp (ix+PANEL.firstfiletoshow)
  679.         ret c
  680.         ld (ix+PANEL.firstfiletoshow),a
  681.         scf
  682.         ret
  683.  
  684. golastfile
  685.         ld ix,(currentpaneladdr)
  686.         call setnextfileindex
  687.         jr c,$-3
  688.         jp drawcurrentpanelfilelist
  689.  
  690. gopagedown     
  691.         ld ix,(currentpaneladdr)
  692.         ld b,FILE_LINE_COUNT
  693.         call setnextfileindex
  694.         djnz $-3
  695.         jp drawcurrentpanelfilelist
  696.  
  697. gonextfile
  698.         ld ix,(currentpaneladdr)
  699.         call setnextfileindex
  700.         ret nc
  701.         jp drawcurrentpanelfilelist
  702.  
  703. setprevfileindex
  704. ;ix = current panel
  705.         ld a,(ix+PANEL.currentfileindex)
  706.         or a
  707.         ret z
  708.         dec a
  709.         ld (ix+PANEL.currentfileindex),a
  710.         cp (ix+PANEL.firstfiletoshow)
  711.         ret nc
  712.         ld (ix+PANEL.firstfiletoshow),a
  713.         ret
  714.  
  715. goprevfile
  716.         ld ix,(currentpaneladdr)
  717.         call setprevfileindex
  718.         jp drawcurrentpanelfilelist
  719.  
  720. gopageup
  721.         ld ix,(currentpaneladdr)
  722.         ld b,FILE_LINE_COUNT
  723.         call setprevfileindex
  724.         djnz $-3
  725.         jp drawcurrentpanelfilelist
  726.  
  727. loadplaylist
  728. ;de = filename
  729.         call markplaylistdirty
  730.         call openstream_file
  731.         or a
  732.         jr nz,initemptyplaylist
  733.         ld de,playlistdatastart
  734.         ld hl,playlistdatasize
  735.         call readstream_file
  736.         call closestream_file
  737.         ld de,PLAYLIST_VERSION
  738.         ld hl,(playlistpanelversion)
  739.         sub hl,de
  740.         ret z
  741. initemptyplaylist
  742.         ld hl,PLAYLIST_VERSION
  743.         ld (playlistpanelversion),hl
  744.         ld ix,playlistpanel
  745.         jr clearpanel
  746.  
  747. clearpanel
  748. ;ix = panel
  749.         xor a
  750.         ld (ix+PANEL.filecount),a
  751.         ld (ix+PANEL.currentfileindex),a
  752.         ld (ix+PANEL.firstfiletoshow),a
  753.         ret
  754.  
  755. changetocurrentfolder
  756. ;out: zf=1 if succeeded, zf=0 otherwise
  757.         ld hl,(currentfolder+2)
  758.         push hl
  759.         ld a,l
  760.         or a
  761.         jr nz,$+8
  762.         ld hl,'/'
  763.         ld (currentfolder+2),hl
  764.         ld de,currentfolder
  765.         OS_CHDIR
  766.         pop hl
  767.         ld (currentfolder+2),hl
  768.         or a
  769.         ret
  770.  
  771. setcurrentfolder
  772. ;out: hl = file name only
  773.         push hl
  774.         ld c,'/'
  775.         call findlastchar ;out: de = after last slash or start
  776.         pop bc
  777.         ld hl,de
  778.         sub hl,bc
  779.         ex hl,de
  780.         ret z
  781. ;copy file path
  782.         ld hl,bc
  783.         ld bc,de
  784.         ld de,currentfolder
  785.         ldir
  786.         dec de
  787.         xor a
  788.         ld (de),a
  789.         ret
  790.  
  791. findfile
  792. ;de = file name
  793. ;out: a = file index, cf=1 if file was found
  794.         ld a,(browserpanel.filecount)
  795.         or a
  796.         ret z
  797.         ld b,a
  798.         ld c,0
  799.         ld hl,browserpanel.fileslist+FILE_NAME_OFFSET
  800. .searchloop
  801.         push bc
  802.         push de
  803.         push hl
  804.         call stricmp
  805.         pop hl
  806.         ld de,FILE_DATA_SIZE
  807.         add hl,de
  808.         pop de
  809.         pop bc
  810.         scf
  811.         ld a,c
  812.         ret z
  813.         inc c
  814.         djnz .searchloop
  815.         xor a
  816.         ret
  817.  
  818. stricmp
  819. ;hl = string1 addr
  820. ;de = string2 addr
  821. ;out: zf=1 if equal
  822.         ld a,(hl)
  823.         call tolower
  824.         ld c,a
  825.         ld a,(de)
  826.         call tolower
  827.         ld b,a
  828.         or c
  829.         ret z
  830.         ld a,b
  831.         cp c
  832.         ret nz
  833.         cp 1
  834.         ret c
  835.         inc hl
  836.         inc de
  837.         jr stricmp
  838.  
  839. drawerrorwindow
  840. ;show the error if esc was pressed to avoid infinitely looping through unplayable files
  841.         OS_GETKEY
  842.         cp key_esc
  843.         jr z,.drawwindow
  844. ;don't display errors in playlist mode and just skip to the next file silently
  845.         ld a,(browserpanel.isinactive)
  846.         or a
  847.         jr z,.drawwindow
  848.         call setnextfileindexandwrap
  849.         call drawui
  850.         jp startplaying
  851. .drawwindow
  852.         ld de,COLOR_ERROR_WINDOW
  853.         OS_SETCOLOR
  854.         ld hl,(ERRORSTRINGADDR)
  855.         ld a,l
  856.         or h
  857.         jp z,drawui; got no text to print!
  858.         bit 7,h
  859.         jr nz,errorcustomui
  860.         ld b,1
  861. .strlenloop
  862.         ld a,(hl)
  863.         inc hl
  864.         inc b
  865.         or a
  866.         jr nz,.strlenloop
  867.         ld c,3
  868.         ld de,10*256+16
  869.         call drawwindow
  870.         ld de,10*256+18
  871.         OS_SETXY
  872.         ld hl,errorwindowheaderstr
  873.         call print_hl
  874.         ld de,12*256+18
  875.         OS_SETXY
  876.         ld hl,(ERRORSTRINGADDR)
  877.         call print_hl
  878.         YIELDGETKEYLOOP
  879.         jp drawui
  880. errorcustomui
  881.         res 7,h
  882.         push hl
  883.         pop ix
  884.         call drawcustomui
  885.         YIELDGETKEYLOOP
  886.         jp drawui
  887.  
  888. drawplayerwindow
  889.         nop
  890.         ld a,(.pos)
  891.         inc a
  892.         ret z
  893.         ld de,COLOR_PANEL
  894.         OS_SETCOLOR
  895. .pos=$+1
  896.         ld de,0x0806
  897. .size=$+1
  898.         ld bc,0x4204
  899.         jp drawwindow
  900.  
  901. getplaytimestring
  902. ;de = string buffer
  903.         push de
  904.         OS_GETTIMER
  905. .starttime=$+1
  906.         ld de,0
  907.         sub hl,de
  908.         pop de
  909.         ld bc,-VSYNC_FREQ*60
  910.         call .writefield ;minutes
  911.         ld a,':'
  912.         ld (de),a
  913.         inc de
  914.         ld bc,-VSYNC_FREQ
  915.         call .writefield ;seconds
  916.         xor a
  917.         ld (de),a
  918.         ret
  919. .writefield
  920.         ld a,255
  921.         inc a
  922.         add hl,bc
  923.         jr c,$-2
  924.         sbc hl,bc
  925.         ld bc,0x2ff6 ;b='0'-1, c=-10
  926.         inc b
  927.         add a,c
  928.         jr c,$-2
  929.         ex de,hl
  930.         ld (hl),b
  931.         ex de,hl
  932.         inc de
  933.         add a,'0'+10
  934.         ld (de),a
  935.         inc de
  936.         ret
  937.  
  938. drawplaytime
  939.         ld a,(.pos)
  940.         inc a
  941.         ret z
  942.         ld de,playtimestr
  943.         call getplaytimestring
  944. .pos=$+1
  945.         ld de,0x0d43
  946.         OS_SETXY
  947. .color=$+1
  948.         ld de,COLOR_CURSOR
  949.         OS_SETCOLOR
  950.         ld hl,playtimestr
  951.         jp print_hl
  952.  
  953. drawplaytimeincremental
  954. ;out: a = number of ticks until the next draw
  955.         ld a,(drawplaytime.pos)
  956.         inc a
  957.         ret z
  958.         ld de,currentplaytimestr
  959.         call getplaytimestring
  960.         ld hl,playtimestr
  961.         ld de,currentplaytimestr
  962.         ld bc,0x0500
  963. .diffsearchloop
  964.         ld a,(de)
  965.         cp (hl)
  966.         jr nz,.difffound
  967.         inc de
  968.         inc hl
  969.         inc c
  970.         djnz .diffsearchloop
  971.         ld a,VSYNC_FREQ/2
  972.         ret
  973. .difffound
  974.         push hl
  975.         ex de,hl
  976.         call strcopy_hltode
  977.         ld de,(drawplaytime.pos)
  978.         ld a,e
  979.         add a,c
  980.         ld e,a
  981.         OS_SETXY
  982.         ld de,(drawplaytime.color)
  983.         OS_SETCOLOR
  984.         pop hl
  985.         call print_hl
  986.         ld a,VSYNC_FREQ/2
  987.         ret
  988.  
  989. drawsongtitle
  990.         ld a,(.pos)
  991.         inc a
  992.         ret z
  993.         ld de,COLOR_PANEL_DIR
  994.         OS_SETCOLOR
  995. .pos=$+1
  996.         ld de,0x0a08
  997.         OS_SETXY
  998. .straddr=$+1
  999.         ld hl,0
  1000.         ld a,l
  1001.         or h
  1002.         jr z,.usefilename
  1003.         ld a,(hl)
  1004.         or a
  1005.         jp nz,print_hl
  1006. .usefilename
  1007.         ld ix,(currentpaneladdr)
  1008.         ld a,(ix+PANEL.currentfileindex)
  1009.         call getfiledataoffset
  1010.         ld a,ixl
  1011.         add PANEL.fileslist+FILE_DISPLAY_INFO_OFFSET
  1012.         ld e,a
  1013.         adc a,ixh
  1014.         sub e
  1015.         ld d,a
  1016.         add hl,de
  1017.         jp print_hl
  1018.  
  1019. drawplayerwindowtitle
  1020.         ld a,(.pos)
  1021.         inc a
  1022.         ret z
  1023.         ld de,COLOR_CURSOR
  1024.         OS_SETCOLOR
  1025. .pos=$+1
  1026.         ld de,0x0808
  1027.         OS_SETXY
  1028. devicemask=$+1
  1029.         ld bc,0
  1030.         ld a,b
  1031.         or c
  1032.         ld hl,(PLAYERNAMESTRADDR)
  1033.         jp z,print_hl
  1034.         ld hl,playingstr
  1035.         ld de,filinfo
  1036.         call strcopy_hltode
  1037.         ld hl,devicelist
  1038.         ld ixl,15
  1039. .loop   bit 0,c
  1040.         jr z,.skip
  1041.         bit 7,b
  1042.         jr z,.noseparator
  1043.         push hl
  1044.         ld hl,deviceseparatorstr
  1045.         call strcopy_hltode
  1046.         pop hl
  1047. .noseparator
  1048.         push hl
  1049.         ld a,(hl)
  1050.         inc hl
  1051.         ld h,(hl)
  1052.         ld l,a
  1053.         call strcopy_hltode
  1054.         pop hl
  1055.         set 7,b
  1056. .skip   inc hl
  1057.         inc hl
  1058.         sra bc
  1059.         dec ixl
  1060.         jr nz,.loop
  1061.         ld hl,playing1str
  1062.         call strcopy_hltode
  1063.         ld hl,filinfo
  1064.         jp print_hl
  1065.  
  1066. drawwindowline
  1067. ;d = left char
  1068. ;e = right char
  1069. ;c = middle char
  1070. ;b = middle char count
  1071.         ld a,d
  1072.         push de
  1073.         push bc
  1074.         PRCHAR
  1075.         pop bc
  1076. .drawloop
  1077.         push bc
  1078.         ld a,c
  1079.         PRCHAR
  1080.         pop bc
  1081.         djnz .drawloop
  1082.         pop de
  1083.         ld a,e
  1084.         PRCHAR
  1085.         ret
  1086.  
  1087. drawwindow
  1088. ;e = left coord
  1089. ;d = top coord
  1090. ;b = client area width
  1091. ;c = client area height
  1092. ;top line
  1093.         push de
  1094.         push bc
  1095.         OS_SETXY
  1096.         pop bc
  1097.         push bc
  1098.         ld de,0xc9bb
  1099.         ld c,0xcd
  1100.         call drawwindowline
  1101.         pop bc
  1102.         pop de
  1103.         inc d
  1104. ;client area
  1105. .drawloop
  1106.         push de
  1107.         push bc
  1108.         OS_SETXY
  1109.         pop bc
  1110.         push bc
  1111.         ld de,0xbaba
  1112.         ld c,0x20
  1113.         call drawwindowline
  1114.         pop bc
  1115.         pop de
  1116.         inc d
  1117.         dec c
  1118.         jr nz,.drawloop
  1119. ;bottom line
  1120.         push bc
  1121.         OS_SETXY
  1122.         pop bc
  1123.         ld de,0xc8bc
  1124.         ld c,0xcd
  1125.         jp drawwindowline
  1126.  
  1127. getfiledataoffset
  1128. ;a = index
  1129. ;out: hl = index * FILE_DATA_SIZE
  1130.         ld l,a
  1131.         ld h,0
  1132.         ld de,hl
  1133.         add hl,hl
  1134.         add hl,hl
  1135.         ex de,hl
  1136.         add hl,de
  1137.         ex de,hl
  1138.         add hl,hl
  1139.         add hl,de
  1140.         add hl,hl
  1141.         add hl,hl
  1142.         ret
  1143.  
  1144. getfileinfocolor
  1145. ;c = file index
  1146. ;hl = file data address
  1147. currentfileindex=$+1
  1148.         ld a,0
  1149.         cp c
  1150.         ld de,COLOR_CURSOR
  1151.         ret z
  1152.         ld a,(ix+FILE_ATTRIB_OFFSET-FILE_DISPLAY_INFO_OFFSET)
  1153.         cp FILE_ATTRIB_MUSIC
  1154.         ld de,COLOR_PANEL_FILE
  1155.         ret z
  1156.         cp FILE_ATTRIB_DRIVE
  1157.         ld de,COLOR_PANEL_DRIVE
  1158.         ret z
  1159. ;FILE_ATTRIB_PARENT_DIR or FILE_ATTRIB_FOLDER
  1160.         ld de,COLOR_PANEL_DIR
  1161.         ret
  1162.  
  1163. printfilesinfos
  1164. ;ix = struct PANEL
  1165. ;e = left coord
  1166. ;d = top coord
  1167. ;b = line count
  1168. ;c = first file index
  1169.         ld a,(ix+PANEL.currentfileindex)
  1170.         or (ix+PANEL.isinactive)
  1171.         ld (currentfileindex),a
  1172.         ld a,(ix+PANEL.filecount)
  1173.         ld (.currentfilecount),a
  1174.         push de
  1175.         ld a,c
  1176.         call getfiledataoffset
  1177.         ld de,ix
  1178.         add hl,de
  1179.         ld de,FILE_DISPLAY_INFO_OFFSET+PANEL.fileslist
  1180.         add hl,de
  1181.         pop de
  1182. .filesloop
  1183.         ld a,c
  1184. .currentfilecount=$+1
  1185.         cp 0
  1186.         ret nc
  1187.         push de
  1188.         push hl
  1189.         push bc
  1190.         OS_SETXY
  1191.         pop bc
  1192.         pop ix
  1193.         push bc
  1194.         push ix
  1195.         call getfileinfocolor
  1196.         OS_SETCOLOR
  1197.         pop hl
  1198.         pop bc
  1199.         push bc
  1200.         ld b,FILE_DISPLAY_INFO_SIZE
  1201. .printdisplaystringloop
  1202.         push bc
  1203.         push hl
  1204.         ld a,(hl)
  1205.         or a
  1206.         jr nz,$+4
  1207.         ld a,' '
  1208.         PRCHAR
  1209.         pop hl
  1210.         pop bc
  1211.         inc hl
  1212.         djnz .printdisplaystringloop
  1213.         ld de,FILE_DATA_SIZE-FILE_DISPLAY_INFO_SIZE
  1214.         add hl,de
  1215.         pop bc
  1216.         pop de
  1217.         inc c
  1218.         inc d
  1219.         djnz .filesloop
  1220.         ret
  1221.  
  1222. getbrowserpanelparams
  1223.         ld ix,browserpanel
  1224.         ld de,256+1+FILES_WINDOW_X
  1225.         ret
  1226.  
  1227. drawbrowserfileslist
  1228.         call getbrowserpanelparams
  1229.         ld b,FILE_LINE_COUNT
  1230.         ld c,(ix+PANEL.firstfiletoshow)
  1231.         jp printfilesinfos
  1232.  
  1233. getplaylistpanelparams
  1234.         ld ix,playlistpanel
  1235.         ld de,256+FILE_DISPLAY_INFO_SIZE+3+FILES_WINDOW_X
  1236.         ret
  1237.  
  1238. drawplaylistfileslist
  1239.         call getplaylistpanelparams
  1240.         ld b,FILE_LINE_COUNT
  1241.         ld c,(ix+PANEL.firstfiletoshow)
  1242.         jp printfilesinfos
  1243.  
  1244. drawcurrentpanelfilelist
  1245. currentpaneladdr=$+2
  1246.         ld ix,0
  1247. currentpanelpos=$+1
  1248.         ld de,0
  1249.         ld b,FILE_LINE_COUNT
  1250.         ld c,(ix+PANEL.firstfiletoshow)
  1251.         jp printfilesinfos
  1252.  
  1253. drawbrowserwindow
  1254.         ld de,COLOR_PANEL
  1255.         OS_SETCOLOR
  1256.         ld de,FILES_WINDOW_X
  1257.         ld bc,FILE_DISPLAY_INFO_SIZE*256+FILE_LINE_COUNT
  1258.         call drawwindow
  1259.         ld de,COLOR_CURSOR
  1260.         OS_SETCOLOR
  1261.         ld de,FILES_WINDOW_X+2
  1262.         OS_SETXY
  1263.         ld hl,currentfolder
  1264.         call print_hl
  1265.         jp drawbrowserfileslist
  1266.  
  1267. drawplaylistwindow
  1268.         ld de,COLOR_PANEL
  1269.         OS_SETCOLOR
  1270.         ld de,FILES_WINDOW_X+FILE_DISPLAY_INFO_SIZE+2
  1271.         ld bc,FILE_DISPLAY_INFO_SIZE*256+FILE_LINE_COUNT
  1272.         call drawwindow
  1273.         ld de,COLOR_CURSOR
  1274.         OS_SETCOLOR
  1275.         ld de,FILES_WINDOW_X+FILE_DISPLAY_INFO_SIZE+4
  1276.         OS_SETXY
  1277.         ld hl,playliststr
  1278.         call print_hl
  1279.         jr drawplaylistfileslist
  1280.  
  1281. redraw  ld e,7
  1282.         OS_CLS
  1283. drawui  call drawbrowserwindow
  1284.         call drawplaylistwindow
  1285.         call drawdialog
  1286.         ld de,COLOR_DEFAULT
  1287.         OS_SETCOLOR
  1288.         ld de,24*256+1
  1289.         OS_SETXY
  1290.         ld hl,hotkeystr
  1291.         call print_hl
  1292.         ld a,(isplaying)
  1293.         or a
  1294.         ret z
  1295.         jp drawplayer
  1296.  
  1297. drawplayer
  1298.         ld ix,(CUSTOMUIADDR)
  1299.         ld a,ixh
  1300.         or ixl
  1301.         ret z
  1302. drawcustomui
  1303. ;ix = commands
  1304. .drawloop
  1305.         ld a,(ix)
  1306.         cp CUSTOM_UI_CMD_COUNT
  1307.         ret nc
  1308.         ld (.commandsizeoffset),a
  1309.         ld b,a
  1310.         add a,a
  1311.         add a,b
  1312.         ld (.commandtable),a
  1313.         push ix
  1314.         ld hl,.finalizecmd
  1315.         push hl
  1316. .commandtable=$+1
  1317.         jr $
  1318.         jp .drawwindow
  1319.         jp .printtext
  1320.         jp .setcolor
  1321.         jp .playerwindow
  1322.         jp .playerwindowtitle
  1323.         jp .playtime
  1324.         jp .playprogress
  1325.         jp .songtitle
  1326.         jp .separator
  1327. .finalizecmd
  1328.         pop ix
  1329. .commandsizeoffset=$+1
  1330.         ld de,0
  1331.         ld hl,.commandsize
  1332.         add hl,de
  1333.         ld e,(hl)
  1334.         add ix,de
  1335.         jp .drawloop
  1336. .commandsize
  1337.         db CUSTOMUIDRAWWINDOW
  1338.         db CUSTOMUIPRINTTEXT
  1339.         db CUSTOMUISETCOLOR
  1340.         db CUSTOMUIPLAYERWINDOW
  1341.         db CUSTOMUIPLAYERWINDOWTITLE
  1342.         db CUSTOMUIPLAYTIME
  1343.         db CUSTOMUIPLAYPROGRESS
  1344.         db CUSTOMUISONGTITLE
  1345.         db CUSTOMUISEPARATOR
  1346. .drawwindow
  1347.         ld e,(ix+CUSTOMUIDRAWWINDOW.topleftx)
  1348.         ld d,(ix+CUSTOMUIDRAWWINDOW.toplefty)
  1349.         ld b,(ix+CUSTOMUIDRAWWINDOW.clientwidth)
  1350.         ld c,(ix+CUSTOMUIDRAWWINDOW.clientheight)
  1351.         jp drawwindow
  1352. .printtext
  1353.         ld e,(ix+CUSTOMUIPRINTTEXT.posx)
  1354.         ld d,(ix+CUSTOMUIPRINTTEXT.posy)
  1355.         ld hl,(ix+CUSTOMUIPRINTTEXT.straddr)
  1356.         push hl
  1357.         OS_SETXY
  1358.         pop hl
  1359.         jp print_hl
  1360. .setcolor
  1361.         ld e,(ix+CUSTOMUISETCOLOR.color)
  1362.         ld d,0
  1363.         OS_SETCOLOR
  1364.         ret
  1365. .playerwindow
  1366.         ld l,(ix+CUSTOMUIPLAYERWINDOW.topleftx)
  1367.         ld h,(ix+CUSTOMUIPLAYERWINDOW.toplefty)
  1368.         ld (drawplayerwindow.pos),hl
  1369.         ld h,(ix+CUSTOMUIPLAYERWINDOW.clientwidth)
  1370.         ld l,(ix+CUSTOMUIPLAYERWINDOW.clientheight)
  1371.         ld (drawplayerwindow.size),hl
  1372.         jp drawplayerwindow
  1373. .playerwindowtitle
  1374.         ld l,(ix+CUSTOMUIPLAYERWINDOWTITLE.posx)
  1375.         ld h,(ix+CUSTOMUIPLAYERWINDOWTITLE.posy)
  1376.         ld (drawplayerwindowtitle.pos),hl
  1377.         jp drawplayerwindowtitle
  1378. .playtime
  1379.         ld l,(ix+CUSTOMUIPLAYTIME.posx)
  1380.         ld h,(ix+CUSTOMUIPLAYTIME.posy)
  1381.         ld (drawplaytime.pos),hl
  1382.         ld hl,(ix+CUSTOMUIPLAYTIME.color)
  1383.         ld (drawplaytime.color),hl
  1384.         ld a,1
  1385.         ld (playnokeypressed.playtimeupdatecounter),a
  1386.         ld a,(isplaying)
  1387.         or a
  1388.         ret z
  1389.         jp drawplaytime
  1390. .playprogress
  1391.         ld e,(ix+CUSTOMUIPLAYPROGRESS.posx)
  1392.         ld d,(ix+CUSTOMUIPLAYPROGRESS.posy)
  1393.         ld (drawprogress.pos),de
  1394.         ld hl,(ix+CUSTOMUIPLAYPROGRESS.counteraddr)
  1395.         ld (drawprogress.counteraddr),hl
  1396.         ld hl,(ix+CUSTOMUIPLAYPROGRESS.color)
  1397.         ld (drawprogress.color),hl
  1398.         ld a,1
  1399.         ld (playnokeypressed.progressupdatecounter),a
  1400.         inc e
  1401.         ret z
  1402.         ld a,(isplaying)
  1403.         or a
  1404.         jp nz,drawprogress
  1405.         ld a,e
  1406.         add a,27
  1407.         ld e,a
  1408.         OS_SETXY
  1409.         ld de,COLOR_PANEL_DIR
  1410.         OS_SETCOLOR
  1411.         ld hl,loadingstr
  1412.         jp print_hl
  1413. .songtitle
  1414.         ld l,(ix+CUSTOMUISONGTITLE.posx)
  1415.         ld h,(ix+CUSTOMUISONGTITLE.posy)
  1416.         ld (drawsongtitle.pos),hl
  1417.         ld hl,(ix+CUSTOMUISONGTITLE.straddr)
  1418.         ld (drawsongtitle.straddr),hl
  1419.         jp drawsongtitle
  1420. .separator
  1421.         ld l,(ix+CUSTOMUISEPARATOR.rightchar)
  1422.         ld h,(ix+CUSTOMUISEPARATOR.leftchar)
  1423.         ld e,(ix+CUSTOMUISEPARATOR.posx)
  1424.         ld d,(ix+CUSTOMUISEPARATOR.posy)
  1425.         ld b,(ix+CUSTOMUISEPARATOR.middlecharcount)
  1426.         ld c,(ix+CUSTOMUISEPARATOR.middlechar)
  1427.         push bc
  1428.         push hl
  1429.         OS_SETXY
  1430.         pop de
  1431.         pop bc
  1432.         jp drawwindowline
  1433.  
  1434. skipword_hl
  1435.         ld a,(hl)
  1436.         or a
  1437.         ret z
  1438.         cp ' '
  1439.         ret z
  1440.         inc hl
  1441.         jr skipword_hl
  1442.  
  1443. skipspaces_hl
  1444.         ld a,(hl)
  1445.         cp ' '
  1446.         ret nz
  1447.         inc hl
  1448.         jr skipspaces_hl
  1449.  
  1450. print_hl
  1451.         ld a,(hl)
  1452.         or a
  1453.         ret z
  1454.         push hl
  1455.         PRCHAR
  1456.         pop hl
  1457.         inc hl
  1458.         jp print_hl
  1459.  
  1460. strcopy_hltode
  1461.         ld a,(hl)
  1462.         ld (de),a
  1463.         or a
  1464.         ret z
  1465.         inc hl
  1466.         inc de
  1467.         jr strcopy_hltode
  1468.  
  1469. ;c = character
  1470. ;hl = poi to filename in string
  1471. ;out: de = after last char or start
  1472. findlastchar
  1473.         ld d,h
  1474.         ld e,l ;de = after last char
  1475. findlastchar0
  1476.         ld a,(hl)
  1477.         inc hl
  1478.         or a
  1479.         ret z
  1480.         cp c
  1481.         jr nz,findlastchar0
  1482.         jr findlastchar
  1483.  
  1484. tolower
  1485.         cp 'A'
  1486.         ret c
  1487.         cp 'Z'+1
  1488.         ret nc
  1489.         add 32
  1490.         ret
  1491.  
  1492. pressanykeystr
  1493.         db "\r\nPress any key to continue...\r\n",0
  1494. mainfilename
  1495.         db "gp.com",0
  1496. playersfilename
  1497.         db "gp/gp.plr",0
  1498. defaultplaylistfilename
  1499.         db "gp/"
  1500. playlistfilename
  1501.         db "playlist.gpl",0
  1502. invalidplayerfilestr
  1503.         db "Corrupted gp/gp.plr file!",0
  1504. noplayersloadedstr
  1505.         db "Unable to load any players!",0
  1506. playersloaderrorstr
  1507.         db "Failed to load gp/gp.plr from OS folder!",0
  1508. initializing1str
  1509.         db "Initializing ",0
  1510. initializing2str
  1511.         db "...",0
  1512. chdirfailedstr
  1513.         db "Unable to change directory!",0
  1514. playliststr
  1515.         db "Playlist",0
  1516. playingstr
  1517.         db "Playing on ",0
  1518. playing1str
  1519.         db "...",0
  1520. deviceseparatorstr
  1521.         db " and ",0
  1522. emptystr
  1523.         db 0
  1524. loadingstr
  1525.         db "LOADING...",0
  1526. errorwindowheaderstr
  1527.         db "Error",0
  1528. hotkeystr
  1529.         db "O=Options  Arrows+Tab=Navigate  Enter=Play  Space=Add/Remove  S=Save Playlist",0
  1530. drivedata
  1531.         db "E: - IDE Master p.1                   E:",0,0,0,0,0,0,0,0,0,0,0,FILE_ATTRIB_DRIVE
  1532.         db "F: - IDE Master p.2                   F:",0,0,0,0,0,0,0,0,0,0,0,FILE_ATTRIB_DRIVE
  1533.         db "M: - SD Z-controller                  M:",0,0,0,0,0,0,0,0,0,0,0,FILE_ATTRIB_DRIVE
  1534.         db "O: - USB ZX-NetUsb                    O:",0,0,0,0,0,0,0,0,0,0,0,FILE_ATTRIB_DRIVE
  1535. drivedataend
  1536.  
  1537. deviceay
  1538.         db "AY8910",0
  1539. deviceturbosound
  1540.         db "TurboSound",0
  1541. devicetfm
  1542.         db "TurboSound-FM",0
  1543. devicemoonsound
  1544.         db "MoonSound",0
  1545. devicebomgemoon
  1546.         db "BomgeMoon",0
  1547. devicegs
  1548.         db "GeneralSound",0
  1549. deviceneogs
  1550.         db "NeoGS",0
  1551. devicemidiuart
  1552.         db "MIDI UART",0
  1553. deviceopm
  1554.         db "YM2151",0
  1555. devicedualopm
  1556.         db "Dual-YM2151",0
  1557. deviceopna
  1558.         db "YM2608",0
  1559. devicelist
  1560.         dw deviceay
  1561.         dw deviceturbosound
  1562.         dw devicetfm
  1563. .moonsoundstraddr
  1564.         dw devicemoonsound
  1565.         dw devicegs
  1566.         dw deviceneogs
  1567.         dw devicemidiuart
  1568.         dw deviceopm
  1569.         dw devicedualopm
  1570.         dw deviceopna
  1571.  
  1572. loadplayer
  1573. ;de = code size
  1574. ;hl = settings variable addr
  1575.         ld (.codesize),de
  1576.         ld a,h
  1577.         or l
  1578.         ld a,'1' ;default for Use<Player> variable is 1
  1579.         jr z,$+3
  1580.         ld a,(hl)
  1581.         ld (.settingsvalue),a
  1582.         OS_NEWPAGE
  1583.         or a
  1584.         ret nz
  1585.         ld a,e
  1586.         ld (.playerpage),a
  1587.         SETPG4000
  1588.         call setsharedpages
  1589.         ld de,0x4000
  1590. .codesize=$+1
  1591.         ld hl,0
  1592.         call readstream_file
  1593. .settingsvalue=$+1
  1594.         ld a,0
  1595.         cp '0'
  1596.         jr z,.cleanup
  1597.         ld hl,initializing1str
  1598.         call print_hl
  1599.         ld hl,(PLAYERNAMESTRADDR)
  1600.         call print_hl
  1601.         ld hl,initializing2str
  1602.         call print_hl
  1603.         ld ix,gpsettings
  1604.         ld a,(.playerpage)
  1605.         call playerinit
  1606.         push af
  1607.         call print_hl
  1608.         pop af
  1609.         jr nz,.cleanup
  1610.         ld hl,playercount
  1611.         ld e,(hl)
  1612.         inc (hl)
  1613.         ld d,0
  1614.         ld hl,playerpages
  1615.         add hl,de
  1616. .playerpage=$+1
  1617.         ld (hl),0
  1618.         ret
  1619. .cleanup
  1620.         ld a,(.playerpage)
  1621.         ld e,a
  1622.         OS_DELPAGE
  1623.         ret
  1624.  
  1625. loadplayers
  1626. ;output: zf=1 if success, zf=0 and hl=error message if failed
  1627.         ld de,playersfilename
  1628.         call openstream_file
  1629.         or a
  1630.         ld hl,playersloaderrorstr
  1631.         ret nz
  1632. ;check if the file matches this build
  1633.         ld a,(filehandle)
  1634.         ld b,a
  1635.         OS_GETFILESIZE
  1636.         ld bc,plrfilesize%65536
  1637.         sub hl,bc
  1638.         ld hl,invalidplayerfilestr
  1639.         ret nz
  1640.         ld hl,plrfilesize/65536
  1641.         sbc hl,de
  1642.         ld hl,invalidplayerfilestr
  1643.         ret nz
  1644. ;load players from file
  1645.         xor a
  1646.         ld (playercount),a
  1647.         ld de,modplrsize : ld hl,(gpsettings.usemoonmod) : call loadplayer
  1648.         ld de,mwmplrsize : ld hl,(gpsettings.usemwm) : call loadplayer
  1649.         ld de,mp3plrsize : ld hl,(gpsettings.usemp3) : call loadplayer 
  1650.         ld de,moonmidsize : ld hl,(gpsettings.usemoonmid) : call loadplayer
  1651.         ld de,pt3plrsize : ld hl,(gpsettings.usept3) : call loadplayer
  1652.         ld de,vgmplrsize : ld hl,(gpsettings.usevgm) : call loadplayer
  1653.         call closestream_file
  1654.         ld a,(playercount)
  1655.         dec a
  1656.         ld hl,noplayersloadedstr
  1657.         ret m
  1658.         xor a
  1659.         ret
  1660.  
  1661. gpsettings GPSETTINGS drawprogresscallback,drawcustomui
  1662. bomgemoonsettings dw 0
  1663. runplayersetup db 0
  1664.  
  1665. getfileextension
  1666. ;hl = file name
  1667. ;out: cde = file extension
  1668.         ld c,'.'
  1669.         call findlastchar ;out: de = after last dot or start
  1670.         ex de,hl
  1671.         ld a,(hl)
  1672.         call tolower
  1673.         ld c,a
  1674.         inc hl
  1675.         ld a,(hl)
  1676.         call tolower
  1677.         ld d,a
  1678.         inc hl
  1679.         ld a,(hl)
  1680.         call tolower
  1681.         ld e,a
  1682.         ret
  1683.  
  1684. isfileplaylist
  1685. ;cde = file extension
  1686. ;out: zf=1 if playlist, zf=0 otherwise
  1687.         ld a,c
  1688.         cp 'g'
  1689.         ret nz
  1690.         ld a,d
  1691.         cp 'p'
  1692.         ret nz
  1693.         ld a,e
  1694.         cp 'l'
  1695.         ret
  1696.  
  1697. findsupportedplayer
  1698. ;cde = file extension
  1699.         ld hl,playerpages
  1700.         ld a,(playercount)
  1701.         ld b,a
  1702. .findplayerloop
  1703.         push hl
  1704.         push bc
  1705.         ld a,(hl)
  1706.         SETPG4000
  1707.         pop bc
  1708.         call isfilesupported
  1709.         pop hl
  1710.         ret z
  1711.         inc hl
  1712.         djnz .findplayerloop
  1713.         dec b ;set zf=0
  1714.         ret
  1715.  
  1716. setsharedpages
  1717.         ld a,(gpsettings.sharedpages+1)
  1718.         SETPG8000
  1719.         ld a,(gpsettings.sharedpages)
  1720.         SETPGC000
  1721.         ret
  1722.  
  1723. createfileslist
  1724.         ld de,emptystr
  1725.         OS_OPENDIR
  1726.         call setsharedpages
  1727.         xor a
  1728.         ld (browserpanel.currentfileindex),a
  1729.         ld (browserpanel.firstfiletoshow),a
  1730.         ld hl,currentfolder+2
  1731.         cp (hl)
  1732.         ld hl,0x8000
  1733.         jr nz,.startloop
  1734.         ex de,hl
  1735.         ld hl,drivedata
  1736.         ld bc,drivedataend-drivedata
  1737.         ldir
  1738.         ex de,hl
  1739.         ld a,(drivedataend-drivedata)/FILE_DATA_SIZE
  1740. .startloop
  1741.         ld (browserpanel.filecount),a
  1742. .fileenumloop
  1743.         ld (.filedataaddr),hl
  1744. .skiptonextfile
  1745.         ld de,filinfo
  1746.         OS_READDIR
  1747.         or a
  1748.         jp nz,.sortfiles
  1749. ;skip '.' folder
  1750.         ld hl,(filinfo+FILINFO_FNAME)
  1751.         ld a,l
  1752.         xor '.'
  1753.         or h
  1754.         jr z,.skiptonextfile
  1755. ;skip findsupportedplayer for folders
  1756.         ld a,(filinfo+FILINFO_FATTRIB)
  1757.         and FATTRIB_DIR
  1758.         jr nz,.foundfileordir
  1759.         ld hl,filinfo+FILINFO_FNAME
  1760.         call getfileextension
  1761.         call isfileplaylist
  1762.         jr z,.foundfileordir
  1763.         call findsupportedplayer
  1764.         jr nz,.skiptonextfile
  1765. ;we've got either a playable file or a folder
  1766. .foundfileordir
  1767. .filedataaddr=$+1
  1768.         ld de,0
  1769.         ld hl,FILE_NAME_OFFSET
  1770.         add hl,de
  1771.         ex de,hl
  1772.         ld hl,filinfo+FILINFO_FNAME
  1773.         ld bc,9*256+SFN_SIZE
  1774. .copysfnloop
  1775.         ld a,(hl)
  1776.         cp '.'
  1777.         jr z,.foundsfnext
  1778.         or a
  1779.         jr z,.sfntailloop
  1780.         call tolower
  1781.         ld (de),a
  1782.         inc hl
  1783.         inc de
  1784.         dec c
  1785.         dec b
  1786.         jr .copysfnloop
  1787. ;this is a folder, pad it to SFN_SIZE with zeros
  1788. .sfntailloop
  1789.         ld (de),a
  1790.         inc de
  1791.         dec c
  1792.         jr nz,.sfntailloop
  1793.         jr .donesfncopy
  1794. ;format SFN as 8.3 fixed-position array padding with '*' if necessary
  1795. ;this is needed for sorting
  1796. .foundsfnext
  1797.         ld a,'*'
  1798. .sfntailloop1
  1799.         ld (de),a
  1800.         inc de
  1801.         djnz .sfntailloop1
  1802.         dec de
  1803. ;copy dot, extension, zero terminator
  1804.         ld b,5
  1805. .sfntailloop2
  1806.         ld a,(hl)
  1807.         call tolower
  1808.         ld (de),a
  1809.         inc hl
  1810.         inc de
  1811.         djnz .sfntailloop2
  1812. .donesfncopy
  1813. ;fill display name
  1814.         ld hl,FILE_DISPLAY_INFO_OFFSET-FILE_NAME_OFFSET-SFN_SIZE
  1815.         add hl,de
  1816.         ex de,hl
  1817.         ld hl,filinfo+FILINFO_LNAME
  1818.         ld a,(hl)
  1819.         or a
  1820.         jr nz,$+5
  1821.         ld hl,filinfo+FILINFO_FNAME
  1822.         ld bc,(FILE_DISPLAY_INFO_SIZE-1)*256+255
  1823. .copylfnloop
  1824.         ldi
  1825.         dec b
  1826.         jr z,.lfncopydone
  1827.         ld a,(hl)
  1828.         or a
  1829.         jr nz,.copylfnloop
  1830. .filltailloop
  1831.         ld (de),a
  1832.         inc de
  1833.         djnz .filltailloop
  1834. .lfncopydone
  1835.         xor a
  1836.         ld (de),a
  1837. ;set atrribute data
  1838.         call getfileattrib
  1839.         ld hl,FILE_ATTRIB_OFFSET-FILE_DISPLAY_INFO_OFFSET-FILE_DISPLAY_INFO_SIZE+1
  1840.         add hl,de
  1841.         ld (hl),a
  1842.         ld de,FILE_DATA_SIZE-FILE_ATTRIB_OFFSET
  1843.         add hl,de
  1844. ;check if we have space for more files
  1845.         ld a,(browserpanel.filecount)
  1846.         inc a
  1847.         ld (browserpanel.filecount),a
  1848.         cp BROWSER_FILE_COUNT
  1849.         jp c,.fileenumloop
  1850. .sortfiles
  1851.         ld a,(browserpanel.filecount)
  1852.         or a
  1853.         ret z
  1854.         ld c,a
  1855.         ld b,0
  1856.         ld a,12
  1857.         ld ix,fileextsortkeyoffsets
  1858.         ld hl,0x8000
  1859.         ld de,FILE_DATA_SIZE
  1860.         ld iy,browserpanel.fileslist
  1861.         call radixsort
  1862. ;remove '*' padding restoring SFN to original null-terminated string form
  1863.         ld a,(browserpanel.filecount)
  1864.         ld b,a
  1865.         ld hl,browserpanel.fileslist+FILE_NAME_OFFSET
  1866. .removepaddingnextfile
  1867.         ld de,hl
  1868.         push hl
  1869. .removepaddingloop
  1870.         ld a,(hl)
  1871.         inc hl
  1872.         cp '*'
  1873.         jr z,.removepaddingloop
  1874.         ld (de),a
  1875.         inc de
  1876.         or a
  1877.         jr nz,.removepaddingloop
  1878.         pop hl
  1879.         ld de,FILE_DATA_SIZE
  1880.         add hl,de
  1881.         djnz .removepaddingnextfile
  1882.         ret
  1883.  
  1884. getfileattrib
  1885. ;out: a = attribute value
  1886.         ld a,(filinfo+FILINFO_FATTRIB)
  1887.         and FATTRIB_DIR
  1888.         ld a,FILE_ATTRIB_MUSIC
  1889.         ret z
  1890.         ld hl,(filinfo+FILINFO_FNAME)
  1891.         ld bc,'..'
  1892.         sub hl,bc
  1893.         ld a,FILE_ATTRIB_PARENT_DIR
  1894.         ret z
  1895.         ld a,FILE_ATTRIB_FOLDER
  1896.         ret
  1897.  
  1898. fileextsortkeyoffsets
  1899.         dw FILE_NAME_OFFSET+7, FILE_NAME_OFFSET+6, FILE_NAME_OFFSET+5
  1900.         dw FILE_NAME_OFFSET+4, FILE_NAME_OFFSET+3, FILE_NAME_OFFSET+2
  1901.         dw FILE_NAME_OFFSET+1, FILE_NAME_OFFSET+0
  1902.         dw FILE_NAME_OFFSET+11, FILE_NAME_OFFSET+10, FILE_NAME_OFFSET+9
  1903.         dw FILE_ATTRIB_OFFSET
  1904.  
  1905. playerinit      = PLAYERINITPROCADDR - 1
  1906. playerdeinit    = PLAYERDEINITPROCADDR - 1
  1907. musicload       = MUSICLOADPROCADDR - 1
  1908. musicunload     = MUSICUNLOADPROCADDR - 1
  1909. musicplay       = MUSICPLAYPROCADDR - 1
  1910. isfilesupported = ISFILESUPPORTEDPROCADDR - 1
  1911.  
  1912.         include "../_sdk/file.asm"
  1913.         include "common/radixsort.asm"
  1914.         include "common/turbo.asm"
  1915.  
  1916. runoptionsode
  1917.         disp STARTUP_CODE_ADDR
  1918. runoptions
  1919.         OS_SETSYSDRV
  1920.         ld de,mainfilename
  1921.         OS_OPENHANDLE
  1922.         or a
  1923.         jp nz,changetocurrentfolder
  1924.         push bc
  1925.         push bc
  1926.         call unloadplayers
  1927.         call savedefaultplaylist
  1928.         ld a,(gpsettings.sharedpages+2)
  1929.         SETPG4000
  1930.         ld de,currentfolder
  1931.         OS_CHDIR
  1932.         ld de,mainbegin
  1933.         ld hl,mainsize
  1934.         pop bc
  1935.         OS_READHANDLE
  1936.         pop bc
  1937.         OS_CLOSEHANDLE
  1938.         ld a,1
  1939.         ld (runplayersetup),a
  1940.         ld sp,STACK_ADDR
  1941.         jp startplayer
  1942.         ent
  1943. runoptionsodesize=$-runoptionsode
  1944.  
  1945. tempmemorystart = $
  1946. startupcode
  1947.         disp STARTUP_CODE_ADDR
  1948.         include "startup.asm"
  1949.         ent
  1950. startupcodesize=$-startupcode
  1951. mainend
  1952. mainsize=mainend-mainbegin
  1953.  
  1954. ;       display "gpsys = ",/d,startupcodesize," bytes"
  1955.         savebin "gp.com",mainbegin,mainsize
  1956.  
  1957.         org tempmemorystart
  1958. playerpages
  1959.         ds NUM_PLAYERS
  1960. filinfo
  1961.         ds FILINFO_sz
  1962. currentfolder
  1963.         ds MAXPATH_sz
  1964. fullpathbuffer
  1965.         ds MAXPATH_sz
  1966.  
  1967.         struct PANEL
  1968. filecount ds 1
  1969. currentfileindex ds 1
  1970. firstfiletoshow ds 1
  1971. isinactive ds 1
  1972. fileslist ds FILE_DATA_SIZE
  1973.         ends
  1974.  
  1975. browserpanel PANEL
  1976.         ds FILE_DATA_SIZE*(BROWSER_FILE_COUNT-1)
  1977. inifilebuffer equ browserpanel
  1978.  
  1979. playlistdatastart=$
  1980. playlistpanelversion ds 2
  1981. playlistpanel PANEL
  1982.         ds FILE_DATA_SIZE*(PLAYLIST_FILE_COUNT-1)
  1983. playlistdatasize=$-playlistdatastart
  1984.  
  1985. musicprogress ds 1
  1986. playercount ds 1
  1987. playtimestr ds 6
  1988. currentplaytimestr ds 6
  1989.  
  1990.         assert $ <= 0x3e00 ;reserve 512 bytes for stack
  1991.         assert startplayer <= SYSTEM_MEMORY_END
  1992.  
  1993.         org 0
  1994. modstart
  1995.         incbin "moonmod.bin"
  1996. modplrsize=$-modstart
  1997. mwmstart
  1998.         incbin "mwm.bin"
  1999. mwmplrsize=$-mwmstart
  2000. mp3start
  2001.         incbin "mp3.bin"
  2002. mp3plrsize=$-mp3start
  2003. moonmidstart
  2004.         incbin "moonmid.bin"
  2005. moonmidsize=$-moonmidstart
  2006. plrpart1size=$
  2007.         savebin "gp1.plr",0,plrpart1size
  2008.  
  2009.         org 0
  2010. pt3start
  2011.         incbin "pt3.bin"
  2012. pt3plrsize=$-pt3start
  2013. vgmstart
  2014.         incbin "vgm.bin"
  2015. vgmplrsize=$-vgmstart
  2016. plrpart2size=$
  2017.  
  2018.         savebin "gp2.plr",0,plrpart2size
  2019.  
  2020. plrfilesize=plrpart1size+plrpart2size
  2021.