How do Triangle Draws Work?

This is a place to post tech details and informative documents about romhacking PSP games.
Post Reply
flamethrower
Programmer
Posts: 995
Joined: Mon Mar 09, 2015 3:03 pm

How do Triangle Draws Work?

Post by flamethrower » Sun Jan 24, 2016 2:43 am

For PPSSPP, there is this thing called display list.
2.jpg
2.jpg (126.82 KiB) Viewed 6684 times
Here it's doing the first draw, using TRIANGLE_STRIP, whatever that means. The COUNT is the number of vertices that are being consumed on the draw. For whatever reason, this is always an even number. Because one "entry" in the display list (we'll see them later) consumes one pair of coordinates. Here, it's drawing "Lloyd" (5 letters). So it needs 4 vertices (two pairs) for each one letter. I really don't know what's going on.

You see clearly the VADDR: 0x90EA660. The V stands for vertex, if you're wondering.
And then above that you see another, super-important thing. It's SetVertexType.
"through" I have no idea what this means. I've never seen a draw command that didn't use "through," though.
float texcoords: The texture coordinates in the vertices will be floating point.
ABGR 8888 colors: This means there will be four bytes for the color. I've never seen a draw command that wasn't this.
s16 positions: The target coordinates will be integers.
One more thing: The Y-positions are offsets from the top of the image, and the X-positions are offsets from the left. It is the same with texture coordinates.

About PPSSPP controls in GE Debugger:
STEP FRAME advances one frame.
STEP TEX advances until the next texture is loaded.
STEP DRAW advances until the next draw command.
STEP and RESUME work just like the R4 debugger.
-------------------------------
Next, we go to VERTEX ADDRESS in order to see the display list. Since this text isn't changing on screen, the display list for this will be relatively static and won't change, in most games.
8.png
8.png (4.87 KiB) Viewed 6684 times
Here you see the display list.
First one: TEX: X = 96.5 (0x42C10000), Y = 111.5 (0x42DF0000); color = 0x000000FF (I think it's black?); POS: X=194, Y=29 (I don't know what the 0xFFFFFFFF is on the end)
Next one: TEX: X = 96.5, Y = 96.5; color = 0x000000FF; POS: X = 194, Y = 15

If we look at sfont, the TEX:
sfont.png
sfont.png (9.87 KiB) Viewed 6684 times
96, 111 is the lower-left corner of the L in sfont.
96, 96 is the upper-left corner of the L in sfont.
As for positions, it's the same: The lower left and upper-left corners of the L.

Next two:
Tex: 103.5, 111.5; Pos: 201, 29
Tex: 103.5, 96.5; Pos: 201, 15
That's the right corners of the L.

From here, it goes on to the next letter.
So, a triangle draw really uses four vertices?
The rectangle draw needs only two vertices in order to draw...a rectangle.

If you backtrace it, you can see instructions that build up the display list. Any floating-point operations always involve the coprocessor.

