News:

11 March 2016 - Forum Rules

Main Menu

Project: FF7 NES Upgrade

Started by Vanya, December 27, 2008, 10:58:55 PM

Previous topic - Next topic

tummai

I was giving this a look today at work.  It's going a little slower than I thought it would, since the version of FCEUX that I found that could actually run the game has a buggy Trace Logger, but I was able to locate some songs, which should help me trace back to how to call songs.

I have a question though.  Searching through the ROM I found only 8 songs.  That seems like so few.  Someone who has played through the game, can you confirm if there are only 8 songs (songs that repeat over and over) in the game?  It will help me move onto the next step if I can get this confirmed.

Lindblum

#61
I was only able to find 8 songs:
   01   FF* Prelude   0x1B8DD($B8CD-$B9??)
   02   Unident. Town   0x1B9DF($B9CF-$BB??)
   03   FF2 Town   0x1BB78($BB68-$BC??)
   04   FF2 Main Theme   0x1BC76($BC66-$BD??)
   05   FF2 Rebel Army   0x1BDEB($BDDB-$BF??)
   06   FF2 Battle   0x1BF73($BF63-$C1??)
   07   FF3 Boss   0x1C21B($C20B-$C4??)
   08   FF* Victory   0x1C470($C460-$C6??)

Confidence is the feeling you have before you understand the situation.

tummai

Yes, those are the ones I found.  When you were playing the game, you didn't hear any other songs, did you?

Lindblum

#63
I've noticed $6E00-$6E01 happens to store the address of the current song.  This address is loaded from $C7-$C8 (dynamic music pointer).  Set an execution breakpoint at $9DAD to watch this pointer get set when the song changes.  Yadda yadda yadda, the song pointers are stored at 0x1B8B2:
   MusicPtrLo = $B8A1 + 2*Index
   MusicPtrHi = $B8A2 + 2*Index
It looks like there are 12 repetitive pointers for Rebel Army at the end of this array, so I bet we could turn those into pointers to new songs :laugh:

At 0x6156($E146-$E1EB) is a list of song indices.  Each index represents a location, and its value is the song to be loaded.  For example:
   $E146==05   World Map is FF2 Rebel Army
   $E170==03   Kalm is FF2 Town
   ...Don't bother figuring out the rest, I have most of that done already.
You can set an execution breakpoint at $E12B to see where a song Index is loaded from.
Confidence is the feeling you have before you understand the situation.

tummai

Quote from: Lindblum on March 02, 2009, 03:02:53 AM
I've noticed $6E00-$6E01 happens to store the address of the current song.  This address is loaded from $C7-$C8 (dynamic music pointer).  Set an execution breakpoint at $9DAD to watch this pointer get set when the song changes.  Yadda yadda yadda, the song pointers are stored at 0x1B8B2:
   MusicPtrLo = $B8A1 + 2*Index
   MusicPtrHi = $B8A2 + 2*Index
It looks like there are 12 repetitive pointers for Rebel Army at the end of this array, so I bet we could turn those into pointers to new songs :laugh:

At 0x6156($E146-$E1EB) is a list of song indices.  Each index represents a location, and its value is the song to be loaded.  For example:
   $E146==05   World Map is FF2 Rebel Army
   $E170==03   Kalm is FF2 Town
   ...Don't bother figuring out the rest, I have most of that done already.
You can set an execution breakpoint at $E12B to see where a song Index is loaded from.

Cool.  That matches my notes, except for the $E146 part which I hadn't gotten to yet.

As a test, I copied one of the songs into some free space at 0x1DBA0 (in the same bank as the loading routines), thus creating a 9th song.  I made a pointer to it at the end of the $B8A1 table (the first repeat of the Rebel Army pointer) and then changed all of the bytes in the E146 table to 09 (the new 9th pointer) and guess what, it worked!  Looks like this will be possible :)

The only snag is that some songs are hard-coded (ie, their song number is loaded directly into A and not pulled from the 0x6156/$E146 table), so we will have to find all of these instances and hard-code the song we want.  The title-screen for example is a hard-coded load at 0x071719 (execution breakpoint $9709).  The introduction soldier "boss" battle is hard-coded too at 0x23FDF (execution breakpoint BFCF).

