Board of Slick

Library of the Ancients => Final Fantasy IV Research & Development => Topic started by: chillyfeez on November 23, 2017, 11:11:42 AM

Title: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on November 23, 2017, 11:11:42 AM
Hello, interested parties!

This is a thread where I'll be documenting the progress of a new "side project." Hopefully this will eventually become the definitive SNES FFIV "everyone gets stored in the Shadow Party" mod.

At this point, it's all conceptual and theoretical, but I'm pretty sure that, with enough time, I can make this mod work exactly according to the plan I'll describe here.

The goal of this project is to make the following changes to the Vanilla FFIIUS ROM:
1) All characters except Cecil can be stored in the shadow party data. As a general rule, characters in the shadow party will not earn experience.

2) Shadow party data, which will occupy the same amount of space in SRAM as it does in Vanilla, will be divided into two distinct parts. Part 1 (0x80 bytes) will store two full character records. Characters stored in part 1 will earn experience. By default, these full records will be used to store Kain (when he is under Golbez's control) and Rydia (between the shipwreck and her return as a teenager). Part 2 (0xB0 bytes) will store a set of essential data for Kain, Rydia, Tellah, Edward, Rosa, Yang, Palom, Porom, Cid, Edge and FySoYa. Characters stored in this section will not gain experience. The tradeoff is that all characters can leave and rejoin the party without losing stat information.

3) The Namingway screen will be removed and replaced with a party switch system, which I am calling the PHS (after the system in FFVII)

4) Character equipment will not be stored in shadow party data, but a hacker using this mod will be able to choose whether all equipment is lost forever or added to the player's inventory (or the fat chocobo's inventory?) when a character is moved to the shadow.


I think this mod will be interesting enough on its own that FFIV fans might want to try it just for fun. The great part about it, though, is that it will be fully compatible with FF4kster, so it will easily lend itself to others' hacking projects.

A few preemptive answers to some possible questions...
Why can't I store Cecil?
Essentially, I had to draw the line somewhere. The reason it's so hard to make a mod that fully stores every character in the shadow party is that the game only has 320 bytes available for the shadow party. I need 128 of those bytes for the records that can gain experience (I wanted 192, actually, but again I had to draw the line), which leaves me with only 192 for the non-experience slots. Even using a little compression trick I thought up, I still need 16 bytes for each character slot, and 16 x 11 (the total number of non-Cecil characters) = 176. I still have 16 bytes leftover then that could be used for Cecil, but that leaves open the possibility to face Zeromus without the ability to use the Crystal, which would leave the player in a game breaking dead end.

So then why include records that can gain experience at all?
In the default game story, I think it's necessary that Kain and Rydia gain experience when they are away. Story-wise, they are off actually doing things (as opposed to, say, Rosa, who spends her time away from the party completely tied up). And also, they are gone long enough that if they didn't level up, their return would be anticlimactic. Kain has, by far, the longest period of time away from the party. You don't want him rejoining at level 13. Rydia needs to come back and immediately provide significant help defeating Golbez and his shadow dragon. In a perfect world, Yang would level up, too, but there isn't enough room, and at least he's only gone for one chapter of the story so he doesn't miss out on very much levelling.

What are these "essential stats" that are getting stored?
A large portion of the character record is completely static and easily retrievable from ROM. What will be stored is everything that is not, specifically: Level, Persistent Negative Statuses, Current HP, Max HP, Current MP, Max MP, Base Str, Base Agi, Base Vit, Base Wis, Base Will, and Exp. I could have opted to save space by not including Persistent Statuses, Current HP and Current MP, but then the PHS system could be used as a free Cabin (for everyone except Cecil) and I feel like that would be a major flaw. The choice not to store equipment also saves seven bytes per record.

But wait - I just counted, and that all adds up to 18 bytes, not 16 - what's up with that?
You're absolutely right. I devised a bit of a compression trick. It's not much, but it saves two bytes per record. The highest possible value for Current and Max HP is 9999, or 0x270F, or #00100111 00001111. The highest possible value for Current and Max MP is 999, or 0x03E7, or #00000011 11100111. So HP never uses the two most significant bits, and MP never uses the six most significant bits. By shifting Max HP left by two bits I can combine it with Max MP into three instead of four bytes, and likewise for Current HP and MP.

So what happens with the stored characters' equipment?
As I said, the hacker will have the option when a character "leaves" to either discard current equipment outright, or to move the equipment into the player's inventory. To me, there are some instances when it makes sense in the story just to discard the equipment - specifically when a character leaves against the party's will (e.g. - Kain gets hypnotized, party gets shipwrecked); and there are times when a departing character might be able to leave equipment with the party (Palom & Porom get stoned, Cid stays in the Dwarf kingdom, any time PHS is used). I'm pretty sure I can work it out that if the player's inventory is full, the "swap or discard" screen will kick in, though I haven't actually tried yet...

So you're hacking the Namingway screen... How's that gonna work?
Well, I don't exactly know just yet. I can tell you that the player will lose the option to change Cecil's name to "Shitty," but the tradeoff should be worth it. As for how I actually come around to hacking the screen... Well you, dear reader, get to see that develop right before your very eyes. You see, I have a concept of how it will all work, but I don't know enough about the SNES PPU to code the visuals yet. Squall is helping me figure that all out on this forum, so you can watch as I learn what I need to learn.

Stay tuned!
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on November 23, 2017, 10:25:04 PM
If you want to catch up on the discussion between Squall and myself thus far regarding hacking the Namingway screen, you can find it here (http://slickproductions.org/forum/index.php?topic=1922.msg27966#msg27966).
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on November 23, 2017, 10:59:09 PM
Please don't alter the $2101, just read the value written there, particularly bits 5-7 (sets Sprite size).
Post the code here, so we can delve in details. Keep in mind that reading/writing to video could be auto-incremented. So even if you have initial value in the address ($2116), if you have some read/writes ($2118/$2139) after initialization and the code you are looking, the address has been already changed! Besides as I said the transfer could be done trough DMA/HDMA ... it all depends.

You know what? Lets do something else:
 - Download vSNES (the tool I've talk about)
 - Make sure you use zSNES as emulator. Load the ROM and when the namingway screen pops up - make a savestate
 - Send me or attach here that savestate
* You can check for yourself many things in vSNES - like what mode you use, layers, tiles, sprites,...
Ok, I made a save state in zSNES and downloaded vSNES and opened it but I don't really know what I'm looking at here...
It's too large to attach so here's a link:
https://drive.google.com/file/d/1_HmFLAMLgSGUHpSmtYkM8ses9BuAsiqD/view?usp=drivesdk
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on November 24, 2017, 09:29:35 AM
First is the blue window. You can see pretty much all register include PPUs. From there we can learn the mode, the layers,... but you need a good 'help'. I will suggest this (http://problemkaputt.de/fullsnes.htm)

Although we have the full info, and we can check the ASM code, its a little bit hard to get info, its more for a reference. Click on 'Screen Viwer', the last tab is 'info'. This is where the info from registers is made in a human form :D

1. Always the first things to check in is mode: here is 0. If you check the doc I linked above, you will see that in that mode we have 4 layers (Backgrounds/BG) all of them 2bpp or 4 colors. This mode is good for simple graphic or heavy on text. Also its important to note screen size: 256x224
2. Second is layers (backgrounds) - you will see that only BG1 and BG4 are visible, the other two - not. 'tile base' is where in the VRAM is the address of tiles, 'tilemap base' is the actual layer content.  I will suggest to click on 'screen' tab and play with layers visibility. Its crucial to understand what element in what layer goes and why!!! In 'layers' tab you can preview each leayer individually, examine what tiles compose the image (just move the mouse over preview).
3. Same way check sprites - in 'info' section about their properties, and in 'layers|sprites' - preview

*Some interesting conclusions:
- although mode 0 is quite limited of colors, trough sprite layer you can add some colors to the screen (since sprite layer is always 4bb or 16 colors). I think it will work fine for your PHS idea: - character that need to be moved will be Sprites, and you can use the screen to show some of their stats
- Its seems to me that whoever has made this, instead of defining a char as a Sprite he/she have defined each tile as Sprite ... I don't see the point of doing it that way ... logically you should have only 4 sprites (1 for the pointer, 2 for the chars and 1 for portrait)
- by knowing ID of tiles, you may try to check the code for LDA/x/y ID and pinpoint 'the drawing' on the screen
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on November 24, 2017, 10:46:06 AM
- Its seems to me that whoever has made this, instead of defining a char as a Sprite he/she have defined each tile as Sprite ... I don't see the point of doing it that way ... logically you should have only 4 sprites (1 for the pointer, 2 for the chars and 1 for portrait)
Yeah, FFIV was the first game Square developed for SNES, and it was released only about eight months after the console. A lot of times when you dig into the code, you get the impression that they really didn't understand the capabilities or how best to use the hardware yet.
Quote
- by knowing ID of tiles, you may try to check the code for LDA/x/y ID and pinpoint 'the drawing' on the screen
Looking forward to that for the practical application (I mean, this project), but I also still want to understand better how this all really works. So, thank you for taking this time.

I have to digest everything here. It's a busy work weekend for me (do they do "Black Friday" where you are?), but I have Monday and Tuesday off, so we can pick up then at the latest.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on November 24, 2017, 10:50:02 AM
Writing those long paragraphs take me quite sometime - to check, to experiment, to synthesize, to add some practicality ... so I really need your input - is it too much, is it not enough, whatever is your first impression/response after reading it (if you prefer PM, Telegram thats fine too)!
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on November 24, 2017, 11:37:36 AM
It's been a good amount of info at a time. I like having it up on the forum, too, because then I know it will be there if I need to go back and reference it again sometime.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on November 25, 2017, 02:18:26 AM
OK, I had some time to do some studying this evening and I had a bit of a breakthrough...

So it seems that FFIV always stores object data in RAM at $0300-$0520 and then regularly does what I think is a DMA transfer. I don't really know what DMA is, but I'm pretty sure that's what's happening.

So that's all well and good. By playing with the data there, I can effectively move the Namingway image to the location where I would want a portrait to be, giving me proof of concept that I could put portraits on the screen in all the right spots.
Here's the problem I'm facing now, though: Maybe it's because the game is treating every tile like a sprite, instead of just using 32x32 sprites, but that Namingway image uses 0x40 bytes of data. So if I wanted to display 11 character portraits on screen at a time, I'd need to transfer 0x02C0 bytes instead of 0x0220. Add in the finger cursor, and I'd need 0x02D0. Then if I also wanted the current party's battle sprites displayed, I'd need 0x0370. I think I could condense all the space used down to 0x0330 bytes, but that doesn't matter, because it seems like the game is already using the RAM beginning at $0600 for something else, so unfortunately it looks like I'm going to have to do without the battle sprites.

The question, then, is this: is there any reason (hardware limitations, or anything like that) why I can't change the 220-byte DMA transfer to a 2D0-byte DMA transfer? I've found the line of assembly that sets the transfer at 220 bytes, so the change would be simple,as long as it wouldn't cause a crash.
The other thing I could learn how to do, I guess, would be to change it so that the game is using 32x32 sprites... Or at least 16x16 sprites. Based on what I'm reading, it seems like that might be the better option, because the Battle sprites are 16x24, so I'd need to keep them as collections of 8x8 sprites, but then each portrait could be four 16x16 sprites instead of 16 8x8 sprites.

 :edit:
OK, forget most of the above post. I just figured out that when they say OAM is 512 + 32 bytes, that's a decimal value, so those 0x0220 bytes being transferred are the entirety of the OAM. That means I have to figure out how to make those sprites 16x16 in order for this to work. By manipulating those last 0x20 bytes I can make the Namingway sprites load as 16x16, but they're not composed of the right tiles (they're half Namingway and half NPC merchant), so I have to figure out the proper arrangement of data in VRAM in order to make the sprites look right. I'm sure there's a pattern and it'll be pretty obvious once I delve into it...
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on November 26, 2017, 07:03:58 AM
II. Layers
The second abstraction is Layer. You may see it as Background or BG in documentation. It work the same way  as in specialized graphic applications: Photoshop or Gimp - the final image is composed by plotting couple of images 1 by 1, each on top of the next, each containing transparent pixels trough which you may see things from the image under it.

SNES contain 4 such layers  (usually called background) + 1 sprite layer (which function in similar way) for a total of 5 layers. Unlike Photoshop where each layer can have 256 levels of transparency, here we have only 2 levels - fully transparent or not. Using color with index 0 mark transparent parts.

The other difference from Photoshop is that in each layer we can define priority for individual Tiles. For BG1-4 we have priority 0 and 1, while for Sprites (OBJ) we have 0-3. The order in which final image is rendered depend on the mode, so check the documentations for specifics (or experiment in vSNES).
While usually the mode define things like BPP or Max Colors, in SNES each layer has its own definition and is determined by the mode. For example in Mode 0 - all 4 BG are 2 BPP (4 color), but in Mode 1 - 4bpp for BG1,2 and 2bpp for BG3. Sprites (OBJ) are always in 4bpp, regardless of the Mode!

Code: [Select]
$212C - control which layer is visible or not
$2105 - tilesize for each leayer
$2107-$210A - set layer's base address in VRAM and its size. For now we all work with 32x32

 :edit:
Now that we know so many things about layers, what exactly we have in a layer?
Each layer is a two dimensional array of 16 bit values. There are 4 possible dimensions, but for now we will talk about 32x32. Each value has this format (exception in Mode 7 or "Offset-per-Tile" modes: 2,4,6):
Code: [Select]
  Bit 0-9     - Tile ID      (000h-3FFh)
  Bit 10-12   - Palette ID   (0-7)
  Bit 13      - BG Priority  (0=Lower, 1=Higher)
  Bit 14      - X-Flip       (0=Normal, 1=Mirror horizontally)
  Bit 15      - Y-Flip       (0=Normal, 1=Mirror vertically)

Clipping???
Scrolling????
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on November 26, 2017, 09:45:59 AM
Not related to this particular project, but related to this section of your tutorial...
A while ago I was helping Rodimus Primal out by recreating the Japanese FFIV title screen for his "Namingway Edition" hack. The major roadblock that I ran into was transparency. In the Japanese version, the title screen is composed of (at least) two layers of the "FINAL FANTASY IV" lettering and the large crystal image. I was unable to recreate the "flashing" effect of the crystal and the lettering because the top layer seems to be semitransparent.
So if a layer is either transparent or not... How did they do that?!
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on November 26, 2017, 10:17:57 AM
Working as a software developer, I  learned one thing about the graphic: eye is easily deceived. What you see on the screen could be totally different on how its implemented. For example, when you battle in FF4, you may think that all monsters and chars are sprites. But if you use vSNES you will see that monsters (not sure about chars) are actually in BG1 or 2 (so to speak they are static picture) :D

Unless you do save-state we can only speculate, but if I have to do it, I will probably make the top-most layer tile prerendered of the crystal and the flashing effect (you merge the two layers in Photoshop and the result is assigned to top-most tile).

Speaking of pre-render effect ... in FFBE check the candles - both walls and candles have clear vision, but if you take sometime and watch the fire/light animation over the wall ... see how pixelize it is (effect that happen from rendering the animation in true color(24/32bits) and then converted to less colors, most like 8bit/256). So instead each frame of fire to be rendered in realtime, they use bitmaps with prerendered effect already applied.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on November 26, 2017, 07:12:54 PM
III Tiles
We used that word so much, so I hope you got some intuitive understanding, but now is it a time to get a more formal one :D

1. What is a Tile
Tile is the basic element to a tile engines. It is the atom of the chemistry so to speak. It is the brick of an wall :D
A tile is a 2D MxN matrix (block/array) of points/pixels. In SNES a tile is an 8x8 block of pixels!. The colors of each pixels could be an index in a palette or Direct Color (R/G/B values) and that is defined by the Mode/Layer

2. Internal storage (or Bit-planes)
A tile is stored in the memory as a Bit-Planes. Depending on how many BPP is a layer, the tile uses the same amount of Bit-planes. Since SNES can use only 2/4/8 BPP, the tiles uses 2/4/8 Bit-planes. I really, really hope you know what bit-plane is, but if not and you want to know SNES specifics let me know.
From hacking standpoint its important to know - how many bytes a Tile occupy:
- in 2bpp, we have 2 x 8x8 = 128 bits = 16 bytes = $10 bytes
- in 4bpp, we have 4 x 8x8 = 256 bits = 32 bytes = $20 bytes

3. Tile map
A Tille Map is a 2D matrix MxN where each value is a Tile ID. Wait a minute, that looks dangerously similar to the definition of a layer. YES it is, a layer is an instance (custom case) of a tile map. And not just that, a Sprite is another instance of a TileMap.
Because of the way SNES works (Tiles don't hold palette info), the values of this 2D matrix (TileMap) are 16 bits, with the same meaning as layers:
Code: [Select]
Bit 0-9     - Tile ID      (000h-3FFh)
Bit 10-12   - Palette ID   (0-7)
Bit 13      - BG Priority  (0=Lower, 1=Higher)
Bit 14      - X-Flip       (0=Normal, 1=Mirror horizontally)
Bit 15      - Y-Flip       (0=Normal, 1=Mirror vertically)

4. Tile Size
SNES uses 2 sizes for tiles - 8x8 and 16x16. Wait a minute, didn't you say earlier is only 8x8? Yes I did! 16x16 tiles are actually 4 tiles (2x2) stored in a certain order.

5. Important registers (soon)
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on November 26, 2017, 09:09:40 PM
OK, I have some questions about this section...

1) is it important for me to know specifically what "MxN" means? You used that a couple of times and I don't know what M and N stand for in this instance.

2) So SNES can only do 2/4/8 BPP? What about the 3BPP format that is very prominent in FFIV? Is that just a somewhat-compressed version of 4BPP? I did notice that when copying (0x18 byte) 3BPP tiles to VRAM, the last 8 bytes get spread out over 0x10 bytes. Is that essentially taking the tile data and converting it to 4BPP?

3) I don't know if it's really important for me to know, since there are graphics viewing and editing programs, but I am curious - how exactly is image data encoded? If four bits are used to define a pixel, what do each of those bits represent?
This may also be an appropriate time to mention that I don't really know what a bit plane is...
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on November 27, 2017, 02:38:30 AM
Excellent questions, m8! Asking questions is the right way of understanding :D

1) MxN usually in the math mean a two dimensional matrix with M rows and N cols. It pretty much mean the same in programming for arrays. The importance is that in it represent rectangular block, but we don't care about exact dimension. If it was MxM or NxN it will mean square rather rectangular. In short MxN stands for 2D rectangular matrix/array/block without specifying the exact dimension.

2) You really nail it!!! Excellent question!!!
As you said FF4 uses internally 3bpp for most monsters and many other graphical objects (inheritance from NES I guess, because FF5 uses 4bpp in most cases). The problem is SNES has 2 or 4 bpp (without loosing quality). That's why all 3bpp stored in the ROM needs to be converted to 4bpp. That is done by inserting a 4th bit-plane with zeroes. 4(decimal) = 100 (binary-3bits) = 0100 (binary-4bits). Because of the way bit-planes are stored, your observation is right: it add 8 zeroes over the last $10 bytes.

Because 3bpp require: 3 x 8x8 bits = 192 bits = 24 bytes = $18, but 4bpp require $20 bytes, we will save 8 bytes per Tile and since we have plenty of Tiles building the image, some people call this compression. FF5 monsters could be 3bpp or 4bpp. There is a flag that tell us that, so in Japanese documents it was named compression :D

Quote
3) I don't know if it's really important for me to know, since there are graphics viewing and editing programs
Pretty much NO. Manipulating the individual pixels of a Tile is used mainly for creating special effects. In my observations, Square were a little bit lazy and were doing only effects trough manipulating PPU registers (easy and fast). The other case is for creating Tiles on the fly (trough code) - a library of functions that can manipulate Tiles, like Plot(TileID, X, Y, Color). In FF4, probably the only occasion of manipulating Tiles is the conversion of 3bb -> 4bpp.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on November 27, 2017, 04:12:13 AM
III.2. Tile internal storage (Bit-planes) EXTENDED

2.1 What is a Bit-plane
A Bit-Plane is a 2d MxN matrix/array/block of 1 bit values, yes only 0 or 1!
In graphics, if we take bit 0 (rightmost) of each pixel of a picture, the 2d matrix of all bit 0 is a Bit-Plane0. Similarly, of all bit1 of pixels of a picture is Bit-Plane1 and so on.

Lets talk specifically about Tiles in 4BPP:
If we take all bit 0 of all 8x8 pixels, we will have 8x8 1bit matrix - Bit-Plane0
If we take all bit 1 of all 8x8 pixels, we will have 8x8 1bit matrix - Bit-Plane1
If we take all bit 2 of all 8x8 pixels, we will have 8x8 1bit matrix - Bit-Plane2
If we take all bit 3 of all 8x8 pixels, we will have 8x8 1bit matrix - Bit-Plane3
* each Bit-Plane is 8 bytes, each byte contain a row of bits
* Number of BPP = Number of Bit-Planes!

2.2. Example
Code: [Select]
   Tile in Decimal:                     Same Tile in Binary (4bit):
00 01 02 03 04 05 06 07          0000 0001 0010 0011 0100 0101 0110 0111
08 09 10 11 12 13 14 15          1000 1001 1010 1011 1100 1101 1110 1111
00 01 02 03 04 05 06 07          0000 0001 0010 0011 0100 0101 0110 0111   
08 09 10 11 12 13 14 15   ---\  1000 1001 1010 1011 1100 1101 1110 1111
00 01 02 03 04 05 06 07   ---/  0000 0001 0010 0011 0100 0101 0110 0111
08 09 10 11 12 13 14 15          1000 1001 1010 1011 1100 1101 1110 1111
00 01 02 03 04 05 06 07          0000 0001 0010 0011 0100 0101 0110 0111
08 09 10 11 12 13 14 15          1000 1001 1010 1011 1100 1101 1110 1111

Code: [Select]
Bit-Plane 0:        Bit-Plane 1:      Bit-Plane 2:       Bit-Plane 3:
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   1 1 1 1 1 1 1 1

2.3 How Bit-Planes are stored in SNES
In the perfect world we will be done, but in SNES things are even more complicated. In memory this is present as:
Code: [Select]
  p -  Bit-Plane,   pX - Bit-Plane X
  r -  row,  rX - row X
  pX:rY - a byte value made by the 8 bits of a row Y in Bit-Plane X
p0:r0  p1:r0  p0:r1  p1:r1  p0:r2  p1:r2  p0:r3  p1:r3  p0:r4  p1:r4  p0:r5  p1:r5  p0:r6  p1:r6  p0:r7  p1:r7
p2:r0  p3:r0  p2:r1  p3:r1  p2:r2  p3:r2  p2:r3  p3:r3  p2:r4  p3:r4  p2:r5  p3:r5  p2:r6  p3:r6  p2:r7  p3:r7

2.4 Fill the missing XXs:
As a practical task, I will give you the value of few pX:rY. Your task is to tell me the missing ones marked as XX. All values are in hex!
Code: [Select]
55 33 XX XX XX XX XX XX XX XX XX XX XX XX XX XX
0F 00 XX XX XX XX XX XX XX XX XX XX XX XX XX XX

2.5 Some interesting cases:
- 2bpp? Its very easy, we have only 2 bit-planes and only 1 row (16 bytes). Its not by chance I used 2 rows to put bytes of a Tile :)
- 3bpp? First row is the same. Second row is only 8 bytes and contain bytes of Bit-Plane 2.
- 3bpp->4bpp? (please tell, how do you think it will happen)
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on November 27, 2017, 07:45:09 AM

Aha, I see...

Code: [Select]
Bit-Plane 0:        Bit-Plane 1:      Bit-Plane 2:       Bit-Plane 3:
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1   0 0 1 1 0 0 1 1   0 0 0 0 1 1 1 1   1 1 1 1 1 1 1 1
Code: [Select]
55-33-55-33-55-33-55-33-55-33-55-33-55-33-55
0F-00-0F-FF-0F-00-0F-FF-00-0F-FF-0F-00-0F-FF

And I've actually watched the 3BPP->4BPP conversion happen for a tile, byte by byte, in Geiger's. At the time I wondered why it made sense to insert 00s in between each of the last 8 bytes, but now I get it.
3BPP uses 3 bit planes. All of the information for the fourth bit plane used by a 4BPP tile would be stored in bytes 11, 13, 15, 17, 19, 1B, 1D and 1F.

Well, that means I can pretty much abandon all hope of editing tiles on the fly in hex (not really that important, anyway) because the unpacking and re-packing of bits is way too complicated for my very human brain to do with any efficiency.

I guess this somehow makes the data easier or faster for the SNES to interpret? You don't have to explain why or how that is - it's probably deeper than I need to go.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on November 27, 2017, 08:32:31 AM
Excellent work, m8!!! I'm proud of you!!!
Both task completed!

That was the hardest part - hard to explain, hard to code, and hard to understand.

Quote
I guess this somehow makes the data easier or faster for the SNES to interpret? You don't have to explain why or how that is - it's probably deeper than I need to go.
My speculation is - hardware. Usually by doing this weird for us things, they organize memory ... like a Bit-Plane in one memory chip. Then you can assign different processors to work on different chip memory simultaneously without interfering (internal multitasking).

The other possibilities is to have separate bus to each chip which will multiply the access to VRAM. For example if each bus is 8 bit and we have 4 banks with separate bus connection - that is effectively 32 bit bus (you can read 32bits in one bus tact).
That's exactly what contemporary video cards do - multiple cores for multitasking and wide bus to guarantee fast access to the VRAM. In the past GTX modifications had better performance, not because they have more cores or frequency, but wide bus, because the bus is quite a bottleneck for the performance.

Anyway we have only 2 things left: Sprites and Palettes. Both should be familiar to you so I'm only going to write SNES specifics. After that we may talk a little bit of DMA/HDMA and if you want finish the 2 ??? - Clipping & Scrolling of layers :)
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on November 28, 2017, 08:03:52 AM
IV. Palette
1. What is a Palette?
Our next abstraction is a Palette. Think of an artist painting a picture - although the picture may contain millions colors, while painting the artist take only couple of colors on a palette (tray/board) to draw specific areas of the picture. The same way, when the PPU draw a Tile, it uses a selection of colors named a Palette.

The number of colors in a Palette is tightly connected with the Layer BPP:
 - If a Layer is 4bpp, then the Palette contain 2^4 = 16 colors with indexes 0..15.
 - If a Layer is 2bpp, then the Palette contain 2^2 = 4 colors with indexes 0..3
 - How many colors we have in 8bpp?

2. Color (Palette Entry)
In each Palette entry 0 is a special - it is used for transparency. All colors are 16 bit in the format: 0BBBBBGGGGGRRRRR.
That is 5 bits for each component - Red/Green/Blue. In specialized books you will see this abbreviated as 5-5-5.

3. Palette memory
PPU contain dedicated memory of 512 bytes for Palettes, abbreviated as CGRAM. That memory can hold 256 colors. Depending of the Layer's BPP that memory is used differently:
- in 8bpp - we have 1 Palette containing 256 colors, entries: $00..$FF
- in 4bpp - we have 8 Palettes, occupying entries: $00..$7F
- in 2bpp (Mode 0) we have 8 Palettes for each layer: $00..$1F (BG1), $20..$3F (BG2), $40..$5F (BG3) and $60..7F (BG4)
* Sprites use 8 Palettes, occupying entries: $80..$FF

4. PPU Registers:
Code: [Select]
$2121: Address for accessing CGRAM (1b/W). This register selects the  word location (byte address * 2)
$2122: Data write to CGRAM (1b/W)
$213B: Data read from CGRAM (1b/R)
[i]*Since read/write return only 1 bite, you need 2 consecutive operations to get the whole color (16bits)[/i]
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on November 28, 2017, 10:11:58 AM
3. Palette memory
PPU contain dedicated memory of 512 bytes for Palettes, abbreviated as CGRAM. That memory can hold 256 colors. Depending of the Layer's BPP that memory is used differently:
- in 8bpp - we have 1 Palette containing 256 colors, entries: $00..$FF
- in 4bpp - we have 8 Palettes, occupying entries: $00..$7F
- in 2bpp (Mode 0) we have 8 Palettes for each layer: $00..$1F (BG1), $20..$3F (BG2), $40..$5F (BG3) and $60..7F (BG4)
* Sprites use 8 Palettes, occupying entries: $80..$FF

Uh-oh... This is going to be a problem for this project.
In FFIV, every character portrait and every PC battle sprite has a dedicated palette. So to use every palette I was planning to use, that would be a minimum of 16 palettes (11 portraits + 5 battle sprites). That means that hardware limitations will definitely prevent me from using the method I had originally intended for this project.

So now I have to rethink how this is all going to work.

The easy option would be to eliminate the battle sprites from the picture entirely, then use a gray palette for "inactive" characters, only using the proper palettes for characters currently in the party. This is not my favorite option. I think it would look cheap.

So looking through the documentation. It looks like Mode 1 uses one 4-color BG and two 16-color BGs... how are the palettes allocated in Mode 1?
I assume sprites get 8 palettes regardless of mode? Would that mean, then, that in Mode 1 there are eight 4-color palettes for BG3 and six 16-color palettes shared by BG1 and BG2?
That still wouldn't be ideal - I'd still have to gray-out the portraits of inactive characters, but I could bring back the battle sprites (they could be a BG). Then, what I could do is have the active party's portraits in color, as well as the highlighted inactive character's portrait (all other portraits would share a grayscale palette)...
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on November 28, 2017, 04:19:09 PM
Quote
So looking through the documentation. It looks like Mode 1 uses one 4-color BG and two 16-color BGs... how are the palettes allocated in Mode 1?
I assume sprites get 8 palettes regardless of mode? Would that mean, then, that in Mode 1 there are eight 4-color palettes for BG3 and six 16-color palettes shared by BG1 and BG2?
Excellent observations, m8!
You actually answered to to your question :) and shared a good observation (something that I should had mention it): all 4bpp Layers share same pool of palettes.
Yes because of BG3 we loose 2 Palettes in Mode 1. Keep in mind that each BG could be turned off, so we can use all 8 Palettes.

Quote
Uh-oh... This is going to be a problem for this project.
In FFIV, every character portrait and every PC battle sprite has a dedicated palette. So to use every palette I was planning to use, that would be a minimum of 16 palettes (11 portraits + 5 battle sprites). That means that hardware limitations will definitely prevent me from using the method I had originally intended for this project.
Let me ask you something:
- What is the max number of colors for BG3 in Mode1?
- What is the max number of colors for BG1 in Mode1 with BG3 on?
- What is the max number of colors for BG1 in Mode1 with BG3 off?

Lets think globally:
We will have 14 different Palettes (6 from BG and 8 from Sprites). That may net you 210 different colors on the screen. That is close to VGA in PC. That is many times more colorful then 90% of all games for SNES.
Of course we can't use both Sprite & BG palettes from one Tile. Lets take the BGs - 6 palettes with max 90 colors. Lets say we use only BGs for the whole PHS. You have 90 colors and 6 palettes. You don't have to limit 1 portrait with 1 palette. You may use all 6 palettes from each portrait. Remember the limitation is a Pal for a Tile, but a portrait composed by 3x3 or 4x4 (not sure what you will use) may use all 6!!! Imagine how cool a portrait will look in 4x4 tiles (64x64 pixels) with 90 colors
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on November 28, 2017, 05:44:09 PM
I think you might be misunderstanding my intentions for this project...
I'm not creating any new images or palettes for the PHS. The portraits I'll be using are the same portraits from the menu ("push X") screen. The portraits are already locked into a dedicated palette for each.
One of the primary goals of this hack is that it can easily be used as a base for other hackers' projects, so I want to avoid creating original content.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on November 28, 2017, 06:39:06 PM
My goal is by knowing how things work, to give you (as an artist) the freedom to create. If you want to restrict yourself ... OK :D
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on November 28, 2017, 07:24:58 PM
Oh, I know, and I do appreciate that, but I am necessarily restricted by the particular scope of this project.
That doesn't mean that I won't eventually have a creative application for what you're teaching me here, but I don't need all of it for this project.
Still, I'm using the tools you're providing here to formulate a workable plan for the project as originally conceived.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on December 13, 2017, 11:53:14 PM
Hello, dear readers.
Quick status update. There isn't much to show, since there is a lot of coding to do for what will end up being just one (dynamic) screen.
Here is the visible portion I have so far:
(http://memberfiles.freewebs.com/22/01/115500122/photos/undefined/Final%20Fantasy%20II%20(U)%20(V1.1)000.png)

The window on the left will display the portraits of the characters currently in the party (except Cecil, as he will not be swappable). The small window to the right of that will display the name of the character the finger cursor is pointing at. The large window on the right will display the portraits of the available characters not currently in the party. Due to palette limitations, those portraits will be displayed in black and white until pointed to by the finger. The small space in between the windows towards the top will show the battle sprites of the current party (including Cecil).

There's a lot to do, and the going is slow, but this is really happening!
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Swordmaster on December 15, 2017, 01:47:54 PM
To quote Alucard from Castlevania: Symphony of the Night, "I'm interested in this."
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on December 22, 2017, 02:26:33 AM
Sorry chillyfeez, just for the sake of completion: SNES PPU Tutorial (https://drive.google.com/file/d/1GGZDANvWr6LOiSLRDvtLrlBrOKx-Y4aM/view?usp=sharing)
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on December 23, 2017, 12:12:44 AM
Cool, Squall, good to have the whole thing in one place.

I haven't had a whole lot of time to work on the project lately. I got a couple of hours in today, but it was all background stuff - literally and figuratively.

A couple of days ago I took out the routines that draw the battle character graphics into the Namingway screen as sprites, because in this mod they'll actually be part of a BG screen. Then I wrote the first part of the routine that will load the battle character tiles into VRAM. But today I realized that the same routine I removed also draws the battle character images in the Load Saved Game screen, so today was spent reworking those changes so that the sprites still load there, but not in my PHS screen.

Anyway, blah-blah-blah, right? I'll keep you guys updated as I make progress when there is progress worth mentioning.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Gedankenschild on December 26, 2017, 01:43:40 PM
The 3bpp to 4bpp explanation was interesting to read. I kinda knew it already but couldn't have explained it myself with the right terminology. Lots of good info here.

Did you consider using overworld sprites for the selection screen, chillyfeez? That would only require 3 (or is it 4?) palettes due to the sharing.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on December 26, 2017, 05:23:45 PM
It's 4, and I did consider it for that reason, but in the end I think those images are too small relative to the screen.
I'm pretty sure the plan I've got will work, and it should look pretty cool once I've got it all working.
Is Squall's tutorial responsible for the better understanding you spoke about on RHDN?
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: thepatirckinator on December 26, 2017, 11:32:16 PM
I'm sure that Cecil cannot be replaced like other 2D Releases of Final Fantasy IV.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Gedankenschild on December 27, 2017, 01:40:27 PM
It's 4, and I did consider it for that reason, but in the end I think those images are too small relative to the screen.
I'm pretty sure the plan I've got will work, and it should look pretty cool once I've got it all working.
Is Squall's tutorial responsible for the better understanding you spoke about on RHDN?

That makes sense. The Final Fantasy V job selection screen does the same thing, graying out all jobs except for the currently selected one. I think it's always a good idea to look at other games in the series and see how things are handled there.

And yes, Squall's tutorial was indeed helpful. Bits, bytes, planes - I know what to do but not what to call it oftentimes... :whoa:
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on December 27, 2017, 05:19:14 PM
There are a lot of reasons that Cecil will not be removable from the party, but the main reason is that, for the purpose of this mod, it would just be too complicated. I'm working with very limited space in certain situations, and in order to make everything work right, I'm going to have to slash character records in such a way that I can fit everyone except Cecil. You, specifically, may be sad to hear that this also leaves no place for Golbez. Sorry, man.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: thepatirckinator on December 27, 2017, 08:47:39 PM
I know it's unfortunate we can't do anything about Golbez. An advantage is we can replace the useless ninja with everyone else.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on December 28, 2017, 11:41:01 AM
So, slow going, but yesterday I finally got the routine written that loads the battle character "sprites" into VRAM (they're not really sprites in this instance, as they are part of BG1). By tomorrow, I plan to finish the routine that actually displays the images of the characters currently in the party. At that point, I'll finally have some new screenshots to show off!
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on December 28, 2017, 05:34:59 PM
And yes, Squall's tutorial was indeed helpful. Bits, bytes, planes - I know what to do but not what to call it oftentimes... :whoa:
I'm glad the tutorial was helpful. Thats is one of the reason it was done here, rather in PM/chat.

So, slow going, but yesterday I finally got the routine written that loads the battle character "sprites" into VRAM (they're not really sprites in this instance, as they are part of BG1).
Wooah good progress! Would you like to share the code in ASM?

P.S. Since the tutorial was more of introduction rather detail coding, would you like to do some practical coding? I'm going to give standalone tasks, that doesn't require zillions of line of code, you must make the ASM code. We will test the result in emulators. I found a small library that produce all the initialization you need, so you can focus mainly on the task that I'm going to give. It doesn't require specific library (so you can implement whatever is on your mind, not limiting yourself to specific) but has defined all PPU registers for easy use (by name rather numbers). So far it produces small 32k ROM files that you can load in any emulator.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on December 29, 2017, 04:46:36 AM
Quote
Would you like to share the code in ASM?

Sure:

Code: [Select]
$01/BA78 A9 0D       LDA #$0D                A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0396 VC:000 FC:24 I:00
$01/BA7A 85 F0       STA $F0    [$00:01F0]   A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0412 VC:000 FC:24 I:00
$01/BA7C A9 10       LDA #$10                A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0428 VC:000 FC:24 I:00
$01/BA7E 85 F2       STA $F2    [$00:01F2]   A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0444 VC:000 FC:24 I:00
$01/BA80 A9 50       LDA #$50                A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0460 VC:000 FC:24 I:00
$01/BA82 85 F3       STA $F3    [$00:01F3]   A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0476 VC:000 FC:24 I:00
$01/BA84 A2 00 00    LDX #$0000              A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0492 VC:000 FC:24 I:00
$01/BA87 A0 60 00    LDY #$0060              A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0508 VC:000 FC:24 I:00
$01/BA8A 20 D0 BA    JSR $BAD0  [$01:BAD0]   A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0524 VC:000 FC:24 I:00
$01/BA8D C2 20       REP #$20                A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0548 VC:000 FC:24 I:00
$01/BA8F 8A          TXA                     A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envmxdIzc HC:0564 VC:000 FC:24 I:00
$01/BA90 18          CLC                     A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envmxdIzc HC:0580 VC:000 FC:24 I:00
$01/BA91 69 40 07    ADC #$0740              A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envmxdIzc HC:0596 VC:000 FC:24 I:00
$01/BA94 AA          TAX                     A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envmxdIzc HC:0612 VC:000 FC:24 I:00
$01/BA95 A5 F2       LDA $F2    [$00:01F2]   A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envmxdIzc HC:0628 VC:000 FC:24 I:00
$01/BA97 69 00 01    ADC #$0100              A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envmxdIzc HC:0644 VC:000 FC:24 I:00
$01/BA9A 85 F2       STA $F2    [$00:01F2]   A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envmxdIzc HC:0660 VC:000 FC:24 I:00
$01/BA9C E2 20       SEP #$20                A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envmxdIzc HC:0684 VC:000 FC:24 I:00
$01/BA9E C6 F0       DEC $F0    [$00:01F0]   A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0700 VC:000 FC:24 I:00
$01/BAA0 D0 E6       BNE $E6    [$BA88]      A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0716 VC:000 FC:24 I:00
$01/BAA2 64 F2       STZ $F2    [$00:01F2]   A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0732 VC:000 FC:24 I:00
$01/BAA4 64 F3       STZ $F3    [$00:01F3]   A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc HC:0748 VC:000 FC:24 I:00
$01/BAA6 60          RTS                     A:0C02 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIzc

This part of the routine essentially sets all of the variables that will be used 13 times over to copy the tiles for each character. The 0D written to 01F0 is used to count the number of times the routine loops. The 5010 written to 1F2 sets the address in VRAM where the data will be written (multiplied by 2, so it actually starts at $A020). The 0060 stored in Y counts the bytes of graphic data copied to VRAM - I'm only using the first $C0 bytes of each character, and since two bytes are written at a time we're counting down from half of C0. Register X functions as an index for the source of copied graphical data.

Code: [Select]
$01/BAD0 8B          PHB                     A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0020 VC:000 FC:28 I:00
$01/BAD1 A9 00       LDA #$00                A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0036 VC:000 FC:28 I:00
$01/BAD3 48          PHA                     A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0052 VC:000 FC:28 I:00
$01/BAD4 AB          PLB                     A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0068 VC:000 FC:28 I:00
$01/BAD5 8D 15 21    STA $2115  [$7E:2115]   A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0084 VC:000 FC:28 I:00
$01/BAD8 C2 20       REP #$20                A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0108 VC:000 FC:28 I:00
$01/BADA A5 F2       LDA $F2    [$00:01F2]   A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envmxdIZc HC:0124 VC:000 FC:28 I:00
$01/BADC 8D 16 21    STA $2116  [$7E:2116]   A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envmxdIZc HC:0140 VC:000 FC:28 I:00
$01/BADF E2 20       SEP #$20                A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envmxdIZc HC:0164 VC:000 FC:28 I:00
$01/BAE1 BF 00 80 1A LDA $1A8000,x[$1A:3D0C] A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0180 VC:000 FC:28 I:00
$01/BAE5 EB          XBA                     A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0196 VC:000 FC:28 I:00
$01/BAE6 E8          INX                     A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0212 VC:000 FC:28 I:00
$01/BAE7 BF 00 80 1A LDA $1A8000,x[$1A:3D0C] A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0228 VC:000 FC:28 I:00
$01/BAEB 8D 19 21    STA $2119  [$7E:2119]   A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0244 VC:000 FC:28 I:00
$01/BAEE EB          XBA                     A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0260 VC:000 FC:28 I:00
$01/BAEF 8D 18 21    STA $2118  [$7E:2118]   A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0276 VC:000 FC:28 I:00
$01/BAF2 E8          INX                     A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0292 VC:000 FC:28 I:00
$01/BAF3 88          DEY                     A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0308 VC:000 FC:28 I:00
$01/BAF4 D0 EB       BNE $EB    [$BAE1]      A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0324 VC:000 FC:28 I:00
$01/BAF6 7B          TDC                     A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0340 VC:000 FC:28 I:00
$01/BAF7 EB          XBA                     A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0356 VC:000 FC:28 I:00
$01/BAF8 AB          PLB                     A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0372 VC:000 FC:28 I:00
$01/BAF9 60          RTS                     A:0C00 X:BD0C Y:0300 D:0100 DB:7E S:02DD P:envMxdIZc HC:0388 VC:000 FC:28 I:00

And this is the part of the routine that actually copies the data into VRAM. You may notice that the routine writes the data one byte at a time by writing to $2119 and then $2118. I was originally under the impression that I could write a two-byte value to $2118, but it turns out that doing so copies the two bytes to bytes $00 and $02 in VRAM, which is weird and unhelpful. But I figured out this workaround, so no problem.


The end result of all this has the tile data written as characters 01, 02, 03, 04, 05, 06, 11, 12, 13... D6. This leaves a lot of unused space in VRAM, but is much easier to index.

Quote
Since the tutorial was more of introduction rather detail coding, would you like to do some practical coding? I'm going to give standalone tasks, that doesn't require zillions of line of code, you must make the ASM code. We will test the result in emulators. I found a small library that produce all the initialization you need, so you can focus mainly on the task that I'm going to give. It doesn't require specific library (so you can implement whatever is on your mind, not limiting yourself to specific) but has defined all PPU registers for easy use (by name rather numbers). So far it produces small 32k ROM files that you can load in any emulator.

Yeah, that sounds like a good exercise. Not sure when I'd be able to get to it, but let's see what you've got.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on January 01, 2018, 12:11:17 PM
Every start is usually slow, so I'm using the whole after all the celebrations to set a common ground

1. Good assembler compiler. We going to use WLA.
I know you don't care but productivity depends on the usefulness of the tool you use. WLA seems to have all the ability I need (as macro-assembler) and I haven't heard negatives about it.
LINKs:  Official site (http://www.villehelin.com/wla.html),  Source code (https://github.com/vhelin/wla-dx), Win32 executable (http://www.villehelin.com/wla-win32/wla-dx-9.5-win32-bin-2013-SVN-rev8-WJ.zip).

2. Good Editor.
I use Notepad++, but feel free whatever you have or know better.
Download (https://notepad-plus-plus.org/download/v7.5.4.html)

3. SNES framework.
This is our framework to get started. It has all necessarily to compile a ROM. We will pretty much get an example, make it blank and inject our code.
LINK: Framework (https://github.com/michielvoo/SNES/tree/master/examples)

4. SNES Emulator
Use whatever your preferences is, but higan will be used as final judge (if something doesn't work)

5. BAT file
Because of the way WLA works, we will need to execute different files, create temporary files, clear the trash ... its easier this to be automated.
Code: [Select]
set WLAPath=..\..\wla_dx_9.2\binaries\
set ProjectName=done

echo [objects] > temp.prj
echo %ProjectName%.obj >> temp.prj

%WLAPath%\wla-65816.exe -o %ProjectName%.asm %ProjectName%.obj
%WLAPath%\wlalink.exe -vr temp.prj %ProjectName%.smc

del %ProjectName%.obj
del temp.prj

pause

P.S. If somebody know how to compile trough Notepad++, please share. Also if you know an editor dedicated on 65x02 assembly, please let me know
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on January 03, 2018, 10:31:06 AM
*whew*

writing these routines took quite a bit longer than I expected, but it works!

Some screenshots, which show off the ability to load different palettes depending on who's in the party, and also the ability to determine if a slot is empty, and leave the space blank:

(http://memberfiles.freewebs.com/22/01/115500122/photos/PHS/Final%20Fantasy%20II%20(U)%20(V1.1)003.png)

(http://memberfiles.freewebs.com/22/01/115500122/photos/PHS/Final%20Fantasy%20II%20(U)%20(V1.1)002.png)

(http://memberfiles.freewebs.com/22/01/115500122/photos/PHS/Final%20Fantasy%20II%20(U)%20(V1.1)001.png)

Ignore the image of Namingway in the top corner. He won't be there anymore once I swap out the routine that loads him for the one that will load the character portraits.

For those interested in seeing the ASM:

Main Routine
Code: [Select]
$01/9DF5 A9 00       LDA #$00   
$01/9DF7 85 F0       STA $F0   
$01/9DF9 A2 00 00    LDX #$0000
$01/9DFC DA          PHX        ;Preparing registers
$01/9DFD 22 60 FD 0B JSL $0BFD60 ;Routine that assigns palettes 1-5 (04,08,0c,10,14) to each character graphic
$01/9E01 A0 00 00    LDY #$0000
$01/9E04 FA          PLX       
$01/9E05 22 85 FD 0B JSL $0BFD85 ;Routine that determines if a character is present in each slot, and if so loads the appropriate tiles
$01/9E09 22 AC FD 0B JSL $0BFDAC ;Routine that loads the appropriate palette for each character
$01/9E0D C2 20       REP #$20   
$01/9E0F 8A          TXA       
$01/9E10 18          CLC       
$01/9E11 69 40 00    ADC #$0040
$01/9E14 AA          TAX       
$01/9E15 98          TYA       
$01/9E16 18          CLC       
$01/9E17 69 06 00    ADC #$0006
$01/9E1A A8          TAY       
$01/9E1B E2 20       SEP #$20   
$01/9E1D E6 F2       INC $F2   
$01/9E1F C6 F0       DEC $F0   
$01/9E21 D0 E2       BNE $E2    ;Loops back to 19E05 to run four more times, for each character slot
$01/9E23 64 F2       STZ $F2   
$01/9E25 20 B2 80    JSR $80B2  ;DMA transfer of all palette data into CGRAM
$01/9E28 20 36 94    JSR $9436  ;DMA transfer of tilemap into VRAM
$01/9E2B 60          RTS       

Palette Assignment Routine:
Code: [Select]
$0B/FD60 A9 02       LDA #$02   
$0B/FD62 85 F2       STA $F2   
$0B/FD64 A5 F0       LDA $F0   
$0B/FD66 1A          INC A     
$0B/FD67 0A          ASL A     
$0B/FD68 0A          ASL A     
$0B/FD69 9D 63 B7    STA $B763,x
$0B/FD6C 9D A3 B7    STA $B7A3,x
$0B/FD6F 9D E3 B7    STA $B7E3,x
$0B/FD72 E8          INX       
$0B/FD73 E8          INX       
$0B/FD74 C6 F2       DEC $F2   
$0B/FD76 D0 F1       BNE $F1   
$0B/FD78 E8          INX       
$0B/FD79 E8          INX       
$0B/FD7A E6 F0       INC $F0   
$0B/FD7C A5 F0       LDA $F0   
$0B/FD7E C9 05       CMP #$05   
$0B/FD80 D0 DE       BNE $DE   
$0B/FD82 7B          TDC       
$0B/FD83 EB          XBA       
$0B/FD84 6B          RTL       

Character Tile Assignment Routine:
Code: [Select]
$0B/FD85 BD 00 10    LDA $1000,x
$0B/FD88 F0 21       BEQ $21   
$0B/FD8A BD 01 10    LDA $1001,x
$0B/FD8D 48          PHA       
$0B/FD8E 0A          ASL A     
$0B/FD8F 0A          ASL A     
$0B/FD90 0A          ASL A     
$0B/FD91 0A          ASL A     
$0B/FD92 1A          INC A     
$0B/FD93 99 62 B7    STA $B762,y
$0B/FD96 1A          INC A     
$0B/FD97 99 64 B7    STA $B764,y
$0B/FD9A 1A          INC A     
$0B/FD9B 99 A2 B7    STA $B7A2,y
$0B/FD9E 1A          INC A     
$0B/FD9F 99 A4 B7    STA $B7A4,y
$0B/FDA2 1A          INC A     
$0B/FDA3 99 E2 B7    STA $B7E2,y
$0B/FDA6 1A          INC A     
$0B/FDA7 99 E4 B7    STA $B7E4,y
$0B/FDAA 68          PLA       
$0B/FDAB 6B          RTL       

Character Palette Loading Routine:
Code: [Select]
$0B/FDAC DA          PHX       
$0B/FDAD 5A          PHY       
$0B/FDAE C2 20       REP #$20   
$0B/FDB0 0A          ASL A     
$0B/FDB1 0A          ASL A     
$0B/FDB2 0A          ASL A     
$0B/FDB3 0A          ASL A     
$0B/FDB4 0A          ASL A     
$0B/FDB5 AA          TAX       
$0B/FDB6 A5 F2       LDA $F2   
$0B/FDB8 0A          ASL A     
$0B/FDB9 0A          ASL A     
$0B/FDBA 0A          ASL A     
$0B/FDBB 0A          ASL A     
$0B/FDBC 0A          ASL A     
$0B/FDBD A8          TAY       
$0B/FDBE E2 20       SEP #$20   
$0B/FDC0 A9 20       LDA #$20   
$0B/FDC2 85 F4       STA $F4   
$0B/FDC4 BF 00 FD 1C LDA $1CFD00,x
$0B/FDC8 99 20 A0    STA $A020,y
$0B/FDCB E8          INX       
$0B/FDCC C8          INY       
$0B/FDCD C6 F4       DEC $F4   
$0B/FDCF D0 F3       BNE $F3   
$0B/FDD1 7A          PLY       
$0B/FDD2 FA          PLX       
$0B/FDD3 6B          RTL       


The next step in this process will be writing in the system that stores and retrieves characters to and from the "shadow." This will probably also take a considerable amount of time, and there won't really be any screenshots to show for my work when it's all done, but I will post the ASM as relevant routines are completed.

 :cycle:
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: thepatirckinator on January 04, 2018, 12:40:25 PM
I look forward to the final product!
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Grimoire LD on January 08, 2018, 01:26:29 PM
That looks great Chillyfeez! I am glad to see you finally managed to make it presentable in-game, that is an incredible start! I know how difficult it is to deal even with the most basic of graphical GUI changes.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on January 09, 2018, 09:14:25 AM
Thanks!
I spent the better part of yesterday just preparing a ROM to reinvestigate the add character/remove character/re-add character routines, which was an unflinching reminder of what a massive undertaking this project is going to be. With a lot of hard work, I'm still probably a month away from a final product. But at least it has a visible end. You know, unlike TfW which will probably be a WIP until just before I die =p

I've got a routine worked out that will add the equipment of a removed character into the player's inventory, or bring up the "choose what to keep" screen if the player's inventory is full. I'm pretty sure it will work, but I'm nowhere near the point where I can actually write it into ROM and run it, so there's not really anything to show ATM.

The other thing I did is create a ROM with FF4kster that gives me easy access to all of the different party-change situations. Essentially, I turned the town of Baron into a sort-of debug room. The four buildings across the front of the town are now Rydia House, Kain House, Tellah House and Edward House.
In Rydia House, there are two Kid Rydias and Two Adult Rydias, which will add and remove the respective character when spoken to.
In Kain House, there are three Kain's - one which adds Kain from ROM, one which adds Kain from RAM, and one which removes either Kain from the party.
In Tellah House, there are four Tellahs. One adds Tellah (from ROM), one removes Tellah, one "transforms" Tellah into his ultimate version (like what happens on Ordeals) and one removes ultimate a version Tellah.
Edward House just has two Edwards - one to add Edward and one to remove him.

If I'm not mistaken, this should be an example of every kind of party change dynamic in the game, which will allow me to breakpoint the add character and remove character functions in order to see all of their routines in action.

All of that was just prepwork to begin investigating what normally happens so I can formulate a plan for how I'm going to hack it.

Good times...
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Swordmaster on January 11, 2018, 06:43:00 AM
Just curious, but what will you do about FuSoYa and the Zemus/Zeromus autobattles?  It would be cool if you could use even FuSoYa at the end of the game without breaking the story or the autobattles.  I'm not requesting or anything, just wondering.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on January 12, 2018, 08:39:55 AM
In terms of FuSoYa's availability for the final battle, I plan to have him available.

Because the PHS system is replacing the Namingway screen, it will be relatively simple to insert a set-your-party prompt into an event.

As for making FuSoYa available through PHS when he wasn't before, that's been accounted for. When a character is removed from the party, they will be set automatically to a "Not Available in PHS" status (which PHS will recognize by the MSB being set in the character's level byte) When an event script calls for "Add Character to Party," the routine will check that level byte. If the MSB is set, then the "Add Character to Party" command will simply clear the bit. If the bit is not set, then the character will be added to the party. It's a relatively simple way to work PHS availability into event scripts without disrupting much else. Of course, it will require me to edit every already-existing event to add an extra "Add Character" command every time a character is actually supposed to be added, but I consider that a small price to pay in the long run.

As far as not-in-party characters participating in autobattles (I guess FuSoYa is the only one, but I may face a similar type of situation with the Cecil vs. Cecil battle and Adult Rydia's return), I'm not fully sure how this will work yet, but I'm confident that I can figure it out when necessary.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Swordmaster on January 12, 2018, 12:54:56 PM
I feel this will be a masterpiece when completed, chillyfeez.  A must for nearly every hack.  This has always been my #1 wish for this game, even way back when it was first released.  #2 wish would be some sort of new game plus where you could choose any character(s) from the very beginning, story be damned (sort of like Lufia II Gift Mode, but for the whole game.  Which, by the way, is really fun to do with Lufia II.  Start a new Gift Mode game, use a code for "airship anywhere", fly to the starting town and begin the story.  You can always warp back to Gruberik to change your party at any point in the game.)
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on January 12, 2018, 02:27:27 PM
Well, thanks! I sure hope it all turns out as well as I envision it. So far I haven't hit any major roadblocks!
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: thepatirckinator on January 13, 2018, 09:11:17 PM
Good! I'm sure it will work out in the end.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on February 23, 2018, 08:07:33 AM
Update time!

Progress has been slower than I had hoped it'd be, but I have a LOT of RL stuff going on these days.

Anyway, I perfected the part of the mod that enables the player to keep a character's equipment when they depart.

If the character is set to "discard," then equipment is lost, but if they are set to a shadow slot the player will have the option of keeping their equipment. In the full mod, this will be a choice depending on whether it makes sense in the story - you won't get to keep any of the equipment from characters lost in the shipwreck, but you'll get to keep Cid's stuff.

https://youtu.be/T7gjur_2-v4
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: Squall on February 23, 2018, 08:43:16 AM
Nice scrolling of the top-right part!
Did you do it or its part of the game?
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on February 23, 2018, 09:38:32 AM
No that's all part of the game. The only thing I'm showing off here is that I was able to make the "choose what to take" screen appear when a character departs, if and only if a) the character has items equipped, and b) The character has a particular flag set to indicate that their equipment is "keep-able."
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: thepatirckinator on February 23, 2018, 10:23:15 AM
Obviously, the characters that leave and rejoin the party in the storyline keep their equipment including Cecil other than Cecil's class change from Dark Knight to Paladin.
Title: Re: Chillyfeez's Shadow Party Hack V 2.0
Post by: chillyfeez on February 23, 2018, 06:01:13 PM
My plan is more to make it "does it make sense that the character would leave his/her equipment?" So, the people in the shipwreck won't leave their equipment, because why would they stop to take all their armor off before falling off the boat? Every time Kain leaves it is sudden and "unexpected," too, so he won't leave his equipment. Cid, however, is like, "I'm gonna stay here in the dwarf castle for a while, see ya later!" So it makes sense that the party would be like, "OK, but can we have all those weapons and armor back that we spent all that money on?"
Tellah dies right in front of you. It's kinda weird, but the party could choose to take his equipment off before they move on to save Rosa.
So I'll be looking at each departure and deciding if it makes sense story-wise that they might leave their equipment benind.