C Library for Wii and Gamecube homebrew
devkitpro / libogc Goto Github PK
View Code? Open in Web Editor NEWC Library for Wii and Gamecube homebrew
Home Page: https://devkitpro.org/viewforum.php?f=40
License: Other
C Library for Wii and Gamecube homebrew
Home Page: https://devkitpro.org/viewforum.php?f=40
License: Other
Sound stream running via OGC Audio plays with a swapped stereo on Dolphin as well as on real hardware. First time I was though I wrongly plugged my component cables, but all was plugged correctly. After some investigations, I found it's a bug of the OGC itself.
Just run this example (I replaced the sample.ogg
with my file): oggplayer-stereo-test.tar.gz
The example file sample.ogg
plays long Beep in every ear. It should play first Beep in left ear. But it plays it at right ear. And second Beep should be played at Right ear, but actually plays at left ear.
Linux.
Long time I did ran my hardware just by TV speakers, but once upon I decited to use hearphones to don't make hard noise and listen in-game stuff accurately. And, once I ran one of my testing stuff, I found the problem of the swapped stereo.
It's possible to set socket options, but it's not possible to get them.
In particular, it would be nice to get net_getsockopt working with SOL_SOCKET, SO_ERROR, as that would make it possible to get the error status of an async connect().
I was looking through the MP3Player code and I don't think there's a function for getting the current position while playing an MP3 file. Is it possible to implement this?
In line 791 of current commit of card.c, in __card_allocblock():
if(count>=(card->blocks-CARD_SYSAREA)) return CARD_ERROR_BROKEN;
This will always be true for the last block of the memory card, thus not being able to write to it. The fix is simple:
if(count>(card->blocks-CARD_SYSAREA)) return CARD_ERROR_BROKEN;
(This information was reported by undergroundmonorail, I saw it wasn't fixed in libog and I thought I'd tell)
UPDATE: after some testing the problem only happens in the following scenario: writing a 59 block file to a 59 block memory card.
There is no problem if card has 48 occupied blocks and then a 11 block file is written.
I made a 251 block file for testing purposes and the same behavior appears. I won't test 1024 or 2048 cards since the same behavior is expected.
Also, I found a bug in Card_delete, opening issue
The Wii U Pro controller does not provide calibration data therefore these data have been written in the code (classic.c)
`/* is this a wiiu pro? */
if (len > 223 && data[223] == 0x20) {
cc->ljs.max.x = cc->ljs.max.y = 0xFF;
cc->ljs.min.x = cc->ljs.min.y = 0;
cc->ljs.center.x = cc->ljs.center.y = 0x80;
cc->rjs = cc->ljs;
cc->type = 2;
}`
However the min and max values (0 and 0xFF) are not correct and far from the real values.
More convenient values should be min=55 and max=197.
Wrong calibration data lead to wrong polar coordinates values (in particular exp.classic.ljs.mag).
It would be necessary to test some Wii U Pro controllers to have more precise results on min, center and max calibration data.
While attempting to build libcurl for the Wii, I ran into problems where some of the necessary functions, namely net_getsockopt
, net_getsockname
, and the data type struct pollfd
were not present in the library. I was aware that all the network functions are prefixed with net_
, but even after adding that prefix, it made no difference.
I checked the network.h
header just to make sure I wasn't going crazy. Lastly, I ran nm
on libogc just on the off-chance the symbols were in the library but not in the header. But this got me no further.
Interestingly enough, I found this note in network.h
:
/*
* Level number for (get/set)sockopt() to apply to socket itself.
*/
#define SOL_SOCKET 0xffff /* options for socket level */
It almost seems as though there were plans to implement net_getsockopt
, but this wasn't done. This has seemingly also persisted for a long time, as I found in this forum post from 2011 and in issue #56 from 2018.
Line 2704 in bc4b778
Example: For Paper Mario two files with the same gamecode and company can be in the same memory card: "rel" and "rel_settings"
If the file "rel_settings" is already present in the memory card when trying to restore "rel", when Card_CreateAsync parses trough the directory entries it will find "rel_setting", but since it will only compare the lenght of the file to create (in this case 3 bytes, snce we are trying to create the "rel" file), memcmp will result in zero and thus Card_CreateAsync will report a CARD_ERROR_EXIST.
Proposed solution is to memcmp the full allowed filename lenght:
else if(memcmp(entry[i].filename,filename,CARD_FILENAMELEN)==0)
It seems like the console doesn't support colors (unless I'm just missing how to enable them). eg:
printf("\x1B[38;5;14mI'm cyan\n");
printf("\x1B[1;14mI'm also cyan\n");
Both produce white. The same is true of other color codes.
Looks like gctypes.h
was supposed to use gcbool.h
, but it includes stdbool.h
instead, which doesn't exist.
(I never used your library, but I did answer to some question about it, with a suggestion for you)
Regards.
Basile Starynkevitch [email protected]
92340 Bourg La Reine, France
Steps to reproduce:
Hello everyone,
i have set a new machine with Ubuntu 21.04, when I try to build my project I have got this Error:
/opt/devkitpro/libogc/include/mp3player.h:13:1: error: unknown type name 'BOOL'
13 | BOOL MP3Player_IsPlaying(void);
Have you any idea why it happens this. Months ago, with Linux, I don't remember that i ever face this type of error
using libogc 1.8.20 (even with the latest 3 commits)
time(null) on wii doesn't get wii's current time. it always starts at jan 1 2000 0:00:00
using libogc 1.8.19 time(null) works correctly.
ogc_card_writepage() will start over when the memory card has over 1024 blocks
card->cmd[1] = (card->cmd_sector_addr>>17)&0x3f;
card->cmd[2] = (card->cmd_sector_addr>>9)&0xff;
card->cmd[3] = (card->cmd_sector_addr>>7)&3;
card->cmd[4] = card->cmd_sector_addr&0x7f;
After address 0x800000 the results are the same as 0x0000, next block (0x802000) is equal to 0x2000 and so on.
This is correctly handled in ogc_card_readsegment() (haven't checked the values for more than 2048 0x2000 sector blocks though, not that there are bigger memory cards...)
card->cmd[1] = (card->cmd_sector_addr&0xFE0000)>>17;
card->cmd[2] = (card->cmd_sector_addr&0x01FE00)>>9;
card->cmd[3] = (card->cmd_sector_addr&0x000180)>>7;
card->cmd[4] = (card->cmd_sector_addr&0x00007F);
I haven't tested restoring single savegames to a memory card that is already filled further than 1023 blocks, but raw writing doesn't work unless ogc_card_writepage is updated to calculate offsets as ogc_card_readsegment()
This has been tested and seems to be working fine so far.
This was found while adding sensor information to the SDL2 port.
Values of the gforce
field of the nunchuck_t
structure are wrongly scaled: instead of having 1.0 as the base gravity value (like the gforce
field of the wiimote), it looks like their base value is about 0.3.
Run the test/testgamecontroller.elf program from the SDL2 tree.
Dolphin emulator with a real WiiMote connected, and a Wii as well.
I am working on a project whereby Homebrew using libogc launches a game mod that does not. In the homebrew code I'm initializing sd and usb so that mods can be loaded from there.
Now I'm adding USB features to the mod, I have found a small oversight in the usbstorage code. Unlike the sd library, usbstorage does not always call IOS_Close for the handles it opened when calling shutdown on the usb disc interface, most noteworthy being a scenario whereby no usb device is plugged in. This causes a conflict with the game that's being launched, since IOS doesn't support more than one usb handle at the time.
I'm aware of the option to call IOS_ReloadIOS to work around this problem, but that shouldn't be required to release all handles opened by libogc modules.
Hi.
I have a 3rd party bluetooth controller (Hyperkin ProCube Gamecube Style Pro Controller) that connects successfully as a Wii U Pro Controller, but none of its inputs are recognized (other than home and power buttons) and it seems like the joystick value is stuck towards bottom left. And of course I tested it with Wii U games and it works normally.
I'd like to do what I can to help get this controller working properly in this library.
When compiling with very strict error reporting settings in GCC (I like my code to be squeaky clean), the compiler gives me this error:
/opt/devkitpro/libogc/include/ogc/es.h:150:21: error: ISO C++ forbids flexible array member 'contents' [-Werror=pedantic]
150 | tmd_content contents[];
| ^~~~~~~~
/opt/devkitpro/libogc/include/ogc/es.h:172:26: error: ISO C++ forbids flexible array member 'contents' [-Werror=pedantic]
172 | tmd_view_content contents[]; //0x005c
| ^~~~~~~~
cc1plus: all warnings being treated as errors
make[1]: *** [/opt/devkitpro/devkitPPC/base_rules:13: init.o] Error 1
make: *** [Makefile:98: build] Error 2
My CFLAGS line:
-Ofast -Wall -Wextra -Wformat-truncation -Wformat-overflow -Wpedantic -Wshadow -Wformat=2 -Wconversion -Wunused-parameter -fsanitize=address,undefined -Werror $(MACHDEP) $(INCLUDE)
Is this fixable? Or do I just need to turn off -Wpedantic
?
EDIT: And no, wrapping the includes in an extern "C"
didn't help either.
The documentation for this function should probably be fixed.
The documentation where it claims to take an absolute timeout.
Relevant header file.
However, following the actual implementation...
LWP_CondTimedWait
__lwp_cond_waitsupp
__lwp_wd_insert_ticks
...shows that it is used as a relative timeout.
Places where people have been confused by the wrong documentation of this function.
A user on the devkitPro forums posted about this in 2014.
SDL Wii had to fix their implementation of SDL_CondWaitTimeout in 2015 (issue apparently reported in 2013).
It confused me too.
When trying to build a program i have the following error:
status
make
linking ... Wii.elf
/opt/devkitpro/devkitPPC/lib/gcc/powerpc-eabi/8.3.0/../../../../powerpc-eabi/bin/ld: /opt/devkitpro/libogc/lib/wii/libSDL.a(SDL_string.o): in functionSDL_strlwr': C:\Users\Daryl\git\sdl-wii\SDL/src/stdlib/SDL_string.c:398: undefined reference to
__locale_ctype_ptr'
/opt/devkitpro/devkitPPC/lib/gcc/powerpc-eabi/8.3.0/../../../../powerpc-eabi/bin/ld: C:\Users\Daryl\git\sdl-wii\SDL/src/stdlib/SDL_string.c:398: undefined reference to `__locale_ctype_ptr'
collect2: error: ld returned 1 exit
this is how my Makefile looks like:
libogc includes a copy of kprintf, which was distributed under the GPL, despite libogc having a license most closely matching MIT.
https://github.com/devkitPro/libogc/blob/master/libogc/kprintf.c
The loop in usbstorage.c#__usbstorage_IsInserted
(referenced in the first link below) breaks as soon as it finds any USB storage device. If a drive with an unreadable proprietary format (e.g. a Wii U formatted drive) happens to appear ahead of a readable drive (e.g. a FAT32 Wii USB drive) in the usb_device_entry
buffer, usbstorage.c
will mount it and exit the function. This may cause issues in higher level apps which rely on this function to mount a USB storage drive when multiple USB storage drives are connected and some subset of them are in an unreadable proprietary format.
Lines 879 to 917 in 46b47a0
This behavior affected WiiFlow on Wii U as documented in WiiFlow issue 338. WiiFlow contains its own modified copy of this function and a fix for the issue can be viewed in pull request 343. Opening this issue to track the problem in libogc
and to note that the fix in WiiFlow could be adapted and included here if desired.
I seem to be unable to get any data from the MotionPlus extension on my Wiimote, or from the integrated MotionPlus on another Wiimote.
Unfortunately my Wii is not usable atm so I am running my code on Dolphin, but I doubt it would make much of a difference.
It's likely this is an error on my part, but I have not had much luck finding examples of reading the Motion Plus sensors using WPAD, and the code seems correct to me.
Here is my current setup:
u32 type;
WPADData* wd;
PAD_Init();
WPAD_Init();
WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
while(1) {
WPAD_ReadPending(WPAD_CHAN_ALL, countevs);
int err = WPAD_Probe(0, &type);
switch(err) {
case WPAD_ERR_NO_CONTROLLER:
print("WIIMOTE NOT CONNECTED");
break;
case WPAD_ERR_NOT_READY:
print("WIIMOTE NOT READY");
break;
case WPAD_ERR_NONE:
print("WIIMOTE READY");
break;
default:
print("UNK WIIMOTE STATE %d", err);
}
print("EVENT COUNT: %d", evctr);
if(err == WPAD_ERR_NONE) {
wd = WPAD_Data(0);
print("DATA ERR: %d",wd->err);
print("\n");
print("ACCEL:");
print("X: %3d", wd->accel.x);
print("Y: %3d", wd->accel.y);
print("Z: %3d", wd->accel.z);
print("\n");
print("ORIENT:");
print("PITCH: %.02f",wd->orient.pitch);
print("YAW: %.02f",wd->orient.yaw); // frozen at 0.00
print("ROLL: %.02f",wd->orient.roll);
print("\n");
print("MP:");
print("PITCH: %.02f",wd->exp.mp.rx); // frozen at 0.00
print("YAW: %.02f",wd->exp.mp.ry); // frozen at 0.00
print("ROLL: %.02f",wd->exp.mp.rz); // frozen at 0.00
print("\n");
print("GFORCE:");
print("X: %.02f",wd->gforce.x);
print("Y: %.02f",wd->gforce.y);
print("Z: %.02f",wd->gforce.z);
}
Here is the data I am seeing (what isn't 0 does change when I move the wiimote):
libogc uses an extern for _wrapup_reent.
In devkitPro/newlib@99e8764 _wrapup_reent
was removed. In devkitPro/buildscripts@116ad3b a patch was added to restore this function, then that patch was deleted by devkitPro/buildscripts@e48ba38 and not replaced. Therefore, even when using the official build scripts, it appears to now be impossible to link libogc when using devkitPPC r29 or later, since _wrapup_reent
does not exist:
test.cpp:
int main() { return 0; }
compiler error:
$ powerpc-eabi-g++ -L/opt/devkitpro/devkitPPC/lib -mogc -L/opt/devkitpro/libogc/lib/cube -logc -Wl,--no-gc-sections -isystem /opt/devkitpro/devkitPPC/include -I/opt/devkitpro/libogc/include ./test.cpp
/opt/devkitpro/libogc/lib/cube/libogc.a(newlibc.o): In function `__libc_wrapup':
C:/Users/davem_000/projects/devkitPro/libogc/libogc/newlibc.c:67: undefined reference to `_wrapup_reent'
collect2: error: ld returned 1 exit status
unwanted links removed, sorry.
If you take a look at this part of the function, you'll quickly notice that if the file is 1 block lenght, the block is never freed in the fat table
// ...
next = fatblock->fat[block-CARD_SYSAREA];
while(1) {
if(next==0xffff) break;
if(next<CARD_SYSAREA || next>=card->blocks) return CARD_ERROR_BROKEN;
// Get the file's next block and clear the previous one from the fat
prev = next;
next = fatblock->fat[prev-CARD_SYSAREA];
fatblock->fat[prev-CARD_SYSAREA] = 0;
fatblock->freeblocks++;
}
return __card_updatefat(chn,fatblock,callback);
I tried the following fix, I've done some savegame writing and erasing and seems to work fine so far, there were no missing blocks and they were correctly allocated:
next = fatblock->fat[block-CARD_SYSAREA];
/*+++/* fatblock->fat[block-CARD_SYSAREA] = 0;
/*+++*/ fatblock->freeblocks++;
while(1) {
if(next==0xffff) break;
if(next<CARD_SYSAREA || next>=card->blocks) return CARD_ERROR_BROKEN;
// Get the file's next block and clear the previous one from the fat
prev = next;
next = fatblock->fat[prev-CARD_SYSAREA];
fatblock->fat[prev-CARD_SYSAREA] = 0;
fatblock->freeblocks++;
}
return __card_updatefat(chn,fatblock,callback);
I'm not really sure if this is the correct way to fix the problem, if someone can confirm or update card.c with a better method I'll be thankful!
Hello,
I've been trying to get debugging working through the debug library inside libogc.
The program is running on Dolphin Emulator v 5.0-16793, and it is emulating usb gecko over port 55020 in slot A. I'm using gdb v13.0.50.20220721 and the latest commit on libogc v3d123eb
DEBUG_Init(GDBSTUB_DEVICE_USB, 1);
_break();
I set a break point with _break(), the program is executed and hits that break point. I then open the elf's symbols in gdb and connect to dolphin via
target remote <Dolphin's Local IP Address>:55020
The debugger attaches to the process, and I can print the stack frame, and see the line of code that the debugger is breaking on. This is all fantastic, but I then try to step or continue and the process hangs.
I've been pausing the emulator at random points to evaluate the call stack and also adding debug strings to see which parts are hit - but I'm a bit out of my depth at the moment, I wanted to check if this is the correct approach for gdb debugging with devkitPro? Or should I using a different method?
Further details that may be of use if this is an actual bug and not user error on my behalf:
The loop seems to go:
Interestingly the using gdb return command will return the program counter to the line one above return address, but when attempting to step or continue after a return, you get taken to the breakpoint immediately instead.
All the best,
Lawrence
If my understanding is correct, the return value of PAD_ScanPads()
is a bit mask where the less significant 4 bits are set to 1 if the respective controller is connected, and 0 otherwise.
Both in a real Wii and in Dolphin, if PAD_ScanPads()
is called on every frame, a connected GameCube controller is reported as present on one call, and absent on the next one, and so on. In order to avoid reporting this wrong information to the application, I've introduced a workaround where I expect PAD_ScanPads()
to return 0 for 4 times in a row before reporting that the joystick has been removed: https://github.com/mardy/SDL/blob/ogc-sdl2-2.28/src/joystick/gamecube/SDL_sysjoystick.c#L171-L188
My guess is that PAD_Read()
returns a structure where the err
member is set to PAD_ERR_NOT_READY
or to PAD_ERR_TRANSFER
, and PAD_ScanPads()
then just returns the controller as not present.
I think that overall the behaviour of PAD_ScanPads()
is correct, but there should be a way for the client to read the error status. Would you be against adding a s8 PAD_GetError(s32 chan)
function which returns the value of __pad_keys[chan].err
? If not, I can prepare a pull request.
With Wii MotionPlus being a expansion, which is a union in libogc code It cant be used if any other expansion such as nunchucks to be used with MotionPlus even if part of the hardware.
I have had many people telling me that the RTC time displayed in my homebrews was different from what was configured and shown in the System Menu.
After few tests, I found out that the issue resides in CONF_GetCounterBias(u32 *bias)
, which treats the bias as an unsigned 32bit integer, while instead it should be signed. By modifying that function and its callers to properly use that (only SYS_Time(void)
), homebrews always shows the correct time.
This issue is not common, as it depends on if the offset is negative. It should be possible to replicate the issue by carefully changing the system time depending on the current counter of the onboard RTC counter.
Despite this looking like an easy fix, sadly it leads to other issues. I am not entirely sure of all of them, but one quick thing I noticed is that the PAD interface stops working and no controller input is detected. I don't have a deep knowledge of libogc, so I am not entirely sure of what could be the source of this, maybe something related to timesupp.c
functions, since SYS_Time()
calls settime()
based on the time read from the RTC.
Does anyone have any idea of what could be the issue and how the fix it? I will keep on digging in libogc's code trying to find a fix myself in the meantime.
Thanks
Line 251 in 6c10421
I'm pretty sure this should be __dsp_currtask->state = DSPTASK_YIELD
as that's what's done in the other yield cases. The corresponding bit in flags
would be __dsp_currtask->flags = DSPTASK_CANCEL
which seems wrong.
I don't know if this affects anything in practice.
It seems that POLLOUT is wrong. When I use it, I don't ever get any events. However, when I used 0x8 (what POLLERR is currently defined to), it works. I'm suspecting those two are swapped?
Was doing some testing with aesndlib a few days ago and found that calling AESND_Reset
on exit just hangs my Wii. Wondered why, and looked into it a little bit.
Apparently, I'm not the first one to find out about this - it was known about when adding support for aesndlib in Dolphin in July of 2022, and even gives a warning about it not working with an explanation of why:
// The relevant code looks like this:
//
// lrs $acc1.m,@CMBL
// ...
// cmpi $acc1.m,#0xdead
// jeq task_terminate
//
// The cmpi instruction always sign-extends, so it will compare $acc1 with 0xff'dead'0000.
// However, recv_cmd runs in set16 mode, so the load to $acc1 will produce 0x00'dead'0000.
// This means that the comparison never succeeds, and no mail is sent in response to
// MAIL_TERMINATE. This means that __dsp_donecallback is never called (since that's
// normally called in response to DSP_DONE), so __aesnddspinit is never cleared, so
// AESND_Reset never returns, resulting in a hang. We always send the mail to avoid this
// hang. (It's possible to exit without calling AESND_Reset, so most homebrew probably
// isn't affected by this bug in the first place.)
//
// A fix exists, but has not yet been added to mainline libogc:
// https://github.com/extremscorner/libogc2/commit/38edc9db93232faa612f680c91be1eb4d95dd1c6
WARN_LOG_FMT(DSPHLE, "AESndUCode - MAIL_TERMINATE is broken in this version of the "
"uCode; this will hang on real hardware or with DSP LLE");
From the linked commit, it looks like the fix is small:
diff --git a/libaesnd/dspcode/dspmixer.s b/libaesnd/dspcode/dspmixer.s
index 6880225..9a66211 100644
--- a/libaesnd/dspcode/dspmixer.s
+++ b/libaesnd/dspcode/dspmixer.s
@@ -157,7 +157,8 @@ recv_cmd:
cmpi $acc1.m,#0x0100
jeq send_samples
- cmpi $acc1.m,#0xdead
+ lri $acc0.m,#0xdead
+ cmp
jeq task_terminate
wait_commands:
I write this as an issue instead of a pull request because this fix is already in a commit (albeit in another remote) and so should be able to be cherry-picked from there. (If doing so would complicate history or other things, though, making another PR would be trivial.)
Compiling with asndlib 2.6.0 results in no audio on Dolphin with the default DSP HLE emulation. When compiling with asndlib 2.5.0 the audio works as expected.
When updating from 2.5.0 to 2.6.0 audio stopped working in dolphin. The console logs Unknown ucode (CRC = 5dbf8bf1)
. I can't hear any issues using DSP LLE emulation or when testing on real hardware so this may purely be an emulation issue to report to dolphin.
Build a project using 2.6.0 that calls ASND_Init();
and run in dolphin with the default settings.
Dolphin 5.0-21264
GNU/Linux 6.6.30 x86_64
I compiled a project using all 2.6.0 libraries except linking a prebuilt version of asndlib 2.5.0 and there was no issue. This should confirm the error is caused by a change in asndlib and not any of the other libraries.
printf()
and puts()
do not work properly.
puts()
or printf()
When building for the Wii, everything works as expected: you will see the messages you print in the logs. When building for the GameCube, puts()
messages are not displayed at all, and printf()
can have one of the following results:
%
)print("Hello, %s\n", name)
will print only the value of name
, without "Hello, ".A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.