Subversion Repositories NedoOS

Rev

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

  1. ; Video Game Music player
  2. ;
  3. ; Supported sound chips:
  4. ;   AY-3-8910
  5. ;   YM3526 (OPL1), YM3812 (OPL2), YMF262 (OPL3), YMF278B (OPL4)
  6. ;   dual YM2203 (OPN), dual YM2151 (OPM), YM2608 (OPNA)
  7. ;   Y8950 (MSX-AUDIO), YM2612 (OPN2)
  8. ;
  9. ; Known mapping limitations:
  10. ;   YM2612 -> TurboSound-FM or YM2608:
  11. ;     - DAC channel not supported
  12. ;   Dual YM2203 -> YM2608:
  13. ;     - only one SSG available
  14. ;   YM2608 -> TurboSound-FM:
  15. ;     - no ADPCM
  16. ;     - SSG envelope volume differs
  17. ;   Y8950 -> MoonSound:
  18. ;     - no ADPCM without YM2608
  19. ;     - MoonSound + YM2608 provide full feature coverage
  20. ;
  21. ; Custom playback rates via hardware timers:
  22. ;   MoonSound, TurboSound-FM, YM2608
  23.  
  24.         DEVICE ZXSPECTRUM128
  25.         include "../_sdk/sys_h.asm"
  26.         include "playerdefs.asm"
  27.  
  28. HEADER_DATA_OFFSET = 0x8034
  29. HEADER_SIZE_MAX = 256
  30. TITLELENGTH = 64
  31. MEMORYSTREAMMAXPAGES = 250
  32. MEMORYSTREAMERRORMASK = 255 ; TODO: do we need to enforce loading the entire file?
  33.  
  34.         org PLAYERSTART
  35.  
  36. begin   PLAYERHEADER 0
  37.  
  38. isfilesupported
  39. ;cde = file extension
  40. ;out: zf=1 if this player can handle the file and the sound hardware is available, zf=0 otherwise
  41.         ld a,c
  42.         cp 'v'
  43.         ret nz
  44.         ld a,d
  45.         cp 'g'
  46.         ret nz
  47.         ld a,e
  48.         cp 'm'
  49.         ret z
  50.         cp 'z'
  51.         ret
  52.  
  53. cleanupvars
  54. ;out: zf=0 so this function can be used as error handler
  55.         ld hl,playerwindowloading
  56.         ld (CUSTOMUIADDR),hl
  57.         or 255
  58.         jp initprogress
  59.  
  60. playerinit
  61. ;ix = GPSETTINGS
  62. ;a = player page
  63. ;out: zf=1 if init is successful, hl=init message
  64.         ld a,(ix+GPSETTINGS.sharedpages+0) : ld (page8000),a
  65.         ld a,(ix+GPSETTINGS.sharedpages+1) : ld (pageC000),a
  66.         ld a,(ix+GPSETTINGS.sharedpages+2) : ld (filedatapage),a
  67.         ld hl,(ix+GPSETTINGS.drawprogresscallback)
  68.         ld (drawloadingprogress.callback),hl
  69.         ld a,(ix+GPSETTINGS.tfmstatus)
  70.         ld (tfmstatus),a
  71.         cp 1
  72.         call z,enablenormaltfm
  73.         ld a,(ix+GPSETTINGS.moonsoundstatus)
  74.         ld (moonsoundstatus),a
  75.         or a
  76.         call nz,usemoonsoundtimer
  77.         ld a,(ix+GPSETTINGS.opmstatus)
  78.         ld (opmstatus),a
  79.         ld a,(ix+GPSETTINGS.opnastatus)
  80.         ld (opnastatus),a
  81.         or a
  82.         call nz,enableopna
  83. ;hardware detection is done when loading VGM
  84.         call cleanupvars
  85.         ld hl,initokstr
  86.         xor a
  87.         ret
  88.  
  89. enablenormaltfm
  90.         ld a,0x21 ;'ld hl,nn' op
  91.         ld (vgmopninit.callturnturbooff),a
  92.         ld hl,opnsettimer
  93.         ld (settimerproc),hl
  94.         ld hl,opnstoptimers
  95.         ld (stoptimerproc),hl
  96.         ret
  97.  
  98. usemoonsoundtimer
  99.         ld hl,opl4settimer
  100.         ld (settimerproc),hl
  101.         ld hl,opl4stoptimers
  102.         ld (stoptimerproc),hl
  103.         ret
  104.  
  105.         macro a_or_dw addr
  106.         ld hl,(addr+0)
  107.         or h
  108.         or l
  109.         ld de,(addr+2)
  110.         or d
  111.         or e
  112.         endm
  113.  
  114. musicload
  115. ;cde = file extension
  116. ;hl = input file name
  117. ;out: hl = device mask, zf=1 if the file is ready for playing, zf=0 otherwise
  118.         push hl
  119.         ld hl,waittimervsync
  120.         ld (waittimercallback),hl
  121.         ld hl,44100/VSYNC_FREQ
  122.         ld (waittimerstep),hl
  123.         ld a,COLOR_PANEL_FILE
  124.         ld (playerwindowui.ratelabelcolor+CUSTOMUISETCOLOR.color),a
  125.         ld hl,0
  126.         ld (waitcounterlo),hl
  127.         ld (samplecounterlo),hl
  128.         ld (dataoffsetlo),hl
  129.         ld (dataoffsethi),hl
  130.         ld (devicemask),hl
  131.         ld (totaldatablocksizelo),hl
  132.         ld a,l
  133.         ld (samplecounterhi),a
  134.         ld (waitcounterhi),a
  135.         ld (vgmheadercopy),a
  136.         ld (totaldatablocksizehi),a
  137.         ld a,e
  138.         pop de
  139.         cp 'z'
  140.         jr z,.loadcompressed
  141.         call memorystreamloadfile
  142.         jr z,.doneloading
  143.         call turnturboon
  144.         call cleanupvars
  145.         ld hl,(ERRORSTRINGADDR)
  146.         ld a,l
  147.         or h
  148.         ret nz
  149.         ld a,(memorystreamerrorcode)
  150.         dec a
  151.         ret m ;MEMORYSTREAMERROR_SUCCESS
  152.         ld hl,fileioerrorstr
  153.         ld (ERRORSTRINGADDR),hl
  154.         dec a
  155.         ret m ;MEMORYSTREAMERROR_FILEIO
  156.         ld hl,oomerrorstr
  157.         ld (ERRORSTRINGADDR),hl
  158.         dec a
  159.         ret m ;MEMORYSTREAMERROR_OOM
  160.         ld hl,0
  161.         ld (ERRORSTRINGADDR),hl
  162.         dec a
  163.         ret
  164. .loadcompressed
  165.         call decompressfiletomemorystream
  166.         jp nz,cleanupvars
  167. .doneloading
  168. ;setup timer
  169.         ld hl,(HEADER_RECORDING_RATE)
  170.         inc h
  171.         dec h
  172.         jr nz,donesettingtimer
  173.         ld a,l
  174. settimerproc=$+1
  175.         call settimerstub
  176.         jr nz,donesettingtimer
  177.         ld a,12
  178.         ld (playerwindowui.ratelabelcolor+CUSTOMUISETCOLOR.color),a
  179. donesettingtimer
  180. ;setup play progress
  181.         call initprogress
  182.         ld hl,(HEADER_SAMPLES_COUNT+2)
  183.         ld bc,(HEADER_LOOP_SAMPLES_COUNT+2)
  184.         add hl,bc
  185.         inc hl ;+1 as if low-word addition sets cf
  186.         ld a,l
  187.         inc h
  188.         dec h
  189.         jr z,$+4
  190.         ld a,255
  191.         call setprogressdelta
  192. ;check for GD3
  193.         xor a
  194.         ld (titlestr),a
  195.         a_or_dw HEADER_GD3_OFFSET
  196.         call nz,parsegd3
  197. ;setup loop
  198.         xor a
  199.         a_or_dw HEADER_LOOP_OFFSET
  200.         ld (loopoffsetlo),hl
  201.         ld (loopoffsethi),de
  202.         jr z,$+4
  203.         ld a,1
  204.         inc a
  205.         ld (loopcounter),a
  206. ;fill VGM info
  207.         ld hl,(totaldatablocksizelo)
  208.         ld a,(totaldatablocksizehi)
  209.         ld bc,1023
  210.         add hl,bc
  211.         adc a,0
  212.         ld l,h
  213.         srl a : rr l
  214.         srl a : rr l
  215.         ld h,a
  216.         or l
  217.         jr z,.nopcm
  218.         ld de,vgmdatablocksizestr
  219.         call hltodecimalstring
  220.         ld hl,kbytestr
  221.         call strcopy_hltode
  222.         jr .donepcm
  223. .nopcm  ld hl,nonestr
  224.         ld de,vgmdatablocksizestr
  225.         call strcopy_hltode
  226. .donepcm
  227.         ld hl,(HEADER_RECORDING_RATE)
  228.         ld a,h
  229.         or l
  230.         jr z,.zerorate
  231.         ld de,vgmratestr
  232.         call hltodecimalstring
  233.         ld hl,hzstr
  234.         call strcopy_hltode
  235.         jr .donerecordingrate
  236. .zerorate
  237.         ld hl,zeroratestr
  238.         ld de,vgmratestr
  239.         call strcopy_hltode
  240. .donerecordingrate
  241.         ld hl,(HEADER_SAMPLES_COUNT+0) : exx
  242.         ld hl,(HEADER_SAMPLES_COUNT+2) : exx
  243.         ld de,vgmlengthstr
  244.         call samplecounttotimestring
  245.         xor a
  246.         ld hl,(HEADER_LOOP_SAMPLES_COUNT+0) : or h : or l : exx
  247.         ld hl,(HEADER_LOOP_SAMPLES_COUNT+2) : or h : or l : exx
  248.         jr z,.finalizevgminfo
  249.         ld a,' ' : ld (de),a : inc de
  250.         ld a,'+' : ld (de),a : inc de
  251.         ld a,' ' : ld (de),a : inc de
  252.         call samplecounttotimestring
  253. .finalizevgminfo
  254.         ld hl,playerwindowui
  255.         ld (CUSTOMUIADDR),hl
  256. ;start command stream
  257. dataoffsetlo=$+1
  258.         ld hl,0
  259. dataoffsethi=$+1
  260.         ld de,0
  261.         call memorystreamseek
  262.         xor a
  263. devicemask=$+1
  264.         ld hl,0
  265.         ret
  266.  
  267. settimerstub
  268.         or 255
  269. stoptimerstub
  270.         ret
  271.  
  272. checkvgmchip
  273. ;hl = header addr
  274. ;de = chip name string
  275. ;out: zf=1 if not found, zf=0 and c=255 otherwise
  276.         ld a,(hl)
  277.         inc hl
  278.         or (hl)
  279.         inc hl
  280.         or (hl)
  281.         inc hl
  282.         or (hl)
  283.         ret z
  284.         push de
  285.         bit 6,(hl)
  286.         push af
  287. .strend=$+1
  288.         ld hl,0
  289. .strcharleft=$+1
  290.         ld b,0
  291.         ld a,b
  292.         cp VGM_CHIP_STR_MAX_LEN
  293.         jr z,.noseparator
  294.         ld de,chipseparatorstr
  295.         call strncopy_detohl
  296. .noseparator
  297.         pop af
  298.         jr z,.singlechip
  299.         ld de,dualchipstr
  300.         call strncopy_detohl
  301. .singlechip
  302.         pop de
  303.         call strncopy_detohl
  304.         ld (.strend),hl
  305.         ld a,b
  306.         ld (.strcharleft),a
  307.         or 255
  308.         ld c,a
  309.         ret
  310.  
  311.         macro check_vgm_chip headeraddr,straddr
  312.         ld hl,headeraddr
  313.         ld de,straddr
  314.         call checkvgmchip
  315.         endm
  316.  
  317.         macro set_device_mask devicebit
  318.         ld hl,devicemask+devicebit/8
  319.         set devicebit%8,(hl)
  320.         endm
  321.  
  322.         macro check_device_mask devicebit
  323.         ld hl,devicemask+devicebit/8
  324.         bit devicebit%8,(hl)
  325.         endm
  326.  
  327. inithardware
  328. ;out: zf=1 if hardware is found, zf=0 otherwise
  329.         ld hl,vgmchipsstr
  330.         ld (checkvgmchip.strend),hl
  331.         ld a,VGM_CHIP_STR_MAX_LEN
  332.         ld (checkvgmchip.strcharleft),a
  333. ;init AY
  334.         check_vgm_chip HEADER_CLOCK_AY8910,ay8910str
  335.         call nz,initAY8910
  336. ;init OPM
  337.         check_vgm_chip HEADER_CLOCK_YM2151,ym2151str
  338.         call nz,initYM2151
  339.         jp nz,.missinghardwareerror
  340. ;init TFM
  341.         ld c,0
  342.         check_vgm_chip HEADER_CLOCK_YM2203,ym2203str
  343.         check_vgm_chip HEADER_CLOCK_YM2608,ym2608str
  344.         check_vgm_chip HEADER_CLOCK_SN76489,sn76489str
  345.         check_vgm_chip HEADER_CLOCK_YM2612,ym2612str
  346.         inc c
  347.         dec c
  348. .opninitfunc=$+1
  349.         call nz,initYM2203
  350.         jp nz,.missinghardwareerror
  351. ;init Moonsound
  352.         ld c,0
  353.         check_vgm_chip HEADER_CLOCK_Y8950,y8950str
  354.         jr z,.nomsxmusic
  355.         push bc
  356.         check_device_mask DEVICE_OPNA_BIT
  357.         call z,initYM2608
  358.         pop bc
  359. .nomsxmusic
  360.         check_vgm_chip HEADER_CLOCK_YM3526,ym3526str
  361.         check_vgm_chip HEADER_CLOCK_YM3812,ym3812str
  362.         ld a,c
  363.         ld (useYM3812),a
  364.         check_vgm_chip HEADER_CLOCK_YMF262,ymf262str
  365.         inc c
  366.         dec c
  367.         jr nz,.opl4notneeded
  368.         check_vgm_chip HEADER_CLOCK_YMF278B,ymf278bstr
  369.         jr z,.opl4notneeded
  370.         ld a,(moonsoundstatus)
  371.         cp 2
  372.         jr nz,.missinghardwareerror
  373.         or a
  374. .opl4notneeded
  375.         call nz,initYMF278B
  376.         jp nz,.missinghardwareerror
  377. ;zf=0 if there is no supported device
  378.         ld hl,(devicemask)
  379.         ld a,l
  380.         or h
  381.         cp 1
  382.         sbc a,a
  383.         ret z
  384. .missinghardwareerror
  385.         ld hl,missinghardwareerrorstr
  386.         ld (ERRORSTRINGADDR),hl
  387.         ret
  388.  
  389. missinghardwareerrorstr
  390.         db "Unable to initialize the sound device!",0
  391. fileioerrorstr
  392.         db "Unable to read the file!",0
  393. oomerrorstr
  394.         db "Not enough memory to load the module!",0
  395. gziperrorstr
  396.         db "Failed to decompress the file!",0
  397.  
  398. playerdeinit
  399.         ret
  400.  
  401.         include "../_sdk/file.asm"
  402.         define ON_FILE_OPENED_CALLBACK onfileopened
  403.         define ON_DATA_LOADED_CALLBACK ondataloaded
  404.         define UNUSED_PAGE_ADDR page8000
  405.         include "common/memorystream.asm"
  406.         include "common/muldiv.asm"
  407.         include "common/opl4.asm"
  408.         include "vgm/opl4.asm"
  409.         define OPN_ENABLE_FM 1
  410.         include "common/opn.asm"
  411.         include "common/opm.asm"
  412.         include "common/opna.asm"
  413.         include "common/turbo.asm"
  414.         include "vgm/opn.asm"
  415.         include "vgm/opm.asm"
  416.         include "vgm/ssg.asm"
  417.         include "vgm/opna.asm"
  418.         include "progress.asm"
  419.  
  420. ondataloaded
  421. ;output: zf=1 if hardware is found, zf=0 otherwise
  422.         ld a,(memorystreampagecount)
  423.         call updateprogress
  424.         call drawloadingprogress
  425.         ret nz
  426.         call memorystreamgetpos
  427.         push de
  428.         push hl
  429.         ld a,(vgmheadercopy)
  430.         or a
  431.         jr nz,.headerloaded
  432. ;copy header
  433.         ld a,(memorystreampages)
  434.         SETPG8000
  435.         ld bc,HEADER_SIZE_MAX
  436.         ld hl,vgmheadercopy
  437.         ld de,vgmheadercopy+1
  438.         ld (hl),0
  439.         ldir
  440.         ld hl,(HEADER_DATA_OFFSET)
  441.         ld a,h
  442.         or l
  443.         ld bc,0x40
  444.         jr z,$+4
  445.         ld c,0x34
  446.         add hl,bc
  447.         ld (dataoffsetlo),hl
  448.         ld bc,hl
  449.         ld hl,-HEADER_SIZE_MAX-1
  450.         add hl,bc
  451.         jr nc,$+5
  452.         ld bc,HEADER_SIZE_MAX
  453.         ld hl,0x8000
  454.         ld de,vgmheadercopy
  455.         ldir
  456. ;we've got the header, now we know which hardware we need
  457.         call inithardware
  458.         jr z,.checkfirstdatablock
  459.         pop hl
  460.         pop de
  461.         ret
  462. .checkfirstdatablock
  463.         ld hl,(dataoffsetlo)
  464.         ld de,(dataoffsethi)
  465.         push de
  466.         push hl
  467.         call memorystreamseek
  468.         pop hl
  469.         pop de
  470.         call .checkdatablock
  471.         pop hl
  472.         pop de
  473.         push de
  474.         push hl
  475. .headerloaded
  476. .blockendlo=$+1
  477.         ld bc,0
  478.         sub hl,bc
  479. .blockendhi=$+1
  480.         ld bc,0
  481.         ex de,hl
  482.         sbc hl,bc
  483.         jr c,.done
  484. .blockstartlo=$+1
  485.         ld hl,0
  486. .blockstarthi=$+1
  487.         ld de,0
  488.         call memorystreamseek
  489.         call memorystreamread3 ;c = 0x67, e = 0x66, d = data type
  490.         ld e,d
  491.         call processdatablock
  492.         call memorystreamgetpos
  493.         ld (dataoffsetlo),hl
  494.         ld (dataoffsethi),de
  495.         call .checkdatablock
  496. ;free unused pages
  497.         ld hl,(dataoffsetlo)
  498.         ld a,(dataoffsethi)
  499.         add hl,hl : rla
  500.         add hl,hl : rla
  501.         call memorystreamfreecustompagecount
  502. .done   pop hl
  503.         pop de
  504.         call memorystreamseek
  505.         xor a
  506.         ret
  507. .checkdatablock
  508. ;dehl = current stream offset
  509.         ld (.blockstartlo),hl
  510.         ld (.blockstarthi),de
  511.         ld hl,0xffff
  512.         ld (.blockendlo),hl
  513.         ld (.blockendhi),hl
  514.         call memorystreamread3 ;c = 0x67, e = 0x66, d = data type
  515.         ld a,c
  516.         cp 0x67
  517.         ret nz
  518.         ld a,e
  519.         cp 0x66
  520.         ret nz
  521.         call memorystreamread4 ;adbc = data size
  522.         xor a
  523.         ld hl,32 ;include the next data block header
  524.         add hl,bc
  525.         adc a,d
  526.         ld bc,(.blockstartlo)
  527.         add hl,bc
  528.         ld (.blockendlo),hl
  529.         ld l,a
  530.         ld h,0
  531.         ld bc,(.blockstarthi)
  532.         adc hl,bc
  533.         ld (.blockendhi),hl
  534.         ret
  535.  
  536. waittimervsync
  537.         YIELD
  538.         ret
  539.  
  540. musicplay
  541. ;out: zf=0 if still playing, zf=1 otherwise
  542. waittimercallback=$+1
  543.         call 0
  544. playloop
  545. waitcounterlo=$+1
  546.         ld hl,0
  547. waitcounterhi=$+1
  548.         ld a,0
  549. waittimerstep=$+1
  550.         ld bc,0
  551.         sub hl,bc
  552.         ld d,0
  553.         sbc a,d
  554.         jr nc,exitplayloop
  555. ;read command
  556.         memory_stream_read_1 e
  557.         ld hl,cmdtable
  558.         add hl,de
  559.         ld e,(hl)
  560.         inc h
  561.         ld d,(hl)
  562.         ld hl,playloop
  563.         push hl
  564.         ex hl,de
  565.         jp (hl)
  566. exitplayloop
  567.         ld (waitcounterlo),hl
  568.         ld (waitcounterhi),a
  569. ;update progress
  570. samplecounterlo=$+1
  571.         ld hl,0
  572. samplecounterhi=$+1
  573.         ld a,0
  574.         add hl,bc
  575.         adc a,d
  576.         jr nc,$+4
  577.         ld a,255
  578.         ld (samplecounterlo),hl
  579.         ld (samplecounterhi),a
  580.         call updateprogress
  581. ;continue playing
  582.         or 1
  583.         ret
  584.  
  585. wait1   ld hl,waitcounterlo
  586.         inc (hl)
  587.         ret nz
  588.         inc hl
  589.         inc (hl)
  590.         ret nz
  591.         ld hl,waitcounterhi
  592.         inc (hl)
  593.         ret
  594.  
  595. wait2   ld a,2
  596. waitn   ld hl,waitcounterlo
  597.         add a,(hl)
  598.         ld (hl),a
  599.         ret nc
  600.         inc hl
  601.         inc (hl)
  602.         ret nz
  603.         ld hl,waitcounterhi
  604.         inc (hl)
  605.         ret
  606.  
  607. wait3   ld a,3  : jp waitn
  608. wait4   ld a,4  : jp waitn
  609. wait5   ld a,5  : jp waitn
  610. wait6   ld a,6  : jp waitn
  611. wait7   ld a,7  : jp waitn
  612. wait8   ld a,8  : jp waitn
  613. wait9   ld a,9  : jp waitn
  614. wait10  ld a,10 : jp waitn
  615. wait11  ld a,11 : jp waitn
  616. wait12  ld a,12 : jp waitn
  617. wait13  ld a,13 : jp waitn
  618. wait14  ld a,14 : jp waitn
  619. wait15  ld a,15 : jp waitn
  620. wait16  ld a,16 : jp waitn
  621.  
  622. wait735 ld de,735
  623. waitnn  ld hl,(waitcounterlo)
  624.         add hl,de
  625.         ld (waitcounterlo),hl
  626.         ret nc
  627.         ld hl,waitcounterhi
  628.         inc (hl)
  629.         ret
  630.  
  631. wait882 ld de,882
  632.         jp waitnn
  633.  
  634. waitvar memory_stream_read_2 e,d
  635.         jp waitnn
  636.  
  637.         macro skip_n n
  638.         ld b,n
  639.         jp memorystreamskip
  640.         endm
  641.  
  642. skip1   ret
  643. skip2   skip_n 1
  644. skip3   skip_n 2
  645. skip4   skip_n 3
  646. skip5   skip_n 4
  647. skip6   skip_n 5
  648. skip11  skip_n 10
  649. skip12  skip_n 11
  650.  
  651. endofsounddata
  652. loopcounter=$+1
  653.         ld a,0
  654.         dec a
  655.         ld (loopcounter),a
  656.         jp nz,seektoloop
  657. cmdunsupported
  658. ;stop playing
  659.         pop af
  660.         xor a
  661.         ret
  662.  
  663. cmdYM2203_tfm
  664.         memory_stream_read_2 e,d
  665.         jp opnwritemusiconlyfm1
  666.  
  667. cmdYM2203dp_tfm
  668.         memory_stream_read_2 e,d
  669.         jp opnwritemusiconlyfm2
  670.  
  671. cmdYM2612p0_tfm
  672. cmdYM2608p0_tfm
  673.         memory_stream_read_2 e,d
  674.         ld a,e
  675.         cp 0x08
  676.         jp c,opnwritefm1
  677.         cp 0x0b
  678.         jr c,.writessgvolume
  679.         cp 0x28
  680.         jp nz,opnwritemusiconlyfm1
  681.         bit 2,d
  682.         jp z,opnwritefm1
  683.         res 2,d
  684.         jp opnwritefm2
  685. .writessgvolume
  686.         ld a,d
  687.         and 31
  688.         add a,.ssgattenuationtable%256
  689.         ld l,a
  690.         adc a,.ssgattenuationtable/256
  691.         sub l
  692.         ld h,a
  693.         ld d,(hl)
  694.         jp opnwritefm1
  695. .ssgattenuationtable
  696.         db 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03
  697.         db 0x04,0x05,0x05,0x06,0x07,0x07,0x08,0x08
  698.         db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
  699.         db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
  700.  
  701. cmdYM2612p1_tfm
  702. cmdYM2608p1_tfm
  703.         memory_stream_read_2 e,d
  704.         ld a,e
  705.         cp 0x30
  706.         ret c
  707.         jp opnwritefm2
  708.  
  709. cmdYMF278B
  710.         memory_stream_read_3 c,e,d
  711.         dec c
  712.         jp z,opl4writemusiconlyfm2
  713.         jp p,opl4writewavemusiconly
  714.         jp opl4writemusiconlyfm1
  715.  
  716. cmdYMF262p0
  717. cmdYM3812
  718. cmdY8950_opl3
  719. cmdYM3526
  720.         memory_stream_read_2 e,d
  721.         jp opl4writemusiconlyfm1
  722.  
  723. cmdYMF262p1
  724. cmdYM3812dp
  725. cmdY8950dp_opl3
  726. cmdYM3526dp
  727.         memory_stream_read_2 e,d
  728.         jp opl4writemusiconlyfm2
  729.  
  730. cmdYM2151
  731.         memory_stream_read_2 e,d
  732.         jp opmwritemusiconlychip0
  733.  
  734. cmdYM2151dp
  735.         memory_stream_read_2 e,d
  736.         jp opmwritemusiconlychip1
  737.  
  738. cmdAY8910
  739.         memory_stream_read_2 e,d
  740.         bit 7,e
  741.         jp z,ssgwritemusiconlychip0
  742.         res 7,e
  743.         jp ssgwritemusiconlychip1
  744.  
  745. cmdYMF262dp0 equ memorystreamread2
  746. cmdYMF262dp1 equ memorystreamread2
  747.  
  748. cmddatablock
  749.         memory_stream_read_2 a,e ;a = 0x66 guard, e = type
  750.         cp 0x66
  751.         jp nz,cmdunsupported
  752. processdatablock
  753. ;e = data type
  754.         call memorystreamread4 ;adbc = data size
  755. totaldatablocksizelo=$+1
  756.         ld hl,0
  757.         add hl,bc
  758.         ld (totaldatablocksizelo),hl
  759. totaldatablocksizehi=$+1
  760.         ld a,0
  761.         adc a,d
  762.         ld (totaldatablocksizehi),a
  763.         ld a,e
  764.         ld hl,bc
  765.         cp 0x88
  766. y8950datablockhandler=$+1
  767.         jp z,$+3
  768.         cp 0x81
  769. opnadatablockhandler=$+1
  770.         jp z,$+3
  771.         cp 0x84
  772.         jp z,opl4loadromdatablock
  773.         cp 0x87
  774.         jp z,opl4loadramdatablock
  775.         push de
  776.         push bc
  777.         call memorystreamgetpos
  778.         pop bc
  779.         pop af
  780.         add hl,bc
  781.         adc a,e
  782.         ld e,a
  783.         adc a,d
  784.         sub e
  785.         ld d,a
  786.         jp memorystreamseek
  787.  
  788. seektoloop
  789.         ld bc,0x1c
  790. loopoffsethi=$+1
  791.         ld de,0
  792. loopoffsetlo=$+1
  793.         ld hl,0
  794. seektopos
  795. ;dehl + bc = position
  796. ;out: hl = read address
  797.         add hl,bc
  798.         jp nc,memorystreamseek
  799.         inc de
  800.         jp memorystreamseek
  801.  
  802. parsegd3
  803. ;dehl = GD3 offset
  804.         ld bc,32
  805.         call seektopos
  806.         ld b,TITLELENGTH
  807.         ld de,titlestr
  808.         ld a,' '
  809. .fillloop
  810.         ld (de),a
  811.         inc de
  812.         djnz .fillloop
  813.         xor a
  814.         ld (de),a
  815.         ld b,TITLELENGTH
  816.         ld de,titlestr
  817.         call gd3stringcopy   ;track name
  818.         call z,gd3stringskip ;track name in Japanese
  819.         push hl
  820.         ld hl,fromstr
  821.         call z,stringcopy
  822.         pop hl
  823.         call z,gd3stringcopy ;game name
  824.         call z,gd3stringskip ;game name in Japanese
  825.         call z,gd3stringskip ;system name
  826.         call z,gd3stringskip ;system name in Japanese
  827.         push hl
  828.         ld hl,bystr
  829.         call z,stringcopy
  830.         pop hl
  831.         call z,gd3stringcopy ;author
  832.         ld a,b
  833.         cp 57
  834.         ret c
  835.         xor a
  836.         ld (titlestr),a
  837.         ret
  838.  
  839. gd3stringcopy
  840. ;hl = memorystreamcurrentaddr
  841. ;de = dest
  842. ;b = bytes remaining
  843. ;out: zf=1 if encountered zero terminator, zf=0 if out of space
  844.         memory_stream_read_byte a
  845.         memory_stream_read_byte c
  846.         or a
  847.         ret z
  848.         ld (de),a
  849.         inc de
  850.         djnz gd3stringcopy
  851.         ret
  852.  
  853. gd3stringskip
  854. ;hl = memorystreamcurrentaddr
  855. ;out: zf=1
  856.         memory_stream_read_byte a
  857.         memory_stream_read_byte c
  858.         or c
  859.         jr nz,gd3stringskip
  860.         ret
  861.  
  862. stringcopy
  863. ;hl = source
  864. ;de = dest
  865. ;b = bytes remaining
  866. ;out: zf=1 if encountered zero terminator, zf=0 if out of space
  867.         ld a,(hl)
  868.         or a
  869.         ret z
  870.         ld (de),a
  871.         inc hl
  872.         inc de
  873.         djnz stringcopy
  874.         ret
  875.  
  876. cmdtable
  877.         db skip1           %256 ; 00
  878.         db skip1           %256 ; 01
  879.         db skip1           %256 ; 02
  880.         db skip1           %256 ; 03
  881.         db skip1           %256 ; 04
  882.         db skip1           %256 ; 05
  883.         db skip1           %256 ; 06
  884.         db skip1           %256 ; 07
  885.         db skip1           %256 ; 08
  886.         db skip1           %256 ; 09
  887.         db skip1           %256 ; 0A
  888.         db skip1           %256 ; 0B
  889.         db skip1           %256 ; 0C
  890.         db skip1           %256 ; 0D
  891.         db skip1           %256 ; 0E
  892.         db skip1           %256 ; 0F
  893.         db skip1           %256 ; 10
  894.         db skip1           %256 ; 11
  895.         db skip1           %256 ; 12
  896.         db skip1           %256 ; 13
  897.         db skip1           %256 ; 14
  898.         db skip1           %256 ; 15
  899.         db skip1           %256 ; 16
  900.         db skip1           %256 ; 17
  901.         db skip1           %256 ; 18
  902.         db skip1           %256 ; 19
  903.         db skip1           %256 ; 1A
  904.         db skip1           %256 ; 1B
  905.         db skip1           %256 ; 1C
  906.         db skip1           %256 ; 1D
  907.         db skip1           %256 ; 1E
  908.         db skip1           %256 ; 1F
  909.         db skip1           %256 ; 20
  910.         db skip1           %256 ; 21
  911.         db skip1           %256 ; 22
  912.         db skip1           %256 ; 23
  913.         db skip1           %256 ; 24
  914.         db skip1           %256 ; 25
  915.         db skip1           %256 ; 26
  916.         db skip1           %256 ; 27
  917.         db skip1           %256 ; 28
  918.         db skip1           %256 ; 29
  919.         db skip1           %256 ; 2A
  920.         db skip1           %256 ; 2B
  921.         db skip1           %256 ; 2C
  922.         db skip1           %256 ; 2D
  923.         db skip1           %256 ; 2E
  924.         db skip1           %256 ; 2F
  925.         db cmdunsupported  %256 ; 30
  926.         db skip2           %256 ; 31
  927.         db skip2           %256 ; 32
  928.         db skip2           %256 ; 33
  929.         db skip2           %256 ; 34
  930.         db skip2           %256 ; 35
  931.         db skip2           %256 ; 36
  932.         db skip2           %256 ; 37
  933.         db skip2           %256 ; 38
  934.         db skip2           %256 ; 39
  935.         db skip2           %256 ; 3A
  936.         db skip2           %256 ; 3B
  937.         db skip2           %256 ; 3C
  938.         db skip2           %256 ; 3D
  939.         db skip2           %256 ; 3E
  940.         db skip2           %256 ; 3F
  941.         db skip3           %256 ; 40
  942.         db skip3           %256 ; 41
  943.         db skip3           %256 ; 42
  944.         db skip3           %256 ; 43
  945.         db skip3           %256 ; 44
  946.         db skip3           %256 ; 45
  947.         db skip3           %256 ; 46
  948.         db skip3           %256 ; 47
  949.         db skip3           %256 ; 48
  950.         db skip3           %256 ; 49
  951.         db skip3           %256 ; 4A
  952.         db skip3           %256 ; 4B
  953.         db skip3           %256 ; 4C
  954.         db skip3           %256 ; 4D
  955.         db skip3           %256 ; 4E
  956.         db skip2           %256 ; 4F
  957.         db cmdSN76489      %256 ; 50
  958.         db cmdYM2413       %256 ; 51
  959.         db cmdYM2612p0_tfm %256 ; 52
  960.         db cmdYM2612p1_tfm %256 ; 53
  961.         db cmdYM2151       %256 ; 54
  962.         db cmdYM2203_tfm   %256 ; 55
  963.         db cmdYM2608p0_tfm %256 ; 56
  964.         db cmdYM2608p1_tfm %256 ; 57
  965.         db cmdunsupported  %256 ; 58
  966.         db cmdunsupported  %256 ; 59
  967.         db cmdYM3812       %256 ; 5A
  968.         db cmdYM3526       %256 ; 5B
  969.         db cmdY8950_opl3   %256 ; 5C
  970.         db skip3           %256 ; 5D
  971.         db cmdYMF262p0     %256 ; 5E
  972.         db cmdYMF262p1     %256 ; 5F
  973.         db cmdunsupported  %256 ; 60
  974.         db waitvar         %256 ; 61
  975.         db wait735         %256 ; 62
  976.         db wait882         %256 ; 63
  977.         db cmdunsupported  %256 ; 64
  978.         db cmdunsupported  %256 ; 65
  979.         db endofsounddata  %256 ; 66
  980.         db cmddatablock    %256 ; 67
  981.         db skip12          %256 ; 68
  982.         db cmdunsupported  %256 ; 69
  983.         db cmdunsupported  %256 ; 6A
  984.         db cmdunsupported  %256 ; 6B
  985.         db cmdunsupported  %256 ; 6C
  986.         db cmdunsupported  %256 ; 6D
  987.         db cmdunsupported  %256 ; 6E
  988.         db cmdunsupported  %256 ; 6F
  989.         db wait1           %256 ; 70
  990.         db wait2           %256 ; 71
  991.         db wait3           %256 ; 72
  992.         db wait4           %256 ; 73
  993.         db wait5           %256 ; 74
  994.         db wait6           %256 ; 75
  995.         db wait7           %256 ; 76
  996.         db wait8           %256 ; 77
  997.         db wait9           %256 ; 78
  998.         db wait10          %256 ; 79
  999.         db wait11          %256 ; 7A
  1000.         db wait12          %256 ; 7B
  1001.         db wait13          %256 ; 7C
  1002.         db wait14          %256 ; 7D
  1003.         db wait15          %256 ; 7E
  1004.         db wait16          %256 ; 7F
  1005.         db skip1           %256 ; 80
  1006.         db wait1           %256 ; 81
  1007.         db wait2           %256 ; 82
  1008.         db wait3           %256 ; 83
  1009.         db wait4           %256 ; 84
  1010.         db wait5           %256 ; 85
  1011.         db wait6           %256 ; 86
  1012.         db wait7           %256 ; 87
  1013.         db wait8           %256 ; 88
  1014.         db wait9           %256 ; 89
  1015.         db wait10          %256 ; 8A
  1016.         db wait11          %256 ; 8B
  1017.         db wait12          %256 ; 8C
  1018.         db wait13          %256 ; 8D
  1019.         db wait14          %256 ; 8E
  1020.         db wait15          %256 ; 8F
  1021.         db skip5           %256 ; 90
  1022.         db skip5           %256 ; 91
  1023.         db skip6           %256 ; 92
  1024.         db skip11          %256 ; 93
  1025.         db skip2           %256 ; 94
  1026.         db skip5           %256 ; 95
  1027.         db cmdunsupported  %256 ; 96
  1028.         db cmdunsupported  %256 ; 97
  1029.         db cmdunsupported  %256 ; 98
  1030.         db cmdunsupported  %256 ; 99
  1031.         db cmdunsupported  %256 ; 9A
  1032.         db cmdunsupported  %256 ; 9B
  1033.         db cmdunsupported  %256 ; 9C
  1034.         db cmdunsupported  %256 ; 9D
  1035.         db cmdunsupported  %256 ; 9E
  1036.         db cmdunsupported  %256 ; 9F
  1037.         db cmdAY8910       %256 ; A0
  1038.         db skip3           %256 ; A1
  1039.         db cmdunsupported  %256 ; A2
  1040.         db cmdunsupported  %256 ; A3
  1041.         db cmdYM2151dp     %256 ; A4
  1042.         db cmdYM2203dp_tfm %256 ; A5
  1043.         db skip3           %256 ; A6
  1044.         db skip3           %256 ; A7
  1045.         db skip3           %256 ; A8
  1046.         db skip3           %256 ; A9
  1047.         db cmdYM3812dp     %256 ; AA
  1048.         db cmdYM3526dp     %256 ; AB
  1049.         db cmdY8950dp_opl3 %256 ; AC
  1050.         db skip3           %256 ; AD
  1051.         db cmdYMF262dp0    %256 ; AE
  1052.         db cmdYMF262dp0    %256 ; AF
  1053.         db skip3           %256 ; B0
  1054.         db skip3           %256 ; B1
  1055.         db skip3           %256 ; B2
  1056.         db skip3           %256 ; B3
  1057.         db skip3           %256 ; B4
  1058.         db skip3           %256 ; B5
  1059.         db skip3           %256 ; B6
  1060.         db skip3           %256 ; B7
  1061.         db skip3           %256 ; B8
  1062.         db skip3           %256 ; B9
  1063.         db skip3           %256 ; BA
  1064.         db skip3           %256 ; BB
  1065.         db skip3           %256 ; BC
  1066.         db skip3           %256 ; BD
  1067.         db skip3           %256 ; BE
  1068.         db skip3           %256 ; BF
  1069.         db skip4           %256 ; C0
  1070.         db skip4           %256 ; C1
  1071.         db skip4           %256 ; C2
  1072.         db skip4           %256 ; C3
  1073.         db skip4           %256 ; C4
  1074.         db skip4           %256 ; C5
  1075.         db skip4           %256 ; C6
  1076.         db skip4           %256 ; C7
  1077.         db skip4           %256 ; C8
  1078.         db skip4           %256 ; C9
  1079.         db skip4           %256 ; CA
  1080.         db skip4           %256 ; CB
  1081.         db skip4           %256 ; CC
  1082.         db skip4           %256 ; CD
  1083.         db skip4           %256 ; CE
  1084.         db skip4           %256 ; CF
  1085.         db cmdYMF278B      %256 ; D0
  1086.         db skip4           %256 ; D1
  1087.         db cmdunsupported  %256 ; D2
  1088.         db skip4           %256 ; D3
  1089.         db skip4           %256 ; D4
  1090.         db skip4           %256 ; D5
  1091.         db skip4           %256 ; D6
  1092.         db skip4           %256 ; D7
  1093.         db skip4           %256 ; D8
  1094.         db skip4           %256 ; D9
  1095.         db skip4           %256 ; DA
  1096.         db skip4           %256 ; DB
  1097.         db skip4           %256 ; DC
  1098.         db skip4           %256 ; DD
  1099.         db skip4           %256 ; DE
  1100.         db skip4           %256 ; DF
  1101.         db cmdunsupported  %256 ; E0
  1102.         db skip5           %256 ; E1
  1103.         db skip5           %256 ; E2
  1104.         db skip5           %256 ; E3
  1105.         db skip5           %256 ; E4
  1106.         db skip5           %256 ; E5
  1107.         db skip5           %256 ; E6
  1108.         db skip5           %256 ; E7
  1109.         db skip5           %256 ; E8
  1110.         db skip5           %256 ; E9
  1111.         db skip5           %256 ; EA
  1112.         db skip5           %256 ; EB
  1113.         db skip5           %256 ; EC
  1114.         db skip5           %256 ; ED
  1115.         db skip5           %256 ; EE
  1116.         db skip5           %256 ; EF
  1117.         db skip5           %256 ; F0
  1118.         db skip5           %256 ; F1
  1119.         db skip5           %256 ; F2
  1120.         db skip5           %256 ; F3
  1121.         db skip5           %256 ; F4
  1122.         db skip5           %256 ; F5
  1123.         db skip5           %256 ; F6
  1124.         db skip5           %256 ; F7
  1125.         db skip5           %256 ; F8
  1126.         db skip5           %256 ; F9
  1127.         db skip5           %256 ; FA
  1128.         db skip5           %256 ; FB
  1129.         db skip5           %256 ; FC
  1130.         db skip5           %256 ; FD
  1131.         db skip5           %256 ; FE
  1132.         db skip5           %256 ; FF
  1133.         db skip1           /256 ; 00
  1134.         db skip1           /256 ; 01
  1135.         db skip1           /256 ; 02
  1136.         db skip1           /256 ; 03
  1137.         db skip1           /256 ; 04
  1138.         db skip1           /256 ; 05
  1139.         db skip1           /256 ; 06
  1140.         db skip1           /256 ; 07
  1141.         db skip1           /256 ; 08
  1142.         db skip1           /256 ; 09
  1143.         db skip1           /256 ; 0A
  1144.         db skip1           /256 ; 0B
  1145.         db skip1           /256 ; 0C
  1146.         db skip1           /256 ; 0D
  1147.         db skip1           /256 ; 0E
  1148.         db skip1           /256 ; 0F
  1149.         db skip1           /256 ; 10
  1150.         db skip1           /256 ; 11
  1151.         db skip1           /256 ; 12
  1152.         db skip1           /256 ; 13
  1153.         db skip1           /256 ; 14
  1154.         db skip1           /256 ; 15
  1155.         db skip1           /256 ; 16
  1156.         db skip1           /256 ; 17
  1157.         db skip1           /256 ; 18
  1158.         db skip1           /256 ; 19
  1159.         db skip1           /256 ; 1A
  1160.         db skip1           /256 ; 1B
  1161.         db skip1           /256 ; 1C
  1162.         db skip1           /256 ; 1D
  1163.         db skip1           /256 ; 1E
  1164.         db skip1           /256 ; 1F
  1165.         db skip1           /256 ; 20
  1166.         db skip1           /256 ; 21
  1167.         db skip1           /256 ; 22
  1168.         db skip1           /256 ; 23
  1169.         db skip1           /256 ; 24
  1170.         db skip1           /256 ; 25
  1171.         db skip1           /256 ; 26
  1172.         db skip1           /256 ; 27
  1173.         db skip1           /256 ; 28
  1174.         db skip1           /256 ; 29
  1175.         db skip1           /256 ; 2A
  1176.         db skip1           /256 ; 2B
  1177.         db skip1           /256 ; 2C
  1178.         db skip1           /256 ; 2D
  1179.         db skip1           /256 ; 2E
  1180.         db skip1           /256 ; 2F
  1181.         db cmdunsupported  /256 ; 30
  1182.         db skip2           /256 ; 31
  1183.         db skip2           /256 ; 32
  1184.         db skip2           /256 ; 33
  1185.         db skip2           /256 ; 34
  1186.         db skip2           /256 ; 35
  1187.         db skip2           /256 ; 36
  1188.         db skip2           /256 ; 37
  1189.         db skip2           /256 ; 38
  1190.         db skip2           /256 ; 39
  1191.         db skip2           /256 ; 3A
  1192.         db skip2           /256 ; 3B
  1193.         db skip2           /256 ; 3C
  1194.         db skip2           /256 ; 3D
  1195.         db skip2           /256 ; 3E
  1196.         db skip2           /256 ; 3F
  1197.         db skip3           /256 ; 40
  1198.         db skip3           /256 ; 41
  1199.         db skip3           /256 ; 42
  1200.         db skip3           /256 ; 43
  1201.         db skip3           /256 ; 44
  1202.         db skip3           /256 ; 45
  1203.         db skip3           /256 ; 46
  1204.         db skip3           /256 ; 47
  1205.         db skip3           /256 ; 48
  1206.         db skip3           /256 ; 49
  1207.         db skip3           /256 ; 4A
  1208.         db skip3           /256 ; 4B
  1209.         db skip3           /256 ; 4C
  1210.         db skip3           /256 ; 4D
  1211.         db skip3           /256 ; 4E
  1212.         db skip2           /256 ; 4F
  1213.         db cmdSN76489      /256 ; 50
  1214.         db cmdYM2413       /256 ; 51
  1215.         db cmdYM2612p0_tfm /256 ; 52
  1216.         db cmdYM2612p1_tfm /256 ; 53
  1217.         db cmdYM2151       /256 ; 54
  1218.         db cmdYM2203_tfm   /256 ; 55
  1219.         db cmdYM2608p0_tfm /256 ; 56
  1220.         db cmdYM2608p1_tfm /256 ; 57
  1221.         db cmdunsupported  /256 ; 58
  1222.         db cmdunsupported  /256 ; 59
  1223.         db cmdYM3812       /256 ; 5A
  1224.         db cmdYM3526       /256 ; 5B
  1225.         db cmdY8950_opl3   /256 ; 5C
  1226.         db skip3           /256 ; 5D
  1227.         db cmdYMF262p0     /256 ; 5E
  1228.         db cmdYMF262p1     /256 ; 5F
  1229.         db cmdunsupported  /256 ; 60
  1230.         db waitvar         /256 ; 61
  1231.         db wait735         /256 ; 62
  1232.         db wait882         /256 ; 63
  1233.         db cmdunsupported  /256 ; 64
  1234.         db cmdunsupported  /256 ; 65
  1235.         db endofsounddata  /256 ; 66
  1236.         db cmddatablock    /256 ; 67
  1237.         db skip12          /256 ; 68
  1238.         db cmdunsupported  /256 ; 69
  1239.         db cmdunsupported  /256 ; 6A
  1240.         db cmdunsupported  /256 ; 6B
  1241.         db cmdunsupported  /256 ; 6C
  1242.         db cmdunsupported  /256 ; 6D
  1243.         db cmdunsupported  /256 ; 6E
  1244.         db cmdunsupported  /256 ; 6F
  1245.         db wait1           /256 ; 70
  1246.         db wait2           /256 ; 71
  1247.         db wait3           /256 ; 72
  1248.         db wait4           /256 ; 73
  1249.         db wait5           /256 ; 74
  1250.         db wait6           /256 ; 75
  1251.         db wait7           /256 ; 76
  1252.         db wait8           /256 ; 77
  1253.         db wait9           /256 ; 78
  1254.         db wait10          /256 ; 79
  1255.         db wait11          /256 ; 7A
  1256.         db wait12          /256 ; 7B
  1257.         db wait13          /256 ; 7C
  1258.         db wait14          /256 ; 7D
  1259.         db wait15          /256 ; 7E
  1260.         db wait16          /256 ; 7F
  1261.         db skip1           /256 ; 80
  1262.         db wait1           /256 ; 81
  1263.         db wait2           /256 ; 82
  1264.         db wait3           /256 ; 83
  1265.         db wait4           /256 ; 84
  1266.         db wait5           /256 ; 85
  1267.         db wait6           /256 ; 86
  1268.         db wait7           /256 ; 87
  1269.         db wait8           /256 ; 88
  1270.         db wait9           /256 ; 89
  1271.         db wait10          /256 ; 8A
  1272.         db wait11          /256 ; 8B
  1273.         db wait12          /256 ; 8C
  1274.         db wait13          /256 ; 8D
  1275.         db wait14          /256 ; 8E
  1276.         db wait15          /256 ; 8F
  1277.         db skip5           /256 ; 90
  1278.         db skip5           /256 ; 91
  1279.         db skip6           /256 ; 92
  1280.         db skip11          /256 ; 93
  1281.         db skip2           /256 ; 94
  1282.         db skip5           /256 ; 95
  1283.         db cmdunsupported  /256 ; 96
  1284.         db cmdunsupported  /256 ; 97
  1285.         db cmdunsupported  /256 ; 98
  1286.         db cmdunsupported  /256 ; 99
  1287.         db cmdunsupported  /256 ; 9A
  1288.         db cmdunsupported  /256 ; 9B
  1289.         db cmdunsupported  /256 ; 9C
  1290.         db cmdunsupported  /256 ; 9D
  1291.         db cmdunsupported  /256 ; 9E
  1292.         db cmdunsupported  /256 ; 9F
  1293.         db cmdAY8910       /256 ; A0
  1294.         db skip3           /256 ; A1
  1295.         db cmdunsupported  /256 ; A2
  1296.         db cmdunsupported  /256 ; A3
  1297.         db cmdYM2151dp     /256 ; A4
  1298.         db cmdYM2203dp_tfm /256 ; A5
  1299.         db skip3           /256 ; A6
  1300.         db skip3           /256 ; A7
  1301.         db skip3           /256 ; A8
  1302.         db skip3           /256 ; A9
  1303.         db cmdYM3812dp     /256 ; AA
  1304.         db cmdYM3526dp     /256 ; AB
  1305.         db cmdY8950dp_opl3 /256 ; AC
  1306.         db skip3           /256 ; AD
  1307.         db cmdYMF262dp0    /256 ; AE
  1308.         db cmdYMF262dp0    /256 ; AF
  1309.         db skip3           /256 ; B0
  1310.         db skip3           /256 ; B1
  1311.         db skip3           /256 ; B2
  1312.         db skip3           /256 ; B3
  1313.         db skip3           /256 ; B4
  1314.         db skip3           /256 ; B5
  1315.         db skip3           /256 ; B6
  1316.         db skip3           /256 ; B7
  1317.         db skip3           /256 ; B8
  1318.         db skip3           /256 ; B9
  1319.         db skip3           /256 ; BA
  1320.         db skip3           /256 ; BB
  1321.         db skip3           /256 ; BC
  1322.         db skip3           /256 ; BD
  1323.         db skip3           /256 ; BE
  1324.         db skip3           /256 ; BF
  1325.         db skip4           /256 ; C0
  1326.         db skip4           /256 ; C1
  1327.         db skip4           /256 ; C2
  1328.         db skip4           /256 ; C3
  1329.         db skip4           /256 ; C4
  1330.         db skip4           /256 ; C5
  1331.         db skip4           /256 ; C6
  1332.         db skip4           /256 ; C7
  1333.         db skip4           /256 ; C8
  1334.         db skip4           /256 ; C9
  1335.         db skip4           /256 ; CA
  1336.         db skip4           /256 ; CB
  1337.         db skip4           /256 ; CC
  1338.         db skip4           /256 ; CD
  1339.         db skip4           /256 ; CE
  1340.         db skip4           /256 ; CF
  1341.         db cmdYMF278B      /256 ; D0
  1342.         db skip4           /256 ; D1
  1343.         db cmdunsupported  /256 ; D2
  1344.         db skip4           /256 ; D3
  1345.         db skip4           /256 ; D4
  1346.         db skip4           /256 ; D5
  1347.         db skip4           /256 ; D6
  1348.         db skip4           /256 ; D7
  1349.         db skip4           /256 ; D8
  1350.         db skip4           /256 ; D9
  1351.         db skip4           /256 ; DA
  1352.         db skip4           /256 ; DB
  1353.         db skip4           /256 ; DC
  1354.         db skip4           /256 ; DD
  1355.         db skip4           /256 ; DE
  1356.         db skip4           /256 ; DF
  1357.         db cmdunsupported  /256 ; E0
  1358.         db skip5           /256 ; E1
  1359.         db skip5           /256 ; E2
  1360.         db skip5           /256 ; E3
  1361.         db skip5           /256 ; E4
  1362.         db skip5           /256 ; E5
  1363.         db skip5           /256 ; E6
  1364.         db skip5           /256 ; E7
  1365.         db skip5           /256 ; E8
  1366.         db skip5           /256 ; E9
  1367.         db skip5           /256 ; EA
  1368.         db skip5           /256 ; EB
  1369.         db skip5           /256 ; EC
  1370.         db skip5           /256 ; ED
  1371.         db skip5           /256 ; EE
  1372.         db skip5           /256 ; EF
  1373.         db skip5           /256 ; F0
  1374.         db skip5           /256 ; F1
  1375.         db skip5           /256 ; F2
  1376.         db skip5           /256 ; F3
  1377.         db skip5           /256 ; F4
  1378.         db skip5           /256 ; F5
  1379.         db skip5           /256 ; F6
  1380.         db skip5           /256 ; F7
  1381.         db skip5           /256 ; F8
  1382.         db skip5           /256 ; F9
  1383.         db skip5           /256 ; FA
  1384.         db skip5           /256 ; FB
  1385.         db skip5           /256 ; FC
  1386.         db skip5           /256 ; FD
  1387.         db skip5           /256 ; FE
  1388.         db skip5           /256 ; FF
  1389.  
  1390. onfileopened
  1391.         ld a,(filehandle)
  1392.         ld b,a
  1393.         OS_GETFILESIZE
  1394.         ld a,e
  1395. setuploadingprogress
  1396. ;ahl = file size
  1397.         ld de,0x3fff
  1398.         add hl,de
  1399.         adc a,0
  1400.         add hl,hl : rla
  1401.         add hl,hl : rla
  1402.         jp setprogressdelta
  1403.  
  1404. decompressfiletomemorystream
  1405. ;de = input file name
  1406. ;out: zf=1 is successful, zf=0 otherwise
  1407.         call openstream_file
  1408.         or a
  1409.         ret nz
  1410. ;setup progress using the last 4 bytes containing decompressed file size
  1411.         ld a,(filehandle)
  1412.         ld b,a
  1413.         OS_GETFILESIZE
  1414.         ld bc,4
  1415.         sub hl,bc
  1416.         jr nc,$+3
  1417.         dec de
  1418.         ld a,(filehandle)
  1419.         ld b,a
  1420.         OS_SEEKHANDLE
  1421.         ld de,memorystreamsize
  1422.         ld hl,4
  1423.         call readstream_file
  1424.         ld a,(filehandle)
  1425.         ld b,a
  1426.         ld hl,0
  1427.         ld de,hl
  1428.         OS_SEEKHANDLE
  1429.         ld hl,(memorystreamsize+0)
  1430.         ld a,(memorystreamsize+2)
  1431.         call setuploadingprogress
  1432. ;init memory stream
  1433.         xor a
  1434.         ld (memorystreampagecount),a
  1435.         ld hl,0
  1436.         ld (memorystreamsize+0),hl
  1437.         ld (memorystreamsize+2),hl
  1438.         call memorystreamstart
  1439. ;backup the data from app page
  1440.         ld a,(filedatapage)
  1441.         SETPG8000
  1442.         ld hl,GzipWorkBuffersStart
  1443.         ld de,0x8000
  1444.         ld bc,GzipWorkBuffersEnd-GzipWorkBuffersStart
  1445.         ldir
  1446. ;decompress
  1447.         call setsharedpages
  1448.         ld (savedSP),sp
  1449.         call GzipExtract
  1450.         call closestream_file
  1451.         call restoreappdata
  1452.         xor a
  1453.         ret
  1454.  
  1455. restoreappdata
  1456. filedatapage=$+1
  1457.         ld a,0
  1458.         SETPG8000
  1459.         ld hl,0x8000
  1460.         ld de,GzipWorkBuffersStart
  1461.         ld bc,GzipWorkBuffersEnd-GzipWorkBuffersStart
  1462.         ldir
  1463.         ret
  1464.  
  1465. GzipThrowException
  1466. GzipExitWithError
  1467.         ld hl,gziperrorstr
  1468.         ld (ERRORSTRINGADDR),hl
  1469. GzipThrowExceptionNoError
  1470. savedSP=$+1
  1471.         ld sp,0
  1472.         call memorystreamfree
  1473.         call restoreappdata
  1474.         call closestream_file
  1475.         call turnturboon
  1476.         or 1
  1477.         ret
  1478.  
  1479. setsharedpages
  1480. page8000=$+1
  1481.         ld a,0
  1482.         SETPG8000
  1483. pageC000=$+1
  1484.         ld a,0
  1485.         SETPGC000
  1486.         ret
  1487.  
  1488. GzipReadInputBuffer
  1489. ;de = InputBuffer
  1490. ;hl = InputBufSize
  1491.         exx
  1492.         ex af,af'
  1493.         push af,bc,de,hl,ix,iy
  1494.         ld de,InputBuffer
  1495.         ld hl,InputBufSize
  1496.         call readstream_file
  1497.         pop iy,ix,hl,de,bc,af
  1498.         exx
  1499.         ex af,af'
  1500.         ret
  1501.  
  1502. GzipWriteOutputBuffer
  1503. ;de = OutputBuffer
  1504. ;hl = size
  1505.         ld a,l
  1506.         add a,0xff
  1507.         ld a,h
  1508.         adc a,0x3f
  1509.         rlca
  1510.         rlca
  1511.         and 3
  1512.         ret z
  1513.         ld b,a
  1514.         exx
  1515.         ex af,af'
  1516.         push af,bc,de,hl,ix,iy
  1517.         exx
  1518. ;allocate memory
  1519.         ld a,(memorystreampagecount)
  1520.         ld c,a
  1521.         push hl
  1522.         add a,memorystreampages%256
  1523.         ld l,a
  1524.         adc a,memorystreampages/256
  1525.         sub l
  1526.         ld h,a
  1527. .allocloop
  1528.         push bc
  1529.         push hl
  1530.         OS_NEWPAGE
  1531.         or a
  1532.         pop hl
  1533.         pop bc
  1534.         jr z,.pageallocated
  1535.         ld a,c
  1536.         ld (memorystreampagecount),a
  1537.         ld hl,oomerrorstr
  1538.         ld (ERRORSTRINGADDR),hl
  1539.         jp GzipThrowExceptionNoError
  1540. .pageallocated
  1541.         ld (hl),e
  1542.         inc hl
  1543.         inc c
  1544.         djnz .allocloop
  1545.         ld a,c
  1546.         ld (memorystreampagecount),a
  1547.         ld hl,(memorystreamsize+0)
  1548.         ld de,(memorystreamsize+2)
  1549.         push hl
  1550.         push de
  1551.         call memorystreamseek
  1552.         pop bc
  1553.         pop hl
  1554.         pop de
  1555.         add hl,de
  1556.         ld (memorystreamsize+0),hl
  1557.         jr nc,$+7
  1558.         inc bc
  1559.         ld (memorystreamsize+2),bc
  1560.         ex de,hl
  1561.         ld de,OutputBuffer
  1562. ;copy data to memory stream
  1563.         ld bc,hl
  1564.         add hl,de
  1565.         bit 7,h
  1566.         jr z,.below8000
  1567.         push hl
  1568.         ld bc,0x8000-OutputBuffer
  1569.         call memorystreamwrite
  1570.         pop hl
  1571.         res 7,h
  1572.         push hl
  1573.         ld de,0x4000
  1574.         sub hl,de
  1575.         ld a,(page8000)
  1576.         jr c,.write8000
  1577.         jr z,.write8000
  1578.         ex (sp),hl
  1579.         SETPGC000
  1580.         ld de,0xc000
  1581.         ld bc,0x4000
  1582.         call memorystreamwrite
  1583.         ld a,(pageC000)
  1584. .write8000
  1585.         SETPGC000
  1586.         ld de,0xc000
  1587.         pop bc
  1588. .below8000
  1589.         call memorystreamwrite
  1590.         call ondataloaded
  1591.         jp nz,GzipThrowExceptionNoError
  1592.         pop iy,ix,hl,de,bc,af
  1593.         exx
  1594.         ex af,af'
  1595.         jp setsharedpages
  1596.  
  1597. drawloadingprogress
  1598. .callback=$+1
  1599.         jp 0
  1600.  
  1601.         include "common/gunzip.asm"
  1602.  
  1603. initAY8910
  1604.         call ssginit
  1605.         ld a,(HEADER_CLOCK_AY8910+3)
  1606.         and 0x40
  1607.         jr nz,.dualchip
  1608.         set_device_mask DEVICE_AY_BIT
  1609.         ret
  1610. .dualchip
  1611.         set_device_mask DEVICE_TURBOSOUND_BIT
  1612.         ret
  1613.  
  1614. initYM2608
  1615. opnastatus=$+1
  1616.         ld a,0
  1617.         dec a
  1618.         ret m
  1619.         call vgmopnainit
  1620.         set_device_mask DEVICE_OPNA_BIT
  1621.         xor a
  1622.         ret
  1623.  
  1624. initYM2203
  1625. tfmstatus=$+1
  1626.         ld a,0
  1627.         dec a
  1628.         ret m
  1629.         call vgmopninit
  1630.         set_device_mask DEVICE_TFM_BIT
  1631.         xor a
  1632.         ret
  1633.  
  1634. initYMF278B
  1635. moonsoundstatus=$+1
  1636.         ld a,0
  1637.         dec a
  1638.         ret m
  1639.         call vgmopl4init
  1640.         ld a,(HEADER_CLOCK_YM3812+3)
  1641.         ld hl,HEADER_CLOCK_YM3526+3
  1642.         or (hl)
  1643.         ld hl,HEADER_CLOCK_Y8950+3
  1644.         or (hl)
  1645.         and 0x40
  1646.         jr nz,notOPL2
  1647. useYM3812=$+1
  1648.         or 0
  1649.         ld de,0x0005
  1650.         call nz,opl4writefm2
  1651. notOPL2
  1652.         set_device_mask DEVICE_MOONSOUND_BIT
  1653.         xor a
  1654.         ret
  1655.  
  1656. initYM2151
  1657. opmstatus=$+1
  1658.         ld a,0
  1659.         dec a
  1660.         ret m
  1661.         jr nz,.hasdualopm
  1662.         call opmdisablechip1
  1663.         ld a,(HEADER_CLOCK_YM2151+3)
  1664.         and 0x40
  1665.         ret nz
  1666. .hasdualopm
  1667.         call opminit
  1668.         ld a,(HEADER_CLOCK_YM2151+3)
  1669.         and 0x40
  1670.         jr nz,.dualchip
  1671.         set_device_mask DEVICE_OPM_BIT
  1672.         xor a
  1673.         ret
  1674. .dualchip
  1675.         set_device_mask DEVICE_DUAL_OPM_BIT
  1676.         xor a
  1677.         ret
  1678.  
  1679. musicunload
  1680. stoptimerproc=$+1
  1681.         call stoptimerstub
  1682.         check_device_mask DEVICE_MOONSOUND_BIT
  1683.         call nz,opl4mute
  1684.         check_device_mask DEVICE_TFM_BIT
  1685.         call nz,vgmopnmute
  1686.         check_device_mask DEVICE_AY_BIT
  1687.         call nz,ssgmute
  1688.         check_device_mask DEVICE_TURBOSOUND_BIT
  1689.         call nz,ssgmute
  1690.         check_device_mask DEVICE_OPM_BIT
  1691.         call nz,opmmute
  1692.         check_device_mask DEVICE_DUAL_OPM_BIT
  1693.         call nz,opmmute
  1694.         check_device_mask DEVICE_OPNA_BIT
  1695.         call nz,opnamute
  1696.         call cleanupvars
  1697.         jp memorystreamfree
  1698.  
  1699.         macro set_cmd_handler cmd,handler
  1700.         ld hl,cmdtable+cmd
  1701.         ld (hl),handler%256
  1702.         inc h
  1703.         ld (hl),handler/256
  1704.         endm
  1705.  
  1706. enableopna
  1707.         ld hl,initYM2608
  1708.         ld (inithardware.opninitfunc),hl
  1709.         ld hl,opnaloaddatablock
  1710.         ld (opnadatablockhandler),hl
  1711.         ld hl,y8950loaddatablock_opna
  1712.         ld (y8950datablockhandler),hl
  1713.         ld hl,opnasettimer
  1714.         ld (settimerproc),hl
  1715.         ld hl,opnastoptimers
  1716.         ld (stoptimerproc),hl
  1717.         set_cmd_handler 0x52,cmdYM2612p0_opna
  1718.         set_cmd_handler 0x53,cmdYM2612p1_opna
  1719.         set_cmd_handler 0x55,cmdYM2203_opna
  1720.         set_cmd_handler 0x56,cmdYM2608p0_opna
  1721.         set_cmd_handler 0x57,cmdYM2608p1_opna
  1722.         set_cmd_handler 0x5c,cmdY8950_opna
  1723.         set_cmd_handler 0xa5,cmdYM2203dp_opna
  1724.         ret
  1725.  
  1726. cmdY8950_opna
  1727. ; MSX-AUDIO is an evolutionary design: an OPL1 FM synth combined with the Delta-T engine,
  1728. ; which later became a standard component in chips such as YM2608 and YM2610.
  1729.         memory_stream_read_2 e,d
  1730.         ld a,e
  1731.         cp 0x20
  1732.         jp nc,opl4writefm1
  1733.         cp 0x13
  1734.         ret nc
  1735.         sub 0x07
  1736.         ret c
  1737.         ld e,a
  1738.         cp 0x09
  1739.         jr z,.convertdeltanlo
  1740.         cp 0x0a
  1741.         jr z,.convertdeltanhi
  1742.         cp 0x0b
  1743.         jr z,.adpcmvolume
  1744.         dec a
  1745.         jp nz,opnawritemusiconlyfm2
  1746.         ld a,d
  1747.         and %00000100
  1748.         or %11000000
  1749.         ld d,a
  1750.         jp opnawritectrl2
  1751. .convertdeltanlo
  1752.         ld a,d
  1753.         ld (.deltan),a
  1754. .writeconverteddeltan
  1755. .deltan=$+1
  1756.         ld hl,0
  1757. ;scale deltaN by 224/256
  1758.         ld d,l
  1759.         ld b,h
  1760.         xor a
  1761.         ld e,a
  1762.         add hl,hl : rla
  1763.         add hl,hl : rla
  1764.         add hl,hl : rla
  1765.         add hl,hl : rla
  1766.         add hl,hl : rla
  1767.         ex de,hl
  1768.         ld c,a
  1769.         ld a,b
  1770.         sbc hl, de : sbc a,c
  1771. ;a:hl = deltaN*224
  1772.         ld d,a
  1773.         ld e,0x0a
  1774.         call opnawritefm2
  1775.         ld d,h
  1776.         dec e
  1777.         jp opnawritefm2
  1778. .convertdeltanhi
  1779.         ld a,d
  1780.         ld (.deltan+1),a
  1781.         jr .writeconverteddeltan
  1782. .adpcmvolume
  1783. ;RE2-Y2608 is way too loud vs. MoonSound
  1784.         srl d
  1785.         srl d
  1786.         srl d
  1787.         jp opnawritefm2
  1788.  
  1789. y8950loaddatablock_opna
  1790.         call opnaloaddatablock
  1791.         ld de,0xc001 ;force LR on
  1792.         jp opnawritectrl2
  1793.  
  1794. cmdYM2203_opna
  1795.         memory_stream_read_2 e,d
  1796.         opn_write_music_only opnawritefm1
  1797.         ret
  1798.  
  1799. cmdYM2203dp_opna
  1800.         memory_stream_read_2 e,d
  1801.         ld a,e
  1802.         cp 0x30
  1803.         jp nc,opnawritefm2
  1804.         cp 0x28
  1805.         ret nz
  1806.         set 2,d
  1807.         jp opnawritefm1
  1808.  
  1809. cmdYM2612p0_opna
  1810. cmdYM2608p0_opna
  1811.         memory_stream_read_2 e,d
  1812.         jp opnawritemusiconlyfm1
  1813.  
  1814. cmdYM2612p1_opna
  1815. cmdYM2608p1_opna
  1816.         memory_stream_read_2 e,d
  1817.         jp opnawritemusiconlyfm2
  1818.  
  1819. cmdSN76489
  1820.         memory_stream_read_1 a
  1821.         ret
  1822.  
  1823. cmdYM2413
  1824.         memory_stream_read_2 e,d
  1825.         ret
  1826.  
  1827. hltodecimalstring
  1828. ;hl = number
  1829. ;de = string buffer
  1830.         ld ixl,e
  1831.         ld bc,-10000
  1832.         inc ixl
  1833.         call .writedigit
  1834.         ld bc,-1000
  1835.         call .writedigit
  1836.         ld bc,-100
  1837.         call .writedigit
  1838.         ld bc,-10
  1839.         call .writedigit
  1840.         ld bc,-1
  1841.         dec ixl ;ensure the last zero is printed
  1842.         call .writedigit
  1843.         xor a
  1844.         ld (de),a
  1845.         ret
  1846. .writedigit
  1847.         ld a,'0'-1
  1848.         inc a
  1849.         add hl,bc
  1850.         jr c,$-2
  1851.         sbc hl,bc
  1852.         ld (de),a
  1853.         inc de
  1854.         cp '0'
  1855.         ret nz
  1856. ;remove leading zeroes
  1857.         ld a,e
  1858.         cp ixl
  1859.         ret nz
  1860.         dec de
  1861.         ret
  1862.  
  1863. samplecounttotimestring
  1864. ;hl'hl = 32 bit sample count
  1865. ;de = string buffer
  1866.         ld bc,-2646000&0xffff
  1867.         exx
  1868.         ld bc,-2646000>>16
  1869.         exx
  1870.         call .writefield ;minutes
  1871.         ld a,':'
  1872.         ld (de),a
  1873.         inc de
  1874.         ld bc,-44100&0xffff
  1875.         exx
  1876.         ld bc,-44100>>16
  1877.         exx
  1878.         call .writefield ;seconds
  1879.         xor a
  1880.         ld (de),a
  1881.         ret
  1882. .writefield
  1883.         ld a,255
  1884. .loop   inc a
  1885.         add hl,bc : exx
  1886.         adc hl,bc : exx
  1887.         jr c,.loop
  1888.         sbc hl,bc : exx
  1889.         sbc hl,bc : exx
  1890.         ld bc,0x2ff6 ;b='0'-1, c=-10
  1891.         inc b
  1892.         add a,c
  1893.         jr c,$-2
  1894.         ex de,hl
  1895.         ld (hl),b
  1896.         ex de,hl
  1897.         inc de
  1898.         add a,'0'+10
  1899.         ld (de),a
  1900.         inc de
  1901.         ret
  1902.  
  1903. strncopy_detohl
  1904. ;de = source string
  1905. ;hl = destionation buffer
  1906. ;b = max. characters to write
  1907.         inc b
  1908.         dec b
  1909.         ret z
  1910. .loop   ld a,(de)
  1911.         ld (hl),a
  1912.         or a
  1913.         ret z
  1914.         inc hl
  1915.         inc de
  1916.         djnz .loop
  1917.         ld (hl),b
  1918.         ret
  1919.  
  1920. strcopy_hltode
  1921.         ld a,(hl)
  1922.         ld (de),a
  1923.         or a
  1924.         ret z
  1925.         inc hl
  1926.         inc de
  1927.         jr strcopy_hltode
  1928.  
  1929. vgmchipstextstr db "Chips: "
  1930. VGM_CHIP_STR_MAX_LEN = 27
  1931. vgmchipsstr ds VGM_CHIP_STR_MAX_LEN+1
  1932. chipseparatorstr db ", ",0
  1933. dualchipstr db "Dual-",0
  1934. ay8910str db "AY8910",0
  1935. sn76489str db "SN76489",0
  1936. ym2151str db "YM2151",0
  1937. ym2203str db "YM2203",0
  1938. ym2608str db "YM2608",0
  1939. ym2612str db "YM2612",0
  1940. y8950str db "MSX-AUDIO",0
  1941. ym3526str db "YM3526",0
  1942. ym3812str db "YM3812",0
  1943. ymf262str db "YMF262",0
  1944. ymf278bstr db "YMF278B",0
  1945. vgmdatablocktextstr db "(AD)PCM Samples: "
  1946. vgmdatablocksizestr ds 10
  1947. nonestr db "None",0
  1948. kbytestr db "KB",0
  1949. vgmratetextstr db "Recording Rate: "
  1950. vgmratestr ds 10
  1951. hzstr db "Hz",0
  1952. zeroratestr db "Undefined",0
  1953. vgmlengthtextstr db "Length: "
  1954. vgmlengthstr ds 12
  1955.  
  1956. initokstr
  1957.         db "OK\r\n",0
  1958. playernamestr
  1959.         db "VGM Player",0
  1960. fromstr
  1961.         db " [",0
  1962. bystr
  1963.         db "] by ",0
  1964. loadingtitlestr
  1965.         db "Loading video game music...",0
  1966. playerwindowloading
  1967.         PROGRESSIVELOADINGWINDOWTEMPLATE loadingtitlestr,musicprogress+1
  1968.  
  1969. playerwindowui
  1970.         CUSTOMUISETCOLOR ,COLOR_PANEL
  1971.         CUSTOMUIDRAWWINDOW ,6,8,66,7
  1972.         CUSTOMUISETCOLOR ,15
  1973.         CUSTOMUISEPARATOR ,7,13,64,196,196,196
  1974.         CUSTOMUIPLAYERWINDOWTITLE ,8,8
  1975.         CUSTOMUISONGTITLE ,8,10,titlestr
  1976.         CUSTOMUIPLAYPROGRESS ,8,11,musicprogress+1
  1977.         CUSTOMUIPLAYTIME ,67,8
  1978.         CUSTOMUISETCOLOR ,COLOR_PANEL_FILE
  1979.         CUSTOMUIPRINTTEXT ,10,14,vgmchipstextstr
  1980.         CUSTOMUIPRINTTEXT ,9,15,vgmlengthtextstr
  1981.         CUSTOMUIPRINTTEXT ,45,14,vgmdatablocktextstr
  1982. .ratelabelcolor
  1983.         CUSTOMUISETCOLOR ,COLOR_PANEL_FILE
  1984.         CUSTOMUIPRINTTEXT ,46,15,vgmratetextstr
  1985.         CUSTOMUIDRAWEND
  1986. end
  1987.  
  1988. GzipWorkBuffersStart = SYSTEM_MEMORY_END
  1989. vgmheadercopy = $
  1990. vgmheadercopyend = vgmheadercopy+HEADER_SIZE_MAX
  1991. GzipOutputBuffersStart = vgmheadercopyend
  1992. waveheaderbuffer = vgmheadercopyend
  1993. waveheaderbufferend = waveheaderbuffer+WAVEHEADERBUFFERSIZE
  1994. titlestr = waveheaderbufferend
  1995. titlestrend = titlestr+TITLELENGTH
  1996.  
  1997. HEADER_CLOCK_SN76489 = vgmheadercopy+0x0c
  1998. HEADER_GD3_OFFSET    = vgmheadercopy+0x14
  1999. HEADER_SAMPLES_COUNT = vgmheadercopy+0x18
  2000. HEADER_LOOP_OFFSET   = vgmheadercopy+0x1c
  2001. HEADER_LOOP_SAMPLES_COUNT = vgmheadercopy+0x20
  2002. HEADER_RECORDING_RATE= vgmheadercopy+0x24
  2003. HEADER_CLOCK_YM2612  = vgmheadercopy+0x2c
  2004. HEADER_CLOCK_YM2151  = vgmheadercopy+0x30
  2005. HEADER_CLOCK_YM2203  = vgmheadercopy+0x44
  2006. HEADER_CLOCK_YM2608  = vgmheadercopy+0x48
  2007. HEADER_CLOCK_YM3812  = vgmheadercopy+0x50
  2008. HEADER_CLOCK_YM3526  = vgmheadercopy+0x54
  2009. HEADER_CLOCK_Y8950   = vgmheadercopy+0x58
  2010. HEADER_CLOCK_YMF262  = vgmheadercopy+0x5c
  2011. HEADER_CLOCK_YMF278B = vgmheadercopy+0x60
  2012. HEADER_CLOCK_AY8910  = vgmheadercopy+0x74
  2013.  
  2014.         assert vgmheadercopyend <= PLAYEREND ;ensure everything is within the player page
  2015.         assert GzipOutputBuffersEnd <= 0x10000
  2016.         assert GzipWorkBuffersEnd <= 0x3500 ;ensure the buffers and stack are not overlapping
  2017.  
  2018.         savebin "vgm.bin",begin,end-begin
  2019.