Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
Moderator: Moderators
- PacManPlus
- Posts: 26
- Joined: Mon Jun 20, 2016 7:56 am
Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
Hi:
Just a curiosity question here. I am porting a game that I developed (an arcade port) on the Atari 7800 over to the NES. I'd like to use the same sounds that I created on the 7800, but I am having great difficulty. (The Atari 7800 uses the same TIA as the Atari 2600)
I've adapted the sound driver that I used for the 7800 TIA over to the NES, and expanded it (from the 2 channels of the TIA to the 4 - two square, one triangle and one noise) for the 2A03.
Is there any conversion chart available for notes and noises from one to the other? I did a Google search but found nothing.
I understand they won't sound exactly the same of course... I was hoping for 'close enough'.
Thank you for your help...
Bob
Just a curiosity question here. I am porting a game that I developed (an arcade port) on the Atari 7800 over to the NES. I'd like to use the same sounds that I created on the 7800, but I am having great difficulty. (The Atari 7800 uses the same TIA as the Atari 2600)
I've adapted the sound driver that I used for the 7800 TIA over to the NES, and expanded it (from the 2 channels of the TIA to the 4 - two square, one triangle and one noise) for the 2A03.
Is there any conversion chart available for notes and noises from one to the other? I did a Google search but found nothing.
I understand they won't sound exactly the same of course... I was hoping for 'close enough'.
Thank you for your help...
Bob
Last edited by PacManPlus on Mon Aug 01, 2016 10:52 am, edited 1 time in total.
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
I think you could fit every 7800 programmer in the world in a small closet. You might literally be the only person who's considering porting music from 7800 to NES.
You may have to start from scratch.
You may have to start from scratch.
nesdoug.com -- blog/tutorial on programming for the NES
- PacManPlus
- Posts: 26
- Joined: Mon Jun 20, 2016 7:56 am
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
Lol, I know. I've done a bunch of arcade ports to the 7800: Astro Fighter, Astro Blaster, Jr. Pac-Man, Super Pac-Man, Rip-Off, Scramble, Berzerk/Frenzy (this is the one I'm trying to port to the NES - I'm just down to sound), Space Duel, Asteroids Deluxe, Space Invaders, etc.. and some 'originals'.dougeff wrote:I think you could fit every 7800 programmer in the world in a small closet. You might literally be the only person who's considering porting music from 7800 to NES.
You may have to start from scratch.
That's why I mentioned that it uses the same sound chip as the 2600.
Thanks,
Bob
- mikejmoffitt
- Posts: 1353
- Joined: Sun May 27, 2012 8:43 pm
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
Principally, aren't both chips implementing the notes as periods to load a counter with? You should be able to apply some coefficient to your load values (and the 2A03 channels are 11-bit, not the 8-bit resolution of the TIA ones) and then it may "just work".
- PacManPlus
- Posts: 26
- Joined: Mon Jun 20, 2016 7:56 am
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
Ok, I found a TIA note chart, so I'll look for a 2A03 note chart as well and do the connections myself.
This wasn't my major concern, however, as sound effects make up 99% of the audio (I just have one short tune at the splash screen). I liked the sounds I had come up with on the 7800 for the shot, explosion, and death, and I wanted to approximate them as close as possible here. If anyone can help with that, it would be great. I dislike re-inventing the wheel.
I also have the voice sample data that I used for the 7800 version as well, and I'll use some of it here once I figure out the Digital channel. The only thing is I'll be cutting some of the speech out as I don't have room for it all (it's 22K for the speech data alone on the 7800 version). I'm trying to keep this at Mapper 0 so as you know I only have 32K total.
Thanks,
Bob
This wasn't my major concern, however, as sound effects make up 99% of the audio (I just have one short tune at the splash screen). I liked the sounds I had come up with on the 7800 for the shot, explosion, and death, and I wanted to approximate them as close as possible here. If anyone can help with that, it would be great. I dislike re-inventing the wheel.
I also have the voice sample data that I used for the 7800 version as well, and I'll use some of it here once I figure out the Digital channel. The only thing is I'll be cutting some of the speech out as I don't have room for it all (it's 22K for the speech data alone on the 7800 version). I'm trying to keep this at Mapper 0 so as you know I only have 32K total.
Thanks,
Bob
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
As you know, the TIA has two channels; each with its own 4-bit volume channel and its own 5-bit frequency divider. Additionally, each channel is limited to one of 16 [tone color and additional frequency divider] choices.
So, ignoring tone color, you can convert the frequency divider (AUDFx) and tone color (AUDCx) to a pure frequency by saying
31400Hz ÷ (AUDFx+1) ÷ table[AUDCx] (table[n] is [inf,15,465,465,2,2,31,31,511,31,31,inf,6,6,93,93].)
In contrast, the NES's pulse wave frequencies are the simpler
111861Hz ÷ divider
and its triangle wave is that÷2.
The math is straightforward, at that point.
Now, compensating for tone color is a good deal more annoying.
Each of the TIA's channels can produce one of eight different tone colors. The NES's tone colors are divided more by channel:
• The two pulse wave channels can make one of three tone colors.
• The triangle channel can make one tone color, but approximately has no volume control
• The noise channel can make two tone colors, but one is random.
Sitting down with the 2600 docs and an FFT, the mapping is approximately:
AUDCx=0,B - silence
AUDCx=1 - LFSR equivalent to 1/15th duty pulse wave; closest match is pulse wave channel 1/8th duty
AUDCx=2 - very approximately the same as =1
AUDCx=3 - too complex for an analog
AUDCx=4,5,C,D - square wave. NES pulse waves support identical
AUDCx=6,A,E - 42% or 68% duty cycle pulse wave. Equally close to the NES's 1/4 and 1/2 duty cycle pulse.
AUDCx=7,9,F - LFSR equivalent to 1/31st duty pulse wave; no good match on the NES (closest is again 1/8th)
AUDCx=8 - 9-bit LFSR white noise. Closest is NES's 15-bit LFSR white noise
There's also this document from someone who used a 2600 as an instrument in a band.
edit#1: give up on summarizing AUDCx=3
edit#2: fix off-by-one
edit#3: fix typo of register name
So, ignoring tone color, you can convert the frequency divider (AUDFx) and tone color (AUDCx) to a pure frequency by saying
31400Hz ÷ (AUDFx+1) ÷ table[AUDCx] (table[n] is [inf,15,465,465,2,2,31,31,511,31,31,inf,6,6,93,93].)
In contrast, the NES's pulse wave frequencies are the simpler
111861Hz ÷ divider
and its triangle wave is that÷2.
The math is straightforward, at that point.
Now, compensating for tone color is a good deal more annoying.
Each of the TIA's channels can produce one of eight different tone colors. The NES's tone colors are divided more by channel:
• The two pulse wave channels can make one of three tone colors.
• The triangle channel can make one tone color, but approximately has no volume control
• The noise channel can make two tone colors, but one is random.
Sitting down with the 2600 docs and an FFT, the mapping is approximately:
AUDCx=0,B - silence
AUDCx=1 - LFSR equivalent to 1/15th duty pulse wave; closest match is pulse wave channel 1/8th duty
AUDCx=2 - very approximately the same as =1
AUDCx=3 - too complex for an analog
AUDCx=4,5,C,D - square wave. NES pulse waves support identical
AUDCx=6,A,E - 42% or 68% duty cycle pulse wave. Equally close to the NES's 1/4 and 1/2 duty cycle pulse.
AUDCx=7,9,F - LFSR equivalent to 1/31st duty pulse wave; no good match on the NES (closest is again 1/8th)
AUDCx=8 - 9-bit LFSR white noise. Closest is NES's 15-bit LFSR white noise
There's also this document from someone who used a 2600 as an instrument in a band.
edit#1: give up on summarizing AUDCx=3
edit#2: fix off-by-one
edit#3: fix typo of register name
Last edited by lidnariq on Tue Aug 02, 2016 6:49 pm, edited 3 times in total.
- PacManPlus
- Posts: 26
- Joined: Mon Jun 20, 2016 7:56 am
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
This is awesome - thank you so much!
- PacManPlus
- Posts: 26
- Joined: Mon Jun 20, 2016 7:56 am
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
Ugh.
I am so lost with this. The TIA and even the Pokey is so straight-forward when making music / sound effects, and the 2A03 is so.... not.
I was trying to use the FamiTracker to get a sound (I downloaded some sound effects from the web), and I tried to convert them to the sound driver I'm using (I have a custom sound driver which I adapted from what I use for the TIA).
This is a quick description of how it is coded:
It reads 3 bytes per delta - Control/Volume, Note Low Byte, Frame Count / Note High Byte
Being that I'm using the Noise Channel, I am ignoring the 'Control' part of the first byte, and just using the Volume ORAing it with #$30 to turn off internal counters and writing that to $400C.
I am writing the second byte (the Sound Low Byte) to $400E.
I am extracting the Frame Count from the 2nd byte, so I know how many frames to play the current sound. There are only 16 sound types, so I am ignoring the Note High Byte from here.
I read somewhere on here that we have to put a non-zero byte in $400F, so I am forcing a '$01' there.
I am trying to get this data written as an example (so I know how to convert the sounds to my driver):
This is how I am doing it for both TIA and Pokey, and it works there. For the 2A03, I seem to get only one sound (the shhhhhhhhhhhh sound).
I've tried the Low Bytes with and without the high bit set (for Mode-0 or Mode-1)
I've also checked the contents to make sure I was writing the values that I think I'm writing, and they are correct.
Does anyone know what I am doing wrong to not be able to get the sound like I've shown above?
This is my data:
Thank you, thank you, thank you all for any help.
Bob
I am so lost with this. The TIA and even the Pokey is so straight-forward when making music / sound effects, and the 2A03 is so.... not.
I was trying to use the FamiTracker to get a sound (I downloaded some sound effects from the web), and I tried to convert them to the sound driver I'm using (I have a custom sound driver which I adapted from what I use for the TIA).
This is a quick description of how it is coded:
It reads 3 bytes per delta - Control/Volume, Note Low Byte, Frame Count / Note High Byte
Being that I'm using the Noise Channel, I am ignoring the 'Control' part of the first byte, and just using the Volume ORAing it with #$30 to turn off internal counters and writing that to $400C.
I am writing the second byte (the Sound Low Byte) to $400E.
I am extracting the Frame Count from the 2nd byte, so I know how many frames to play the current sound. There are only 16 sound types, so I am ignoring the Note High Byte from here.
I read somewhere on here that we have to put a non-zero byte in $400F, so I am forcing a '$01' there.
I am trying to get this data written as an example (so I know how to convert the sounds to my driver):
Code: Select all
PATTERN 00
ROW 00 : ... .. . ... : ... .. . ... : ... .. . ... : 5-# 00 D F01 : ... .. . ...
ROW 01 : ... .. . ... : ... .. . ... : ... .. . ... : 4-# 00 C ... : ... .. . ...
ROW 02 : ... .. . ... : ... .. . ... : ... .. . ... : 3-# 00 B F02 : ... .. . ...
ROW 03 : ... .. . ... : ... .. . ... : ... .. . ... : 2-# 00 A ... : ... .. . ...
ROW 04 : ... .. . ... : ... .. . ... : ... .. . ... : 1-# 00 9 F03 : ... .. . ...
ROW 05 : ... .. . ... : ... .. . ... : ... .. . ... : 0-# 00 8 ... : ... .. . ...
ROW 06 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 7 F04 : ... .. . ...
ROW 07 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 6 ... : ... .. . ...
ROW 08 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 5 F05 : ... .. . ...
ROW 09 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 4 ... : ... .. . ...
ROW 0A : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 3 F06 : ... .. . ...
ROW 0B : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 2 ... : ... .. . ...
ROW 0C : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 1 F07 : ... .. . ...
ROW 0D : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 0 ... : ... .. . ...
ROW 0E : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ...
ROW 0F : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ...
I've tried the Low Bytes with and without the high bit set (for Mode-0 or Mode-1)
I've also checked the contents to make sure I was writing the values that I think I'm writing, and they are correct.
Does anyone know what I am doing wrong to not be able to get the sound like I've shown above?
This is my data:
Code: Select all
; FREQUENCY LOW BYTE - LOW BYTE OF NOTE (LFTUNEXX)
; FRAME/FREQUENCY - BIT 76543XXX CONTROL THE NUMBER OF FRAMES, BIT XXXXX210 CONTAIN THE HIGH BYTE OF NOTE (FHTUNEXX)
; VOICE/VOLUME - BITS 76--XXXX CONTAIN THE VOICE CONTROL, BITS XX--3210 CONTAIN THE VOLUME (CVTUNEXX)
; $00 IN ALL THREE BYTES ENDS THE SOUND
; TEMPOS
T01 = $00
T02 = $08
T03 = $10
T04 = $18
T05 = $20
T06 = $28
T07 = $30
T08 = $38
LFTUNE02:
.byte $05,$04,$03,$02,$01,$00,$00,$00
.byte $00,$00,$00,$00,$00,$00,$00,$00
FHTUNE02:
.byte T01,T01,T02,T02,T03,T03,T04,T04
.byte T05,T05,T06,T06,T07,T07,$00,$00
CVTUNE02:
.byte $0D,$0C,$0B,$0A,$09,$08,$07,$06
.byte $05,$04,$03,$02,$01,$00,$00,$00
Bob
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
One: on the 2A03, white noise (analogous to AUDCn = 8) can only come out of the 4th ("noise") channel, and the 4th noise channel usually only produces white noise (the NES's noise channel has a tonal noise mode, but the harmonic content you get out is practically random: a function of the LFSR's exact contents when it's switched to tonal noise mode)
Two: The NES's white noise channel is fairly constrained. Unlike the two pulse wave channels and the triangle wave channel, it's restricted to one of sixteen frequencies ( http://wiki.nesdev.com/w/index.php/APU_Noise ).
LFSR white noise sources (like in the AY-8910, 2A03, VIC-1, SN76489, TIA) clocked at sample rate X are approximately equivalent to an ideal white noise source followed by a first-order lowpass filter at that same frequency.
So, with the TIA, the sixteen corner frequencies are 31400 Hz ÷ (1,2,3,…32) = (31400, 15700, 10466,…980)Hz, but on the NES it's restricted to instead a relatively constrained (and oddly musically related) set of periods going both much higher (rate 0 = period 4 = 447kHz) and lower (rate $F = period 4068 = 440Hz)
The NES noise channel periods corresponding to the TIA's range are values $4 ( rate 28kHz ≈ AUDFn=0@31kHz) through $E (rate 880Hz ≈ AUDFn=31@980Hz)
Two: The NES's white noise channel is fairly constrained. Unlike the two pulse wave channels and the triangle wave channel, it's restricted to one of sixteen frequencies ( http://wiki.nesdev.com/w/index.php/APU_Noise ).
LFSR white noise sources (like in the AY-8910, 2A03, VIC-1, SN76489, TIA) clocked at sample rate X are approximately equivalent to an ideal white noise source followed by a first-order lowpass filter at that same frequency.
So, with the TIA, the sixteen corner frequencies are 31400 Hz ÷ (1,2,3,…32) = (31400, 15700, 10466,…980)Hz, but on the NES it's restricted to instead a relatively constrained (and oddly musically related) set of periods going both much higher (rate 0 = period 4 = 447kHz) and lower (rate $F = period 4068 = 440Hz)
The NES noise channel periods corresponding to the TIA's range are values $4 ( rate 28kHz ≈ AUDFn=0@31kHz) through $E (rate 880Hz ≈ AUDFn=31@980Hz)
- PacManPlus
- Posts: 26
- Joined: Mon Jun 20, 2016 7:56 am
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
Thank you for that, and I think I get most of it, but I guess putting it into use is the part that I am not understanding.
I.E. my thing is, to get the above data:
What would be the bytes written to $400C and $400E (assuming $400F is constant at #$01)? I am not using the internal length counter (I have it disabled). I am keeping track of the number of frames myself, and writing to these registers once per frame. If I write what I *think* these values translate to (see my data in my previous post), I get just a 'plink' when mode = 1 and a 'shhhhhh' when mode = 0. In other words, nothing like what plays in Tracker.
I'm just trying to figure out what I am translating incorrectly.
Again, thank you, and I'm sorry that I am having a hard time with this.
Bob
I.E. my thing is, to get the above data:
Code: Select all
PATTERN 00
ROW 00 : ... .. . ... : ... .. . ... : ... .. . ... : 5-# 00 D F01 : ... .. . ...
ROW 01 : ... .. . ... : ... .. . ... : ... .. . ... : 4-# 00 C ... : ... .. . ...
ROW 02 : ... .. . ... : ... .. . ... : ... .. . ... : 3-# 00 B F02 : ... .. . ...
ROW 03 : ... .. . ... : ... .. . ... : ... .. . ... : 2-# 00 A ... : ... .. . ...
ROW 04 : ... .. . ... : ... .. . ... : ... .. . ... : 1-# 00 9 F03 : ... .. . ...
ROW 05 : ... .. . ... : ... .. . ... : ... .. . ... : 0-# 00 8 ... : ... .. . ...
ROW 06 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 7 F04 : ... .. . ...
ROW 07 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 6 ... : ... .. . ...
ROW 08 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 5 F05 : ... .. . ...
ROW 09 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 4 ... : ... .. . ...
ROW 0A : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 3 F06 : ... .. . ...
ROW 0B : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 2 ... : ... .. . ...
ROW 0C : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 1 F07 : ... .. . ...
ROW 0D : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 0 ... : ... .. . ...
ROW 0E : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ...
ROW 0F : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ...
I'm just trying to figure out what I am translating incorrectly.
Again, thank you, and I'm sorry that I am having a hard time with this.
Bob
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
There's nothing too mystical about the noise channel if you disable the envelope and stop the length counter. Just make sure to reload the length counter after you stop it, so that it will have non-zero value.
Show some code, maybe?
Show some code, maybe?
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
- PacManPlus
- Posts: 26
- Joined: Mon Jun 20, 2016 7:56 am
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
Thank you for the reply. Here is the sound code I am using (please remember, it's adapted from the TIA driver I use):
First, here is a video of the sound in FamiTracker, then what I get when I use 'Mode 0', and then 'Mode 1':
https://youtu.be/UUA6iNb8gFU
The sounds I will eventually try to replicate (once I figure this example out) are attached.
First, here is a video of the sound in FamiTracker, then what I get when I use 'Mode 0', and then 'Mode 1':
https://youtu.be/UUA6iNb8gFU
The sounds I will eventually try to replicate (once I figure this example out) are attached.
Code: Select all
; TUNE ROUTINES ------------------------------------------------------------------------------------------------------------>
AUDC0T EQU $4000 ;Audio Control / Volume Channel 0
AUDF0T EQU $4002 ;Audio Frequency Channel 0
; INITIALIZE SOUND HARDWARE
INITTUN
LDA #$1F ;ENABLE ALL CHANNELS (SQUARE1, SQUARE2, TRIANGLE, NOISE, DIGITAL)
STA $4015
LDA #$00 ;SILENCE ALL CHANNELS
STA AUDF0T+$00
STA AUDC0T+$00
STA AUDF0T+$04
STA AUDC0T+$04
STA AUDF0T+$08
STA AUDC0T+$08
STA AUDF0T+$0C
STA AUDC0T+$0C
RTS
; TURN OFF ALL SOUNDS
STOPTUN
LDA #$00 ;TURN OFF SOUNDS
STA AUDF0T+$00
STA AUDC0T+$00
STA AUDF0T+$04
STA AUDC0T+$04
STA AUDF0T+$08
STA AUDC0T+$08
STA AUDF0T+$0C
STA AUDC0T+$0C
LDA #$01
STA TUNOFF
RTS
; TURN ON ALL SOUNDS
STARTTUN
LDA #$00
STA TUNOFF
RTS
; THIS ROUTINE ERASES ALL TUNES
; X AND Y ARE PRESERVED
CLEARTUN
TXA ;STACK REGISTERS
PHA
TYA
PHA
LDX #$03
CTLOOP
JSR ENDTUNE ;ERASE CURRENT TUNE
DEX
BPL CTLOOP
PLA ;UNSTACK REGISTERS
TAY
PLA
TAX
RTS
; ROUTINE TO KILL A PARTICULAR TUNE - IF IT IS RUNNING
; INPUT: TUNE NUMBER IN A
; X AND Y ARE PRESERVED
KILLTUNE
STA TUNNUM ;SAVE IT
TXA ;STACK REGISTERS
PHA
TYA
PHA
LDX #$03 ;CHECK ALL CHANNELS
KTLOOP
LDA TUNON,X ;SEE IF CHANNEL ON
BEQ KTNEXT
LDA TUNINDEX,X ;SEE IF HAS TUNE TO BE KILLED
CMP TUNNUM
BNE KTNEXT
JSR ENDTUNE ;ERASE IT
KTNEXT
DEX
BPL KTLOOP
PLA ;UNSTACK REGISTERS
TAY
PLA
TAX
RTS
; THIS ROUTINE CLEARS OUT A TUNE CHANNEL
; INPUT: X IS CHANNEL
ENDTUNE
LDA #$00
STA TUNON,X ;INDICATE CHANNEL CLEAR
STA TUNINDEX,X ;CLEAR TUNE INDEX
TXA
ASL A
ASL A
TAY
LDA #$00
STA AUDF0T,Y ;SILENCE THE CHANNEL
STA AUDC0T,Y
RTS
; THIS ROUTINE ENTERS A TUNE INTO ONE OF THE SOUND CHANNELS IF IT CAN
; INPUT: TUNE NUMBER IN A
; X AND Y ARE PRESERVED
DOTUNE
BMI DTEXIT ;$FF MEANS NO TUNE (FOR TABLE READS)
STA TUNNUM ;SAVE IT
;LDA AUTOPLAY ;IF IN AUTOPLAY - NO SOUND
;BEQ DTCONT
;RTS
DTCONT
TXA ;STACK REGISTERS
PHA
TYA
PHA
LDY TUNNUM ;SEE IF WE CAN PUT IT IN
LDX TUNCHANNL,Y ;GET WHAT CHANNEL TO TRY TO PUT IT IN
LDA TUNON,X ;SEE IF CHANNEL OPEN
BEQ DTDOIT
LDA TUNPRIRTY,Y ;SEE IF WE CAN BUMP CHANNEL
CMP TUNPRIOR,X
BMI DTOUT
DTDOIT
LDA TUNNUM
TAY ;PUT TUNE IN Y
STA TUNINDEX,X ;SET THE TUNE INDEX
LDA #$00 ;TURN TUNE OFF WHILE CHANGING IT
STA TUNON,X
LDA TUNLOWFRQL,Y ;GET LOW BYTE OF FREQUENCY LOW ADDRESS
STA LOWFRQL,X
LDA TUNLOWFRQH,Y ;GET LOW BYTE OF FREQUENCY HIGH ADDRESS
STA LOWFRQH,X
LDA TUNFRMFRQL,Y ;GET TUNE DURATION AND FREQUENCY LOW ADDRESS
STA FRMFRQL,X
LDA TUNFRMFRQH,Y ;GET TUNE DURATION AND FREQUENCY HIGH ADDRESS
STA FRMFRQH,X
LDA TUNCTLVOLL,Y ;GET TUNE CNTL AND VOLUME LOW ADDRESS
STA CTLVOLL,X
LDA TUNCTLVOLH,Y ;GET TUNE CNTL AND VOLUME HIGH ADDRESS
STA CTLVOLH,X
LDA TUNPRIRTY,Y ;SET PRIORITY
STA TUNPRIOR,X
LDA #$01 ;SET FREQ, CTL, AND VOL TO BE SET
STA TUNFRM,X
STA TUNON,X ;AND TURN THE TUNE ON!
DTOUT
PLA ;UNSTACK REGISTERS
TAY
PLA
TAX
DTEXIT
RTS
; THIS ROUTINE IS CALLED EVERY VBLANK TO TAKE CARE OF TUNES
; REGISTERS ARE NOT SAVED
TUNER
LDX #$03 ;TWO TUNES CHANNELS, START WITH LAST
LDA TUNOFF
BEQ TUNLOOP
RTS
TUNLOOP
LDA TUNON,X
BNE TUNBODY
TXA
ASL A
ASL A
TAY
LDA #$00
STA AUDC0T,Y ;IF THE CHANNEL IS OFF - MAKE SURE VOLUME IS OFF
JMP TUNNEXT
TUNBODY
DEC TUNFRM,X ;SEE IF WE'RE DONE WITH THIS SOUND
BEQ TUNCTLVOL
JMP TUNNEXT ;NOPE, CONTINUE
TUNCTLVOL
LDA CTLVOLL,X ;GET THE CURRENT DUTY CYCLE / VOLUME BYTE
STA SOUNDZP
LDA CTLVOLH,X
STA SOUNDZP+1
LDY #$00
LDA [SOUNDZP],Y
BEQ TUNEND ;$00 HERE MEANS END OF TUNE
ORA #$30 ;FORCE BITS 4 AND 5 TO BE ON (WE CONTROL FRAMES AND VOLUME)
PHA
TXA ;MAKE 'Y' AN INDEX INTO THE SOUND REGISTERS
ASL A
ASL A
TAY
PLA
STA AUDC0T,Y ;STORE CONTROL
INC CTLVOLL,X
BNE TUNFRMFRQ
INC CTLVOLH,X
TUNFRMFRQ
LDY #$00
LDA LOWFRQL,X ;GET THE LOW PERIOD ADDRESS
STA SOUNDZP
LDA LOWFRQH,X
STA SOUNDZP+1
LDA [SOUNDZP],Y ;NOW GET THE LOW BYTE OF THE PERIOD
STA SOUNDTEMP
LDA FRMFRQL,X ;GET THE DURATION / HIGH PERIOD ADDRESS
STA SOUNDZP
LDA FRMFRQH,X
STA SOUNDZP+1
LDA [SOUNDZP],Y ;GET THE CURRENT DURATION / HIGH PERIOD BYTE
STA SOUNDTEMP+1
TXA ;MAKE 'Y' AN INDEX INTO THE SOUND REGISTERS
ASL A
ASL A
TAY
LDA SOUNDTEMP
STA AUDF0T,Y ;STORE FREQUENCY
LDA SOUNDTEMP+1
CPX #$03 ;WE NEED TO WRITE A DUMMY VALUE TO $400F IF WE ARE ON THE NOISE CHANNEL
BNE TUNNOTANOISE
LDA #$01
TUNNOTANOISE
AND #$07 ;GET LOW THREE BITS OF THE HIGH FREQUENCY BYTE
STA AUDF0T+1,Y
CPX #$02 ;IF TRIANGLE OR NOISE, SKIP THIS PART
BPL TUNSKIPTN
LDA #$08
STA AUDC0T+1,Y
TUNSKIPTN
LDA SOUNDTEMP+1 ;NOW EXTRACT THE NUMBER OF FRAMES
LSR A
LSR A
LSR A
STA TUNFRM,X ;STORE DURATION (IN FRAMES)
INC TUNFRM,X ;WE NEED THIS BECAUSE THE DURATION GETS DECREMENTED FIRST
INC LOWFRQL,X
BNE TUNNXT1
INC LOWFRQH,X
TUNNXT1
INC FRMFRQL,X
BNE TUNNEXT
INC FRMFRQH,X
TUNNEXT
DEX
BMI TUNEXIT
JMP TUNLOOP
TUNEXIT
RTS
TUNEND
LDA FRMFRQL,X ;SEE IF WE SHOULD REPEAT
STA SOUNDZP
LDA FRMFRQH,X
STA SOUNDZP+1
LDY #$00
LDA [SOUNDZP],Y
BMI TUNRESTART
JSR ENDTUNE
JMP TUNNEXT
TUNRESTART
LDA TUNINDEX,X ;GET TUNE NUMBER
TAY
LDA TUNLOWFRQL,Y ;GET LOW BYTE OF FREQUENCY LOW ADDRESS
STA LOWFRQL,X
LDA TUNLOWFRQH,Y ;GET LOW BYTE OF FREQUENCY HIGH ADDRESS
STA LOWFRQH,X
LDA TUNFRMFRQL,Y ;GET TUNE DURATION AND FREQUENCY LOW ADDRESS
STA FRMFRQL,X
LDA TUNFRMFRQH,Y ;GET TUNE DURATION AND FREQUENCY HIGH ADDRESS
STA FRMFRQH,X
LDA TUNCTLVOLL,Y ;GET TUNE CNTL AND VOLUME LOW ADDRESS
STA CTLVOLL,X
LDA TUNCTLVOLH,Y ;GET TUNE CNTL AND VOLUME HIGH ADDRESS
STA CTLVOLH,X
LDA #$01 ;SET FREQ, CTL, AND VOL TO BE SET
STA TUNFRM,X
JMP TUNNEXT
; TUNE TABLES, BASE ADDRESSES FOR TUNES AND THE OFFSETS WITHIN THE TUNES WHERE
; THE CTL AND VOL INFORMATION START
TUNLOWFRQL
.byte LOW(LFTUNE00),LOW(LFTUNE01),LOW(LFTUNE02),LOW(LFTUNE03)
.byte LOW(LFTUNE04),LOW(LFTUNE05),LOW(LFTUNE06),LOW(LFTUNE07)
.byte LOW(LFTUNE08),LOW(LFTUNE09);,LOW(LFTUNE0A),LOW(LFTUNE0B)
TUNLOWFRQH
.byte HIGH(LFTUNE00),HIGH(LFTUNE01),HIGH(LFTUNE02),HIGH(LFTUNE03)
.byte HIGH(LFTUNE04),HIGH(LFTUNE05),HIGH(LFTUNE06),HIGH(LFTUNE07)
.byte HIGH(LFTUNE08),HIGH(LFTUNE09);,HIGH(LFTUNE0A),HIGH(LFTUNE0B)
TUNFRMFRQL
.byte LOW(FHTUNE00),LOW(FHTUNE01),LOW(FHTUNE02),LOW(FHTUNE03)
.byte LOW(FHTUNE04),LOW(FHTUNE05),LOW(FHTUNE06),LOW(FHTUNE07)
.byte LOW(FHTUNE08),LOW(FHTUNE09);,LOW(FHTUNE0A),LOW(FHTUNE0B)
TUNFRMFRQH
.byte HIGH(FHTUNE00),HIGH(FHTUNE01),HIGH(FHTUNE02),HIGH(FHTUNE03)
.byte HIGH(FHTUNE04),HIGH(FHTUNE05),HIGH(FHTUNE06),HIGH(FHTUNE07)
.byte HIGH(FHTUNE08),HIGH(FHTUNE09);,HIGH(FHTUNE0A),HIGH(FHTUNE0B)
TUNCTLVOLL
.byte LOW(CVTUNE00),LOW(CVTUNE01),LOW(CVTUNE02),LOW(CVTUNE03)
.byte LOW(CVTUNE04),LOW(CVTUNE05),LOW(CVTUNE06),LOW(CVTUNE07)
.byte LOW(CVTUNE08),LOW(CVTUNE09);,LOW(CVTUNE0A),LOW(CVTUNE0B)
TUNCTLVOLH
.byte HIGH(CVTUNE00),HIGH(CVTUNE01),HIGH(CVTUNE02),HIGH(CVTUNE03)
.byte HIGH(CVTUNE04),HIGH(CVTUNE05),HIGH(CVTUNE06),HIGH(CVTUNE07)
.byte HIGH(CVTUNE08),HIGH(CVTUNE09);,HIGH(CVTUNE0A),HIGH(CVTUNE0B)
; TUNE CHANNEL TABLE - DEFINES WHICH CHANNEL THE TUNE BELONGS IN, INDEXED BY TUNE NUMBER
TUNCHANNL
.byte $00,$01,$03,$03,$00,$01,$01,$00
.byte $00,$00,$00,$00,$00,$00,$00,$00
; TUNE PRIORITTY TABLE - DEFINES WHICH TUNES HAVE PRIORITY OVER OTHERS, INDEXED BY TUNE NUMBER
TUNPRIRTY
.byte $00,$00,$04,$04,$0D,$0D,$08,$04
.byte $04,$0F,$00,$00,$00,$00,$00,$00
; DATA FOR TUNES
; PRIORITY - FOUND IN TABLE ABOVE, INDEXED BY TUNE NUMBER
; CHANNEL - FOUND IN TABLE ABOVE, INDEXED BY TUNE NUMBER
; FREQUENCY LOW BYTE - LOW BYTE OF NOTE (LFTUNEXX)
; FRAME/FREQUENCY - BIT 76543XXX CONTROL THE NUMBER OF FRAMES, BIT XXXXX210 CONTAIN THE HIGH BYTE OF NOTE (FHTUNEXX)
; VOICE/VOLUME - BIT 76--XXXX CONTAIN THE VOICE CONTROL, BIT XX--3210 CONTAIN THE VOLUME (CVTUNEXX)
; $00 IN VOICE/VOLUME ENDS THE SOUND
; TEMPOS
T01 = $00
T02 = $08
T03 = $10
T04 = $18
T05 = $20
T06 = $28
T07 = $30
T08 = $38
LFTUNE02: ; PLAYER SHOT
.byte $05,$04,$03,$02,$01,$00,$00,$00
.byte $00,$00,$00,$00,$00,$00,$00,$00
FHTUNE02: ; PLAYER SHOT
.byte T01,T01,T02,T02,T03,T03,T04,T04
.byte T05,T05,T06,T06,T07,T07,$00,$00
CVTUNE02:
.byte $0D,$0C,$0B,$0A,$09,$08,$07,$06
.byte $05,$04,$03,$02,$01,$00,$00,$00
- Attachments
-
- RobotShot.mp3
- (17.99 KiB) Downloaded 263 times
-
- RobotExplosion.mp3
- (15.54 KiB) Downloaded 256 times
-
- PlayerShot.mp3
- (29.01 KiB) Downloaded 261 times
- PacManPlus
- Posts: 26
- Joined: Mon Jun 20, 2016 7:56 am
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
Ok, I think I know what was going on...
If you look at the FamiTracker data,
...the '5, 4, 3, 2, 1' down the left-hand side is actually the inverse of what the data is, for some reason. I had to use $8A,$8B,$8C,$8D,$8E, and $8F. Also, I thought the $00 in the second column was the mode, and I guess it isn't, because I had to use Mode-1 to get that sound (hence the $8X in my listed values above)...
Strange.
So, it looks like the third column is the volume, and the fourth is the number of frames per sound.
At least I have a starting point now.
Bob
If you look at the FamiTracker data,
Code: Select all
PATTERN 00
ROW 00 : ... .. . ... : ... .. . ... : ... .. . ... : 5-# 00 D F01 : ... .. . ...
ROW 01 : ... .. . ... : ... .. . ... : ... .. . ... : 4-# 00 C ... : ... .. . ...
ROW 02 : ... .. . ... : ... .. . ... : ... .. . ... : 3-# 00 B F02 : ... .. . ...
ROW 03 : ... .. . ... : ... .. . ... : ... .. . ... : 2-# 00 A ... : ... .. . ...
ROW 04 : ... .. . ... : ... .. . ... : ... .. . ... : 1-# 00 9 F03 : ... .. . ...
ROW 05 : ... .. . ... : ... .. . ... : ... .. . ... : 0-# 00 8 ... : ... .. . ...
ROW 06 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 7 F04 : ... .. . ...
ROW 07 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 6 ... : ... .. . ...
ROW 08 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 5 F05 : ... .. . ...
ROW 09 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 4 ... : ... .. . ...
ROW 0A : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 3 F06 : ... .. . ...
ROW 0B : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 2 ... : ... .. . ...
ROW 0C : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 1 F07 : ... .. . ...
ROW 0D : ... .. . ... : ... .. . ... : ... .. . ... : ... .. 0 ... : ... .. . ...
ROW 0E : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ...
ROW 0F : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ...
Strange.
So, it looks like the third column is the volume, and the fourth is the number of frames per sound.
At least I have a starting point now.
Bob
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
Yeah, this is actually not as strange as it sounds. In the APU noise channel, $0 means the lowest period (= highest frequency) and $F is the highest period (lowest frequency). It's reversed in FamiTracker, probably because for most people it would make most sense that "bigger number" should mean "higher frequency".PacManPlus wrote:...the '5, 4, 3, 2, 1' down the left-hand side is actually the inverse of what the data is, for some reason. I had to use $8A,$8B,$8C,$8D,$8E, and $8F. Also, I thought the $00 in the second column was the mode, and I guess it isn't, because I had to use Mode-1 to get that sound (hence the $8X in my listed values above)...
Strange.
Simply EOR the value with $F and you're good to go.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi