Initial commit
This commit is contained in:
commit
1d7a13e2c5
72 changed files with 21402 additions and 0 deletions
MakefileMakefile.mingwblocks.cppblocks.hbuild.makconfig.makdbframes.cppframes.hicon.cppicon.hmemcard.cppmemcard.hpsxicontool.cpppsxicontool.h
qt-gui
BA.pngBE.pngBJ.pngmain.cpppsxicon.cpppsxicon.hpsxmemcard.cpppsxmemcard.hpsxsavewidget.cpppsxsavewidget.hqt-gui.pro
qt-test-cli
test.cpptestdata
ALUNDRA2 FILE1 Cabin.mcsCHRONO CROSS 01.mcsCHRONO CROSS 02.mcsCHRONO CROSS 03.mcsCHRONO CROSS 04.mcsCHRONO CROSS 05.mcsCHRONO CROSS 06.mcsCHRONO CROSS 07.mcsCHRONO CROSS 08.mcsCHRONO CROSS 09.mcsDW7 01 Phoe L01 0 00.mcsFF7 SAVE01 64 05.mcsFF7 SAVE01 64 23.mcsFF7 SAVE02 32 17.mcsFF7 SAVE02 47 20.mcsFF7 SAVE03 65 03.mcsFF8 01 14 05.mcsFF9 FILE01 14 01.mcsFF9 FILE06 58 04.mcsFFT FILE01 02 28 48.mcsFFT FILE01 13 01 48.mcsGRANDIA 1 Gadwin s House 272 07.mcsIntelligent Qube.mcsLegend of Legaia 01 Time 09 53.mcsMGS EZ 01 40 U Grnd Pssge.mcsMGS EZ 04 45 Spply Rte.mcsMGS NM 00 29 Cell.mcsMGS NM 08 21 U Grnd Base 3.mcsMGS VR Training Data.mcsSaiyuki01 Lv23 Ch 2 19 43 Map.mcsSaiyuki02 Lv25 Ch 2 20 53 In B.mcsSaiyuki03 Lv26 Ch 2 21 05 In B.mcsTHE KING OF FIGHTERS 99.mcsVALKYRIE PROFILE No 1 LV 18.mcsWO3 CFG.mcsWO3 Venom PortKr Pirna 1 45 06.mcsWild Arms FILE01 LV13.mcsWild Arms FILE01 LV14.mcsdbdbase.ps1epsxe000.mcrff7.mcs
8
Makefile
Normal file
8
Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
include config.mak
|
||||
|
||||
OUTPUT = $(PROG)
|
||||
CC = g++
|
||||
LD = $(CC)
|
||||
AR = ar
|
||||
|
||||
include build.mak
|
8
Makefile.mingw
Normal file
8
Makefile.mingw
Normal file
|
@ -0,0 +1,8 @@
|
|||
include config.mak
|
||||
|
||||
OUTPUT = $(PROG).exe
|
||||
CC = /opt/cross/bin/i386-mingw32msvc-g++
|
||||
LD = $(CC)
|
||||
AR = /opt/cross/bin/i386-mingw32msvc-ar
|
||||
|
||||
include build.mak
|
33
blocks.cpp
Normal file
33
blocks.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "blocks.h"
|
||||
#include <string.h>
|
||||
|
||||
Frame* Block::getFrame( int index ) { return index >= 0 && index < 64 ? &frames[index] : 0; }
|
||||
|
||||
IdentificationFrame* DirectoryBlock::IDFrame() { return (IdentificationFrame*)&frames[0]; }
|
||||
DirectoryFrame* DirectoryBlock::Directory( int index ) { return index < 15 && index >= 0 ? (DirectoryFrame*)&frames[index + 1] : 0; }
|
||||
void DirectoryBlock::Directory( int index, DirectoryFrame *frame ) { memcpy( &frames[index], frame, sizeof( DirectoryFrame ) ); }
|
||||
Frame* DirectoryBlock::Reserved( int index ) { return index < 20 && index >= 0 ? &frames[index + 16] : 0; }
|
||||
Frame* DirectoryBlock::Unused( int index ) { return index < 27 && index >= 0 ? &frames[index + 36] : 0; }
|
||||
Frame* DirectoryBlock::WriteTest() { return &frames[63]; }
|
||||
int DirectoryBlock::nextOpenBlock() {
|
||||
for( int i = 0; i < 15; i++ ) {
|
||||
int type = Directory( i )->blockType();
|
||||
if( type >= 160 && type <= 163 ) { return i + 1; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
SaveHeaderFrame* InitialBlock::Header() { return (SaveHeaderFrame*)&frames[0]; }
|
||||
Icon* InitialBlock::getIcon( int index ) {
|
||||
//return index < 3 && index >= 0 ? &frames[index + 1] : 0;
|
||||
SaveHeaderFrame *header = Header();
|
||||
IconFrame *frame = (IconFrame*)&frames[index + 1];
|
||||
Icon *icon = new Icon();
|
||||
for( int y = 0; y < 16; y++ ) {
|
||||
icon->paletteColor( y, header->paletteColor( y ) );
|
||||
for( int x = 0; x < 16; x++ ) {
|
||||
icon->pixel( x, y, frame->colorAt( x, y ) );
|
||||
}
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
40
blocks.h
Normal file
40
blocks.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef BLOCKS_H
|
||||
#define BLOCKS_H
|
||||
|
||||
#include "frames.h"
|
||||
|
||||
class Block {
|
||||
protected:
|
||||
Frame frames[64];
|
||||
public:
|
||||
Frame* getFrame( int index );
|
||||
enum blockType {
|
||||
PSX_BLOCK_INITIAL = 81,
|
||||
PSX_BLOCK_MEDIAL = 82,
|
||||
PSX_BLOCK_FINAL = 83,
|
||||
PSX_BLOCK_FORMATTED = 160,
|
||||
PSX_BLOCK_DELETED_INITIAL = 161,
|
||||
PSX_BLOCK_DELETED_MEDIAL = 162,
|
||||
PSX_BLOCK_DELETED_FINAL = 163,
|
||||
PSX_BLOCK_RESERVED = 0xFFFFFFFF
|
||||
};
|
||||
};
|
||||
|
||||
class DirectoryBlock : protected Block {
|
||||
public:
|
||||
IdentificationFrame* IDFrame();
|
||||
DirectoryFrame* Directory( int index );
|
||||
void Directory( int index, DirectoryFrame *frame );
|
||||
Frame* Reserved( int index );
|
||||
Frame* Unused( int index );
|
||||
Frame* WriteTest();
|
||||
int nextOpenBlock();
|
||||
};
|
||||
|
||||
class InitialBlock : protected Block {
|
||||
public:
|
||||
SaveHeaderFrame* Header();
|
||||
Icon* getIcon( int index );
|
||||
};
|
||||
|
||||
#endif // BLOCKS_H
|
43
build.mak
Normal file
43
build.mak
Normal file
|
@ -0,0 +1,43 @@
|
|||
CFLAGS = -g -Wall
|
||||
LDFLAGS = -L.
|
||||
|
||||
LIBVERSIONMAJOR = 0
|
||||
LIBVERSIONMINOR = 0.1
|
||||
|
||||
OBJS = blocks.o \
|
||||
frames.o \
|
||||
memcard.o \
|
||||
icon.o
|
||||
|
||||
.PHONY: clean lib-static static lib-shared shared qtdir
|
||||
|
||||
all: clean static
|
||||
qt: clean lib-shared qtdir
|
||||
|
||||
qtdir:
|
||||
make -C qt-test-cli clean all
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a *.so* $(OUTPUT)
|
||||
|
||||
lib-static: $(OBJS)
|
||||
$(AR) rcs lib$(LIB).a $(OBJS)
|
||||
|
||||
lib-shared: $(OBJS)
|
||||
ifeq ($(CC),g++)
|
||||
$(LD) -shared -Wl,-soname,lib$(LIB).so.$(LIBVERSIONMAJOR) -o lib$(LIB).so.$(LIBVERSIONMAJOR).$(LIBVERSIONMINOR) $(OBJS)
|
||||
ln -fs lib$(LIB).so.$(LIBVERSIONMAJOR).$(LIBVERSIONMINOR) lib$(LIB).so.$(LIBVERSIONMAJOR)
|
||||
ln -fs lib$(LIB).so.$(LIBVERSIONMAJOR).$(LIBVERSIONMINOR) lib$(LIB).so
|
||||
else
|
||||
$(LD) -shared -Wl,-soname,lib$(LIB).so.$(LIBVERSIONMAJOR) -o lib$(LIB).dll $(OBJS)
|
||||
endif
|
||||
|
||||
static: lib-static
|
||||
$(LD) $(LDFLAGS) -static $(PROG).cpp -l$(LIB) -o $(OUTPUT)
|
||||
|
||||
shared: lib-shared $(PROG).o
|
||||
$(LD) $(LDFLAGS) -l$(LIB) $(PROG).o -o $(OUTPUT)
|
||||
|
||||
%.o: %.cpp
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
4
config.mak
Normal file
4
config.mak
Normal file
|
@ -0,0 +1,4 @@
|
|||
PROG = test
|
||||
LIB = psxsave
|
||||
LIBVERSIONMAJOR = 0
|
||||
LIBVERSIONMINOR = 0.1
|
1
db
Symbolic link
1
db
Symbolic link
|
@ -0,0 +1 @@
|
|||
testdata/db
|
75
frames.cpp
Normal file
75
frames.cpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
#include "frames.h"
|
||||
#include <string.h>
|
||||
|
||||
char* Frame::getString( int offset, int length ) {
|
||||
char* data = new char[length];
|
||||
strncpy( data, &bytes[offset], length );
|
||||
data[length] = 0; // Properly terminate the returned string
|
||||
return data;
|
||||
}
|
||||
|
||||
int Frame::getInt32( int offset ) {
|
||||
return *reinterpret_cast<int*>( &bytes[offset] );
|
||||
}
|
||||
int Frame::getInt16( int offset ) {
|
||||
return *reinterpret_cast<short int*>( &bytes[offset] );
|
||||
}
|
||||
void Frame::putInt32( int offset, int value ) {
|
||||
for( int i = 0; i < 4; i++ ) {
|
||||
bytes[offset + i] = ( value & ( 0xFF << ( 8 * i ) ) ) >> ( 8 * i );
|
||||
}
|
||||
}
|
||||
void Frame::putInt16( int offset, int value ) {
|
||||
for( int i = 0; i < 2; i++ ) {
|
||||
bytes[offset + i] = ( value & ( 0xFF << ( 8 * i ) ) ) >> ( 8 * i );
|
||||
}
|
||||
}
|
||||
void Frame::putString( int offset, char* value, int maxLen ) {
|
||||
maxLen = maxLen < 0 ? strlen( value ) : 0;
|
||||
maxLen = (unsigned int)maxLen > strlen( value ) ? strlen( value ) : 0;
|
||||
strncpy( &bytes[offset], value, maxLen );
|
||||
//bytes[offset+maxLen] = 0;
|
||||
}
|
||||
void Frame::putChar( int offset, char value ) {
|
||||
bytes[offset] = value;
|
||||
}
|
||||
|
||||
bool XORFrame::getXOR() {
|
||||
char x = 0;
|
||||
for( int i = 0; i < 128; i++ ) x ^= bytes[i];
|
||||
if( x == 0 ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void XORFrame::setXOR() {
|
||||
char x = 0;
|
||||
for( int i = 0; i < 127; i++ ) x ^= bytes[i];
|
||||
bytes[127] = x;
|
||||
}
|
||||
|
||||
bool IdentificationFrame::isValid() {
|
||||
if( strcmp( id(), "MC" ) == 0 ) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RGB SaveHeaderFrame::paletteColor( int index ) {
|
||||
index = index < 0 || index >= 16 ? 0 : index;
|
||||
char triplet[2] = { bytes[0x60 + ( index * 2 )], bytes[0x60 + ( index * 2 + 1 )] };
|
||||
RGB color;
|
||||
color.r = ( triplet[0] & 31 ) << 3;
|
||||
color.g = ( ( triplet[0] & 224 ) >> 2 ) + ( ( triplet[1] & 3 ) << 6 );
|
||||
color.b = ( triplet[1] & 124 ) << 1;
|
||||
return color;
|
||||
}
|
||||
|
||||
int IconFrame::colorAt( int x, int y ) {
|
||||
int offset = x / 2;
|
||||
if( x % 2 == 0 ) {
|
||||
return bytes[(y*8)+offset] & 15;
|
||||
} else {
|
||||
return ( bytes[(y*8)+offset] & 240 ) >> 4;
|
||||
}
|
||||
}
|
60
frames.h
Normal file
60
frames.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
#ifndef FRAMES_H
|
||||
#define FRAMES_H
|
||||
|
||||
#include "icon.h"
|
||||
|
||||
class Frame {
|
||||
protected:
|
||||
char bytes[128];
|
||||
public:
|
||||
char* getData( int offset ) { return &bytes[offset]; }
|
||||
char* getString( int offset, int length );
|
||||
int getInt32( int offset );
|
||||
int getInt16( int offset );
|
||||
void putInt32( int offset, int value );
|
||||
void putInt16( int offset, int value );
|
||||
void putString( int offset, char* value, int maxLen = -1 );
|
||||
void putChar( int offset, char value );
|
||||
};
|
||||
|
||||
class XORFrame : protected Frame {
|
||||
public:
|
||||
bool getXOR();
|
||||
void setXOR();
|
||||
};
|
||||
|
||||
class IdentificationFrame : public XORFrame {
|
||||
public:
|
||||
// I might put a byte-for-byte check here for safety and completeness, but the XOR is fine for now.
|
||||
char* id() { return getString( 0x00, 2 ); }
|
||||
bool isValid();
|
||||
};
|
||||
|
||||
class DirectoryFrame : public XORFrame {
|
||||
public:
|
||||
int blockType() { return getInt32( 0x00 ); }
|
||||
void blockType( int value ) { putInt32( 0x00, value ); }
|
||||
int size() { return getInt32( 0x04 ); }
|
||||
void size( int size ) { putInt32( 0x04, size ); }
|
||||
int nextBlock() { return getInt16( 0x08 ); }
|
||||
char* territoryCode() { return getString( 0x0A, 2 ); }
|
||||
char* licenseCode() { return getString( 0x0C, 10 ); }
|
||||
char* saveCode() { return getString( 0x16, 8 ); }
|
||||
|
||||
};
|
||||
|
||||
class SaveHeaderFrame : protected Frame {
|
||||
public:
|
||||
char* magicNumber() { return getString( 0x00, 2 ); }
|
||||
int iconDisplayType() { return bytes[0x02]; }
|
||||
int blocksUsed() { return bytes[0x03]; }
|
||||
char* SJISSaveTitle() { return getString( 0x04, 64 ); }
|
||||
RGB paletteColor( int index );
|
||||
};
|
||||
|
||||
class IconFrame : protected Frame {
|
||||
public:
|
||||
int colorAt( int x, int y );
|
||||
};
|
||||
|
||||
#endif // FRAMES_H
|
80
icon.cpp
Normal file
80
icon.cpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
#include "icon.h"
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
Icon::Icon() {
|
||||
for( int x = 0; x < 16; x++ ) {
|
||||
palette[x] = RGB();
|
||||
for( int y = 0; y < 16; y++ ) {
|
||||
pixels[x][y] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Icon::pixel( int x, int y ) {
|
||||
x = x < 0 || x >= 16 ? 0 : x;
|
||||
y = y < 0 || y >= 16 ? 0 : y;
|
||||
return pixels[x][y];
|
||||
}
|
||||
|
||||
RGB Icon::pixelRGB( int x, int y ) {
|
||||
x = x < 0 || x >= 16 ? 0 : x;
|
||||
y = y < 0 || y >= 16 ? 0 : y;
|
||||
return paletteColor( pixels[x][y] );
|
||||
}
|
||||
|
||||
void Icon::pixel( int x, int y, int colorIndex ) {
|
||||
x = x < 0 || x >= 16 ? 0 : x;
|
||||
y = y < 0 || y >= 16 ? 0 : y;
|
||||
pixels[x][y] = colorIndex;
|
||||
}
|
||||
|
||||
RGB Icon::paletteColor( int index ) {
|
||||
index = index < 0 || index >= 16 ? 0 : index;
|
||||
return palette[index];
|
||||
}
|
||||
|
||||
void Icon::paletteColor( int index, RGB color ) {
|
||||
index = index < 0 || index >= 16 ? 0 : index;
|
||||
palette[index] = color;
|
||||
}
|
||||
|
||||
bool Icon::exportXPM( char* fileName ) {
|
||||
FILE *xpm = fopen( fileName, "w" );
|
||||
if( xpm < 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf( xpm, "/* XPM */\n" );
|
||||
fprintf( xpm, "static char *psx[] = {\n" );
|
||||
fprintf( xpm, "/* columns rows colors chars-per-pixel */\n" );
|
||||
fprintf( xpm, "\"16 16 16 1\",\n" );
|
||||
|
||||
// Palette Conversion
|
||||
|
||||
char paletteXPM[17] = " .XoO+@#$%&*=-;:";
|
||||
for( int i = 0; i < 16; i++ ) {
|
||||
RGB col = paletteColor( i );
|
||||
fprintf( xpm, "\"%c c #%.2x%.2x%.2x\",\n", paletteXPM[i], col.r, col.g, col.b );
|
||||
}
|
||||
|
||||
fprintf( xpm, "/* pixels */\n" );
|
||||
|
||||
// Pixel Conversion
|
||||
|
||||
for( int y = 0; y < 16; y++ ) {
|
||||
fprintf( xpm, "\"" );
|
||||
for( int x = 0; x < 16; x++ ) {
|
||||
fprintf( xpm, "%c", paletteXPM[ pixel( x, y ) ] );
|
||||
}
|
||||
if( y < 15 ) {
|
||||
fprintf( xpm, "\",\n" );
|
||||
} else {
|
||||
fprintf( xpm, "\"\n}" );
|
||||
}
|
||||
}
|
||||
|
||||
fclose( xpm );
|
||||
return true;
|
||||
}
|
27
icon.h
Normal file
27
icon.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef ICON_H
|
||||
#define ICON_H
|
||||
|
||||
struct RGB {
|
||||
int r;
|
||||
int g;
|
||||
int b;
|
||||
RGB( int r = 0, int g = 0, int b = 0 ) { this->r = r; this->g = g; this->b = b; }
|
||||
};
|
||||
|
||||
class Icon {
|
||||
private:
|
||||
char pixels[16][16];
|
||||
RGB palette[16];
|
||||
public:
|
||||
Icon();
|
||||
int pixel( int x, int y );
|
||||
RGB pixelRGB( int x, int y );
|
||||
void pixel( int x, int y, int colorIndex );
|
||||
RGB paletteColor( int index );
|
||||
void paletteColor( int index, RGB color );
|
||||
|
||||
bool exportXPM( char* fileName );
|
||||
};
|
||||
|
||||
#endif // ICON_H
|
||||
|
120
memcard.cpp
Normal file
120
memcard.cpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "memcard.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
MemoryCard::MemoryCard() {
|
||||
for( int i = 0; i < 16; i++ ) {
|
||||
this->blocks[i] = new Block();
|
||||
}
|
||||
}
|
||||
|
||||
bool MemoryCard::loadFile( char *fileName ) {
|
||||
fstream file;
|
||||
file.open( fileName, ios::in | ios::binary );
|
||||
if( !file.is_open() ) {
|
||||
cout << "'" << fileName << "' could not be opened for input, exiting.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
for( int i = 0; i < 16; i++ ) {
|
||||
/*
|
||||
blocks[i] = new Block();
|
||||
file.read( reinterpret_cast<char*>( blocks[i] ), sizeof( Block ) );
|
||||
if( file.gcount() != sizeof( Block ) ) {
|
||||
cout << "Error reading block " << i << ", read count less than initial block size\n";
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
this->loadBlockFromFile( fileName, i );
|
||||
}
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemoryCard::loadBlockFromFile( char *fileName, int srcBlock, int dstBlock, int offset ) {
|
||||
srcBlock = srcBlock > 15 || srcBlock < 0 ? 0 : srcBlock;
|
||||
dstBlock = dstBlock > 15 || dstBlock < 0 ? srcBlock : dstBlock;
|
||||
fstream file;
|
||||
file.open( fileName, ios::in | ios::binary );
|
||||
if( !file.is_open() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
file.seekg( srcBlock * sizeof( Block ) + offset );
|
||||
this->blocks[dstBlock] = new Block();
|
||||
file.read( reinterpret_cast<char*>( this->blocks[dstBlock] ), sizeof( Block ) );
|
||||
if( file.gcount() != sizeof( Block ) ) {
|
||||
cout << "Error reading block " << srcBlock << ", read count less than initial block size\n";
|
||||
return false;
|
||||
}
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemoryCard::loadMCS( char* fileName, int dstBlock ) {
|
||||
if( dstBlock <= 0 ) {
|
||||
dstBlock = this->directory()->nextOpenBlock();
|
||||
if( dstBlock <= 0 ) { return false; }
|
||||
}
|
||||
fstream file;
|
||||
file.open( fileName, ios::in | ios::binary );
|
||||
if( !file.is_open() ) {
|
||||
return false;
|
||||
}
|
||||
DirectoryFrame *dirEntry = new DirectoryFrame();
|
||||
file.read( reinterpret_cast<char*>( dirEntry ), sizeof( DirectoryFrame ) );
|
||||
file.close();
|
||||
|
||||
if( file.gcount() == sizeof( DirectoryFrame ) ) {
|
||||
this->loadBlockFromFile( fileName, 0, dstBlock, sizeof( DirectoryFrame ) );
|
||||
this->directory()->Directory( dstBlock, dirEntry );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemoryCard::saveFile( char* fileName, fileFormatCard format ) {
|
||||
fstream file;
|
||||
file.open( fileName, ios::out | ios::binary );
|
||||
if( !file.is_open() ) {
|
||||
return false;
|
||||
}
|
||||
switch( format ) {
|
||||
case FORMAT_RAW:
|
||||
default:
|
||||
for( int i = 0; i < 16; i++ ) {
|
||||
file.write( reinterpret_cast<char*>( blocks[i] ), sizeof( Block ) );
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemoryCard::saveBlockToFile( char* fileName, int block, fileFormatSingle format ) {
|
||||
fstream file;
|
||||
file.open( fileName, ios::out | ios::binary );
|
||||
if( !file.is_open() ) {
|
||||
return false;
|
||||
}
|
||||
switch( format ) {
|
||||
case FORMAT_MCS:
|
||||
default:
|
||||
file.write( reinterpret_cast<char*>( directory()->Directory( block - 1 ) ), sizeof( Frame ) );
|
||||
file.write( reinterpret_cast<char*>( blocks[block] ), sizeof( Block ) );
|
||||
break;
|
||||
}
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
Block* MemoryCard::getBlock( int index = 0 ) {
|
||||
index = index > 15 || index < 0 ? 0 : index;
|
||||
return blocks[index];
|
||||
}
|
||||
|
||||
DirectoryBlock* MemoryCard::directory() {
|
||||
return (DirectoryBlock*)this->blocks[0];
|
||||
}
|
28
memcard.h
Normal file
28
memcard.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef MEMCARD_H
|
||||
#define MEMCARD_H
|
||||
|
||||
#include "blocks.h"
|
||||
|
||||
class MemoryCard {
|
||||
private:
|
||||
Block *blocks[16];
|
||||
public:
|
||||
MemoryCard();
|
||||
|
||||
enum fileFormatCard {
|
||||
FORMAT_RAW
|
||||
};
|
||||
enum fileFormatSingle {
|
||||
FORMAT_MCS
|
||||
};
|
||||
|
||||
bool loadFile( char* fileName );
|
||||
bool loadBlockFromFile( char *fileName, int srcBlock, int dstBlock = -1, int offset = 0 );
|
||||
bool loadMCS( char* fileName, int dstBlock = -1 );
|
||||
bool saveFile( char* fileName, fileFormatCard format = FORMAT_RAW );
|
||||
bool saveBlockToFile( char *fileName, int block, fileFormatSingle format = FORMAT_MCS );
|
||||
Block* getBlock( int index );
|
||||
DirectoryBlock* directory();
|
||||
};
|
||||
|
||||
#endif // MEMCARD_H
|
92
psxicontool.cpp
Normal file
92
psxicontool.cpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
#include "psxicontool.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
PSXIconTool::PSXIconTool() {
|
||||
this->error[0] = 0;
|
||||
}
|
||||
|
||||
bool PSXIconTool::loadMCS( char* filename ) {
|
||||
fstream savefile;
|
||||
savefile.open( filename, ios::in );
|
||||
if( !savefile.is_open() ) {
|
||||
sprintf( this->error, "Unable to open file \"%s\" for reading", filename );
|
||||
return false;
|
||||
}
|
||||
savefile.read( reinterpret_cast<char*>( &PSX_Save ), sizeof( _PSX_Save ) );
|
||||
savefile.close();
|
||||
|
||||
// Convert icon data
|
||||
|
||||
for( int i = 0; i < 16; i++ ) {
|
||||
icon.palette[i].red = ( PSX_Save.save_header.palette[i][0] & 31 ) << 3;
|
||||
icon.palette[i].green = ( ( PSX_Save.save_header.palette[i][0] & 224 ) >> 2 ) + ( ( PSX_Save.save_header.palette[i][1] & 3 ) << 6 );
|
||||
icon.palette[i].blue = ( PSX_Save.save_header.palette[i][1] & 124 ) << 1;
|
||||
}
|
||||
for( int y = 0; y < 16; y++ ) {
|
||||
for( int x = 0; x < 8; x++ ) {
|
||||
icon.pixels[y][x * 2] = PSX_Save.save_header.icons[0][y][x] & 15;
|
||||
icon.pixels[y][x * 2 + 1] = ( PSX_Save.save_header.icons[0][y][x] & 240 ) >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool PSXIconTool::exportXPM( char* filename ) {
|
||||
FILE *xpm = fopen( filename, "w" );
|
||||
if( xpm < 0 ) {
|
||||
sprintf( this->error, "Unable to open file \"%s\" for writing", filename );
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf( xpm, "/* XPM */\n" );
|
||||
fprintf( xpm, "static char *psx[] = {\n" );
|
||||
fprintf( xpm, "/* columns rows colors chars-per-pixel */\n" );
|
||||
fprintf( xpm, "\"16 16 16 1\",\n" );
|
||||
|
||||
// Palette Conversion
|
||||
|
||||
char palette[17] = " .XoO+@#$%&*=-;:";
|
||||
for( int i = 0; i < 16; i++ ) {
|
||||
fprintf( xpm, "\"%c c #%.2x%.2x%.2x\",\n", palette[i], icon.palette[i].red, icon.palette[i].green, icon.palette[i].blue );
|
||||
}
|
||||
|
||||
fprintf( xpm, "/* pixels */\n" );
|
||||
|
||||
// Pixel Conversion
|
||||
|
||||
for( int y = 0; y < 16; y++ ) {
|
||||
fprintf( xpm, "\"" );
|
||||
for( int x = 0; x < 16; x++ ) {
|
||||
fprintf( xpm, "%c", palette[ icon.pixels[y][x] ] );
|
||||
}
|
||||
if( y < 15 ) {
|
||||
fprintf( xpm, "\",\n" );
|
||||
} else {
|
||||
fprintf( xpm, "\"\n}" );
|
||||
}
|
||||
}
|
||||
|
||||
fclose( xpm );
|
||||
return true;
|
||||
}
|
||||
|
||||
char* PSXIconTool::errorMessage() {
|
||||
return error;
|
||||
}
|
||||
|
||||
void PSXIconTool::printInfo() {
|
||||
char* var;
|
||||
|
||||
printf( "Block Type: %d\n", PSX_Save.block_header.block_type );
|
||||
printf( "Save Size: %d\n", PSX_Save.block_header.save_size );
|
||||
printf( "Next Block: %d\n", PSX_Save.block_header.next_block );
|
||||
strncpy( var, PSX_Save.block_header.territory_code, 2 ); var[2] = 0;
|
||||
printf( "Territory Code: %s\n", var );
|
||||
strncpy( var, PSX_Save.block_header.license_code, 10 ); var[10] = 0;
|
||||
printf( "License Code: %s\n", var );
|
||||
strncpy( var, PSX_Save.block_header.save_code, 8 ); var[8] = 0;
|
||||
printf( "Save Code: %s\n", var );
|
||||
}
|
81
psxicontool.h
Normal file
81
psxicontool.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
|
||||
/**
|
||||
Stores the header data from the first block of
|
||||
playstation save data
|
||||
*/
|
||||
struct PSX_Save_Block_Header {
|
||||
int block_type;
|
||||
int save_size;
|
||||
short next_block;
|
||||
char territory_code[2];
|
||||
char license_code[10];
|
||||
char save_code[8];
|
||||
char code_end;
|
||||
char unused[94];
|
||||
char xor_code;
|
||||
};
|
||||
|
||||
/**
|
||||
Stores the header data from the first frame of
|
||||
playstation save data
|
||||
*/
|
||||
struct PSX_Save_Header {
|
||||
char magic_number[2]; //!< "SC"
|
||||
char icon_display; //!< 17 - static (1 frame), 18 - animated (2 frames), 19 - animated (3 frames)
|
||||
char blocks_used;
|
||||
char sjis_save_title[64]; //!< Save title in Shift-JIS character set, kanji only
|
||||
char padding[28];
|
||||
char palette[16][2]; //!< Stored as BBBBBGGGGGRRRRR
|
||||
char icons[3][16][8]; //!< Three icons, sixteen rows of 8 bytes (4 bits per pixel)
|
||||
};
|
||||
|
||||
/**
|
||||
Structure for holding parsed icon data
|
||||
*/
|
||||
struct Icon {
|
||||
struct _RGB {
|
||||
int red;
|
||||
int blue;
|
||||
int green;
|
||||
};
|
||||
_RGB palette[16];
|
||||
char pixels[16][16];
|
||||
};
|
||||
|
||||
|
||||
class PSXIconTool {
|
||||
private:
|
||||
struct _PSX_Save {
|
||||
PSX_Save_Block_Header block_header;
|
||||
PSX_Save_Header save_header;
|
||||
} PSX_Save;
|
||||
Icon icon;
|
||||
char error[2048];
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/** Constructor */
|
||||
PSXIconTool();
|
||||
|
||||
/**
|
||||
* Load an MCS file (raw block data for a single playstation save file)
|
||||
* @param filename
|
||||
* @return True on success, False on failure.
|
||||
* Use errorMessage() to determine the error that occurred upon failure.
|
||||
*/
|
||||
bool loadMCS( char* filename );
|
||||
|
||||
bool exportXPM( char* filename );
|
||||
bool exportPCX( char* filename );
|
||||
|
||||
Icon *getIcon() { return &icon; }
|
||||
|
||||
void printInfo();
|
||||
/**
|
||||
*
|
||||
* @return The message from the last error to occur.
|
||||
*/
|
||||
char* errorMessage();
|
||||
};
|
||||
|
BIN
qt-gui/BA.png
Normal file
BIN
qt-gui/BA.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 252 B |
BIN
qt-gui/BE.png
Normal file
BIN
qt-gui/BE.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 284 B |
BIN
qt-gui/BJ.png
Normal file
BIN
qt-gui/BJ.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 248 B |
50
qt-gui/main.cpp
Normal file
50
qt-gui/main.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
#include <QtGui>
|
||||
#include <iostream>
|
||||
|
||||
#include "psxsavewidget.h"
|
||||
#include "memcard.h"
|
||||
#include "psxmemcard.h"
|
||||
|
||||
int main( int argc, char *argv[] ) {
|
||||
QApplication app( argc, argv );
|
||||
|
||||
MemoryCard *memCard = new MemoryCard();
|
||||
if( argc > 1 ) {
|
||||
memCard->loadFile( argv[1] );
|
||||
if( argc > 2 ) {
|
||||
for( int i = 2; i < argc; i++ ) {
|
||||
memCard->loadMCS( argv[i] );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::cout << "No filename provided, exiting.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
QMap<QString, QString> games;
|
||||
QWidget *mainWidget = new QWidget;
|
||||
QVBoxLayout *vlayout = new QVBoxLayout;
|
||||
QHBoxLayout *hlayout = new QHBoxLayout;
|
||||
|
||||
PSXMemoryCardModel *memCardModel = new PSXMemoryCardModel( memCard );
|
||||
QTreeView *tv = new QTreeView();
|
||||
tv->setModel( memCardModel );
|
||||
tv->setColumnHidden( 0, true );
|
||||
for( int i = 1; i < 5; i++ ) tv->resizeColumnToContents( i );
|
||||
vlayout->addWidget( tv );
|
||||
|
||||
QWidget *listContainer = new QWidget;
|
||||
listContainer->setLayout( vlayout );
|
||||
hlayout->addWidget( listContainer );
|
||||
PSXSaveWidget *saveWidget = new PSXSaveWidget( memCard );
|
||||
hlayout->addWidget( saveWidget );
|
||||
|
||||
QObject::connect(
|
||||
tv, SIGNAL( clicked( const QModelIndex & ) ),
|
||||
saveWidget, SLOT( setBlockFromModel( const QModelIndex & ) ) );
|
||||
|
||||
mainWidget->setLayout( hlayout );
|
||||
mainWidget->resize( 900, 400 );
|
||||
mainWidget->show();
|
||||
return app.exec();
|
||||
}
|
31
qt-gui/psxicon.cpp
Normal file
31
qt-gui/psxicon.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include "psxicon.h"
|
||||
#include <QPainter>
|
||||
|
||||
PSXIcon::PSXIcon( Icon *icon, QWidget *parent ) : QWidget( parent ) {
|
||||
this->icon = icon;
|
||||
setFixedSize( 64, 64 );
|
||||
}
|
||||
|
||||
void PSXIcon::setIcon( Icon *icon ) {
|
||||
this->icon = icon;
|
||||
}
|
||||
|
||||
void PSXIcon::paintEvent( QPaintEvent *event ) {
|
||||
QImage image( 16, 16, QImage::Format_Indexed8 );
|
||||
image.setNumColors( 16 );
|
||||
for( int i = 0; i < 16; i++ ) {
|
||||
RGB col = this->icon->paletteColor( i );
|
||||
QRgb rgb = QColor::fromRgb( col.r, col.g, col.b ).rgb();
|
||||
image.setColor( i, rgb );
|
||||
}
|
||||
for( int x = 0; x < 16; x++ ) {
|
||||
for( int y = 0; y < 16; y++ ) {
|
||||
image.setPixel( x, y, icon->pixel( x, y ) );
|
||||
}
|
||||
}
|
||||
QRectF target(0.0, 0.0, 64.0, 64.0);
|
||||
QRectF source(0.0, 0.0, 16.0, 16.0);
|
||||
QPainter painter( this );
|
||||
painter.drawImage(target, image, source);
|
||||
|
||||
}
|
12
qt-gui/psxicon.h
Normal file
12
qt-gui/psxicon.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include <QWidget>
|
||||
#include "memcard.h"
|
||||
|
||||
class PSXIcon : public QWidget {
|
||||
private:
|
||||
Icon *icon;
|
||||
protected:
|
||||
void paintEvent( QPaintEvent *event );
|
||||
public:
|
||||
PSXIcon( Icon *icon, QWidget *parent = 0 );
|
||||
void setIcon( Icon *icon );
|
||||
};
|
108
qt-gui/psxmemcard.cpp
Normal file
108
qt-gui/psxmemcard.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
#include "psxmemcard.h"
|
||||
#include "psxicon.h"
|
||||
#include <QTextCodec>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
PSXMemoryCardModel::PSXMemoryCardModel( MemoryCard *memCard, QObject *parent ) : QAbstractTableModel( parent ) {
|
||||
this->memCard = memCard;
|
||||
for( int i = 1; i < 16; i++ ) {
|
||||
DirectoryFrame *directory = memCard->directory()->Directory( i - 1 );
|
||||
int type = directory->blockType();
|
||||
if( type == Block::PSX_BLOCK_INITIAL ) {
|
||||
this->blocks.append( memCard->getBlock( i ) );
|
||||
this->blockId.append( i );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int PSXMemoryCardModel::rowCount( const QModelIndex &parent ) const {
|
||||
if( parent.isValid() ) { return 0; }
|
||||
return this->blocks.count();
|
||||
}
|
||||
|
||||
int PSXMemoryCardModel::columnCount( const QModelIndex &parent ) const {
|
||||
if( parent.isValid() ) { return 0; }
|
||||
return 5;
|
||||
}
|
||||
|
||||
QVariant PSXMemoryCardModel::data( const QModelIndex & index, int role ) const {
|
||||
if( !index.isValid() ) { return QVariant(); }
|
||||
InitialBlock *block = (InitialBlock*)blocks[index.row()];
|
||||
|
||||
switch( index.column() ) {
|
||||
case 0:
|
||||
if( role != Qt::DisplayRole ) { return QVariant(); }
|
||||
return blockId[ index.row() ];
|
||||
case 1:
|
||||
if( role == Qt::DisplayRole ) {
|
||||
QTextCodec *codec = QTextCodec::codecForName("Shift-JIS");
|
||||
if( codec == 0 ) { return QVariant(); }
|
||||
return codec->toUnicode( block->Header()->SJISSaveTitle() );
|
||||
} else if ( role == Qt::DecorationRole ) {
|
||||
Icon *icon = block->getIcon( 0 );
|
||||
QImage image( 16, 16, QImage::Format_Indexed8 );
|
||||
image.setNumColors( 16 );
|
||||
for( int i = 0; i < 16; i++ ) {
|
||||
RGB col = icon->paletteColor( i );
|
||||
QRgb rgb = QColor::fromRgb( col.r, col.g, col.b ).rgb();
|
||||
image.setColor( i, rgb );
|
||||
}
|
||||
for( int x = 0; x < 16; x++ ) {
|
||||
for( int y = 0; y < 16; y++ ) {
|
||||
image.setPixel( x, y, icon->pixel( x, y ) );
|
||||
}
|
||||
}
|
||||
return QPixmap::fromImage( image );
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if( role == Qt::DisplayRole ) {
|
||||
return QString( this->memCard->directory()->Directory( blockId[ index.row() ] - 1 )->licenseCode() );
|
||||
} else if ( role == Qt::DecorationRole ) {
|
||||
QString image = QString( this->memCard->directory()->Directory( blockId[ index.row() ] - 1 )->territoryCode() );
|
||||
image.append( ".png" );
|
||||
return QPixmap::fromImage( QImage( image ) );
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
case 3:
|
||||
if( role != Qt::DisplayRole ) { return QVariant(); }
|
||||
return QString( this->memCard->directory()->Directory( blockId[ index.row() ] - 1 )->saveCode() );
|
||||
case 4:
|
||||
if( role != Qt::DisplayRole ) { return QVariant(); }
|
||||
return ( (InitialBlock*)blocks[ index.row() ] )->Header()->blocksUsed();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant PSXMemoryCardModel::headerData( int section, Qt::Orientation orientation, int role ) const {
|
||||
if( role != Qt::DisplayRole ) { return QVariant(); }
|
||||
switch( section ) {
|
||||
case 0:
|
||||
return tr( "Id" );
|
||||
case 1:
|
||||
return tr( "Save Title" );
|
||||
case 2:
|
||||
return tr( "License Code" );
|
||||
case 3:
|
||||
return tr( "Save Code" );
|
||||
case 4:
|
||||
return tr( "Blocks" );
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QString unicodeToAscii( QString text ) {
|
||||
for( int i = 0xff01; i < 0xff5f; i++ ) {
|
||||
text.replace( QChar( i ), QChar( i - 0xff00 + 0x0020 ) );
|
||||
}
|
||||
for( int i = 0; i < text.length(); i++ ) {
|
||||
if( text[i].unicode() > 0x7f ) { text[i] = 0x5f; }
|
||||
}
|
||||
return text.toAscii();
|
||||
}
|
||||
|
18
qt-gui/psxmemcard.h
Normal file
18
qt-gui/psxmemcard.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <QListView>
|
||||
#include "memcard.h"
|
||||
|
||||
class PSXMemoryCardModel : public QAbstractTableModel {
|
||||
private:
|
||||
MemoryCard *memCard;
|
||||
QList<Block*> blocks;
|
||||
QList<int> blockId;
|
||||
public:
|
||||
PSXMemoryCardModel( MemoryCard *memCard, QObject *parent = 0 );
|
||||
int rowCount( const QModelIndex & parent = QModelIndex() ) const;
|
||||
int columnCount( const QModelIndex & parent = QModelIndex() ) const;
|
||||
QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const;
|
||||
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
|
||||
};
|
||||
|
||||
QString unicodeToAscii( QString text );
|
||||
|
39
qt-gui/psxsavewidget.cpp
Normal file
39
qt-gui/psxsavewidget.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include "psxsavewidget.h"
|
||||
#include <QVBoxLayout>
|
||||
#include <QTextCodec>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
PSXSaveWidget::PSXSaveWidget( MemoryCard *memCard, int block, QWidget *parent ) : QFrame( parent ) {
|
||||
this->memCard = memCard;
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
Icon *icon = new Icon;
|
||||
QFrame *iconContainer = new QFrame;
|
||||
iconContainer->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken );
|
||||
QVBoxLayout *iconLayout = new QVBoxLayout;
|
||||
iconWidget = new PSXIcon( icon );
|
||||
iconLayout->addWidget( iconWidget );
|
||||
iconContainer->setLayout( iconLayout );
|
||||
mainLayout->addWidget( iconContainer );
|
||||
mainLayout->addStretch();
|
||||
label = new QLabel(); mainLayout->addWidget( label );
|
||||
this->setLayout( mainLayout );
|
||||
this->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
|
||||
this->setEnabled( false );
|
||||
if( block != 0 ) { this->setBlock( block ); }
|
||||
}
|
||||
|
||||
void PSXSaveWidget::setBlock( int id ) {
|
||||
InitialBlock *block = (InitialBlock*)memCard->getBlock( id );
|
||||
QTextCodec *codec = QTextCodec::codecForName("Shift-JIS");
|
||||
QString saveTitle = codec->toUnicode( block->Header()->SJISSaveTitle() );
|
||||
//this->label->setText( saveTitle );
|
||||
this->iconWidget->setIcon( block->getIcon( 0 ) );
|
||||
this->iconWidget->update();
|
||||
this->setEnabled( true );
|
||||
}
|
||||
|
||||
void PSXSaveWidget::setBlockFromModel( const QModelIndex &index ) {
|
||||
this->setBlock( index.model()->index( index.row(), 0 ).data().toInt() );
|
||||
}
|
||||
|
18
qt-gui/psxsavewidget.h
Normal file
18
qt-gui/psxsavewidget.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <QFrame>
|
||||
#include <QLabel>
|
||||
#include <QAbstractItemModel>
|
||||
#include "memcard.h"
|
||||
#include "psxicon.h"
|
||||
|
||||
class PSXSaveWidget : public QFrame {
|
||||
Q_OBJECT
|
||||
private:
|
||||
MemoryCard *memCard;
|
||||
PSXIcon *iconWidget;
|
||||
QLabel *label;
|
||||
public:
|
||||
PSXSaveWidget( MemoryCard *memCard = 0, int block = 0, QWidget *parent = 0 );
|
||||
public slots:
|
||||
void setBlock( int id );
|
||||
void setBlockFromModel( const QModelIndex &index );
|
||||
};
|
13
qt-gui/qt-gui.pro
Normal file
13
qt-gui/qt-gui.pro
Normal file
|
@ -0,0 +1,13 @@
|
|||
######################################################################
|
||||
# Automatically generated by qmake (2.01a) Thu Dec 6 10:48:15 2007
|
||||
######################################################################
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET =
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += . ..
|
||||
LIBS += -L.. -lpsxsave
|
||||
|
||||
# Input
|
||||
HEADERS += psxsavewidget.h psxicon.h psxmemcard.h
|
||||
SOURCES += main.cpp psxsavewidget.cpp psxicon.cpp psxmemcard.cpp
|
1
qt-test-cli/db
Symbolic link
1
qt-test-cli/db
Symbolic link
|
@ -0,0 +1 @@
|
|||
../testdata/db
|
97
qt-test-cli/main.cpp
Normal file
97
qt-test-cli/main.cpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <QtGui>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "memcard.h"
|
||||
|
||||
char* decode_sjis( char* sjis ) {
|
||||
QTextCodec *codec = QTextCodec::codecForName("Shift-JIS");
|
||||
if( codec == 0 ) { return "Shift-JIS Not Supported"; }
|
||||
QString unicode = codec->toUnicode( sjis );
|
||||
return unicode.toUtf8().data();
|
||||
}
|
||||
|
||||
int main( int argc, char * argv[] )
|
||||
{
|
||||
QCoreApplication app( argc, argv );
|
||||
char* filename;
|
||||
char buffer[256];
|
||||
string name;
|
||||
string code;
|
||||
map<string, string> games;
|
||||
|
||||
if( argc > 1 ) {
|
||||
filename = argv[1];
|
||||
} else {
|
||||
cout << "No filename provided, exiting.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
fstream db;
|
||||
db.open( "db", ios::in );
|
||||
while( !db.eof() ) {
|
||||
db.getline( buffer, 256 );
|
||||
code = buffer;
|
||||
int offset = code.find( ";" );
|
||||
if( offset > 0 ) {
|
||||
name = code.substr( offset + 1 );
|
||||
code = code.substr( 0, offset );
|
||||
games[code] = name;
|
||||
}
|
||||
}
|
||||
db.close();
|
||||
|
||||
MemoryCard *memCard = new MemoryCard();
|
||||
memCard->loadFile( filename );
|
||||
if( argc > 2 ) {
|
||||
for( int i = 2; i < argc; i++ ) {
|
||||
cout << "Loading MCS (" << argv[i] << ")\n";
|
||||
memCard->loadMCS( argv[i] );
|
||||
}
|
||||
}
|
||||
|
||||
DirectoryBlock *directory = (DirectoryBlock*)memCard->getBlock( 0 );
|
||||
cout << "Loaded " << games.size() << " unique entries from the game database.\n";
|
||||
cout << "================================================================================\n";
|
||||
cout << "Initial block\n";
|
||||
cout << "================================================================================\n";
|
||||
cout << "ID Frame\n";
|
||||
cout << "--------------------------------------------------------------------------------\n";
|
||||
printf( "ID: %s\n", directory->IDFrame()->id() );
|
||||
printf( "XOR Valid: %s\n", directory->IDFrame()->getXOR() ? "Yes" : "No" );
|
||||
printf( "Block Valid: %s\n", directory->IDFrame()->isValid() ? "Yes" : "No" );
|
||||
for( int i = 1; i < 16; i++ ) {
|
||||
cout << "================================================================================\n";
|
||||
cout << "Block " << i << "\n";
|
||||
cout << "================================================================================\n";
|
||||
SaveHeaderFrame *h = ( ( (InitialBlock*)memCard->getBlock( i ) )->Header() );
|
||||
DirectoryFrame *dir = directory->Directory( i - 1 );
|
||||
string code = dir->licenseCode();
|
||||
if( code.size() > 5 ) { code.replace( 4, 1, "-" ); }
|
||||
printf( "Type: %d\n", dir->blockType() );
|
||||
printf( "Size: %d\n", dir->size() );
|
||||
printf( "Next Block: %d\n", dir->nextBlock() );
|
||||
printf( "Territory: %s\n", dir->territoryCode() );
|
||||
printf( "License: %s (%s)\n", dir->licenseCode(), games[code].c_str() );
|
||||
printf( "Save: %s\n", dir->saveCode() );
|
||||
printf( "XOR Valid: %s\n", dir->getXOR() ? "Yes" : "No" );
|
||||
switch( dir->blockType() ) {
|
||||
case 81:
|
||||
cout << "--------------------------------------------------------------------------------\n";
|
||||
printf( "Magic Number: %s\n", h->magicNumber() );
|
||||
printf( "Icon Display Type: %d\n", h->iconDisplayType() );
|
||||
printf( "Blocks Used: %d\n", h->blocksUsed() );
|
||||
printf( "SJIS Save Title: %s\n", decode_sjis( h->SJISSaveTitle() ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
cout << "\n\nNext Open Block: " << directory->nextOpenBlock() << "\n";
|
||||
memCard->saveFile( "test.mcr" );
|
||||
memCard->saveBlockToFile( "test.mcs", 4 );
|
||||
( (InitialBlock*)memCard->getBlock( 4 ) )->getIcon( 0 )->exportXPM( "test.xpm" );
|
||||
return 0;
|
||||
}
|
14
qt-test-cli/qt.pro
Normal file
14
qt-test-cli/qt.pro
Normal file
|
@ -0,0 +1,14 @@
|
|||
######################################################################
|
||||
# Automatically generated by qmake (2.01a) Tue Dec 4 17:27:04 2007
|
||||
######################################################################
|
||||
|
||||
TEMPLATE = app
|
||||
#QT -= gui
|
||||
TARGET = qtpsx
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += . ..
|
||||
LIBS += -L.. -lpsxsave
|
||||
|
||||
|
||||
# Input
|
||||
SOURCES += main.cpp
|
84
test.cpp
Normal file
84
test.cpp
Normal file
|
@ -0,0 +1,84 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "memcard.h"
|
||||
|
||||
char* decode_sjis( char* sjis ) {
|
||||
return sjis;
|
||||
}
|
||||
|
||||
int main( int argc, char * argv[] )
|
||||
{
|
||||
char* filename;
|
||||
char buffer[256];
|
||||
string name;
|
||||
string code;
|
||||
map<string, string> games;
|
||||
|
||||
if( argc > 1 ) {
|
||||
filename = argv[1];
|
||||
} else {
|
||||
cout << "No filename provided, exiting.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
fstream db;
|
||||
db.open( "db", ios::in );
|
||||
while( !db.eof() ) {
|
||||
db.getline( buffer, 256 );
|
||||
code = buffer;
|
||||
int offset = code.find( ";" );
|
||||
if( offset > 0 ) {
|
||||
name = code.substr( offset + 1 );
|
||||
code = code.substr( 0, offset );
|
||||
games[code] = name;
|
||||
}
|
||||
}
|
||||
db.close();
|
||||
|
||||
MemoryCard *memCard = new MemoryCard();
|
||||
memCard->loadFile( filename );
|
||||
if( argc > 2 ) {
|
||||
cout << "Loading MCS (" << argv[2] << ")\n";
|
||||
memCard->loadMCS( argv[2], 4 );
|
||||
}
|
||||
|
||||
DirectoryBlock *directory = (DirectoryBlock*)memCard->getBlock(0);
|
||||
cout << "Loaded " << games.size() << " unique entries from the game database.\n";
|
||||
cout << "================================================================================\n";
|
||||
cout << "Initial block\n";
|
||||
cout << "================================================================================\n";
|
||||
cout << "ID Frame\n";
|
||||
cout << "--------------------------------------------------------------------------------\n";
|
||||
printf( "ID: %s\n", directory->IDFrame()->id() );
|
||||
printf( "XOR Valid: %s\n", directory->IDFrame()->getXOR() ? "Yes" : "No" );
|
||||
printf( "Block Valid: %s\n", directory->IDFrame()->isValid() ? "Yes" : "No" );
|
||||
for( int i = 1; i < 16; i++ ) {
|
||||
cout << "================================================================================\n";
|
||||
cout << "Block " << i << "\n";
|
||||
cout << "================================================================================\n";
|
||||
SaveHeaderFrame *h = ( ( (InitialBlock*)memCard->getBlock( i ) )->Header() );
|
||||
DirectoryFrame *dir = directory->Directory( i - 1 );
|
||||
printf( "Type: %d\n", dir->blockType() );
|
||||
printf( "Size: %d\n", dir->size() );
|
||||
printf( "Next Block: %d\n", dir->nextBlock() );
|
||||
printf( "Territory: %s\n", dir->territoryCode() );
|
||||
printf( "License: %s (%s)\n", dir->licenseCode(), games[dir->licenseCode()].c_str() );
|
||||
printf( "Save: %s\n", dir->saveCode() );
|
||||
printf( "XOR Valid: %s\n", dir->getXOR() ? "Yes" : "No" );
|
||||
switch( dir->blockType() ) {
|
||||
case 81:
|
||||
cout << "--------------------------------------------------------------------------------\n";
|
||||
printf( "Magic Number: %s\n", h->magicNumber() );
|
||||
printf( "Icon Display Type: %d\n", h->iconDisplayType() );
|
||||
printf( "Blocks Used: %d\n", h->blocksUsed() );
|
||||
printf( "SJIS Save Title: %s\n", decode_sjis( h->SJISSaveTitle() ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
BIN
testdata/ALUNDRA2 FILE1 Cabin.mcs
vendored
Normal file
BIN
testdata/ALUNDRA2 FILE1 Cabin.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/CHRONO CROSS 01.mcs
vendored
Normal file
BIN
testdata/CHRONO CROSS 01.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/CHRONO CROSS 02.mcs
vendored
Normal file
BIN
testdata/CHRONO CROSS 02.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/CHRONO CROSS 03.mcs
vendored
Normal file
BIN
testdata/CHRONO CROSS 03.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/CHRONO CROSS 04.mcs
vendored
Normal file
BIN
testdata/CHRONO CROSS 04.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/CHRONO CROSS 05.mcs
vendored
Normal file
BIN
testdata/CHRONO CROSS 05.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/CHRONO CROSS 06.mcs
vendored
Normal file
BIN
testdata/CHRONO CROSS 06.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/CHRONO CROSS 07.mcs
vendored
Normal file
BIN
testdata/CHRONO CROSS 07.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/CHRONO CROSS 08.mcs
vendored
Normal file
BIN
testdata/CHRONO CROSS 08.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/CHRONO CROSS 09.mcs
vendored
Normal file
BIN
testdata/CHRONO CROSS 09.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/DW7 01 Phoe L01 0 00.mcs
vendored
Executable file
BIN
testdata/DW7 01 Phoe L01 0 00.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/FF7 SAVE01 64 05.mcs
vendored
Executable file
BIN
testdata/FF7 SAVE01 64 05.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/FF7 SAVE01 64 23.mcs
vendored
Normal file
BIN
testdata/FF7 SAVE01 64 23.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/FF7 SAVE02 32 17.mcs
vendored
Normal file
BIN
testdata/FF7 SAVE02 32 17.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/FF7 SAVE02 47 20.mcs
vendored
Executable file
BIN
testdata/FF7 SAVE02 47 20.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/FF7 SAVE03 65 03.mcs
vendored
Executable file
BIN
testdata/FF7 SAVE03 65 03.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/FF8 01 14 05.mcs
vendored
Normal file
BIN
testdata/FF8 01 14 05.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/FF9 FILE01 14 01.mcs
vendored
Executable file
BIN
testdata/FF9 FILE01 14 01.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/FF9 FILE06 58 04.mcs
vendored
Executable file
BIN
testdata/FF9 FILE06 58 04.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/FFT FILE01 02 28 48.mcs
vendored
Executable file
BIN
testdata/FFT FILE01 02 28 48.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/FFT FILE01 13 01 48.mcs
vendored
Executable file
BIN
testdata/FFT FILE01 13 01 48.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/GRANDIA 1 Gadwin s House 272 07.mcs
vendored
Normal file
BIN
testdata/GRANDIA 1 Gadwin s House 272 07.mcs
vendored
Normal file
Binary file not shown.
BIN
testdata/Intelligent Qube.mcs
vendored
Executable file
BIN
testdata/Intelligent Qube.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/Legend of Legaia 01 Time 09 53.mcs
vendored
Executable file
BIN
testdata/Legend of Legaia 01 Time 09 53.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/MGS EZ 01 40 U Grnd Pssge.mcs
vendored
Executable file
BIN
testdata/MGS EZ 01 40 U Grnd Pssge.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/MGS EZ 04 45 Spply Rte.mcs
vendored
Executable file
BIN
testdata/MGS EZ 04 45 Spply Rte.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/MGS NM 00 29 Cell.mcs
vendored
Executable file
BIN
testdata/MGS NM 00 29 Cell.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/MGS NM 08 21 U Grnd Base 3.mcs
vendored
Executable file
BIN
testdata/MGS NM 08 21 U Grnd Base 3.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/MGS VR Training Data.mcs
vendored
Executable file
BIN
testdata/MGS VR Training Data.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/Saiyuki01 Lv23 Ch 2 19 43 Map.mcs
vendored
Executable file
BIN
testdata/Saiyuki01 Lv23 Ch 2 19 43 Map.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/Saiyuki02 Lv25 Ch 2 20 53 In B.mcs
vendored
Executable file
BIN
testdata/Saiyuki02 Lv25 Ch 2 20 53 In B.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/Saiyuki03 Lv26 Ch 2 21 05 In B.mcs
vendored
Executable file
BIN
testdata/Saiyuki03 Lv26 Ch 2 21 05 In B.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/THE KING OF FIGHTERS 99.mcs
vendored
Executable file
BIN
testdata/THE KING OF FIGHTERS 99.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/VALKYRIE PROFILE No 1 LV 18.mcs
vendored
Executable file
BIN
testdata/VALKYRIE PROFILE No 1 LV 18.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/WO3 CFG.mcs
vendored
Executable file
BIN
testdata/WO3 CFG.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/WO3 Venom PortKr Pirna 1 45 06.mcs
vendored
Executable file
BIN
testdata/WO3 Venom PortKr Pirna 1 45 06.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/Wild Arms FILE01 LV13.mcs
vendored
Executable file
BIN
testdata/Wild Arms FILE01 LV13.mcs
vendored
Executable file
Binary file not shown.
BIN
testdata/Wild Arms FILE01 LV14.mcs
vendored
Executable file
BIN
testdata/Wild Arms FILE01 LV14.mcs
vendored
Executable file
Binary file not shown.
10107
testdata/db
vendored
Normal file
10107
testdata/db
vendored
Normal file
File diff suppressed because it is too large
Load diff
10110
testdata/dbase.ps1
vendored
Normal file
10110
testdata/dbase.ps1
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
testdata/epsxe000.mcr
vendored
Executable file
BIN
testdata/epsxe000.mcr
vendored
Executable file
Binary file not shown.
BIN
testdata/ff7.mcs
vendored
Executable file
BIN
testdata/ff7.mcs
vendored
Executable file
Binary file not shown.
Loading…
Add table
Reference in a new issue