Reading nes file inputs and extracting data from header.

Creating rom image struct/object to store rom header data.
This commit is contained in:
paul eeepc 2016-12-05 00:42:29 -06:00
parent 497e53378b
commit 8654a8f4bf
5 changed files with 198 additions and 32 deletions

View File

@ -2,6 +2,7 @@
int detect_console( cartridge *cart, USBtransfer *transfer )
{
printf("attempting to detect cartridge...\n");
//always start with resetting i/o
io_reset( transfer );
@ -58,11 +59,29 @@ int detect_console( cartridge *cart, USBtransfer *transfer )
//always end with resetting i/o
io_reset( transfer );
switch (cart->console) {
case NES_CART: printf("NES cartridge detected!\n");
break;
case FC_CART: printf("Famicom cartridge detected!\n");
break;
case SNES_CART: printf("SNES cartridge detected!\n");
break;
case BKWD_CART: log_err("CARTRIDGE INSERTED BACKWARDS!!!\n");
//TODO detection not yet implemented need to look over connector pinouts
break;
case UNKNOWN: printf("Unable to detect cartridge...\n");
//TODO error out properly
break;
default:
sentinel("cartridge console element got set to something unsupported.");
}
return SUCCESS;
}
error:
return -1;
}
//Can detect INL discrete, XO, and possily others with pullup EXP0 test
//These carts have pullups on EXP0 so rising edge is faster
@ -73,4 +92,3 @@ int detect_console( cartridge *cart, USBtransfer *transfer )
//INL SNES boards memory mapping is controlled by /RESET pin
//roms are still visible when /RESET low, but SRAM isn't

87
host/source/file.c Normal file
View File

@ -0,0 +1,87 @@
#include "file.h"
#define SIZE_NES_HEADER 16
#define SIZE_PRG_BANK 16384
#define SIZE_CHR_BANK 8192
int detect_file( rom_image *rom_info, char *filename )
{
int rv = 0;
// int index = 0;
FILE *fileptr = NULL;
//warn uint8_t data[128];
//first open file
fileptr = fopen( filename, "rb");
//returns file ptr on success, NULL on fail
check( fileptr, "Unable to open file: %s in read binary mode", filename);
//then determine file type
uint8_t header[SIZE_NES_HEADER];
//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
rv = fread( header, sizeof(header[0]), (sizeof(header)/sizeof(header[0])), fileptr);
check( rv = sizeof(header), "Unable to read NES header");
//for ( index = 0; index < SIZE_NES_HEADER; index++ ) {
// debug("header byte #%d = h%x c%c", index, header[index], header[index]);
//}
//0-3: Constant $4E $45 $53 $1A ("NES" followed by MS-DOS end-of-file)
if ( (header[0]=='N') && (header[1]=='E') && (header[2]=='S') && (header[3]==0x1A) ) {
debug("detected ines header");
rom_info->console = NES_CART;
} else {
debug("only ines files currently accepted as input");
goto error;
}
//4: Size of PRG ROM in 16 KB units
rom_info->prg_size = header[4] * SIZE_PRG_BANK;
debug("PRG ROM size= %d", rom_info->prg_size);
//5: Size of CHR ROM in 8 KB units (Value 0 means the board uses CHR RAM)
rom_info->chr_size = header[5] * SIZE_CHR_BANK;
debug("CHR ROM size= %d", rom_info->chr_size);
//6: Flags 6
// 76543210
// ||||||||
// ||||+||+- 0xx0: vertical arrangement/horizontal mirroring (CIRAM A10 = PPU A11)
// |||| || 0xx1: horizontal arrangement/vertical mirroring (CIRAM A10 = PPU A10)
// |||| || 1xxx: four-screen VRAM
// |||| |+-- 1: Cartridge contains battery-backed PRG RAM ($6000-7FFF) or other persistent memory
// |||| +--- 1: 512-byte trainer at $7000-$71FF (stored before PRG data)
// ++++----- Lower nybble of mapper number
rom_info->mapper = (header[6]>>4);
rom_info->mapper |= (header[7] & 0xF0);
debug("mapper #%d", rom_info->mapper);
rom_info->mirroring = header[6] & 0x09; //0b0000 1001
debug("mirroring:%x", rom_info->mirroring);
//7: Flags 7
// 76543210
// ||||||||
// |||||||+- VS Unisystem
// ||||||+-- PlayChoice-10 (8KB of Hint Screen data stored after CHR data)
// ||||++--- If equal to 2, flags 8-15 are in NES 2.0 format
// ++++----- Upper nybble of mapper number
//8: Size of PRG RAM in 8 KB units (Value 0 infers 8 KB for compatibility; see PRG RAM circuit)
//9: Flags 9
//10: Flags 10 (unofficial)
//11-15: Zero filled
//close file
check( fclose(fileptr) == SUCCESS, "Unable to close file");
fileptr = NULL;
return 0;
error:
if (fileptr) {
fclose(fileptr);
}
return -1;
}

34
host/source/file.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef _file_h
#define _file_h
//uncomment to DEBUG this file alone
#define DEBUG
//"make debug" to get DEBUG msgs on entire program
#include "dbg.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <libusb.h>
//TODO put defintions in separate project wide .h file
#include "cartridge.h"
//cartridge object/struct
typedef struct rom_image{
int console; //console the cart plays in
int mapper; //mapper number of the board
int submap;
int mapvariant;
int prg_size;
int chr_size;
int ram_size;
int battery;
int mirroring;
} rom_image;
int detect_file( rom_image *rom_info, char *filename );
#endif

