øAslickproductions.org/forum/index.php?PHPSESSID=5f0fck550j2m4m2fpbtkj2vkm1&action=profile;u=339;area=showposts;start=75e:/My Web Sites/Slick Productions - FFIV Message Board/slickproductions.org/forum/index261e.htmlslickproductions.org/forum/index.php?PHPSESSID=5f0fck550j2m4m2fpbtkj2vkm1&action=profile;area=showposts;u=339e:/My Web Sites/Slick Productions - FFIV Message Board/slickproductions.org/forum/index261e.html.zxÜ›h^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈ00W4ÞOKtext/htmlISO-8859-1gzip@øÕ4ÞÿÿÿÿÿÿÿÿWed, 11 Mar 2020 08:22:12 GMT0ó°° ®0®P®€§²ð®Û›h^ÿÿÿÿÿÿÿÿ04Þ Show Posts - avalanche

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - avalanche

Pages: « 1 2 3 4 5 6 7 8 9 »
76
Just curious, does anyone know why they didn't use the stack for temporary variables?
... Isn't that the primary purpose of pushing and pulling the registers and the accumulator?

Absolutely, with PHA, PLA.   But they only do that to save them momentarily, and all the other temporary storage is from some other memory.  They use a lot of temporary global variables.  Though granted it's hard to tell which of the global uses are truly temporaries.  I was more referring to instructions with stack-relative addressing, like "AND $#04,S", so you wouldn't need the global memory, and would probably make our deciphering easier since we know a stack-relative address like that is certainly a local variable which is only used inside that very routine, rather than wondering how many other routines might modify it before we can tell what it might be.  Same thing with memory used for parameters.  There is limited stack space though, so that could be part of it.  I also wonder if those instructions were not actually available on the SNES, but that's just speculation.

77
Final Fantasy IV Research & Development / Re: Graphics info
« on: January 04, 2015, 05:53:11 PM »
Quote
Code: [Select]

F0 60 F1 35 E1 FF


I wonder what F0 60 is since 60 would be an index beyond the speical forms (0x3F indexes)...
Interesting... I wonder if this could be a key to the mysteries avalanche was pondering recently about monsters that change form in nonstandard ways.
given there are 0x3F special sizes, that leaves two bits unaccounted for in the "change form" command, leaving for the possibility of as many as three different nonstandard transitions...

Darn, I just got so excited!  But I only see 3 uses:

 F0 60  - Q.Eblan in AI B8
 F0 43  - Titan (Rydia's) in AI 89
 F0 74  - Elements in AI D1 (reflex)

78
Thanks guys! :blush:  I will say it's kind of a double-edged sword. Sometimes I'm a little too logical and having bashed out so many calculations in C over the years really spoiled me. I have to remember now that to multiply two numbers I need to transfer them to the appropriate registers (in the proper order) and then wait. I compare it to sticking two things in a microwave and waiting for the ding!  :tongue:

If you've programmed in C, I think you're in great shape to learn assembly.  In C you are really thinking about how array buffers work and pointer arithmetic and such, all very good foundations to go deeper into the figurative rabbit hole that is assembly.  People who have only worked with C++ or Python (even though python is the best thing ever imo) might have a harder time thinking about registers and memory. 

Bonus if you often use a ton of global variables in C, often a bad idea in programming, since that's all this game does.  The hardest part about deciphering this assembly is not what the instructions are doing but what all the memory references are for without the variable names.

Quote
http://wiki.superfamicom.org/snes/show/65816+Reference
Just a heads up about that site is that while I was writing a disassembler for analyzing this game I noticed some errors on that wiki page.  One that comes to mind is rather important I think: the description for the SBC instructions says "Subtracts operand from the Accumulator; subtracts an additional 1 if carry is set" which is backwards.  It subtracts an extra 1 if the carry is CLEAR.

Just curious, does anyone know why they didn't use the stack for temporary variables?

79
Overworld is Mode7. Mode7 uses 8bpp tiles with no bitplanes. All it has to do is split up the nibbles and combine them with palette assignment data (ff4.txt called this the "World Map Tile Palette Pointers").

I should have read your post through one more time, and it would have saved me some time.  The FF4.txt naming of "World Map Tile Palette Pointers" threw me.

This probably deserves a longer tech post, but the crux is that each 8x8 graphics tile is stored in the special 4 bpp format and has 1 byte in this "palette pointers" section that you just add (or 'or', either way) to each pixel's value.  That's the final color index for each pixel, which happens to be effectively only 6-bit color index because those bytes only have certain values.  And that matches with the fact that the palettes for each world have 64 entries in them.

A belated thanks to Vehek for having posted the information needed here and in the older overworld thread even though I didn't realize it for too long.


 :edit:
(As usual, forgive me if this is already known.)


The row pointers and FF-terminated rows worked for me for the overworld, but the underground and moon were a little unexpected.  First of all the row pointers seem to have 256 for underground, even though there are only 128 rows in reality, right?  I don't know what is in the extra space, but the moon is definitely 512 entries after the first instead of an expected 384:
  B0200  Overworld row pointers
  B0400  Underground row pointer
  B0600  Moon row pointers

Then the FF terminator frequently doesn't occur at the end of the expected row length.  I found the underground rows all appeared 256 long and when I just chucked the extra and kept the first 128 it looked right.

As for the offset you add to those pointers, the underground and moon need a different value:
  B0680  Overworld row data base
  B4680  Underground row data base
  B6380  Moon row data base

80
Congrats Pinkpuff!  The animations make it seem so much more real, very rewarding.

81
The glowing red bars I mentioned turned out to be correct, they pulse with the palette tricks as it happens.

Just a guess based on what I saw in my code for the Giant's background.  I had the big gears working, but all the various rods and things were messed up.  Many of those are in the 130+ (hex) range, way up through at least 185 in tileset 8.  So are you using all 10 bits, and only trying to animate the ones that are 120-12F?

I am, but actually I think I know where the problem might lie. Suppose something has sprite index 110. No problem. It looks at ((starting offset) + 110 * (bpp) * 8) to find the graphic data. Now, suppose instead it has sprite index 120. Ok no problem it looks at ((animated offset) + 0 * (bpp) * 8) to find the graphic data. Suppose, however, that instead it has sprite index 130. Where do I look? ((starting offset) + 130 * (bpp) * 8)? Or ((starting offset) + 120 * (bpp) * 8)? (i.e. where it would have "left off" when it took a detour for the animated sprites) Somewhere else entirely? I think could be where it's getting confused.

It seems odd, but the former.  Treat just like normal.  See attached pic.  That is extracted from the Giant's base address, F9700.  Tiles 09 and 0A in the tileset both use graphics indices 132, 133, 172, 173.  I highlighted those green.  Also the bottom half of the warp tiles at 72 and 73 use graphics indices 17C-17F.

Not sure what goes into the hole at 120, I don't recognize the graphics there.

82
So if I'm reading this all correctly, then the quickest possible transition is six frames, right?
If the parameter "00" tells the game to revert using the previous dissolution duration, then 01 would be the quickest controllable amount of time to revert... Right?
The event scripts in the game only actually use 00 for reverting, there are no occurences of 01-1F.  So I am not sure what happens if you use those values.  I haven't actually seen the assembly that controls this, but I wouldn't be surprised if they just checked the top 3 bits for 0 and ignored the bottom 5 bits, but I'm just speculating there.

 :edit:
Okay so I think I could not have been more wrong. It lined up so well in my test, but that was coincidence.

The routine to implement an F9 tint instruction is at 00:E731.
I was right about the timing of reverting, but the criterion for reverting is just that it is every other use of the F9 command.  Presumably then the parameter byte there is completely unused, not even that 0 color part.

Code: [Select]
bgrsiiii
   bgr:  are the color bits you want to SUBTRACT from.  I assume 000 would appear to have no effect
   s:  indeed a speed factor.  see below
   iiii:  intensity of effect.  Again I assume 0 would appear to have no effect, and F is the most possible.
The duration is based on the intensity and speed bit.  It is (intensity * 2 + 1) frames, and multiply by 8 if the speed bit is on to slow it down.

So for the intro example of 9A, that is:  100/1/1010  subtract from Blue (so looks yellow), Slow mode, intensity of A out of a possible F.  The number of frames would be about 168 frames (decimal, compared to the 156 I said erroneously before).

So to newly answer your question chillyfeez even though I got the premise wrong earlier, is that I think you have no control over reverting whatsoever.

 :edit:
..except that global memory like this uses allows external changes. It looks like an intervening Toggle Screen Fade (cmd DA) forces the slow mode for the next revert and Load Map (FE) looks like it forces fast mode.  I'm not going to dive deep to find all such occurances, but it just took me hours to find out why the Inn scripts were asymmetric, using fast blue-tinting but slow untinting which occurs while the screen is still fully black due to the screen fade.  But it makes the sleepy-time music fit like exactly, and without that forced slow mode it was cutting off the sleep music by a little.


Some of them still look... not correct... (e.g. I'm also seeing red bars in the Giant of Babil ceiling, and the Giant of Babil background looks messed up for some reason) ...
The glowing red bars I mentioned turned out to be correct, they pulse with the palette tricks as it happens.

Just a guess based on what I saw in my code for the Giant's background.  I had the big gears working, but all the various rods and things were messed up.  Many of those are in the 130+ (hex) range, way up through at least 185 in tileset 8.  So are you using all 10 bits, and only trying to animate the ones that are 120-12F?

83
Small note regarding the event script command that tints the screen.  I think this is from Phoenix?
Code: [Select]
F9 xx Toggle screen tint xx (fast transition/slow transition)
0F/1F = normal tint
2F/3F = teal
4F/5F = purple
6F/7F = blue
8F/9F = yellow
AF/BF = green
CF/DF = red
EF/FF = black

I have a different interpretation of the bits for the parameter byte:
Code: [Select]
CCCddddd
    CCC:   color (0=normal, 1=teal, 2=purple, 3=blue, 4=yellow, 5=green, 6=red, 7=black)
    ddddd: duration, in 6 frame units
So for the first tint in the opening scene which is (F9 9A), that is yellow but 1A is the duration which means 1A*6=9C (156 decimal) screen frames.  I just counted the frames during this event in the emulator and it lines up perfectly.  Oh and I think to revert to normal, all scripts just use 00, and I'm speculating that the game remembers the duration of the last tinting and uses that when reverting, rather than looking at the parameter for that duration at all.

Related is that each unit in the E9 "Pause" command is worth 8 screen frames.

Just for those with minor OCD with regard to exact timing (coughmecough).

 :edit:
I think the tint stuff above is totally wrong... see later post.

84
Quote
The assembly must do some crazy stuff to get this ready for the PPU...
Overworld is Mode7. Mode7 uses 8bpp tiles with no bitplanes. All it has to do is split up the nibbles and combine them with palette assignment data (ff4.txt called this the "World Map Tile Palette Pointers").

Ah, yes!  I hadn't thought of the Mode7 factor.  Makes total sense.

85
Ok so with regard to the 4bpp encoding of the overworld tiles, is it this?:

Quote from: consolegfx.txt
11. 4BPP Game Gear/Sega Master System/Wonderswan Color
  Colors Per Tile - 0-15
  Space Used - 4 bits per pixel.  32 bytes per 8x8 tile.

  Note: This is a tiled, linear bitmap format.
  Each pair represents one byte
  Format:

  [r0, bp1], [r0, bp2], [r0, bp3], [r0, bp4], [r1, bp1], [r1, bp2], [r1, bp3], [r1, bp4]
  [r2, bp1], [r2, bp2], [r2, bp3], [r2, bp4], [r3, bp1], [r3, bp2], [r3, bp3], [r3, bp4]
  [r4, bp1], [r4, bp2], [r4, bp3], [r4, bp4], [r5, bp1], [r5, bp2], [r5, bp3], [r5, bp4]
  [r6, bp1], [r6, bp2], [r6, bp3], [r6, bp4], [r7, bp1], [r7, bp2], [r7, bp3], [r7, bp4]

  Short Description:

  Bitplanes 1, 2, 3, and 4 are intertwined and stored row by row.

Or this?:

Quote from: consolegfx.txt
12. 4BPP Genesis/x68k
  Colors Per Tile - 0-15
  Space Used - 4 bits per pixel.  32 bytes per 8x8 tile.

  Note: This is a tiled, big Endian, linear format.
  Each pair represents one byte
  Format:

  [p1-2 r0: bp*], [p2-3 r0: bp*], [p4-5 r1: bp*], [p6-7 r1: bp*]
  [p1-2 r2: bp*], [p2-3 r2: bp*], [p4-5 r3: bp*], [p6-7 r3: bp*]
  [p1-2 r4: bp*], [p2-3 r4: bp*], [p4-5 r5: bp*], [p6-7 r5: bp*]
  [p1-2 r6: bp*], [p2-3 r6: bp*], [p4-5 r7: bp*], [p6-7 r7: bp*]

  Short Description:

  Bitplanes 1, 2, 3, and 4 are intertwined and stored pixel by pixel.

Quote from: consolegfx.txt
     BPP:  Bits per pixel.

     Xth Bitplane: Tells how many bitplanes deep the pixel or row is; the top layer
          is the first bitplane, the one below that is the second, and so on.

     [rC: bpD]: row number C (0-7 in a 8x8 tile), bitplane number D (starting at 1).

     [pA-B rC: bpD]: pixels A-B (leftmost pixel is 0), row number C (0-7 in a 8x8 tile),
          bitplane number D (starting at 1. bp* means it's a linear format and stores the
          bitplanes one after another bp 1 to bp Max.)

Or is it something else entirely? Or is that unknown as of yet?

I think it's the second one you listed.  I'm shocked it isn't either what the other 4 bpp ones in the game are or the first one you listed, as they are close to the hardware format.  The assembly must do some crazy stuff to get this ready for the PPU...

The first byte has the first two pixels, the low nibble is the 1st pixel, high nibble is the 2nd pixel.  No bitplanes at all.

Here's an example, with one awful palette for everything, extracted using this method:

86
I think it might be 9*8*7*6 = 3024 formations? But yeah still too many :)

It's a great idea. It would be sweet if earlier there were some options. But you're right, it seems like the story doesn't lend itself to it since everybody is pulled from the party rather harshly and they aren't available, either presumed dead or working for the bad guy.

87
I _heart_ this idea.

I pondered about this at one point and was immediately discouraged by the amount of event scripts that would be messed up by someone in or not in your party. But if you are doing it only later in the game, when the whale is available, maybe that isn't so bad.

88
Now for the palette tricks!

There is a routine called every frame, like the one that updates the animated tiles graphics.  This one is at 15:C420.  It explicitly looks for tilesets by number.  Tilesets 8,A,B do one thing (Whale, Tower, Giant), and tileset 9 (Land of monsters) does another thing.  The code does some surgery to manipulate very specific color slots in specific palettes, but pulls the colors to use from tables in ROM.

All of the addresses listed below refer to lists of 8 colors, 2 bytes each.  So they are each 16 bytes.  Time is used to index all of them.  The game does something like move to the next slot every 4 frames, I believe.  Update - one of them is 16 entries long and goes twice as fast as the others.

For tilesets 8,A,B: 
14:F7D6 (ROM A79D6) -> palette 1, color 1
14:F7E6 (ROM A79E6)  -> palette 2, color 1
14:F7F6 (ROM A79F6)  -> palette 4, color 1

The following is a similar table, but instead of only updating 1 color, the entire palette is replaced, and time is used to slide the palette smoothly; starting from the appropriate point moving forward, and wrapping as necessary.  This is used for the real trippy blue-white crystal tiles.  Update - this one is 16 long and goes twice as fast.  The table is 16 long, but a sliding window of 8 are copied out to the palette.
14:F826 (ROM A7A26)  -> palette 7, all colors


For tileset 9, when the map palette is 9:
14:FBC6 (ROM A7DC6) -> palette 1, color 1
14:FBD6 (ROM A7DD6) -> palette 1, color 2   AND  palette 5, color 2
14:FBE6 (ROM A7DE6) -> palette 1, color 3
14:FBF6 (ROM A7DF6) -> palette 5, color 1

For tileset 9, when the map palette is F:
Same as above, only add 40 (hex) to all those table addresses.  They pull from tables immediately after the ones above.


 :edit:
Corrected one of the entries above.  The cycling palette table is 16 long and runs twice as fast.

89
Yeah. It's nice to have someone around who actually understands how SNES graphics work.
Wtg, avalanche!

Thanks!  Now I want to look into the glowing effects like in the Tower tileset.  But I have a rather newbie problem which is that I don't have a bunch of save states or SRAMs to get me to various places in the game for arbitrary debugging.  Anybody know if there is an easy way to force loading a certain map, or is hacking an SRAM for the emulator the way to go?

90
The addresses I posted before fix more of the animated tiles, but it is still not perfect.  I think those addresses are correct, but the way I described indexing the animated tiles is where I got it wrong.  The interesting thing is that it worked for like half the tilesets even though it was not really right. 

Anyway, I'm making major headway into how the game handles the animated tiles, but it's a slightly slower process than I'd like.

 :edit:
Update.  I spoke too soon; that first formula I gave was pretty close, there's just a tweak below.

For the hardcore enthusiasts out there, I just realized that the 2-byte tile formation data is already in the SNES background tilemap hardware format.  So the game itself only uses the unmodified tile formation data, even for animated tiles.  But what it does is copy the special animated graphics right after the normal graphics, and then overwrite the animated set every 8 screen frames.  So from its point of view, it's just a standard:
Code: [Select]
vhopppcc cccccccc
  v=vflip,  h=hflip,  o=priority,  p=palette, c=index (a full 10-bit tile index!)

So Pinkpuff, if you are using what I posted before, there are some small tweaks in order to interpret more correctly:

  • Firstly, you need to use all 10 bits for the graphic tile index.  This actually adds even more non-animated tiles after the animated ones
  • The animated tiles are only for those with graphic tile index 120-12F (hex).  Again, above this I think are more non-animated tiles that can be treated as normal
  • And the major index is only 2 bits instead of 3 (or a mask of 0C instead of 1C).

I tested this with house, town, castle int/ext, the caves.  Even the robot gears work now and other parts that I think used to be > 130.  One tile that does still look wrong is the one that shows at the top wall of the Giant's CPU map (actually, is that long red rectangle supposed to be there? maybe it is right...).

I hope that helps, Pinkpuff!  Sometimes it just takes a few iterations to get perfect.

Pages: « 1 2 3 4 5 6 7 8 9 »