Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Final Fantasy III and lines problems #2921

Closed
chaosjs1 opened this issue Jul 25, 2013 · 19 comments · Fixed by #6329
Closed

Final Fantasy III and lines problems #2921

chaosjs1 opened this issue Jul 25, 2013 · 19 comments · Fixed by #6329

Comments

@chaosjs1
Copy link

Hello to all, First of all this is playable now it's that it has lines on the screen and the lines that I am referring to are quite annoying and they appear in battle only near the command menu for each character and such however they do appear as black lines outside battle and only in the menu screen and the like. Here is some screenshots to show you all better what I mean and all.
screen00000
screen00001
screen00003
screen00002

@hrydgard
Copy link
Owner

These lines get reported over and over again. It's not really fixable. The game is not designed to run at any other resolution than 480x272 and has not taken into account that texture filtering can read a little bit outside the source textures when scaling up.

What you try to work around it:

  • Enable force nearest neighbour filtering
  • Set texture scaling to 2x or 3x

@unknownbrackets
Copy link
Collaborator

Actually, although in most games that is true, these particular lines occur in Final Fantasy 3 even at 1x resolution with nearest neighbour filtering, 2xSSAA off, and texture scaling off. Enabling texture scaling doesn't appear to help.

-[Unknown]

@chaosjr7
Copy link

Look Closer at the backround, and you might see, as I did, Note the color of the 'Lines" to see the truth, it's clearly a "Transparency" issue.. The 'Lines' Mimic the backround color as thus, they must be part of the backround.

@unknownbrackets
Copy link
Collaborator

I haven't checked but this is possible the same basic issue as #4617. If they're the same that should probably be marked as a duplicate or etc.

-[Unknown]

@solarmystic
Copy link
Contributor

@unknownbrackets

I don't think they're the same thing, since in FFIV, the issue is tied to whether or not HW TnL is enabled. In this FFIII issue, the "lines" appear regardless of the HW TnL setting, but in FFIV's #4617 issue, disabling HW TnL resolves those gaps in the dialog boxes.

@unknownbrackets
Copy link
Collaborator

So, the vertex positions here are passed as s16 in through mode - so they are just integers. It clearly looks to be drawing the box slanted.

However, this actually shows properly in both JPCSP and our software renderer. The vertices are still skewed, even when sent to our software renderer, but the box is rendered as a rectangle.

It's actually a triangle strip of 4 points, in order:

  • top left
  • bottom left (offset one to the left)
  • top right
  • bottom right (offset one to the left)

The software renderer draws two triangles as a result of this:

  • top right, bottom left, top left (82,173 - 25,229 - 26,173)
  • bottom right, bottom left, top right (81,229 - 25,229 - 82,173)

Bigger picture, it draws the background in slices, which look like this:

111122223
111122223
111122223
444455556
444455556

1: (25/26 - 81/82 slanted)
2: (82 - 138 even)
3: (137/138 - 141/142 slanted)
4: (25/26 - 81/82 slanted)
5: (82 - 138 even)
6: (138 - 142 slanted)

The gaps appear between 1 and 2, and between 4 and 5. There's no gaps between 2 and 3 or 5 and 6.

-[Unknown]

@unknownbrackets
Copy link
Collaborator

Hmm. Interesting.

I created a test that simply draws a box, using that exact same coordinates I mention above, and in throughmode using s16. If it joins the triangles in a way that somehow creates a straight box, I should get the same.

I don't:
pos expected

In fact, GLES matches just fine what I get. It's softgpu which is wrong, and gives a square.

So I wonder if we're somehow getting the wrong coordinates here, after all... it does happen jit or not.

-[Unknown]

@hrydgard
Copy link
Owner

That's just weird, I've never seen anything intentionally draw slanted boxes aiming to end up with straight ones. I assume it's not the texture contents adjusting for the shape? In Through mode, there's really no other transform that might be messing things up either as viewport and matrices are completely ignored...

@unknownbrackets
Copy link
Collaborator

No, the UVs are a square.

The vertices are memcpy'd to 09D2E204 from 09E6A9E8 (offending at +4)... z_un_0893b19c seems to be the author. Unfortunately, this func and its descendents seem to basically use a ton of fpu and vfpu instructions.

One of the floats is 81.99999237, but it uses trunc.w.s. Ugh...

-[Unknown]

@unknownbrackets
Copy link
Collaborator

The difference is between 0x41CFFFFC (25.9999923706) and 0x41D00001 (26.0000019073).

These are the involved fpu ops:

lwc1
mfc1
mtc1
swc1
cvt.s.w
trunc.w.s
mov.s
mul.s
sub.s

mul.s resulted in 26.000002 from 26000.000000_0.001000
sub.s resulted in 26.000002 from 26.000002-0.000000
mul.s resulted in 26.000002 from 26.000002_1.000000
sub.s resulted in 25.999992 from 25.999992-0.000000
mul.s resulted in 25.999992 from 25.999992_1.000000
mul.s resulted in 26.000002 from 26000.000000_0.001000
sub.s resulted in 26.000002 from 26.000002-0.000000
mul.s resulted in 26.000002 from 26.000002*1.000000

These are the involved vfpu ops:

lv.q
lv.s
sv.q
vcst.s
vidt.q
vmidt.q
vmmov.q

vmmul.q
vmul.s
vrot.q

vmmul.q resulted in 26.000002 from (4) 26.000002_1.000000
vmmul.q resulted in 25.999992 from (4) 25.999992_1.000000
vmmul.q resulted in 26.000002 from (4) 26.000002*1.000000

Great, so it's probably input to this... hmm.

After MIPSInt::Int_FPU3op fpu op, some reg contains 25.999992

Okay, so it first appears after Int_FPU3op -> assuming the wrongness is 25.99 and not 26. The quest continues later. Not sure, maybe I got that wrong, actually.

add.s 26.000002 + -0.000010...

vmmul.q resulted in -0.000010 from (4) 0.000000_1.000000 + 56.000000_-0.000000 (b43bbd2e) + 0.000000_0.00000 + 1.000000_0.000000

vrot.q resulted in -0.000000 from sin=-0.000000, cos=1.000000

-[Unknown]

@unknownbrackets
Copy link
Collaborator

So the basic problem here is that vrot(4.0) is giving an off-zero result due to multiply/constant error.

-[Unknown]

@hrydgard
Copy link
Owner

Wow, great detective work!

Not sure how to best solve it though - I think it's unlikely that with any scaling factor you will get sin(4.0) to come out to exactly 0. The problem is that sin/cos are radian based, and not the strange integer angle units that the PSP uses where 1.0 corresponds to 90 degrees or pi/2 radians. I assume that the PSP is using some neat approximation to compute sin and cos that doesn't have that issue.

So either we need to find our own approximation with this property, or add some hackery around integer inputs, or simply choose a slightly too large scaling factor if that gets this game to round right anyway....

@unknownbrackets
Copy link
Collaborator

If I use sin/cos rather than sinf/cosf, and make M_PI_2 and angle doubles, it works, so it definitely is about accuracy.

I do wonder how accurate vrot really is. Maybe we could just round or something to chop off the inaccuracy...

-[Unknown]

@hrydgard
Copy link
Owner

I think vrot is fairly but not super accurate, double math should be overkill. However we need to be inaccurate in the same way..

@unknownbrackets
Copy link
Collaborator

In speed terms, there's no difference between float and double on the more modern hardware. Space-wise, double is 2x larger. As with desktop machines, assuming space isn't an issue, you should prefer double to float.

Android docs say doubles ought not be that slow. I need to upload and test this on my Android to see, I've never checked if it happens there.

-[Unknown]

@hrydgard
Copy link
Owner

That "double is as fast as float" has a couple of exceptions: double divides take nearly twice as long to execute, and functions like sin, cos, sqrt etc have to do more iterations to converge so are also slower. In addition SIMD gets narrower, but that isn't always an issue of course.

That said, for vrot it might not matter very much.

@unknownbrackets
Copy link
Collaborator

Seems like the results are at least consistent if not accurate (roughly seems accurate to 6 digits or so):

vrot -8388608.000000: 3f800000,80000000,00000000,00000000
vrot -1.000000: 80000000,bf800000,00000000,00000000
vrot 0.000000: 3f800000,00000000,00000000,00000000
vrot 1.000000: 80000000,3f800000,00000000,00000000
vrot 0.250000: 3f6c835c,3ec3ef14,00000000,00000000
vrot 0.500000: 3f3504f0,3f3504f0,00000000,00000000
vrot 0.750000: 3ec3ef14,3f6c835c,00000000,00000000
vrot 1.000000: 80000000,3f800000,00000000,00000000
vrot 4.000000: 3f800000,00000000,00000000,00000000
vrot 8192.000000: 3f800000,00000000,00000000,00000000
vrot 8192.500000: 3f3504f0,3f3504f0,00000000,00000000
vrot 8388608.000000: 3f800000,00000000,00000000,00000000

-[Unknown]

@hrydgard
Copy link
Owner

Yeah, they are probably taking modulo 4 then using some pre-fitted curve that approximates sin (or one quarter of it and mirroring). Modulo 4 can be taken more accurately than modulo PI*2...

Come to think of it, we could do the same thing, but fall back on sin as the curve.

@unknownbrackets
Copy link
Collaborator

Just to verify, the behavior is the same on Android. All of the glitches (dialog box edges, holes in places, etc.) are fixed by this.

-[Unknown]

@fp64 fp64 mentioned this issue Mar 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants