home *** CD-ROM | disk | FTP | other *** search
/ Dave Lowe: Latest Version…itors Megaman XInfo File / Lowe_LatestVersionsOfMusicEditors_MegamanXInfoFile.img / GEAR / D-GEAR30.ASM next >
Encoding:
Assembly Source File  |  1994-10-31  |  56.2 KB  |  2,767 lines

  1. ;-----------------------------------------------------------------------------
  2. ;GAME GEAR MUSIC DRIVER - (c) Martin Walker 1993/1994
  3. ;-----------------------------------------------------------------------------
  4.  
  5. ;example to produce a final customer driver file
  6. ;DEMO        equ    0    ;0=driver only/ 1=demo & driver
  7. ;MUSICROM    equ    08000h    ;Music Driver start address
  8. ;MUSICRAM    equ    0C500h    ;Ram variables start address
  9.  
  10. ;default settings to use with the music editor
  11. DEMO        equ    1    ;0=driver only/ 1=demo & driver
  12. MUSICROM    equ    01000h    ;Driver start address
  13. MUSICRAM    equ    0C000h    ;Ram variables start address
  14.  
  15.  
  16. MASTER        equ 0        ;0=GAMEGEAR/ 1=MASTER SYSTEM
  17.  
  18.  
  19. ;CURRENT STATISTICS
  20. ;CODESIZE (ROM) = 3368 bytes (approx 3 Kbytes)
  21. ;VARSIZE  (RAM) = 214 bytes
  22. ;Typical compressed music file 2-10 Kbytes
  23.  
  24. GAMEGEAR    equ 1-MASTER    ;GAME GEAR
  25. HOLDTIME    equ 200        ;number of frames to hold effect
  26.  
  27.  
  28. ;VERSION DETAILS
  29. ;3.0 - Tiny format adopted/drumbend special added/ Get_info added
  30. ;      drumbend added
  31. ;1.7 - SFX specials moved/fixed special added/music channel 0 first
  32. ;1.6 - SFX routine implemented
  33. ;1.5 - noise allocation/superbug
  34. ;1.4 - simplified loop code/envlevel to byte/PAL or NTSC options
  35. ;1.3 - updated envelope routines/voicenum default to 0/rest & fade added
  36. ;1.2 - new format notes/extended parameters/32 byte effects & voices
  37. ;1.1 - CLOCK/updated TEMPO routine
  38. ;1.0 - First working prototype
  39.  
  40.  
  41.  
  42.  
  43. ;REGISTER EQUATES
  44.  
  45. VCOUNT    EQU 7Eh
  46. PSG    EQU 7Fh        ;both models
  47. VDPD    EQU 0BEh
  48. VDPA    EQU 0BFh
  49. VCHR    EQU 0000h
  50. VSCHR    EQU 2000h
  51. VMAP    EQU 3800h
  52. VSMAP    EQU 3F00h
  53. JOY1    EQU 0DCh
  54. JOY2    EQU 0DDh
  55. RKV    EQU 08h
  56. LKV    EQU 04h
  57. UKV    EQU 01h
  58. DKV    EQU 02h
  59. FAKV    EQU 10h
  60. FBKV    EQU 20h
  61. BNKAD    equ 0FFFFh    ;Rom bank select register
  62.  
  63.  
  64. COMAD    EQU 7FF8h ;The address of the comms interface in the GAMEGEAR
  65. HDLEN    EQU 16    ;Header buffer length (don't change)
  66. RESTRT    EQU 0    ;Main program start address
  67.  
  68. ;-----------------------------------------------------------------------------
  69.     IF DEMO
  70.     ORG 0000H    ;Start of program
  71.     JP START
  72.  
  73.     ORG 0030h    ;RST 30h is used for breakpoint
  74.  
  75.     PUSH BC
  76.     PUSH AF
  77.     LD BC,4170h
  78.     JP ASM10
  79.  
  80.     JP VBLINT    ;38h VERTICAL BLANK
  81.  
  82. ;-----------------------------------------------------------------------------
  83. STBNK:            ;This routine selects the rom bank in the A reg
  84.     PUSH BC        ;and returns the previous bank in the A reg
  85.     LD B,A
  86.     LD A,(BANKVAL)    ;Get current bank from ram
  87.     LD C,A
  88.     LD A,B
  89.     AND 1Fh
  90.     LD (BANKVAL),A    ;Save new bank
  91.     LD (BNKAD),A    ;Set bank
  92.     LD A,C
  93.     POP BC
  94.     RET        ;A is previous bank
  95.  
  96. ;-----------------------------------------------------------------------------
  97.     ORG 0066h
  98. NMI:    RETN        ;NMI #66
  99.  
  100.  
  101.  
  102.  
  103.  
  104. VIDREG:    DB 06,0A0h,0FFh,0FFh,0FFh,0FFh,0FFh,0Fh+(MASTER*0F0h),00,00,01 ;VIDEO REGS INIT
  105. PALTAB:    DB 0,0,4,8,16,1,6,11 ;PALLETE
  106.     DB 15,16,36,57,43,55,42,63
  107.     DB 2Ah,15h,00h,3Fh,00h,00h,00h,00h
  108.     DB 00h,00h,00h,00h,00h,00h,00h,00h
  109.  
  110. CHRS:    DB 0F0h,0F0h,0F0h,0F0h    ;PATTERN
  111.     DB 0F0h,0F0h,0F0h,0F0h
  112.     DB 0F0h,0F0h,0F0h,0F0h
  113.     DB 0F0h,0F0h,0F0h,0F0h
  114.     DB 0FFh,0FFh,0FFh,0FFh
  115.     DB 0FFh,0FFh,0FFh,0FFh
  116.     DB 000h,000h,000h,000h
  117.     DB 000h,000h,000h,000h
  118.  
  119. ;-----------------------------------------------------------------------------
  120. START:
  121.     DI
  122.  
  123. ;    IF GAMEGEAR
  124. PR20:    IN A,(VCOUNT)    ;Wait for end of reset sequence
  125.     CP 0B0h
  126.     JR NZ,PR20
  127. ;    ENDIF
  128.  
  129.     IM 1
  130.     XOR A        ;Reset unused ROM bank registers
  131.     LD (0FFFCh),A    ;bank register 0
  132.     LD (0FFFDh),A    ;bank register 0 (unused, always set to 0)
  133.     INC A
  134.     LD (0FFFEh),A    ;bank register 1
  135.     LD SP,0DFEFh
  136.     LD HL,0C000h    ;fill C000-DFF0 with zero
  137. PR40:    LD (HL),0
  138.     INC HL
  139.     LD A,L
  140.     SUB 0F0h
  141.     LD A,H
  142.     SBC A,0DFh
  143.     JR C,PR40
  144.  
  145.     LD A,2        ;Set default ROM bank
  146.     CALL STBNK    ;(Banks switched in at 8000h)
  147.  
  148.     XOR A
  149.     LD DE,0
  150.     LD BC,4000h
  151.     CALL FILVID        ;Reset video ram
  152.     LD A,0E0h
  153.     LD DE,VSMAP
  154.     LD BC,0040h
  155.     CALL FILVID    ;Turn off sprites
  156.     CALL INVREG    ;Init video regs
  157.     LD HL,PALTAB
  158.     CALL SETPALETTE    ;Set palette
  159.     LD HL,CHRS
  160.     LD DE,VCHR
  161.     LD BC,32
  162.     CALL STVID    ;Draw pattern in first char
  163.     LD A,(VIDREG+1)    ;Display on
  164.     SET 6,A
  165.  
  166.     DI
  167.     OUT (VDPA),A
  168.     LD A,81h
  169.     OUT (VDPA),A
  170.  
  171.     CALL JUMPTABLE+0    ;Initialise driver
  172.     LD A,0FFH
  173.     LD (sfxno),A
  174.     LD (tuneno),A
  175.     LD (PCnewdata),A
  176.     XOR A
  177.     LD (editnum),A
  178.     EI
  179.  
  180.  
  181. ;-----------------------------------------------------------------------------
  182. MAIN:    CALL COMMS
  183.  
  184. NEWchk:    ld a,(PCnewdata)
  185.     cp 0ffh
  186.     jr z,JOYchk
  187.     call JUMPTABLE+6    ;re-initialise after compression
  188.     LD A,0FFH
  189.     LD (PCnewdata),A    ;cancel flag
  190.  
  191.  
  192. JOYchk:    IN A,(JOY1)
  193.     BIT 0,A
  194.     JR Z,UPKEY
  195.     BIT 1,A
  196.     JR Z,DNKEY
  197.     BIT 2,A
  198.     JR Z,STOPKEY
  199.     BIT 3,A
  200.     JR Z,STOPKEY
  201.     BIT 4,A
  202.     JR Z,ONEKEY
  203.     BIT 5,A
  204.     JR Z,TWOKEY
  205.     JR VBLK_WT
  206.  
  207. UPKEY:    LD A,(editnum)        ;inc call number
  208.     INC A
  209.     LD (editnum),A
  210.     JR KEYEND
  211. DNKEY:    LD A,(editnum)        ;dec call number
  212.     DEC A
  213.     LD (editnum),A
  214.     JR KEYEND
  215. ONEKEY:    ld a,(editnum)
  216.     LD (tuneno),A
  217.     JR KEYEND
  218. TWOKEY:    LD A,(editnum)
  219.     LD (sfxno),A
  220.     JR keyend
  221. STOPKEY:
  222.     call INVEC        ;re-initialise after compression
  223.     ld a,07Dh
  224.     ld (TEMPOVAL),a        ;default tempo = 7Dh = 125bpm
  225.     ld a,080h
  226.     ld (tuneno),A        ;kill music
  227.     xor a
  228.     ld (sfxno),A        ;effect 0
  229.  
  230.  
  231. KEYEND:    IN A,(JOY1)
  232.     CP 0FFh
  233.     JR NZ,KEYEND        ;wait for key release
  234.  
  235. VBLK_WT:
  236.     LD A,(vbi_flag)
  237.     AND A            ;VBLANK interrupt ?
  238.     JR Z,VBLK_WT
  239.     XOR A
  240.     LD (vbi_flag),A        ;clear flag (set at end of VBLANK)
  241.     JP MAIN
  242.  
  243.  
  244. ;-----------------------------------------------------------------------------
  245. VBLINT:        ;VERTICAL BLANK INTERRUPT
  246.     PUSH AF
  247.     PUSH BC
  248.     PUSH DE
  249.     PUSH HL
  250.  
  251.     IN A,(VDPA)
  252.     RLA        ;move interrupt bit to carry
  253.     JR NC,VB90    ;Not vertical blank
  254.     LD A,(SCRLCOUNT)    ;Scroll screen
  255.     DEC A
  256.     LD (SCRLCOUNT),A
  257.     NEG
  258.     OUT (VDPA),A
  259.     LD A,88h
  260.     OUT (VDPA),A
  261.  
  262.     CALL JUMPTABLE+3    ;60Hz SOUND INTERRUPT ROUTINE
  263.     CALL Get_Info
  264.     LD A,1
  265.     LD (vbi_flag),A    ;VBLANK INTERRUPT END FLAG
  266.  
  267. VB90:    POP HL
  268.     POP DE
  269.     POP BC
  270.     POP AF
  271.         EI
  272.     RET
  273.  
  274.  
  275. ;-----------------------------------------------------------------------------
  276. INVREG:        ;SET UP VIDEO REGS
  277.     IN A,(VDPA)
  278.     LD HL,VIDREG
  279.     LD B,11
  280.     LD C,80h
  281. ST5:    LD A,(HL)
  282.     INC HL
  283.     OUT (VDPA),A
  284.     LD A,C
  285.     INC C
  286.     OUT (VDPA),A
  287.     DJNZ ST5
  288. ;    LD A,(VIDREG+1)    ;Used for display on/off
  289. ;    LD (BLFLG),A
  290.     RET
  291.  
  292. ;-----------------------------------------------------------------------------
  293. SETPALETTE:        ;SET PALETTE
  294.     IF GAMEGEAR
  295.     LD IX,PALLETTE    ;GAMEGEAR DIFFERENT FORMAT
  296.     LD B,32
  297. SP10:    LD A,(HL)
  298.     RLCA
  299.     RLCA
  300.     EXX
  301.     LD HL,0
  302.     LD D,H
  303.     LD B,3
  304.     LD C,A
  305. SP20:    ADD HL,HL
  306.     ADD HL,HL
  307.     ADD HL,HL
  308.     ADD HL,HL
  309.     RLC C
  310.     RLC C
  311.     LD A,C
  312.     AND 03h
  313.     LD E,A
  314.     ADD A,A
  315.     ADD A,A
  316.     ADD A,E
  317.     LD E,A
  318.     ADD HL,DE
  319.     DJNZ SP20
  320.     LD (IX+0),L
  321.     LD (IX+1),H
  322.     INC IX
  323.     INC IX
  324.     EXX
  325.     INC HL
  326.     DJNZ SP10
  327.     LD HL,PALLETTE
  328.     ENDIF
  329.     LD BC,32*(GAMEGEAR+1)
  330.     XOR A
  331.     DI
  332.     OUT (VDPA),A
  333.     LD A,0C0h
  334.     JR ST8
  335.  
  336. ;-----------------------------------------------------------------------------
  337. STVID:        ;WRITE TO VIDEO RAM
  338.     LD A,E
  339.     DI
  340.     OUT (VDPA),A
  341.     LD A,D
  342.     AND 03Fh
  343.     OR 040h
  344. ST8:    JR ST9
  345. ST9:    OUT (VDPA),A
  346.     JR ST10
  347. ST10:    LD A,(HL)
  348.     INC HL
  349.     DEC BC
  350.     OUT (VDPD),A
  351.     LD A,B
  352.     OR C
  353.     JR NZ,ST10
  354.     EI
  355.     RET
  356.  
  357. ;-----------------------------------------------------------------------------
  358. FILVID:        ;FILL VIDEO RAM
  359.     PUSH AF
  360.     LD A,E
  361.     DI
  362.     OUT (VDPA),A
  363.     LD A,D
  364.     AND 03Fh
  365.     OR 040h
  366.     JR ST15
  367. ST15:    OUT (VDPA),A
  368.     POP AF
  369.     NOP
  370.     DEC BC
  371. ST20:    DEC BC
  372.     NOP
  373.     OUT (VDPD),A
  374.     BIT 7,B
  375.     JR Z,ST20
  376.     EI
  377.     RET
  378.  
  379.  
  380. ;-----------------------------------------------------------------------------
  381. ;Start of Debugger routines
  382. ;-----------------------------------------------------------------------------
  383. COMMS:            ;Enter debugger if host waiting to transfer
  384. ;    DI        ;Interrupts should be off
  385.     PUSH BC
  386.     PUSH AF
  387.     LD BC,0C0F0h
  388. ASM10:    LD A,(COMAD)    ;'Read' port of comms link
  389.     XOR B    ;Bits 4-6 are used to determine if the comms is
  390.     AND C    ;enabled. Bit 7 set indicates that the host is
  391.     JR NZ,ASM20    ;waiting to transfer
  392.     CALL COMRT    ;Enter debugger if host waiting
  393. ASM20:    POP AF
  394.     POP BC
  395.     RET    ;Return to main program (interrupts off)
  396.         ;All regs preserved unless changed by host
  397.         ;command
  398.  
  399.  
  400. ;-----------------------------------------------------------------------------
  401. ;This is the debugger.
  402. ;If a new bank was paged in, the previous value should be in the A
  403. ;reg. This can be read by the 'transfer registers' command.
  404. ;The B reg holds the breakpoint type (041h-BRKPNT, 042h-TRACE AND 0C0h-COMMS).
  405. ;-----------------------------------------------------------------------------
  406. COMRT:    PUSH DE
  407.     PUSH HL
  408.     LD HL,12
  409.     ADD HL,SP
  410.     PUSH HL    ;Stack value
  411.     LD C,A
  412.     PUSH BC    ;Bank and type
  413.     LD HL,-HDLEN AND 0FFFFH
  414.     ADD HL,SP
  415.     LD SP,HL    ;Buffer for header
  416. COM20:    LD A,(COMAD)
  417.     AND 0F0h
  418.     CP 040h
  419.     JR Z,COM20    ;Wait for host (for DEBUG entry)
  420.     LD A,(COMAD+6)     ;Reset port
  421.     LD A,(COMAD+4)
  422. COM30:    LD A,(COMAD+3)
  423. COM40:    CALL COMRX    ;Read first byte of header
  424.     JR C,COM70    ;Enter ram or exit
  425.     AND A
  426.     JR Z,COM80    ;This command not used
  427.     LD HL,0
  428.     ADD HL,SP
  429.     CALL COMCMD    ;Execute command
  430.     JR NC,COM30    ;If no error loop back for next command
  431.     LD A,(COMAD+2)     ;Signal error to host
  432.     LD A,(COMAD+4)
  433.     LD A,(COMAD+7)
  434. COM60:    LD A,(COMAD)    ;Wait for host to disable comms with COMOFF
  435.     AND 0F0h
  436.     CP 0C0h
  437.     JR Z,COM60
  438.     JR COM90    ;Exit
  439. COM70:    JR NZ,COM80    ;Jump if exit
  440.     LD A,(COMAD+6)
  441.     DI        ;Prepare to enter ram (for ESYS access)
  442.     LD HL,(HDLEN-CWTLN) AND 0FFFFH
  443.     ADD HL,SP
  444.     LD SP,HL    ;Make space for ram routine
  445.     PUSH HL
  446.     LD D,H
  447.     LD E,L
  448.     LD HL,COMWT    ;Copy routine into stack buffer
  449.     LD BC,CWTLN    ;LD BC,/LDIR (for Z80)
  450. COM75:    LDIR
  451.     RET        ;Enter ram
  452.  
  453. ;-----------------------------------------------------------------------------
  454. COMCT:    LD A,(COMAD+2)    ;Continue here after exiting ram
  455.     LD HL,CWTLN-HDLEN
  456.     ADD HL,SP
  457.     LD SP,HL    ;Reclaim space
  458.     EI
  459. COM78:    LD A,(COMAD)    ;Wait for acknowledgement from host
  460.     AND 0F2h
  461.     CP 0C0h
  462.     JR Z,COM78
  463.     JR COM30
  464. COM80:    LD A,(COMAD+6)     ;Prepare for exit
  465.     LD A,(COMAD+2)
  466. COM90:    LD HL,HDLEN    ;Exit after error
  467.     ADD HL,SP
  468.     LD SP,HL        ;Reclaim header buffer
  469.     POP BC
  470.     LD A,C
  471.     POP HL
  472.     POP HL
  473.     POP DE
  474.     RET
  475.  
  476.  
  477. ;-----------------------------------------------------------------------------
  478. ;Execute command, A is command number
  479. ;-----------------------------------------------------------------------------
  480. COMCMD:
  481.     CP 10h    ;This command not used
  482.     JR NZ,CMD10
  483.     LD DE,HDLEN+1
  484.     ADD HL,DE
  485.     LD A,(HL)
  486.     CALL COMTX
  487.     RET C
  488.  
  489. TXACK:    LD A,(COMAD)    ;Wait for acknowledgement from host
  490.     AND 0F2h
  491.     CP 0C0h
  492.     JR Z,TXACK
  493.     LD A,(COMAD+2)
  494. CMD5:    LD A,(COMAD)
  495.     AND 0F1h
  496.     XOR 0C0h
  497.     JR Z,CMD5
  498.     RET
  499.  
  500. CMD10:    LD E,A
  501.     AND 0Fh
  502.     RET Z    ;Single byte command
  503.     LD C,A
  504.     LD B,0
  505.     PUSH DE
  506.     PUSH HL
  507.     CALL CRXLP    ;Load rest of header
  508.     POP HL
  509.     POP DE
  510.     RET C    ;Error
  511.     LD A,E
  512.     AND 0EFh
  513.     CP 02h
  514.     JR NZ,CMD20    ;Jump if not transfer regs command
  515.     LD C,(HL)
  516.     INC HL
  517.     LD A,(HL)
  518.     LD B,0
  519.     ADD HL,BC
  520.     LD C,HDLEN-1
  521.     ADD HL,BC    ;Point to regs list on stack
  522.     LD C,A
  523.     LD D,B
  524.     JR CMD30
  525. CMD20:    XOR 05h
  526.     RET NZ    ;Return if not transfer memory command
  527.     LD A,(HL)
  528.     INC HL
  529.     LD D,(HL)
  530.     INC HL
  531.     INC HL
  532.     LD C,(HL)
  533.     INC HL
  534.     LD B,(HL)
  535.     LD H,D
  536.     LD L,A
  537.     LD D,0
  538.     ;CALL CKDOFF    ;Turn GBOY display off if required
  539. CMD30:    PUSH DE
  540.     BIT 4,E
  541.     JR Z,CMD40
  542.     CALL CTXBUF    ;Send data
  543.     CALL NC,TXACK    ;Wait for acknowledgement
  544.     JR CMD50
  545. CMD40:    CALL CRXBUF    ;Load data
  546. CMD50:    POP DE
  547.     ret
  548.  
  549.  
  550.  
  551. ;-----------------------------------------------------------------------------
  552. ;This routine is copied into ram to allow the host access
  553. ;to the ESYS
  554. ;-----------------------------------------------------------------------------
  555. COMWT:
  556.     LD A,(COMAD+2)
  557. CWT10:    XOR A    ;Wait for command
  558. CWT20:    ADD HL,HL
  559.     DEC A
  560.     JR NZ,CWT20
  561.     LD A,(COMAD)
  562.     AND 0F0h
  563.     CP 0C0h
  564.     JR Z,CWT30    ;Jump if host waiting to send command
  565.     CP 040h
  566.     JR Z,CWT10
  567.     JR CWT50    ;Jump if comms disabled
  568. CWT30:    LD A,(COMAD+3) ;Send acknowledgement
  569. CWT40:    LD A,(COMAD)
  570.     AND 0F2h
  571.     CP 0C0h
  572.     JP Z,COMCT    ;Jump back to debugger
  573.     CP 0C2h
  574.     JR Z,CWT40
  575.     LD A,(COMAD+2)
  576. CWT50:    JP RESTRT    ;Jump to start if comms disabled or ENDTRN called
  577. CWTLN    EQU $-COMWT
  578.  
  579.  
  580. ;-----------------------------------------------------------------------------
  581. ;Transmit data to host
  582. ;HL points to data, BC is the length
  583. ;-----------------------------------------------------------------------------
  584. CTXBUF:
  585.     LD E,0
  586. CTX10:    LD A,(HL)
  587.     LD D,A
  588.     INC HL
  589.     CALL COMTX    ;Send byte
  590.     RET C    ;Error
  591.     LD A,D    ;Checksum
  592.     ADD A,E
  593.     LD E,A
  594.     DEC BC
  595.     LD A,B
  596.     OR C
  597.     JR NZ,CTX10
  598.     LD A,E    ;Send checksum
  599.     ;Send a byte (in A)
  600. COMTX:    PUSH BC
  601.     PUSH DE
  602.     PUSH HL
  603.     LD C,A
  604.     LD B,0C2h
  605.     LD DE,COMAD+2
  606.     LD HL,COMAD+4
  607.     SCF
  608.     RL C
  609. CTX20:    RR E
  610.     RLC E
  611. CTX30:    LD A,(COMAD)    ;Wait for handshake
  612.     XOR B
  613.     AND 0F2h
  614.     JR Z,CTX40
  615.     XOR 02h
  616.     JR Z,CTX30
  617.     AND 070h
  618.     SCF
  619.     JR NZ,CTX50    ;Exit if comms disabled
  620.     BIT 3,B
  621.     JR NZ,CTX30
  622. CTX40:    SET 3,B    ;Send first bit even if host is not ready
  623.     LD A,(DE)
  624.     LD A,L
  625.     XOR 01h
  626.     LD L,A
  627.     LD A,B
  628.     XOR 02h
  629.     LD B,A
  630.     LD A,(HL)
  631.     SLA C
  632.     JR NZ,CTX20
  633.     AND A
  634. CTX50:    POP HL
  635.     POP DE
  636.     POP BC
  637.     RET
  638.     ;On exit NC=send OK, C=comms disabled
  639.  
  640.  
  641. ;-----------------------------------------------------------------------------
  642. ;Receive data from host
  643. ;HL points to data, BC is the length
  644. ;-----------------------------------------------------------------------------
  645. CRXBUF:
  646.     LD E,0
  647. CRXLP:    CALL COMRX    ;Load byte
  648.     RET C    ;Error
  649.     LD (HL),A
  650.     INC HL
  651.     ADD A,E    ;Checksum
  652.     LD E,A
  653.     DEC BC
  654.     LD A,B
  655.     OR C
  656.     JR NZ,CRXLP
  657.     CALL COMRX    ;Load checksum
  658.     RET C    ;Error
  659.     XOR E
  660.     ADD A,0FFh    ;Signal error if checksums do not match
  661.     RET
  662.     ;On exit NC=load OK, C=comms disabled or error
  663.  
  664.  
  665. ;-----------------------------------------------------------------------------
  666. ;Receive a byte from host
  667. ;-----------------------------------------------------------------------------
  668. COMRX:
  669.     PUSH BC
  670.     PUSH HL
  671.     LD BC,0C001h
  672.     LD HL,COMAD+6
  673. CRX10:    LD A,(COMAD)    ;Wait for handshake
  674.     AND 0F2h
  675.     XOR B
  676.     JR Z,CRX20
  677.     XOR 02h
  678.     JR Z,CRX10
  679.     XOR B
  680.     XOR 042h
  681.     JR NZ,CRX30    ;Jump if comms disabled
  682.     LD A,C    ;Check for 'enter ram' command
  683.     XOR 3
  684.     JR CRX30
  685. CRX20:    LD A,L
  686.     XOR 01h
  687.     LD L,A
  688.     LD A,B
  689.     XOR 02h
  690.     LD B,A
  691.     LD A,(COMAD)
  692.     CP (HL)
  693.     RRA
  694.     RL C
  695.     JR NC,CRX10
  696.     LD A,C
  697. CRX30:    POP HL
  698.     POP BC
  699.     CCF
  700.     RET
  701.     ;On exit NC=load OK, value in A
  702.     ;        C and A=0 - Enter ram command
  703.     ;        C and A<>0 - Comms transfer ended
  704.  
  705.  
  706.  
  707. ;-------------------------------------------------------------------------------
  708. ;Get_Info
  709. ;-------------------------------------------------------------------------------
  710. Get_Info:
  711.     LD BC,PCbuffer
  712.     LD A,(TUNENO)
  713.     LD (BC),A
  714.     INC BC
  715.     LD A,(STATUS)
  716.     LD (BC),A
  717.     INC BC
  718.     LD A,(TEMPOVAL)
  719.     LD (BC),A
  720.     INC BC
  721.     LD A,(CLOCK_L)
  722.     LD (BC),A
  723.     INC BC
  724.     LD A,(CLOCK_H)
  725.     LD (BC),A
  726.     INC BC
  727.     LD A,(globoffset)
  728.     LD (BC),A
  729.     INC BC
  730.  
  731.     XOR A
  732.     LD D,A
  733.     LD E,A
  734.     LD (chan_num),A
  735.     LD IX,ENV_VARS
  736.     LD IY,MUS_VARS
  737.  
  738. Gilup1:    LD A,(IY+24)        ;notelength
  739.     LD (BC),A
  740.     INC BC
  741.     ld A,(IY+75)        ;threshold
  742.     LD (BC),A
  743.     INC BC
  744.     LD A,(IY+39)        ;voicenum
  745.     LD (BC),A
  746.     INC BC
  747.     LD A,(IY+15)        ;notevalue
  748.     LD (BC),A
  749.     INC BC
  750.     LD A,(IY+12)        ;seqnumber
  751.     LD (BC),A
  752.     INC BC
  753.     LD A,(IX+9)        ;envlevel
  754.     LD (BC),A
  755.     INC BC
  756.  
  757.     INC IY
  758.     INC IX
  759.     LD HL,chan_num
  760.     INC (HL)
  761.     LD A,(HL)
  762.     CP 3
  763.     JP C,Gilup1
  764.     RET
  765.  
  766.  
  767.  
  768.  
  769.     ENDIF
  770.  
  771.  
  772. ;*****************************************************************************
  773. ; ****** START OF DRIVER CODE ******
  774. ;*****************************************************************************
  775.     ORG MUSICROM
  776.  
  777. JUMPTABLE:
  778.     JP INITSND    ;Initialise sound routine
  779.     JP INTSND    ;Game Gear 60Hz Interrupt routine
  780.     JP INVEC        ;New load routine
  781.  
  782. INITSND:
  783.     LD HL,RAM_VARS    ;clear variable RAM
  784.     LD BC,VARSIZE
  785. CLRVAR:    LD (HL),0
  786.     INC HL
  787.     DJNZ CLRVAR
  788.  
  789.     CALL INVEC    ;calc. addresses from vector table
  790.  
  791.     LD A,0ffh
  792.     LD (sfx_channel),A    ;cancel any current calls
  793.     LD (sfx_channel+SDLN),A
  794.     LD (sfx_channel+SDLN+SDLN),A
  795.     LD (sfx_priority),A    ;set lowest priority
  796.     LD (sfx_priority+SDLN),A
  797.     LD (sfx_priority+SDLN+SDLN),A
  798.     LD (vce_mute),A        ;force music muted for effects
  799.     LD (vce_mute+1),A
  800.     LD (vce_mute+2),A
  801.     LD (NCHAN),A        ;noise channel free
  802.  
  803.     ld a,0FFh
  804.     ld (TEMPOVAL),A        ;default tempo = 296
  805.     LD A,0Dh
  806.     LD (musicvol),A
  807.     LD A,0Fh
  808.     LD (effectvol),A        ;default to maximum volume
  809.     CALL PSG_off        ;silence all channels
  810.     ret
  811.  
  812.  
  813. ;-----------------------------------------------------------------------------
  814. ;Calculate new pointers from Musicdata chunk sizes
  815. ;-----------------------------------------------------------------------------
  816. INVEC:    LD HL,GAMEDATA    ;chunk table start address
  817.     LD DE,GAMEDATA+14    ;music data start address
  818. IN50:    LD A,E
  819.     LD (FXBANK),A
  820.     LD A,D
  821.     LD (FXBANK+1),A    ;save start address of envelopes
  822.  
  823.     ld bc,FXTABLE
  824.     call stvar    ;calculate FXBANK address
  825.     CALL STVAR    ;calculate VCEBANK address
  826.     CALL STVAR    ;calc. SEQOFF address
  827.     CALL STVAR    ;calc. SEQDATA address
  828.     CALL STVAR    ;calc. TRKOFF address
  829.             ;calc. TRKDATA address
  830. STVAR:    LD A,(HL)    ;get low byte from vector table
  831.     INC HL
  832.     ADD A,E        ;add GAMEDATA low byte address
  833.     LD E,A        ;and save in E
  834.     LD (BC),A    ;and save in final offset low byte
  835.     INC BC        ;now move to high byte
  836.     LD A,(HL)    ;get high byte from vector table
  837.     INC HL
  838.     ADC A,D        ;add GAMEDATA high byte address
  839.     LD D,A        ;DE now holds address of this block
  840.     LD (BC),A    ;save to final offset high byte
  841.     INC BC        ;now move to next dest. entry
  842.  
  843.     RET
  844.  
  845. ;-------------------------------------------------------------------------------
  846. ;INTERRUPT ROUTINE
  847. ;-------------------------------------------------------------------------------
  848. INTSND:    LD A,(sfxno)
  849.     CP 0FFH
  850.     JR Z,INTSND2
  851.     CALL SENDFX
  852.     LD A,0FFH
  853.     LD (sfxno),A
  854. INTSND2:
  855.     LD A,(tuneno)
  856.     CP 0FFH
  857.     JR Z,INTSND3
  858.     CALL SENDMUS
  859.     LD A,0FFH
  860.     LD (tuneno),A
  861. INTSND3:
  862.     CALL INTSFX
  863.     CALL INTMUSIC
  864.     ret
  865.  
  866.  
  867. ;-------------------------------------------------------------------------------
  868. SENDFX:    ld hl,0
  869.     ld l,a            ;enter with A=FXTABLE call number
  870.     add hl,hl
  871.     add hl,hl        ;4 bytes for each entry
  872.     ld a,(FXTABLE)
  873.     add a,l
  874.     ld c,a
  875.     ld a,(FXTABLE+1)
  876.     adc a,h
  877.     ld h,a            ;final high byte of address
  878.     ld l,c            ;final low byte of address
  879.  
  880.     ld c,(hl)        ;get priority
  881.     inc hl
  882.     ld a,(hl)        ;get chan0 call
  883.     inc hl
  884.     cp 0ffh
  885.     jr z,sendfx1
  886.     ld (sfx_channel),a
  887.     ld a,c
  888.     ld (sfx_priortest),a
  889. sendfx1:
  890.     ld a,(hl)        ;get chan1 call
  891.     inc hl
  892.     cp 0ffh
  893.     jr z,sendfx2
  894.     ld (sfx_channel+SDLN),a
  895.     ld a,c
  896.     ld (sfx_priortest+SDLN),a
  897. sendfx2:
  898.     ld a,(hl)        ;get chan2 call
  899.     inc hl
  900.     cp 0ffh
  901.     jr z,sendfx3
  902.     ld (sfx_channel+SDLN+SDLN),a
  903.     ld a,c
  904.     ld (sfx_priortest+SDLN+SDLN),a
  905. sendfx3:
  906.     ret
  907.  
  908.  
  909. ;-----------------------------------------------------------------------------
  910. INTSFX:
  911.     LD A,2            ;3 channels
  912.     LD (chan_num),A
  913.  
  914. SFXLOOP:
  915.     XOR A
  916.     LD (freqoffset),A        ;reset waver to 0
  917.     LD IX,ENV_VARS
  918.     LD IY,SFX_VARS
  919.     LD BC,(chan_num)
  920.     ADD IX,BC
  921.     LD A,C
  922.     AND A
  923.     JR Z,SF5            ;channel 1
  924.     LD C,SDLN
  925.     ADD IY,BC
  926.     DEC A
  927.     JR Z,SF5            ;channel 2
  928.     ADD IY,BC        ;channel 3
  929.  
  930. SF5:    LD A,(IY+0)        ;new sound effect needed? (sfx_channel)
  931.     INC A
  932.     JR Z,TESTMUSIC        ;sfx_channel=0FFh is no effect required
  933.     DEC A            ;return to previous value
  934.     LD B,A            ;new effect number saved to B
  935.     LD A,(IY+2)
  936.     LD C,A            ;C=sfx_priortest
  937.  
  938.     LD A,(IY+1)        ;get current sfx_priority
  939.     CP C
  940.     JR NC,loadfx        ;higher or equal, so accept
  941.     LD A,(IY+3)        ;sfx_hold
  942.     AND A
  943.     JR Z,loadfx        ;past critical portion
  944.     LD (IY+0),0FFH        ;else cancel this try (sfx_channel)
  945.  
  946. TESTMUSIC:
  947.     LD HL,MUS_VARS
  948.     LD BC,(chan_num)
  949.     ADD HL,BC
  950.     LD A,(HL)        ;get vce_mute
  951.     AND A            ;0 = not muted i.e.
  952.     JR Z,TESTABORT        ;new note of music taken over
  953.     LD A,(IY+4)        ;else continue until SFX end (sfx_framechop)
  954.     AND A
  955.     JP NZ,timefx        ;carry on with existing SFX
  956.  
  957.  
  958. TESTABORT:
  959.     LD (IY+3),0        ;force sfx_hold = 0 if snd < hold length
  960.     LD (IY+4),0        ;sfx_framechop (just in case)
  961.     JP NEXT_SFX
  962.  
  963. ;-----------------------------------------------------------------------------
  964. loadfx:    LD A,C            ;get new priority
  965.     LD (IY+1),A        ;& save new sfx_priority
  966.     LD L,(IY+0)        ;accept new sound (sfx_channel)
  967.     LD H,0
  968.     ADD HL,HL
  969.     ADD HL,HL
  970.     ADD HL,HL
  971.     ADD HL,HL
  972.     ADD HL,HL        ;32 bytes per effect
  973.     LD DE,(FXBANK)
  974.     ADD HL,DE
  975.     LD (IY+7),L
  976.     LD (IY+8),H        ;save new sfx_address (word)
  977.  
  978.     PUSH HL
  979.     EX (SP),IX
  980.     LD A,(IX+0)        ;byte0 = s_atkwve
  981.     LD (IY+5),A        ;sfx_waveform
  982.     LD A,(IX+2)        ;byte2 = s_atkcnt
  983.     LD (IY+11),A        ;sfx_atkcnt
  984.     LD A,(IX+3)        ;byte3 = s_endcnt
  985.     LD (IY+4),A        ;sfx_framechop
  986.     LD A,(IX+4)        ;byte4 = s_freqhi
  987.     LD (IY+10),A        ;sfx_period (high)
  988.     LD A,(IX+5)        ;byte5 = s_freqlo
  989.     LD (IY+9),A        ;sfx_period (low)
  990.     LD A,(IX+6)        ;byte6 = nsefrq
  991.     LD (IY+6),A        ;sfx_noisetype
  992.     LD A,(IX+13)        ;byte13= s_count2
  993.     LD (IY+12),A        ;sfx_count2
  994.     LD (IY+13),0FFH        ;sfx_dirflag
  995.  
  996.     LD L,(IY+7)        ;sfx_address (word)
  997.     LD H,(IY+8)
  998.     POP IX            ;IX=1st byte of effect
  999.     LD BC,16
  1000.     ADD HL,BC        ;envelope start @ byte 16 of voicedata
  1001.     EX DE,HL            ;DE = start address of this envelope
  1002.  
  1003.     LD HL,sfx_envaddress
  1004.     LD BC,(chan_num)
  1005.     SLA C            ;convert to word offset
  1006.     ADD HL,BC
  1007.     LD (HL),E
  1008.     INC HL
  1009.     LD (HL),D        ;save env address to sfx_envaddress
  1010.  
  1011.     LD IX,ENV_VARS
  1012.     LD BC,(chan_num)
  1013.     ADD IX,BC
  1014.  
  1015.     INC DE
  1016.     INC DE            ;envbyte2 = repeat number
  1017.     LD A,(DE)
  1018.     LD (IX+6),A        ;new envrepeats
  1019.     LD (IX+0),B        ;envstage to 0
  1020.     LD (IX+3),1        ;envframecnt
  1021.     LD (IX+9),B        ;envlevel to 0
  1022.     LD (IY+3),HOLDTIME    ;sfx_hold
  1023.     LD (IY+0),0FFH        ;reset test byte (sfx_channel)
  1024.     JP sfxenvelope
  1025.  
  1026. ;-----------------------------------------------------------------------------
  1027. timefx:    LD A,(IY+3)        ;sfx_hold
  1028.     AND A
  1029.     JR Z,timing1
  1030.     DEC (IY+3)        ;sfx_hold
  1031. timing1: DEC (IY+12)        ;sfx_count2
  1032.     JP P,timing2
  1033.     LD L,(IY+7)
  1034.     LD H,(IY+8)        ;sfx_address (word)
  1035.     LD BC,13            ;byte13= s_count2
  1036.     ADD HL,BC
  1037.     LD A,(HL)        ;get s_count2
  1038.     LD (IY+12),A        ;to sfx_count2
  1039.     LD A,(IY+13)        ;sfx_dirflag
  1040.     CPL
  1041.     LD (IY+13),A        ;sfx_dirflag
  1042. timing2:
  1043.     LD A,(IY+11)        ;sfx_atkcnt
  1044.     AND A
  1045.     JR NZ,timing4
  1046.     LD L,(IY+7)
  1047.     LD H,(IY+8)        ;sfx_address
  1048.     INC HL
  1049.     LD A,(HL)        ;byte1 = s_endwve
  1050.     LD (IY+5),A        ;sfx_waveform
  1051.  
  1052.     LD A,(IY+4)        ;sfx_framechop
  1053.     INC A
  1054.     JR Z,sfxbending        ;continuous SFX
  1055.     DEC (IY+4)        ;sfx_framechop
  1056.     JR NZ,sfxbending
  1057.  
  1058.     LD A,0            ;force 0 volume at end of sound
  1059.     LD HL,(chan_num)        ;0,1,2,3
  1060.     CALL PSG_volume
  1061.     LD A,(NCHAN)
  1062.     CP L            ;was this the noise channel?
  1063.     JP NZ,NEXT_SFX        ;no
  1064.     LD A,0FFh        ;yes, so release noise channel
  1065.     LD (NCHAN),A
  1066.     XOR A
  1067.     LD HL,3            ;force channel 3 (noise)
  1068.     CALL PSG_volume        ;& set noise volume to 0
  1069.     JP NEXT_SFX
  1070.  
  1071. timing4:
  1072.     DEC (IY+11)        ;sfx_atkcnt
  1073.  
  1074. ;-----------------------------------------------------------------------------
  1075. sfxbending:
  1076.     LD L,(IY+7)
  1077.     LD H,(IY+8)        ;sfx_address (word)
  1078.     LD BC,8            ;byte8 = bend type
  1079.     ADD HL,BC
  1080.     LD A,(HL)
  1081.     AND A
  1082.     JP Z,sfxspec
  1083.  
  1084. sfxbend1:
  1085.     CP 1
  1086.     JR NZ,sfxbend2
  1087. sfxbend1a:
  1088.     LD L,(IY+7)
  1089.     LD H,(IY+8)
  1090.     LD BC,9            ;byte9 = bendhi
  1091.     ADD HL,BC
  1092.     LD D,(HL)
  1093.     INC HL            ;byte10= bendlo
  1094.     LD E,(HL)
  1095.     LD L,(IY+9)
  1096.     LD H,(IY+10)        ;sfx_period
  1097.     AND A
  1098.     SBC HL,DE
  1099.     JR sfxbend2b
  1100.  
  1101. sfxbend2:
  1102.     CP 2
  1103.     JR NZ,sfxbend3
  1104. sfxbend2a:
  1105.     LD L,(IY+7)
  1106.     LD H,(IY+8)
  1107.     LD BC,9            ;byte9 = bendhi
  1108.     ADD HL,BC
  1109.     LD D,(HL)
  1110.     INC HL            ;byte10= bendlo
  1111.     LD E,(HL)
  1112.     LD L,(IY+9)
  1113.     LD H,(IY+10)
  1114.     ADD HL,DE
  1115. sfxbend2b:
  1116.     LD (IY+9),L
  1117.     LD (IY+10),H
  1118.     JR sfxspec
  1119.  
  1120. sfxbend3:
  1121.     CP 3
  1122.     LD C,(IY+11)        ;sfx_atkcnt
  1123.     JR NZ,sfxbend4
  1124.     LD A,C
  1125.     AND A
  1126.     JR NZ,sfxbend1a
  1127.     JR sfxspec
  1128.  
  1129. sfxbend4:
  1130.     CP 4
  1131.     JR NZ,sfxbend5
  1132.     LD A,C
  1133.     AND A
  1134.     JR NZ,sfxbend2a
  1135.     JR sfxspec
  1136.  
  1137. sfxbend5:
  1138.     CP 5
  1139.     JR NZ,sfxbend6
  1140.     LD A,C
  1141.     AND A
  1142.     JR NZ,sfxbend1a
  1143.     JR sfxbend2a
  1144.  
  1145. sfxbend6:
  1146.     CP 6
  1147.     JR NZ,sfxbend7
  1148.     LD A,C
  1149.     AND A
  1150.     JR NZ,sfxbend2a
  1151.     JR sfxbend1a
  1152.  
  1153. sfxbend7:
  1154.     CP 7
  1155.     JR NZ,sfxbend8
  1156.     LD A,C
  1157.     AND A
  1158.     JR Z,sfxbend1a
  1159.     JR sfxspec
  1160.  
  1161. sfxbend8:
  1162.     CP 8
  1163.     JR NZ,sfxbend9
  1164.     LD A,C
  1165.     AND A
  1166.     JR Z,sfxbend2a
  1167.     JR sfxspec
  1168.  
  1169. sfxbend9:
  1170.     CP 9
  1171.     JR NZ,sfxspec
  1172.     BIT 7,(IY+13)        ;sfx_dirflag
  1173.     JP NZ,sfxbend1a
  1174.     JR sfxbend2a
  1175.  
  1176. ;-----------------------------------------------------------------------------
  1177. sfxspec:
  1178.     LD L,(IY+7)
  1179.     LD H,(IY+8)
  1180.     LD BC,12            ;byte12= specls
  1181.     ADD HL,BC
  1182.     LD A,(HL)        ;s_specls
  1183.     AND A
  1184.     JP Z,sfxenvelope
  1185.  
  1186. sfxspec01:
  1187.     LD L,(IY+7)
  1188.     LD H,(IY+8)
  1189.     LD BC,12            ;byte12= specls
  1190.     ADD HL,BC
  1191.     BIT 0,(HL)        ;swap freqhi/lo @ 50Hz
  1192.     JR Z,sfxspec02
  1193.     LD A,(IY+9)
  1194.     LD C,(IY+10)
  1195.     LD (IY+10),A
  1196.     LD (IY+9),C
  1197.  
  1198. sfxspec02:
  1199.     LD L,(IY+7)
  1200.     LD H,(IY+8)        ;sfx_address
  1201.     LD BC,12            ;byte12= s_specls
  1202.     ADD HL,BC
  1203.     BIT 1,(HL)        ;Complex Hi (freqhi-bendhi/eor with newfhi)
  1204.     JR Z,sfxspec04
  1205.     LD A,(IY+10)        ;sfx_period (high)
  1206.     DEC HL
  1207.     DEC HL
  1208.     DEC HL            ;12-3
  1209.     SUB (HL)            ;byte9 = bendhi
  1210.     LD BC,5
  1211.     ADD HL,BC        ;byte14= newfhi
  1212.     LD C,(HL)
  1213.     XOR C
  1214.     LD (IY+10),A
  1215.  
  1216. sfxspec04:
  1217.     LD L,(IY+7)
  1218.     LD H,(IY+8)        ;sfx_address
  1219.     LD BC,12            ;byte12= s_specls
  1220.     ADD HL,BC
  1221.     BIT 2,(HL)        ;;waver F lo + (random and 0Fh)
  1222.     JR Z,sfxspec08
  1223.     CALL RANDOM
  1224.     AND 0Fh
  1225.     LD (freqoffset),A
  1226.  
  1227. sfxspec08:            ;RELOAD
  1228.     LD L,(IY+7)
  1229.     LD H,(IY+8)        ;sfx_address
  1230.     LD BC,12            ;byte12= s_specls
  1231.     ADD HL,BC
  1232.     BIT 3,(HL)        ;freqhi reloaded with newfhi after each newcnt)
  1233.     JR Z,sfxspec10
  1234.     LD A,(IY+12)        ;sfx_count2
  1235.     AND A
  1236.     JR NZ,sfxspec10
  1237.     LD C,2            ;byte14 = newfhi (12+2)
  1238.     ADD HL,BC
  1239.     LD A,(HL)
  1240.     LD (IY+10),A        ;sfx_period (high)
  1241.  
  1242. sfxspec10:            ;Swap low frequency nibbles @ 50Hz
  1243.     LD L,(IY+7)
  1244.     LD H,(IY+8)
  1245.     LD BC,12            ;byte12= specls
  1246.     ADD HL,BC
  1247.     BIT 4,(HL)
  1248.     JR Z,sfxspec20
  1249.     LD A,(IY+9)
  1250.     RRCA
  1251.     RRCA
  1252.     RRCA
  1253.     RRCA
  1254.     LD (IY+9),A
  1255.  
  1256. sfxspec20:
  1257.     LD L,(IY+7)
  1258.     LD H,(IY+8)        ;sfx_address
  1259.     LD BC,12            ;byte12= s_specls
  1260.     ADD HL,BC
  1261.     BIT 5,(HL)        ;Complex Lo (freqlo-bendlo/eor with newflo)
  1262.     JR Z,sfxspec40
  1263.     LD A,(IY+9)        ;sfx_period (low)
  1264.     DEC HL
  1265.     DEC HL            ;12-2
  1266.     SUB (HL)            ;byte10= bendlo
  1267.     LD BC,5
  1268.     ADD HL,BC        ;byte15= newfhi
  1269.     LD C,(HL)
  1270.     XOR C
  1271.     LD (IY+9),A
  1272.  
  1273. sfxspec40:
  1274.     LD L,(IY+7)
  1275.     LD H,(IY+8)        ;sfx_address
  1276.     LD BC,12            ;byte12= s_specls
  1277.     ADD HL,BC
  1278.     BIT 6,(HL)        ;;waver F lo + (random and 03h)
  1279.     JR Z,sfxenvelope
  1280.     CALL RANDOM
  1281.     AND 03H
  1282.     LD (freqoffset),A
  1283.  
  1284. ;-----------------------------------------------------------------------------
  1285. sfxenvelope:
  1286.     LD HL,sfx_envaddress    ;address only
  1287.     LD BC,(chan_num)
  1288.     SLA C
  1289.     ADD HL,BC
  1290.     LD E,(HL)
  1291.     INC HL
  1292.     LD D,(HL)        ;DE = addr of 1st byte of effect envelope
  1293.  
  1294.     BIT 7,(IX+3)        ;envframecnt
  1295.     JR NZ,sfxfinalvalues    ;80h = end of envelope
  1296.     DEC (IX+3)        ;frame countdown (envframecnt)
  1297.     JR NZ,sfxfinalvalues    ;more frames till next step
  1298.  
  1299.     LD A,(IX+9)        ;A = current envlevel
  1300.     LD L,(IX+0)        ;envstage
  1301.     LD H,B            ;HL = 0,3,6,9,12,or 15 (word)
  1302.     ADD HL,DE        ;HL = address of current env stage byte
  1303.     INC HL            ;envbyte1 = step size
  1304.     ADD A,(HL)        ;+ env step value
  1305.     DEC HL            ;envbyte0 = frames
  1306.     LD (IX+9),A        ;save new envlevel
  1307.  
  1308.     DEC (IX+6)        ;envrepeats
  1309.     JR Z,sfxnew_stage
  1310.     LD A,(HL)        ;number of frames till next
  1311.     LD (IX+3),A        ;& store it in envframecnt
  1312.     JR sfxfinalvalues
  1313.  
  1314.  
  1315. sfxnew_stage:
  1316.     LD A,(IX+0)        ;envstage
  1317.     ADD A,3            ;0-3-6-9-12-15
  1318.     LD (IX+0),A        ;update pointer (envstage)
  1319.  
  1320.     LD HL,sfx_envaddress    ;update pointer
  1321.     LD BC,(chan_num)
  1322.     SLA C
  1323.     ADD HL,BC
  1324.     LD E,(HL)
  1325.     INC HL
  1326.     LD D,(HL)        ;DE = sfx_envaddress
  1327.  
  1328.     LD L,A
  1329.     LD H,B
  1330.     ADD HL,DE
  1331.  
  1332.     LD A,(HL)        ;envbyte0 = frames
  1333.     CP 0C0H            ;any loops ?
  1334.     JR C,sfxenv_noloops
  1335.  
  1336.     AND 3FH            ;loop point found
  1337.     LD (IX+0),A        ;so store it (envstage)
  1338.     LD L,A
  1339.     LD H,B
  1340.     ADD HL,DE
  1341.     LD A,(HL)        ;new envframecnt at loop point
  1342.  
  1343. sfxenv_noloops:
  1344.     LD (IX+3),A        ;store new envframecnt
  1345.     LD A,(IX+0)        ;envstage
  1346.     CP 15            ;end stage offset ?
  1347.     JR Z,sfxfinalvalues
  1348.     INC HL
  1349.     INC HL            ;envbyte 2
  1350.     LD A,(HL)        ;no, so new envrepeats
  1351.     LD (IX+6),A        ;& store it
  1352.  
  1353. ;-----------------------------------------------------------------------------
  1354. ;sfxfinalvalues are mapped in for 'sounding' voice only
  1355. ;-----------------------------------------------------------------------------
  1356. sfxfinalvalues:
  1357.     LD A,(IX+9)        ;A = current envlevel
  1358.     CP 10H
  1359.     JR C,sfx_newvolume    ;0Fh or less = within limits
  1360.     CP 80H
  1361.     JR C,sfx_highclip        ;10h to 7Fh = 0Fh (high clip)
  1362.     LD A,0            ;80h to FFh = wrapround ( <0 )
  1363.     JR sfx_newvolume
  1364. sfx_highclip:
  1365.     LD A,0FH
  1366. sfx_newvolume:
  1367.     LD E,A
  1368.  
  1369.     LD A,(effectvol)
  1370.     LD D,B
  1371.     AND A
  1372.     JR Z,sfx_novol
  1373.     LD B,A            ;loop effectvol times
  1374. SF344:    LD A,E
  1375.     ADD A,D
  1376.     LD D,A
  1377.     DJNZ SF344
  1378.  
  1379. sfx_novol:
  1380.     LD L,D
  1381.     LD H,B
  1382.     LD E,L
  1383.     LD D,H
  1384.     ADD HL,HL
  1385.     ADD HL,HL
  1386.     ADD HL,HL
  1387.     ADD HL,HL
  1388.     ADD HL,DE
  1389.     LD A,H
  1390.     RL L
  1391.     ADC A,0
  1392.     LD (tempbyte),A        ;save envelope level
  1393.  
  1394.     LD A,(IY+5)        ;get sfx_waveform
  1395.     AND 01H            ;tone needed ?
  1396.     JR Z,sfxtonevol        ;no, so leave A=0
  1397.     LD A,(tempbyte)        ;yes, so retreive envelope level
  1398. sfxtonevol:
  1399.     LD HL,(chan_num)        ;0,1,2,3
  1400.     CALL PSG_volume
  1401.  
  1402. ;-----------------------------------------------------------------------------
  1403.     LD A,(tempbyte)
  1404.     AND A
  1405.     JR Z,sfxnonoise        ;release noise if env level = 0
  1406.     LD A,(IY+5)        ;get sfx_waveform
  1407.     AND 02H            ;noise needed ?
  1408.     JR NZ,sfxfinalnoise    ;yes
  1409.  
  1410. sfxnonoise:
  1411.     LD A,(NCHAN)        ;no noise needed in this channel
  1412.     CP L            ;was this the noise channel?
  1413.     JP NZ,sfxfinalfreq    ;no
  1414.     LD A,0FFh        ;yes, so release noise channel
  1415.     LD (NCHAN),A
  1416.     XOR A            ;& set noise volume to 0
  1417.     JR sfxnoisevol
  1418.  
  1419. sfxfinalnoise:
  1420.     LD BC,(chan_num)
  1421.     LD A,(NCHAN)
  1422.     CP 0FFH            ;any noise already?
  1423.     JR NZ,sfxfinalnoise2    ;yes, so check for this channel
  1424.     LD A,C            ;no noise used so far
  1425.     LD (NCHAN),A        ;so this channel will use noise
  1426.  
  1427. sfxfinalnoise2:
  1428.     CP C            ;noise in this channel?
  1429.     JR NZ,sfxfinalfreq    ;no
  1430.     LD A,(IY+6)        ;sfx_noisetype
  1431.     and 07h            ;mask out any rubbish
  1432.     or 0E0h            ;select Noise Generator control
  1433.     OUT (PSG),A        ;and send value
  1434.     LD A,(tempbyte)        ;retreive final envelope level
  1435.  
  1436. sfxnoisevol:
  1437.     LD HL,3            ;force channel 3 (noise)
  1438.     CALL PSG_volume        ;& set noise volume
  1439.  
  1440.  
  1441. ;-----------------------------------------------------------------------------
  1442. sfxfinalfreq:
  1443.     LD A,(freqoffset)        ;any random offset (special 04)
  1444.     ADD A,(IY+9)        ;sfx_period
  1445.     LD C,A
  1446.     LD B,(IY+10)
  1447.     LD HL,(chan_num)        ;0,1,2,3
  1448.     CALL PSG_freq
  1449.  
  1450.  
  1451. NEXT_SFX:
  1452.     LD HL,chan_num
  1453.     DEC (HL)
  1454.     BIT 7,(HL)
  1455.     JP Z,SFXLOOP
  1456.     RET
  1457.  
  1458.  
  1459. ;-----------------------------------------------------------------------------
  1460. RANDOM:
  1461.     LD A,(randseed)        ;random number generator
  1462.     LD B,A
  1463.     ADD A,A
  1464.     ADD A,A
  1465.     ADD A,A
  1466.     ADD A,A
  1467.     ADD A,B
  1468.     ADD A,11
  1469.     LD (randseed),A
  1470.     SRL A
  1471.     SRL A
  1472.     SRL A
  1473.     SRL A
  1474.     RET
  1475.  
  1476. ;-------------------------------------------------------------------------------
  1477. ;START OF MUSIC CODE
  1478. ;-------------------------------------------------------------------------------
  1479.  
  1480. SENDMUS:
  1481.     BIT 7,A        ;Enter with A = tracknum or (80H+fader count)
  1482.     JR Z,SMUSIC2
  1483.     AND 07FH        ;negative value = fade value
  1484.     LD (FADER),A
  1485.     RET        ;nothing this time
  1486.  
  1487. SMUSIC2:        ;positive value = new track
  1488.     DI        ;just in case interrupt strikes
  1489.     LD HL,(TRKOFF)
  1490.     EX DE,HL
  1491.     LD L,A
  1492.     LD H,0
  1493.     ADD HL,HL
  1494.     ADD HL,HL
  1495.     ADD HL,HL
  1496.     ADD HL,DE    ;+ address of 1st byte
  1497.     LD BC,6        ;3 words per track
  1498.     LD DE,trackbuffer
  1499.     LDIR
  1500.  
  1501.     LD A,2            ;3 channels
  1502.      LD (chan_num),A
  1503.     LD IY,MUS_VARS+2
  1504. IMLP:    LD (IY+0),0        ;vce_mute
  1505.     LD (IY+6),0        ;seqstep
  1506.     LD (IY+18),0        ;loopcntr
  1507.     LD (IY+27),1        ;duration
  1508.     LD (IY+39),0        ;voicenum
  1509.     LD (IY+75),0FFh        ;threshold
  1510. ;    LD A,(IY+78)        ;marker
  1511. ;    LD (IY+3),A        ;trkstep
  1512.     LD (IY+3),0FFh        ;trkstep
  1513.  
  1514.     CALL readtrack
  1515.  
  1516.     LD HL,(VCEBANK)        ;init envelope (in case of rest at start)
  1517.     LD BC,16
  1518.     ADD HL,BC        ;envelope start @ byte 16 of voicedata
  1519.     EX DE,HL            ;DE = start address of this envelope
  1520.     LD HL,vce_envaddress
  1521.     LD BC,(chan_num)
  1522.     SLA C            ;convert to word offset
  1523.     ADD HL,BC
  1524.     LD (HL),E
  1525.     INC HL
  1526.     LD (HL),D        ;save env address to vce_envaddress
  1527.  
  1528.     DEC IY
  1529.     LD HL,chan_num
  1530.     DEC (HL)
  1531.     JP P,IMLP
  1532.  
  1533.     XOR A
  1534.     LD (fadecnt),A
  1535.     LD (globoffset),A
  1536.     DEC A
  1537.     LD (fader),A
  1538.     LD (status),A
  1539.     LD (TEMPOCNTR),A
  1540.     ld (CLOCK_L),a    ;starts @ 0FFFFh 1st inc to 0000h
  1541.     ld (CLOCK_H),a
  1542.     LD A,(musicvol)
  1543.     LD (fadevol),A        ;reset music volume
  1544.     CALL PSG_off
  1545.     EI            ;re-enable after changes
  1546.     RET
  1547.  
  1548.  
  1549. ;-----------------------------------------------------------------------------
  1550. INTMUSIC:
  1551.     LD A,(status)
  1552.     BIT 7,A
  1553.     RET Z
  1554.  
  1555. fadetest:
  1556.     LD A,(fader)
  1557.     BIT 7,A
  1558.     JR NZ,tempotest
  1559.  
  1560.     OR A        ;set flags
  1561.     JR Z,TRKSTOP    ;080H fader value = stop immediately
  1562.     LD HL,fadecnt
  1563.     DEC (HL)
  1564.     JP P,TEMPOTEST
  1565.     LD (HL),A
  1566.     LD A,(fadevol)
  1567.     DEC A
  1568.     LD (fadevol),A
  1569.     JR Z,trkstop
  1570.  
  1571. TEMPOTEST:
  1572.     LD A,(TEMPOCNTR)        ;init to 0FFh
  1573.     LD HL,TEMPOVAL
  1574.     ADD A,(HL)
  1575.     LD (TEMPOCNTR),A
  1576.     JR NC,TEMPO2
  1577.     ld hl,CLOCK_L    ;now update tempo clock
  1578.     inc (hl)
  1579.     jp nz,TEMPO1
  1580.     inc hl
  1581.     inc (hl)
  1582. TEMPO1:    XOR A
  1583.     JR TEMPO3
  1584. TEMPO2:    LD A,0FFH
  1585. TEMPO3:    LD (TEMPOFLAG),A
  1586.  
  1587. music1:    LD A,0            ;start with channel 0
  1588.     LD (chan_num),A
  1589. musicloop:
  1590.     LD BC,(chan_num)
  1591.     LD A,C
  1592.     AND A            ;set flags only
  1593.     LD HL,0
  1594.     JR Z,MS20        ;chan0
  1595.     LD L,SDLN
  1596.     DEC A
  1597.     JR Z,MS20        ;chan1
  1598.     SLA L
  1599. MS20:    LD (SVPTR),HL        ;SVPTR = 0,SDLN,SDLN*2 (offset for SFX)
  1600.     LD IY,MUS_VARS
  1601.     ADD IY,BC        ;+ channel
  1602.     LD B,H
  1603.     LD C,L
  1604.  
  1605. ;-----------------------------------------------------------------------------
  1606.     LD IX,SFX_VARS
  1607.     ADD IX,BC
  1608.     LD A,(IX+3)        ;sfx_hold
  1609.     AND A
  1610.     JR Z,music1b
  1611.     LD (IY+0),0FFH        ;vce_mute
  1612. ;-----------------------------------------------------------------------------
  1613.  
  1614. music1b:
  1615.     LD A,(TEMPOFLAG)
  1616.     AND A
  1617.     JP NZ,treatment
  1618.  
  1619.     INC (IY+24)        ;notelength
  1620.     DEC (IY+27)        ;duration
  1621.     JP NZ,treatment
  1622.  
  1623.     LD A,(IY+12)        ;trkread (seqnumber)
  1624.     CP 0FEH
  1625.     JR C,seqread
  1626.     JR NZ,trkloop
  1627.  
  1628. trkstop:
  1629.     XOR A
  1630.     LD (status),A
  1631.     LD A,0FFh
  1632.     LD (vce_mute),A        ;mute for effects
  1633.     LD (vce_mute+1),A
  1634.     LD (vce_mute+2),A
  1635.     JP PSG_off
  1636. trkloop:
  1637.     LD (IY+6),0        ;seqstep
  1638.     CALL readtrack
  1639.  
  1640.  
  1641. seqread:
  1642.     LD L,(IY+12)        ;seqnumber
  1643.     LD H,0
  1644.     ADD HL,HL        ;2 bytes per address
  1645.     LD BC,(SEQOFF)
  1646.     ADD HL,BC
  1647.     LD C,(HL)        ;low byte 1st
  1648.     INC HL
  1649.     LD B,(HL)        ;high byte 2nd
  1650.     LD HL,(SEQDATA)
  1651.     ADD HL,BC
  1652.     LD B,H
  1653.     LD C,L
  1654.  
  1655.     LD A,0FFH
  1656.     LD (tempbyte),A        ;check later for new voice
  1657.     LD L,(IY+6)        ;seqstep
  1658.     LD A,l
  1659.     AND A
  1660.     JR NZ,seqread2
  1661.     LD (IY+75),0FFh        ;reset threshold at start of new sequence
  1662.  
  1663. seqread2:
  1664.     LD H,0
  1665.     LD (IY+42),H        ;bendbyte=0
  1666.     LD (IY+36),H        ;attkend=0
  1667.     ld (IY+60),H        ;tied_note=0
  1668.     add HL,BC
  1669.  
  1670. newpair:
  1671.     LD A,(HL)        ;get new sequence byte
  1672.     BIT 7,A
  1673.     JR Z,noteread        ;bpl
  1674.     inc hl            ;ready for 2nd byte in pair
  1675.  
  1676. parm80:    cp 080h            ;voice change
  1677.     jr nz,parm81
  1678.     ld A,(HL)
  1679.     LD (tempbyte),A
  1680.     jp parmexit
  1681.  
  1682. parm81:    cp 081h            ;rest
  1683.     jr nz,parm82
  1684.     LD (IY+60),0FFh        ;force tied_note (continue with same env)
  1685.     CALL VOICEFADE        ;set envelope to fade portion
  1686.     jp duraread
  1687.  
  1688.  
  1689. parm82:    cp 082h            ;bend
  1690.     jr nz,parm83
  1691.     ld a,(hl)
  1692.     LD (IY+42),A        ;bendbyte
  1693.     jp parmexit
  1694.  
  1695. parm83:    cp 083h            ;tempo
  1696.     jr nz,parm84
  1697.     ld a,(hl)
  1698.     LD (TEMPOVAL),A
  1699.     jp parmexit
  1700.  
  1701. parm84:    cp 084h            ;tied
  1702.     jr nz,parm85
  1703.     ld a,0FFh
  1704.     LD (IY+60),A        ;tied_note
  1705.     jp parmexit
  1706.  
  1707. parm85:    cp 085h            ;gate
  1708.     jr nz,parm86
  1709.     ld a,(hl)
  1710.     ld (IY+75),A        ;threshold
  1711.     jp parmexit
  1712.  
  1713. parm86:    cp 086h            ;global offset
  1714.     jr nz,parmexit
  1715.     ld a,(hl)
  1716.     ld (globoffset),A
  1717.  
  1718.  
  1719. parmexit:
  1720.     INC HL            ;ready for note
  1721.     INC (IY+6)        ;add 2 to seqstep
  1722.     INC (IY+6)
  1723.     jp newpair
  1724.  
  1725.  
  1726. noteread:
  1727.     LD A,(HL)
  1728.     LD (IY+15),A        ;notevalue
  1729.     INC HL
  1730. duraread:
  1731.     LD A,(HL)        ;get next sequence byte
  1732.     LD (IY+27),A        ;duration
  1733.     LD (IY+24),0        ;notelength to 0
  1734.     inc hl
  1735.     inc (IY+6)
  1736.     inc (IY+6)        ;add 2 to seqstep
  1737.  
  1738. ;-----------------------------------------------------------------------------
  1739.     LD A,(IY+0)        ;vce_mute
  1740.     AND A
  1741.     JR Z,newstart        ;no SFX
  1742.     LD IX,SFX_VARS
  1743.     LD BC,(SVPTR)        ;0,SDLN,2*SDLN
  1744.     ADD IX,BC
  1745.     LD A,(IX+3)        ;sfx_hold
  1746.     AND A
  1747.     JR NZ,newstart        ;SFX still in initial part
  1748.     LD (IY+60),0        ;ended, so force new note
  1749. ;-----------------------------------------------------------------------------
  1750.  
  1751. newstart:
  1752.     LD A,(tempbyte)        ;set to 0FFh before read
  1753.     BIT 7,A
  1754.     JR NZ,modread        ;00h to 3Fh = new voice
  1755.     CP (IY+39)        ;voicenum = existing voice
  1756.     JR Z,modread        ;ignore if same voice
  1757.     LD (IY+39),A        ;or else save new voice (voicenum)
  1758.     LD (IY+60),0        ;and force envelope restart (tied_note)
  1759.  
  1760. modread:
  1761.     BIT 7,(IY+60)        ;0 forced for new voice/sfx (tied_note)
  1762.     JR NZ,readend        ;continue same env.
  1763.     PUSH HL
  1764.     LD L,(IY+39)        ;voicenum
  1765.     LD H,0
  1766.     ADD HL,HL
  1767.     ADD HL,HL
  1768.     ADD HL,HL
  1769.     ADD HL,HL
  1770.     ADD HL,HL        ;32 bytes in each voice
  1771.     EX DE,HL
  1772.     LD HL,vce_offset
  1773.     LD BC,(chan_num)
  1774.     SLA C
  1775.     ADD HL,BC
  1776.     LD (HL),E
  1777.     INC HL
  1778.     LD (HL),D        ;save new vce_offset (00h,20h,40h,60h etc.)
  1779.     LD HL,(VCEBANK)
  1780.     ADD HL,DE
  1781.     EX (SP),HL        ;HL restored to SEQDATA
  1782.     POP IX            ;IX = 1st byte of voice(VCEBANK+vce_offset)
  1783.     LD A,(IX+0)        ;byte0 = wvefrm
  1784.     LD (IY+30),A        ;mus_waveform
  1785.     LD A,(IX+1)        ;byte1 = nsefrq
  1786.     LD (IY+78),A        ;mus_noisetype
  1787.     LD A,(IX+3)        ;byte3 = specls
  1788.     LD (IY+63),A        ;special
  1789.     LD A,(IX+5)        ;byte5 = offset
  1790.     LD (IY+72),A        ;transpose
  1791.     LD A,(IX+7)        ;byte7 = atkcntr
  1792.     LD (IY+66),A        ;specntdn
  1793.     LD A,(IX+15)        ;byte15= vdelay
  1794.     LD (IY+48),A        ;vibdelay
  1795.  
  1796. ;-----------------------------------------------------------------------------
  1797.     LD IX,SFX_VARS
  1798.     LD BC,(SVPTR)        ;0,SDLN,2*SDLN
  1799.     ADD IX,BC
  1800.     LD A,(IX+3)        ;sfx_hold
  1801.     AND A
  1802.     JR NZ,readend
  1803.     LD (IY+0),0        ;force vce_mute to 0
  1804. ;-----------------------------------------------------------------------------
  1805. readend:
  1806.     LD A,(IY+15)        ;notevalue
  1807.     add A,(IY+72)        ;transpose
  1808.     BIT 7,(IY+63)        ;special (fixed)
  1809.     JR NZ,rdend2
  1810.     ld BC,(globoffset)
  1811.     add A,C
  1812. rdend2:    ld (IY+33),A        ;finalnote
  1813.  
  1814.     ADD A,A
  1815.     ADD A,NOTETABLE AND 255
  1816.     LD E,A
  1817.     ADC A,NOTETABLE/256
  1818.     SUB E
  1819.     LD D,A
  1820.     LD IX,vce_period
  1821.     LD BC,(chan_num)
  1822.     SLA C            ;times 2 for word
  1823.     ADD IX,BC
  1824.     LD A,(DE)
  1825.     LD (IX+0),A        ;new vce_period (low)
  1826.     INC DE
  1827.     LD A,(DE)
  1828.     LD (IX+1),A        ;new vce_period (high)
  1829.  
  1830.     LD A,(HL)
  1831.     CP 0FFH
  1832.     JR NZ,readexit
  1833.  
  1834.     LD (IY+6),0        ;0FFh=end of sequence
  1835.     DEC (IY+9)        ;seqrepeat
  1836.     JR NZ,readexit
  1837.     CALL readtrack
  1838.  
  1839. readexit:
  1840.     BIT 7,(IY+0)        ;vce_mute
  1841.     JP NZ,next_channel
  1842.     LD IX,vce_offset        ;address only
  1843.     LD BC,(chan_num)
  1844.     SLA C            ;* 2 for words
  1845.     ADD IX,BC
  1846.     LD (IX+18),B        ;vibfraction (word)
  1847.     LD (IX+19),B        ;ensures vibrato calculation
  1848.     LD (IY+69),B        ;specntup
  1849.     JP spec10
  1850.  
  1851. treatment:
  1852.     BIT 7,(IY+0)        ;vce_mute
  1853.     JP NZ,next_channel
  1854.  
  1855.     LD IX,vce_offset        ;address only
  1856.     LD BC,(chan_num)
  1857.     SLA C
  1858.     ADD IX,BC
  1859.     LD A,(IY+42)        ;bendbyte
  1860.     AND A
  1861.     JR Z,vibrato
  1862.     LD H,(IX+13)
  1863.     LD L,(IX+12)        ;vce_period
  1864.     LD C,A
  1865.     CP 080H
  1866.     JR NC,bending2
  1867.  
  1868.     LD C,A            ;bend up
  1869.     SBC HL,BC
  1870.     JR bending3
  1871.  
  1872. bending2:
  1873.     AND 7FH
  1874.     LD C,A            ;bend down
  1875.     ADD HL,BC
  1876.  
  1877. bending3:
  1878.     LD (IX+12),L
  1879.     LD (IX+13),H        ;save new vce_period
  1880.     JP specials
  1881.  
  1882.  
  1883. vibrato:
  1884.     LD A,(IY+48)        ;vibdelay
  1885.     AND A
  1886.     JR Z,vib1
  1887.     DEC (IY+48)        ;vibdelay
  1888.     JP specials
  1889.  
  1890. vib1:    LD A,(IY+66)        ;specntdn
  1891.     AND A
  1892.     JP NZ,specials
  1893.     LD E,(IX+0)        ;vce_offset
  1894.     LD D,(IX+1)
  1895.     LD HL,(VCEBANK)
  1896.     ADD HL,DE        ;1st byte of this voice data
  1897.     LD C,14            ;byte14 = vibrato
  1898.     ADD HL,BC
  1899.     LD A,(HL)
  1900.     AND A
  1901.     JP Z,specials        ;vibrato = 0 (none)
  1902.  
  1903.     BIT 7,(IX+19)          ;vibfraction
  1904.     JR NZ,vib4        ;values caclulated
  1905.     LD E,A            ;1st frame of every new note
  1906.     LD D,0
  1907.     LD HL,vibtab1
  1908.     ADD HL,DE
  1909.     LD A,(HL)
  1910.     LD (IY+57),A        ;viblimit
  1911.     LD HL,vibtab2
  1912.     ADD HL,DE
  1913.     LD A,(HL)
  1914.     LD (IX+18),A        ;vibfraction
  1915.     LD (IY+51),D        ;vibdir
  1916.     LD (IY+54),D        ;vibstep
  1917.  
  1918.     LD L,(IY+33)        ;finalnote
  1919.     LD H,D
  1920.     ADD HL,HL
  1921.     LD DE,NOTETABLE
  1922.     ADD HL,DE
  1923.     LD A,(HL)
  1924.     LD C,A
  1925.     LD (IX+12),A        ;vce_period (low)
  1926.     INC HL
  1927.     LD A,(HL)
  1928.     LD B,A
  1929.     LD (IX+13),A        ;vce_period (high)
  1930.     INC HL
  1931.     LD E,(HL)        ;1 semitone higher vce_period (low)
  1932.     INC HL
  1933.     LD D,(HL)        ;DE = vce_period 1 semitone higher
  1934.     LD H,B
  1935.     LD L,C
  1936.     AND A
  1937.     SBC HL,DE        ;HL = semitone 'size'
  1938.  
  1939.     LD E,(IX+18)        ;vibfraction
  1940.     LD D,(IX+19)
  1941.     CALL DIVHL
  1942.     LD A,H
  1943.     OR L
  1944.     JR NZ,vib2        ;0 = step too small
  1945.     LD HL,1            ;so default to 1
  1946. vib2:    LD (IX+6),L
  1947.     LD (IX+7),H        ;vibstepsize
  1948.     LD (IX+19),0FFH        ;finished = minus
  1949.     JR specials
  1950.  
  1951. vib4:    LD E,(IX+6)        ;vibstepsize (word)
  1952.     LD D,(IX+7)
  1953.     LD L,(IX+12)        ;vce_period (word)
  1954.     LD H,(IX+13)
  1955.     BIT 7,(IY+45)        ;freqdir
  1956.     JR NZ,vib5
  1957.     ADD HL,DE
  1958.     JR vib6
  1959.  
  1960. vib5:    AND A
  1961.     SBC HL,DE
  1962.  
  1963. vib6:    LD (IX+12),L        ;vce_period
  1964.     LD (IX+13),H
  1965.     BIT 7,(IY+51)        ;vibdir
  1966.     JR NZ,vib7
  1967.     INC (IY+54)
  1968.     LD A,(IY+54)        ;vibstep
  1969.     CP (IY+57)        ;reached viblimit ?
  1970.     JR C,specials
  1971.     LD (IY+51),0FFH        ;vibdir
  1972.     LD A,(IY+45)
  1973.     CPL
  1974.     LD (IY+45),A        ;swap direction (freqdir)
  1975.     JR specials
  1976.  
  1977. vib7:    DEC (IY+54)        ;vibstep
  1978.     JR NZ,specials
  1979.     LD (IY+51),0        ;vibdir
  1980.  
  1981.  
  1982. ;-----------------------------------------------------------------------------
  1983. specials:
  1984.     LD H,(IX+1)        ;vce_offset (00h,20h,40h,60h etc.)
  1985.     LD L,(IX+0)
  1986.     BIT 0,(IY+63)        ;ARPEGGIO
  1987.     JR Z,spec02
  1988.     LD A,(IY+69)        ;specntup
  1989.     SRL A
  1990.     AND 3
  1991.     LD E,A
  1992.     LD D,0
  1993.     ADD HL,DE
  1994.     JP spec20a
  1995.  
  1996.  
  1997. spec02:    BIT 1,(IY+63)        ;TRILL NOTE
  1998.     JR Z,spec04
  1999.     BIT 0,(IY+69)        ;specntup
  2000.     JR NZ,spec02b
  2001.     LD L,(IY+33)        ;finalnote
  2002.     LD H,0
  2003.     JR spec02c
  2004. spec02b: LD BC,(VCEBANK)
  2005.     ADD HL,BC
  2006.     LD BC,13
  2007.     ADD HL,BC
  2008.     LD L,(HL)
  2009.     LD H,B
  2010.     BIT 7,L
  2011.     JR Z,spec02c
  2012.     LD A,L
  2013.     AND 7FH
  2014.     ADD A,(IY+33)        ;finalnote
  2015.     LD L,A
  2016. spec02c: ADD HL,HL        ;change to alternate note
  2017.     LD DE,NOTETABLE
  2018.     EX DE,HL
  2019.     ADD HL,DE
  2020.     LD A,(HL)
  2021.     LD (IX+12),A        ;vce_period
  2022.     INC HL
  2023.     LD A,(HL)
  2024.     LD (IX+13),A
  2025.  
  2026.  
  2027. spec04:    BIT 2,(IY+63)        ;DRUM
  2028.     JR Z,spec08
  2029.     LD L,(IX+0)        ;vce_offset (00h,20h,40h,60h etc.)
  2030.     LD H,(IX+1)
  2031.     BIT 0,(IY+69)        ;specntup
  2032.     JR NZ,spec04b
  2033.     LD BC,(VCEBANK)
  2034.     ADD HL,BC
  2035.     LD A,(HL)        ;byte0 = wvefrm (HL=VCEBANK+vce_offset)
  2036.     JR spec04c
  2037. spec04b: LD A,2            ;noise alternate frames (2 = noise)
  2038. spec04c: LD (IY+30),A        ;mus_waveform
  2039.     LD BC,(VCEBANK)
  2040.     LD L,(IX+0)
  2041.     LD H,(IX+1)
  2042.     ADD HL,BC
  2043.     LD BC,4            ;byte4 = bendrate
  2044.     ADD HL,BC
  2045.     LD A,(IX+12)        ;vce_period
  2046.     ADD A,(HL)        ;(HL=VCEBANK+vce_offset+4)
  2047.     LD C,A
  2048.     LD A,(IX+13)
  2049.     ADC A,B
  2050.     LD B,A
  2051.     RLA
  2052.     JR C,spec08
  2053.     LD (IX+12),C
  2054.     LD (IX+13),B
  2055.  
  2056.  
  2057. spec08:    BIT 3,(IY+63)        ;CHORD
  2058.     JR Z,spec10
  2059.     LD A,(IY+69)        ;specntup
  2060.     AND 3
  2061.     ADD A,(IX+0)
  2062.     LD L,A
  2063.     ADC A,(IX+1)
  2064.     SUB L
  2065.     LD H,A
  2066.     JR spec20a
  2067.  
  2068.     
  2069. spec10:    BIT 4,(IY+63)        ;ATKCTRL
  2070.     JR Z,spec20
  2071.     LD L,(IX+0)
  2072.     LD H,(IX+1)
  2073.     LD A,(IY+66)
  2074.     LD BC,(VCEBANK)
  2075.     AND A
  2076.     JR Z,spec10b
  2077.     ADD HL,BC
  2078.     LD BC,8            ;byte8 = atkctrl
  2079.     JR spec10c
  2080. spec10b: BIT 7,(IY+36)        ;attkend
  2081.     JR NZ,spec20
  2082. spec10c: ADD HL,BC
  2083.     LD A,(HL)
  2084.     LD (IY+30),A        ;mus_waveform
  2085.  
  2086.  
  2087. spec20:    BIT 5,(IY+63)        ;ATKNOTE
  2088.     JR Z,spec40
  2089.     LD A,(IY+66)        ;specntdn
  2090.     AND A
  2091.     JR Z,spec20c
  2092.     LD A,(IY+69)        ;specntup
  2093.     ADD A,(IX+0)        ;+ vce_offset
  2094.     LD L,A
  2095.     ADC A,(IX+1)
  2096.     SUB L
  2097.     LD H,A
  2098. spec20a: LD BC,(VCEBANK)
  2099.     ADD HL,BC
  2100.     LD BC,9            ;byte9 = atknote1
  2101.     ADD HL,BC
  2102.     LD A,(HL)
  2103.     LD L,A
  2104.     LD H,B
  2105.     BIT 7,A
  2106.     JR Z,spec20d
  2107.     AND 7FH            ;fixed interval
  2108.     LD L,A
  2109.     CP 40H
  2110.     JR NC,spec20b
  2111.     ADD A,(IY+33)        ;finalnote
  2112.     LD L,A
  2113.     JR spec20d
  2114. spec20b: AND 3FH
  2115.     LD L,A
  2116.     LD A,(IY+33)        ;finalnote
  2117.     SUB L
  2118.     LD L,A
  2119.     JR spec20d
  2120. spec20c: BIT 7,(IY+36)        ;attkend 1 frame after attack
  2121.     JR NZ,spec40
  2122.     LD L,(IY+33)        ;restore proper note (finalnote)
  2123. spec20d: LD H,0
  2124.     ADD HL,HL
  2125.     LD BC,NOTETABLE
  2126.     ADD HL,BC
  2127.     LD A,(HL)
  2128.     INC HL
  2129.     LD (IX+12),A        ;vce_period
  2130.     LD A,(HL)
  2131.     LD (IX+13),A
  2132.  
  2133.  
  2134. spec40:    BIT 6,(IY+63)
  2135.     JR Z,gatecheck
  2136.     LD BC,(VCEBANK)
  2137.     LD L,(IX+0)
  2138.     LD H,(IX+1)
  2139.     ADD HL,BC
  2140.     LD BC,9            ;byte9 = atknote1
  2141.     ADD HL,BC
  2142.     LD A,(HL)
  2143.     LD (IY+42),A        ;bendbyte
  2144.  
  2145.  
  2146. ;-----------------------------------------------------------------------------
  2147. gatecheck:
  2148.     LD A,(IY+24)        ;notelength
  2149.     CP (IY+75)        ;threshold
  2150.     JR NZ,envelopes
  2151.     CALL VOICEFADE
  2152.     LD IX,vce_offset        ;address only
  2153.     LD BC,(chan_num)
  2154.     SLA C
  2155.     ADD IX,BC
  2156.  
  2157.  
  2158. envelopes:
  2159.     BIT 7,(IY+60)        ;tied_note
  2160.     JR NZ,oldenvelope
  2161.     LD A,(IY+69)        ;specntup
  2162.     AND A
  2163.     JR NZ,oldenvelope        ;not 1st frame
  2164.  
  2165. newenvelope:
  2166.     LD L,(IX+0)        ;vce_offset
  2167.     LD H,(IX+1)
  2168.     LD BC,(VCEBANK)
  2169.     ADD HL,BC
  2170.     LD BC,16
  2171.     ADD HL,BC        ;envelope start @ byte 16 of voicedata
  2172.     EX DE,HL            ;DE = start address of this envelope
  2173.  
  2174.     LD HL,vce_envaddress
  2175.     LD BC,(chan_num)
  2176.     SLA C            ;convert to word offset
  2177.     ADD HL,BC
  2178.     LD (HL),E
  2179.     INC HL
  2180.     LD (HL),D        ;save env address to vce_envaddress
  2181.  
  2182.     LD IX,ENV_VARS    ;address only
  2183.     LD BC,(chan_num)
  2184.     ADD IX,BC        ;IX=address of ENV_VARS+channel
  2185.     INC DE
  2186.     INC DE            ;envbyte2 = repeat number
  2187.     LD A,(DE)
  2188.     LD (IX+6),A        ;read envrepeats
  2189.     LD (IX+0),B        ;envstage to 0 (start at 1st env byte)
  2190.     LD (IX+3),1        ;envframecnt (dec to 0 this time)
  2191.     LD (IX+9),B        ;envlevel to 0
  2192.  
  2193. oldenvelope:
  2194.     LD BC,(chan_num)
  2195.     LD IX,ENV_VARS    ;address only
  2196.     ADD IX,BC
  2197.     SLA C
  2198.  
  2199.     LD HL,vce_envaddress
  2200.     ADD HL,BC
  2201.     LD E,(HL)
  2202.     INC HL
  2203.     LD D,(HL)        ;DE = address of 1st byte of voice envelope
  2204.     LD L,(IX+0)        ;envstage
  2205.     LD H,B            ;HL = 0,3,6,9,12,or 15 (word)
  2206.     ADD HL,DE
  2207.     EX DE,HL            ;DE = address of current env stage byte
  2208.     BIT 7,(IX+3)        ;envframecnt
  2209.     JR NZ,vcefinalvalues    ;80h = end of envelope
  2210.     DEC (IX+3)        ;frame countdown (envframecnt)
  2211.     JR NZ,vcefinalvalues    ;more frames till next step
  2212.  
  2213.     LD C,(IX+9)        ;C = current envlevel
  2214.     INC DE
  2215.     LD A,(DE)        ;A = new env step value
  2216.     DEC DE
  2217.     ADD A,C
  2218.     LD (IX+9),A        ;save new envlevel
  2219.  
  2220.     DEC (IX+6)        ;envrepeats
  2221.     JR Z,new_stage
  2222.     LD A,(DE)        ;number of frames till next
  2223.     LD (IX+3),A        ;& store it in envframecnt
  2224.     JR vcefinalvalues
  2225.  
  2226.  
  2227. new_stage:
  2228.     LD A,(IX+0)        ;envstage
  2229.     ADD A,3            ;0-3-6-9-12-15
  2230.     LD (IX+0),A        ;save new envstage
  2231.  
  2232.     LD HL,vce_envaddress    ;update pointer
  2233.     LD BC,(chan_num)
  2234.     SLA C
  2235.     ADD HL,BC
  2236.     LD E,(HL)
  2237.     INC HL
  2238.     LD D,(HL)        ;DE = vce_envaddress
  2239.     LD L,A
  2240.     LD H,B
  2241.     ADD HL,DE
  2242.  
  2243.     LD A,(HL)        ;A = design framecnt
  2244.     CP 0C0H            ;any loops ?
  2245.     JR C,env_noloops
  2246.     AND 3FH            ;loop point found
  2247.     LD (IX+0),A        ;envstage
  2248.     LD L,A
  2249.     LD H,B
  2250.     ADD HL,DE
  2251.     LD A,(HL)        ;new envframecnt at loop point
  2252.  
  2253. env_noloops:
  2254.     LD (IX+3),A        ;store new envframecnt
  2255.     LD A,(IX+0)        ;envstage
  2256.     CP 15            ;end stage offset ?
  2257.     JR Z,vcefinalvalues
  2258.     INC HL
  2259.     INC HL            ;envbyte2
  2260.     LD A,(HL)        ;no, so new envrepeats
  2261.     LD (IX+6),A        ;and store it
  2262.  
  2263.  
  2264. ;-----------------------------------------------------------------------------
  2265. ;vcefinalvalues are mapped in for 'sounding' voices only
  2266. ;tone/noise bits, frequency & volume overriden direct to PSG chip
  2267. ;-----------------------------------------------------------------------------
  2268. vcefinalvalues:
  2269.     LD A,(IX+9)        ;A = current envlevel
  2270.     CP 10H
  2271.     JR C,vce_newvolume    ;0Fh or less = within limits
  2272.     CP 80H
  2273.     JR C,vce_highclip        ;10h to 7Fh = 0Fh (high clip)
  2274.     LD A,0            ;80h to FFh = wrapround ( <0 )
  2275.     JR vce_newvolume
  2276. vce_highclip:
  2277.     LD A,0FH
  2278. vce_newvolume:
  2279.     LD E,A
  2280.  
  2281.     LD A,(fadevol)        ;A = master volume
  2282.     LD D,B            ;D = 0
  2283.     AND A            ;set flags only
  2284.     JR Z,vce_novol
  2285.     LD B,A
  2286. MS421:    LD A,E
  2287.     ADD A,D
  2288.     LD D,A
  2289.     DJNZ MS421
  2290.  
  2291. vce_novol:
  2292.     LD L,D
  2293.     LD H,B
  2294.     LD E,L
  2295.     LD D,H
  2296.     ADD HL,HL
  2297.     ADD HL,HL
  2298.     ADD HL,HL
  2299.     ADD HL,HL
  2300.     ADD HL,DE
  2301.     LD A,H
  2302.     RL L
  2303.     ADC A,0
  2304.     LD (tempbyte),A        ;save envelope level
  2305.  
  2306.     LD A,(IY+30)        ;get mus_waveform
  2307.     AND 01H            ;tone needed ?
  2308.     JR Z,vcetonevol        ;no, so leave A=0
  2309.     LD A,(tempbyte)        ;yes, so retreive envelope level
  2310. vcetonevol:
  2311.     LD HL,(chan_num)        ;0,1,2,3
  2312.     CALL PSG_volume
  2313.  
  2314. ;-----------------------------------------------------------------------------
  2315.     LD A,(tempbyte)
  2316.     AND A
  2317.     JR Z,nonoise        ;release noise if envelope level = 0
  2318.     LD A,(IY+30)        ;get mus_waveform
  2319.     AND 02H            ;noise needed ?
  2320.     JR NZ,finalnoise        ;yes
  2321.  
  2322. nonoise:
  2323.     LD A,(NCHAN)        ;no noise needed in this channel
  2324.     CP L            ;was this the noise channel?
  2325.     JP NZ,finalfreq        ;no
  2326.     LD A,0FFh        ;yes, so release noise channel
  2327.     LD (NCHAN),A
  2328.     XOR A            ;& set noise volume to 0
  2329.     JR vcenoisevol
  2330.  
  2331. finalnoise:
  2332.     LD BC,(chan_num)
  2333.     LD A,(NCHAN)
  2334.     CP 0FFH            ;any noise already?
  2335.     JR NZ,finalnoise2        ;yes, so check for this channel
  2336.     LD A,C            ;no noise used so far
  2337.     LD (NCHAN),A        ;so this channel will use noise
  2338.  
  2339. finalnoise2:
  2340.     CP C            ;noise in this channel?
  2341.     JR NZ,finalfreq        ;no
  2342.     LD A,(IY+78)        ;mus_noisetype
  2343.     and 07h            ;just in case
  2344.     or 0E0h            ;select Noise Generator control
  2345.     OUT (PSG),A        ;and send value
  2346.     LD A,(tempbyte)        ;retreive final envelope level
  2347.  
  2348. vcenoisevol:
  2349.     LD HL,3            ;force channel 3 (noise)
  2350.     CALL PSG_volume        ;& set noise volume
  2351.  
  2352.  
  2353. ;-----------------------------------------------------------------------------
  2354. finalfreq:
  2355.     LD HL,vce_period
  2356.     LD BC,(chan_num)
  2357.     SLA C
  2358.     ADD HL,BC
  2359.     EX DE,HL
  2360.     LD A,(DE)        ;vce_period (low)
  2361.     INC DE
  2362.     LD L,A
  2363.     LD A,(DE)
  2364.     LD H,A            ;HL = vce_period (word)
  2365.     LD A,(chan_num)
  2366.     AND A
  2367.     JR Z,finalfreq3        ;channel 1 always in tune
  2368.  
  2369.     LD D,0
  2370.     LD E,H
  2371.     CP 1
  2372.     JR NZ,finalfreq2
  2373.     ADD HL,DE        ;channel 2 1/256th lower
  2374.     JR finalfreq3
  2375. finalfreq2:
  2376.     AND A
  2377.     SBC HL,DE        ;channel 3 1/256th higher
  2378. finalfreq3:
  2379.     LD C,L
  2380.     LD B,H            ;frequency in BC
  2381.     LD HL,(chan_num)        ;0,1,2,3
  2382.     CALL PSG_freq
  2383.  
  2384.  
  2385. ;-----------------------------------------------------------------------------
  2386.     LD A,(IY+66)        ;specntdn
  2387.     AND A
  2388.     JR NZ,finalval1
  2389.     LD (IY+36),0FFH        ;attkend
  2390.     JR finalval2
  2391. finalval1:
  2392.     DEC (IY+66)        ;specntdn
  2393. finalval2:
  2394.     INC (IY+69)        ;specntup
  2395.  
  2396. next_channel:
  2397.     LD HL,chan_num
  2398.     inc (HL)
  2399.     LD A,(HL)
  2400.     CP 3
  2401.     JP C,MUSICLOOP
  2402.     RET
  2403.  
  2404.  
  2405.  
  2406.  
  2407. ;-----------------------------------------------------------------------------
  2408. readtrack:
  2409.     LD HL,trackbuffer
  2410.     LD BC,(chan_num)
  2411.     SLA C
  2412.     ADD HL,BC        ;times 2 for word offset
  2413.     LD C,(HL)        ;low byte 1st
  2414.     INC HL
  2415.     LD B,(HL)        ;high byte 2nd
  2416.     LD HL,(TRKDATA)
  2417.     ADD HL,BC
  2418.     LD B,H
  2419.     LD C,L            ;BC=address of 1st track byte
  2420.  
  2421. readt0:    INC (IY+3)        ;trackstep
  2422.     LD L,(IY+3)
  2423.     LD H,0
  2424.     ADD HL,BC        ;HL=address of this track byte
  2425.     LD A,(HL)
  2426.     CP 0FDH
  2427.     JR C,readt1
  2428.     JR Z,readfade
  2429.     LD (IY+12),A        ;seqnumber
  2430.     INC HL
  2431.     LD A,(HL)
  2432.     DEC A
  2433.     LD (IY+3),A        ;trackstep
  2434.     RET
  2435.  
  2436. readfade:
  2437.     INC (IY+3)        ;trackstep
  2438.     INC HL
  2439.     LD A,(HL)
  2440.     LD (fader),A
  2441.     JR readt0
  2442.  
  2443. readt1:    BIT 6,(HL)        ;40h bit set means loop
  2444.     JR Z,readt2
  2445.  
  2446. readl0:    LD A,(IY+18)        ;loopcntr
  2447.     AND A
  2448.     JR NZ,readl1        ;loopcntr <> 0 means already in loop
  2449.     LD A,(HL)        ;get track byte
  2450.     AND 3FH
  2451.     LD (IY+18),A        ;loopcntr
  2452.     INC (IY+3)        ;trackstep
  2453.     INC HL
  2454.     PUSH HL
  2455.     AND A
  2456.     SBC HL,BC
  2457.     LD (IY+21),L        ;return point (loopmem)
  2458.     POP HL
  2459.     JR readt2
  2460.  
  2461. readl1:    DEC (IY+18)        ;already in loop (loopcntr)
  2462.     JR NZ,readl2
  2463.     JR readt0        ;move to next track byte
  2464.  
  2465. readl2:    LD A,(IY+21)        ;loopmem
  2466.     LD (IY+3),A        ;-> trackstep
  2467.     LD L,A
  2468.     LD H,0
  2469.     ADD HL,BC
  2470.  
  2471. readt2:    LD A,(HL)
  2472.     LD (IY+9),A        ;seqrepeat
  2473.     INC (IY+3)        ;trackstep
  2474.     INC HL
  2475.     LD A,(HL)
  2476.     LD (IY+12),A        ;seqnumber
  2477.     RET
  2478.  
  2479. ;-----------------------------------------------------------------------------
  2480. ;Set all chip volumes to zero
  2481. ;-----------------------------------------------------------------------------
  2482. PSG_off:
  2483.     ld HL,CLRPSG
  2484.     ld C,PSG
  2485.     ld B,4            ;4 bytes in table
  2486.     OTIR
  2487.     ret
  2488.  
  2489.  
  2490. ;-----------------------------------------------------------------------------
  2491. ;Set PSG volume (Enter with A = 4 bit volume value/HL=chan_num)
  2492. ;-----------------------------------------------------------------------------
  2493. PSG_volume:
  2494.     PUSH AF
  2495.     cpl
  2496.     and 0Fh            ;convert volume to attenuation
  2497.     ld B,A            ;& save for later
  2498.     LD A,L            ;get chan_num (0,1,2,3)
  2499.     SLA A            ;0,2,4,6
  2500.     ADD A,9            ;9,B,D,F
  2501.     SLA A
  2502.     SLA A
  2503.     SLA A
  2504.     SLA A            ;90,B0,D0,F0
  2505.     ADD A,B            ;add in atten. value
  2506.     OUT (PSG),A
  2507.     POP AF
  2508.     RET
  2509.  
  2510. ;-----------------------------------------------------------------------------
  2511. ;Set PSG frequency (Enter with BC = 10 bit frequency value/HL=chan_num)
  2512. ;-----------------------------------------------------------------------------
  2513. PSG_freq:
  2514.     LD A,L            ;get chan_num (0,1,2,3)
  2515.     SLA A            ;0,2,4,6
  2516.     ADD A,8            ;8,A,C,E
  2517.     SLA A
  2518.     SLA A
  2519.     SLA A
  2520.     SLA A            ;80,A0,C0,E0
  2521.     ld D,A            ;save for later
  2522.     ld A,C            ;get low byte of frequency
  2523.     AND 0Fh            ;mask out high nibble
  2524.     OR D
  2525.     OUT (PSG),A        ;set 1st byte
  2526.  
  2527.     LD A,C            ;get low byte of frequency
  2528.  
  2529.     nop            ;OK with this
  2530.  
  2531. bug:    SRL B
  2532.     RRA
  2533.     SRL B
  2534.     RRA
  2535.     SRL B
  2536.     RRA
  2537.     SRL B
  2538.     RRA
  2539.     AND 3Fh            ;top 2 bits of 2nd byte always 0
  2540.     OUT (PSG),A        ;set 2nd byte
  2541.     RET
  2542.  
  2543. ;-----------------------------------------------------------------------------
  2544. ;Sets envelope to fade portion (called by GATE and REST)
  2545. ;-----------------------------------------------------------------------------
  2546. VOICEFADE:
  2547.     LD IX,ENV_VARS    ;address only
  2548.     LD DE,(chan_num)
  2549.     ADD IX,DE
  2550.     LD A,(IX+0)        ;current envstage
  2551.     CP 15            ;already at fade ?
  2552.     JR Z,VCEXIT        ;yes, so leave alone
  2553.     LD (IX+0),9        ;envstage to 12 (fade) this frame
  2554.     LD (IX+3),1        ;envframecnt to 0 this frame
  2555.     LD (IX+6),1        ;envrepeats to 0 this frame
  2556. VCEXIT:    RET
  2557.  
  2558. ;-----------------------------------------------------------------------------
  2559. ;DIVHL - unsigned divide HL/DE
  2560. ;-----------------------------------------------------------------------------
  2561. DIVHL:
  2562.     ADD HL,HL
  2563.     LD A,H
  2564.     LD C,L
  2565.     LD HL,0
  2566. APDIV:    LD B,16
  2567. DI22:    ADC HL,HL
  2568.     SBC HL,DE
  2569.     JR NC,DI32
  2570.     ADD HL,DE
  2571. DI32:    RL C
  2572.     RLA
  2573.     DJNZ DI22
  2574.     CPL
  2575.     LD H,A
  2576.     LD A,C
  2577.     CPL
  2578.     LD L,A
  2579.     RET
  2580.  
  2581.  
  2582. ;-------------------------------------------------------------------------------
  2583. ;START OF ROM DATA
  2584. ;-------------------------------------------------------------------------------
  2585. CLRPSG        db 09Fh,0BFh,0DFh,0FFh
  2586.  
  2587. vibtab1:    DB 0,1,1,1,1,4,3,2
  2588.         DB 4,3,2,1,3,2,1,3,2,2,1
  2589. vibtab2:    DB 1,32,16,8,4,32,32,16
  2590.         DB 16,16,8,2,8,4,1,2,2,1,1
  2591.  
  2592. NOTETABLE:    dw 3FFh,3FFh,3FFh,3FFh,3FFh,3FFh    ;C-2 00h (too low)
  2593.         dw 3FFh,3FFh,3FFh,3FFh,3FFh,3FFh
  2594.         dw 3FFh,3FFh,3FFh,3FFh,3FFh,3FFh    ;C-1 0Ch (too low)
  2595.         dw 3FFh,3FFh,3FFh,3FFh,3FFh,3FFh
  2596.         dw 3FFh,3FFh,3FFh,3FFh,3FFh,3FFh    ;C0 18h (too low)
  2597.         dw 3FFh,3FFh,3FFh,3FFh,3FFh,3FFh
  2598.         dw 3FFh,3FFh,3FFh,3FFh,3FFh,3FFh    ;C1 24h (up 1 octave)
  2599.         dw 3FFh,3FFh,3FFH,3F0h,3B7h,382h    ;A1 110Hz (lowest)
  2600.         dw 34Fh,320h,2F3h,2C9h,2A1h,27Bh    ;C2 30h 130Hz
  2601.         dw 257h,236h,216h,1F8h,1DCh,1C1h
  2602.         dw 1A8h,190h,179h,164h,150h,13Dh    ;C3 3Ch 262Hz(MID)
  2603.         dw 12Ch,11Bh,10Bh,0FCh,0EEh,0E0h
  2604.         dw 0D4h,0C8h,0BDh,0B2h,0A8h,09Fh    ;C4 48h 523Hz
  2605.         dw 096h,08Dh,085h,07Eh,077h,070h
  2606.         dw 06Ah,064h,05Eh,059h,054h,04Fh    ;C5 54h 1046Hz
  2607.         dw 04Bh,047h,043h,03Fh,03Bh,038h
  2608.         dw 035h,032h,02Fh,02Dh,02Ah,028h    ;C6 60h 2093Hz
  2609.         dw 025h,023h,021h,01Fh,01Eh,01Ch
  2610.         dw 01Ah,019h,018h,016h,015h,014h    ;C7 6Ch 4186Hz
  2611.         dw 013h,012h,011h,010h,00Fh,00Eh
  2612.         dw 00Dh,00Ch,00Ah,008h,006h,004h    ;C8 78h 8372Hz
  2613.         dw 002h,000h            ;G8 7Fh 12542Hz
  2614. ;        dw 00Dh,00Ch,00Ch,00Bh,00Ah,00Ah    ;C8 78h 8372Hz
  2615. ;        dw 009h,009h            ;G8 7Fh 12542Hz
  2616.  
  2617. CODESIZE    equ $-JUMPTABLE
  2618.  
  2619. ;*****************************************************************************
  2620.         ORG 2000H    ;comment this out for driver version
  2621.  
  2622. GAMEDATA:    INCLUDE BLANK-GG.SND (BIN) ;7 WORD VECTOR TABLE @ START
  2623.  
  2624. MUSICEND:
  2625. ;*****************************************************************************
  2626.  
  2627. ;        IF GAMEGEAR
  2628. ;        ORG $7FF8
  2629. ;        DB 0FFH DUP 8
  2630. ;        ENDIF
  2631. ;On the Master system this area is occupied by the registration area.
  2632. ;It is not used on the Game Gear so 7FF8H to 7FFFH should be filled
  2633. ;with 0FFH to ensure valid values 'under' the comms.
  2634.  
  2635. ;-------------------------------------------------------------------------------
  2636. ;DRIVER RAM VARIABLES
  2637. ;-------------------------------------------------------------------------------
  2638.         ORG    MUSICRAM
  2639.  
  2640. RAM_VARS:
  2641. sfxno        DS    1    ;00h-4Fh=effect/ 0FFh=no effect
  2642. tuneno        DS    1    ;00h-17h=music/ 80h=stop/ 81h-0FEh=fade
  2643. status:        DS    1    ;0FFh=music active/ 00h=music finished
  2644. effectvol:    DS    1    ;00h-0Fh=master volume setting for effects
  2645. musicvol:    DS    1    ;00h-0Fh=master volume setting for music
  2646. fadevol:    DS    1    ;00-0Fh=current music volume
  2647.  
  2648. ;-----------------------------------------------------------------------------
  2649. SFX_VARS:
  2650. sfx_channel:    DS    1    ;IY=0
  2651. sfx_priority:    DS    1    ;+1
  2652. sfx_priortest:    DS    1    ;+2
  2653. sfx_hold:    DS    1    ;+3
  2654. sfx_framechop:    DS    1    ;+4
  2655. sfx_waveform:    DS    1    ;+5
  2656. sfx_noisetype    DS    1    ;+6
  2657. sfx_address:    DS    2    ;+7/8  (word)
  2658. sfx_period:    DS    2    ;+9/10 (word)
  2659. sfx_atkcnt:    DS    1    ;+11
  2660. sfx_count2:    DS    1    ;+12
  2661. sfx_dirflag:    DS    1    ;+13
  2662.  
  2663. SDLN        equ    $-SFX_VARS
  2664. SVARSB:        DS    SDLN
  2665. SVARSC:        DS    SDLN
  2666.  
  2667. ;-----------------------------------------------------------------------------
  2668. MUS_VARS:
  2669. vce_mute:    DS    3    ;IY=0 0=music sounds/FFh=voice muted
  2670. trackstep:    DS    3    ;3
  2671. seqstep:    DS    3    ;6
  2672. seqrepeat:    DS    3    ;9
  2673. seqnumber:    DS    3    ;12
  2674. notevalue    DS    3    ;15
  2675. loopcntr:    DS    3    ;18
  2676. loopmem:    DS    3    ;21
  2677. notelength:    DS    3    ;24
  2678. duration:    DS    3    ;27
  2679. mus_waveform:    DS    3    ;30 0=none/1=tone/2=noise/3=tone & noise
  2680. finalnote:    DS    3    ;33
  2681. attkend:    DS    3    ;36
  2682. voicenum:    DS    3    ;39
  2683. bendbyte:    DS    3    ;42
  2684.  
  2685. freqdir:    DS    3    ;45
  2686. vibdelay:    DS    3    ;48
  2687. vibdir:        DS    3    ;51
  2688. vibstep:    DS    3    ;54
  2689. viblimit:    DS    3    ;57
  2690.  
  2691. tied_note:    DS    3    ;60
  2692. special:    DS    3    ;63
  2693. specntdn:    DS    3    ;66
  2694. specntup:    DS    3    ;69
  2695.  
  2696. transpose    DS    3    ;+72
  2697. threshold    DS    3    ;+75 length before gate off (init to $FF)
  2698. mus_noisetype    DS    3    ;+78
  2699.  
  2700. ;marker:    DS    3    ;+78 (DEFB 0FFH,0FFH,0FFH)
  2701.  
  2702.  
  2703. vce_offset:    DS    6    ;IX=0   (+75)    00h,20h,40h,60h etc.
  2704. vibstepsize:    DS    6    ;+6/7   (+81)
  2705. vce_period:    DS    6    ;+12/13 (+87)
  2706. vibfraction:    DS    6    ;+18/19 (+93)
  2707. trackbuffer:    DS    6
  2708.  
  2709. ;-----------------------------------------------------------------------------
  2710. ENV_VARS:
  2711. envstage:    DS    3    ;+0    0,3,6,9,12, or 15
  2712. envframecnt:    DS    3    ;+3
  2713. envrepeats:    DS    3    ;+6
  2714. envlevel    DS    3    ;+9
  2715.  
  2716. sfx_envaddress:    DS    6    ;address of 1st byte of current envelope
  2717. vce_envaddress:    DS    6    ;address of 1st byte of current envelope
  2718.  
  2719.  
  2720. ;-----------------------------------------------------------------------------
  2721. chan_num:    DS    2    ;words
  2722. SVPTR:        DS    2    ;SVPTR = 0,SDLN,SDLN*2 (offset for SFX)
  2723. NCHAN:        DS    1    ;current noise channel 0,1,2 (FF=no noise)
  2724. randseed    DS    1    ;for random number
  2725. freqoffset    DS    1    ;random frequency offset
  2726.  
  2727. fader:        DS    1
  2728. fadecnt:    DS    1
  2729. tempbyte:    DS    1
  2730. TEMPOVAL:    DS    1
  2731. TEMPOFLAG:    DS    1
  2732. TEMPOCNTR:    DS    1
  2733. CLOCK_L        DS    1
  2734. CLOCK_H        DS    1
  2735. globoffset    DS    1
  2736.  
  2737. FXBANK:        DS    2    ;address of 1st byte of effects
  2738. FXTABLE:    DS    2
  2739. VCEBANK:    DS    2
  2740. SEQOFF:        DS    2
  2741. SEQDATA:    DS    2
  2742. TRKOFF:        DS    2
  2743. TRKDATA:    DS    2
  2744.  
  2745. VARSIZE        equ    $-RAM_VARS
  2746.  
  2747.  
  2748.  
  2749.  
  2750. ;-------------------------------------------------------------------------------
  2751. ;DEMO RAM VARIABLES
  2752. ;-------------------------------------------------------------------------------
  2753.         IF DEMO
  2754. BANKVAL:    DS    1    ;Current bank value (in ram)
  2755.         IF GAMEGEAR
  2756. PALLETTE:    DS    64    ;Temp Game Gear pallette
  2757.         ENDIF
  2758. SCRLCOUNT:    DS     1    ;Counter for scroll
  2759. editnum        DS    1
  2760. vbi_flag    DS    1
  2761. PCnewdata    ds    1
  2762. PCbuffer    ds    24    ;6 + (6 * 3)
  2763.         ENDIF
  2764.  
  2765.         END
  2766. 
  2767.