vgmoose / wiiu-space

[Wii U] Homebrew space shooter written with libwiiu
MIT License
26 stars 5 forks source link

Doesn't render full display on TV screen #1

Closed eastcoastcoder closed 8 years ago

eastcoastcoder commented 8 years ago

When starting the game, I notice only a corner of my display renders the entire game. The gamepad renders just fine though. WiiU is set to 1080p mode.

vgmoose commented 8 years ago

I have this issue as well. The video on youtube is actually a recording of the TV screen, cropped. I'm not sure how exactly to solve it.

I believe it stems from the fact that the TV resolution doesn't match the gamepad. So fixing this may require detecting the target width/height, and then scaling the draw pixel calls to the TV screen to account for the new ratio.

It's definitely an important problem, thanks for reporting it formally. I will check how other open source OSScreen homebrew gets around this. (For me, Pong has the same issue)

CreeperMario commented 8 years ago

I have found that this is not a limitation of the Wii U at all, but rather a limitation of draw.c. Despite leaving a pull request on libwiiu with fixes to this, they were not satisfactory.

How I'm designing my upcoming homebrew is by not using draw.c at all, and rather calling the OSScreenDoSomethingEx functions directly. This allows me to draw to the TV and GamePad framebuffers independently (although it does still get slow at times). Here's an example to render separate messages on the TV and GamePad screens. http://pastebin.com/hJGLy0pU - it is a little messy, but I hope you get the gist of it

Basically, the way I like to work is by calling OSScreenClearBufferEx instead of fillScreen, OSScreenPutFontEx instead of drawString and DCFlushRange/OSScreenFlipBuffersEx instead of flipBuffers.

The OSScreen functions offer a number as the first argument - 0 represents the TV screen, 1 represents the screen of the first GamePad, and 2 represents the screen of the second GamePad (assuming you actually managed to connect a second pad).

This allows drawing to both screens independently, although it is a little messier. While it takes more code space, you do also lose the overhead of draw.c's habit of re-linking to coreinit.rpl and re-retrieving the function address.

If you would like more information on the OSScreen functions, simply go to http://wiiubrew.org/wiki/Coreinit.rpl - I was able to work with the information there.

I apologize for the long comment, but I hope this helps any Wii U homebrew devs!

eastcoastcoder commented 8 years ago

Intriguing! I'm trying to jump into the Wii U Brew scene myself between school work. Good explanation, hopefully the libs can get ironed out and everyone can be on the same page. Two things though:

  1. I've never had this scaling issue with the homebrew launcher. (I have one installed on my sd card but I always load from wiiubru.com so I'm not sure if it's local or not). Does homebrew launcher call draw.c as well?
  2. Does changing the Wii U's resolution change the sizing of the application displayed on the screen? For example if I put the system in 480p mode would it still be a small window in the upper left corner or would it want to stretch at that point? What is the gamepad's resolution?
CreeperMario commented 8 years ago

1) I have no idea how the Homebrew Launcher works, but I think it actually doesn't use OSScreen at all, but rather GX2. GX2 is a system (provided by Nintendo) that allows GPU-accelerated graphics, which are probably auto-scaled by the Wii U. Again, I'm not quite sure, the person to ask about that would be @dimok789 himself. It also seems that he managed to create a C++ cross-compiler system, as he's programmed in C++ instead of C.

2) Again, I'm not really sure. I can definitely say that the GamePad ALWAYS outputs at 854x480. The TV screen can be scaled between 854x480, 1280x720 and 1920x1080, depending on the TV and cable you use. But despite my Wii U being at 1080p for its whole life, OSScreen still seems to think that the resolution is 1280x720. I have no idea what will happen if I switch to 480p or 720p, but I will be sure to try on Thursday afternoon (when I have access to my console).

Before @Hykem disappeared off the face of the Earth, he stated that he was working on a new SDK for the Wii U. If that's true, I imagine that it would be much easier to use than Nintendo's APIs. 😜

vgmoose commented 8 years ago

dimok had this to say regarding the OSScreen function, which is true. After all, if only the pixels on the gamepad screen are written to both screens, no scaling will take place on the TV screen.

Looking at HBL's code, it seems like some scaling math for the TV screen is happening here. Even though this is using GX2, it still fetches the TV's width and height. It would be interesting to see if there's an equivalent function that can be used with OSScreen (or maybe the GX2GetSystemTVScanMode can be used anyway?).

Since Space Game uses a modified version of draw.c, the changes for scaling for the TV screen would likely happen here. Modifying this with code styled after @CreeperMario's pastebin and taking into account the TV's width and height should allow for proper scaling for all TV's.

That is, unless there's another trick to make the Wii U "auto" scale OSScreen calls. Tricky area! Looking forward to hearing when happens when switching resolutions (I don't have access to my console right now either!)

CreeperMario commented 8 years ago

Okay, so I've run some tests, and I've found that changing the resolution does not affect OSScreen calls at all. Despite my resolution setting (480p 4:3, 480p 16:9, 720p 16:9, 1080i 16:9, 1080p 16:9) the text and square I programmed always showed up at the same place on my TV in the end.

For OSScreenPutPixelEx(unsigned int buffer, unsigned int x, unsigned int y, unsigned int color);, the TV screen is always represented as being in pixels 0-1279 (width) and 0-719 (height). The GamePad is always represented as 0-853 (width) and 0-479 (height).

OSScreenPutFontEx(unsigned int buffer, unsigned int x, unsigned int y, void * string); works a little differently. On the TV screen, the width is represented as being from -4 to 101 characters, and the height is -1 to 27 (heaven knows why Nintendo chose to do that...). Similarly, the GamePad is represented as -4 to 65 (width) and -1 to 17 (height).

The reason Space Game shows up in a box on the corner of the TV screen is because the pixels and characters are being drawn to the same places on the TV and GamePad screens. Because the game was adapted to the GamePad screen, and because the TV screen uses a larger pixel buffer, the program shows up in a box at the top-left of the TV screen. My method of skipping draw.c and calling the OSScreen functions directly is one way of avoiding this issue, and is the way that I like programming.

CreeperMario commented 8 years ago

@NWPlayer123 put this up a couple days ago. http://wiiubrew.org/wiki/Avm.rpl

It appears to be some sort of audio/video manager (https://twitter.com/NWPlayer1234/status/718689952129687553).

One function that looks interesting is bool AVMSetTVScale(int width, int height); which I assume is capable of changing the TV's resolution.

I don't know if it requires kernel access, but it looks to be persistent once it has been run. (@NWPlayer123 managed to crop Mii Maker's screen with it.)

EDIT: This method of scaling the TV Screen works with Space Game, and I have left a pull request with changes. Just a note, if you are running the payload binary in the PHP browserhax by @yellows8 it will give you an error about the payload being too large. The script is incorrect with this statement, just change 0x6000 on line 78 in index.php to 0x7000, it all still works.

vgmoose commented 8 years ago

Thank you @CreeperMario !

vgmoose commented 8 years ago

Just saw your comment about the filesize... I suppose we'll have to go over the "limit" then. I've added compilation instructions to the readme now that accounts for this.

CreeperMario commented 8 years ago

@ethanx94 if you aren't aware, this method of scaling was broken in the HBL and Loadiine ports of the game. This has now once again been fixed (to a certain degree... see #16 and #17 for details).