Hacking Calling all Wii programmers, new coder needs some help.

  • Thread starter Thread starter RiCK420
  • Start date Start date
  • Views Views 7,650
  • Replies Replies 73
  • Likes Likes 1
Some basic concepts I already know from programming other languages:

  • Functions
  • Includes
  • if / then / else Statements
  • Loops
  • Operators
  • Strings
  • Arrays
 
Joostin, shut up. sleep() is not a basic C command, it is implementation/platform specific. On windows the argument for Sleep() is in milliseconds which makes the OP's question completely reasonable. Your so-called optimization is terrible, how is "sizeof(x)/sizeof(x[0])" useful for char arrays (where sizeof(x[0]) is known to be 1) ? All you are doing is making the code harder to read. Your earlier attempts to pass an uninitialized usbstorage_handle struct show that you're just as much a noob as the OP. BTW, "Logical Unit Number" refers to usb devices with multiple drives like universal card readers or cd stackers, not the partition!

This whole thread has been full of crappy advice. USBStorage_ReadCapacity() has nothing to do with finding how much free space a filesystem has, it is used to find the sector size and sector count (i.e. the entire CAPACITY, who would've thunk it) of a USB drive.

OP: statvfs is the function you want, not any of this USBStorage stuff. You can't use those functions from regular code because all the important USB device info is declared as static variables inside the usbstorage source file (due to libogc's interfaces being extremely poorly designed).
 
  • Like
Reactions: RiCK420
Your so-called optimization is terrible, how is "sizeof(x)/sizeof(x[0])" useful for char arrays (where sizeof(x[0]) is known to be 1)
Because sizeof(x[0]) isn't always 1, dumbass. It depends on the variable type. That macro will show the length of any array, whether it is of chars or a ints. It's pre-processed too.

It's also very easy to read, because MAX_ELEMENTS() is pretty self-explanatory.
 
x never changes the size of its elements because it's declared as a char array; it says so right there in the code. sizeof(x) does exactly the same thing.
Nearly all bounds checking functions (snprintf, strncat, etc.) are for char arrays, using anything more than sizeof()-1 is a waste of space except when the array size isn't known; in those cases your code will fail spectacularly anyway.
 
x never changes the size of its elements because it's declared as a char array; it says so right there in the code. sizeof(x) does exactly the same thing.
Nearly all bounds checking functions (snprintf, strncat, etc.) are for char arrays, using anything more than sizeof()-1 is a waste of space except when the array size isn't known; in those cases your code will fail spectacularly anyway.
Pretty sure you're just trolling right now, but I'll give you the benefit of the doubt and assume you're just an idiot.

I made the macro so that it could be used in multiple situations for multiple variables types. Its main use is for char arrays, especially with functions like snprintf, but it's also very useful if a loop is involved. If you have an array of ints and a for loop, you can add another element to the array without having to remember to change the for loop parameters. Far too often mistakes like that are made.
 
Dude, I'm not the one who helped stretch a thread out to four pages without even knowing the right function to use or how to call it without causing a crash - you can't pass an uninitialized usbstorage_handle and expect it to work.
If you're using that macro on char arrays you're doing it wrong, it's as simple as that. sizeof(char) is guaranteed to be 1 for all machine types so you're just adding a redundant "/1" for the preprocessor to ignore. As for little mistakes, how about this one:
Code:
void find_size(short *buffer) {
  printf("number of elements in buffer: %u\n", MAX_ELEMENTS(buffer));
}
The compiler gives no warnings or errors but running it gives a completely wrong answer. How awesome and time-saving your macro is!
 
You're just trolling now. Not all arrays are char arrays, and you know that.

he is clearly not trolling and neither he said all arrays are char array

BUT in the example you gave, array is declared as a char array so your macro is indeed pointless in that case and in other cases, nobody should use it either because it's bad coding, you cannot find the size of an array like that unless the size is already known (i.e it does not work with array pointers, only locally declared array), which makes it even more useless after all.

So i don't know if the worst thing is that you are trying to help and correct someone with bad tips or that you are convinced that people are trolling you when they are only correctingyour obvious coding mistakes ^^


As for the initial problem you are trying to solve, the best way is to look at usbStorage implementation in libogc: the function you want to use needs a pointer to an INITIALIZED usb device handler, you cannot just declare an empty device handler structure and expect it to work magically. It is not clear to me how you are supposed to do that but the answer is surely in usbstorage.c within libogc, which uses this function. But as said before, that function does NOT gives you the drive capacity but apparently the sector (block unit if you prefer) size. Again, this comes from a quick review of the code in libogc, which is how you should do to try to figure things out, not random clueless guessing...
 
he is clearly not trolling and neither he said all arrays are char array

BUT in the example you gave, array is declared as a char array so your macro is indeed pointless in that case and in other cases, nobody should use it either because it's bad coding, you cannot find the size of an array like that unless the size is already known (i.e it does not work with array pointers, only locally declared array), which makes it even more useless after all.
Of course it's only for predefined sizes. Sizes can change though, and if the function is big enough, it's easy to forget to change the parameters of a loop. This doesn't make the binary bigger or slow anything down, it just eliminates the possibility of accidentally forgetting to change a parameter.

If all you ever use is char arrays, then there is absolutely no problem using sizeof(). I didn't say it was bad to use that. It's a very simple, all-purpose macro for pre-defined sizes.

So i don't know if the worst thing is that you are trying to help and correct someone with bad tips or that you are convinced that people are trolling you when they are only correctingyour obvious coding mistakes ^^
I was simply making a suggestion to Foxi.

As for the initial problem you are trying to solve, the best way is to look at usbStorage implementation in libogc: the function you want to use needs a pointer to an INITIALIZED usb device handler, you cannot just declare an empty device handler structure and expect it to work magically. It is not clear to me how you are supposed to do that but the answer is surely in usbstorage.c within libogc, which uses this function. But as said before, that function does NOT gives you the drive capacity but apparently the sector (block unit if you prefer) size. Again, this comes from a quick review of the code in libogc, which is how you should do to try to figure things out, not random clueless guessing...
Are you talking to the OP now?
 
I'm annoyed because you are trying to program in a new language without learning it.

Maybe we just learn differently? I am a hands-on-learning person. I can read a book or tutorial, and get some concepts out of it, but I have better memory retention when I actually use the info I gain in a practical manner.
So rather than just reading, I like to learn by doing. So by trying to make this program, I am learning the language. I appreciate your posts and tips you have offered me, thank you.
 
  • Like
Reactions: Madridi
So I finally have some working code that does get the Used & Free Space on the USB or SD card. (Currently just one of them at a time).

Code:
#include <stdio.h>
#include <stdlib.h>
#include <gccore.h>
#include <wiiuse/wpad.h>
#include <ogc/usbstorage.h>
#include <iostream>
#include <string>
#include <string.h>
#include <unistd.h>
#include <sys/statvfs.h>
#include <fat.h>
#include <dirent.h>
#include <math.h>
 
static void *xfb = NULL;
static GXRModeObj *rmode = NULL;
 
int statvfs(const char *path, struct statvfs *buf);
int fstatvfs(int fd, struct statvfs *buf);
 
int round_int( double r ) {
    return (r > 0.0) ? (r + 0.5) : (r - 0.5);
}
 
int fat_shit()
{
    if (!fatInitDefault()) {
        printf("Unable to initialize FAT subsystem, exiting. \n \n");
        exit(0);
    }
    else {
        printf("Successfully initialized FAT subsystem. \n \n");
    }
   
    const uint GB = (1024 * 1024) * 1024;
   
    struct statvfs buffer;
   
    // usb:/ usb2:/ usb3:/ sd:/
   
    statvfs("sd:/", &buffer);
   
    const double total = (double)buffer.f_blocks * buffer.f_frsize / GB;
    const double available = (double)buffer.f_bfree * buffer.f_frsize / GB;
    const double used = total - available;
    const double usedPercentage = ceil(used / total * 100);
    const double availablePercentage = ceil(available / total * 100);
    int usedPercentageRounded = round_int(usedPercentage);
    int availablePercentageRounded = round_int(availablePercentage);
   
    printf("Used Space: %u", usedPercentageRounded); printf("%% \n \n");
    printf("Free Space: %u", availablePercentageRounded); printf("%% \n \n");
   
    fatUnmount(0);
   
    return 0;
}
 
int my_sleep(int s)
{
    usleep(s * 1000000);
    return 0;
}
 
//---------------------------------------------------------------------------------
int main(int argc, char **argv) {
//---------------------------------------------------------------------------------
 
    // Initialise the video system
    VIDEO_Init();
   
    // This function initialises the attached controllers
    WPAD_Init();
   
    // Obtain the preferred video mode from the system
    // This will correspond to the settings in the Wii menu
    rmode = VIDEO_GetPreferredMode(NULL);
 
    // Allocate memory for the display in the uncached region
    xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
   
    // Initialise the console, required for printf
    console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
   
    // Set up the video registers with the chosen mode
    VIDEO_Configure(rmode);
   
    // Tell the video hardware where our display memory is
    VIDEO_SetNextFramebuffer(xfb);
   
    // Make the display visible
    VIDEO_SetBlack(FALSE);
 
    // Flush the video register changes to the hardware
    VIDEO_Flush();
 
    // Wait for Video setup to complete
    VIDEO_WaitVSync();
    if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
 
    // The console understands VT terminal escape codes
    // This positions the cursor on row 2, column 0
    // we can use variables for this with format codes too
    // e.g. printf ("\x1b[%d;%dH", row, column );
    printf("\x1b[2;0H");
   
    printf("RiCK420 has taken over your Wii! \n \n");
   
    my_sleep(3);
   
    printf("...Just Kidding! Please wait patiently! \n \n");
 
   
    //Fat Shit
   
    fat_shit();
   
   
    // Exiting Routine
   
    printf("Process complete, press [HOME] to EXIT or wait 30 seconds. \n \n");
   
    my_sleep(30);
   
    printf("...EXITING! \n");
    exit(0);
 
    while(1) {
 
        // Call WPAD_ScanPads each loop, this reads the latest controller states
        WPAD_ScanPads();
       
        // WPAD_ButtonsDown tells us which buttons were pressed in this loop
        // this is a "one shot" state which will not fire again until the button has been released
        u32 pressed = WPAD_ButtonsDown(0);
       
        // We return to the launcher application via exit
        if ( pressed & WPAD_BUTTON_HOME ) { printf("...EXITING! \n"); exit(0);}
       
        // Wait for the next frame
        VIDEO_WaitVSync();
    }
 
    return 0;
}


So now I am working on making it check the SD card and Each Partition of the USB Harddisk.
I am trying to use a string variable to set the drive to each of: sd:/ usb1:/ usb2:/ usb3:/

Code:
#include <stdio.h>
#include <stdlib.h>
#include <gccore.h>
#include <wiiuse/wpad.h>
#include <ogc/usbstorage.h>
#include <iostream>
#include <string>
#include <string.h>
#include <unistd.h>
#include <sys/statvfs.h>
#include <fat.h>
#include <dirent.h>
#include <math.h>

static void *xfb = NULL;
static GXRModeObj *rmode = NULL;

int statvfs(const char *path, struct statvfs *buf);
int fstatvfs(int fd, struct statvfs *buf);

int round_int( double r ) {
    return (r > 0.0) ? (r + 0.5) : (r - 0.5); 
}

int fat_shit(std::string drive)
{
    if (!fatInitDefault()) {
        printf("Unable to initialize FAT subsystem, exiting. \n \n");
        exit(0);
    }
    else {
        printf("Successfully initialized FAT subsystem. \n \n");
    }
    
    const uint GB = (1024 * 1024) * 1024;
    
    struct statvfs buffer;
    
    // usb2:/ usb3:/ sd:/ (string drive) ?
    
    statvfs(drive, &buffer);
    
    const double total = (double)buffer.f_blocks * buffer.f_frsize / GB;
    const double available = (double)buffer.f_bfree * buffer.f_frsize / GB;
    const double used = total - available;
    const double usedPercentage = ceil(used / total * 100);
    const double availablePercentage = ceil(available / total * 100);
    int usedPercentageRounded = round_int(usedPercentage);
    int availablePercentageRounded = round_int(availablePercentage);
    
    printf("Used Space: %u", usedPercentageRounded); printf("%% \n \n");
    printf("Free Space: %u", availablePercentageRounded); printf("%% \n \n");
    
    fatUnmount(0);
    
    return 0;
}

int my_sleep(int s)
{
    usleep(s * 1000000);
    return 0;
}

//---------------------------------------------------------------------------------
int main(int argc, char **argv) {
//---------------------------------------------------------------------------------

    // Initialise the video system
    VIDEO_Init();
    
    // This function initialises the attached controllers
    WPAD_Init();
    
    // Obtain the preferred video mode from the system
    // This will correspond to the settings in the Wii menu
    rmode = VIDEO_GetPreferredMode(NULL);

    // Allocate memory for the display in the uncached region
    xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
    
    // Initialise the console, required for printf
    console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
    
    // Set up the video registers with the chosen mode
    VIDEO_Configure(rmode);
    
    // Tell the video hardware where our display memory is
    VIDEO_SetNextFramebuffer(xfb);
    
    // Make the display visible
    VIDEO_SetBlack(FALSE);

    // Flush the video register changes to the hardware
    VIDEO_Flush();

    // Wait for Video setup to complete
    VIDEO_WaitVSync();
    if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();

    // The console understands VT terminal escape codes
    // This positions the cursor on row 2, column 0
    // we can use variables for this with format codes too
    // e.g. printf ("\x1b[%d;%dH", row, column );
    printf("\x1b[2;0H");
    
    printf("RiCK420 has taken over your Wii! \n \n");
    
    my_sleep(3);
    
    printf("...Just Kidding! Please wait patiently! \n \n");
   

    //Fat Shit
    
    std::string d;
    d = "sd:/";
    
    fat_shit(d);
    
    
    // Exiting Routine
    
    printf("Process complete, press [HOME] to EXIT or wait 30 seconds. \n \n");
    
    my_sleep(30);
    
    printf("...EXITING! \n");
    exit(0);

    while(1) {

        // Call WPAD_ScanPads each loop, this reads the latest controller states
        WPAD_ScanPads();
        
        // WPAD_ButtonsDown tells us which buttons were pressed in this loop
        // this is a "one shot" state which will not fire again until the button has been released
        u32 pressed = WPAD_ButtonsDown(0);
        
        // We return to the launcher application via exit
        if ( pressed & WPAD_BUTTON_HOME ) { printf("...EXITING! \n"); exit(0);}
        
        // Wait for the next frame
        VIDEO_WaitVSync();
    }

    return 0;
}

This spills out an error, which I think means I am using the wrong type of string, but I am not sure how to make a proper format string that it is asking for, I have been searching for documents online, but can't find an answer. There doesn't seem to be much for documents or tutorials for DevKitPPC, and the one tutorial I did find is for an out dated version. :/

> "make"
template.cpp
c:/projects/wii/FreeSpace/source/template.cpp: In function 'int fat_shit(std::string)':
c:/projects/wii/FreeSpace/source/template.cpp:42:24: error: cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*' for argument '1' to 'int statvfs(const char*, statvfs*)'
make[1]: *** [template.o] Error 1
"make": *** [build] Error 2

> Process Exit Code: 2
> Time Taken: 00:01
 
Here is another great site for Learning C++ for beginners:

http://www.learncpp.com/


The little quizzes at the end of each chapter are great for testing you to make sure you have learned each lesson before moving onto the next.
 

Site & Scene News

Popular threads in this forum