C programming help

Place to talk about all that new hardware and decaying software you have.

Moderator: General Mods

Post Reply
badinsults
"Your thread will be crushed."
Posts: 1236
Joined: Wed Jul 28, 2004 1:49 am
Location: Not in Winnipeg
Contact:

C programming help

Post by badinsults »

I've resolved to learn a new programming language (FORTRAN is pretty limited), so I have decided to learn C and use it to make some snes utilities.

The first problem I want to solve is that I want to read in a binary file, find the value of a particular memory address, and output the value in hexidecimal. Let's say I want to read in the values from 0xFF7D to 0xFF80.

Code: Select all

#include <stdio.h>
#include <stdlib.h>  // required for the function malloc

int main ( int argc, char *argv[] ){

char *buffer;
int *romsize;
int i;
unsigned long file_length;


int mem_address1 = 0xFF7D;
int mem_address2 = 0xFF7E;
int mem_address3 = 0xFF7F;
int mem_address4 = 0xFF80;

FILE *rom_image;


    if ( argc != 2 ){ 
    
    // print out error if there are not the right amount of arguments
    printf( "usage: %s filename", argv[0] );

    }
    else {
    // argv[1] is a filename to open
    rom_image = fopen( argv[1], "rb" );

    // if the file does not exist, it throws an error
    if ( rom_image == 0 ){
        printf( "Could not open file\n" );
    }
    else {

        
        printf( "successfully opened file\n" );

        // find the size of the binary file

        fseek(rom_image, 0, SEEK_END);
        file_length = ftell(rom_image);
        fseek(rom_image, 0, SEEK_SET);


        // creates a pointer that is the same size as the file

        buffer=malloc(file_length+1);

        if (!buffer) {

            fprintf (stderr, "Memory error!");
            fclose(rom_image);
        }


        // read the file into the buffer

        char a = fread(buffer, file_length, 1, rom_image);

        // file read into the buffer, can close

        fclose( rom_image );

        // print out the desired byte    

        
        printf("%X ", buffer[mem_address1]);
        printf("\n");
        printf("%X ", buffer[mem_address2]);
        printf("\n");
        printf("%X ", buffer[mem_address3]);
        printf("\n");
        printf("%X ", buffer[mem_address4]);
        printf("\n");
                   
        // clear memory

        free(buffer);
    }
    
    }
}

In my test game (Super Mario World), I should get the following output:

Code: Select all

BD
53
FF
99
Instead, I am getting this:

Code: Select all

FFFFFFBD 
53 
FFFFFFFF 
FFFFFF99
What is causing some of the bytes to not be read in properly?
<pagefault> i'd break up with my wife if she said FF8 was awesome
grinvader
ZSNES Shake Shake Prinny
Posts: 5632
Joined: Wed Jul 28, 2004 4:15 pm
Location: PAL50, dood !

Re: C programming help

Post by grinvader »

First, a very minor (pretty much unrelated) issue:

badinsults wrote:

Code: Select all

    // print out error if there are not the right amount of arguments
    printf( "usage: %s filename", argv[0] );
Unlike puts, printf doesn't append a newline at end of string. This would lead to something like:

Code: Select all

dood@machine ~/tmp $ ./awesome
usage: %s filenamedood@machine ~/tmp $ _

Code: Select all

printf( "usage: %s filename\n", argv[0] );
would work.

Code: Select all

    if ( rom_image == 0 ){
        printf( "Could not open file\n" );
If the string is static and you want a newline at the end, you can use puts.

Code: Select all

puts( "Could not open file" );
The same can be done with "successfully opened file\n".
Unrelated done.

Code: Select all

        if (!buffer) {

            fprintf (stderr, "Memory error!");
            fclose(rom_image);
        }

        // read the file into the buffer

        char a = fread(buffer, file_length, 1, rom_image);
An issue there. If you cannot allocate memory for the rom, and buffer == 0, you close the file, but you still try to read from the pointer (which will cause a segmentation violation). Quitting the program after the error message will handle that.

Code: Select all

            fclose(rom_image);
            return (-1); // or any other value you may want to use that would not be "success"
        }

Code: Select all

        printf("%X ", buffer[mem_address1]);
        printf("\n");
        printf("%X ", buffer[mem_address2]);
        printf("\n");
        printf("%X ", buffer[mem_address3]);
        printf("\n");
        printf("%X ", buffer[mem_address4]);
        printf("\n");
It may be a little confusing, but you can have all that on a single line instead.
What is causing some of the bytes to not be read in properly?
You declared the buffer as a (signed) char *. This makes the compiler sign-extend values that are negative (80-FF) over the 4 bytes supported by the %X formatter.
To fix...

Code: Select all

  unsigned char *buffer;
Also you probably want

Code: Select all

  return(0); // or any value that means "success"
at the end.
皆黙って俺について来い!!

Code: Select all

<jmr> bsnes has the most accurate wiki page but it takes forever to load (or something)
Pantheon: Gideon Zhi | CaitSith2 | Nach | kode54
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Re: C programming help

Post by Nach »

Use this:

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>

bool process_file(const char *rom_image_file_name)
{
  bool ret = false;

  FILE *rom_image = fopen(rom_image_file_name, "rb");
  if (rom_image)
  {
    const size_t minimum_size = 0xFF80;
    size_t rom_image_size;

    //Find the size of the binary file
    fseek(rom_image, 0, SEEK_END);
    rom_image_size = (size_t)ftell(rom_image);
    if (rom_image_size > minimum_size)
    {
      uint8_t *buffer = malloc(rom_image_size); //Allocates enough memory to store the file
      if (buffer)
      {
        size_t amount_read;

        rewind(rom_image);
        amount_read = fread(buffer, 1, rom_image_size, rom_image);
        if (amount_read > minimum_size)
        {
          if (amount_read != rom_image_size)
          {
            fprintf(stderr, "Warning: Was only able to read %zu/%zu of \"%s\"\n",
                    amount_read, rom_image_size, rom_image_file_name);
          }
          //Print out bytes
          printf("%02X\n%02X\n%02X\n%02X\n", buffer[0xFF7D], buffer[0xFF7E], buffer[0xFF7F], buffer[0xFF80]);
          ret = true;
        }
        else { fprintf(stderr, "Was only able to read %zu of %zu bytes\n", amount_read, rom_image_size); }
        free(buffer);
      }
      else { fprintf(stderr, "Unable to allocate %zu bytes of memory\n", rom_image_size); }
    }
    else { fprintf(stderr, "File is too small, only %zu bytes\n", rom_image_size); }
    fclose(rom_image);
  }
  else { fprintf(stderr, "Could not open \"%s\"\n", rom_image_file_name); }

  return(ret);
}

int main (int argc, const char *const argv[])
{
  int ret = -1;

  if (argc == 2) { ret = ((int)process_file(argv[1]))-1; }
  else { fprintf(stderr, "usage: %s filename\n", *argv); }

  return(ret);
}

May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
funkyass
"God"
Posts: 1128
Joined: Tue Jul 27, 2004 11:24 pm

Re: C programming help

Post by funkyass »

why am I not surprised by Nach's post?

you could also use stat to get the file size.
Does [Kevin] Smith masturbate with steel wool too?

- Yes, but don’t change the subject.
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Re: C programming help

Post by Nach »

funkyass wrote:why am I not surprised by Nach's post?

you could also use stat to get the file size.
What exactly should be surprising about it???
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
Post Reply