diff options
author | B. Watson <urchlay@slackware.uk> | 2024-05-16 01:43:09 -0400 |
---|---|---|
committer | B. Watson <urchlay@slackware.uk> | 2024-05-16 01:43:09 -0400 |
commit | a4cc3ad3504d634e379369862c9f9fd8eed379f3 (patch) | |
tree | 7b6f55c352a4ca62dddaa1b4a6854799111d2d2f /jindroush/chkbas/chkbas.cpp | |
parent | b33c25d1363110e6e4a714530f460b0ff951f56b (diff) | |
download | bw-atari8-tools-a4cc3ad3504d634e379369862c9f9fd8eed379f3.tar.gz |
Add Jindrich Kubec's tools.
Diffstat (limited to 'jindroush/chkbas/chkbas.cpp')
-rw-r--r-- | jindroush/chkbas/chkbas.cpp | 1009 |
1 files changed, 1009 insertions, 0 deletions
diff --git a/jindroush/chkbas/chkbas.cpp b/jindroush/chkbas/chkbas.cpp new file mode 100644 index 0000000..a1ad505 --- /dev/null +++ b/jindroush/chkbas/chkbas.cpp @@ -0,0 +1,1009 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "jintypes.h" +#include <unistd.h> +#include <fcntl.h> +#include <math.h> +#include <string.h> +#include "carray.h" +#include "cfile.h" + +#include "pub.def" + +#include "basic.h" +#include "basic_tb.h" +#include "basic_xl.h" +#include "basic_xe.h" + +extern void strlwr(char *); + +typedef enum +{ + BASIC = 0, //standard basic + BASIC_TB = 1, //Turbo Basic + BASIC_XL = 2, //OSS Basic XL + BASIC_XE = 3, //OSS Basic XE + BASIC_XEX = 4 //OSS Basic XE in extended mode +} BASIC_TYPE; + +typedef struct +{ + char** ppCommands; //array of commands + char** ppOperands; //array of operands + + int iCmdNum; //number of commands + int iOpNum; //number of operands + int iOpFirst; //first operand +} LANGDESC; + +LANGDESC langtbl[] = +{ + { aCmdsBasic, aOpsBasic, BASIC_CMD_NUM, BASIC_OPS_NUM, 0x0E }, + { aCmdsTBasic, aOpsTBasic, TBASIC_CMD_NUM, TBASIC_OPS_NUM, 0x0D }, + { aCmdsBasicXl, aOpsBasicXl, BASICXL_CMD_NUM, BASICXL_OPS_NUM, 0x0D }, + { aCmdsBasicXe, aOpsBasicXe, BASICXE_CMD_NUM, BASICXE_OPS_NUM, 0x0D }, + { aCmdsBasicXe, aOpsBasicXe, BASICXE_CMD_NUM, BASICXE_OPS_NUM, 0x0D }, +}; + +#define OP_NHCONST 0x0D +#define OP_NCONST 0x0E +#define OP_SCONST 0x0F +#define OP_EOL 0x16 + +#define VART_SCALAR 0x00 + +#define VART_ARRAYU 0x40 +#define VART_ARRAY 0x41 + +#define VART_STRINGU 0x80 +#define VART_STRING 0x81 + +#define VART_STRINGAU 0x90 +#define VART_STRINGA 0x91 + +#define VART_PROC 0xC1 +#define VART_LABEL 0xC2 + +#define SHEADER PRG_NAME " v" PRG_VERSION " (c) " PRG_COPYRIGHT " " PRG_AUTHOR "\n" + +#define HEADER SHEADER \ + PRG_DESC "\n" \ + " Latest version can be found at " PRG_URL "\n" \ + " Published under GPL. See GPL.TXT.\n" \ + " Thanks to Russ Gilbert for his SALVAGE programs.\n\n" + +#define USAGE HEADER "Usage: " PRG_NAME " " PRG_USAGE + +BOOL GenCode( CFile* pcf, DWORD dwStart, DWORD dwEnd ); +BOOL GenLineCode( CFile* pcf, DWORD dwEnd ); +BOOL GenCmdCode( CFile* pcf, DWORD dwLineStart, DWORD dwLineEnd ); +BOOL GenOpsCode( CFile* pcf, DWORD dwTokEnd ); +double ReadAtariBCD( CFile* pcf ); + +BOOL Vars_Load( CFile* pcf, WORD wVNT, WORD wVNTL, WORD wVVT, WORD NV ); +void Var_Get( char* szRet, int iNum ); +void Vars_Destroy(); + +FILE* g_fout = NULL; +CArray g_aVariables; //array of variables + +BOOL g_bVerbose = FALSE; //verbose output +BOOL g_bAtariOut = FALSE; //atari output +BOOL g_bExtOut = TRUE; //extended output +BOOL g_bHasErrors = FALSE; //decode error flag +BOOL g_bNoInverse = FALSE; //don't emit inverse +BASIC_TYPE g_Type = BASIC; //basic type. Default is Atari Basic + +char** g_aBasicCmds; //array of commands +char** g_aBasicOps; //array of operands +int g_iCmdNum; //number of commands +int g_iOpsNum; //number of operands +int g_iOpFirst; //first operand + +#include "switches.cpp" + +int main( int argc, char* argv[] ) +{ + setbuf( stdout, NULL ); + setbuf( stderr, NULL ); + + if ( !SWITCHES_Init( &argc, argv ) ) + return 1; + + if(strstr(argv[0], "listbas")) + g_bExtOut = FALSE; + + if ( argc < 2 ) + { + SWFN_HELP( USAGE ); + return 1; + } + + if ( g_bExtOut ) + fprintf( stderr, SHEADER "\n" ); + else + fprintf( stderr, HEADER ); + + char* szInfile = argv[ 1 ]; + char* szOutfile = NULL; + + if ( argc > 2 ) + szOutfile = argv[ 2 ]; + + CFile cf; + + if ( !cf.Open( szInfile ) ) + { + fprintf( stderr, "Can't open input file '%s'\n", szInfile ); + return 1; + } + + if ( szOutfile ) + { + if( g_bAtariOut ) + g_fout = fopen( szOutfile, "wb" ); //opening as binary because of + //atascii + else + g_fout = fopen( szOutfile, "wt" ); + } + + if ( !g_fout ) + g_fout = stdout; + + //Don't emit additional info if you are in Atari mode + if ( g_bAtariOut ) + g_bExtOut = FALSE; + + if ( g_bExtOut ) + { + fprintf( g_fout, HEADER ); + fprintf( g_fout, "Input file: %s\n\n", szInfile ); + } + + //initialize globals depending on language set + g_aBasicCmds = langtbl[ g_Type ].ppCommands; + g_aBasicOps = langtbl[ g_Type ].ppOperands; + g_iCmdNum = langtbl[ g_Type ].iCmdNum; + g_iOpsNum = langtbl[ g_Type ].iOpNum; + g_iOpFirst = langtbl[ g_Type ].iOpFirst; + + DWORD dwFileLen = cf.GetLength(); + + //read head + WORD wLOMEM = cf.readLEw(); + WORD wVNT = cf.readLEw(); + WORD wVNTE = cf.readLEw(); + WORD wVVT = cf.readLEw(); + WORD wSTMTAB = cf.readLEw(); + WORD wSTMCUR = cf.readLEw(); + WORD wSTARP = cf.readLEw(); + + if( ( wLOMEM == 0x00DD ) && ( g_Type == BASIC_XE ) ) + { + //extended mode of Basic XE + wLOMEM = 0; + g_Type = BASIC_XEX; + } + + WORD wCOR = wVNT - wLOMEM - 0x0E; + + wVNT -= wCOR; + wVNTE -= wCOR; + wVVT -= wCOR; + wSTMTAB -= wCOR; + wSTMCUR -= wCOR; + wSTARP -= wCOR; + + WORD wVNTL = wVNTE - wVNT + 1; + WORD wVVTE = wSTMTAB - 1; + WORD wVVTL = wVVTE - wVVT + 1; + WORD NV = wVVTL / 8; + + WORD wCodeLen = wSTMCUR - wSTMTAB; + WORD wCodeLenCur = wSTARP - wSTMCUR; + + long lLenDiff = (long)dwFileLen - (long)wSTARP; + + if ( g_bExtOut ) + { + fprintf( g_fout, "Constants & pointers:\n" ); + fprintf( g_fout, "Start of Name Table (VNT) : %04X\n", wVNT ); + fprintf( g_fout, "End of Name Table (VNTE) : %04X\n", wVNTE ); + fprintf( g_fout, "Lenght of Name Table (VNTL) : %04X\n", wVNTL ); + + fprintf( g_fout, "Start of Variable Table (VVT) : %04X\n", wVVT ); + fprintf( g_fout, "End of Variable Table (VVTE) : %04X\n", wVVTE ); + fprintf( g_fout, "Length of Variable Table (VVTL) : %04X\n", wVVTL ); + + fprintf( g_fout, "Number of Variables (NV) : %04X\n", NV ); + + fprintf( g_fout, "Start of Code (STMTAB): %04X\n", wSTMTAB ); + fprintf( g_fout, "Length of Code : %04X\n", wCodeLen ); + fprintf( g_fout, "Current command (STMCUR): %04X\n", wSTMCUR ); + fprintf( g_fout, "Length of current command : %04X\n", wCodeLenCur ); + fprintf( g_fout, "First byte after program (STARP) : %04X\n", wSTARP ); + + if( g_Type != BASIC_XEX ) + { + fprintf( g_fout, "Length of file : %04lX\n", dwFileLen ); + fprintf( g_fout, "File len difference : %08lX\n", (DWORD)lLenDiff ); + } + fputc( '\n', g_fout ); + } + + //records must be 8 bytes long + if ( NV * 8 != wVVTL ) + { + fprintf( stderr, "Variable Table Length Mismatch!\n" ); + return 1; + } + + if ( lLenDiff <0 ) + { + fprintf( stderr, "File Length Incorrect!\n" ); + return 1; + } + + if ( !Vars_Load( &cf, wVNT, wVNTL, wVVT, NV ) ) + return 1; + + if ( g_bExtOut ) + { + fprintf( g_fout, "Main code starts here:\n" ); + } + + GenCode( &cf, wSTMTAB, wSTMCUR ); + + if ( g_bExtOut ) + { + fputc( '\n', g_fout ); + + fprintf( g_fout, "Immediate code starts here:\n" ); + GenCode( &cf, wSTMCUR, wSTARP ); + fputc( '\n', g_fout ); + } + else + { + cf.Seek( wSTARP, SEEK_SET ); + } + + //if extended mode of Basic XE + if( g_Type == BASIC_XEX ) + { + //code is stored in 4 extended memory banks + for( int iBank = 0; iBank < 4; iBank++ ) + { + //read the end of code in bank + WORD wLen = cf.readLEw(); + + //because bank starts at 0x4000, the value must be GE + if( wLen < 0x4000 ) + { + fprintf( stderr, "Bank end too low! %04X\n", wLen ); + g_bHasErrors = TRUE; + break; + } + + wLen -= 0x4000; + + if ( g_bExtOut ) + { + fprintf( g_fout, "\nBank %d code:\n", iBank ); + } + + if ( wLen ) + { + //if we have anything to process, we do so + long lNow = cf.Tell(); + GenCode( &cf, lNow, lNow + wLen ); + } + else + { + //else we skip one byte (error in BXE?) in empty bank + cf.skip( 1 ); + } + + if ( g_bExtOut ) + { + fputc( '\n', g_fout ); + } + } + } + + cf.Close(); + + if ( g_bHasErrors ) + fprintf( stderr, "File may contain some errors!\n" ); + + if ( g_fout != stdout ) + fclose( g_fout ); + + fprintf( stderr, "Done!\n" ); + + Vars_Destroy(); + + return 0; +} + +BOOL GenCode( CFile* pcf, DWORD dwStart, DWORD dwEnd ) +{ + pcf->Seek( dwStart, SEEK_SET ); + + //going thru the bank + while( pcf->Tell() < (long)dwEnd ) + { + //generating line + if ( !GenLineCode( pcf, dwEnd ) ) + { + g_bHasErrors = TRUE; + return FALSE; + } + + //output the correct line terminator + if ( g_bAtariOut ) + fputc( 0x9B, g_fout ); + else + fputc( '\n', g_fout ); + } + + return TRUE; +} + +BOOL GenLineCode( CFile* pcf, DWORD dwEnd ) +{ + DWORD dwLineStart = pcf->Tell(); + + //some debug info + if ( g_bVerbose ) + fprintf( g_fout, "[O:%08lX]", dwLineStart ); + + //line number + WORD wLineNum = pcf->readLEw(); + + //end of line + BYTE btLEnd = pcf->readb(); + DWORD dwLineEnd = dwLineStart + btLEnd; + + //don't print immediate line in BASIC XE extended (already filtered in + // other versions + + if( g_Type == BASIC_XEX ) + { + if( wLineNum == 0x8000 ) + { + pcf->Seek( dwLineEnd, SEEK_SET ); + return TRUE; + } + } + + fprintf( g_fout, "%d ", wLineNum ); + + if ( g_bVerbose ) + { + fprintf( g_fout, "[S:%04lX E:%04lX]", dwLineStart, dwLineEnd ); + } + + //if the line goes the end of buffer, croak + if ( ( dwLineStart > dwEnd ) || ( dwLineEnd > dwEnd ) ) + { + fprintf( g_fout, "***Line size mismatch. (%04lX-%04lX)\n", dwLineEnd, dwEnd ); + return FALSE; + } + + //and generate the output for commands + while( pcf->Tell() < (long)dwLineEnd ) + { + if ( !GenCmdCode( pcf, dwLineStart, dwLineEnd ) ) + return FALSE; + } + + return TRUE; +} + +BOOL GenCmdCode( CFile* pcf, DWORD dwLineStart, DWORD dwLineEnd ) +{ + //end of token + BYTE btTEnd = pcf->readb(); + + DWORD dwTokStart = pcf->Tell(); + DWORD dwTokEnd = dwLineStart + btTEnd; + + if ( g_bVerbose ) + { + fprintf( g_fout, "[C:%04lX E:%04lX]", dwTokStart, dwTokEnd ); + } + + //could this ever happen? + if ( dwTokStart >= dwTokEnd ) + { + fprintf( g_fout, "***Command size problem!\n" ); + return FALSE; + } + + //if token goes behind the eol + if ( dwTokEnd > dwLineEnd ) + { + fprintf( g_fout, "***Command size mismatch. (%04lX-%04lX)\n", dwTokEnd, dwLineEnd ); + return FALSE; + } + + //which token + BYTE btTok = pcf->readb(); + + //token buffer + char szTok[ 50 ]; + + //if known token + if ( btTok < g_iCmdNum ) + { + //sub table for BXL extended commands + if( ( btTok == BXL_EXTEND ) && ( g_Type == BASIC_XL ) ) + { + BYTE btTok = pcf->readb(); + + switch( btTok ) + { + case 0x10: + strcpy( szTok, "LOCAL" ); + break; + + case 0x11: + strcpy( szTok, "EXIT" ); + break; + + case 0x12: + strcpy( szTok, "PROCEDURE" ); + break; + + case 0x13: + strcpy( szTok, "CALL" ); + break; + + case 0x14: + strcpy( szTok, "SORTUP" ); + break; + + case 0x15: + strcpy( szTok, "SORTDOWN" ); + break; + + default: + sprintf( szTok, "EXTEND?%02X", btTok ); + g_bHasErrors = TRUE; + break; + + } + } + else + strcpy( szTok, g_aBasicCmds[ btTok ] ); + } + else + { + sprintf( szTok, "COM%02X", btTok ); + fprintf( stderr, "Unknown command %02X!!!\n", btTok ); + g_bHasErrors = TRUE; + } + + if ( *szTok ) + { + //lower case for some dialects + if( ( g_Type == BASIC_XL ) || ( g_Type == BASIC_XE ) || ( g_Type == BASIC_XEX ) ) + { + strlwr( szTok + 1 ); + } + + fprintf( g_fout, "%s ", szTok ); + } + + //special handling for REM & DATA (first two statements) + if ( btTok < 2 ) + { + BYTE c; + + int iSecure = 0x100; + + for( ;; ) + { + c = pcf->readb(); + + if ( c == 0x9B ) + break; + + if ( g_bNoInverse ) + c &= 0x7F; + + fputc( c, g_fout ); + + iSecure--; + + if( !iSecure ) + { + fprintf( stderr, "Runaway in Rem/Data code!\n" ); + return FALSE; + } + } + + return TRUE; + + } + + //generate operands for remain of command + while( pcf->Tell() < (long)dwTokEnd ) + { + if ( !GenOpsCode( pcf, dwTokEnd ) ) + return FALSE; + } + + return TRUE; +} + +BOOL GenOpsCode( CFile* pcf, DWORD dwTokEnd ) +{ + //get operand + BYTE btTok = pcf->readb(); + + if ( btTok == OP_EOL ) + { + //new line + return TRUE; + } + + if ( btTok == OP_NCONST ) + { + //bcd num + + fprintf( g_fout, "%.10g", ReadAtariBCD( pcf ) ); + + return TRUE; + } + + if ( btTok == OP_NHCONST ) + { + if ( g_Type == BASIC_TB ) + { + //hex num TBASIC + fprintf( g_fout, "$%X", (unsigned short)ReadAtariBCD( pcf ) ); + return TRUE; + } + + if( ( g_Type == BASIC_XL ) || ( g_Type == BASIC_XE ) || ( g_Type == BASIC_XEX ) ) + { + //hex num BASIC XL + WORD wNum = (unsigned short)ReadAtariBCD( pcf ); + + if( wNum > 0xFF ) + fprintf( g_fout, "$%04X", wNum ); + else + fprintf( g_fout, "$%02X", wNum ); + + return TRUE; + } + } + + if ( btTok == OP_SCONST ) + { + //string + BYTE c; + + BYTE btLen = pcf->readb(); + + fprintf( g_fout, "\"" ); + while( btLen-- ) + { + c = pcf->readb(); + + if ( c == 0x9B ) + { + break; + } + + //is this for TBASIC only? + if ( c == '\"' ) + { + fprintf( g_fout, "\"\"" ); + } + else + fputc( c, g_fout ); + + } + fprintf( g_fout, "\"" ); + return TRUE; + } + + //and now for variables + if ( btTok & 0x80 ) + { + char szPom[ 255 ]; + + Var_Get( szPom, btTok & 0x7F ); + + if( ( g_Type == BASIC_XL ) || ( g_Type == BASIC_XE ) || ( g_Type == BASIC_XEX ) ) + { + strlwr( szPom + 1 ); + } + + fprintf( g_fout, szPom ); + + return TRUE; + } + + //func or op + if ( ( btTok < g_iOpFirst ) || ( btTok - g_iOpFirst + 1 > (BYTE)g_iOpsNum ) ) + { + fprintf( g_fout, "UNKOP%02X", btTok ); + fprintf( stderr, "Unknown operand %02X!!!\n", btTok ); + g_bHasErrors = TRUE; + } + else + { + char szPom[ 100 ]; + strcpy( szPom, g_aBasicOps[ btTok - g_iOpFirst ] ); + + if( ( g_Type == BASIC_XL ) || ( g_Type == BASIC_XE ) || ( g_Type == BASIC_XEX ) ) + { + strlwr( szPom + 1 ); + } + + fprintf( g_fout, "%s", szPom ); + } + + return TRUE; + +} + +//code for reading Atari BCD format +double ReadAtariBCD( CFile* pcf ) +{ + double dRes = 0; + + //reads exponent + BYTE btExp = pcf->readb(); + + int iExp; + + if ( !btExp ) + { + //if Exp==0, we're skipping it! (silently!) + iExp = 0; + pcf->skip( 5 ); + } + else + { + //compute exponent + iExp = ( btExp - 68 ) * 2; + + int i = 5; + + //read 5 pairs of numbers and combine 'em + while ( i-- ) + { + BYTE btPom = pcf->readb(); + + BYTE btNum = ( btPom >> 4 ) * 10 + ( btPom &0xf ); + + dRes *= 100; + dRes += btNum; + } + + } + + dRes *= pow( 10, iExp ); + + return dRes; +} + +BOOL Vars_Load( CFile* pcf, WORD wVNT, WORD wVNTL, WORD wVVT, WORD NV ) +{ + char szVarTemp[ 256 ]; + char szVarGen[ 256 ]; + + char* pStr = NULL; + + BOOL bTog = FALSE; + + pcf->Seek( wVNT, SEEK_SET ); + + for( int i = 0; i < wVNTL; i++ ) + { + if ( !pStr ) + pStr = szVarTemp; + + char c = pcf->readb(); + + if ( c & 0x80 ) + { + c &= 0x7F; + bTog = TRUE; + } + + *( pStr++ ) = c; + *pStr = '\0'; + + //this is for correcting the runaway + if ( pStr - szVarTemp > 254 ) + { + *szVarTemp = '\0'; + bTog = TRUE; + } + + if ( bTog ) + { + int iVar = g_aVariables.GetSize(); + + sprintf( szVarGen, "VAR%d", iVar ); + + pStr = szVarTemp; + + int iLength = strlen( szVarTemp ); + + if ( iLength ) + { + for( int i = 0; i < iLength; i++ ) + { + if ( !isprint( *( pStr++ ) ) ) + { + strcpy( szVarTemp, szVarGen ); + break; + } + } + + if ( iVar ) + { + for( int i = 0; i < iVar; i++ ) + { + if( !strcmp( (char*)g_aVariables.GetAt( i ), szVarTemp ) ) + { + fprintf( g_fout, "Dupped varname: %s\n", szVarTemp ); + strcpy( szVarTemp, szVarGen ); + break; + } + } + } + + } + else + { + strcpy( szVarTemp, szVarGen ); + } + + pStr = new char [ strlen( szVarTemp ) + 1 ]; + + if ( pStr ) + { + strcpy( pStr, szVarTemp ); + g_aVariables.Add( pStr ); + } + else + { + printf( "Not enough memory!\n" ); + return FALSE; + } + + bTog = FALSE; + pStr = NULL; + } + } + + if ( g_bExtOut ) + { + fprintf( g_fout, "Variable table:\n" ); + } + + pcf->Seek( wVVT, SEEK_SET ); + + for( int i = 0 ; i < NV; i++ ) + { + BYTE btType = pcf->readb(); + BYTE btNumber = pcf->readb(); + + char* szType; + + char szText[ 50 ]; + + switch( btType ) + { + case VART_SCALAR: + { + szType = "SCALAR "; + sprintf( szText, "%.10g", ReadAtariBCD( pcf ) ); + break; + } + + case VART_ARRAYU: + { + szType = "ARRAYu "; + char* szP = szText; + szP += sprintf( szP, "SPoff: %04X ", pcf->readLEw() ); + szP += sprintf( szP, "Dim1: %d ", pcf->readLEw() ); + szP += sprintf( szP, "Dim2: %d ", pcf->readLEw() ); + break; + } + + case VART_ARRAY: + { + szType = "ARRAY "; + char* szP = szText; + szP += sprintf( szP, "SPoff: %04X ", pcf->readLEw() ); + szP += sprintf( szP, "Dim1: %d ", pcf->readLEw() ); + szP += sprintf( szP, "Dim2: %d ", pcf->readLEw() ); + break; + } + + case VART_STRINGAU: + { + //BASIC_XL / XE + szType = "STRINGAu"; + char* szP = szText; + szP += sprintf( szP, "SPoff: %04X ", pcf->readLEw() ); + szP += sprintf( szP, "Dim1: %d ", pcf->readLEw() ); + szP += sprintf( szP, "Dim2: %d ", pcf->readLEw() ); + break; + } + + case VART_STRINGA: + { + //BASIC_XL / XE + szType = "STRINGA "; + char* szP = szText; + szP += sprintf( szP, "SPoff: %04X ", pcf->readLEw() ); + szP += sprintf( szP, "Dim1: %d ", pcf->readLEw() ); + szP += sprintf( szP, "Dim2: %d ", pcf->readLEw() ); + break; + } + + case VART_STRINGU: + { + szType = "STRINGu "; + char* szP = szText; + szP += sprintf( szP, "SPoff: %04X ", pcf->readLEw() ); + szP += sprintf( szP, "Len: %d ", pcf->readLEw() ); + szP += sprintf( szP, "Dim: %d ", pcf->readLEw() ); + break; + } + + case VART_STRING: + { + szType = "STRING "; + char* szP = szText; + szP += sprintf( szP, "SPoff: %04X ", pcf->readLEw() ); + szP += sprintf( szP, "Len: %d ", pcf->readLEw() ); + szP += sprintf( szP, "Dim: %d ", pcf->readLEw() ); + break; + } + + case VART_PROC: + { + //TBASIC + szType = "PROC "; + char* szP = szText; + for( int i = 0 ; i < 6; i++ ) + { + szP += sprintf( szP, "%02X ", pcf->readb() ); + } + break; + } + + case VART_LABEL: + { + //TBASIC + szType = "LABEL "; + char* szP = szText; + for( int i = 0 ; i < 6; i++ ) + { + szP += sprintf( szP, "%02X ", pcf->readb() ); + } + break; + } + + default: + { + szType = "UNKNOWN "; + char* szP = szText; + for( int i = 0 ; i < 6; i++ ) + { + szP += sprintf( szP, "%02X ", pcf->readb() ); + } + g_bHasErrors = TRUE; + } + } + + char szName[ 255 ]; + Var_Get( szName, btNumber ); + + char cLastChar = szName[ strlen( szName ) - 1 ]; + + switch( btType ) + { + case VART_STRING: + case VART_STRINGU: + { + if ( cLastChar != '$' ) + { + strcat( szName, "$" ); + char* szStr = new char [ strlen( szName ) + 1 ]; + strcpy( szStr, szName ); + char* szOld = (char*) g_aVariables.GetAt( btNumber ); + + if ( szOld ) + delete [] szOld; + + g_aVariables.SetAt( btNumber, szStr ); + + } + + break; + } + + case VART_ARRAY: + case VART_ARRAYU: + { + if ( cLastChar == '(' ) + { + szName[ strlen( szName ) - 1 ] = '\0'; + char* szStr = new char [ strlen( szName ) + 1 ]; + strcpy( szStr, szName ); + char* szOld = (char*) g_aVariables.GetAt( btNumber ); + + if ( szOld ) + delete [] szOld; + + g_aVariables.SetAt( btNumber, szStr ); + + } + + break; + } + + } + + if ( g_bExtOut ) + { + fprintf( g_fout, "%04X %s (%02X) %02X: %s %s\n", + i+1, + szType, + btType, + btNumber, + szText, + szName ); + } + + } + + if ( g_bExtOut ) + fputc( '\n', g_fout ); + + return TRUE; +} + +void Var_Get( char* szRet, int iNum ) +{ + char* szVar = (char*) g_aVariables.GetAt( iNum ); + + if ( szVar ) + strcpy( szRet, szVar ); + else + sprintf( szRet, "VAR%d", iNum ); +} + +void Vars_Destroy() +{ + for( int i = 0; i < g_aVariables.GetSize(); i++ ) + { + if ( g_aVariables.GetAt( i ) ) + delete [] ( char* ) g_aVariables.GetAt( i ); + } +} + |