Still, it looks like you nailed it.  If we can decode the song format, we can add our own songs in.  Cool deal.

Tauwasser

Now, remember to write a doc about the song format and upload it to RHDN and we're all cool :D
This is going to be serious good news for other hacks that want to incorporate somewhat different themes!

cYa,

Tauwasser

Vanya

I agree with that completely! The more knowledge we put down for others to read, the more the community will grow. ^_^

Lindblum

#67
Found more info. 
All songs start with "FF 00 __ __ 01 __ __ 02 __ __ 03 __ __ FF"
00-03 seem to be channel indexes, and the 2 bytes after them are the bigendian addresses of those channel streams relative to the song's root address.  That's super important. 
After the song header comes the header of the first channel, which is a series of opcodes and values that I hope tummai can figure out (I'm pretty sure "D8 __" sets the pitch shift).  Then there's the actual melody block (notes, note lengths and rests), followed by the D0 repeat byte. 

By my calculations for FF3 Boss, each of the 4 channels add up to exactly 624 ticks, so I think we can synchronize channels without much trouble! 

Once the other channel header opcodes are figured out (C4, C7, CC, CD, DB, DE), we've got this code cracked!

The bad news is, I calculate we only have enough room for about 3 or 4 more songs (about 400-500 bytes each).  I'm all for destroying a few present songs to fit in better ones, even if they're truncated versions. 

Songs I'm considering:
Prelude   //Already present
Tifa's Theme
Red XIII's Theme/Cosmo Canyon
Cid's Theme
Aeris's Theme
Chocobo Theme   //Short version from FF2j
Turks Theme   //Could use little mem
Fighting/Hurry Faster!   //Battle music
Still More Fighting   //Boss battle music
JENOVA/Jenova Absolute
The Birth Of A God/One Winged Angel
Victory Fanfare   //Already present
Bombing Mission/Mako Reactor
Shinra Company
Main Theme/Holding My Thoughts In My Heart
Those Chosen by The Planet   //Could use little mem
You Can Hear The Cry Of The Planet
Anxious Heart/On That Day, 5 Years Ago
Ahead On Our Way   //To maybe replace town music
Underneath The Rotting Pizza   //Could use little mem
Off The Edge Of Despair
Gold Saucer
Reunion
Judgment Day
The Promised Land (Yakusoku no Chi)
Confidence is the feeling you have before you understand the situation.

tummai

Quote from: Lindblum on March 03, 2009, 01:27:36 PM
Found more info. 
All songs start with "FF 00 __ __ 01 __ __ 02 __ __ 03 __ __ FF"
00-03 seem to be channel indexes, and the 2 bytes after them are the bigendian addresses of those channel streams relative to the song's root address.  That's super important. 
After the song header comes the header of the first channel, which is a series of opcodes and values that I hope tummai can figure out (I'm pretty sure "D8 __" sets the pitch shift).  Then there's the actual melody block (notes, note lengths and rests), followed by the D0 repeat byte. 

This is already in my notes.  :)

Quote
The bad news is, I calculate we only have enough room for about 3 or 4 more songs (about 400-500 bytes each).  I'm all for destroying a few present songs to fit in better ones, even if they're truncated versions. 

It may be possible to introduce a new opcode to place in the channel headers (or even just the first channel header) that can indicate a bank and an address, and then we can write some code for that opcode that will:

1)dynamically write some copy code to RAM (so that it can be executed after we've bankswitched away from the sound engine bank)
2)switch banks to the bank specified in the opcode
3)go to the address specified in the opcode and copy the song data to RAM
4)switch back to the sound engine and reroute pointers to the song data in RAM.

If we can pull something like this off, then we can scatter songs all across the ROM in any open space we find.

This will require:

1) enough RAM to hold the data for one song at a time.
2) enough RAM to hold the song-copying code (which should be quite short). 
3) enough ROM space in the sound engine bank to hold the new opcode code (shouldn't be a problem)

If we don't have the RAM, we'll have to find another solution.  But we might have it!  Is the RAM in $7000-7999 used by the game at all?

Lindblum

#69
I have sequenced (short versions of):

TitleSizeQuality
Ahead On Our Way233Good
Those Chosen by The Planet319Painful
Chocobo Theme214Decent
Main Theme in progress...

//I've noticed that in my document the bytes don't match up with the right notes.  I must've accidentally stepped on the equation while working on the document. 

G :D :D D NEWS: I miscalc'd before, I think I was looking at the wrong ROM bank.  We've got over 8,700 bytes of free space!  We can fit 20 more songs easy!  On the down side I should head backwards to rework my dinky loops into fuller songs. 
Confidence is the feeling you have before you understand the situation.

SFSeiei

Awesome, good work and good idea, i hope someday play this game at 100% :thumbsup:
Bye.

tummai

Quote from: Lindblum on March 04, 2009, 05:23:50 PM
I have sequenced (short versions of):

TitleSizeQuality
Ahead On Our Way233Good
Those Chosen by The Planet319Painful
Chocobo Theme214Decent
Main Theme in progress...

//I've noticed that in my document the bytes don't match up with the right notes.  I must've accidentally stepped on the equation while working on the document. 

G :D :D D NEWS: I miscalc'd before, I think I was looking at the wrong ROM bank.  We've got over 8,700 bytes of free space!  We can fit 20 more songs easy!  On the down side I should head backwards to rework my dinky loops into fuller songs. 

Awesome.  That's good news!  Hopefully we don't have to do any crazy bankswitching at all!  BTW, I've traced through a little ways and found the note tables.  This should help you sequencing the songs.  The note table actually has a big error too, so three notes in octave 2 are completely wrong.  To fix this, please change the following bytes in the ROM:

1ADBB: from 04 to 03
1ADBC: from 04 to 03
1ADBD: from 04 to 03

Note Table:
Acceptable values: #$40-#$80.  Note that NES octaves start at A, not C.

Octave 1
40: A
41: A#
42: B
43: C
44: C#
45: D
46: D#
47: E
48: F
49: F#
4A: G
4B: G#

Octave 2:
4C: A
4D: A#
4E: B
4F: C
50: C#
51: D
52: D#
53: E
54: F
55: F#
56: G
57: G#

Octave 3:
58: A
59: A#
5A: B
5B: C
5C: C#
5D: D
5E: D#
5F: E
60: F
61: F#
62: G
63: G#

Octave 4:
64: A
65: A#
66: B
67: C
68: C#
69: D
6A: D#
6B: E
6C: F
6D: F#
6E: G
6F: G#

Octave 5
70: A
71: A#
72: B
73: C
74: C#
75: D
76: D#
77: E
78: F
79: F#
7A: G
7B: G#

Octave 6
7C: A
7D: A#
7E: B
7F: C
80: C#

Lindblum

#72
My new table is *almost* like that, except I have 0x40 start at G# instead of A.  I'm still confused, it doesn't seem like I could be fooled by a half step so easily. 

Note123456
A0x410x4D0x590x650x710x7D
A#0x420x4E0x5A0x660x720x7E
B0x430x4F0x5B0x670x730x7F
C0x440x500x5C0x680x740x80
C#0x450x510x5D0x690x75
D0x460x520x5E0x6A0x76
D#0x470x530x5F0x6B0x77
E0x480x540x600x6C0x78
F0x490x550x610x6D0x79
F#0x4A0x560x620x6E0x7A
G0x4B0x570x630x6F0x7B
G#0x4C0x580x640x700x7C
Is it just me, or does FCEUX's sound seem a little flatter than Nestopia, or is that just because it's slower (yes, I set the speed to 100%)?
Confidence is the feeling you have before you understand the situation.

Killa B

I don't know about yours, but the version of FCEUX I have uses 11kHz for sound by default. I had to change it to 44.1kHz manually (you might want to change it to 48kHz, depending on your sound card).
Quote from: KaioShin on January 25, 2010, 09:25:28 AMI always dreamed of doing a Pokemon hack

tummai

Quote from: Lindblum on March 05, 2009, 09:49:51 PM
My new table is *almost* like that, except I have 0x40 start at G# instead of A.  I'm still confused, it doesn't seem like I could be fooled by a half step so easily. 

Is it just me, or does FCEUX's sound seem a little flatter than Nestopia, or is that just because it's slower (yes, I set the speed to 100%)?

All of the period values for the tones that the game uses are a little flat, so that might be why your table is a half-step down, since the first note is actually somewhere in between a G# and an A.  Traditionally though the highest period value possible (#$7FF) is considered an A.

As for the emulators, I have no idea.   PAL vs. NTSC makes a difference.   Are you running both emulators in NTSC mode?

Killa B

Oh, wow, I though you meant flat as in poor quality, not flat as in ♭. :P
Quote from: KaioShin on January 25, 2010, 09:25:28 AMI always dreamed of doing a Pokemon hack

tummai

Here is some opcode information for the Square channels.  I'm not 100% on them, but since there are some people working on songs already, I thought I should throw them out there for experimentation.  Let me know if I have anything wrong (let me know if I'm right too :) ).  Again, this is just for the Square channels.

