?login_element?

Subversion Repositories NedoOS

Rev

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