SuperH-based fx calculators
fx legacy: eactivityformat

 

G1E/G2E eActivity-files consist of a StandardHeader, a special header, the setup-area, some intermediate data, the linedirectory and the lines.
The
File type identifier in the non-inverted StandardHeader is 0x49.
The setup-area:
When an EACT-file is stored, a part of the actual calculator-setup is stored inside of the EACT-file. Each bit of the setup-directory represents the corresponding setup-entry. The size of the setup-directory is 0x10 with G1E/G2E- and 0x2C with
G3E-files. The setup-data-area contains the setup-value for each setup-entry, which corresponding bit in the setup-directory is set. If a bit in the setup-directory is not set, the value of the corresponding setup-entry is assumed to be zero and does not occur in the setup-data-area. Therefore the length of the setup-data-area depends on the count of setup-entries, which value is not zero.
After the line count, the line directory starts. It consists of an according number of line descriptors (EntryType, EntryOffset). A line must be delimited by at least one binary zero and has to end 4-aligned. Alignment fillbytes are generally at random.

G2E-files may contain ECON2-EntryTypes, which is not supported by G1E-eactivity.

The standard heading has the EntryType 0x07.
Pure text lines have the EntryType 0x81.
Text mixed with functions (sin, tan, log a.s.o.) contains zeros and has the EntryType 0x82. The end of such lines cannot be detected by search-for-zero. The offset of the next entry has to be used instead.

The 8 bytes at offset 0x28 are (as hex):
00 01 01 00 50 61 63 6B with G1E-files;
00 01 02 00 02 02 02 01 with G2E-files; (the second int is the version of the OS, which has written the file)
00 01 04 00 01 04 02 00 with G3E-files. (the second int is the version of the OS, which has written the file)
Possibly this is some EACT-version information.

 

EACT:

Offset (b) Size (b) Description
0x20 4 filesize
0x24 4 LS, length of the setup-area (starting at 0x30; 4-aligned)
0x28 4 some EACT-version information (see above)
0x2C 4 with G2E/G3E the OS version, when writing the file ( (see above; only informational)
0x30 4 { 0, 0, 0, 0 }
0x34 0x10 (LSDIR) setup-directory (0x2C for G3E-files)
0x34+LSDIR LS-0x30 setup-data; 4-aligned (filler bytes are usually zero)
0x20+LS 0x10 zeros
0x30+LS 8 "@EACT" 0x00 0x00 0x00
0x38+LS 4 { 0, 0, 0, 1 }
0x3C+LS 4 length1 (filesize - 0x40 - LS)
0x40+LS 8 "EACT1" 0 0 0
0x48+LS 4 { 0, 0, 0, 0x14 }
0x4C+LS 4 length2 (filesize - 0x54 - LS)
0x50+LS 4 { 0xD4, 0, 0, 0x66 }
0x54+LS 4 LC; Line count
0x58+LS 4*LC LineDirectory (array of TLineDescriptor; see below)
0x58+LS+4*LC 4 { 0, 0, 0, 0 } (equal to length2 for G3E-files)
0x5C+LS+4*LC ... Line array; each line is zero-terminated and 4-aligned by random filler bytes

 

struct LineDirectory {
        unsigned int LineCount;
        TLineDescriptor LineDescriptor[LineCount];
};

typedef struct LineDescriptor {
        char EntryType;
        char EntryOffset[3]/* offset relative to
0x54+LS, big endian */
} TLineDescriptor;   
 


EACT/Text-conversion:


The setup-area should be based on a template, which has been derived from some valid G1E/G2E/G3E-file. Only such setup-enties should be changed, which are well known.

Build a G1E/G2E/G3E-file from pure text:
First calculate the filesize. Add the sizes of the constant parts: TStandardHeader, TEACTcommonHeader, TEACTsubHeader. The size of the setup-area depends on the EACT-filetype and on the amount of setup-entries, which values should be non-zero. The setup-data must end 4-aligned. Fill up with zeros in case of need. The setup-area has four zero bytes at the beginning and 16 zero bytes at the end. These must be included into the count LS stored at offset 0x24. The length of the LineDirectory is LC*4. The LineDirectory is terminated by four bytes (see offset
0x58+LS+4*LC). Finally each line needs at least space for the line itself and one terminatiing zero. Each line must end 4-aligned, hence add zero bytes in case of need.

After the filesize is properly calculated,  the StandardHeader can be set up. Hint: fx-CG OS 1.04 does not care for the bytes at offset 0x1C/0x1D of G3E-files.
Then EACTcommonHeader can be written. The size of the setup-area has to be known.
The setup-area has to be constructed as described or some convenient constant pattern could be used.
The most important data of the following intermediate block EACTsubHeader is the line count.
The first entry in the LineDirectory must be the heading (EntryType 0x07), though it is not used, when the file is read in by EACT. The heading is always derived from the filename.

 

The following code fragment contains a function EACT2TXT to demonstrate the conversion of an EACT-file to some text. The function TXT2EACT converts some textlines to an EACT-file. The snippet is a fragment. It cannot be compiled as it is.

 

#define G1E 0x00010100
#define G2E 0x00010200
#define G3E 0x00010400
#define OMIT_ZERO_SETUP_VALUES
#define MAX_SETUP_DIR_SIZE 0x2C
#define WRITE_THE_LINES	
#define SETUP_ANGLE 0x13
#define SETUP_ANGLE_DEG 0x00
#define SETUP_ANGLE_RAD 0x01
#define SETUP_ANGLE_GRA 0x02
#define SETUP_SHIFT_ALPHA 0x14
#define SETUP_SHIFT_ALPHA_OFF 0x00
#define SETUP_SHIFT_ALPHA_SHIFT 0x01
#define SETUP_SHIFT_ALPHA_ALPHA 0x04
#define SETUP_SHIFT_ALPHA_SHIFT_ALPHA 0x84
#define SETUP_INS_OVWR 0x15
#define SETUP_INS_OVWR_OVWR 0x01
#define SETUP_INS_OVWR_INS 0x02
#define SETUP_MODE 0x17
#define SETUP_MODE_COMP 0x00
#define SETUP_MODE_BIN 0x01
#define SETUP_MODE_OCT 0x07
#define SETUP_MODE_DEC 0x09
#define SETUP_MODE_HEX 0x0F
#define SETUP_FUNCTYPE 0x18
#define SETUP_FUNCTYPE_YEQ 0x00
#define SETUP_FUNCTYPE_REQ 0x01
#define SETUP_FUNCTYPE_PARAM 0x02
#define SETUP_FUNCTYPE_XC 0x03
#define SETUP_FUNCTYPE_YGT 0x04
#define SETUP_FUNCTYPE_YLT 0x05
#define SETUP_FUNCTYPE_YGE 0x06
#define SETUP_FUNCTYPE_YLE 0x07
#define SETUP_DRAWTYPE 0x19
#define SETUP_DRAWTYPE_CON 0x00
#define SETUP_DRAWTYPE_PLOT 0x01
#define SETUP_DERIVATIVE 0x1A
#define SETUP_DERIVATIVE_ON 0x00
#define SETUP_DERIVATIVE_OFF 0x01
#define SETUP_COORD 0x1B
#define SETUP_COORD_ON 0x00
#define SETUP_COORD_OFF 0x01
#define SETUP_GRID 0x1C
#define SETUP_GRID_ON 0x00
#define SETUP_GRID_OFF 0x01
#define SETUP_AXES 0x1D
#define SETUP_AXES_ON 0x00
#define SETUP_AXES_OFF 0x01
#define SETUP_LABEL 0x1E
#define SETUP_LABEL_ON 0x00
#define SETUP_LABEL_OFF 0x01
#define SETUP_STATWIND 0x20
#define SETUP_STATWIND_AUTO 0x00
#define SETUP_STATWIND_MANUAL 0x01
#define SETUP_GRAPHFUNC 0x21
#define SETUP_GRAPHFUNC_ON 0x00
#define SETUP_GRAPHFUNC_OFF 0x01
#define SETUP_DUALSCREEN 0x22
#define SETUP_DUALSCREEN_OFF 0x03
#define SETUP_SIMULFUNC 0x23
#define SETUP_SIMULFUNC_ON 0x00
#define SETUP_SIMULFUNC_OFF 0x01
#define SETUP_DYNAMICTYPE 0x24
#define SETUP_DYNAMICTYPE_CONT 0x00
#define SETUP_DYNAMICTYPE_STOP 0x01
#define SETUP_SIGMADISPLAY 0x25
#define SETUP_SIGMADISPLAY_ON 0x00
#define SETUP_SIGMADISPLAY_OFF 0x01
#define SETUP_SLOPE 0x26
#define SETUP_SLOPE_ON 0x00
#define SETUP_SLOPE_OFF 0x01
#define SETUP_PAYMENT 0x27
#define SETUP_PAYMENT_BGN 0x00
#define SETUP_PAYMENT_END 0x01
#define SETUP_DATEMODE 0x28
#define SETUP_DATEMODE_365 0x00
#define SETUP_DATEMODE_360 0x01
#define SETUP_ANSWERTYPE 0x29
#define SETUP_ANSWERTYPE_REAL 0x00
#define SETUP_ANSWERTYPE_COMPLEX 0x01
#define SETUP_COMPLEXMODE 0x2A
#define SETUP_COMPLEXMODE_REAL 0x00
#define SETUP_COMPLEXMODE_APBI 0x01
#define SETUP_COMPLEXMODE_RLTT 0x02
#define SETUP_DISPLAY 0x2B
#define SETUP_DISPLAY_NORM1 0x00
#define SETUP_DISPLAY_NORM2 0x10
#define SETUP_DISPLAY_FIX0 0x20
#define SETUP_DISPLAY_FIX1 0x21
#define SETUP_DISPLAY_FIX2 0x22
#define SETUP_DISPLAY_FIX3 0x23
#define SETUP_DISPLAY_FIX4 0x24
#define SETUP_DISPLAY_FIX5 0x25
#define SETUP_DISPLAY_FIX6 0x26
#define SETUP_DISPLAY_FIX7 0x27
#define SETUP_DISPLAY_FIX8 0x28
#define SETUP_DISPLAY_FIX9 0x29
#define SETUP_DISPLAY_SCI0 0x30
#define SETUP_DISPLAY_SCI1 0x31
#define SETUP_DISPLAY_SCI2 0x32
#define SETUP_DISPLAY_SCI3 0x33
#define SETUP_DISPLAY_SCI4 0x34
#define SETUP_DISPLAY_SCI5 0x35
#define SETUP_DISPLAY_SCI6 0x36
#define SETUP_DISPLAY_SCI7 0x37
#define SETUP_DISPLAY_SCI8 0x38
#define SETUP_DISPLAY_SCI9 0x39
#define SETUP_DISPLAY_TOGGLE_E_MODE 0x80
#define SETUP_BACKGROUND 0x2C
#define SETUP_BACKGROUND_NONE 0x00
#define SETUP_BACKGROUND_PICT01 0x01
#define SETUP_BACKGROUND_PICT02 0x02
#define SETUP_BACKGROUND_PICT03 0x03
#define SETUP_BACKGROUND_PICT04 0x04
#define SETUP_BACKGROUND_PICT05 0x05
#define SETUP_BACKGROUND_PICT06 0x06
#define SETUP_BACKGROUND_PICT07 0x07
#define SETUP_BACKGROUND_PICT08 0x08
#define SETUP_BACKGROUND_PICT09 0x09
#define SETUP_BACKGROUND_PICT10 0x0A
#define SETUP_BACKGROUND_PICT11 0x0B
#define SETUP_BACKGROUND_PICT12 0x0C
#define SETUP_BACKGROUND_PICT13 0x0D
#define SETUP_BACKGROUND_PICT14 0x0E
#define SETUP_BACKGROUND_PICT15 0x0F
#define SETUP_BACKGROUND_PICT16 0x10
#define SETUP_BACKGROUND_PICT17 0x11
#define SETUP_BACKGROUND_PICT18 0x12
#define SETUP_BACKGROUND_PICT19 0x13
#define SETUP_BACKGROUND_PICT20 0x14
#define SETUP_RESIDLIST 0x2D
#define SETUP_RESIDLIST_NONE 0x00
#define SETUP_RESIDLIST_LIST01 0x01
#define SETUP_RESIDLIST_LIST02 0x02
#define SETUP_RESIDLIST_LIST03 0x03
#define SETUP_RESIDLIST_LIST04 0x04
#define SETUP_RESIDLIST_LIST05 0x05
#define SETUP_RESIDLIST_LIST06 0x06
#define SETUP_RESIDLIST_LIST07 0x07
#define SETUP_RESIDLIST_LIST08 0x08
#define SETUP_RESIDLIST_LIST09 0x09
#define SETUP_RESIDLIST_LIST10 0x0A
#define SETUP_RESIDLIST_LIST11 0x0B
#define SETUP_RESIDLIST_LIST12 0x0C
#define SETUP_RESIDLIST_LIST13 0x0D
#define SETUP_RESIDLIST_LIST14 0x0E
#define SETUP_RESIDLIST_LIST15 0x0F
#define SETUP_RESIDLIST_LIST16 0x10
#define SETUP_RESIDLIST_LIST17 0x11
#define SETUP_RESIDLIST_LIST18 0x12
#define SETUP_RESIDLIST_LIST19 0x13
#define SETUP_RESIDLIST_LIST20 0x14
#define SETUP_RESIDLIST_LIST21 0x15
#define SETUP_RESIDLIST_LIST22 0x16
#define SETUP_RESIDLIST_LIST23 0x17
#define SETUP_RESIDLIST_LIST24 0x18
#define SETUP_RESIDLIST_LIST25 0x19
#define SETUP_RESIDLIST_LIST26 0x1A
#define SETUP_LISTFILE 0x2E
#define SETUP_LISTFILE_FILE01 0x01
#define SETUP_LISTFILE_FILE02 0x02
#define SETUP_LISTFILE_FILE03 0x03
#define SETUP_LISTFILE_FILE04 0x04
#define SETUP_LISTFILE_FILE05 0x05
#define SETUP_LISTFILE_FILE06 0x06
#define SETUP_VARIABLE 0x2F
#define SETUP_VARIABLE_RANGE 0x00
#define SETUP_VARIABLE_LIST01 0x01
#define SETUP_VARIABLE_LIST02 0x02
#define SETUP_VARIABLE_LIST03 0x03
#define SETUP_VARIABLE_LIST04 0x04
#define SETUP_VARIABLE_LIST05 0x05
#define SETUP_VARIABLE_LIST06 0x06
#define SETUP_VARIABLE_LIST07 0x07
#define SETUP_VARIABLE_LIST08 0x08
#define SETUP_VARIABLE_LIST09 0x09
#define SETUP_VARIABLE_LIST10 0x0A
#define SETUP_VARIABLE_LIST11 0x0B
#define SETUP_VARIABLE_LIST12 0x0C
#define SETUP_VARIABLE_LIST13 0x0D
#define SETUP_VARIABLE_LIST14 0x0E
#define SETUP_VARIABLE_LIST15 0x0F
#define SETUP_VARIABLE_LIST16 0x10
#define SETUP_VARIABLE_LIST17 0x11
#define SETUP_VARIABLE_LIST18 0x12
#define SETUP_VARIABLE_LIST19 0x13
#define SETUP_VARIABLE_LIST20 0x14
#define SETUP_VARIABLE_LIST21 0x15
#define SETUP_VARIABLE_LIST22 0x16
#define SETUP_VARIABLE_LIST23 0x17
#define SETUP_VARIABLE_LIST24 0x18
#define SETUP_VARIABLE_LIST25 0x19
#define SETUP_VARIABLE_LIST26 0x1A
#define SETUP_RECURDUAL 0x31
#define SETUP_RECURDUAL_TPG 0x00
#define SETUP_RECURDUAL_OFF 0x01
#define SETUP_AUTOCALC 0x4E
#define SETUP_AUTOCALC_ON 0x00
#define SETUP_AUTOCALC_OFF 0x01
#define SETUP_SHOWCELL 0x4F
#define SETUP_SHOWCELL_FORMULA 0x00
#define SETUP_SHOWCELL_VALUE 0x01
#define SETUP_MOVE 0x50
#define SETUP_MOVE_LOWER 0x00
#define SETUP_MOVE_RIGHT 0x01
#define SETUP_SUBNAME 0x51
#define SETUP_SUBNAME_ON 0x00
#define SETUP_SUBNAME_OFF 0x01
#define SETUP_INPUTMODE 0x53
#define SETUP_INPUTMODE_MATH 0x00
#define SETUP_INPUTMODE_LINEAR 0x01
#define SETUP_LOCUS 0x54
#define SETUP_LOCUS_ON 0x00
#define SETUP_LOCUS_OFF 0x01
#define SETUP_DRAWSPEED 0x55
#define SETUP_DRAWSPEED_NORM 0x00
#define SETUP_DRAWSPEED_HIGH 0x01
#define SETUP_SKETCHLINE 0x56
#define SETUP_SKETCHLINE_NORM 0x00
#define SETUP_SKETCHLINE_THICK 0x01
#define SETUP_SKETCHLINE_BROKEN 0x02
#define SETUP_SKETCHLINE_DOT 0x03
#define SETUP_FRACRESULT 0x57
#define SETUP_FRACRESULT_DC 0x00
#define SETUP_FRACRESULT_ABC 0x01
#define SETUP_SIMPLIFY 0x5F
#define SETUP_SIMPLIFY_AUTO 0x00
#define SETUP_SIMPLIFY_MANUAL 0x01
#define SETUP_EOL 0xFF
typedef struct {
	unsigned char Id;
	unsigned char Value;
} TSetupEntry;
const TSetupEntry SetupTemplate[] = 
	{ 
		{ SETUP_ANGLE, SETUP_ANGLE_GRA }
		,{ SETUP_INS_OVWR, SETUP_INS_OVWR_INS }
		,{ SETUP_DERIVATIVE, SETUP_DERIVATIVE_OFF }
		,{ SETUP_GRID, SETUP_GRID_OFF }
		,{ SETUP_LABEL, SETUP_LABEL_OFF }
		,{ SETUP_DUALSCREEN, SETUP_DUALSCREEN_OFF }
		,{ SETUP_SIMULFUNC, SETUP_SIMULFUNC_OFF }
		,{ SETUP_DYNAMICTYPE, SETUP_DYNAMICTYPE_STOP }
		,{ SETUP_SIGMADISPLAY, SETUP_SIGMADISPLAY_OFF }
		,{ SETUP_SLOPE, SETUP_SLOPE_OFF }
		,{ SETUP_PAYMENT, SETUP_PAYMENT_END }
		,{ SETUP_LISTFILE, SETUP_LISTFILE_FILE01 }
		,{ 0x30, 0x01 }
		,{ 0x31, 0x01 }
		,{ 0x52, 0x01 }
		,{ 0x54, 0x01 }
		,{ 0x5A, 0x01 }
		,{ 0x5B, 0x01 }
		,{ SETUP_EOL, 0 }
	};
typedef struct { 
	unsigned char USBPower[8];
	unsigned char Type;
	unsigned char Filler1[5];
	unsigned char ControlByte1;
	unsigned char One1;
	unsigned int filesize;
	unsigned char ControlByte2;
	unsigned char Filler2[11];
} TStandardHeader;
typedef struct { 
	unsigned int filesize;
	unsigned int setup_area_size;
	unsigned int version[2];
} TEACTcommonHeader;
typedef struct { 
	unsigned char AT_EACT[8];
	unsigned int one;
	unsigned int length1;
	unsigned char EACT1[8];
	unsigned int onefour;
	unsigned int length2;
	unsigned int D4000066;
	unsigned int line_count;
} TEACTsubHeader;
typedef union{
	unsigned int Entry;
	struct {
        unsigned char EntryType;
        unsigned char EntryOffset[3];  /* offset relative to 0x54+LS, big endian */
	};
} TLineDescriptor;    
typedef TLineDescriptor* PLineDescriptor;
//
void TwoAlign( char*s, char*sFiller ){
	if ( strlen( s ) & 1 ) strcat( s, sFiller );
}
//
void writeln( int h, char*s ){
	TwoAlign( s, " " );
	strcat( (char*)s, "\x00D\x00A" );
	Bfile_WriteFile_OS( h, s, strlen( s ) );
}
//
unsigned int EACT2TXT( void ){
int result = -1;
int readresult = -1;
unsigned short in_name[ FILENAMESIZE ];
unsigned short out_name[ FILENAMESIZE ];
unsigned char textfilename[ FILENAMESIZE ];
int handle, hTXT;
unsigned int key;
unsigned char x[21];
unsigned char y[21];
TStandardHeader StandardHeader;
int i, j, jMax;
TEACTcommonHeader EACTcommonHeader;
int setup_dir_size;
int required_setup_size, required_size;
unsigned char setup_directory[ MAX_SETUP_DIR_SIZE ];
unsigned char setup_data[ MAX_SETUP_DIR_SIZE*8 ];
unsigned char bitroll, ibit, ibits, isetup_entry;
unsigned int line_count;
unsigned int iwork, offset_of_line_count, inext;
PLineDescriptor LineDirectory;
unsigned int start_of_line, required_line_size;
char*line;
char*line_out;
TSMemView smv;
	smv.SetFlags( FLAG_EXIT_ON_EXE | smv.GetFlags() );
	smv.SetFilter( "*.g?e" );
	smv.AutoSelectPattern();
	if ( smv.browse() != lvmKEY +  KEY_CTRL_EXE ) return 1;
	
//	MessageDlg( (void*)smv.SelectedFullname, mtInformation, 6 );
	
	memset( textfilename, 0, sizeof( textfilename ) );
	strcpy( (char*)textfilename, smv.SelectedFullname );
	i = strlen( (char*)textfilename );
	while ( i > 0 ){
		if ( textfilename[ i ] == '.' ) break;
		textfilename[ i-- ] = 0;
	}
	strcat( (char*)textfilename, "TXT" );
//	MessageDlg( (void*)textfilename, mtInformation, 6 );
	LineDirectory = 0;
	line = 0;
	line_out = 0;
	handle = -1;
	hTXT = -1;
	while ( 1 ){
	// open EACT-file
//		Bfile_StrToName_ncpy( in_name, "\\\\fls0\\EACTTST2.g2e", FILENAMESIZE );
//		Bfile_StrToName_ncpy( in_name, "\\\\fls0\\EAEXMPL.g1e", FILENAMESIZE );
		Bfile_StrToName_ncpy( in_name, (unsigned char*)smv.SelectedFullname, FILENAMESIZE );
		handle = Bfile_OpenFile_OS( in_name, 3 );
		if ( handle < 0 ){ 
			result = 0x80000001;
			break;
		}
		
// read StandardHeader and check readresult
		readresult = Bfile_ReadFile_OS( handle, (void*)&StandardHeader, sizeof( TStandardHeader ), 0 );
		if ( readresult != sizeof( TStandardHeader ) ){
			result = 0x80010001;
			break;
		}
		// invert the standard header
		InvertMem( (char*)&StandardHeader, sizeof( StandardHeader ) );
// check controlbyte1		
		if ( ( ( StandardHeader.filesize + 0x41 ) & 0xFF ) != StandardHeader.ControlByte1 ){
			result = 0x80010002;
			break;
		}
// check controlbyte2
		if ( ( ( StandardHeader.filesize + 0xB8 ) & 0xFF ) != StandardHeader.ControlByte2 ){
			result = 0x80010003;
			break;
		}
// read the common EACT-header and check readresult
		readresult = Bfile_ReadFile_OS( handle, (void*)&EACTcommonHeader, sizeof( TEACTcommonHeader ), -1 );
		if ( readresult != sizeof( TEACTcommonHeader ) ){
			result = 0x80020001;
			break;
		}
// check for consistency		
		if ( EACTcommonHeader.filesize != StandardHeader.filesize ){
			result = 0x80020002;
			break;
		}
// now decide, which type of EACT-file has been read.		
		if ( EACTcommonHeader.version[0] == G1E ) setup_dir_size = 0x10;
		else if ( EACTcommonHeader.version[0] == G2E ) setup_dir_size = 0x10;
		else if ( EACTcommonHeader.version[0] == G3E ) setup_dir_size = 0x2C;
		else{
			result = 0x80020003;
			setup_dir_size = EACTcommonHeader.version[0];
			break;
		}
		
		readresult = Bfile_ReadFile_OS( handle, (void*)setup_directory, 4, -1 );	// kill the four trailing zero bytes
		readresult = Bfile_ReadFile_OS( handle, (void*)setup_directory, (int)setup_dir_size, -1 );
		if ( readresult != setup_dir_size ){
			result = 0x80020004;
			break;
		}
// calculate number of non-zero setup-entries
		ibits = 0;
		for ( i = 0; i < setup_dir_size; i++ ){
			bitroll = setup_directory[ i ];
			for ( ibit = 0; ibit < 8; ibit++ ){
				if ( bitroll & 0x80  ){
					ibits++;
				}
				bitroll<<=1;
			}
		}
// read the setup-data
		required_setup_size = ( ibits + 3 ) & 0xFFFFFFFC;	// 4-aligned
		readresult = Bfile_ReadFile_OS( handle, (void*)&setup_data, required_setup_size, -1 );
		if ( readresult != required_setup_size ){
			result = 0x80020005;
			break;
		}
// read the count of EACT-lines
		offset_of_line_count = 0x54+EACTcommonHeader.setup_area_size;
		readresult = Bfile_ReadFile_OS( handle, (void*)&line_count, sizeof( line_count ), offset_of_line_count );
		if ( readresult != sizeof( line_count ) ){
			result = 0x80020006;
			break;
		}
// allocate memory for the LineDirectory		
		LineDirectory = (PLineDescriptor)malloc( sizeof( TLineDescriptor ) * line_count );
// read the LineDirectory
		readresult = Bfile_ReadFile_OS( handle, (void*)LineDirectory, sizeof( TLineDescriptor ) * line_count, -1 );
		if ( readresult != ( sizeof( TLineDescriptor ) * line_count ) ){
			result = 0x80020007;
			break;
		}
		
		required_line_size = 0;
#ifdef WRITE_THE_LINES	
// calculate the size of the lines
		for ( i = 0; i < line_count; i++ ){
			start_of_line = offset_of_line_count + ( LineDirectory[ i ].Entry & 0x00FFFFFF );
			if ( i < ( line_count - 1 ) ) 
			  inext =  offset_of_line_count + ( LineDirectory[ i + 1 ].Entry & 0x00FFFFFF );
			else 
			  inext =  StandardHeader.filesize;
			jMax = inext - start_of_line;
			switch ( LineDirectory[ i ].EntryType ){
				case 0x03 :
					line = (char*)malloc( jMax ); 
					readresult = Bfile_ReadFile_OS( handle, line, jMax, start_of_line );
					required_line_size += strlen( ( line + 8 ) );
					break;
				case 0x07 :
				case 0x81 :
					line = (char*)malloc( jMax ); 
					readresult = Bfile_ReadFile_OS( handle, line, jMax, start_of_line );
					required_line_size += strlen( line );
					break;
				default :
					required_line_size += jMax * 3;
					break;
			}
			required_line_size += 2;	// CRLF
			required_line_size = ( required_line_size + 1 ) & 0xFFFFFFFE;	// 2-align
			free( line );
			line = 0;
		}
#endif
		
		
// prepare the textfile
#ifdef OMIT_ZERO_SETUP_VALUES
		required_size = ibits*8;
#else
		required_size = setup_dir_size*8*8;
#endif		
		required_size += 10;	// for the line count (); 8 bytes for the hex-representation and two for 0D0A
		required_size += 14*line_count;
		
		required_size += required_line_size;
// 2-alignment		
		required_size += 1;
		required_size &= 0xFFFFFFFE;
		
// create the textfile
		Bfile_StrToName_ncpy( out_name, textfilename, FILENAMESIZE );
#ifdef fxCG
		Bfile_DeleteEntry( out_name );
#else		
		Bfile_DeleteEntry( out_name, 0 );
#endif		
		result = Bfile_CreateEntry_OS( out_name, 1, &required_size );
		if ( result == 0 ){
			hTXT = Bfile_OpenFile_OS( out_name, 3 );
			if ( hTXT < 0 ){ 
				result = 0x80030001;
				break;
			}
		}else{
			result = 0x80030002;
			break;
		}
		
// write the setup-informmation to the textfile		
		ibits = 0;
		isetup_entry = 0;
		memset( y, 0, sizeof( y ) );
		for ( i = 0; i < setup_dir_size; i++ ){
			bitroll = setup_directory[ i ];
			for ( ibit = 0; ibit < 8; ibit++ ){
				memset( x, 0, sizeof( x ) );
				ByteToHex( isetup_entry, (unsigned char*)x );  
				strcat( (char*)x, "=" );
				
				if ( bitroll & 0x80  ){
					ByteToHex( setup_data[ ibits ], (unsigned char*)y );  
					strcat( (char*)x, (char*)y );
					ibits++;
				}else{
					strcat( (char*)x, "00" );
				}
#ifdef OMIT_ZERO_SETUP_VALUES
				if ( bitroll & 0x80  )
#endif
				writeln( hTXT, (char*)x );
				
				bitroll<<=1;
				isetup_entry++;
			}
		}
// write the line-count to the textfile		
		memset( x, 0, sizeof( x ) );
		IntToHex( line_count, (unsigned char*)x );  
		writeln( hTXT, (char*)x );
		
// write the LineDirectory to the textfile		
		memset( y, 0, sizeof( y ) );
		for ( i = 0; i < line_count; i++ ){
			memset( x, 0, sizeof( x ) );
			ByteToHex( LineDirectory[ i ].EntryType, (unsigned char*)x );  
			strcat( (char*)x, ": " );
			
			iwork = LineDirectory[ i ].Entry & 0x00FFFFFF;
			
			iwork += offset_of_line_count;
			IntToHex( iwork, (unsigned char*)y );  
			strcat( (char*)x, (char*)y );
			
			writeln( hTXT, (char*)x );
		}
		
		break;
	}
	
#ifdef WRITE_THE_LINES	
// write the lines
		memset( x, 0, sizeof( x ) );
		for ( i = 0; i < line_count; i++ ){
			start_of_line = offset_of_line_count + ( LineDirectory[ i ].Entry & 0x00FFFFFF );
			if ( i < ( line_count - 1 ) )
				inext =  offset_of_line_count + ( LineDirectory[ i + 1 ].Entry & 0x00FFFFFF );
			else
				inext =  StandardHeader.filesize;
			jMax = inext - start_of_line;
			line = (char*)malloc( jMax + 4 ); 
			readresult = Bfile_ReadFile_OS( handle, line, jMax, start_of_line );
			switch ( LineDirectory[ i ].EntryType ){
				case 0x03 :
					writeln( hTXT, line+8 );
					break;
				case 0x07 :
				case 0x81 :
					writeln( hTXT, line );
					break;
				default :
					line_out = (char*)malloc( jMax * 3 + 2 ); 
					memset( line_out, 0, jMax * 3 );
					for ( j = 0; j < jMax; j++ ){
						ByteToHex( line[ j ], (unsigned char*)x );  
						strcat( line_out, (char*)x );
						strcat( line_out, " " );
					}
					writeln( hTXT, line_out );
					break;
			}
			free( line );
			line = 0;
			free( line_out );
			line_out = 0;
		}
#endif		
	
	
// close TXT-file
	if ( hTXT >= 0 ){
		result = Bfile_CloseFile_OS( hTXT );
	}else result = 0x80040001;
// close EACT-file
	if ( handle >= 0 ){
		result = Bfile_CloseFile_OS( handle );
	}else result = 0x80040002 ;
		
	free( LineDirectory );
// display some results	for diagnostics during development
	Bdisp_AllClr_VRAM();
	
	locate(1,1);  
	IntToHex( result, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	locate(1,2);  
	IntToHex( handle, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	
	locate(1,3);  
	IntToHex( required_setup_size, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	locate(1,4);  
	IntToHex( setup_dir_size, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	
	locate(1,5);  
	IntToHex( StandardHeader.filesize, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	
	locate(1,6);  
	IntToHex( required_size, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	locate(1,7);  
	IntToHex( line_count, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	
	locate(1,8);  
//	IntToHex( EACTcommonHeader.setup_area_size, (unsigned char*)x );  
//	IntToHex( iwork, (unsigned char*)x );  
	IntToHex( offset_of_line_count, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
//	Print( (unsigned char*)smv.SelectedFullname );
	
	GetKey( &key );
	return result;
}
// specify test scheme for TXT2EACT
#define EACT_TYPE G1E
#define EACT_FILENAME "\\\\fls0\\EACTNEW1."
// test lines as stringlist
const unsigned char Lines[] = "x\x00D\x00A\x000"
							  "first line\x00D\x00A\x000"	
							  "second line\x00D\x00A\x000"	
							  "\x00D\x00A\x000"	
							  "fourth line\x00D\x00A\x000"	
							  "1\x00D\x00A\x000"	
							  "12\x00D\x00A\x000"	
							  "123\x00D\x00A\x000"	
							  "1234\x00D\x00A\x000"	
							  "12345\x00D\x00A\x000"	
							  "123456\x00D\x00A\x000"	
							  "1234567\x00D\x00A\x000"	
							  "12345678\x00D\x00A\x000"	
							  "last line\x00D\x00A\x000"	
;
// the heading is not heeded for by the OS. It is always constructed based on the filename.
// size of CRLF (0x0D0A), which is used as input line delimiter in this case
#define SIZE_OF_TEXTLINE_DELIMITER 2
//
int TXT2EACT( void ){
unsigned short in_name[ FILENAMESIZE ];
unsigned short out_name[ FILENAMESIZE ];
unsigned char work[ FILENAMESIZE ];
int setup_dir_size, setup_data_size;
int required_setup_size, required_size, required_lines_size, required_line_size;
int i, j, k, ibits;
unsigned char setup_directory[ MAX_SETUP_DIR_SIZE ];
unsigned char setup_data[ MAX_SETUP_DIR_SIZE*8+16 ];	// +16 because of the 16 finalizing zero bytes
TStandardHeader StandardHeader;
TEACTcommonHeader EACTcommonHeader;
TEACTsubHeader EACTsubHeader;
unsigned int filesize;
unsigned int line_count;
TStringList sl;
int handle = -1;
int ioresult;
unsigned int line_offset;
TLineDescriptor LineDescriptor;
unsigned char*workline;
unsigned char x[21];
unsigned int key;
	workline = 0;
//---------------------------		
// the StringList is used for convenience during development only; normally a textfile would be used as input
	sl.Assign( (char*)Lines );
	sl.GoEndOfList();
	line_count = sl.LineNo() + 1;
//---------------------------		
// now calculate the required size for all lines
	required_lines_size = 0;
// goto begin of text-input (the first line is the EACT-heading)	
	sl.GoBeginOfList();
	while ( 1 ){
		// calculate the required space for the current line
		required_line_size = sl.StringLength();	// length of the current text-line
		required_line_size++;	// add one for the terminating zero
		required_line_size -= SIZE_OF_TEXTLINE_DELIMITER;
		required_line_size = ( required_line_size + 3 ) & 0xFFFFFFFC;	// 4-align
		
		required_lines_size += required_line_size;
		if ( !sl.NextLine() ) break;	// break, if end of text
	}
//---------------------------		
// build up the EACT-filename	
	memset( work, 0, sizeof( work ) );	// initialize
	strcpy( (char*)work, EACT_FILENAME );	// copy the basefilename
	EACTcommonHeader.version[0] = EACT_TYPE;	// this is important!
//	EACTcommonHeader.version[0] = 0;			// this leads to failure
	switch ( EACT_TYPE ){
		case G1E :
			strcat( (char*)work, "g1e" );	// append the extension to filename
			setup_dir_size = 0x10;
			EACTcommonHeader.version[1] = 0x5061636B;	// written on save on fx-9860 OS 1.XX
//			EACTcommonHeader.version[1] = 0x00000000;	// the OS does not mind while reading
			break;
		case G2E :
			strcat( (char*)work, "g2e" );	// append the extension to filename
			setup_dir_size = 0x10;
			EACTcommonHeader.version[1] = 0x02020201;	// the version of the OS while writing (fx-9860 OS 2.XX)
//			EACTcommonHeader.version[1] = 0x00000000;	// the OS does not mind while reading
			break;
		case G3E :
			strcat( (char*)work, "g3e" );	// append the extension to filename
			setup_dir_size = 0x2C;
			EACTcommonHeader.version[1] = 0x01040200;
			break;
	};
	// convert an unsigned char filename to unsigned short
	Bfile_StrToName_ncpy( out_name, work, FILENAMESIZE );
	
//---------------------------		
// calculate the setup sizes
	memset( setup_directory, 0, sizeof( setup_directory ) );	// initialize with zeros
	memset( setup_data, 0, sizeof( setup_data ) );				// initialize with zeros
	k = 0;	// index to SetupTemplate
	ibits = 0;
	for ( i = 0; i < setup_dir_size; i++ ){
		for ( j = 0; j < 8; j++ ){
			if ( SetupTemplate[ k ].Id == SETUP_EOL ) break;
			if ( SetupTemplate[ k ].Id == i*8+j ){
				if ( SetupTemplate[ k ].Value ){	// only the entries with non-zero-values are heeded for
					setup_directory[ i ] |= ( 0x80 >> j );	// set the corresponding bit
					setup_data[ ibits ] = SetupTemplate[ k ].Value;  // stor the next non-zero value to the setup_data-array
					ibits++;
				}
				// next SetupTemplate-item
				k++;
			}
		}
		if ( SetupTemplate[ k ].Id == SETUP_EOL ) break;
	}
	// ibits contains the count of non-zero setup-values now
	setup_data_size = ( ( ibits + 3 ) & 0xFFFFFFFC );	// 4-align
	required_setup_size = setup_dir_size + setup_data_size;
	required_setup_size += 4;	// starting zeros at offset 0x30
	required_setup_size += 16;  // trailing zeros at offset ( 0x20 + setup_area_size )
	
//---------------------------		
// calculate the required filesize
	filesize = sizeof( TStandardHeader );
	filesize += sizeof( TEACTcommonHeader );
	filesize += required_setup_size;
	filesize += sizeof( TEACTsubHeader );
	filesize += line_count*4;	// LineDirectory
	filesize += 4;	// LineDirectory finalizing four bytes (all zeros with G1E/G2E; filesize - 0x54 - required_setup_size with G3E )
	filesize += required_lines_size;	// space required for the LineArray
	
	// set up standard header
	memcpy( StandardHeader.USBPower, "USBPower", 8 );
	StandardHeader.Type = 0x49;
	memset( StandardHeader.Filler1, 0, sizeof( StandardHeader.Filler1 ) );
	StandardHeader.ControlByte1 = ( filesize + 0x41 ) & 0xFF;
	StandardHeader.One1 = 1;
	StandardHeader.filesize = filesize;
	StandardHeader.ControlByte2 = ( filesize + 0xB8 ) & 0xFF;
	memset( StandardHeader.Filler2, 0, sizeof( StandardHeader.Filler2 ) );
	// invert the standard header
	InvertMem( (char*)&StandardHeader, sizeof( StandardHeader ) );
	
	// set up EACTcommonHeader header
	EACTcommonHeader.filesize = filesize;
	EACTcommonHeader.setup_area_size = required_setup_size;
	memset( &EACTsubHeader, 0, sizeof( EACTsubHeader ) );
	memcpy( EACTsubHeader.AT_EACT, "@EACT\x000\x000\x000", sizeof( EACTsubHeader.AT_EACT ) );  // mandatory
	EACTsubHeader.one = 0x00000001;  // mandatory
	EACTsubHeader.length1 = filesize - 0x40 - required_setup_size;
	memcpy( EACTsubHeader.EACT1, "EACT1\x000\x000\x000", sizeof( EACTsubHeader.EACT1 ) );
	EACTsubHeader.onefour = 0x00000014;
	EACTsubHeader.length2 = filesize - 0x54 - required_setup_size;
	EACTsubHeader.D4000066 = 0xD4000066;
	EACTsubHeader.line_count = line_count;
//---------------------------		
// delete EACT-file
#ifdef fxCG
	ioresult = Bfile_DeleteEntry( out_name );
#else		
	ioresult = Bfile_DeleteEntry( out_name, 0 );
#endif		
//---------------------------		
// create and open EACT-file
	required_size = filesize;
	ioresult = Bfile_CreateEntry_OS( out_name, 1, &required_size );
	if ( ioresult == 0 ){
		handle = Bfile_OpenFile_OS( out_name, 3 );
		if ( handle >= 0 ){ 
//---------------------------		
// write the StandardHeader
			ioresult = Bfile_WriteFile_OS( handle, &StandardHeader, sizeof( TStandardHeader ) );
//---------------------------		
// write the EACTcommonHeader
			ioresult = Bfile_WriteFile_OS( handle, &EACTcommonHeader, sizeof( TEACTcommonHeader ) );
//---------------------------		
// write the setup-area
			k = 0;
			ioresult = Bfile_WriteFile_OS( handle, &k, sizeof( k ) );
			ioresult = Bfile_WriteFile_OS( handle, &setup_directory, setup_dir_size );
			ioresult = Bfile_WriteFile_OS( handle, &setup_data, setup_data_size+16 );	// +16 because of the 16 finalizing zero bytes
//---------------------------		
// write the EACTsubHeader
			ioresult = Bfile_WriteFile_OS( handle, &EACTsubHeader, sizeof( TEACTsubHeader ) );
		
// process the lines
// each TEXT line gives one EACT-line (type 0x81)
//---------------------------		
// first the LineDirectory
			line_offset = ( line_count + 2 ) * 4;
			sl.GoBeginOfList();	// go to the start of text-input
			for ( i = 0; i < line_count; i++ ){
				LineDescriptor.Entry = line_offset;
				if ( i ) LineDescriptor.EntryType = 0x81; // normal line
				else LineDescriptor.EntryType = 0x07; // header-line
				// now write the LineDescriptor
				ioresult = Bfile_WriteFile_OS( handle, &LineDescriptor, sizeof( TLineDescriptor ) );
			
				required_line_size = sl.StringLength();
				required_line_size++;	// add one for the terminating zero
				required_line_size -= SIZE_OF_TEXTLINE_DELIMITER;
				required_line_size = ( required_line_size + 3 ) & 0xFFFFFFFC;	// 4-align
				line_offset += required_line_size;
				sl.NextLine();
			}
//---------------------------		
// write LineDirectory finalizing item.			
			switch ( EACT_TYPE ){
				case G1E :
				case G2E :
					k = 0;
					break;
				case G3E :
					k = EACTsubHeader.length2;
					break;
			}
			ioresult = Bfile_WriteFile_OS( handle, &k, 4 );
			
//---------------------------		
// write the lines			
			sl.GoBeginOfList();	// go to the start of text-input again
			for ( i = 0; i < line_count; i++ ){
				// calculate the required space for the current line
				required_line_size = sl.StringLength();
				required_line_size -= SIZE_OF_TEXTLINE_DELIMITER;
				k = required_line_size;	// remember the count to be copied to workline
				required_line_size++;	// add one for the terminating zero
				required_line_size = ( required_line_size + 3 ) & 0xFFFFFFFC;	// 4-align
				
				workline = (unsigned char*)malloc( required_line_size );	// get some heap
				memset( workline, 0, required_line_size );	// initialize the allocated memory with zeros
				memcpy( workline, sl.Line(), k );	// this truncates the trailing TEXTLINE_DELIMITER
				
				ioresult = Bfile_WriteFile_OS( handle, workline, required_line_size );
				
				free( workline );
				
				sl.NextLine();
			}
		}
	}
//---------------------------		
// close EACT-file
	if ( handle >= 0 ){
		ioresult = Bfile_CloseFile_OS( handle );
	}
	
// display some results	for diagnostics during development
	Bdisp_AllClr_VRAM();
	
	locate(1,1);  
	IntToHex( ioresult, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	locate(1,2);  
	IntToHex( handle, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	
	locate(1,3);  
	IntToHex( required_lines_size, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	locate(1,4);  
	IntToHex( ibits, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	
	locate(1,5);  
	IntToHex( filesize, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	
	locate(1,6);  
	IntToHex( line_count, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	locate(1,7);  
	IntToHex( 0, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	
	locate(1,8);  
	IntToHex( 0, (unsigned char*)x );  
	Print( (unsigned char*)x ); 
	
	GetKey( &key );
	
	
	return 1;
}

 

 

(06.10.2012 09:21:42)