Compare commits

...

35 Commits

Author SHA1 Message Date
Wayne Warthen
d5f0699fc3 Regen Docs and Bump Version 2023-01-01 11:06:39 -08:00
Wayne Warthen
5c84fc6213 Merge pull request #313 from b1ackmai1er/dev
Change romldr to accept a baud rate
2023-01-01 11:02:10 -08:00
b1ackmai1er
d9f11b9f5e ym2612 minors 2022-12-31 21:30:01 +08:00
b1ackmai1er
bb2a68e066 Update romldr.asm 2022-12-31 11:22:34 +08:00
b1ackmai1er
cd426ba6ca Update GettingStarted.md 2022-12-31 10:43:29 +08:00
b1ackmai1er
491bbb68a6 Update romldr.asm 2022-12-31 01:00:06 +08:00
b1ackmai1er
b3bf3e27ee Update romldr.asm 2022-12-30 20:08:28 +08:00
b1ackmai1er
523ce60093 Update GettingStarted.md 2022-12-30 16:38:43 +08:00
b1ackmai1er
3f00cfbfb8 Merge pull request #31 from wwarthen/dev
Dev
2022-12-30 05:08:01 +08:00
Wayne Warthen
2dd9edd8ca Regenerate Docs and Bump Version 2022-12-29 10:14:02 -08:00
Wayne Warthen
6145383a65 Make VGM Names Lowercase (part 2) 2022-12-29 10:07:02 -08:00
Wayne Warthen
c0721a3f85 Make VGM Names Lowercase (part 1) 2022-12-29 10:05:58 -08:00
Wayne Warthen
c10497bd03 Merge pull request #312 from b1ackmai1er/dev
ym2612 driver updates
2022-12-29 09:15:09 -08:00
b1ackmai1er
5b1542e49b Update ym2612.asm 2022-12-29 18:57:50 +08:00
b1ackmai1er
96269a7f45 Update ym2612.asm 2022-12-21 22:53:47 +08:00
b1ackmai1er
bd03277bfe Update ym2612.asm 2022-12-21 05:31:38 +08:00
b1ackmai1er
c072027b87 Preserve registers 2022-12-20 17:19:12 +08:00
b1ackmai1er
e409391f14 Update Scales.asm 2022-12-19 21:54:17 +08:00
b1ackmai1er
030228e9b8 Update ym2612.asm 2022-12-18 22:44:05 +08:00
b1ackmai1er
d584d3d553 rename fm demo program 2022-12-18 21:03:10 +08:00
b1ackmai1er
2049b35ee2 Update ym2612.asm 2022-12-18 20:56:12 +08:00
b1ackmai1er
285bc6611f Update Scales.asm 2022-12-18 20:44:55 +08:00
b1ackmai1er
be8177b8a4 ym26112 driver 2022-12-18 20:41:29 +08:00
Wayne Warthen
9c80db786e Merge pull request #311 from b1ackmai1er/dev
Some vgmplayer updates
2022-12-16 19:29:43 -08:00
b1ackmai1er
d062b4345d Update YM2612.ASM
Tidy up
2022-12-16 22:31:25 +08:00
b1ackmai1er
03bf1527cc Adjust to fit on disk images 2022-12-15 22:02:58 +08:00
b1ackmai1er
38318262e9 reset defaults 2022-12-15 21:36:45 +08:00
b1ackmai1er
eefad65904 Remove tunes
They get copied over in build process. I think this is the right behaviour ?
2022-12-15 21:31:02 +08:00
b1ackmai1er
4d6a922402 Merge pull request #30 from wwarthen/dev
Dev
2022-12-15 21:26:46 +08:00
b1ackmai1er
e32d6e2d5d vgmplay updates
Still not in a terrific state but better
2022-12-15 21:25:56 +08:00
Wayne Warthen
9ea462ef7a Fix ZDE Default Config
Re-enable use of control-K to access menus.
2022-12-14 17:05:35 -08:00
b1ackmai1er
ef1989f600 vgm ym2612 updates 2022-12-12 21:41:18 +08:00
b1ackmai1er
023e54a9a8 Merge pull request #29 from wwarthen/dev
User Defined SD Interface
2022-12-12 17:13:16 +08:00
b1ackmai1er
f86019a628 Merge pull request #28 from wwarthen/dev
Dev
2022-12-09 20:19:44 +08:00
b1ackmai1er
149ffb899b Merge pull request #27 from wwarthen/dev
Dev
2022-12-07 05:30:20 +08:00
47 changed files with 2716 additions and 564 deletions

View File

@@ -7,4 +7,4 @@
***********************************************************************
This directory contains some sample ProTracker and MYM sound
files that can be played by the TUNE application.
files that can be played by the TUNE or VGMPLAY application.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -3,7 +3,7 @@
## Z80/Z180 System Software
Version 3.1 Pre-release
10 Dec 2022
01 Jan 2023
Wayne Warthen <wwarthen@gmail.com>
@@ -270,26 +270,20 @@ VDU type devices or serial devices. If you want to change which device
is the console, the ***I*** menu option can be used to choose the unit
and its speed.
The command format is `I <u> [<c>]`
The command format is `I <u> [<b>]`
where ***u*** is unit to select and ***c*** is the optional baud rate
code as listed below.
where ***u*** is unit to select and ***b*** is the optional baud rate.
Code | Rate | Code | Rate | Code | Rate | Code | Rate |
------|----------|------|----------|------|----------|------|----------|
0 | 75 | 8 | 1800 | 16 | 28880 | 24 | 460800 |
1 | 150 | 9 | 2400 | 17 | 38400 | 25 | 614400 |
2 | 225 | 10 | 3600 | 18 | 57600 | 26 | 921600 |
3 | 300 | 11 | 4800 | 19 | 76800 | 27 | 1228822 |
4 | 450 | 12 | 7200 | 20 | 115200 | 28 | 1843200 |
5 | 600 | 13 | 9600 | 21 | 153600 | 29 | 2457600 |
6 | 900 | 14 | 14400 | 22 | 230400 | 30 | 3686400 |
7 | 1200 | 15 | 19200 | 23 | 307200 | 31 | 7372800 |
------------------------------------------------------------------------
Supported baud rates are:
75 450 1800 7200 38400 115200 460800 1843200
150 600 2400 9600 28800 153600 614400 2457600
225 900 3600 14400 57600 230400 921600 3686400
300 1200 4800 19200 76800 307200 1228800 7372800
Example: To change current console to 9600 baud
I 0 13
I 0 9600
## Drive Letter Assignment

View File

@@ -1,6 +1,6 @@
RomWBW Getting Started
Wayne Warthen (mailto:wwarthen@gmail.com)
10 Dec 2022
01 Jan 2023
@@ -17,7 +17,7 @@ RomWBW
Z80/Z180 System Software
Version 3.1 Pre-release
10 Dec 2022
01 Jan 2023
Wayne Warthen wwarthen@gmail.com
@@ -307,26 +307,20 @@ VDU type devices or serial devices. If you want to change which device
is the console, the I menu option can be used to choose the unit and
its speed.
The command format is I <u> [<c>]
The command format is I <u> [<b>]
where u is unit to select and c is the optional baud rate code as listed
below.
where u is unit to select and b is the optional baud rate.
Code | Rate | Code | Rate | Code | Rate | Code | Rate |
------|----------|------|----------|------|----------|------|----------|
0 | 75 | 8 | 1800 | 16 | 28880 | 24 | 460800 |
1 | 150 | 9 | 2400 | 17 | 38400 | 25 | 614400 |
2 | 225 | 10 | 3600 | 18 | 57600 | 26 | 921600 |
3 | 300 | 11 | 4800 | 19 | 76800 | 27 | 1228822 |
4 | 450 | 12 | 7200 | 20 | 115200 | 28 | 1843200 |
5 | 600 | 13 | 9600 | 21 | 153600 | 29 | 2457600 |
6 | 900 | 14 | 14400 | 22 | 230400 | 30 | 3686400 |
7 | 1200 | 15 | 19200 | 23 | 307200 | 31 | 7372800 |
------------------------------------------------------------------------
Supported baud rates are:
75 450 1800 7200 38400 115200 460800 1843200
150 600 2400 9600 28800 153600 614400 2457600
225 900 3600 14400 57600 230400 921600 3686400
300 1200 4800 19200 76800 307200 1228800 7372800
Example: To change current console to 9600 baud
I 0 13
I 0 9600
Drive Letter Assignment

View File

@@ -0,0 +1,329 @@
;
;------------------------------------------------------------------------------
; PLAY SCALES USING HBIOS
;------------------------------------------------------------------------------
;
FCB .EQU $5C ; Location of default FCB
BDOS .EQU $0005
;
.ORG $0100
;
LD (OLDSTACK),SP ; save old stack pointer
LD SP,STACK ; set new stack pointer
;
;------------------------------------------------------------------------------
; GET DEVICE # FROM COMMAND LINE
;------------------------------------------------------------------------------
;
LD A,(FCB+1) ; GET FIRST CHAR
SUB ' '
JR Z,NO_ARG
SUB '0'-' '
JP C,EXIT
;
;------------------------------------------------------------------------------
; DISPLAY DEVICE AND NUMBER OF CHANNELS
;------------------------------------------------------------------------------
;
NO_ARG: LD (DEVICE),A ;
LD DE,TXT_DEV ; DEVICE:
CALL PRTSTR
CALL PRTDECB
LD C,A ; GET DEVICE ID
LD A,':'
CALL PRTCHR
LD B,$55
PUSH BC
LD E,4
RST 08
LD DE,TXT_NAME
LD A,B
RRCA \ RRCA \ RRCA \ RRCA
CALL PRTIDXDEA ; SHOW NAME
LD DE,TXT_CH
CALL PRTSTR
;
POP BC ; GET & DISPLAY # CHANNELS
LD E,1
RST 08
LD A,B
CALL PRTDECB
CALL CRLF ; NUMBER OF CHANNELS IS IN B
;
;------------------------------------------------------------------------------
; LOOP THROUGH EACH CHANNEL
;------------------------------------------------------------------------------
CH__TONE: LD A,(DEVICE) ; C CONTAINS DEVICE
LD C,A ; THROUGH THIS LOOP
;
PUSH BC
LD B,50H ; RESET DEVICE
RST 08
POP BC
;
PUSH BC
LD B,51H ; VOLUME FULL
LD L,0FFH
RST 08
POP BC
;
LD A,B
TST_TONE_LP: DEC A
LD (CHANNEL),A ; SAVE CURRENT CHANNEL
CALL TST_SCALES ; SCALES TEST
; CALL TST_VOLUME ; VOLUME TEST
CALL CRLF
DJNZ TST_TONE_LP
;
PUSH BC
LD B,50H ; RESET DEVICE
RST 08
POP BC
;
;------------------------------------------------------------------------------
; RESTORE STACK & EXIT
;------------------------------------------------------------------------------
;
EXIT: LD SP, (OLDSTACK) ; Exit to CP/M
RST 00H
DI
HALT
;
;------------------------------------------------------------------------------
; PLAY SCALES FROM HIGHEST HBIOS NOTE TO LOWEST
;------------------------------------------------------------------------------
;
TST_SCALES: PUSH BC
PUSH AF
;
LD HL,380 ; START NOTE
LD (NOTE),HL ; Top of Octave 7 is 343
LD B,51H ; VOLUME HIGH
LD L,0FFH
PUSH BC
RST 08
POP BC
;
NEXT0: PUSH BC
;
LD DE,TXT_TSTCH ; DISPLAY CHANNEL
CALL PRTSTR
LD A,(CHANNEL)
CALL PRTDECB
;
LD DE,TXT_NOTE ; DISPLAY NOTE
CALL PRTSTR
LD HL,(NOTE)
CALL PRTDECW
POP BC
;
LD B,53H ; SET NOTE
LD HL,(NOTE)
PUSH BC
RST 08
POP BC
OR A ; DID DRIVER FAIL
JR Z,NEXT4 ; THIS NOTE ?
LD DE,TXT_BAD_N
CALL FAILMSG
JR SKIP
;
NEXT4: LD B,57H ; DURATION
LD HL,1000
PUSH BC
RST 08
POP BC
LD B,54H ; PLAY
LD A,(CHANNEL)
LD D,A
PUSH BC
RST 08
POP BC
;
OR A ; DID DRIVER FAIL
JR Z,NEXT2 ; TO PLAY ?
LD DE,TXT_BAD_N
CALL FAILMSG
JR SKIP
;
NEXT2: CALL DELAY
CALL CRLF
;
SKIP: LD HL,(NOTE)
DEC HL
LD (NOTE),HL
INC HL
LD A,H
OR L
DEC HL
JR NZ,NEXT0
;
LD B,51H ; VOLUME
LD L,00H ; OFF
PUSH BC
RST 08
POP BC
;
LD B,54H ; PLAY
LD A,(CHANNEL)
LD D,A
PUSH BC
RST 08
POP BC
PUSH BC
LD C, 6 ; check for keypress
LD E,0FFH
CALL BDOS
POP BC
OR A
JP NZ,EXIT
POP AF
POP BC
;
RET
;
FAILMSG: PUSH AF
PUSH BC
CALL PRTSTR
CALL CRLF
POP BC
POP AF
RET
;
;------------------------------------------------------------------------------
; CONSTANT TONE ON ALL CHANNELS, SCALE VOLUME
;------------------------------------------------------------------------------
;
TST_VOLUME:
LD HL,332+48 ; TONE
LD (NOTE),HL
;
LD B,3
NEXTCH1 LD A,B
DEC A
LD (CHANNEL),A
PUSH BC ; ACROSS
CALL TONE ; ALL
LD C, 6 ; KEYPRESS
LD E, 0FFH
CALL BDOS
POP BC ; CHANNELS
OR A
JP NZ,EXIT
DJNZ NEXTCH1
RET
TONE: LD A,(DEVICE)
LD C,A
LD B,50H ; RESET
PUSH BC
RST 08
POP BC
;
NEXT1: LD B,51H ; VOLUME
LD A,(VOLUME)
LD L,A
PUSH BC
RST 08
POP BC
;
LD B,53H ; NOTE
LD HL,(NOTE)
PUSH BC
RST 08
POP BC
;
LD B,54H ; PLAY
LD A,(CHANNEL)
LD D,A
PUSH BC
RST 08
POP BC
;
CALL DELAY
;
LD A,(VOLUME)
DEC A
LD (VOLUME),A
JR NZ,NEXT1
;
LD B,51H ; VOLUME
LD L,00H
PUSH BC
RST 08
POP BC
;
LD B,54H ; PLAY
PUSH BC
LD A,(CHANNEL)
LD D,A
POP BC
RST 08
;
RET
;;
;------------------------------------------------------------------------------
; LONG DELAY
;------------------------------------------------------------------------------
;
DELAY: LD HL,-1
DELAY1: DEC HL
LD A,H
OR L
JR NZ,DELAY1
RET
;
;------------------------------------------------------------------------------
; PRINT THE nTH STRING IN A LIST OF STRINGS WHERE EACH IS TERMINATED BY 0
; A REGISTER DEFINES THE nTH STRING IN THE LIST TO PRINT AND DE POINTS
; TO THE START OF THE STRING LIST.
;------------------------------------------------------------------------------
;
PRTIDXDEA: LD C,A
OR A
PRTIDXDEA1: JR Z,PRTIDXDEA3 ; FOUND TARGET SO EXIT
PRTIDXDEA2: LD A,(DE) ; LOOP UNIT
INC DE ; WE REACH
OR A ; END OF STRING
JR NZ,PRTIDXDEA2
DEC C ; AT STRING END. SO GO
JR PRTIDXDEA1 ; CHECK FOR INDEX MATCH
PRTIDXDEA3: CALL PRTSTR ; DISPLAY THE STRING
RET
;
#INCLUDE "printing.inc"
;
TXT_CH .DB "CHANNELS: ",0
TXT_TSTCH .DB "CHANNEL: ",0
TXT_BAD_N .DB " BAD NOTE",0
TXT_BAD_P .DB " PLAY ERROR",0
TXT_NOTE .DB " NOTE: ",0
TXT_DEV .DB "DEVICE: ",0
TXT_NAME .DB "SN76489 ",0
.DB "AY-3-8910 ",0
.DB "I/O PORT ",0
.DB "YM2612 ",0
MODE .DB 0 ; scales mode or volume mode
DEVICE .DB 0
NOTE .DW 128
VOLUME .DB 0
CHANNEL .DB 0
OLDSTACK .DW 0 ; original stack pointer
.DS 40H ; space for stack
STACK ; top of stack
;
.END

View File

@@ -34,6 +34,7 @@ PRTCR:
; Print a zero terminated string at (DE) without destroying any registers
;
PRTSTR:
PUSH AF
PUSH DE
;
PRTSTR1:
@@ -46,6 +47,7 @@ PRTSTR1:
;
PRTSTR2:
POP DE ; restore registers
POP AF
RET
;
; Print the value in A in hex without destroying any registers

View File

@@ -6,6 +6,7 @@ set PATH=%TOOLS%\tasm32;%PATH%
set TASMTABS=%TOOLS%\tasm32
tasm -t180 -g3 -fFF -dWBW vgmplay.asm vgmplay.com vgmplay.lst || exit /b
tasm -t180 -g3 -fFF -dWBW ymfmdemo.asm ymfmdemo.com ymfmdemo.lst || exit /b
copy /Y vgmplay.com ..\..\..\Binary\Apps\ || exit /b
copy /Y Tunes\*.* ..\..\..\Binary\Apps\Tunes\ || exit /b
copy /Y Tunes\*.vgm ..\..\..\Binary\Apps\Tunes\ || exit /b

View File

@@ -10,6 +10,9 @@ DEPS := vgmplay.asm $(shell find . -name '*.inc')
vgmplay.com: $(DEPS)
$(TASM) -dWBW vgmplay.asm vgmplay.com vgmplay.lst
ym2612.com:
$(TASM) -dWBW ymfmdemo.asm ymfmdemo.com ymfmdemo.lst
all::
mkdir -p $(DEST)/Tunes
cp Tunes/* $(DEST)/Tunes
cp Tunes/*.vgm $(DEST)/Tunes

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -34,6 +34,7 @@ PRTCR:
; Print a zero terminated string at (DE) without destroying any registers
;
PRTSTR:
PUSH AF
PUSH DE
;
PRTSTR1:
@@ -46,6 +47,7 @@ PRTSTR1:
;
PRTSTR2:
POP DE ; restore registers
POP AF
RET
;
; Print the value in A in hex without destroying any registers

View File

@@ -9,122 +9,173 @@
; YM2151 support from Ed Brindley
;
; YM2162/YM3484, GD3 support, VGM Chip identification,
; default file type, basic file size checking added by Phil Summers
; default file type, basic file size checking, polled CTC mode
; added by Phil Summers
;
; Bugs: YM2151 playback untested & no mute.
; CTC polled timing - predicted 44100 divider is too slow
;
; Assemble with:
;
; TASM -80 -b VGMPLAY.ASM VGMPLAY.COM
;
;
; A VGM file can play 44100 samples a second. This may be sound chip
; register commands or PCM data. This player does not support PCM playback
; due to the high processor speed and file size required. Typical VGM files
; available use a much lower sample rate and are playable. Where the processor
; speed is low and the sample rate is high, the playback overhead will cause
; playback speed to be inaccurate.
;------------------------------------------------------------------------------
; Device and system specific definitions
;------------------------------------------------------------------------------
;
P8X180 .EQU 0 ; System configuration
RC2014 .EQU 0
SBCECB .EQU 1
MBC .EQU 0
custom .equ 0 ; System configurations
P8X180 .equ 1
RC2014 .equ 2
sbcecb .equ 3
MBC .equ 4
;
.IF P8X180
RSEL .EQU 82H ; Primary AY-3-8910 Register selection
RDAT .EQU 83H ; Primary AY-3-8910 Register data
RSEL2 .EQU 88H ; Secondary AY-3-8910 Register selection
RDAT2 .EQU 89H ; Secondary AY-3-8910 Register data
PSG1REG .EQU 84H ; Primary SN76489
PSG2REG .EQU 8AH ; Secondary SN76489
YM2151_SEL1 .EQU 0B0H ; Primary YM2151 register selection
YM2151_DAT1 .EQU 0B1H ; Primary YM2151 register data
YM2151_SEL2 .EQU 0B2H ; Secondary YM2151 register selection
YM2151_DAT2 .EQU 0B3H ; Secondary YM2151 register data
FRAME_DLY .EQU 48 ; Frame delay (~ 1/44100)
.ENDIF
plt_romwbw .equ 1 ; Build for ROMWBW?
plt_type .equ sbcecb ; Select build configuration
debug .equ 0 ; Display port, register, config info
;
.IF RC2014
RSEL .EQU 0D8H ; Primary AY-3-8910 Register selection
RDAT .EQU 0D0H ; Primary AY-3-8910 Register data
RSEL2 .EQU 0A0H ; Secondary AY-3-8910 Register selection
RDAT2 .EQU 0A1H ; Secondary AY-3-8910 Register data
PSG1REG .EQU 0FFH ; Primary SN76489
PSG2REG .EQU 0FBH ; Secondary SN76489
YM2151_SEL1 .EQU 0FEH ; Primary YM2151 register selection
YM2151_DAT1 .EQU 0FFH ; Primary YM2151 register data
YM2151_SEL2 .EQU 0D0H ; Secondary YM2151 register selection
YM2151_DAT2 .EQU 0D1H ; Secondary YM2151 register data
FRAME_DLY .EQU 15 ; Frame delay (~ 1/44100)
.ENDIF
#IF (plt_type=custom)
RSEL .equ 09AH ; Primary AY-3-8910 Register selection
RDAT .equ 09BH ; Primary AY-3-8910 Register data
RSEL2 .equ 88H ; Secondary AY-3-8910 Register selection
RDAT2 .equ 89H ; Secondary AY-3-8910 Register data
VGMBASE .equ $C0
YMSEL .equ VGMBASE+00H ; Primary YM2162 11000000 a1=0 a0=0
YMDAT .equ VGMBASE+01H ; Primary YM2162 11000001 a1=0 a0=1
YM2SEL .equ VGMBASE+02H ; Secondary YM2162 11000010 a1=1 a0=0
YM2DAT .equ VGMBASE+03H ; Secondary YM2162 11000011 a1=1 a0=1
PSG1REG .equ VGMBASE+08H ; Primary SN76489
PSG2REG .equ VGMBASE+09H ; Secondary SN76489
ctcbase .equ VGMBASE+0CH ; CTC base address
YM2151_SEL1 .equ 0FEH ; Primary YM2151 register selection
YM2151_DAT1 .equ 0FFH ; Primary YM2151 register data
YM2151_SEL2 .equ 0FEH ; Secondary YM2151 register selection
YM2151_DAT2 .equ 0FFH ; Secondary YM2151 register data
FRAME_DLY .equ 10 ; Frame delay (~ 1/44100)
plt_cpuspd .equ 6 ; Non ROMWBW cpu speed default
#ENDIF
;
.IF SBCECB
RSEL .EQU 0D8H ; Primary AY-3-8910 Register selection
RDAT .EQU 0D0H ; Primary AY-3-8910 Register data
RSEL2 .EQU 0A0H ; Secondary AY-3-8910 Register selection
RDAT2 .EQU 0A1H ; Secondary AY-3-8910 Register data
YMSEL .EQU 0C0H ; Primary YM2162 11000000 a1=0 a0=0
YMDAT .EQU 0C1H ; Primary YM2162 11000001 a1=0 a0=1
YM2SEL .EQU 0C2H ; Secondary YM2162 11000010 a1=1 a0=0
YM2DAT .EQU 0C3H ; Secondary YM2162 11000011 a1=1 a0=1
PSG1REG .EQU 0C6H ; Primary SN76489
PSG2REG .EQU 0C7H ; Secondary SN76489
YM2151_SEL1 .EQU 0FEH ; Primary YM2151 register selection
YM2151_DAT1 .EQU 0FFH ; Primary YM2151 register data
YM2151_SEL2 .EQU 0FEH ; Secondary YM2151 register selection
YM2151_DAT2 .EQU 0FFH ; Secondary YM2151 register data
FRAME_DLY .EQU 8 ; Frame delay (~ 1/44100)
.ENDIF
#IF (plt_type=P8X180)
RSEL .equ 82H ; Primary AY-3-8910 Register selection
RDAT .equ 83H ; Primary AY-3-8910 Register data
RSEL2 .equ 88H ; Secondary AY-3-8910 Register selection
RDAT2 .equ 89H ; Secondary AY-3-8910 Register data
PSG1REG .equ 84H ; Primary SN76489
PSG2REG .equ 8AH ; Secondary SN76489
YM2151_SEL1 .equ 0B0H ; Primary YM2151 register selection
YM2151_DAT1 .equ 0B1H ; Primary YM2151 register data
YM2151_SEL2 .equ 0B2H ; Secondary YM2151 register selection
YM2151_DAT2 .equ 0B3H ; Secondary YM2151 register data
ctcbase .equ 000H ; CTC base address
YMSEL .equ 000H ; Primary YM2162 11000000 a1=0 a0=0
YMDAT .equ 000H ; Primary YM2162 11000001 a1=0 a0=1
YM2SEL .equ 000H ; Secondary YM2162 11000010 a1=1 a0=0
YM2DAT .equ 000H ; Secondary YM2162 11000011 a1=1 a0=1
FRAME_DLY .equ 48 ; Frame delay (~ 1/44100)
plt_cpuspd .equ 20 ; Non ROMWBW cpu speed default
#ENDIF
;
.IF MBC
RSEL .EQU 0A0H ; Primary AY-3-8910 Register selection
RDAT .EQU 0A1H ; Primary AY-3-8910 Register data
RSEL .EQU 0D8H ; Secondary AY-3-8910 Register selection
RDAT .EQU 0D0H ; Secondary AY-3-8910 Register data
YMSEL .EQU 0C0H ; 11000000 a1=0 a0=0
YMDAT .EQU 0C1H ; 11000001 a1=0 a0=1
YM2SEL .EQU 0C2H ; 11000010 a1=1 a0=0
YM2DAT .EQU 0C3H ; 11000011 a1=1 a0=1
PSGREG .EQU 0C6H ; Primary SN76489
PSG2REG .EQU 0C7H ; Secondary SN76489
YM2151_SEL1 .EQU 0FEH ; Primary YM2151 register selection
YM2151_DAT1 .EQU 0FFH ; Primary YM2151 register data
YM2151_SEL2 .EQU 0FEH ; Secondary YM2151 register selection
YM2151_DAT2 .EQU 0FFH ; Secondary YM2151 register data
FRAME_DLY .EQU 10 ; Frame delay (~ 1/44100)
.ENDIF
#IF (plt_type=RC2014)
RSEL .equ 0D8H ; Primary AY-3-8910 Register selection
RDAT .equ 0D0H ; Primary AY-3-8910 Register data
RSEL2 .equ 0A0H ; Secondary AY-3-8910 Register selection
RDAT2 .equ 0A1H ; Secondary AY-3-8910 Register data
PSG1REG .equ 0FFH ; Primary SN76489
PSG2REG .equ 0FBH ; Secondary SN76489
YM2151_SEL1 .equ 0FEH ; Primary YM2151 register selection
YM2151_DAT1 .equ 0FFH ; Primary YM2151 register data
YM2151_SEL2 .equ 0D0H ; Secondary YM2151 register selection
YM2151_DAT2 .equ 0D1H ; Secondary YM2151 register data
ctcbase .equ 000H ; CTC base address
YMSEL .equ 000H ; Primary YM2162 11000000 a1=0 a0=0
YMDAT .equ 000H ; Primary YM2162 11000001 a1=0 a0=1
YM2SEL .equ 000H ; Secondary YM2162 11000010 a1=1 a0=0
YM2DAT .equ 000H ; Secondary YM2162 11000011 a1=1 a0=1
FRAME_DLY .equ 12 ; Frame delay (~ 1/44100)
plt_cpuspd .equ 7 ; Non ROMWBW cpu speed default
#ENDIF
;
#IF (plt_type=sbcecb)
RSEL .equ 09AH ; Primary AY-3-8910 Register selection
RDAT .equ 09BH ; Primary AY-3-8910 Register data
RSEL2 .equ 0A0H ; Secondary AY-3-8910 Register selection
RDAT2 .equ 0A1H ; Secondary AY-3-8910 Register data
VGMBASE .equ $C0
YMSEL .equ VGMBASE+00H ; Primary YM2162 11000000 a1=0 a0=0
YMDAT .equ VGMBASE+01H ; Primary YM2162 11000001 a1=0 a0=1
YM2SEL .equ VGMBASE+02H ; Secondary YM2162 11000010 a1=1 a0=0
YM2DAT .equ VGMBASE+03H ; Secondary YM2162 11000011 a1=1 a0=1
PSG1REG .equ VGMBASE+06H ; Primary SN76489
PSG2REG .equ VGMBASE+07H ; Secondary SN76489
ctcbase .equ VGMBASE+0CH ; CTC base address
YM2151_SEL1 .equ 0FEH ; Primary YM2151 register selection
YM2151_DAT1 .equ 0FFH ; Primary YM2151 register data
YM2151_SEL2 .equ 0FEH ; Secondary YM2151 register selection
YM2151_DAT2 .equ 0FFH ; Secondary YM2151 register data
FRAME_DLY .equ 13 ; Frame delay (~ 1/44100)
plt_cpuspd .equ 8 ; Non ROMWBW cpu speed default
#ENDIF
;
#IF (plt_type=MBC)
RSEL .equ 0A0H ; Primary AY-3-8910 Register selection
RDAT .equ 0A1H ; Primary AY-3-8910 Register data
RSEL2 .equ 0D8H ; Secondary AY-3-8910 Register selection
RDAT2 .equ 0D0H ; Secondary AY-3-8910 Register data
YMSEL .equ 0C0H ; 11000000 a1=0 a0=0
YMDAT .equ 0C1H ; 11000001 a1=0 a0=1
YM2SEL .equ 0C2H ; 11000010 a1=1 a0=0
YM2DAT .equ 0C3H ; 11000011 a1=1 a0=1
PSG1REG .equ 0C6H ; Primary SN76489
PSG2REG .equ 0C7H ; Secondary SN76489
ctcbase .equ 000H ; CTC base address
YM2151_SEL1 .equ 0FEH ; Primary YM2151 register selection
YM2151_DAT1 .equ 0FFH ; Primary YM2151 register data
YM2151_SEL2 .equ 0FEH ; Secondary YM2151 register selection
YM2151_DAT2 .equ 0FFH ; Secondary YM2151 register data
FRAME_DLY .equ 13 ; Frame delay (~ 1/44100)
plt_cpuspd .equ 8 ; Non ROMWBW cpu speed default
#ENDIF
;
;------------------------------------------------------------------------------
; Your customer overrides can go in here i.e. ports
; Configure timing loop
;------------------------------------------------------------------------------
;
;RSEL .SET 09AH ; Primary AY-3-8910 Register selection
;RDAT .SET 09BH ; Primary AY-3-8910 Register data
cpu_loop: .equ 0
ctc_poll: .equ 1
ctc_int: .equ 2 ; not implemented
;
delay_type: .equ cpu_loop ; cpu timed loop or utilize ctc
delay_wait .equ 0 ; funny wait mode for ctc
;
D60 .equ 735 ; 735x60=44100 Frame delay values for ntsc
D50 .equ 882 ; 882x50=44100 Frame delay values for pal
;
;------------------------------------------------------------------------------
; Frame delay overide values for different processor speeds.
; CTC Defaults
;------------------------------------------------------------------------------
;
;FRAME_DLY .SET 10 ; 1Mhz ; not
;FRAME_DLY .SET 10 ; 2Mhz ; implemented
;FRAME_DLY .SET 10 ; 4Mhz ; yet
;FRAME_DLY .SET 15 ; 8Mhz
;FRAME_DLY .SET 10 ; 10Mhz
;FRAME_DLY .SET 20 ; 12Mhz
;
;------------------------------------------------------------------------------
; Frame delay values for pal/ntsc
;------------------------------------------------------------------------------
;
D60 .EQU 735
D50 .EQU 882
ctcdiv0 .equ 1 ; Divider chain for 3.579545MHz input
ctcdiv1 .equ 1 ; Ctc with 3 step divider base address
ctcdiv2 .equ 16
ctcdiv3 .equ 3 ; 3579545 / 1 / 2 / 41 = 43653 = 1% error
;
;------------------------------------------------------------------------------
; Processor speed control for SBCV2004+
;------------------------------------------------------------------------------
;
;#DEFINE SBCV2004 ; My SBC board at 12Mhz needs this to switch to
HB_RTCVAL .EQU 0FFEEH ; 6MHz for it to work with the ECB-VGM reliably.
RTCIO .EQU 070H
HB_RTCVAL .equ 0FFEEH ; 6MHz for it to work with the ECB-VGM reliably.
RTCIO .equ 070H
;
;------------------------------------------------------------------------------
; YM2162 Register write macros
; YM2162 Register write macros - with wait and timeout
;------------------------------------------------------------------------------
;
#DEFINE setreg(reg,val) \
@@ -132,53 +183,57 @@ RTCIO .EQU 070H
#DEFCONT \ out (YMSEL),a
#DEFCONT \ ld a,val
#DEFCONT \ out (YMDAT),a
#DEFCONT \ ld b,0
#DEFCONT \ in a,(YMSEL)
#DEFCONT \ rlca
#DEFCONT \ jp c,$-3
#DEFCONT \ jp nc,$+5
#DEFCONT \ djnz $-6
;
#DEFINE setreg2(reg,val) \
#DEFCONT \ ld a,reg
#DEFCONT \ out (YM2SEL),a
#DEFCONT \ ld a,val
#DEFCONT \ out (YM2DAT),a
#DEFCONT \ ld b,0
#DEFCONT \ in a,(YMSEL)
#DEFCONT \ rlca
#DEFCONT \ jp c,$-3
#DEFCONT \ jp nc,$+5
#DEFCONT \ djnz $-6
;------------------------------------------------------------------------------
; VGM Codes
; VGM Codes - see vgmrips.net/wiki/VGM_specification
;------------------------------------------------------------------------------
VGM_GG_W .EQU 04FH ; GAME GEAR PSG STEREO. WRITE DD TO PORT 0X06
VGM_PSG1_W .EQU 050H ; PSG (SN76489/SN76496) #1 WRITE VALUE DD
VGM_PSG2_W .EQU 030H ; PSG (SN76489/SN76496) #2 WRITE VALUE DD
VGM_YM26121_W .EQU 052H ; YM2612 #1 WRITE VALUE DD
VGM_YM26122_W .EQU 053H ; YM2612 #2 WRITE VALUE DD
VGM_WNS .EQU 061H ; WAIT N SAMPLES
VGM_W735 .EQU 062H ; WAIT 735 SAMPLES (1/60TH SECOND)
VGM_W882 .EQU 063H ; WAIT 882 SAMPLES (1/50TH SECOND)
VGM_ESD .EQU 066H ; END OF SOUND DATA
VGM_YM21511_W .EQU 054H ; YM2612 #1 WRITE VALUE DD
VGM_YM21512_W .EQU 0A4H ; YM2612 #2WRITE VALUE DD
VGM_GG_W .equ 04FH ; GAME GEAR PSG STEREO. WRITE DD TO PORT 0X06
VGM_PSG1_W .equ 050H ; PSG (SN76489/SN76496) #1 WRITE VALUE DD
VGM_PSG2_W .equ 030H ; PSG (SN76489/SN76496) #2 WRITE VALUE DD
VGM_YM26121_W .equ 052H ; YM2612 #1 WRITE VALUE DD
VGM_YM26122_W .equ 053H ; YM2612 #2 WRITE VALUE DD
VGM_WNS .equ 061H ; WAIT N SAMPLES
VGM_W735 .equ 062H ; WAIT 735 SAMPLES (1/60TH SECOND)
VGM_W882 .equ 063H ; WAIT 882 SAMPLES (1/50TH SECOND)
VGM_ESD .equ 066H ; END OF SOUND DATA
VGM_YM21511_W .equ 054H ; YM2612 #1 WRITE VALUE DD
VGM_YM21512_W .equ 0A4H ; YM2612 #2 WRITE VALUE DD
;------------------------------------------------------------------------------
; Generic CP/M definitions
;------------------------------------------------------------------------------
BOOT .EQU 0000H ; boot location
BDOS .EQU 0005H ; bdos entry point
FCB .EQU 005CH ; file control block
FCBCR .EQU FCB + 20H ; fcb current record
BUFF .EQU 0080H ; DMA buffer
TOPM .EQU 0002H ; Top of memory
BOOT .equ 0000H ; boot location
BDOS .equ 0005H ; bdos entry point
FCB .equ 005CH ; file control block
FCBCR .equ FCB + 20H ; fcb current record
BUFF .equ 0080H ; DMA buffer
TOPM .equ 0002H ; Top of memory
PRINTF .EQU 9 ; BDOS print string function
OPENF .EQU 15 ; BDOS open file function
CLOSEF .EQU 16 ; BDOS close file function
READF .EQU 20 ; BDOS sequential read function
PRINTF .equ 9 ; BDOS print string function
OPENF .equ 15 ; BDOS open file function
CLOSEF .equ 16 ; BDOS close file function
READF .equ 20 ; BDOS sequential read function
CR .EQU 0DH ; carriage return
LF .EQU 0AH ; line feed
CR .equ 0DH ; carriage return
LF .equ 0AH ; line feed
;------------------------------------------------------------------------------
; Program Start
@@ -188,12 +243,29 @@ LF .EQU 0AH ; line feed
LD (OLDSTACK),SP ; save old stack pointer
LD SP,STACK ; set new stack pointer
LD DE,MSG_WELC ; Welcome Message
CALL PRTSTR
;
#IF (delay_type==cpu_loop)
call setfdelay ; Setup the frame delay based on cpu speed
#ENDIF
;
#IF (delay_type==ctc_poll)
call cfgctc_poll ; If building for polled ctc, initialize it
#ENDIF
;
#IF (delay_type==ctc_int) ; If building for interrupt driven ctc, initialize it
call cfgctc_int
#ENDIF
;
#IF (debug)
; LD A,0 ; tone to validate presence
;TST: LD C,PSG1REG
; OUT (C),A
; LD C,PSG2REG
; OUT (C),A
; JR TST
#ENDIF
call welcome ; Welcome message and build debug info
CALL READVGM ; Read in the VGM file
CALL VGMINFO ; Check and display VGM Information
LD HL, (VGMDATA + 34H) ; Determine start of VGM
@@ -206,25 +278,63 @@ _S1 LD DE, VGMDATA + 34H
LD (VGMPOS), HL
LD HL,D60 ; VGM delay (60hz)
LD (VGMDLY), HL
LD (vdelay), HL
;
LD IX,VGM_DEV ; IX points to device mask
;
;------------------------------------------------------------------------------
; Play loop
;------------------------------------------------------------------------------
;
MAINLOOP CALL PLAY ; Play one frame
LD C,6 ; Check for keypress
LD E,0FFH
CALL BDOS
;
LD HL,KEYCHK ; Check for keypress
DEC (HL)
JR NZ,NO_CHK
;
LD C,6 ; Every 256 commands
LD E,0FFH ; because HBIOS calls
CALL BDOS ; take a long time
OR A
JR NZ,EXIT
NO_CHK:
#IF (delay_type==cpu_loop)
vdelay: .equ $+1
ld hl,vdelay
fdelay: .equ $+1
lp1: LD B,FRAME_DLY ; 44100 one frame = 0.0000226757 seconds
DJNZ $
DEC HL
LD A,H
OR L
JP NZ,lp1 ; Normally NZ so jp is faster
#ENDIF
;
#IF (delay_type==ctc_poll)
vdelay: .equ $+1
ld hl,vdelay ; Frame delay
lp1: in a,(ctcch3) ; wait for counter to reach zero
dec a
jr nz,lp1
#IF (delay_wait)
lp2: in a,(ctcch3) ; wait for counter to pass zero
dec a
jr z,lp2
LD HL,(VGMDLY) ; Frame delay
L1 LD B,FRAME_DLY
DJNZ $
DEC HL
LD A,H
OR L
JR NZ,L1
JR MAINLOOP
lp3: in a,(ctcch3) ; wait for counter to reach zero
dec a
jr nz,lp3
#ENDIF
DEC HL
LD A,H
OR L
JP NZ,lp1 ; Normally NZ so jp is faster
#ENDIF
;
#IF (delay_type==ctc_int)
#ENDIF
;
JP MAINLOOP
;
;------------------------------------------------------------------------------
; Program Exit
@@ -240,6 +350,194 @@ EXIT: CALL VGMDEVICES ; Display devices used
EXIT_ERR: CALL PRTSTR ; Generic message or error
LD SP, (OLDSTACK) ; Exit to CP/M
RST 00H
DI
HALT
;
;------------------------------------------------------------------------------
; Welcome
;------------------------------------------------------------------------------
;
welcome: LD DE,MSG_WELC ; Welcome Message
CALL PRTSTR
;
#IF (plt_romwbw)
LD DE,MSG_ROMWBW ; display system type
CALL PRTSTR
#ENDIF
;
LD A,delay_type ; display build type
LD DE,MSG_CPU
CALL PRTIDXDEA
;
LD A,plt_type ; display system type
LD DE,MSG_CUSTOM
CALL PRTIDXDEA
call CRLF
;
#IF (debug)
#IF (delay_type==cpu_loop)
ld a,'f' ; Display frame rate delay
call PRTCHR
call PRTDOT
ld a,(fdelay)
call PRTDECB
LD A,' '
#ENDIF
CALL PRTCHR
ld a,'c'
call PRTCHR
call PRTDOT
ld a,ctcdiv0 ; Display ctc divider values
call PRTDECB
CALL PRTDOT
ld a,ctcdiv1
call PRTDECB
CALL PRTDOT
ld a,ctcdiv2
call PRTDECB
CALL PRTDOT
ld a,ctcdiv3
call PRTDECB
;
#IF (delay_wait)
ld a,' '
CALL PRTCHR
LD A,'w' ; Display if using double wait
CALL PRTCHR
#ENDIF
#ENDIF
CALL CRLF
ret
;
;------------------------------------------------------------------------------
; Setup frame delay value - Loop count for DJNZ $ loop
;------------------------------------------------------------------------------
;
setfdelay:
#IF (delay_type==cpu_loop)
#IF (plt_romwbw)
LD BC,$F8F0 ; GET CPU SPEED
RST 08 ; FROM HBIOS
LD A,L ;
#ELSE
ld a,plt_cpuspd ; USE STANDALONE CPU SPEED
#ENDIF
LD HL,CLKTBL-1 ; CPU SPEED
ADD A,L ; INDEXES
LD L,A ; INTO
ADC A,H ; TABLE
SUB L
LD H,A ; LOOK IT UP IN THE
LD A,(HL) ; CLOCK TABLE
LD (fdelay),A ; SAVE LOOP COUNTER FOR CPU SPEED
RET
;------------------------------------------------------------------------------
; Frame delay values for different processor speeds.
;------------------------------------------------------------------------------
;
; 1/44100hz = 22676ns
; 16Mhz = 62.5ns : DJNZ $ = 1 frame delay= 22676ns/13*62.5ns = 27.91
; 12Mhz = 83.3ns : DJNZ $ = 1 frame delay= 22676ns/13*83.3ns = 20.94
; 10Mhz = 100ns : DJNZ $ = 1 frame delay= 22676ns/13*100ns = 17.44
; 8Mhz = 125ns : DJNZ $ = 1 frame delay= 22676ns/13*125ns = 13.95
; 7.3728Mhz = 135.6ns : DJNZ $ = 1 frame delay= 22676ns/13*135.6ns = 12.86
; 6Mhz = 166.6s : DJNZ $ = 1 frame delay= 22676ns/13*166.6ns = 10.47
; 4Mhz = 250ns : DJNZ $ = 1 frame delay= 22676ns/13*250ns = 6.98
; 2Mhz = 500ns : DJNZ $ = 1 frame delay= 22676ns/13*500ns = 3.49
; 1Mhz = 1000ns : DJNZ $ = 1 frame delay= 22676ns/13*1000ns = 1.74
;
CLKTBL: .DB 1 ; 1Mhz ; none of these
.DB 3 ; 2Mhz ; have been
.DB 0 ; 3Mhz ; validated
.DB 6 ; 4Mhz
.DB 0 ; 5Mhz
.DB 10 ; 6Mhz
.DB 12 ; 7Mhz 7.3728Mhz
.DB 13 ; 8Mhz
.DB 0 ; 9Mhz
.DB 17 ; 10Mhz
.DB 0 ; 11Mhz
.DB 20 ; 12Mhz
.DB 0 ; 13Mhz
.DB 0 ; 14Mhz
.DB 0 ; 15Mhz
.DB 27 ; 16Mhz
.DB 0 ; 17Mhz
.DB 0 ; 18Mhz
.DB 0 ; 19Mhz
.DB 0 ; 20Mhz
#ENDIF
;
;------------------------------------------------------------------------------
; Initialize CTC
;------------------------------------------------------------------------------
;
; %01010011 ; CTC DEFAULT CONFIG
; %01010111 ; CTC COUNTER MODE CONFIG
; %11010111 ; CTC COUNTER INTERRUPT MODE CONFIG
; |||||||+-- CONTROL WORD FLAG
; ||||||+--- SOFTWARE RESET
; |||||+---- TIME CONSTANT FOLLOWS
; ||||+----- AUTO TRIGGER WHEN TIME CONST LOADED
; |||+------ RISING EDGE TRIGGER
; ||+------- TIMER MODE PRESCALER (0=16, 1=256)
; |+-------- COUNTER MODE
; +--------- INTERRUPT ENABLE
;
cfgctc_poll:
;
ctcch0 .equ ctcbase
ctcch1 .equ ctcbase+1
ctcch2 .equ ctcbase+2
ctcch3 .equ ctcbase+3
;
ctccfg0 .equ %01010011
ctccfg1 .equ %01010111
ctccfg2 .equ %01010111
ctccfg3 .equ %01010111
;
ld a,ctccfg0 & $7f ; ; Channel 0
out (ctcch0),a
;
ld a,ctccfg1 & $7f ; Channel 1
out (ctcch1),a ;
ld a,ctcdiv1 & $ff ;
out (ctcch1),a ;
;
ld a,ctccfg2 & $7f ; Channel 2
out (ctcch2),a ;
ld a,ctcdiv2 & $ff ;
out (ctcch2),a ;
;
ld a,ctccfg3 & $7f ; Channel 3
out (ctcch3),a ;
ld a,ctcdiv3 & $ff ;
out (ctcch3),a ;
;
ret
;
#IF (debug)
ctctest:
ld b,0
ctclp1: in a,(ctcch3) ; wait for counter to reach zero
dec a
jr nz,ctclp1
ctclp2: in a,(ctcch3) ; wait for counter to pass zero
dec a
jr z,ctclp2
call PRTDOT
;
djnz ctclp1
#ENDIF
ret
;
cfgctc_int:
ret
;
;------------------------------------------------------------------------------
; Read VGM file into memory
@@ -396,7 +694,6 @@ PLAY
#IFDEF SBCV2004
CALL SLOWIO
#ENDIF
LD IX,VGM_DEV
LD HL, (VGMPOS) ; Start processing VGM commands
NEXT LD A, (HL)
INC HL
@@ -406,19 +703,14 @@ NEXT LD A, (HL)
LD HL, (VGMDATA + 1CH) ; Loop offset
LD A, H
OR L
JP Z, EXIT
JP Z, EXIT
LD DE, VGMDATA + 1CH
ADD HL, DE
LD (VGMPOS), HL
JR NEXT
NEXT1 CP VGM_GG_W ; Game Gear SN76489 stereo. Ignored
JR NZ, PSG
LD IX,VGM_DEV
SET 0,(IX+1)
INC HL
JR NEXT
NEXT1:
;
; SN76489 SECTION
PSG CP VGM_PSG1_W ; Write byte to SN76489.
@@ -426,7 +718,6 @@ PSG CP VGM_PSG1_W ; Write byte to SN76489.
LD A, (HL)
INC HL
OUT (PSG1REG), A
LD IX,VGM_DEV
SET 0,(IX+0)
JR NEXT
@@ -435,7 +726,6 @@ PSG2 CP VGM_PSG2_W ; Write byte to second SN76489.
LD A, (HL)
INC HL
OUT (PSG2REG), A
LD IX,VGM_DEV
SET 1,(IX+0)
JR NEXT
@@ -452,19 +742,17 @@ AY CP 0A0H
LD A, (HL)
INC HL
OUT (RDAT2), A
LD IX,VGM_DEV
SET 2,(IX+0)
JR NEXT
AY1 OUT (RSEL), A
LD A, (HL)
INC HL
OUT (RDAT), A
LD IX,VGM_DEV
SET 3,(IX+0)
JR NEXT
;
; YM2612 SECTION
;
YM2162_1 CP VGM_YM26121_W
JR NZ, YM2162_2
LD A,(HL)
@@ -473,7 +761,6 @@ YM2162_1 CP VGM_YM26121_W
LD A,(HL)
OUT (YMDAT),A
INC HL
LD IX,VGM_DEV
SET 4,(IX+0)
JP NEXT
;
@@ -485,12 +772,11 @@ YM2162_2 CP VGM_YM26122_W
LD A,(HL)
OUT (YM2DAT),A
INC HL
LD IX,VGM_DEV
SET 4,(IX+0) ; 2nd channel
JP NEXT
;
; YM2151 SECTION
;
YM2151_1 CP VGM_YM21511_W
JR NZ,YM2151_2
LD A,(HL)
@@ -499,21 +785,27 @@ YM2151_1 CP VGM_YM21511_W
LD A,(HL)
OUT (YM2151_DAT1),A
INC HL
LD IX,VGM_DEV
SET 6,(IX+0)
JP NEXT
;
YM2151_2 CP VGM_YM21512_W
JR NZ,WAITNN
JR NZ,GG
LD A,(HL)
OUT (YM2151_SEL2),A
INC HL
LD A,(HL)
OUT (YM2151_DAT2),A
INC HL
LD IX,VGM_DEV
SET 7,(IX+0)
JP NEXT
;
; GAME GEAR SN76489 STEREO SECTION
;
GG: CP VGM_GG_W ; Stereo steering port value
JR NZ, WAITNN
; SET 0,(IX+1)
INC HL
JP NEXT
;
WAITNN CP VGM_WNS ; Wait nn samples
JR NZ, WAIT60
@@ -524,36 +816,43 @@ WAITNN CP VGM_WNS ; Wait nn samples
LD (VGMPOS), HL
LD L, A
LD H, D
LD (VGMDLY), HL
LD (vdelay), HL
RET
;
WAIT60 CP VGM_W735 ; Wait 735 samples (60Hz)
JR NZ, WAIT50
LD (VGMPOS), HL
LD HL, D60
LD (VGMDLY), HL
LD (vdelay), HL
RET
;
WAIT50 CP VGM_W882 ; Wait 882 samples (50Hz)
JR NZ, WAIT1
LD (VGMPOS), HL
LD HL, D50
LD (VGMDLY), HL
WAIT50: CP VGM_W882 ; Wait 882 samples (50Hz)
JR NZ, WAIT1
LD (VGMPOS), HL
LD HL, D50
LD (vdelay), HL
RET
;
WAIT1 CP 70H ; WAIT 0-15 SAMPLES
WAIT1: CP 70H ; WAIT 0-15 SAMPLES
JR C, UNK ; CODES 70-7FH
CP 80H
JP NC, UNK
SUB 6FH
LD L, A
LD H, 0
LD (VGMDLY), HL
LD (vdelay), HL
RET
;
UNK LD IX,VGM_DEV ; Set flag for
SET 0,(IX+1) ; unknown device
UNK: SET 0,(IX+1) ; unknown device
INC HL ; Try and skip
#IF (debug)
ld a,'u' ; Display unknow command
call PRTCHR
call PRTDOT
call PRTHEX
ld a,' '
call PRTCHR
#ENDIF
JP NEXT
;
;------------------------------------------------------------------------------
@@ -609,12 +908,6 @@ CHKDEV: AND %00000011 ; Display
CALL PRTCHR ; Skip if not
CALL PRTSTR ; used.
RET
DEBUG: PUSH AF
LD A,'*'
CALL PRTCHR
POP AF
RET
;
;------------------------------------------------------------------------------
; Mute Devices.
@@ -939,6 +1232,28 @@ FASTIO:
RET
;
;------------------------------------------------------------------------------
; PRINT THE nTH STRING IN A LIST OF STRINGS WHERE EACH IS TERMINATED BY 0
; A REGISTER DEFINES THE nTH STRING IN THE LIST TO PRINT AND DE POINTS
; TO THE START OF THE STRING LIST.
;------------------------------------------------------------------------------
;
PRTIDXDEA:
LD C,A
OR A
PRTIDXDEA1:
JR Z,PRTIDXDEA3 ; FOUND TARGET SO EXIT
PRTIDXDEA2:
LD A,(DE) ; LOOP UNIT
INC DE ; WE REACH
OR A ; END OF STRING
JR NZ,PRTIDXDEA2
DEC C ; AT STRING END. SO GO
JR PRTIDXDEA1 ; CHECK FOR INDEX MATCH
PRTIDXDEA3:
CALL PRTSTR ; DISPLAY THE STRING
RET
;
;------------------------------------------------------------------------------
; External routines.
;------------------------------------------------------------------------------
;
@@ -948,8 +1263,8 @@ FASTIO:
; Strings and constants.
;------------------------------------------------------------------------------
;
MSG_WELC: .DB "VGM Player for RomWBW v0.3, 2-Jul-2022",CR,LF
; .DB "J.B. Langston/Marco Maccaferri/Phil Summers",CR,LF
MSG_WELC: .DB "VGM Player v0.4, 11-Dec-2022"
; .DB CR,LF, "J.B. Langston/Marco Maccaferri/Ed Brindley/Phil Summers",CR,LF
.DB 0
MSG_BADF: .DB "Not a VGM file",CR,LF,0
MSG_PO .DB "Played on : ",0
@@ -963,17 +1278,33 @@ MSG_NOFILE: .DB "File not found", CR, LF, 0
MSG_MEM: .DB "File to big", CR, LF, 0
MSG_TITLE: .DB " from: ",0
MSG_TRACK .DB "Playing: ",0
MSG_CPU .DB "[cpu]",0
MSG_CTCPOLL .DB "[ctc polled]",0
MSG_CTCINT .DB "[ctc interrupts]",0
MSG_ROMWBW .DB " [romwbw] ",0
MSG_CUSTOM .DB " [custom] ",0
MSG_P8X180 .DB " [p8x180] ",0
MSG_RC2014 .DB " [rc2014] ",0
MSG_SBCECB .DB " [sbc] ",0
MSG_MBC .DB " [mbc] ",0
;
;------------------------------------------------------------------------------
; Variables
;------------------------------------------------------------------------------
;
VGMPOS .DW 0
VGMDLY .DW 0
VGMUNK_F .DB 0 ; Flag for unknown device
VGM_DEV .DB %00000000 ; yyYYAASS
.DB %00000000 ; Unimplemented device flags
;VGMDLY .DW 0 ; Saves number of frames to delay
KEYCHK .DB 0 ; Counter for keypress checks
;
VGM_DEV .DB %00000000 ; IX+0 Flags for devices
; xx...... ym2151 1 & 2
; ..x..... ym2612 2 (not supported)
; ...x.... ym2612 1
; ....xx.. ay-3-8910 1 & 2
; ......xx sn76489 1 & 2
.DB %00000000 ; IX+1 Unimplemented device flags & future devices
;
OLDSTACK .DW 0 ; original stack pointer
.DS 40H ; space for stack
STACK ; top of stack

View File

@@ -5,39 +5,70 @@ Simple player for VGM (Video Game Music) files.
Usage:
VGMPLAY MUSIC.VGM
VGMPLAY MUSIC[.VGM]
Default Ports:
Press a key to exit the program.
D8H-D0H - First AY-3-8910 (RSEL/RDAT)
A0H-A1H - Second AY-3-8910
FFH - First SN76489
FBH - Second SN76489
C6H-C7H - YM2612/YM3484
Supported devices
=================
If your system uses different ports you need to recompile the source.
SN76489
AY-3-89810
YM2612/YM3484
YM2151
Note: The player should be compatible with VGM files up to version 1.51
but there are very few controls (if any) in the code, be sure to have
a good VGM file that doesn't contain much extra data. These files can be
very big, the player is limited to the available TPA space which is
typically around 54-55k, bigger files will overwrite the CP/M code and/or
wrap around the 64k limit.
Supported platforms
===================
The played is designed to run on a standard RC2014 with a 7.3728 MHz clock,
if your system uses a different clock you need to adjust the frame delay accordingly.
VGM Player is currently being developed on the ROMWBW platform using the Retrobrew computers
EBC-SBC-V2 (Z80), ECB-SCG (AY-3-8910) and ECB-VGM (YM2612 and 2xSN76489) board.
It can be configured to run with other hardware such as RC2014, P8X180 and nhyodyne MBC.
VGM files can be very big and are limited in size by the available TPA space, which is typically 52k.
Processor speed affects the playback speed. Under ROMWBW the player will detect the cpu speed configuration
and adjust timing loops. For other platforms, default speeds are configured but may need to be changed
to suit your hardware. Counter/Timer hardware may be supported in future.
Example Music Files
===================
LEMMIN01.VGM - SN76489 - Lemmings: Title Screen
PENGUI03.VGM - AY-3-8910 - Penguin Adventure: Forest Path
PITFAL02.VGM - 2xSN76489 - Pitfall II: Scene 1
TIGER02.VGM - 2xAY-3-8910 - Tiger Hely: First Mission
WONDER01.VGM - 2xSN76489 - Wonder Boy in Monster Land
FILTHY01.VGM - YM3484 - Columns : Filthy
ITSGAMOV.VGM - YM3484+SN76489 - Puyo Puyo Tsuu : It's Game Over!
ENDING.VGM - AY-3-8910 * Puyo Puyo: Ending (Unused) : 24K
QIX.VGM - AY-3-8910 - Super Qix: Main BGM 2 : 28K
AGGRESS.VGM - AY-3-8910 - Rastan Saga: Aggressive World : 32K
PENGUI03.VGM - AY-3-8910 - Penguin Adventure: Forest Path : 44K
TIGER02.VGM - 2xAY-3-8910 - Tiger Hely: First Mission : 28K
BGM.VGM - 2xAY-3-8910 * SHM: BGM : 8K
LEMMIN01.VGM - SN76489 - Lemmings: Title Screen : 44K
TEDDY.VGM - 2xSN76489 - TeddyBoy Blues: Title ~ Main Theme : 52K
PITFAL02.VGM - 2xSN76489 - Pitfall II: Scene 1 : 16K
WONDER01.VGM - 2xSN76489 * Wonder Boy in Monster Land: Monster Land : 40K
DESCENT.VGM - SN76489+YM2612 - Flashback: The Quest for Identity: Descent into the Tunnels : 40K
SHIRAKAW.VGM - SN76489+YM2612 * Jantei Monogatari: St. Shirakawa University : 32K
ANNA.VGM - SN76489+YM2612 - Jantei Monogatari: Anna : 32K
FIELDMAP.VGM - SN76489+YM2612 - Taikou Risshiden: Field Map: Summer : 8K
ITSGAMOV.VGM - SN76489+YM2612 - Puyo Puyo Tsuu: It's Game Over! : 16K
STARTDEM.VGN - 2xSN76489+AY-3-8910 * Exed Exes / Savage Bees: Start Demo ~Main BGM : 32K
INCHINA.VGM - YM2612 * Double Dragon 3: The Rosetta Stone: In China : 44K
Original Source by J.B Langston, Marco Maccaferri
ROMWBW + YM2612/YM3484 version by Phil Summers
* Included in disk images
VGM sources
===========
https://www.smspower.org/forums/15359-VGMPacksGameGearMegaCollection
https://vgmrips.net/packs/chip/ym2612
https://project2612.org/
VGM Tools
=========
https://vgmrips.net/wiki/VGMTool
https://github.com/vgmrips/vgmtools
References
==========
http://www.primrosebank.net/computers/mtx/tools/PD/vgmplayer.zip - Paul Daniels MTX SN76489 interrupt version with embedded VGM tune.
https://github.com/jblang/SN76489/blob/master/examples/vgmplayer.asm - J.B. Langston RC2014 polled version with file loading.
https://groups.google.com/g/rc2014-z80/c/9nHnETJzGKU - Marco Maccaferri P8X180 & AY-3-8910 support
https://github.com/electrified/rc2014-ym2151/tree/main/software/vgmplay - Ed Brindly RC2014 & YM2151 support
ROMWBW version by Phil Summers. VGM Player is still in development. The ECB-VGM is also still under development.

View File

@@ -0,0 +1,779 @@
;
;------------------------------------------------------------------------------
; Simple Z80 FM Music Driver.
; Adapted from https://github.com/michaelcmartin/bumbershoot/genesis/fm_mus.asm
;------------------------------------------------------------------------------
;
; A song in this system is a series of records, where each record
; begins with a byte for the number of frames this record lasts,
; followed by a byte for the number of register writes to the first
; block of FM registers, followed by that many pairs of (register,
; value) bytes.
; When a zero byte is reached for a record length, the playback
; loops back to the "segno" label.
;
; Song data is created from a Music Macro Language score (mml)
; by the makebach.py script
;
;------------------------------------------------------------------------------
; Device and system specific definitions
;------------------------------------------------------------------------------
;
custom .equ 0 ; System configurations
sbcecb .equ 1
MBC .equ 2
;
plt_romwbw .equ 1 ; Build for ROMWBW?
plt_type .equ sbcecb ; Select build configuration
plt_cpuspd .equ 6 ; Non ROMWBW cpu speed default
debug .equ 0
ctc_delay .equ 0
;
.org 100H
;
BDOS .equ 0005h
;
YMSEL .equ $c0
YMDAT .equ $c1
ctcbase .equ $cc
;
;------------------------------------------------------------------------------
; Initialize sound chip and ctc etc
;------------------------------------------------------------------------------
;
init:
#IF (debug)
call ym_init
#ENDIF
#IF (ctc_delay)
call ctc_config
#ENDIF
;
;------------------------------------------------------------------------------
; Main loop
;------------------------------------------------------------------------------
;
mloop: LD C, 6 ; check for keypress
LD E, 0FFH
CALL 5
OR A
JP NZ,0
;
call ploop ; PLAY
jp z,0
;
ld hl,$1000 ; DELAY
dlp: dec hl
ld a,h
or l
jr nz,dlp
;
jr mloop
;
;------------------------------------------------------------------------------
; Play loop
;------------------------------------------------------------------------------
;
ploop: ld hl, wait ; HAVE WE REACHED THE
dec (hl) ; LAST FRAME
ret nz
ld hl, (ptr) ; POINT TO START OF SONG
ld a, (hl) ; GET NO OF FRAMES
and a ;
ret z
; jr nz, nolp
;
; ld a,'@'
; call PRTCHR
;
; ld hl, segno ; POINT TO CURRENT SEGMENT
; ld a, (hl) ; GET FRAME COUNT
nolp: ld (wait), a ; AND SAVE IT
inc hl
call PRTHEX
call PRTDOT
ld b, (hl) ; GET NUMBER OF REGISTER PAIRS TO WRITE
inc hl ; POINT TO REGISTER
ld a,b
call PRTHEX
call PRTDOT
rlp: ld a, (hl) ; SELECT REGISTER
out (YMSEL),a
call PRTHEX
inc hl ; GET VALUE
ld a, (hl)
call PRTHEX
inc hl
out (YMDAT),a ; WRITE THE VALUE
djnz rlp ; DO ALL THE PAIRS IN THIS SEGMENT
ld (ptr), hl ; SAVE WHERE WE ARE AT
call CRLF
ret
;
;------------------------------------------------------------------------------
; CTC initialization
;------------------------------------------------------------------------------
;
ctc_config:
; ld b,4 ; 4 channels
; ld c,ctcbase ; first channel port
;ctc_lp: ld a,ctc_defcfg ; ctc default config
; out (c),a ; ctc command
; inc c ; next channel port
; djnz ctc_lp
; ld hl,hb_timint ; TIMER INT HANDLER ADR
; ld (ivt(ctctivt)),hl
;
; ld a,int_ctc0a * 2
out (ctcbase),a ; SETUP CTC BASE INT VECTOR
;
ctcch0 .equ ctcbase
ctcch1 .equ ctcbase+1
ctcch2 .equ ctcbase+2
ctcch3 .equ ctcbase+3
ctccfg0 .equ %01010011
ctccfg1 .equ %01010111
ctccfg2 .equ %01010111
ctccfg3 .equ %01010111
ctcdiv0 .equ 1 ; 3.579545MHz input 60Hz timer tick
ctcdiv1 .equ 8
ctcdiv2 .equ 0
ctcdiv3 .equ 29
;ctcdiv0 .equ 1 ; 3.579545MHz input 50Hz timer tick
;ctcdiv1 .equ 8
;ctcdiv2 .equ 0
;ctcdiv3 .equ 34
;ctcdiv0 .equ 1 ; 3.579545MHz input 44100z timer tick
;ctcdiv1 .equ 1
;ctcdiv2 .equ 1
;ctcdiv3 .equ 81
ld a,ctccfg0 & $7f ; ; Channel 0
out (ctcch0),a
;
ld a,ctccfg1 & $7f ; Channel 1
out (ctcch1),a ;
ld a,ctcdiv1 & $ff ;
out (ctcch1),a ;
;
ld a,ctccfg2 & $7f ; Channel 2
out (ctcch2),a ;
ld a,ctcdiv2 & $ff ;
out (ctcch2),a ;
;
ld a,ctccfg3 & $7f ; Channel 3
out (ctcch3),a ;
ld a,ctcdiv3 & $ff ;
out (ctcch3),a ;
;
ret
;
ptr: .dw song
wait: .db $01
;
;------------------------------------------------------------------------------
; YM2612 initialization - not required if included in song data
;------------------------------------------------------------------------------
;
#DEFINE setreg(reg,val) \
#DEFCONT \ ld a,reg
#DEFCONT \ out (YMSEL),a
#DEFCONT \ ld a,val
#DEFCONT \ out (YMDAT),a
#DEFCONT \ ld b,0
#DEFCONT \ in a,(YMSEL)
#DEFCONT \ rlca
#DEFCONT \ jp nc,$+5
#DEFCONT \ djnz $-6
;
ym_init:
setreg($22,$00) ; lfo off
setreg($27,$00) ; note off ch 0
setreg($28,$01) ; note off ch 1
setreg($28,$02) ; note off ch 2
setreg($28,$03) ; note off ch 3
setreg($28,$04) ; note off ch 4
setreg($28,$05) ; note off ch 5
setreg($28,$06) ; note off ch 6
setreg($28,$01) ; note off ch 1
setreg($2b,$00) ; dac off
setreg($30,$71)
setreg($34,$0d)
setreg($38,$33)
setreg($3c,$01) ; dt1/mul
setreg($40,$23)
setreg($44,$2d)
setreg($48,$26)
setreg($4c,$00) ; total level
setreg($50,$5f)
setreg($54,$99)
setreg($58,$5f)
setreg($5c,$94) ; rs/ar
setreg($60,$05)
setreg($64,$05)
setreg($68,$05)
setreg($6c,$07) ; am/dir
setreg($70,$02)
setreg($74,$02)
setreg($78,$02)
setreg($7c,$02) ; d2r
setreg($80,$11)
setreg($84,$11)
setreg($88,$11)
setreg($8c,$a6) ; d1l/rr
setreg($90,$00)
setreg($94,$00)
setreg($98,$00)
setreg($9c,$00) ; proprietary
setreg($b0,$32) ; feedback/algorithm
setreg($b4,$c0) ; both speakers on
setreg($28,$00) ; key off
setreg($a4,$22)
setreg($a0,$69) ; set frequency
;
ret
;
;------------------------------------------------------------------------------
; Example breakdown of first section, which is initialization
;------------------------------------------------------------------------------
;
; BYTE NUMBER OF FRAMES
; BYTE NUMBER OF REGISTER WRITES
; BYTE REGISTER
; BYTE VALUE
;
; CNT $0D 13 frames
; $42 66 register writes (132 BYTES)
; 2 $30,$71 dac
; 4 $34,$0D dac
; 6 $38,$33 dac
; 8 $3C,$01 dt1/mul
; 10 $40,$23 dt1/mul
; 12 $44,$2D dt1/mul
; 14 $48,$26 dt1/mul
; 16 $4C,$00 total level
; 18 $50,$5F total level
; 20 $54,$99 total level
; 22 $58,$5F total level
; 24 $5C,$94 rs/ar
; 26 $60,$05 rs/ar
; 28 $64,$05 rs/ar
; 30 $68,$05 rs/ar
; 32 $6C,$07 am/dir
; 34 $70,$02 am/dir
; 36 $74,$02 am/dir
; 38 $78,$02 am/dir
; 40 $7c,$02 d2r
; 42 $80,$11 d2r
; 44 $84,$11 d2r
; 46 $88,$11 d2r
; 48 $8C,$A6
; 50 $90,$00
; 52 $94,$00
; 54 $98,$00
; 56 $9C,$00
; 58 $B0,$32
; 60 $B4,$C0
; 62 $31,$71
; 64 $35,$0D
; 66 $39,$33
; 68 $3D,$01
; 70 $41,$23
; 72 $45,$2D
; 74 $49,$26
; 76 $4D,$00
; 78 $51,$5F
; 80 $55,$99
; 82 $59,$5F
; 84 $5D,$94
; 86 $61,$05
; 88 $65,$05
; 90 $69,$05
; 92 $6D,$07
; 94 $71,$02
; 96 $75,$02
; 98 $79,$02
; 100 $7D,$02
; 102 $81,$11
; 104 $85,$11
; 106 $89,$11
; 108 $8D,$A6
; 110 $91,$00
; 112 $95,$00
; 114 $99,$00
; 116 $9D,$00
; 118 $B0,$32
; 120 $B4,$C0
; 122 $A4,$17
; 124 $A0,$89
; 126 $28,$F0
; 128 $A5,$0F
; 130 $A1,$89
; 132 $28,$F1
;
;------------------------------------------------------------------------------
; Song data created from Music Macro Language (mml) by makebach
;------------------------------------------------------------------------------
;
song:
segno: .db $0D,$42,$30,$71,$34,$0D,$38,$33,$3C,$01,$40,$23,$44,$2D,$48,$26
.db $4C,$00,$50,$5F,$54,$99,$58,$5F,$5C,$94,$60,$05,$64,$05,$68,$05
.db $6C,$07,$70,$02,$74,$02,$78,$02,$7C,$02,$80,$11,$84,$11,$88,$11
.db $8C,$A6,$90,$00,$94,$00,$98,$00,$9C,$00,$B0,$32,$B4,$C0,$31,$71
.db $35,$0D,$39,$33,$3D,$01,$41,$23,$45,$2D,$49,$26,$4D,$00,$51,$5F
.db $55,$99,$59,$5F,$5D,$94,$61,$05,$65,$05,$69,$05,$6D,$07,$71,$02
.db $75,$02,$79,$02,$7D,$02,$81,$11,$85,$11,$89,$11,$8D,$A6,$91,$00
.db $95,$00,$99,$00,$9D,$00,$B0,$32,$B4,$C0,$A4,$17,$A0,$89,$28,$F0
.db $A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00,$0D,$03,$A4,$1C,$A0,$BF
.db $28,$F0,$02,$01,$28,$00,$0D,$03,$A4,$1D,$A0,$A5,$28,$F0,$02,$01
.db $28,$00,$07,$03,$A4,$1F,$A0,$89,$28,$F0,$06,$01,$28,$01,$02,$01
.db $28,$00,$0D,$06,$A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1
.db $02,$01,$28,$00,$0B,$03,$A4,$1F,$A0,$1D,$28,$F0,$02,$01,$28,$01
.db $02,$01,$28,$00,$0D,$06,$A4,$1F,$A0,$89,$28,$F0,$A5,$07,$A1,$89
.db $28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01
.db $28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D
.db $A1,$A5,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0F,$A1,$89,$28,$F1
.db $02,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0
.db $A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF
.db $28,$F1,$02,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89
.db $28,$F0,$A5,$07,$A1,$89,$28,$F1,$02,$01,$28,$00,$0D,$03,$A4,$1C
.db $A0,$BF,$28,$F0,$02,$01,$28,$00,$0D,$03,$A4,$1D,$A0,$A5,$28,$F0
.db $02,$01,$28,$00,$07,$03,$A4,$1F,$A0,$89,$28,$F0,$06,$01,$28,$01
.db $02,$01,$28,$00,$0D,$06,$A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$A5
.db $28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1F,$A0,$1D,$28,$F0,$02,$01
.db $28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1F,$A0,$89,$28,$F0,$A5,$07
.db $A1,$89,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1
.db $02,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0
.db $A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0F,$A1,$89
.db $28,$F1,$02,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89
.db $28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0C
.db $A1,$BF,$28,$F1,$02,$01,$28,$00,$02,$01,$28,$01,$1A,$06,$A4,$1E
.db $A0,$56,$28,$F0,$A5,$0D,$A1,$08,$28,$F1,$04,$02,$28,$00,$28,$01
.db $1A,$06,$A4,$1E,$A0,$56,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$04,$02
.db $28,$00,$28,$01,$0D,$06,$A4,$1E,$A0,$56,$28,$F0,$A5,$0D,$A1,$08
.db $28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1F,$A0,$89,$28,$F0,$02,$01
.db $28,$01,$02,$01,$28,$00,$1A,$06,$A4,$1D,$A0,$A5,$28,$F0,$A5,$0C
.db $A1,$BF,$28,$F1,$04,$02,$28,$00,$28,$01,$1A,$06,$A4,$1D,$A0,$A5
.db $28,$F0,$A5,$0F,$A1,$89,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06
.db $A4,$1D,$A0,$A5,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1F,$A0,$89,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $1A,$06,$A4,$1D,$A0,$08,$28,$F0,$A5,$0C,$A1,$3B,$28,$F1,$04,$02
.db $28,$00,$28,$01,$0D,$06,$A4,$1D,$A0,$A5,$28,$F0,$A5,$0F,$A1,$1D
.db $28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1D,$A0,$08,$28,$F0,$02,$01
.db $28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1C,$A0,$BF,$28,$F0,$A5,$0F
.db $A1,$89,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1D,$A0,$08,$28,$F0
.db $02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1C,$A0,$3B,$28,$F0
.db $A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$01,$0D,$03,$A5,$0E,$A1,$56
.db $28,$F1,$02,$01,$28,$01,$0D,$03,$A5,$0F,$A1,$1D,$28,$F1,$02,$01
.db $28,$01,$0D,$03,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$01,$0D,$03
.db $A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$01,$03,$03,$A5,$0F,$A1,$1D
.db $28,$F1,$0A,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89
.db $28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00,$0D,$03,$A4,$1C
.db $A0,$BF,$28,$F0,$02,$01,$28,$00,$0D,$03,$A4,$1D,$A0,$A5,$28,$F0
.db $02,$01,$28,$00,$07,$03,$A4,$1F,$A0,$89,$28,$F0,$06,$01,$28,$01
.db $02,$01,$28,$00,$0D,$06,$A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$A5
.db $28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1F,$A0,$1D,$28,$F0,$02,$01
.db $28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1F,$A0,$89,$28,$F0,$A5,$07
.db $A1,$89,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1
.db $02,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0
.db $A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0F,$A1,$89
.db $28,$F1,$02,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89
.db $28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0C
.db $A1,$BF,$28,$F1,$02,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17
.db $A0,$89,$28,$F0,$A5,$07,$A1,$89,$28,$F1,$02,$01,$28,$00,$0D,$03
.db $A4,$1C,$A0,$BF,$28,$F0,$02,$01,$28,$00,$0D,$03,$A4,$1D,$A0,$A5
.db $28,$F0,$02,$01,$28,$00,$07,$03,$A4,$1F,$A0,$89,$28,$F0,$06,$01
.db $28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1C,$A0,$3B,$28,$F0,$A5,$0D
.db $A1,$A5,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1F,$A0,$1D,$28,$F0
.db $02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1F,$A0,$89,$28,$F0
.db $A5,$07,$A1,$89,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF
.db $28,$F1,$02,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89
.db $28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0F
.db $A1,$89,$28,$F1,$02,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17
.db $A0,$89,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$01,$0B,$03
.db $A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00,$02,$01,$28,$01,$1A,$06
.db $A4,$1E,$A0,$56,$28,$F0,$A5,$0D,$A1,$08,$28,$F1,$04,$02,$28,$00
.db $28,$01,$0D,$06,$A4,$1D,$A0,$A5,$28,$F0,$A5,$0E,$A1,$56,$28,$F1
.db $02,$01,$28,$00,$0B,$03,$A4,$1D,$A0,$08,$28,$F0,$02,$01,$28,$01
.db $02,$01,$28,$00,$0D,$06,$A4,$1C,$A0,$BF,$28,$F0,$A5,$0F,$A1,$89
.db $28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1C,$A0,$3B,$28,$F0,$02,$01
.db $28,$01,$02,$01,$28,$00,$1A,$06,$A4,$1D,$A0,$A5,$28,$F0,$A5,$0C
.db $A1,$BF,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06,$A4,$1D,$A0,$08
.db $28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1C
.db $A0,$BF,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1C
.db $A0,$3B,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00,$0B,$03
.db $A4,$17,$A0,$89,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$08,$06
.db $A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$08,$28,$F1,$02,$01,$28,$00
.db $08,$03,$A4,$1C,$A0,$BF,$28,$F0,$02,$01,$28,$00,$06,$03,$A4,$1D
.db $A0,$08,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$1A,$06,$A4,$15
.db $A0,$A5,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$04,$02,$28,$00,$28,$01
.db $1A,$06,$A4,$17,$A0,$1D,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$04,$02
.db $28,$00,$28,$01,$1A,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0F,$A1,$89
.db $28,$F1,$04,$01,$28,$01,$1A,$03,$A5,$0D,$A1,$A5,$28,$F1,$04,$01
.db $28,$01,$12,$03,$A5,$07,$A1,$89,$28,$F1,$08,$01,$28,$00,$04,$01
.db $28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0F,$A1,$89,$28,$F1
.db $02,$01,$28,$00,$0D,$03,$A4,$1C,$A0,$BF,$28,$F0,$02,$01,$28,$00
.db $0D,$03,$A4,$1D,$A0,$A5,$28,$F0,$02,$01,$28,$00,$07,$03,$A4,$1F
.db $A0,$89,$28,$F0,$06,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1C
.db $A0,$3B,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00,$0B,$03
.db $A4,$1F,$A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06
.db $A4,$1F,$A0,$89,$28,$F0,$A5,$07,$A1,$89,$28,$F1,$02,$01,$28,$01
.db $0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00,$02,$01,$28,$01
.db $0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01
.db $28,$01,$0B,$03,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00,$02,$01
.db $28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1
.db $02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00
.db $02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$07,$A1,$89
.db $28,$F1,$02,$01,$28,$00,$0D,$03,$A4,$1C,$A0,$BF,$28,$F0,$02,$01
.db $28,$00,$0D,$03,$A4,$1D,$A0,$A5,$28,$F0,$02,$01,$28,$00,$07,$03
.db $A4,$1F,$A0,$89,$28,$F0,$06,$01,$28,$01,$02,$01,$28,$00,$0D,$06
.db $A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1F,$A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $0D,$06,$A4,$1F,$A0,$89,$28,$F0,$A5,$07,$A1,$89,$28,$F1,$02,$01
.db $28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00,$02,$01
.db $28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1
.db $02,$01,$28,$01,$0B,$03,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00
.db $02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5
.db $28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01
.db $28,$00,$02,$01,$28,$01,$1A,$06,$A4,$1E,$A0,$56,$28,$F0,$A5,$0D
.db $A1,$08,$28,$F1,$04,$02,$28,$00,$28,$01,$1A,$06,$A4,$1E,$A0,$56
.db $28,$F0,$A5,$0F,$A1,$89,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06
.db $A4,$1E,$A0,$56,$28,$F0,$A5,$0D,$A1,$08,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1F,$A0,$89,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $1A,$06,$A4,$1D,$A0,$A5,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$04,$02
.db $28,$00,$28,$01,$1A,$06,$A4,$1D,$A0,$A5,$28,$F0,$A5,$0F,$A1,$89
.db $28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06,$A4,$1D,$A0,$A5,$28,$F0
.db $A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1F,$A0,$89
.db $28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$1A,$06,$A4,$1D,$A0,$08
.db $28,$F0,$A5,$0C,$A1,$3B,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06
.db $A4,$1D,$A0,$A5,$28,$F0,$A5,$0F,$A1,$1D,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1D,$A0,$08,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $0D,$06,$A4,$1C,$A0,$BF,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01
.db $28,$00,$0B,$03,$A4,$1D,$A0,$08,$28,$F0,$02,$01,$28,$01,$02,$01
.db $28,$00,$0D,$06,$A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1
.db $02,$01,$28,$01,$0D,$03,$A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$01
.db $0D,$03,$A5,$0F,$A1,$1D,$28,$F1,$02,$01,$28,$01,$0D,$03,$A5,$0D
.db $A1,$A5,$28,$F1,$02,$01,$28,$01,$0D,$03,$A5,$0E,$A1,$56,$28,$F1
.db $02,$01,$28,$01,$03,$03,$A5,$0F,$A1,$1D,$28,$F1,$0A,$01,$28,$00
.db $02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0F,$A1,$89
.db $28,$F1,$02,$01,$28,$00,$0D,$03,$A4,$1C,$A0,$BF,$28,$F0,$02,$01
.db $28,$00,$0D,$03,$A4,$1D,$A0,$A5,$28,$F0,$02,$01,$28,$00,$07,$03
.db $A4,$1F,$A0,$89,$28,$F0,$06,$01,$28,$01,$02,$01,$28,$00,$0D,$06
.db $A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1F,$A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $0D,$06,$A4,$1F,$A0,$89,$28,$F0,$A5,$07,$A1,$89,$28,$F1,$02,$01
.db $28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00,$02,$01
.db $28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1
.db $02,$01,$28,$01,$0B,$03,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00
.db $02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5
.db $28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01
.db $28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$07
.db $A1,$89,$28,$F1,$02,$01,$28,$00,$0D,$03,$A4,$1C,$A0,$BF,$28,$F0
.db $02,$01,$28,$00,$0D,$03,$A4,$1D,$A0,$A5,$28,$F0,$02,$01,$28,$00
.db $07,$03,$A4,$1F,$A0,$89,$28,$F0,$06,$01,$28,$01,$02,$01,$28,$00
.db $0D,$06,$A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01
.db $28,$00,$0B,$03,$A4,$1F,$A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01
.db $28,$00,$0D,$06,$A4,$1F,$A0,$89,$28,$F0,$A5,$07,$A1,$89,$28,$F1
.db $02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00
.db $02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5
.db $28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0F,$A1,$89,$28,$F1,$02,$01
.db $28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D
.db $A1,$A5,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1
.db $02,$01,$28,$00,$02,$01,$28,$01,$1A,$06,$A4,$1E,$A0,$56,$28,$F0
.db $A5,$0D,$A1,$08,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06,$A4,$1D
.db $A0,$A5,$28,$F0,$A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$00,$0B,$03
.db $A4,$1D,$A0,$08,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06
.db $A4,$1C,$A0,$BF,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1C,$A0,$3B,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $1A,$06,$A4,$1D,$A0,$A5,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$04,$02
.db $28,$00,$28,$01,$0D,$06,$A4,$1D,$A0,$08,$28,$F0,$A5,$0D,$A1,$A5
.db $28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1C,$A0,$BF,$28,$F0,$02,$01
.db $28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1C,$A0,$3B,$28,$F0,$A5,$0F
.db $A1,$89,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$17,$A0,$89,$28,$F0
.db $02,$01,$28,$01,$02,$01,$28,$00,$08,$06,$A4,$1C,$A0,$3B,$28,$F0
.db $A5,$0D,$A1,$08,$28,$F1,$02,$01,$28,$00,$08,$03,$A4,$1C,$A0,$BF
.db $28,$F0,$02,$01,$28,$00,$06,$03,$A4,$1D,$A0,$08,$28,$F0,$02,$01
.db $28,$01,$02,$01,$28,$00,$1A,$06,$A4,$15,$A0,$A5,$28,$F0,$A5,$0D
.db $A1,$A5,$28,$F1,$04,$02,$28,$00,$28,$01,$1A,$06,$A4,$17,$A0,$1D
.db $28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$04,$02,$28,$00,$28,$01,$1A,$06
.db $A4,$17,$A0,$89,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$04,$01,$28,$01
.db $1A,$03,$A5,$0D,$A1,$A5,$28,$F1,$04,$01,$28,$01,$12,$03,$A5,$07
.db $A1,$89,$28,$F1,$08,$01,$28,$00,$04,$01,$28,$01,$0D,$06,$A4,$17
.db $A0,$89,$28,$F0,$A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$00,$0B,$03
.db $A4,$1C,$A0,$3B,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06
.db $A4,$1C,$A0,$BF,$28,$F0,$A5,$0D,$A1,$FB,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1C,$A0,$3B,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$02,$01
.db $28,$00,$0B,$03,$A4,$17,$A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01
.db $28,$00,$1A,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0E,$A1,$56,$28,$F1
.db $04,$02,$28,$00,$28,$01,$1A,$06,$A4,$16,$A0,$56,$28,$F0,$A5,$0C
.db $A1,$BF,$28,$F1,$04,$02,$28,$00,$28,$01,$1A,$06,$A4,$16,$A0,$56
.db $28,$F0,$A5,$06,$A1,$56,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06
.db $A4,$1F,$A0,$89,$28,$F0,$A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1F,$A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $0D,$06,$A4,$1E,$A0,$56,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01
.db $28,$00,$0B,$03,$A4,$1F,$A0,$89,$28,$F0,$02,$01,$28,$01,$02,$01
.db $28,$00,$0D,$06,$A4,$1F,$A0,$1D,$28,$F0,$A5,$14,$A1,$BF,$28,$F1
.db $02,$01,$28,$00,$0B,$03,$A4,$1E,$A0,$56,$28,$F0,$02,$01,$28,$01
.db $02,$01,$28,$00,$0D,$06,$A4,$1F,$A0,$1D,$28,$F0,$A5,$0C,$A1,$BF
.db $28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0D,$A1,$FB,$28,$F1,$02,$01
.db $28,$00,$02,$01,$28,$01,$0D,$06,$A4,$1C,$A0,$BF,$28,$F0,$A5,$0F
.db $A1,$1D,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$14,$A1,$BF,$28,$F1
.db $02,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$1C,$A0,$BF,$28,$F0
.db $A5,$0F,$A1,$1D,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0D,$A1,$FB
.db $28,$F1,$02,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$1F,$A0,$89
.db $28,$F0,$A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1F
.db $A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1E
.db $A0,$56,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00,$0B,$03
.db $A4,$1F,$A0,$89,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06
.db $A4,$1F,$A0,$1D,$28,$F0,$A5,$14,$A1,$BF,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1E,$A0,$56,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $1A,$06,$A4,$1F,$A0,$1D,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$04,$02
.db $28,$00,$28,$01,$1A,$06,$A4,$1C,$A0,$BF,$28,$F0,$A5,$14,$A1,$3B
.db $28,$F1,$04,$02,$28,$00,$28,$01,$1A,$06,$A4,$1E,$A0,$56,$28,$F0
.db $A5,$0F,$A1,$89,$28,$F1,$04,$02,$28,$00,$28,$01,$08,$06,$A4,$1F
.db $A0,$1D,$28,$F0,$A5,$14,$A1,$3B,$28,$F1,$02,$01,$28,$00,$08,$03
.db $A4,$1F,$A0,$89,$28,$F0,$02,$01,$28,$00,$06,$03,$A4,$24,$A0,$3B
.db $28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$1A,$06,$A4,$1C,$A0,$BF
.db $28,$F0,$A5,$14,$A1,$BF,$28,$F1,$04,$02,$28,$00,$28,$01,$1A,$06
.db $A4,$1D,$A0,$FB,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$04,$02,$28,$00
.db $28,$01,$1A,$06,$A4,$1E,$A0,$56,$28,$F0,$A5,$0E,$A1,$56,$28,$F1
.db $04,$01,$28,$00,$0D,$03,$A4,$1D,$A0,$FB,$28,$F0,$02,$01,$28,$00
.db $0D,$03,$A4,$1E,$A0,$56,$28,$F0,$02,$01,$28,$00,$12,$03,$A4,$1F
.db $A0,$1D,$28,$F0,$08,$01,$28,$01,$04,$01,$28,$00,$1A,$06,$A4,$1F
.db $A0,$89,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$04,$02,$28,$00,$28,$01
.db $0D,$06,$A4,$1F,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01
.db $28,$00,$0B,$03,$A4,$1F,$A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01
.db $28,$00,$0D,$06,$A4,$1E,$A0,$56,$28,$F0,$A5,$0F,$A1,$89,$28,$F1
.db $02,$01,$28,$00,$0B,$03,$A4,$1D,$A0,$A5,$28,$F0,$02,$01,$28,$01
.db $02,$01,$28,$00,$1A,$06,$A4,$1E,$A0,$56,$28,$F0,$A5,$0D,$A1,$08
.db $28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06,$A4,$1E,$A0,$56,$28,$F0
.db $A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1D,$A0,$A5
.db $28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1D,$A0,$08
.db $28,$F0,$A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1C
.db $A0,$BF,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$1A,$06,$A4,$1D
.db $A0,$08,$28,$F0,$A5,$0C,$A1,$3B,$28,$F1,$04,$02,$28,$00,$28,$01
.db $0D,$06,$A4,$1D,$A0,$08,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$02,$01
.db $28,$00,$0B,$03,$A4,$1C,$A0,$BF,$28,$F0,$02,$01,$28,$01,$02,$01
.db $28,$00,$0D,$06,$A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$08,$28,$F1
.db $02,$01,$28,$00,$0B,$03,$A4,$17,$A0,$89,$28,$F0,$02,$01,$28,$01
.db $02,$01,$28,$00,$1A,$06,$A4,$17,$A0,$1D,$28,$F0,$A5,$0D,$A1,$A5
.db $28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06,$A4,$16,$A0,$56,$28,$F0
.db $A5,$0C,$A1,$3B,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$17,$A0,$1D
.db $28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$1A,$06,$A4,$15,$A0,$A5
.db $28,$F0,$A5,$05,$A1,$A5,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06
.db $A4,$1C,$A0,$3B,$28,$F0,$A5,$0F,$A1,$1D,$28,$F1,$02,$01,$28,$01
.db $0B,$03,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00,$02,$01,$28,$01
.db $0D,$06,$A4,$15,$A0,$A5,$28,$F0,$A5,$0F,$A1,$1D,$28,$F1,$02,$01
.db $28,$01,$0B,$03,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00,$02,$01
.db $28,$01,$0D,$06,$A4,$15,$A0,$A5,$28,$F0,$A5,$0F,$A1,$1D,$28,$F1
.db $02,$01,$28,$01,$0B,$03,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00
.db $02,$01,$28,$01,$0D,$06,$A4,$1C,$A0,$BF,$28,$F0,$A5,$0F,$A1,$89
.db $28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0D,$A1,$A5,$28,$F1,$02,$01
.db $28,$00,$02,$01,$28,$01,$0D,$06,$A4,$15,$A0,$A5,$28,$F0,$A5,$0F
.db $A1,$89,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0D,$A1,$A5,$28,$F1
.db $02,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$15,$A0,$A5,$28,$F0
.db $A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0D,$A1,$A5
.db $28,$F1,$02,$01,$28,$00,$02,$01,$28,$01,$1A,$06,$A4,$1D,$A0,$08
.db $28,$F0,$A5,$0F,$A1,$1D,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06
.db $A4,$1D,$A0,$A5,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1D,$A0,$08,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $0D,$06,$A4,$1C,$A0,$BF,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01
.db $28,$00,$0B,$03,$A4,$1D,$A0,$08,$28,$F0,$02,$01,$28,$01,$02,$01
.db $28,$00,$0D,$06,$A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1
.db $02,$01,$28,$01,$0D,$03,$A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$01
.db $0D,$03,$A5,$0F,$A1,$1D,$28,$F1,$02,$01,$28,$01,$0D,$03,$A5,$0D
.db $A1,$A5,$28,$F1,$02,$01,$28,$01,$0D,$03,$A5,$0E,$A1,$56,$28,$F1
.db $02,$01,$28,$01,$03,$03,$A5,$0F,$A1,$1D,$28,$F1,$0A,$01,$28,$00
.db $02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0F,$A1,$89
.db $28,$F1,$02,$01,$28,$00,$0D,$03,$A4,$1C,$A0,$BF,$28,$F0,$02,$01
.db $28,$00,$0D,$03,$A4,$1D,$A0,$A5,$28,$F0,$02,$01,$28,$00,$07,$03
.db $A4,$1F,$A0,$89,$28,$F0,$06,$01,$28,$01,$02,$01,$28,$00,$0D,$06
.db $A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1F,$A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $0D,$06,$A4,$1F,$A0,$89,$28,$F0,$A5,$07,$A1,$89,$28,$F1,$02,$01
.db $28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00,$02,$01
.db $28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1
.db $02,$01,$28,$01,$0B,$03,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00
.db $02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5
.db $28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01
.db $28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$07
.db $A1,$89,$28,$F1,$02,$01,$28,$00,$0D,$03,$A4,$1C,$A0,$BF,$28,$F0
.db $02,$01,$28,$00,$0D,$03,$A4,$1D,$A0,$A5,$28,$F0,$02,$01,$28,$00
.db $07,$03,$A4,$1F,$A0,$89,$28,$F0,$06,$01,$28,$01,$02,$01,$28,$00
.db $0D,$06,$A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01
.db $28,$00,$0B,$03,$A4,$1F,$A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01
.db $28,$00,$0D,$06,$A4,$1F,$A0,$89,$28,$F0,$A5,$07,$A1,$89,$28,$F1
.db $02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00
.db $02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5
.db $28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0F,$A1,$89,$28,$F1,$02,$01
.db $28,$00,$02,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D
.db $A1,$A5,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1
.db $02,$01,$28,$00,$02,$01,$28,$01,$1A,$06,$A4,$1E,$A0,$56,$28,$F0
.db $A5,$0D,$A1,$08,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06,$A4,$1D
.db $A0,$A5,$28,$F0,$A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$00,$0B,$03
.db $A4,$1D,$A0,$08,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06
.db $A4,$1C,$A0,$BF,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1C,$A0,$3B,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $1A,$06,$A4,$1D,$A0,$A5,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$04,$02
.db $28,$00,$28,$01,$0D,$06,$A4,$1D,$A0,$08,$28,$F0,$A5,$0D,$A1,$A5
.db $28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1C,$A0,$BF,$28,$F0,$02,$01
.db $28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1C,$A0,$3B,$28,$F0,$A5,$0F
.db $A1,$89,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$17,$A0,$89,$28,$F0
.db $02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1C,$A0,$3B,$28,$F0
.db $A5,$0D,$A1,$08,$28,$F1,$02,$01,$28,$00,$0D,$03,$A4,$1C,$A0,$BF
.db $28,$F0,$02,$01,$28,$00,$16,$03,$A4,$15,$A0,$A5,$28,$F0,$04,$01
.db $28,$01,$04,$01,$28,$00,$1A,$06,$A4,$17,$A0,$1D,$28,$F0,$A5,$0D
.db $A1,$A5,$28,$F1,$04,$02,$28,$00,$28,$01,$1A,$06,$A4,$17,$A0,$89
.db $28,$F0,$A5,$0F,$A1,$89,$28,$F1,$04,$01,$28,$01,$1A,$03,$A5,$0D
.db $A1,$A5,$28,$F1,$04,$01,$28,$01,$12,$03,$A5,$07,$A1,$89,$28,$F1
.db $08,$01,$28,$00,$04,$01,$28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0
.db $A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1C,$A0,$3B
.db $28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1C,$A0,$BF
.db $28,$F0,$A5,$0D,$A1,$FB,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1C
.db $A0,$3B,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$17
.db $A0,$89,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00,$0B,$03
.db $A4,$17,$A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$1A,$06
.db $A4,$17,$A0,$89,$28,$F0,$A5,$0E,$A1,$56,$28,$F1,$04,$02,$28,$00
.db $28,$01,$1A,$06,$A4,$16,$A0,$56,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1
.db $04,$02,$28,$00,$28,$01,$1A,$06,$A4,$16,$A0,$56,$28,$F0,$A5,$06
.db $A1,$56,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06,$A4,$1F,$A0,$89
.db $28,$F0,$A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1F
.db $A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1E
.db $A0,$56,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00,$0B,$03
.db $A4,$1F,$A0,$89,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06
.db $A4,$1F,$A0,$1D,$28,$F0,$A5,$14,$A1,$BF,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1E,$A0,$56,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $0D,$06,$A4,$1F,$A0,$1D,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$02,$01
.db $28,$01,$0B,$03,$A5,$0D,$A1,$FB,$28,$F1,$02,$01,$28,$00,$02,$01
.db $28,$01,$0D,$06,$A4,$1C,$A0,$BF,$28,$F0,$A5,$0F,$A1,$1D,$28,$F1
.db $02,$01,$28,$01,$0B,$03,$A5,$14,$A1,$BF,$28,$F1,$02,$01,$28,$00
.db $02,$01,$28,$01,$0D,$06,$A4,$1C,$A0,$BF,$28,$F0,$A5,$0F,$A1,$1D
.db $28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0D,$A1,$FB,$28,$F1,$02,$01
.db $28,$00,$02,$01,$28,$01,$0D,$06,$A4,$1F,$A0,$89,$28,$F0,$A5,$0E
.db $A1,$56,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1F,$A0,$1D,$28,$F0
.db $02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1E,$A0,$56,$28,$F0
.db $A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1F,$A0,$89
.db $28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1F,$A0,$1D
.db $28,$F0,$A5,$14,$A1,$BF,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1E
.db $A0,$56,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$1A,$06,$A4,$1F
.db $A0,$1D,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$04,$02,$28,$00,$28,$01
.db $1A,$06,$A4,$1C,$A0,$BF,$28,$F0,$A5,$14,$A1,$3B,$28,$F1,$04,$02
.db $28,$00,$28,$01,$1A,$06,$A4,$1E,$A0,$56,$28,$F0,$A5,$0F,$A1,$89
.db $28,$F1,$04,$02,$28,$00,$28,$01,$08,$06,$A4,$1F,$A0,$1D,$28,$F0
.db $A5,$14,$A1,$3B,$28,$F1,$02,$01,$28,$00,$08,$03,$A4,$1F,$A0,$89
.db $28,$F0,$02,$01,$28,$00,$06,$03,$A4,$24,$A0,$3B,$28,$F0,$02,$01
.db $28,$01,$02,$01,$28,$00,$1A,$06,$A4,$1C,$A0,$BF,$28,$F0,$A5,$14
.db $A1,$BF,$28,$F1,$04,$02,$28,$00,$28,$01,$1A,$06,$A4,$1D,$A0,$FB
.db $28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$04,$02,$28,$00,$28,$01,$1A,$06
.db $A4,$1E,$A0,$56,$28,$F0,$A5,$0E,$A1,$56,$28,$F1,$04,$01,$28,$00
.db $0D,$03,$A4,$1D,$A0,$FB,$28,$F0,$02,$01,$28,$00,$0D,$03,$A4,$1E
.db $A0,$56,$28,$F0,$02,$01,$28,$00,$12,$03,$A4,$1F,$A0,$1D,$28,$F0
.db $08,$01,$28,$01,$04,$01,$28,$00,$1A,$06,$A4,$1F,$A0,$89,$28,$F0
.db $A5,$0C,$A1,$BF,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06,$A4,$1F
.db $A0,$89,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00,$0B,$03
.db $A4,$1F,$A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06
.db $A4,$1E,$A0,$56,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$1D,$A0,$A5,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $1A,$06,$A4,$1E,$A0,$56,$28,$F0,$A5,$0D,$A1,$08,$28,$F1,$04,$02
.db $28,$00,$28,$01,$0D,$06,$A4,$1E,$A0,$56,$28,$F0,$A5,$0D,$A1,$A5
.db $28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1D,$A0,$A5,$28,$F0,$02,$01
.db $28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1D,$A0,$08,$28,$F0,$A5,$0E
.db $A1,$56,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1C,$A0,$BF,$28,$F0
.db $02,$01,$28,$01,$02,$01,$28,$00,$1A,$06,$A4,$1D,$A0,$08,$28,$F0
.db $A5,$0C,$A1,$3B,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06,$A4,$1D
.db $A0,$08,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00,$0B,$03
.db $A4,$1C,$A0,$BF,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06
.db $A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$08,$28,$F1,$02,$01,$28,$00
.db $0B,$03,$A4,$17,$A0,$89,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00
.db $1A,$06,$A4,$17,$A0,$1D,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$04,$02
.db $28,$00,$28,$01,$0D,$06,$A4,$16,$A0,$56,$28,$F0,$A5,$0C,$A1,$3B
.db $28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$17,$A0,$1D,$28,$F0,$02,$01
.db $28,$01,$02,$01,$28,$00,$1A,$06,$A4,$15,$A0,$A5,$28,$F0,$A5,$05
.db $A1,$A5,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06,$A4,$1C,$A0,$3B
.db $28,$F0,$A5,$0F,$A1,$1D,$28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0D
.db $A1,$A5,$28,$F1,$02,$01,$28,$00,$02,$01,$28,$01,$0D,$06,$A4,$15
.db $A0,$A5,$28,$F0,$A5,$0F,$A1,$1D,$28,$F1,$02,$01,$28,$01,$0B,$03
.db $A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00,$02,$01,$28,$01,$0D,$06
.db $A4,$15,$A0,$A5,$28,$F0,$A5,$0F,$A1,$1D,$28,$F1,$02,$01,$28,$01
.db $0B,$03,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00,$02,$01,$28,$01
.db $0D,$06,$A4,$1C,$A0,$BF,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01
.db $28,$01,$0B,$03,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00,$02,$01
.db $28,$01,$0D,$06,$A4,$15,$A0,$A5,$28,$F0,$A5,$0F,$A1,$89,$28,$F1
.db $02,$01,$28,$01,$0B,$03,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00
.db $02,$01,$28,$01,$0D,$06,$A4,$15,$A0,$A5,$28,$F0,$A5,$0F,$A1,$89
.db $28,$F1,$02,$01,$28,$01,$0B,$03,$A5,$0D,$A1,$A5,$28,$F1,$02,$01
.db $28,$00,$02,$01,$28,$01,$1A,$06,$A4,$1D,$A0,$08,$28,$F0,$A5,$0F
.db $A1,$1D,$28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06,$A4,$1D,$A0,$A5
.db $28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1D
.db $A0,$08,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1C
.db $A0,$BF,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00,$0B,$03
.db $A4,$1D,$A0,$08,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06
.db $A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$01
.db $0D,$03,$A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$01,$0D,$03,$A5,$0F
.db $A1,$1D,$28,$F1,$02,$01,$28,$01,$0D,$03,$A5,$0D,$A1,$A5,$28,$F1
.db $02,$01,$28,$01,$0D,$03,$A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$01
.db $03,$03,$A5,$0F,$A1,$1D,$28,$F1,$0A,$01,$28,$00,$02,$01,$28,$01
.db $0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01
.db $28,$00,$0D,$03,$A4,$1C,$A0,$BF,$28,$F0,$02,$01,$28,$00,$0D,$03
.db $A4,$1D,$A0,$A5,$28,$F0,$02,$01,$28,$00,$07,$03,$A4,$1F,$A0,$89
.db $28,$F0,$06,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1C,$A0,$3B
.db $28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1F
.db $A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1F
.db $A0,$89,$28,$F0,$A5,$07,$A1,$89,$28,$F1,$02,$01,$28,$01,$0B,$03
.db $A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00,$02,$01,$28,$01,$0D,$06
.db $A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$01
.db $0B,$03,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00,$02,$01,$28,$01
.db $0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01
.db $28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00,$02,$01
.db $28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$07,$A1,$89,$28,$F1
.db $02,$01,$28,$00,$0D,$03,$A4,$1C,$A0,$BF,$28,$F0,$02,$01,$28,$00
.db $0D,$03,$A4,$1D,$A0,$A5,$28,$F0,$02,$01,$28,$00,$07,$03,$A4,$1F
.db $A0,$89,$28,$F0,$06,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1C
.db $A0,$3B,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01,$28,$00,$0B,$03
.db $A4,$1F,$A0,$1D,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06
.db $A4,$1F,$A0,$89,$28,$F0,$A5,$07,$A1,$89,$28,$F1,$02,$01,$28,$01
.db $0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00,$02,$01,$28,$01
.db $0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01
.db $28,$01,$0B,$03,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00,$02,$01
.db $28,$01,$0D,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1
.db $02,$01,$28,$01,$0B,$03,$A5,$0C,$A1,$BF,$28,$F1,$02,$01,$28,$00
.db $02,$01,$28,$01,$1A,$06,$A4,$1E,$A0,$56,$28,$F0,$A5,$0D,$A1,$08
.db $28,$F1,$04,$02,$28,$00,$28,$01,$0D,$06,$A4,$1D,$A0,$A5,$28,$F0
.db $A5,$0E,$A1,$56,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1D,$A0,$08
.db $28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$0D,$06,$A4,$1C,$A0,$BF
.db $28,$F0,$A5,$0F,$A1,$89,$28,$F1,$02,$01,$28,$00,$0B,$03,$A4,$1C
.db $A0,$3B,$28,$F0,$02,$01,$28,$01,$02,$01,$28,$00,$1A,$06,$A4,$1D
.db $A0,$A5,$28,$F0,$A5,$0C,$A1,$BF,$28,$F1,$04,$02,$28,$00,$28,$01
.db $0D,$06,$A4,$1D,$A0,$08,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1,$02,$01
.db $28,$00,$0B,$03,$A4,$1C,$A0,$BF,$28,$F0,$02,$01,$28,$01,$02,$01
.db $28,$00,$0D,$06,$A4,$1C,$A0,$3B,$28,$F0,$A5,$0F,$A1,$89,$28,$F1
.db $02,$01,$28,$00,$0B,$03,$A4,$17,$A0,$89,$28,$F0,$02,$01,$28,$01
.db $02,$01,$28,$00,$0D,$06,$A4,$1C,$A0,$3B,$28,$F0,$A5,$0D,$A1,$08
.db $28,$F1,$02,$01,$28,$00,$0D,$03,$A4,$1C,$A0,$BF,$28,$F0,$02,$01
.db $28,$00,$16,$03,$A4,$15,$A0,$A5,$28,$F0,$04,$01,$28,$01,$04,$01
.db $28,$00,$1A,$06,$A4,$17,$A0,$1D,$28,$F0,$A5,$0D,$A1,$A5,$28,$F1
.db $04,$02,$28,$00,$28,$01,$1A,$06,$A4,$17,$A0,$89,$28,$F0,$A5,$0F
.db $A1,$89,$28,$F1,$04,$01,$28,$01,$1A,$03,$A5,$0D,$A1,$A5,$28,$F1
.db $04,$01,$28,$01,$12,$03,$A5,$07,$A1,$89,$28,$F1,$08,$01,$28,$00
.db $04,$01,$28,$01,$00
;; 7045 bytes in song
#include "printing.inc"
.end

View File

@@ -1398,7 +1398,7 @@ Increase by steps of 4 to select the next corresponding note.
Increase by steps of 48 to select the same note in next octave.
If the driver is able to generate the requested note, a success (0) is
returned, otherwise a non-zero error state will be returned.
returned, otherwise a non-zero error value will be returned.
The sound chip resolution and its oscillator limit the range and
accuracy of the notes played. The typical range of the AY-3-8910
@@ -1443,7 +1443,7 @@ the following HBIOS calls would need to be made:
```
HBIOS B=51 C=00 L=80 ; Set volume to half level
HBIOS B=53 C=00 L=69 ; Select Middle C (C4) assuming SN76489
HBIOS B=53 C=00 HL=152 ; Select Middle C (C4)
HBIOS B=54 C=00 D=01 ; Play note on Channel 1
```
@@ -1518,6 +1518,8 @@ AUDIO ID | Value | Device | Returned registers
SND_SN76489 | 0x01 | SN76489 | E: Left channel port, L: Right channel port
SND_AY38910 | 0x02 | AY-3-8910 | D: Address port, E: Data port
SND_BITMODE | 0x03 | I/O PORT | D: Address port, E: Bit mask
SND_YM2612 | 0x04 | YM2612 | D: Part 0 Address port, E: Part 0 Data port
| | | H: Part 1 Address port, L: Part 1 Data port
### Function 0x56 -- Sound Duration (SNDDUR)
@@ -1547,10 +1549,10 @@ and then return.
| _Exit Results_
| A: Status (0=OK, else error)
| D: Serial Device Type
| E: Serial Device Number
| H: Serial Device Unit Mode
| L: Serial Device Unit I/O Base Address
| D: Sound Device Type
| E: Sound Device Number
| H: Sound Device Unit Mode
| L: Sound Device Unit I/O Base Address
Reports information about the sound device unit specified. Register D
indicates the device type (driver) and register E indicates the physical
@@ -1565,6 +1567,7 @@ _Id_ | _Device Type / Driver_
0x00 | SN76489
0x10 | AY38910
0x20 | BITMODE
0x30 | YM2612
`\clearpage`{=latex}

View File

@@ -272,28 +272,22 @@ be VDU type devices or serial devices. If you want to change which
device is the console, the ***I*** menu option can be used to choose
the unit and it's speed.
The command format is ```I <u> [<c>]```
The command format is ```I <u> [<b>]```
where ***u*** is unit to select and ***c*** is the optional baud rate code as listed below.
where ***u*** is unit to select and ***b*** is the optional baud rate.
Supported baud rates are:
```
Code | Rate | Code | Rate | Code | Rate | Code | Rate |
------|----------|------|----------|------|----------|------|----------|
0 | 75 | 8 | 1800 | 16 | 28880 | 24 | 460800 |
1 | 150 | 9 | 2400 | 17 | 38400 | 25 | 614400 |
2 | 225 | 10 | 3600 | 18 | 57600 | 26 | 921600 |
3 | 300 | 11 | 4800 | 19 | 76800 | 27 | 1228822 |
4 | 450 | 12 | 7200 | 20 | 115200 | 28 | 1843200 |
5 | 600 | 13 | 9600 | 21 | 153600 | 29 | 2457600 |
6 | 900 | 14 | 14400 | 22 | 230400 | 30 | 3686400 |
7 | 1200 | 15 | 19200 | 23 | 307200 | 31 | 7372800 |
------------------------------------------------------------------------
75 450 1800 7200 38400 115200 460800 1843200
150 600 2400 9600 28800 153600 614400 2457600
225 900 3600 14400 57600 230400 921600 3686400
300 1200 4800 19200 76800 307200 1228800 7372800
```
Example: To change current console to 9600 baud
```
I 0 13
I 0 9600
```

View File

@@ -3725,7 +3725,7 @@ SND_ADDENT:
; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS)
;
SND_FNCNT .EQU 8 ; NUMBER OF SND FUNCS (FOR RANGE CHECK)
SND_MAX .EQU 4 ; UP TO 4 UNITS
SND_MAX .EQU 5 ; UP TO 5 UNITS
SND_SIZ .EQU SND_MAX * 4 ; EACH ENTRY IS 4 BYTES
;
.DB SND_FNCNT ; SND FUNCTION COUNT (FOR RANGE CHECK)
@@ -3737,7 +3737,7 @@ SND_TBL .FILL SND_SIZ,0 ; SPACE FOR ENTRIES
; SPEAKER BEEP ROUTINE
;==================================================================================================
;
; ROUTINE TO BEEP THE DEAULT SOUND UNIT
; ROUTINE TO BEEP THE DEFAULT SOUND UNIT
; NEED TO CHECK FOR EXISTENCE OF SOUND UNIT
; WHICH CHANNEL SHOULD BE USED? IS THERE A GOOD DEFAULT CHANNEL?
;
@@ -7041,6 +7041,7 @@ PS_SDSND .TEXT "SND$"
PS_SDSN76489 .TEXT "SN76489$"
PS_SDAY38910 .TEXT "AY-3-8910$"
PS_SDBITMODE .TEXT "I/O PORT$"
PS_SDYM2612 .TEXT "YM2612$"
;
; 0 1 2 3 4 5 6 7
; 01234567890123456789012345678901234567890123456789012345678901234567890123456789

View File

@@ -333,6 +333,7 @@ VDADEV_VGA .EQU $40 ; ECB VGA3 - HITACHI HD6445
SNDDEV_SN76489 .EQU $00
SNDDEV_AY38910 .EQU $10
SNDDEV_BITMODE .EQU $20
SNDDEV_YM2612 .EQU $30
;
; HBIOS CONTROL BLOCK OFFSETS
; WARNING: THESE OFFSETS WILL CHANGE SIGNIFICANTLY BETWEEN RELEASES

View File

@@ -499,10 +499,50 @@ setcon:
call skipws ; skip whitespace
call isnum ; do we have a number?
jp nz,docon ; if no we don't change baudrate
call getnum ; parse a number
jp c,err_invcmd ; handle overflow error
call getbnum ; return in HL:BC
;
cp 32 ; handle invalid
ld e,32 ; search baud rate table
push de ; for a matching entry
ld de,tbl_baud
nextbaud:
ex de,hl ; hl = tbl_baud, de = msw
ld a,d ; check all four bytes
cp (hl) ; against HL:BC
inc hl ; exit to next table
jr nz,mm1 ; entry on mismatch
ld a,e
cp (hl)
inc hl
jr nz,mm2
ld a,b
cp (hl)
inc hl
jr nz,mm3
ld a,c
cp (hl)
inc hl
jr nz,mm4
;
; we have a match
pop de ; get our count value
ld a,32
sub e
jr s_exit
;
mm1: inc hl
mm2: inc hl
mm3: inc hl
mm4: ex (sp),hl ; hl = count value, stack = tbl_baud, de = msw
dec l
ex (sp),hl ; hl = tbl_baud, stack= count
ex de,hl ; hl = msw, de = tbl_baud
jr nz,nextbaud
;
; Failed to match
pop de
jp err_invcmd
;
s_exit: cp 32 ; handle invalid
jp nc,err_invcmd ; baud rate
bit 0,a
jr z,iseven ; convert sequential
@@ -512,6 +552,7 @@ setcon:
iseven: dec a ; 15=19200
srl a ; 17=38400
add a,16 ; 20=115200
;
setspd: ld (newspeed),a ; save validated baud rate
;
ld hl,str_chspeed ; notify user
@@ -554,7 +595,92 @@ docon: ld hl,str_newcon ; new console msg
call nl2 ; formatting
ld hl,str_banner ; display boot banner
call pstr ; do it
ret ; done
ret
;
;=======================================================================
; Get numeric chars at DE and convert to BCD number returned in HL:BC
;=======================================================================
;
getbnum:ld bc,0 ; lsw
ld hl,0 ; msw
getbnum1:
ld a,(de) ; get the active char
cp '0' ; compare to ascii '0'
jr c,getbnum2 ; abort if below
cp '9' + 1 ; compare to ascii '9'
jr nc,getbnum2 ; abort if above
;
sub '0' ; convert '0'-'9' to 0-9
;
push de ; save char posn
push hl ; save hl bcd
;
ld hl,tmpbcd ; rotate 1 nyble in A
ld (hl),c ; through HL:BC
rld
ld c,(hl)
ld (hl),b
rld
ld b,(hl)
pop de ; get hl bcd
ld (hl),e
rld
ld e,(hl)
ld (hl),d
rld
ld d,(hl)
ld h,d
ld l,e
;
pop de ; get char posn
inc de ; bump to next char
jr getbnum1 ; loop
;
getbnum2:
or a ; with flags set, CF is cleared
ret
;
tmpbcd: .db 0
;
#DEFINE PACK(a,b,c,d,e,f,g) \
#DEFCONT \ .db (16*('0'-'0'))+(a-'0'))
#DEFCONT \ .db (16*(b-'0'))+(c-'0'))
#DEFCONT \ .db (16*(d-'0'))+(e-'0'))
#DEFCONT \ .db (16*(f-'0'))+(g-'0'))
;
tbl_baud:
PACK('0','0','0','0','0','7','5') ; 75 0 > 0
PACK('0','0','0','0','1','5','0') ; 150 1 > 1
PACK('0','0','0','0','2','2','5') ; 225 2 > 16
PACK('0','0','0','0','3','0','0') ; 300 3 > 2
PACK('0','0','0','0','4','5','0') ; 450 4 > 17
PACK('0','0','0','0','6','0','0') ; 600 5 > 3
PACK('0','0','0','0','9','0','0') ; 900 6 > 18
PACK('0','0','0','1','2','0','0') ; 1200 7 > 4
PACK('0','0','0','1','8','0','0') ; 1800 8 > 19
PACK('0','0','0','2','4','0','0') ; 2400 9 > 5
PACK('0','0','0','3','6','0','0') ; 3600 10 > 20
PACK('0','0','0','4','8','0','0') ; 4800 11 > 6
PACK('0','0','0','7','2','0','0') ; 7200 12 > 21
PACK('0','0','0','9','6','0','0') ; 9600 13 > 7
PACK('0','0','1','4','4','0','0') ; 14400 14 > 22
PACK('0','0','1','9','2','0','0') ; 19200 15 > 8
PACK('0','0','2','8','8','0','0') ; 28800 16 > 23
PACK('0','0','3','8','4','0','0') ; 38400 17 > 9
PACK('0','0','5','7','6','0','0') ; 57600 18 > 24
PACK('0','0','7','6','8','0','0') ; 76800 19 > 10
PACK('0','1','1','5','2','0','0') ; 115200 20 > 25
PACK('0','1','5','3','6','0','0') ; 153600 21 > 11
PACK('0','2','3','0','4','0','0') ; 230400 22 > 26
PACK('0','3','0','7','2','0','0') ; 307200 23 > 12
PACK('0','4','6','0','8','0','0') ; 460800 24 > 27
PACK('0','6','1','4','4','0','0') ; 614400 25 > 13
PACK('0','9','2','1','6','0','0') ; 921600 26 > 28
PACK('1','2','2','8','8','0','0') ; 1228800 27 > 14
PACK('1','8','4','3','2','0','0') ; 1843200 28 > 29
PACK('2','4','5','7','6','0','0') ; 2457600 29 > 15
PACK('3','6','8','6','4','0','0') ; 3686400 30 > 30
PACK('7','3','7','2','8','0','0') ; 7372800 31 > 31
;
#endif
;

View File

@@ -1721,7 +1721,7 @@ SD_SETUP:
OUT (SD_OPRREG),A
#ENDIF
;
#IF ((SDMODE == SDMODE_MK4) | (SDMODE == SDMODE_DSD) | (SDMODE == SDMODE_PPI)| (SDMODE == SDMODE_MT))
#IF ((SDMODE == SDMODE_MK4) | (SDMODE == SDMODE_DSD) | (SDMODE == SDMODE_PPI) | (SDMODE == SDMODE_MT))
LD A,SD_OPRDEF
LD (SD_OPRVAL),A
OUT (SD_OPRREG),A

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -2,4 +2,4 @@
#DEFINE RMN 1
#DEFINE RUP 1
#DEFINE RTP 0
#DEFINE BIOSVER "3.1.1-pre.185"
#DEFINE BIOSVER "3.1.1-pre.187"

View File

@@ -3,5 +3,5 @@ rmn equ 1
rup equ 1
rtp equ 0
biosver macro
db "3.1.1-pre.185"
db "3.1.1-pre.187"
endm