Author Topic: Chrono Trigger Sprite Insertion -- Development of a Guide  (Read 27987 times)

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #15 on: November 11, 2008, 06:32:52 pm »
A-ha, changing the next animation pointer over (Marle's) to the value that would normally follow Magus' animation pointer did the trick for the most part, though Magus' attack animation is still screwed up a bit for some reason.

A simple pointer switch doesn't change the palettes, but changing the palette data byte-by-byte does the trick -- it's as if the palette pointers are there for record-keeping purposes, and this other palette-determination method is the real deal.

As a side note, Magus looks pretty awesome doing Cyclone.

I've made some more corrections and re-attached the Sprite Offsets spreadsheet here and removed it from all other posts so as to minimize the number of versions floating around.

[attachment deleted by admin]

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #16 on: November 11, 2008, 10:38:42 pm »
LET US DISCUSS SPRITE ASSEMBLY

I'm up to speed on how the game engine specifies which tile to load I think, and am examining everyone's notes to figure out how the game engine places the loaded tiles on a 2D plane. But in the meantime, here's something I find extremely unsettling, probably due to my inexperience in this area:



Illustrated are the 9 non-blank tiles summoned from Crono's GFX pack to form his first frame, which I will call Frame #1 (Standing-Front). Notice how that damn little hair piece at the very top of his head has to be misaligned for the sprite to be built correctly?

How does sprite assembly data specify such a thing? Is there some function in the last eight bytes of Crono's first frame that allows pixel-by-pixel shifting of a tile?

______________

But I digress -- I should have used this post to describe my understanding of sprite assembly a.) to revive the topic and b.) to ensure that I have a correct understanding of how the game engine decides which tiles from a GFX pack to load. What follows is essentially a regurgitation of what Vehek and justin3009 had posted earlier, just in my own language.

Let's start with the hex code for Crono's first sprite frame, Frame #1 (Standing-Front):

00 00 00 00 02 00 01 00-00 00 00 00 20 00 21 00
00 00 00 00 10 00 11 00-00 00 31 00 30 00 30 40
F8 00 F8 E0 F5 D0 F8 F0                       

This consists of 16 tiles from Crono's GFX pack, 2 bytes each, plus 8 bytes that I'm still trying to figure out tagging along at the end (third row).

I like to think of the format for the two-byte pairs in rows 1 and 2 as follows:

VH OS
 With...
 V = Vertical Axis slot
 H = Horizontal Axis slot
 O = Orientation
 S = Section

The Vertical Axis nybble specifies which tile the game engine looks for in the up-down direction.
The Horizontal Axis nybble specifies which tile the game engine looks for in the right-left direction.
The Orientation nybble specifies whether the tile should be mirrored in the built sprite. There may be other ways to orient
     the tile, but I am currently unaware of other values besides "4," which is the mirror value.
The Section nybble specifies which 0xF by 0xF grouping in a GFX pack the game engine is supposed to look at when pulling
     tiles. Notice that on the vertical axis of the GFX pack pictured below I leave room for two nybbles, or a whole byte --
     starting with 0x00 and going through 0x3D at the very bottom. There are four "sections," one from 00 ~ 0F, another from
     10 ~ 1F, another from 20 ~ 2F, and another from 30 ~ 3D.

Next, let's get Crono's GFX pack up:


Note that the horizontal axis consists of hexidecimal values from 0x0 through 0xF -- these are H values.
Note that the vertical axis consists of hexidecimal values 0x00 through 0x3D -- these are SV values.

Let's go through the blue-colored bytes in Crono's first frame: 02 00

The game engine reads everything in Little Endian order, so we're looking at [OS VH] being [00 02].

The O value is 0, meaning there's no mirroring of the tile. The S value is 0, meaning we're in the 0V section of the GFX pack. The V value is 0x0, meaning we're in the top row. The H value is 0x2, meaning we're in the third row over. Thus, the tile loaded by this byte pair is the pink-filled tile in the pic below:


In the same vein, the red-colored bytes highlighted in Crono's first frame sprite assembly (30 00) specify the following tile:


The green-highlighted bytes highighted in Crono's first frame sprite assembly (30 40) give us much better practice. Read 0x4030, the first nybble tells us that the tile is mirrored and the second tells us that the game engine is pulling from the 0x00 ~ 0x0F range on the vertical axis. The tile in question is once again:


...it's just flipped this time so Crono can have two feet using the same tile.


Sprite Assembly gurus, don't hold back -- let me know if my understanding is correct so far, and please guide me on the meaning of the last eight bytes in Crono's first frame at your convenience.
« Last Edit: November 11, 2008, 10:45:46 pm by FaustWolf »

Vehek

  • Errare Explorer (+1500)
  • *
  • Posts: 1761
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #17 on: November 11, 2008, 10:46:23 pm »
As the sprite assembly thread says, the last 8 bytes have to do with x/y. They seem to shift in pixels. For the x-coord part, 00-7F seem to place to the right of where the sprite when x-coord is FF.
« Last Edit: November 11, 2008, 10:48:42 pm by Vehek »

justin3009

  • Fan Project Leader
  • God of War (+3000)
  • *
  • Posts: 3296
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #18 on: November 11, 2008, 11:51:42 pm »
What he said, and by changing a specific byte...forgot which, but it's in the old tutorial posted back, it'll flip the image horizontally so it can be used again.

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #19 on: November 12, 2008, 12:44:31 am »
Hmmm, I might just be on the verge of understanding the final 8 bytes if I think about them the way you proposed in this post Vehek:

00 00 00 00 02 00 01 00 00 00 00 00 20 00 21 00
00 00 00 00 10 00 11 00 00 00 31 00 30 00 30 40
F8 00 F8 E0 F5 D0 F8 F0                       

So am I correct in positing that what I've been calling "tiles" up to now (8x8 pixel units) are actually subtiles, whereas the game engine actually likes to work with full tiles (16x16 pixel units) at a time? Thus, the following four tiles must compose Crono's first sprite frame?



And the four byte pairs following those tiles are associated with the tiles in the pictured fashion, determining their coordinates on the x/y 2-dimensional plane? If I'm understanding this right so far, then I must ask a question Vargose posed in that thread: any idea on what the relative point of "origin" is? And where would the "anchor" be on a tile, i.e., the point on each tile whose coordinates are being specified?

EDIT: Ah, well, I can see this much -- the F5 D0 tile is placed above the F8 E0 and F8 F0 tiles, so that they're all stacked one on top of the other, and then the F5 D0 tile is laterally shifted by what appear to be three pixels relative to the lower tiles. Hence the three-unit difference between 0xF5 and 0xF8. That makes sense!

EDIT 2: Reference point of origin and tile anchor are best studied in the following context, I suppose. Here's what happened when I zero'd out the "FE 80" X/Y coordinate bytes:


So, question -- is the reference point of origin for the x/y coordinates at the very bottom-right of this pic, with the tile "anchor" being the bottom right-most pixel of the tile, or is the point of origin the bottom-right corner where Crono's foot is, and the tile "anchor" is at the top-left corner of the moved tile? In other words, are the reference point of origin and anchor where the green dot is, or where the red dot is?
« Last Edit: November 12, 2008, 02:33:08 am by FaustWolf »

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #20 on: November 12, 2008, 03:40:42 pm »
Okay, I think I understand the location of the sprite frame's origin and where a given tile's "anchor" is. The "anchor" I refer to, in case it wasn't clear, is the point/pixel on a tile to which the X/Y plane coordinates are applied, thus dragging the whole tile with it and snapping it into place.

The origin on the X/Y plane appears to be the red dot below, whereas the green dot is the anchor of Crono's head tile:


The red dot represents the coordinates 0,0.

The green dot represents the coordinates -8,-32.

Let's get the scale that the game engine's working with down-pat before moving any further:

0x00 ~ 0x7F: +0 ~ +127
0x81 ~ 0xFF: -127 ~ -1

WAIT -- if the X coordinate is 0xF8 (-8 dec), it's understandable that the anchor would be eight pixels left of the origin. But if the Y coordinate is -32, shouldn't the tile be below, and not above, the origin? It's mysterious to me, but it seems that the game engine determines the tile anchor's Y coordinate in reverse fashion. That is, if I make the Y coordinate 0x10 (+16 dec), Crono's head tile ends up 16 pixels below his feet.

Someone let me know if my understanding of any of the above is in error.

Moving on -- we have the following format a size 0 sprite frame's assembly:

VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
XX YY XX YY XX YY XX YY

Where...
 V = Vertical Axis slot of a subtile in the GFX pack
 H = Horizontal Axis slot of a subtile in the GFX pack
 O = Orientation of the subtile (0 for normal, 4 for reversed)
 S = Section (allows the game engine to search past 0xF on the vertical axis of the GFX pack; it could theoretically search all
       the way down to 0xFF thanks to this nybble.

 XX = The horizontal displacement of a tile's anchor, in pixels. Interpreted as we would expect, with positive values moving the
       anchor right and negative values moving the anchor left.
 YY = The vertical displacement of a tile's anchor, in pixels. Interpreted inversely from what we would expect, with positive values
       moving the tile anchor down and negative values moving the anchor left.

The VH OS subtiles are grouped into tiles as indicated by color-coding.
Each XX YY coordinate byte pair controls the tile that matches its color.
The scale on which the XX YY byte pair operates is as follows:
  0x00 ~ 0x7F: +0 ~ +127
  0x81 ~ 0xFF: -127 ~ -1

But enough theory. It's time for the first test of my understanding of sprite assembly...

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #21 on: November 12, 2008, 06:13:17 pm »
Sprite assembly pulled off without a hitch, so it would appear that my understanding is correct. In the pics below, note that I couldn't fit all of Slash into a Size 0 sprite assembly -- he'd need a Size 1 sprite assembly I suppose, and I'm not sure how to work with those yet. For now he shall remain footless:


EDIT: It occurs to me I should have posted my sprite assembly code. Here it is below.

00 00 01 00 00 40 03 00-20 00 21 00 22 00 23 00 
10 00 11 00 12 00 13 00-30 00 31 00 32 00 03 00
F0 E0 00 E0 F0 F0 00 F0                       


What I'm having trouble with right now are palettes. We haaatesss them, precious! Therefore, before moving the subject of sprite sizes, I would like to take a detour...


LET US DISCUSS PALETTES

When you (or at least I) work with sprites in a typical image editing program, I'm working with a palette that invariably looks something like this:



That's thirteen colors -- 12 for the actual sprite and one for the background. My question is, when creating a bitmap for import into the ROM, should I ensure that the background color is in the slot labeled "1" or the slot labeled "13"? In other words, I'm trying to manually anticipate what position in a 16-color palette the transparency would occupy. I thought at first that the transparency would occupy the slot labeled "1," so I assigned Slash's colors to slots 2 ~ 13 in the pic above. However, it would appear from my results that the thirteenth palette position is, in fact, where the transparency is being loaded. The solution could be as simple as making sure that the sprite pixels are "pointing" to palette slots 1 ~ 12 when I'm whipping up a bitmap for export, but I wanted to confer with more experienced sprite hackers first.


SUPER EDIT: Palette success! Though I haphazardly re-injected the sprite frame into the ROM, causing some misalignment that's reflected in the one mirrored subtile I used.



Once again, I had to use the palette correctional factor -- when editing Crono's palette, I had to start with address 0x23FFFE, which is two bytes prior to 0x240000. Therefore, the palette correctional factor in the spreadsheet must be used both for editing and viewing in TileMolester. I'm not sure why this is, because I can't imagine the game engine would be fond of starting a new block of data at 0x23FFFE as opposed to 0x240000, given that the latter is a very well-rounded value.

To answer my question above, one should ensure that all sprite colors fall into slots 1 ~ 12, and the background color falls into slot 13.
« Last Edit: November 12, 2008, 08:14:03 pm by FaustWolf »

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #22 on: November 12, 2008, 09:42:30 pm »
LET US DISCUSS SPRITE ASSEMBLY SIZE

Earlier Vehek noted that a Size 0 sprite assembly scheme consists of 40 bytes, whereas a Size 1 assembly scheme consists of 80 bytes. Thus, the difference between a Size 0 and a Size 1 assembly is as follows.

Size 0 Assembly
VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
XX YY XX YY XX YY XX YY -

Size 1 Assembly (Obsolete as per Vehek's observations; see following posts)
VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
XX YY XX YY XX YY XX YY - XX YY XX YY XX YY XX YY


In other words, bumping up the sprite's size by +1 increases the number of tile groups available by 4. So we have 8 tiles to work with instead of 4 with a Size 1 sprite. Those in the know, is it likely that this "+4 tiles" pattern holds through all sprite sizes? I.e., would we have the following?

Size 0 Sprite: 4 tiles
Size 1 Sprite: 8 tiles
Size 2 Sprite: 12 tiles
Size 3 Sprite: 16 tiles
Size 4 Sprite: 20 tiles

...and so on?


Also, it appears that a Sprite's Size parameter is defined in the "Sprite Data" section as contained in Geiger's NA Offsets Guide:

0x24F000 ~ 24F022: PC sprite data (5 bytes each)
0x24F023 ~ 24F522: NPC sprite data (5 bytes each)
0x24F600 ~ 24FFFF: Enemy sprite data (10 bytes each)

Vehek, Geiger, or justin, after snooping through the data, I suspect that the fifth byte in a player character's sprite data specifies the Assembly Size, is that correct?
« Last Edit: November 12, 2008, 11:28:17 pm by FaustWolf »

Vehek

  • Errare Explorer (+1500)
  • *
  • Posts: 1761
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #23 on: November 12, 2008, 10:07:42 pm »
The largest sprite assembly type I know of is 2.
I just checked, and what I said back then still seems to be true: The second row for size 1 assemblies is placed in a different spot. Size 2 assemblies seem to have the 2nd row in the same place though.

justin3009

  • Fan Project Leader
  • God of War (+3000)
  • *
  • Posts: 3296
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #24 on: November 12, 2008, 10:19:29 pm »
Yea, you're correct Faust.  Pretty certain of that.

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #25 on: November 12, 2008, 10:31:45 pm »
Man, now I'm worried about Size 1 Assemblies after re-reading Vehek's sprite assembly thread. Vehek, could you expound on what you meant here?

Quote from: Vehek
[In a Size 1 Sprite Assembly] There are 8 groups of 4-tile groups. Because there're more groups, the start of the second row of a group is 32 bytes after the start of the first row.

I think you mentioned Gato somewhere as an example of Size 1 Assembly, so I'll look at its sprite assembly and GFX pack as well.

Vehek

  • Errare Explorer (+1500)
  • *
  • Posts: 1761
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #26 on: November 12, 2008, 10:34:53 pm »
I was wrong about Gato's sprite assembly size back then. He's size 2.
« Last Edit: November 12, 2008, 10:36:27 pm by Vehek »

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #27 on: November 12, 2008, 10:38:25 pm »
I'll bet Slash is a Size 1, so I'll look at his assembly data. But first, it appears that I really need to pay attention to those sections labeled "Sprite Data" in Geiger's offsets guide, so I'll add those offsets to the developing spreadsheet.

Vehek

  • Errare Explorer (+1500)
  • *
  • Posts: 1761
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #28 on: November 12, 2008, 10:51:32 pm »
Yes, Slash uses size 1.

Basically, I think size 1 assembly is more like this (rearrangement of what you had):

VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
The x/y coordinates are still in the same place at the end.

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Re: Chrono Trigger Sprite Insertion -- Development of a Guide
« Reply #29 on: November 12, 2008, 11:22:33 pm »
Many thanks! Ugh, so the subtile groups are sort of spliced together in an unholy way when viewed with 16 bytes per row.

However, if you view with 32 bytes per row, it becomes this:

VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS | VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS | VH OS VH OS VH OS VH OS - VH OS VH OS VH OS VH OS
XX YY XX YY XX YY XX YY - XX YY XX YY XX YY XX YY

That's way easier for me to look at. Seems the size attribute widens the "window" through which the game engine reads the tiles.