Subversion Repositories NedoOS

Rev

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