View File

@ -18,6 +18,7 @@
#include "erase.h"
#include "test.h"
#include "cartridge.h"
#include "file.h"
int main(int argc, char *argv[])
@ -163,17 +164,6 @@ int main(int argc, char *argv[])
libusb_log = atoi(L_value);
check( ((libusb_log >= LIBUSB_LOG_LEVEL_NONE) && (libusb_log <=LIBUSB_LOG_LEVEL_DEBUG)),
"Invalid LIBUSB_LOG_LEVEL: %d, must be from 0 to 4", libusb_log );
printf("setting LIBUSB_LOG_LEVEL to: %d\n", libusb_log);
if (libusb_log == 0) {
printf("\tNONE: default no messages ever printed by library\n"); }
if (libusb_log == 1) {
printf("\tERROR: error messages are printed to stderr\n"); }
if (libusb_log == 2) {
printf("\tWARNING: warning and error messages are printed to stderr\n"); }
if (libusb_log == 3) {
printf("\tINFO: informational, warning, & error messages are printed to stdout\n"); }
if (libusb_log == 4) {
printf("\tDEBUG: debug, info, warning, & error messages are printed to stdout\n"); }
}
//open INL retro prog with firmware version 2.0 or greater
if (K_value != NULL) {
@ -182,9 +172,6 @@ int main(int argc, char *argv[])
transfer->handle = open_usb_device( context, libusb_log );
check( transfer->handle != NULL, "Unable to open INL retro-prog usb device handle.");
//report successful connection to INL retro-prog
printf("Successfully found and connected to INL retro-prog with firmware version 2.0\n");
//TEST flag for development use to provide means to only call test.c functions
if (T_flag) {
test_function( transfer );
@ -199,31 +186,52 @@ int main(int argc, char *argv[])
cart->console = UNKNOWN;
// -x flag turns off all autodection
if (!x_flag) {
printf("attempting to detect cartridge...\n");
detect_console( cart, transfer );
switch (cart->console) {
case NES_CART: printf("NES cartridge detected!\n");
break;
case FC_CART: printf("Famicom cartridge detected!\n");
break;
case SNES_CART: printf("SNES cartridge detected!\n");
break;
case BKWD_CART: log_err("CARTRIDGE INSERTED BACKWARDS!!!\n");
break;
case UNKNOWN: printf("Unable to detect cartridge...\n");
break;
default:
sentinel("cartridge console element got set to something unsupported.");
}
check(!detect_console( cart, transfer ), "Problem detecting cartridge.");
} else {
printf("auto-detection turned off\n");
}
//detect mapper as much as possible
//detect board manufacturer/flash memories as much as possible
//detect rom sizes as much as possible
//read in user files/args that glean info about expected board
//create file object/struct
rom_image *rom_info = malloc( sizeof(rom_image));
check_mem(rom_info);
//for now just assume user file/args are correct
if ( p_value != NULL ) {
//program file provided at commandline
detect_file( rom_info, p_value );
}
//compare detections to user args and get permission to continue if there are discrepencies
//if flashing, determine if erasures are necessary and where
//erase required sectors of flash
//forced to erase board regardless of current status
if (e_flag) {
erase_nes( transfer );
}
//if flashing determine auto-doubling for oversized flash
//determine if rom can be flashed in a manner to make board compatible with rom
//ie CNROM/colordreams can be over flashed to play NROM
//BNROM can be overflashed to simulate UNROM
//SUROM can be overflashed to run as SNROM
//determine if snes input rom needs deinterleaved
//dump or flash data based on user args
//find some fun trivia to present to user while waiting for flash operatoin..?
//perform CRC checking to check integrity of dump/flash operation
//handle simple LED ON/OFF within main for now
//TODO cut this newbie code out of here

View File

@ -37,6 +37,23 @@ libusb_device_handle * open_usb_device( libusb_context *context, int log_level )
if (log_level>0) printf("Successfully initalized libusb\n");
//void libusb_set_debug ( libusb_context * ctx, int level )
if ( log_level>0) {
printf("setting LIBUSB_LOG_LEVEL to: %d\n", log_level);
switch ( log_level) {
case 1:
printf("\tERROR: error messages are printed to stderr\n");
break;
case 2:
printf("\tWARNING: warning and error messages are printed to stderr\n");
break;
case 3:
printf("\tINFO: informational, warning, & error messages are printed to stdout\n");
break;
case 4:
printf("\tDEBUG: debug, info, warning, & error messages are printed to stdout\n");
break;
}
}
libusb_set_debug(context, log_level);
//discover all usb devices
@ -155,6 +172,8 @@ libusb_device_handle * open_usb_device( libusb_context *context, int log_level )
//
// As an implementation detail, libusb_open() actually adds a reference to the device in question. This is because the device remains available through the handle via libusb_get_device(). The reference is deleted during libusb_close().
//report successful connection to INL retro-prog
printf("Successfully found and connected to INL retro-prog with firmware version 2.0\n");
//free device list if it was left open
if (device_list) {