Reading nes file inputs and extracting data from header.
Creating rom image struct/object to store rom header data.
This commit is contained in:
parent
497e53378b
commit
8654a8f4bf
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue