Subversion Repositories NedoOS

Rev

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

  1. ; Player for NeoGS decoder chip (also GS/NeoGS .mod player)
  2. ; Supports a range of VLSI decoders: VS1001, VS1011, VS1003, VS1033, VS1053
  3.  
  4.         DEVICE ZXSPECTRUM128
  5.         include "../_sdk/sys_h.asm"
  6.         include "ngsdec/gscodedefs.asm"
  7.         include "ngsdec/gsports.asm"
  8.         include "ngsdec/vs10xx.asm"
  9.         include "playerdefs.asm"
  10.  
  11. BUFADDR = 0x8000
  12. BUFSIZE = 0x8000
  13.  
  14.         org PLAYERSTART
  15.  
  16. begin   PLAYERHEADER
  17.  
  18. isfilesupported
  19. ;cde = file extension
  20. ;out: zf=1 if this player can handle the file and the sound hardware is available, zf=0 otherwise
  21.         ld a,c
  22.         cp 'o'
  23.         jp nz,.checkaac
  24.         ld hl,'gg'
  25.         sbc hl,de
  26.         jp nz,.checkaac
  27.         ld a,(vsversion)
  28.         cp SS_VER_VS1053
  29.         jr z,.initmp3vars
  30.         cp SS_VER_VS1063
  31.         jr z,.initmp3vars
  32.         ret
  33. .checkaac
  34.         cp 'a'
  35.         jp nz,.checkmp3modmid
  36.         ld hl,'ac'
  37.         sbc hl,de
  38.         jp nz,.checkmp3modmid
  39.         ld a,(vsversion)
  40.         cp SS_VER_VS1053
  41.         jr z,.initmp3vars
  42.         cp SS_VER_VS1033
  43.         jr z,.initmp3vars
  44.         cp SS_VER_VS1063
  45.         jr z,.initmp3vars
  46.         ret
  47. .checkmp3modmid
  48.         cp 'm'
  49.         ret nz
  50.         ld hl,'od'
  51.         sbc hl,de
  52. .disablemod=$+1
  53.         jr z,.initmodvars
  54.         ld hl,'id'
  55.         sub hl,de
  56. .disablemid=$+1
  57.         jr z,.checkmid
  58.         ld hl,'p3'
  59.         sub hl,de
  60.         ret nz
  61. .initmp3vars
  62.         ld (filechunkcounter),hl
  63.         ld (MUSICTITLEADDR),hl
  64.         ld hl,musicprogress+1
  65.         ld (MUSICPROGRESSADDR),hl
  66.         jp initprogress
  67. .initmodvars
  68.         ld (MUSICTITLEADDR),hl
  69.         ld hl,musicprogress+1
  70.         ld (MUSICPROGRESSADDR),hl
  71.         jp initprogress
  72. .checkmid
  73.         ld a,(vsversion)
  74.         cp SS_VER_VS1053
  75.         jr z,.initmidvars
  76.         cp SS_VER_VS1003
  77.         jr z,.initmidvars
  78.         cp SS_VER_VS1033
  79.         jr z,.initmidvars
  80.         cp SS_VER_VS1103
  81.         ret nz
  82. .initmidvars
  83.         ld (filechunkcounter),hl
  84.         ld (MUSICTITLEADDR),hl
  85.         ld (MUSICPROGRESSADDR),hl
  86.         jp initprogress
  87.  
  88. isfilesupportedgsonly
  89. ;specialized function for GeneralSound
  90.         ld a,c
  91.         cp 'm'
  92.         ret nz
  93.         ld hl,'od'
  94.         sbc hl,de
  95.         ret nz
  96.         jr isfilesupported.initmodvars
  97.  
  98. ismodenabled
  99. ;output: zf=1 if .mod is enabled on this device, zf=0 otherwise
  100.         ld de,(ix+GPSETTINGS.moddevice)
  101.         ld a,d
  102.         or e
  103.         ret z
  104.         ld a,(de)
  105.         cp '0'
  106.         ret z
  107.         cp '2'
  108.         ret
  109.  
  110. checkmididevicesettings
  111. ;output: zf=1 if this player is enabled, zf=0 otherwise
  112.         ld de,(ix+GPSETTINGS.mididevice)
  113.         ld a,d
  114.         or e
  115.         ret z
  116.         ld a,(de)
  117.         cp '0'
  118.         ret z
  119.         cp '2'
  120.         ret z
  121.         ld a,0
  122.         ld (isfilesupported.disablemid),a
  123.         ret
  124.  
  125. playerinit
  126. ;hl,ix = GPSETTINGS
  127. ;a = player page
  128. ;out: zf=1 if init is successful, hl=init message
  129.         ld (.settingsaddr),hl
  130.         ld a,(hl)
  131.         ld (page8000),a
  132.         inc hl
  133.         ld a,(hl)
  134.         ld (pageC000),a
  135. ;       call gssoftreset
  136. ;b==0 if no reply from GS
  137. ;       dec b
  138. ;       inc b
  139. ;       call z,gshardreset
  140.         call gshardreset
  141. ;b==0 if no reply from GS
  142.         ld a,b
  143.         cp 1
  144.         ld hl,nodevicestr
  145.         ret c
  146. ;get chip id
  147.         call gsstartcode
  148.         SC CMDGETCHIPID
  149.         WC
  150.         WN
  151.         GD
  152.         ld (vsversion),a
  153.         call gscodereset
  154. .settingsaddr=$+2
  155.         ld ix,0
  156.         ld a,(vsversion)
  157.         cp SS_VER_VS1103+1
  158.         jr nc,.initgsonly
  159.         rrca
  160.         rrca
  161.         add a,idtostr%256
  162.         ld l,a
  163.         adc a,idtostr/256
  164.         sub l
  165.         ld h,a
  166.         ld de,chipidstr
  167.         ld bc,4
  168.         ldir
  169.         call ismodenabled
  170.         jr z,$+6
  171.         xor a
  172.         ld (isfilesupported.disablemod),a
  173.         call checkmididevicesettings
  174.         ld hl,ngsinitokstr
  175.         xor a
  176.         ret
  177. .initgsonly
  178.         call ismodenabled
  179.         ld hl,playerdisabledstr
  180.         ret nz
  181.         ld hl,isfilesupportedgsonly
  182.         ld (ISFILESUPPORTEDPROCADDR),hl
  183.         ld hl,gsinitokstr
  184.         xor a
  185.         ret
  186.  
  187. playerdeinit
  188.         ret
  189.  
  190. ismodfile
  191. ;cde = file extension
  192. ;out: zf=1 if .mod, zf=0 otherwise
  193.         ld a,'m'
  194.         cp c
  195.         ret nz
  196.         ld a,'o'
  197.         cp d
  198.         ret nz
  199.         ld a,'d'
  200.         cp e
  201.         ret
  202.  
  203. musicload
  204. ;cde = file extension
  205. ;hl = input file name
  206. ;out: hl = device mask, zf=1 if the file is ready for playing, zf=0 otherwise
  207.         call ismodfile
  208.         ld a,1
  209.         jr z,$+3
  210.         dec a
  211.         ld (isplayingmodfile),a
  212.         ex de,hl
  213.         call openstream_file
  214.         or a
  215.         ret nz
  216. page8000=$+1
  217.         ld a,0
  218.         SETPG8000
  219. pageC000=$+1
  220.         ld a,0
  221.         SETPGC000
  222.         ld a,(isplayingmodfile)
  223.         or a
  224.         jr nz,loadmod
  225.         ld a,(filehandle)
  226.         ld b,a
  227.         OS_GETFILESIZE
  228.         ld a,e
  229.         call setprogressdelta
  230.         call gsstartcode
  231.         ld hl,firstpaddingframedata
  232.         ld (paddingframedataptr),hl
  233.         ld hl,0
  234.         ld (paddingframecount),hl
  235.         ld (bufferdataleft),hl
  236.         ld hl,DEVICE_NEOGS_MASK
  237.         xor a
  238.         ret
  239.  
  240. TITLELENGTH = 64
  241. MODHEADERSIZE = 1084
  242.  
  243. loadmod
  244.         ld hl,MODHEADERSIZE
  245.         ld de,BUFADDR
  246.         call readstream_file
  247. ;init progress
  248.         call getmodtype
  249.         ld a,(BUFADDR+950)
  250.         jr z,$+5
  251.         ld a,(BUFADDR+470)
  252.         call setprogressdelta
  253. ;set title
  254.         ld hl,titlestr
  255.         ld (MUSICTITLEADDR),hl
  256.         ld de,BUFADDR
  257.         ld b,TITLELENGTH+1
  258. .copytitleloop
  259.         ld a,(de)
  260.         ld (hl),a
  261.         inc de
  262.         inc hl
  263.         dec b
  264.         or a
  265.         jr nz,.copytitleloop
  266.         dec hl
  267. .filltitleloop
  268.         ld (hl),' '
  269.         inc hl
  270.         djnz .filltitleloop
  271.         ld (hl),0
  272. ;load module
  273.         SC 0x30
  274.         WC
  275. ;open stream
  276.         SC 0xD1
  277.         WC
  278. ;upload file
  279.         ld hl,BUFADDR
  280.         ld bc,MODHEADERSIZE
  281. .uploadloop
  282.         ld a,(hl)
  283.         out (GSDAT),a
  284.         WD
  285.         inc hl
  286.         dec bc
  287.         ld a,b
  288.         or c
  289.         jr nz,.uploadloop
  290.         ld hl,BUFSIZE
  291.         ld de,BUFADDR
  292.         push de
  293.         call readstream_file
  294.         ex (sp),hl
  295.         pop bc
  296.         ld a,b
  297.         or c
  298.         jr nz,.uploadloop
  299.         call closestream_file
  300. ;close stream
  301.         SC 0xD2
  302.         WC
  303. ;play module
  304.         ld a,1
  305.         out (GSDAT),a
  306.         SC 0x31
  307.         WC
  308.         xor a
  309.         ld (currentposition),a
  310.         ld hl,DEVICE_GS_MASK
  311.         ret
  312.  
  313. musicunload
  314.         ld a,(isplayingmodfile)
  315.         or a
  316.         jr nz,unloadmod
  317.         call closestream_file
  318.         jp gscodereset
  319.  
  320. unloadmod
  321.         SC 0xf3
  322.         WC
  323.         ret
  324.  
  325. musicplay
  326. ;out: zf=0 if still playing, zf=1 otherwise
  327. isplayingmodfile=$+1
  328.         ld a,0
  329.         or a
  330.         jr nz,playmod
  331.  
  332. bufferreadptr=$+1
  333.         ld hl,0
  334. bufferdataleft=$+1
  335.         ld bc,0
  336.         ld a,c
  337.         or b
  338.         jr nz,checkifcanupload
  339. readfilechunk
  340.         ld hl,(paddingframecount)
  341.         ld de,150
  342.         sub hl,de
  343.         sbc a
  344.         ret z
  345.         call readdata
  346.         ld hl,BUFADDR
  347.         ex de,hl
  348.         sub hl,de
  349.         ld b,l
  350.         dec hl
  351.         inc h
  352.         ld c,h
  353.         ex de,hl
  354.         jr checkifcanupload
  355.  
  356. uploaddataloop
  357.         ld a,(hl)
  358.         out (GSDAT),a
  359.         WD
  360.         inc hl
  361.         djnz uploaddataloop
  362.         dec c
  363.         jr z,readfilechunk          ;done uploading current chunk
  364.         bit 0,c
  365.         jr z,uploaddataloop         ;poll GS once per 512 bytes
  366. checkifcanupload
  367.         SC CMDGETFREEBUFFERSPACE
  368.         WC
  369.         WN
  370.         GD
  371.         cp 6
  372.         jr nc,uploaddataloop        ;keep uploading until we have less than 1024 free buffer space
  373.         ld (bufferreadptr),hl
  374.         ld (bufferdataleft),bc
  375.         YIELD
  376.         or 1
  377.         ret
  378.  
  379. playmod
  380.         YIELD
  381.         YIELD
  382.         YIELD
  383.         YIELD
  384. ;update progress
  385.         SC 0x60
  386.         WC
  387.         WN
  388.         GD
  389.         push af
  390.         call updateprogress
  391.         pop af
  392. ;check if the position is increasing monotonically
  393.         ld hl,currentposition
  394.         cp (hl)
  395.         ld (hl),a
  396.         ccf
  397.         sbc a
  398.         ret
  399.  
  400. readdata
  401. ;out: de = past-the-end data pointer
  402.         ld hl,(paddingframecount)
  403.         ld a,l
  404.         or h
  405.         ld hl,BUFSIZE
  406.         ld de,BUFADDR
  407.         jr nz,writepadding
  408.         call readstream_file
  409.         ld bc,hl
  410.         ld hl,BUFADDR
  411.         add hl,bc
  412.         ex de,hl
  413.         ld hl,BUFSIZE
  414.         sub hl,bc
  415.         jr nz,writepadding
  416. ;update progress
  417.         ld hl,(filechunkcounter)
  418.         ld de,BUFSIZE>>8 ;256 bytes chunks
  419.         add hl,de
  420.         ld (filechunkcounter),hl
  421.         ld a,h
  422.         call updateprogress
  423.         ld de,(BUFADDR+BUFSIZE)%65536
  424.         ret
  425.  
  426. writepadding
  427.         ld bc,paddingframedata_end-paddingframedata
  428.         sub hl,bc
  429.         ret c
  430.         push hl
  431. paddingframedataptr=$+1
  432.         ld hl,0
  433.         ldir
  434.         ld hl,paddingframedata
  435.         ld (paddingframedataptr),hl
  436. paddingframecount=$+1
  437.         ld hl,0
  438.         inc hl
  439.         ld (paddingframecount),hl
  440.         pop hl
  441.         jr writepadding
  442.  
  443. gshardreset
  444. ;out: b!=0 if got reply from GS, b==0 otherwise
  445.         ld a,C_GRST
  446.         out (GSCTR),a               ;hw reset
  447.         YIELD
  448.         YIELD
  449.         YIELD
  450. gssoftreset
  451.         SC 0xf3                     ;GS reset
  452.         ld b,50                     ;max spins
  453. wcloop
  454.         push bc
  455.         YIELD
  456.         pop bc
  457.         dec b
  458.         ret z
  459.         in a,(GSCOM)
  460.         rrca
  461.         jr c,wcloop
  462.         ret
  463.  
  464. gsstartcode
  465.         ld bc,GSDAT
  466.         ld de,gscode_end-gscode
  467.         ld hl,GSPROGSTART
  468.         out (c),e
  469.         SC 0x14
  470.         WC
  471.         out (c),d
  472.         WD
  473.         out (c),l
  474.         WD
  475.         out (c),h
  476.         WD
  477. ;start upload
  478.         ld hl,gscode
  479. .uploadloop
  480.         outi
  481.         WD
  482.         dec de
  483.         ld a,d
  484.         or e
  485.         jr nz,.uploadloop
  486. ;launch the code
  487.         ld hl,GSPROGSTART
  488.         out (c),l
  489.         SC 0x13
  490.         WC
  491.         out (c),h
  492.         WD
  493. ;the code is starting
  494.         YIELD
  495.         YIELD
  496.         YIELD
  497.         ret
  498.  
  499. getmodtype
  500. ;https://github.com/psbhlw/gs-firmware/blob/6c783a56147511b43d197e4079e993c2b94b4f12/firmware/src/PLAY.a80#L27
  501. ;out: zf=0 for SoundTracker 4/15 file, zf=1 otherwise
  502.         LD A,(BUFADDR+1080)
  503.         CP "M"
  504.         JR Z,TTY1
  505.         CP "4"
  506.         JR Z,TTY1
  507.         CP "F"
  508.         JR Z,TTY1
  509.         ret
  510. TTY1    LD A,(BUFADDR+1081)
  511.         CP "."
  512.         JR Z,TTY2
  513.         CP "L"
  514.         JR Z,TTY2
  515.         CP "!"
  516.         JR Z,TTY2
  517.         CP "C"
  518.         JR Z,TTY2
  519.         ret
  520. TTY2    LD A,(BUFADDR+1082)
  521.         CP "K"
  522.         ret z
  523.         CP "T"
  524.         ret z
  525.         CP "H"
  526.         ret
  527.  
  528. gscodereset
  529.         SC CMDRESET
  530.         WC
  531.         ret
  532.  
  533. firstpaddingframedata
  534.         db 0xFF,0xFB,0x90,0x64,0x00,0x0F,0xF0,0x00,0x00
  535.         db 0x69,0x00,0x00,0x00,0x08,0x00,0x00,0x0D,0x20
  536.         db 0x00,0x00,0x01,0x00,0x00,0x01,0xA4,0x00,0x00
  537.         db 0x00,0x20,0x00,0x00,0x34,0x80,0x00,0x00,0x04
  538.         ds 381,0x55
  539. firstpaddingframedata_end
  540.  
  541. paddingframedata
  542.         db 0xFF,0xFB,0x90,0x64,0x40,0x8F,0xF0,0x00,0x00
  543.         db 0x69,0x00,0x00,0x00,0x08,0x00,0x00,0x0D,0x20
  544.         db 0x00,0x00,0x01,0x00,0x00,0x01,0xA4,0x00,0x00
  545.         db 0x00,0x20,0x00,0x00,0x34,0x80,0x00,0x00,0x04
  546.         ds 381,0x55
  547. paddingframedata_end
  548.  
  549. gscode
  550.         incbin "gscode.bin"
  551. gscode_end
  552.  
  553.         include "../_sdk/file.asm"
  554.         include "progress.asm"
  555.  
  556. SS_VER_VS1001 = 0x00
  557. SS_VER_VS1011 = 0x10
  558. SS_VER_VS1002 = 0x20
  559. SS_VER_VS1003 = 0x30
  560. SS_VER_VS1053 = 0x40
  561. SS_VER_VS8053 = 0x40
  562. SS_VER_VS1033 = 0x50
  563. SS_VER_VS1063 = 0x60
  564. SS_VER_VS1103 = 0x70
  565.  
  566. vsversion
  567.         db 255
  568. idtostr
  569.         db "1001"
  570.         db "1011"
  571.         db "1002"
  572.         db "1003"
  573.         db "1053"
  574.         db "1033"
  575.         db "1063"
  576. ngsinitokstr
  577.         db "NeoGS with VS"
  578. chipidstr
  579.         db "????\r\n",0
  580. gsinitokstr
  581.         db "GS\r\n",0
  582. nodevicestr
  583.         db "no device!\r\n",0
  584. playernamestr
  585.         db "GS/NeoGS",0
  586. playerdisabledstr
  587.         db "disabled!\r\n",0
  588. end
  589.  
  590. currentposition
  591.         ds 1
  592. filechunkcounter
  593.         ds 2
  594. titlestr
  595.         ds TITLELENGTH+1
  596.  
  597.         savebin "mp3.bin",begin,end-begin
  598.