One thing to investigate is the between-letter X-distance (it can give a clue as to what's going on). It looks like 7 pixels between each letter in the X-direction. So keep a lookout for that as you look through the MIPS code. I was looking, and it looks like it's loading the value 7 at 0898B2A8.
Edit: 0898B260 looks suspicious as well.
Edit: I now think it's 0898AF1C.
Edit: Okay, time for a new post?

flamethrower
Programmer
Posts: 995
Joined: Mon Mar 09, 2015 3:03 pm

Re: How do Triangle Draws Work?

Post by flamethrower » Sun Jan 24, 2016 3:47 am

I produced these:
NPJH50311_00068.jpg
NPJH50311_00068.jpg (43.25 KiB) Viewed 6678 times
NPJH50311_00067.jpg
NPJH50311_00067.jpg (42.46 KiB) Viewed 6678 times
The magic register is f2, I think, at least for VWF. Also observe that the "m" is still not fixed. I have no idea how to fix it, actually. This is just "manual-ish" modifications of f2. And you see it makes it narrower and wider. Maybe what is needed is adding "1.0" to the x coordinate after drawing and before it gets stored for use on the next pass. That way, the display list draws won't overlap each other by one pixel anymore. I'll give that a try.

The next step is to ID the part of the algo that translates the actual letter into the texture coordinates of that letter. Which it must do, otherwise it could never draw even a single letter. I think that part is at 0898B384. Once we actually know that, we can jump to our super-special awesome routine that spies on which letter it is drawing and modifies f2 accordingly. In this way, the width for each letter can be adjusted individually (rather than grossly as in the examples above), creating a variable-width font!
Note: Don't get too excited. I don't know if it will actually work yet.

After that's done, the next step will be adjusting the TEX so that each letter is on the left side of its tile. You can't draw a good VWF with letters in the middle of their tiles.

User avatar
zeromonkey
Hacker, script editor and control freak
Posts: 486
Joined: Thu Mar 05, 2015 3:10 pm
Location: Tennessee

Re: How do Triangle Draws Work?

Post by zeromonkey » Sun Jan 24, 2016 8:39 pm

Very interesting information. Progress is being made one way or the other. I can wrap my head around some of it and some of it is above my hacking level (MIPS). I will say this, go ahead and work all the magic you want to on the eboot. Get all the hacks and tweaks into a single file. We can then go back and edit the dialog into that one instead of trying to patch them into the one I have. Because changing the fonts and various other things will open up a whole new realm of possibilities. Really cool stuff. I'll focus on dialog related stuff and less hacking while you look at this stuff. After you get done with it, I think we should create a patch for quickly patching the eboot when we need to apply the hacks to a clean one.

flamethrower
Programmer
Posts: 995
Joined: Mon Mar 09, 2015 3:03 pm

Re: How do Triangle Draws Work?

Post by flamethrower » Mon Jan 25, 2016 1:19 am

It's just a curiosity at this point, I think.
If we do manage to get it working, then it'll give more characters per line in most situations in-game, I think. And it'll make the job of making "line leveling" (making the lines in each text box the same length) IMPOSSIBLE.

It's just a curiosity at this point. I was on the totally wrong track, unfortunately. That's not to say yesterday's investigation was fruitless. Knowing the character width will help. I mentioned this earlier if you were paying attention. But changing the character width won't help at all. What we really need is to change the character spacing - the distance between each character.

Letter load is at 0x0898B384, a3 points to current letter
Display list creation is at 0x0898B258
Start of vertices (that actually get written): 0x090EA4D0

So it knows where the left of the first letter should go. From there, it's a multiplication problem. That's great for fixed width font, but won't work for our purposes. We have to change the multiplication step to storage and load steps.

User avatar
zeromonkey
Hacker, script editor and control freak
Posts: 486
Joined: Thu Mar 05, 2015 3:10 pm
Location: Tennessee

Re: How do Triangle Draws Work?

Post by zeromonkey » Mon Jan 25, 2016 10:58 pm

Would it help to make a quick new font (not a permanent) to test if it is possible? Something with the characters properly aligned to the left?

flamethrower
Programmer
Posts: 995
Joined: Mon Mar 09, 2015 3:03 pm

Re: How do Triangle Draws Work?

Post by flamethrower » Tue Jan 26, 2016 2:53 am

No, unfortunately that will not help.
-----------------------------
Another day, another failed test.
9.png
9.png (273.19 KiB) Viewed 6639 times
NPJH50311_00069.jpg
NPJH50311_00069.jpg (45.47 KiB) Viewed 6639 times
Failure analysis:
I modified it so it is drawing the letters on top of each other (note that it does not do this on the original). I am just moving the x-position back by 2 pixels for each letter, so that they draw on top of each other. From here I can modify so that it's individual for each character, but... It's no good in terms of quality so I won't do that just yet.

This worked in other games, really. I think it is because TRIANGLE_STRIP is being used.
Read on Wikipedia (of all places) about TRIANGLE_STRIP: https://en.wikipedia.org/wiki/Triangle_strip
This is also why the draw looks funky in GE Debugger. It'd look fine if it was RECTANGLES.
Just as a test, you can load up the original game and see that it uses RECTANGLES for SHIFT-JIS text.
If we modify it to be RECTANGLES (an invasive modification), then it will probably work.

Okay, I'm probably just an idiot. Alright, that much was certain.
My next idea is to change so that certain draws are transparent color (so you can't see them).
This is 8x16 font, I think that's the size of the draws too. See those artifacts? They are 2x16 in size, I think.
It's hard to explain, but... Since it's TRIANGLE_STRIP:
1) Set base position
2) Draw the letter
3) Reset the base position
4) Draw the next letter
etc...
On the "reset" draws, it changes texture coordinates, but doesn't change positions. This means that nothing is drawn on the screen on the reset draws. But in my modified version, I do change positions on those "reset" draws. Since the positions are changing, "stuff" is being drawn on the screen. Note: The positions don't change very much even on my modified "reset" draws, which is why those artifacts took like they do.
For more on the reset draws, look at what Wikipedia says about degenerate strips, which is basically drawing triangle strips that don't draw anything.
OK, my idea is to change the color of the "reset" draws to be transparent. Let me give that a try.
---------------------
Nope, that didn't work either. I think it has to be changed to a rectangle draw to work properly.

Draw command addresses = 090EA860 (name), 090EAC4C (name2), 090EB38C (text), 090EBACC (text2)
Change to RECTANGLES: Change 089E8200 to lui v1, 0x406 (0604033C)

Tex Coords:
0898B2F8 - Write x-origin (should be f3, x-origin) OK as is, no changes required
0898B2F4 - Write y-origin (should be f5, y-origin) (040005E5)
0898B338 - Write x-destination (should be f6, x-dest) (0000C6E4)
0898B330 - Write y-destination (should be f4, y-dest) (0400C4E4)
Positions:
0898B2B8 - Write x-origin (should be v0, x-origin) OK as is, no changes required
0898B2E0 - Write y-origin (should be ra, y-origin) (0E001FA5)
0898B2C4 - Write x-destination (should be a1, x-destination) (0000A5A6)
0898B300 - Write y-destination (should be v0, y-destination) (000082A6)

flamethrower
Programmer
Posts: 995
Joined: Mon Mar 09, 2015 3:03 pm

Re: How do Triangle Draws Work?

Post by flamethrower » Tue Jan 26, 2016 4:41 am

Non-funky draw get!!! Haha! See how not weird that looks!?
10.png
10.png (272.88 KiB) Viewed 6631 times
Note: The drawn image looks the same as usual ("normal") so I'm not going to post it.

SkyeWelse, do I need to worry about using up too much bandwidth or disk space with these pictures?
There's 1MB+ already just on this page...

Font shifter: http://pastebin.com/PMdggtc9

User avatar
SkyeWelse
Graphics & Web Design
Posts: 490
Joined: Thu Mar 05, 2015 4:32 am
Location: Georgia
Contact:

Re: How do Triangle Draws Work?

Post by SkyeWelse » Tue Jan 26, 2016 6:11 am

flamethrower wrote:SkyeWelse, do I need to worry about using up too much bandwidth or disk space with these pictures?
There's 1MB+ already just on this page...
I wouldn't worry about it. If you want though, you can visit the site tinypng.com and feed the panda your images and he'll regurgitate it as a much lower size that will be optimized with virtually no drop in image quality.

-Thomas

flamethrower
Programmer
Posts: 995
Joined: Mon Mar 09, 2015 3:03 pm

Re: How do Triangle Draws Work?

Post by flamethrower » Wed Jan 27, 2016 4:56 am

NPJH50311_00071.jpg
NPJH50311_00071.jpg (42.94 KiB) Viewed 6606 times
This is text.
NPJH50311_00072.jpg
NPJH50311_00072.jpg (42.98 KiB) Viewed 6606 times

flamethrower
Programmer
Posts: 995
Joined: Mon Mar 09, 2015 3:03 pm

Re: How do Triangle Draws Work?

Post by flamethrower » Thu Jan 28, 2016 12:28 pm

NPJH50311_00073.jpg
NPJH50311_00073.jpg (42.34 KiB) Viewed 6591 times
It's messing up on lines that have more than one string. But all characters are still legible. Probably pretty hard to fix.
It's also messing up on the title screen. "Push Start" and "The Legend of Heroes Zero no Kiseki" don't display. I don't think this one will be too hard to fix. These draws can be modified to use a rectangle draw, and that will fix the bug.
Don't worry if spacing isn't to your liking. You'll be able to adjust as necessary. Easily, even.

armips .asm script: http://pastebin.com/kyGw6EG8

File package (see attached)
You need your EBOOT, then run the .bat file (it just runs armips)
Then pack and test. Good luck!
This .asm has the fixes from previous hacking efforts too, so it's one less thing to keep track of.
It still needs the JamRules fix for certain text displays.

How the spacing works:
0x01 means 1 pixel extra (wider)
0xFF means 1 pixel less (narrower)
(default spacing is 7)
Characters not in the table will use default spacing.
Lines with SHIFT-JIS characters in them won't use the VWF.

How to adjust at runtime:
CTRL+D
Click in the memory view
CTRL+G, 0x8A661E0, enter
Manually change the values in the VWF table. You can add new letters too, if you want.
This table is read I think every frame, maybe it's every other frame. Anyway, you'll see the effect of your changes immediately.

How to adjust permanently:
Edit the .asm script. Look @ line 73 for the start of the VWF table.
Re-run armips and insert.
You could just use a hex editor, but where's the fun in that!? And if you're in a sharing mood, it will be easier to share your changes. You will only need to share your modified .asm script.

Download compiled armips: https://www.mediafire.com/?bafcp5ij45jjcja (5MB download)
---------------
30Jan16:
A lot of backtracing today.

Quest 1: Title screen restore (this was an easy one)

Code: Select all

//Menu Screen Fix
.org 0x88BD474
	mul.s	f20, f25, f20
.org 0x88BD484
	mov.s	f13, f20
	lw	a3, 0x14(sp)
Quest 2: Text box size restore.
This was a hard one. There's still a little more to do now, but it seems doable.
1. The box draw routine is at 0x088F2388. There's a little entry into that routine at 0x088F46EC.
I messed around with this. You can change the x-origin and y-origin of the boxes by messing with the values in 0x088F46EC.

I ended up using the hunt and peck method. This routine prepares a triangle draw with 108 vertices.
Maybe the best method is to estimate the x-destination position and then look for that value in the positions.
So I found that 0x088F258C lw v0,0xE8(t2) is loading the width of the text in the box.

2. Backtracing that, I got to 0x088F5538. This code gets hit only when a new box is generated.
If you change 0x088F5538 to li v1, 0x6, it will assume all the letters are six pixels wide (instead of the default 7) and everything ends up looking pretty nice.
I could do even better than this though by computing the actual width for each letter based on the VWF table.

User avatar
zeromonkey
Hacker, script editor and control freak
Posts: 486
Joined: Thu Mar 05, 2015 3:10 pm
Location: Tennessee

Re: How do Triangle Draws Work?

Post by zeromonkey » Mon Feb 01, 2016 11:18 pm

I have read all the information but my brain isn't doing a lot of processing today. Have you been able to locate the character table thing that tells how many pixels wide/high stuff is? If I missed the information, please point me in the right direction. Reason I ask, is we can make another font and maybe make them look good. I know M and W are some of characters that could use for custom sizes. I mean you can limit them to less than 8 pixels, but they look really cramped. I'm probably talking out of my head, been in the rain all day and staring at the bottom of a combine.

flamethrower
Programmer
Posts: 995
Joined: Mon Mar 09, 2015 3:03 pm

Re: How do Triangle Draws Work?

Post by flamethrower » Tue Feb 02, 2016 12:28 am

There is no width table. This is a fixed-width font. The width is always 8 for the texture coordinates and always 7 for the positions.
I could change it so that width is 8 for the positions as well. Would that help? I think we can change it so the value is different for each letter, too. Is that what's needed?

What you're asking for sounds impossible. The game is expecting 8x16 tiles. I don't think I can make it do something that isn't 8x16 tiles. And another thing: I think it's only looking at an 8x15 slice of each tile. I could be wrong though.

It's possible, I just don't want to spend the time to do it. I don't want to do the asm programming work to modify the part that loads the texture coordinates. I didn't touch that part, except as necessary to accommodate the rectangle draw.

Edit, it sounded impossible at first glance, but... I think it's actually not that hard.
So, you want to vary the actual width for each letter. Like make some letters super wide like those earlier examples, and some letters narrow, like those earlier examples. Is that correct? For the actual letters themselves (in the texture), we have to stick with an 8x16 tile though. I don't want to do that asm work.

If you want to put your own 8x16 font in, I think it's possible. I can think of a pseudocode. First you need to understand something though.
It is Tahoma 12 pt (rendered in MS word, but I don't think that matters), screenshotted, and then zoomed in to 800% of original size.
test.png
test.png (3.59 KiB) Viewed 6572 times
Now the psuedocode:
1) Pick a font and zoom level that will give a max height of 16 and a max width of 8. Not sure how to do this. I was thinking guess and check unless there's a better way. For the max height of 16, that's easy, just pick a font size that gives the letter lowercase j a height of 15 pixels.
2A) For each white color in the font, get colorindex and alpha.
2B) Chop up each letter into an 8x16 tile.
3) For each letter, and each pixel in each letter:
3A) Quantize the color value by (R + G + B) / 3. Is there a better way to quantize? Maybe it's max(R, G, B) instead. Yeah, that sounds right.
3B) Find the white colorindex whose alpha best matches that value and write that for the colorindex of the current pixel
3C) Write the pixel to the original image.
...Then we can convert back with itp converter.

josejl
Programmer
Posts: 200
Joined: Mon Apr 13, 2015 6:49 pm
Location: Spain
Contact:

Re: How do Triangle Draws Work?

Post by josejl » Tue Feb 02, 2016 11:42 am

Lots of interesting information on this thread,great job.

However,something struck me as odd,unless I misunderstood something.

The texture coordinates are measured in pixels?
I've never seen that before, all the 3D APIs I've used use floats in the range of (0,1) as the UV coordinates (of course,I only have used Direct3D and OpenGL/OpenGL ES).

It's not like I made a full game on those APIs,but I made a really simple VWF system in D3D11,and while the font file measured the offsets in pixels,I had to normalise them to the (0,1) range for rendering.

flamethrower
Programmer
Posts: 995
Joined: Mon Mar 09, 2015 3:03 pm

Re: How do Triangle Draws Work?

Post by flamethrower » Tue Feb 02, 2016 3:19 pm

Yeah, for PSP GE, texture coordinates are given as a distance, in pixels. That goes for both texture coordinates and positions.

I don't know about APIs. I work only at the assembly level. And for modifying textures, generally you modify the image file without changing game code.

Maybe official Sony tools is worth looking into. I don't think they are publicly available yet and I don't think they will ever be. You have to sign up to be a Sony PSP developer to get access to them.

Commercial game production software is also possibly capable of building game files. Most of them are proprietary, I think. Even the middleware ones, which are commercial products, are nonpublic. I'm not aware of any public software of this type, except for maybe IDA Pro, which is a disassembler.

SetVertexType instruction (see it in the 1st post) for GE sets the coordinate types. I've only ever seen "s16" (not sure what that is) or "float." s16 just means the coordinates are halfword integers, but I'm not sure what s16 itself stands for. 16 bits in a halfword, maybe? And then it's possible for both the texture coordinates and positions to be either type. Commonly you will see it "split" (one of them s16 and the other float) because there's a whole other set of registers (the ones in the coprocessor) that can be used to store the values needed for building the vertex list.

josejl
Programmer
Posts: 200
Joined: Mon Apr 13, 2015 6:49 pm
Location: Spain
Contact:

Re: How do Triangle Draws Work?

Post by josejl » Wed Feb 03, 2016 3:26 pm

And what about the open source PSP SDK?
I remember it had some documentation on some of the sce system calls.

I am giving it a try,you can generate EBOOTs that run on PPSSPP just fine from C/C++ code.

Going by that SDK,s16 means signed 16 bit integer

User avatar
zeromonkey
Hacker, script editor and control freak
Posts: 486
Joined: Thu Mar 05, 2015 3:10 pm
Location: Tennessee

Re: How do Triangle Draws Work?

Post by zeromonkey » Fri Feb 05, 2016 6:49 am

Alright. I will look into various fonts tomorrow if time permits. Tahoma is a good one though. I had actually looked at that one the other day when trying to find fonts that would fit into the 8x16 tiles.

flamethrower
Programmer
Posts: 995
Joined: Mon Mar 09, 2015 3:03 pm

Re: How do Triangle Draws Work?

Post by flamethrower » Fri Feb 05, 2016 5:00 pm

I don't really want to replace the font. I think it looks fine, except for certain letters. W is the biggest offender. I think M looks fine. I just have too much spacing for it in the screenshot. I should make test screenshots or something.

Things to try are:
1) Changing so default width is 8 rather than 7, which makes a 1:1 mapping between texture and position. It's slightly compressed now, the default width is 7 (texture width must always be 8, we can make the position width narrower or wider).
2) Flip the M upside-down to make a W. This is the oldest trick in the book.
3) Touch-up the W so it looks better. I can make a false-color image according to alpha, which you could then edit as needed, with GIMP. With a conversion tool, you could view your edits in COLGA rather than in-game so you can iterate faster.

Or, if you can find a nice-looking 8x16 font. You can try asking at romhacking.net. It's the perfect place to ask something like this.

Fun projects could be:
1) VWF patch for Trails in the Sky PSP
2) VWF patch for Trails in the Sky SC PSP
3) VWF patch for Nayuta no Kiseki - It only makes sense for the English version, the JA version doesn't need VWF.
For 1+2 and Ao no Kiseki, the drawing routine is probably extremely similar to ZnK.
---------------------------
I've finished the VWF for this. Next will be to put in the current version of:
m3000, m3002, e0410, c0000, c1150, c0800, m0000, m0001, m0002 (those are the intro scripts up to the first boss fight).

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests