Subversion Repositories NedoOS

Rev

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

  1.         DEVICE ZXSPECTRUM128
  2.         include "gsports.asm"
  3.         include "gscodedefs.asm"
  4.         include "vs10xx.asm"
  5.  
  6. XTALI_FREQ = 14000000 ;14mhz on NGS
  7. CLOCKF_VS1011 = 0x8000|((XTALI_FREQ+1000)/2000) ;28mhz
  8. CLOCKF_VS1033 = ((XTALI_FREQ-8000000+2000)/4000)|SC_MULT_03_35X|SC_ADD_03_00X ;49mhz
  9. CLOCKF_VS1053 = ((XTALI_FREQ-8000000+2000)/4000)|SC_MULT_53_40X|SC_ADD_53_00X ;56mhz
  10.  
  11.         MACRO WDC
  12. ;       in a,(SSTAT)
  13. ;       and M_MCRDY
  14. ;       jr z,$-4
  15. ;TODO: why MCRDY polling works fine on real hardware, but not in UnrealSpeccy?
  16. ;Neo Player Light does this
  17.         call noper
  18.         ENDM
  19.  
  20.         MACRO WDD
  21.         in a,(SSTAT)
  22.         rrca
  23.         jr nc,$-3
  24.         ENDM
  25.  
  26.         MACRO ATOZX
  27.         out (ZXDATWR),a
  28.         in a,(ZXSTAT)
  29.         rlca
  30.         jr c,$-3
  31.         ENDM
  32.  
  33.         MACRO CALCFREEBUFFERSPACE
  34.         ld a,h
  35.         sub d
  36.         and 0x7f
  37.         ENDM
  38.  
  39.         MACRO LOAD256 IENABLED
  40. .loadloop
  41.         in a,(ZXSTAT)                         ;check if data or command is pending
  42.         and M_CBIT|M_DBIT
  43.         jr z,.loadloop
  44.         rlca
  45.         jr c,.loaddata
  46. ;got command
  47.         IF IENABLED
  48.         di
  49.         ENDIF
  50.         call processcommand
  51.         IF IENABLED
  52.         ei
  53.         ENDIF
  54.         jr .loadloop
  55. .loaddata
  56.         in a,(ZXDATRD)
  57.         ld (de),a
  58.         inc e
  59.         jr nz,.loadloop
  60.         inc d
  61.         ENDM
  62.  
  63.         org GSPROGSTART
  64. begin   di
  65.         ld sp,GSSTACKADDR
  66.         call checkifngs
  67. ;uploading is done via interrupt handler
  68.         ld hl,interrupthandler
  69.         ld (GSINTERRUPTTABLEENTRYADDR),hl
  70.         ld a,GSINTERRUPTTABLEENTRYADDR>>8
  71.         ld i,a
  72.         im 2
  73.         call mutemod
  74.         ld a,%10011100
  75.         out (SCTRL),a
  76. ;set ngs to 10mhz
  77.         ld d,C_10MHZ
  78.         call ngssetfreq
  79. ;hw decoder reset
  80.         ld a,M_MPXRS
  81.         out (SCTRL),a
  82.         WDC
  83. ;clear reset signal
  84.         ld a,M_MPXRS|M_SETNCLR
  85.         out (SCTRL),a
  86. ;go to 12mhz
  87.         ld d,C_12MHZ
  88.         call ngssetfreq
  89. ;write to a register after reset
  90.         ld l,SCI_VOL
  91.         ld de,SV_SILENCE
  92.         call vswriteregister
  93. ;read chip id
  94.         ld l,SCI_STATUS
  95.         call vsreadregister
  96.         ld a,e
  97.         and SS_VER_MASK
  98.         ld (vsversion),a
  99. ;set an arbitrary writable page for the ring buffer in 0x8000...0xffff
  100.         ld a,2
  101.         out (MPAG),a
  102. startnewstream
  103.         call vssoftreset                      ;reset decoder setting SDI to compatibility mode
  104. ;start preloading
  105.         ld a,255
  106.         ld (streaminfobyte),a
  107.         ld h,0x70
  108.         ld de,0x8000                          ;de is ring buffer write pointer
  109. preloadloop
  110.         LOAD256 0
  111.         ld a,d
  112.         cp 0xdf
  113.         jr c,preloadloop
  114. ;start uploading
  115.         ld hl,0x8000                          ;hl is ring buffer read pointer
  116.         ei
  117. mainloop
  118.         in a,(ZXSTAT)                         ;check if a command is pending
  119.         rrca
  120.         jr nc,.checkifcandownload
  121. ;handle command
  122.         di
  123.         call processcommand
  124.         ei
  125.         jr mainloop
  126. .checkifcandownload
  127.         CALCFREEBUFFERSPACE
  128.         cp 3
  129.         jr c,mainloop                         ;keep read and write addresses of the ring buffer at least 256 bytes apart
  130.         LOAD256 1
  131.         set 7,d
  132.         jr mainloop
  133.  
  134. interrupthandler
  135.         push af
  136.         push bc
  137.         ld a,d
  138.         sub h
  139.         and 0x7f
  140.         cp 3
  141.         jr c,.skipupload                      ;keep read and write addresses of the ring buffer at least 256 bytes apart
  142.         in a,(SSTAT)
  143.         rrca
  144.         jr nc,.skipupload                     ;update stream info if data is not requested
  145.         ld b,32                               ;upload 32 bytes
  146. .uploadloop
  147.         ld a,(hl)
  148.         out (MD_SEND),a
  149.         inc hl
  150.         djnz .uploadloop
  151.         bit 7,h                               ;check if the address wrapped to 0x0000
  152.         call z,updatestreaminfo
  153. ;blink LED
  154. ;       ld a,h
  155. ;       rlca
  156. ;       rlca
  157. ;       out (LEDCTR),a
  158. .skipupload
  159.         pop bc
  160.         pop af
  161.         ei
  162.         ret
  163.  
  164. updatestreaminfo
  165.         push hl
  166.         push de
  167.         ld l,SCI_HDAT1
  168.         call vsreadregister
  169.         push de
  170.         ld l,SCI_HDAT0
  171.         call vsreadregister
  172.         pop bc
  173.         ld a,b
  174.         cp 255
  175.         jr nz,.notmpeg
  176.         ld a,d
  177.         rrca
  178.         rrca
  179.         rrca
  180.         rrca
  181.         and %00001111
  182.         ld b,a
  183.         ld a,c
  184.         rlca
  185.         rlca
  186.         rlca
  187.         and %11110000
  188.         or b
  189.         add mp3bitratestringlookup%256
  190.         ld l,a
  191.         adc mp3bitratestringlookup/256
  192.         sub l
  193.         ld h,a
  194.         ld a,e
  195.         rrca
  196.         and %01100000
  197.         or (hl)
  198. .setstreaminfo
  199.         ld (streaminfobyte),a
  200.         pop de
  201.         pop hl
  202.         set 7,h                               ;wrap the address to 0x8000
  203.         ret
  204. .notmpeg
  205.         cp 'A'
  206.         jr nz,.notaac
  207.         ld a,c
  208.         cp 'T'
  209.         jr z,$+6
  210.         cp 'D'
  211.         jr nz,.unsupportedstream
  212.         xor a
  213. .getbitratestringindex
  214.         ld hl,0x0380
  215.         add hl,de
  216.         rr h
  217.         srl h
  218.         ld l,h
  219.         ld h,0
  220.         ld de,bitratestringlookup
  221.         add hl,de
  222.         or (hl)
  223.         jr .setstreaminfo
  224. .notaac
  225.         cp 'O'
  226.         jr nz,.unsupportedstream
  227.         ld a,c
  228.         cp 'g'
  229.         ld a,%01000000
  230.         jr z,.getbitratestringindex
  231. .unsupportedstream
  232.         ld a,255
  233.         jr .setstreaminfo
  234.  
  235. mp3bitratestringlookup
  236. ;lookup_index = (id<<6) | (layer<<4) | bitrate_index
  237.         db 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152
  238.         db 152,128,129,130,131,132,133,134,135,136,137,138,139,140,141,152
  239.         db 152,128,129,130,131,132,133,134,135,136,137,138,139,140,141,152
  240.         db 152,131,133,134,135,136,137,138,139,140,141,142,143,144,145,152
  241.         db 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152
  242.         db 152,128,129,130,131,132,133,134,135,136,137,138,139,140,141,152
  243.         db 152,128,129,130,131,132,133,134,135,136,137,138,139,140,141,152
  244.         db 152,131,133,134,135,136,137,138,139,140,141,142,143,144,145,152
  245.         db 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152
  246.         db 152,128,129,130,131,132,133,134,135,136,137,138,139,140,141,152
  247.         db 152,128,129,130,131,132,133,134,135,136,137,138,139,140,141,152
  248.         db 152,131,133,134,135,136,137,138,139,140,141,142,143,144,145,152
  249.         db 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152
  250.         db 152,131,132,133,134,135,136,137,138,139,141,143,144,145,147,152
  251.         db 152,131,133,134,135,136,137,138,139,141,143,144,145,147,149,152
  252.         db 152,131,135,137,139,141,143,144,145,146,147,148,149,150,151,152
  253.  
  254. bitratestringlookup
  255. ;lookup_index = (HDAT0*8/1024 + 7)/8
  256.         db 0,0,1,2,3,4,5,6
  257.         db 7,8,8,9,9,10,10,11
  258.         db 11,12,12,13,13,14,14,15
  259.         db 15,16,16,16,16,17,17,17
  260.         db 17,18,18,18,18,19,19,19
  261.         db 19,20,20,20,20,21,21,21
  262.         db 21,22,22,22,22,23,23,23
  263.         db 23,23,23,23,23,23,23,23
  264.         db 23
  265.  
  266. vssoftreset
  267.         ld l,SCI_VOL
  268.         ld de,SV_SILENCE
  269.         call vswriteregister                  ;set volume to minimum
  270.         ld l,SCI_MODE
  271.         call vsreadregister
  272.         ld a,e
  273.         xor SM_RESET
  274.         ld e,a
  275.         ld a,d
  276.         and ~(SM_SDINEW>>8)                   ;NGS implements compatibility mode only
  277.         ld d,a
  278.         call vswriteregister                  ;reset
  279.         ld a,e
  280.         xor SM_RESET
  281.         ld e,a
  282.         call vswriteregister                  ;clear reset
  283. volumevalue=$+1
  284.         ld de,0
  285.         ld l,SCI_VOL
  286.         call vswriteregister                  ;restore volume
  287.         call vsclockvalue
  288.         ld l,SCI_CLOCKF
  289.         call vswriteregister                  ;set internal clock
  290. vsversion=$+1
  291.         ld a,255
  292.         cp SS_VER_VS1001
  293.         ret nz
  294.         ld l,0x02                             ;Force the clock-doubler on by writing 0x8008 to SCI_INT_FCTLH.
  295.         ld de,0x8008                          ;The datasheet states that you should never write to this register.
  296.         jr vswriteregister                    ;This is, however, an exception.
  297.  
  298. ;l = register
  299. ;de = value
  300. vswriteregister
  301.         WDD
  302.         WDC
  303.         ld a,M_MCNCS
  304.         out (SCTRL),a                         ;SCI start
  305.         WDC
  306.         ld bc,MC_SEND
  307.         ld a,2
  308.         out (c),a                             ;write op
  309.         WDC
  310.         out (c),l                             ;which register
  311.         WDC
  312.         out (c),d                             ;high byte
  313.         WDC
  314.         out (c),e                             ;low byte
  315.         WDC
  316.         ld a,M_MCNCS|M_SETNCLR
  317.         out (SCTRL),a                         ;SCI end
  318.         WDC
  319.         ret
  320.  
  321. ;l = register
  322. ;out: de = value
  323. vsreadregister
  324.         WDD
  325.         WDC
  326.         ld a,M_MCNCS
  327.         out (SCTRL),a                         ;SCI start
  328.         WDC
  329.         ld bc,MC_SEND
  330.         ld a,3
  331.         out (c),a                             ;read op
  332.         WDC
  333.         out (c),l                             ;which register
  334.         WDC
  335.         ld a,0xff
  336.         out (c),a
  337.         WDC
  338.         ld bc,MC_READ
  339.         in d,(c)                              ;high byte
  340.         WDC
  341.         ld a,0xff
  342.         out (MC_SEND),a
  343.         WDC
  344.         in e,(c)                              ;low byte
  345.         WDC
  346.         ld a,M_MCNCS|M_SETNCLR
  347.         out (SCTRL),a                         ;SCI end
  348.         WDC
  349.         ret
  350.  
  351. vsclockvalue
  352. ;out: de = CLOCKF value
  353.         ld a,(vsversion)
  354.         ld de,CLOCKF_VS1011
  355.         cp SS_VER_VS1001
  356.         ret z
  357.         cp SS_VER_VS1002
  358.         ret z
  359.         cp SS_VER_VS1011
  360.         ret z
  361.         ld de,CLOCKF_VS1033
  362.         cp SS_VER_VS1003
  363.         ret z
  364.         cp SS_VER_VS1033
  365.         ret z
  366.         ld de,CLOCKF_VS1053
  367.         ret
  368.  
  369. ngssetfreq
  370. ;d = frequency constant
  371.         in a,(GSCFG0)
  372.         and %11001111
  373.         or d
  374.         out (GSCFG0),a
  375.         ret
  376.  
  377. checkifngs
  378.         in a,(GSCFG0)
  379.         cp 255
  380.         ret nz
  381. .msgloop
  382.         in a,(ZXSTAT)
  383.         rrca
  384.         call c,processcommand
  385.         jr .msgloop
  386.  
  387. mutemod
  388.         xor a
  389.         out (VOL1),a
  390.         out (VOL2),a
  391.         out (VOL3),a
  392.         out (VOL4),a
  393.         out (VOL5),a
  394.         out (VOL6),a
  395.         out (VOL7),a
  396.         out (VOL8),a
  397.         ret
  398.  
  399. processcommand
  400.         in a,(ZXCMD)
  401.         cp CMDCOUNT
  402.         jr nc,.cmdreset                       ;received an invalid command, so the player crashed?
  403.         add a,a
  404.         ld (.commandtable),a
  405.         out (CLRCBIT),a
  406. .commandtable=$+1
  407.         jr $
  408.         jr .cmdreset
  409.         jr .cmdgetfreebufferspace
  410.         jr .cmdgetchipid
  411.         jr .cmdrestartstream
  412.         jr .cmdvolumeup
  413.         jr .cmdvolumedown
  414.         jr .cmdgetstreaminfo
  415. .cmdreset
  416.         ld a,(vsversion)
  417.         inc a
  418.         jp z,0
  419.         call vssoftreset
  420.         ld d,C_20MHZ
  421.         call ngssetfreq
  422.         jp 0
  423. .cmdgetfreebufferspace
  424.         CALCFREEBUFFERSPACE
  425.         ATOZX
  426.         ret
  427. .cmdgetchipid
  428.         ld a,(vsversion)
  429.         ATOZX
  430.         ret
  431. .cmdrestartstream
  432.         ld sp,GSSTACKADDR
  433.         jp startnewstream
  434. .cmdvolumeup
  435.         ld a,(volumevalue)
  436.         or a
  437.         ret z
  438.         dec a
  439. .setvolume
  440.         push hl
  441.         push de
  442.         push bc
  443.         ld e,a
  444.         ld d,a
  445.         ld (volumevalue),de
  446.         ld l,SCI_VOL
  447.         call vswriteregister
  448.         pop bc
  449.         pop de
  450.         pop hl
  451.         ret
  452. .cmdvolumedown
  453.         ld a,(volumevalue)
  454.         cp SV_SILENCE>>8
  455.         ret nc
  456.         inc a
  457.         jr .setvolume
  458. .cmdgetstreaminfo
  459. streaminfobyte=$+1
  460.         ld a,255
  461.         ATOZX
  462.         ret
  463.  
  464. noper
  465.         ds 18,0
  466.         ret
  467. end
  468.         savebin "gscode.bin",begin,end-begin
  469.