Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176488)
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
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176490)
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.
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176492)
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.


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'.
That's why I mentioned that it uses the same sound chip as the 2600. ;)

Thanks,
Bob
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176495)
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".
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176497)
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
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176499)
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
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176500)
This is awesome - thank you so much! :)
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176574)
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):
Code:
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 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ...


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:
Code:
;   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


Thank you, thank you, thank you all for any help.
Bob
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176576)
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)
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176584)
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:
Code:
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 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ...


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
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176589)
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?
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176605)
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.

Code:
;   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
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176633)
Ok, I think I know what was going on...

If you look at the FamiTracker data,
Code:
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 : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ... : ... .. . ...


...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
Re: Does this exist? (Atari 2600 TIA -> NES 2A03 Note conv.)
by on (#176635)
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.

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".

Simply EOR the value with $F and you're good to go.