Eric
|
New snail.asm
Posted: Fri Jul 30, 1999 5:37 am
|
Below is the newest version of snail.asm. I still can not get it to work with Meka. It works correctly with Massage and BrSMS.
I've discovered that the only problem it has with Meka is that it is running too fast. Believe it or not, the garbage you will hear is the song being played at high speed. To slow it down, set DURATION_025S to $FF. Note, though, that this makes it run much too slow on other emulators.
Zoop, if possible could you please take a look at my code. I've tried everything I can, with no luck. I can only assume that Meka makes some assumption about the SMS hardware that I don't know about. Could you please explain how the VSync interrupts are generated? They seem to be occuring much more often then 1/60 (or 1/50 of a second.)
Thank you.
Eric
New snail.asm:
; Eric R. Quinn
; July 21, 1999
; snail.asm
; This program plays the theme from "Maze: The Snail Game" on SMS hardware.
; It has been tested on the emulator MASSAGE.
; Feel free to use this code as you wish. It is provided "As-is"
; Submitted to S8-Dev on July 22, 1999
#define EQU .equ
; Key offsets
;
START EQU $0000
MASKABLE_INTERRUPT_VECTOR EQU $0038
NONMASKABLE_INTERRUPT_VECTOR EQU $0066
INTERRUPT_HANDLER_OFFSET EQU $2000
MAIN EQU $1000
DATA_SEGMENT EQU $4000
HEADER_OFFSET EQU $7FF0
LAST_PAGE_OFFSET EQU $8000
; Useful definitions
;
VDP_ADDRESS_PORT EQU $BF
PSG_PORT EQU $7F
VDP_REG_WRITE EQU $80
VDP_REG_1 EQU $01
VDP_REG_0 EQU $00
VDP_REG_A EQU $0A
VDPREG1_VSYNC_FLAG EQU $20
VDPREG1_DISP_ENABLE_FLAG EQU $40
SOUND_VOLUME_WRITE EQU $90
SOUND_CHANNEL_0 EQU $00
SOUND_VOLUME_LOUDEST EQU $00
SOUND_VOLUME_OFF EQU $0F
SOUND_FREQUENCY_WRITE_LO EQU $80
SOUND_FREQUENCY_WRITE_HI EQU $00
; Frequency table
;
CONCERT_G3_LO EQU $0E
CONCERT_G3_HI EQU $13
CONCERT_GS3_LO EQU $0E
CONCERT_GS3_HI EQU $12
CONCERT_AF3_LO EQU CONCERT_GS3_LO
CONCERT_AF3_HI EQU CONCERT_GS3_HI
CONCERT_A4_LO EQU $0C
CONCERT_A4_HI EQU $11
CONCERT_AS4_LO EQU $0C
CONCERT_AS4_HI EQU $01
CONCERT_BF4_LO EQU CONCERT_AS4_LO
CONCERT_BF4_HI EQU CONCERT_AS4_HI
CONCERT_B4_LO EQU $0D
CONCERT_B4_HI EQU $0F
CONCERT_C4_LO EQU $0F
CONCERT_C4_HI EQU $0E
CONCERT_CS4_LO EQU $01
CONCERT_CS4_HI EQU $0E
CONCERT_DF4_LO EQU CONCERT_CS4_LO
CONCERT_DF4_HI EQU CONCERT_CS4_HI
CONCERT_D4_LO EQU $05
CONCERT_D4_HI EQU $0D
CONCERT_DS4_LO EQU $09
CONCERT_DS4_HI EQU $0C
CONCERT_EF4_LO EQU CONCERT_DS4_LO
CONCERT_EF4_HI EQU CONCERT_DS4_HI
CONCERT_E4_LO EQU $0E
CONCERT_E4_HI EQU $0B
CONCERT_F4_LO EQU $03
CONCERT_F4_HI EQU $0B
CONCERT_FS4_LO EQU $09
CONCERT_FS4_HI EQU $0A
CONCERT_GF4_LO EQU CONCERT_FS4_LO
CONCERT_GF4_HI EQU CONCERT_FS4_HI
CONCERT_G4_LO EQU $0F
CONCERT_G4_HI EQU $09
CONCERT_GS4_LO EQU $07
CONCERT_GS4_HI EQU $09
CONCERT_AF4_LO EQU CONCERT_GS4_LO
CONCERT_AF4_HI EQU CONCERT_GS4_HI
CONCERT_A5_LO EQU $0E
CONCERT_A5_HI EQU $08
CONCERT_AS5_LO EQU $06
CONCERT_AS5_HI EQU $08
CONCERT_BF5_LO EQU CONCERT_AS5_LO
CONCERT_BF5_HI EQU CONCERT_AS5_HI
CONCERT_B5_LO EQU $0F
CONCERT_B5_HI EQU $07
CONCERT_C5_LO EQU $07
CONCERT_C5_HI EQU $07
; Music note durations
DURATION_1S EQU 60
DURATION_05S EQU 30
DURATION_025S EQU 15
DURATION_INTRO EQU 15
DURATION_BETWEEN_NOTES EQU 1
.ORG START
; This code contains standard SMS initialization routines.
DI ; Disable Interrupts
IM 1 ; Interrupt Mode 1
LD SP, $D000 ; Initialize stack pointer
LD HL, $FFFD
LD (HL), $00 ; Map ROM page 0
INC HL
LD (HL), $01 ; Map ROM page 1
INC HL
LD (HL), $00 ; Map ROM page 0
JP MAIN
.ORG MASKABLE_INTERRUPT_VECTOR
JP INTERRUPT_HANDLER_OFFSET
.ORG NONMASKABLE_INTERRUPT_VECTOR
RETN
.ORG MAIN
; Turn off HBlank interrupt
XOR A
OUT (VDP_ADDRESS_PORT), A
LD A, VDP_REG_WRITE
OR VDP_REG_0
OUT (VDP_ADDRESS_PORT), A
; HBlank interrupts at line 255
LD A, $FF
OUT (VDP_ADDRESS_PORT), A
LD A, VDP_REG_WRITE
OR VDP_REG_A
OUT (VDP_ADDRESS_PORT), A
; Turn on VBlank interrupt
XOR A
LD A, VDPREG1_VSYNC_FLAG
OUT (VDP_ADDRESS_PORT), A
LD A, VDP_REG_WRITE
OR VDP_REG_1
OUT (VDP_ADDRESS_PORT), A
; Set up sound channel 0 volume.
;LD A, SOUND_VOLUME_WRITE
;OR SOUND_CHANNEL_0
;OR SOUND_VOLUME_LOUDEST
;OUT (PSG_PORT), A
; Set up music pointer and counters.
; HL register is pointer, BC is duration counter.
LD D, $00
LD HL, MUSIC_DATA_TABLE
LD C, $01
EI
; Start loop
MAIN_LOOP:
JR MAIN_LOOP
HALT
.ORG INTERRUPT_HANDLER_OFFSET
DI
DEC C ; Decrement duration counter
JR Z, NEXT_NOTE ; If counter is 0, then play next note
LD A, C
CP DURATION_BETWEEN_NOTES ; Play short silence between notes.
JR NZ, I_HANDLER_DONE
; Silence sound channel 0 for inter-note break.
LD A, SOUND_VOLUME_WRITE
OR SOUND_CHANNEL_0
OR SOUND_VOLUME_OFF
OUT (PSG_PORT), A
JR I_HANDLER_DONE
NEXT_NOTE:
; Turn sound channel 0 back on.
LD A, SOUND_VOLUME_WRITE
OR SOUND_CHANNEL_0
OR SOUND_VOLUME_LOUDEST
OUT (PSG_PORT), A
; Load low frequency bits
LD A, (HL)
OR SOUND_FREQUENCY_WRITE_LO
OR SOUND_CHANNEL_0
OUT (PSG_PORT), A
; Point to next byte in music data table.
; Register D contains the count of bytes accessed in music
; data table. This count is used to determine when end
; of music data is reached so song can be repeated.
INC HL
INC D
; Load high frequency bits
LD A, (HL)
OR SOUND_FREQUENCY_WRITE_HI
OR SOUND_CHANNEL_0
OUT (PSG_PORT), A
; Load duration counter.
INC HL
INC D
LD C, (HL)
INC HL
INC D
; Check if at we're at the end of the music data table.
LD A, D
CP (END_MUSIC_DATA_TABLE-MUSIC_DATA_TABLE+3)
JR NZ, I_HANDLER_DONE
; If we are set HL to point back to beginning.
; Clear D
; Set C to allow a short break between songs.
LD HL, MUSIC_DATA_TABLE
LD D, $00
LD C, DURATION_INTRO
; Silence sound channel 0.
LD A, SOUND_VOLUME_WRITE
OR SOUND_CHANNEL_0
OR SOUND_VOLUME_OFF
OUT (PSG_PORT), A
I_HANDLER_DONE:
EI
RETI
.ORG DATA_SEGMENT
; This data table contains the information necessary to play the
; theme from "Maze: The Snail Game" The data is in the form of bytes
; arranged as ordered pairs of (frequency, duration). Duration is
; measured in VBlanks. Consequently, a value of 60 for duration implies
; a note lasting one second on NTSC machines.
MUSIC_DATA_TABLE:
.DB CONCERT_C4_LO
.DB CONCERT_C4_HI
.DB DURATION_025S
.DB CONCERT_G4_LO
.DB CONCERT_G4_HI
.DB DURATION_025S
.DB CONCERT_E4_LO
.DB CONCERT_E4_HI
.DB DURATION_025S
.DB CONCERT_G4_LO
.DB CONCERT_G4_HI
.DB DURATION_025S
.DB CONCERT_F4_LO
.DB CONCERT_F4_HI
.DB DURATION_025S
.DB CONCERT_D4_LO
.DB CONCERT_D4_HI
.DB DURATION_025S
.DB CONCERT_E4_LO
.DB CONCERT_E4_HI
.DB DURATION_025S
.DB CONCERT_D4_LO
.DB CONCERT_D4_HI
.DB DURATION_025S
.DB CONCERT_C4_LO
.DB CONCERT_C4_HI
.DB DURATION_025S
.DB CONCERT_D4_LO
.DB CONCERT_D4_HI
.DB DURATION_025S
.DB CONCERT_E4_LO
.DB CONCERT_E4_HI
.DB DURATION_025S
.DB CONCERT_D4_LO
.DB CONCERT_D4_HI
.DB DURATION_025S
.DB CONCERT_G3_LO
.DB CONCERT_G3_HI
.DB DURATION_025S
.DB CONCERT_A4_LO
.DB CONCERT_A4_HI
.DB DURATION_025S
.DB CONCERT_G3_LO
.DB CONCERT_G3_HI
.DB DURATION_025S
.DB CONCERT_G3_LO
.DB CONCERT_G3_HI
.DB DURATION_025S
.DB CONCERT_C4_LO
.DB CONCERT_C4_HI
.DB DURATION_025S
.DB CONCERT_G4_LO
.DB CONCERT_G4_HI
.DB DURATION_025S
.DB CONCERT_E4_LO
.DB CONCERT_E4_HI
.DB DURATION_025S
.DB CONCERT_G4_LO
.DB CONCERT_G4_HI
.DB DURATION_025S
.DB CONCERT_F4_LO
.DB CONCERT_F4_HI
.DB DURATION_025S
.DB CONCERT_D4_LO
.DB CONCERT_D4_HI
.DB DURATION_025S
.DB CONCERT_E4_LO
.DB CONCERT_E4_HI
.DB DURATION_025S
.DB CONCERT_D4_LO
.DB CONCERT_D4_HI
.DB DURATION_025S
.DB CONCERT_E4_LO
.DB CONCERT_E4_HI
.DB DURATION_025S
.DB CONCERT_D4_LO
.DB CONCERT_D4_HI
.DB DURATION_025S
.DB CONCERT_C4_LO
.DB CONCERT_C4_HI
.DB DURATION_025S
.DB CONCERT_B4_LO
.DB CONCERT_B4_HI
.DB DURATION_025S
.DB CONCERT_C4_LO
.DB CONCERT_C4_HI
.DB DURATION_025S
.DB CONCERT_C4_LO
.DB CONCERT_C4_HI
.DB DURATION_025S
.DB CONCERT_C4_LO
.DB CONCERT_C4_HI
.DB DURATION_025S
END_MUSIC_DATA_TABLE:
.ORG HEADER_OFFSET
.DB "TMR MESA" ; Tradmark
.DW 9919h ; Year
.DW 0000h ; Checksum not correct
.DW 0000h ; Part Num not correct
.DW 2107h ; Day / Month
.ORG LAST_PAGE_OFFSET
.END
Eric
|