C4: takes one operand.  The right side (0-F) is used as the base volume (pre-envelope) for the channel.  Not sure about the left side yet.

CD: takes two operands.  The first operand can be a value 0-9 and selects the volume envelope.  The second operand can be a value 0-3 and selects the duty cycle for your square wave (but backwards.  3 sets the duty cycle to #%00xxxxxx, and 0 sets it to #%11xxxxxx).

Below are the volume envelopes.  These envelopes are applied to each note, so for fast notes they will likely be very subtle to the ear.  The maximum volume in these envelopes is the base volume set in opcode C4.  Please experiment with them:

1: Slow fadedown
2: low to high quick, then fade down (might sound like a pluck?)
3: fade down to half volume, then fade back up
4: fade up from half volume, then fade back down to half
5: fade down fast two times
6: down a little, up a little, then down to 0
7: down a lot, up a little, then down to 0
8: constant low volume, then rises to high, finally drops to half volume
9: fade down to half volume fast two times, then fade from half volume down.

I don't have #0 down in my notes.  I must have overlooked it.  I think it's not like the others though.  I'll have to look it over again later and do an update.

Lindblum

Cool, I'm definitely gonna play with those opcodes later, see if I can balance those channels and get the best volume envelope.  I wonder if there's another one for instrument. 
I played around with the regions.  Big difference.  I live in NTSC, but Nanjing is in PAL, but regardless I don't know which the game's supposed to be.  I'm probably going to trust that 0x40 is A, because I think I saw another document also have it that way.  I write down my notes by what sounds best in a MIDI editor, then run a script to parse my notes into a hex string. 
Confidence is the feeling you have before you understand the situation.

tummai

Quote from: Lindblum on March 06, 2009, 08:12:33 AM
Cool, I'm definitely gonna play with those opcodes later, see if I can balance those channels and get the best volume envelope.  I wonder if there's another one for instrument. 

Changing the duty cycle is a lot like changing instruments.  Pop in different values as the 2nd operand to opcode CD and you'll notice right away the difference in tone for your square wave.  Actually, I don't even know what duty cycle means, that's just what those bits are called in the NES sound docs I've looked at. :)

I'll keep digging at the other opcodes, but it may take some time.  This sound engine is pretty complicated for something that only plays 8 songs.

Quote
I played around with the regions.  Big difference.  I live in NTSC, but Nanjing is in PAL, but regardless I don't know which the game's supposed to be.  I'm probably going to trust that 0x40 is A, because I think I saw another document also have it that way.  I write down my notes by what sounds best in a MIDI editor, then run a script to parse my notes into a hex string. 

The ROM is for NTSC I think.  If it were PAL, the period value for the low A would be something like $760, not $7FF.  BTW, these NES note tables by Celius on nesdev are nice little references to have around: http://nesdev.parodius.com/bbs/viewtopic.php?t=3728&start=0

Lindblum

#79
Does the meaning of an A-note change from region to region?  (I'm only asking for the rhetoric)

I didn't get to do any more work last night.  It's too much work to make a patch, upload it, and set up a link for every little thing, so i'll give you my works-in-progress as hex strings so you can just paste them into the ROM at 0x1B8DD (over the Prelude) to audit them.  If it would save on thread-clutter (we've been talking for 3 pages) I could maybe send these strings to you directly in future.  Anyway...

Ahead On Our Way (v1)

FF 00 0E 00 01 62 00 02 BB 00 03 D6 00 FF CC C8 C7 FF C4 6E CD 03 00 DB 07 00 1E 78 D8 00 DE 06
CD 03 01 D8 00 04 71 6F 6E 6F 08 71 04 67 6A 6E 6C 14 6C 04 C9 6C 73 71 6F 0C 71 02 73 75 04 76
73 14 73 04 C9 73 74 73 71 0C 6F 04 71 73 67 68 6A 6E 0C 6C 04 6C 73 71 6F 0C 71 08 6E 18 6F 04
C9 D0 CC FE C7 FF C4 0E CD 03 00 DB 07 00 1E 78 D8 00 DE 06 CD 03 01 D8 00 04 C9 57 5B 57 63 57
5B 57 C9 57 5B 57 60 57 5B 57 C9 59 5C 60 C9 59 5E 62 C9 5B 5E 5B 62 5B 5E 5B C9 5B 60 63 C9 5A
5F 63 C9 57 5B 63 C9 57 5B 60 C9 59 5C 60 C9 59 5E 62 C9 57 5B 57 63 57 5B 57 D0 CC FE C7 FF C4
6E DB 07 00 1E 78 D8 00 DE 06 20 67 63 65 67 68 67 6C 10 6B 6A D0 CC FE C7 FF C4 4E CD 45 00 D8
00 DE 06 20 C9 C9 C9 C9 C9 C9 C9 C9 D0


Those Chosen By The Planet (v1)

FF 00 0E 00 01 33 00 02 62 00 03 B6 00 FF CC C8 C7 FF C4 6E CD 03 00 DB 07 00 1E 78 D8 00 DE 06
CD 03 01 D8 00 10 52 C9 52 C9 52 C9 52 C9 52 C9 53 C9 D0 CC FE C7 FF C4 0E CD 03 00 DB 07 00 1E
78 D8 00 DE 06 CD 03 01 D8 00 20 C9 24 C9 04 59 59 58 14 C9 04 59 58 5A 18 C9 08 59 58 5A 59 18
C9 D0 CC FE C7 FF C4 6E DB 07 00 1E 78 D8 00 DE 06 20 C9 C9 02 46 48 46 48 49 4B 49 48 46 48 46
48 49 4B 49 48 46 48 46 48 49 4B 49 48 46 48 46 48 49 4B 49 48 46 48 46 48 49 4B 49 48 46 48 46
48 49 4B 49 48 46 4B 49 4B 4D 4B 49 48 46 4B 49 4B 4D 4B 49 48 D0 CC FE C7 FF C4 4E CD 45 00 D8
00 DE 06 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06
C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 01
46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46
06 C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 01 46 46 06 C9 D0


Chocobo Theme (v1)

FF 00 0E 00 01 4C 00 02 88 00 03 A7 00 FF CC C8 C7 FF C4 6E CD 03 00 DB 07 00 1E 78 D8 00 DE 06
CD 03 01 D8 00 04 6A 02 67 65 63 6A 67 63 04 67 63 06 67 02 65 63 01 63 65 02 63 61 06 63 02 61
63 01 63 68 02 6A 6C 06 6D 02 C9 D0 CC FE C7 FF C4 0E CD 03 00 DB 07 00 1E 78 D8 00 DE 06 CD 03
01 D8 00 04 57 02 5E 59 57 5B 55 59 57 5E 57 5B 04 57 02 59 55 04 57 02 5E 59 57 5B 55 59 57 5E
57 5B 04 57 02 59 55 D0 CC FE C7 FF C4 6E DB 07 00 1E 78 D8 00 DE 06 10 63 08 5E 6A 10 67 04 5E
02 5E 5E 04 67 65 D0 CC FE C7 FF C4 4E CD 45 00 D8 00 DE 06 02 61 5A 5A 61 61 5A 5A 61 61 5A 5A
61 61 5A 65 63 61 5A 5A 61 61 5A 5A 61 61 5A 5A 61 61 5A 61 63 D0
Confidence is the feeling you have before you understand the situation.