diff options
author | Juan J. Martinez <jjm@usebox.net> | 2023-11-05 11:22:55 +0000 |
---|---|---|
committer | Juan J. Martinez <jjm@usebox.net> | 2023-11-05 11:31:28 +0000 |
commit | 2fbdf974338bde8576efdae40a819a76b2391033 (patch) | |
tree | 64d41a37470143f142344f9a439d96de3e7918c2 /tools/iDSK | |
download | kitsunes-curse-2fbdf974338bde8576efdae40a819a76b2391033.tar.gz kitsunes-curse-2fbdf974338bde8576efdae40a819a76b2391033.zip |
Initial import of the open source release
Diffstat (limited to 'tools/iDSK')
28 files changed, 4800 insertions, 0 deletions
diff --git a/tools/iDSK/AUTHORS b/tools/iDSK/AUTHORS new file mode 100644 index 0000000..0c18ff6 --- /dev/null +++ b/tools/iDSK/AUTHORS @@ -0,0 +1,3 @@ +cpcemu - Marco Vieth +manageDSK - Ludovic Deplanque +iDSK - Sid from IMPACT / PulkoMandy from the Shinra Team diff --git a/tools/iDSK/CMakeLists.txt b/tools/iDSK/CMakeLists.txt new file mode 100644 index 0000000..9e8319e --- /dev/null +++ b/tools/iDSK/CMakeLists.txt @@ -0,0 +1,15 @@ +PROJECT(iDSK) + +add_executable(iDSK + src/Basic.cpp + src/BitmapCPC.cpp + src/Dams.cpp + src/Desass.cpp + src/endianPPC.cpp + src/GestDsk.cpp + src/getopt_pp.cpp + src/Main.cpp + src/Outils.cpp + src/ViewFile.cpp + src/Ascii.cpp +) diff --git a/tools/iDSK/COPYING b/tools/iDSK/COPYING new file mode 100644 index 0000000..d200743 --- /dev/null +++ b/tools/iDSK/COPYING @@ -0,0 +1,23 @@ +Portions parts of CPCemu, (C) 1991-2002 Marco Vieth & Rainer Loritz +Portions parts of ManageDSK, (c) 2005-2015 Ludovic Deplanque (Demoniak) + +iDSK is copyright (c) ????-2019 Jérôme Le Saux (Sid), Colin Pitrat, Thomas Bernard (miniupnp), Romain Giot (Krusty) and Adrien Destugues (PulkoMandy) + +Distributed under the terms of the MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be included in all copies +or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/tools/iDSK/README.md b/tools/iDSK/README.md new file mode 100644 index 0000000..54a773c --- /dev/null +++ b/tools/iDSK/README.md @@ -0,0 +1,7 @@ +[![Build Status](https://travis-ci.org/cpcsdk/idsk.svg?branch=master)](https://travis-ci.org/cpcsdk/idsk) + +iDSK is a tool to edit DSK (Amstrad CPC disk images) files from the command +line. You can add and remove files from your image, but also list BASIC and +DAMS source files (which are usually in a tokenized format, not plain ASCII). + +iDSK can add and remove AMSDOS headers as needed. diff --git a/tools/iDSK/src/Ascii.cpp b/tools/iDSK/src/Ascii.cpp new file mode 100644 index 0000000..19fced5 --- /dev/null +++ b/tools/iDSK/src/Ascii.cpp @@ -0,0 +1,16 @@ +#include <iostream> +using namespace std; +#include <cmath> +#include <cstring> +#include <cstdio> +#include <ctype.h> + +#include "MyType.h" +#include "Ascii.h" + +void Ascii(unsigned char *Prg, char *Listing, int Longueur) +{ + int Adr = 0; + * Listing = 0; + strncpy(Listing,(const char*)Prg,Longueur); +}
\ No newline at end of file diff --git a/tools/iDSK/src/Ascii.h b/tools/iDSK/src/Ascii.h new file mode 100644 index 0000000..688f8a4 --- /dev/null +++ b/tools/iDSK/src/Ascii.h @@ -0,0 +1,6 @@ +#ifndef ASCII_H +#define ASCII_H + +void Ascii(unsigned char *Prg, char *Listing, int Longueur); + +#endif
\ No newline at end of file diff --git a/tools/iDSK/src/Basic.cpp b/tools/iDSK/src/Basic.cpp new file mode 100644 index 0000000..6fe044d --- /dev/null +++ b/tools/iDSK/src/Basic.cpp @@ -0,0 +1,359 @@ +#include <iostream> +using namespace std; +#include <cmath> +#include <cstring> +#include <cstdio> +#include <ctype.h> + +#include "MyType.h" +#include "Basic.h" + + +//static char ConvCpcFr[ 128 ] = " !\"#$%&'()*+,-./0123456789:;<=>?àABCDEFGHIJKLMNOPQRSTUVWXYZ[ç]^_`abcdefghijklmnopqrstuvwxyzéùè~"; + + +// +// Tableau de décryptage d'un programme en basic protégé +// +static BYTE DproBasic[ 128 ] = + { + 0xAB, 0x2C, 0xED, 0xEA, 0x6C, 0x37, 0x3F, 0xEC, + 0x9B, 0xDF, 0x7A, 0x0C, 0x3B, 0xD4, 0x6D, 0xF5, + 0x04, 0x44, 0x03, 0x11, 0xDF, 0x59, 0x8F, 0x21, + 0x73, 0x7A, 0xCC, 0x83, 0xDD, 0x30, 0x6A, 0x30, + 0xD3, 0x8F, 0x02, 0xF0, 0x60, 0x6B, 0x94, 0xE4, + 0xB7, 0xF3, 0x03, 0xA8, 0x60, 0x88, 0xF0, 0x43, + 0xE8, 0x8E, 0x43, 0xA0, 0xCA, 0x84, 0x31, 0x53, + 0xF3, 0x1F, 0xC9, 0xE8, 0xAD, 0xC0, 0xBA, 0x6D, + 0x93, 0x08, 0xD4, 0x6A, 0x2C, 0xB2, 0x07, 0x27, + 0xC0, 0x99, 0xEE, 0x89, 0xAF, 0xC3, 0x53, 0xAB, + 0x2B, 0x34, 0x5C, 0x2F, 0x13, 0xEE, 0xAA, 0x2C, + 0xD9, 0xF4, 0xBC, 0x12, 0xB3, 0xC5, 0x1C, 0x68, + 0x01, 0x20, 0x2C, 0xFA, 0x77, 0xA6, 0xB5, 0xA4, + 0xFC, 0x9B, 0xF1, 0x32, 0x5B, 0xC3, 0x70, 0x77, + 0x85, 0x36, 0xBE, 0x5B, 0x8C, 0xC8, 0xB5, 0xC2, + 0xF0, 0x0B, 0x98, 0x0F, 0x36, 0x9D, 0xD8, 0x96 + }; + + +BYTE GetByte( BYTE * BufFile, int Pos, int Deprotect ) +{ + //BYTE b = ( BYTE )( BufFile[ Pos ] ^ ( DproBasic[ Pos & 0x7F ] * Deprotect ) ); + //cout << "GetByte:"<<hex<<b<<endl; + return( BYTE )( BufFile[ Pos ] ^ ( DproBasic[ Pos & 0x7F ] * Deprotect ) ); +} + + +int GetWord( BYTE * BufFile, int Pos, int Deprotect ) +{ + int Ret = BufFile[ Pos ] ^ ( DproBasic[ Pos & 0x7F ] * Deprotect ); + Pos++; + Ret += ( ( BufFile[ Pos ] ^ ( DproBasic[ Pos & 0x7F ] * Deprotect ) ) << 8 ); + return( Ret ); +} + + +// +// Ajoute un "mot" (nom d'une variable, RSX...) dans la chaine "Listing" +// +int AddWord( BYTE * BufFile, int Pos, char * Listing, int Deprotect ) +{ + int LenVar = 0, l = strlen( Listing ); + BYTE b; + + do + { + b = GetByte( BufFile, Pos++, Deprotect ); + Listing[ l++ ] = ( char )( b & 0x7F ); + } + while( ! ( b & 0x80 ) && LenVar++ < 0xFF ); + Listing[ l ] = 0; + return( Pos ); +} + + +// +// Convertir le buffer en listing basic +// +void Basic( BYTE * BufFile, char * Listing, bool IsBasic, bool CrLf ) +{ + static char Tmp[ 32 ]; + int Pos = 0, Token = 0; + int StartLigne = 0, EndLigne; + char * p; + double f; + int exp; + int Deprotect=0; + //cout << BufFile <<endl; + static const char * Nbre[ 11 ] = + { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" + }; + static const char * MotsClefs[ 0x80 ] = + { + "AFTER", "AUTO", "BORDER", "CALL", "CAT", "CHAIN", "CLEAR", "CLG", + "CLOSEIN", "CLOSEOUT", "CLS", "CONT", "DATA", "DEF", "DEFINT", + "DEFREAL", "DEFSTR", "DEG", "DELETE", "DIM", "DRAW", "DRAWR", "EDIT", + "ELSE", "END", "ENT", "ENV", "ERASE", "ERROR", "EVERY", "FOR", + "GOSUB", "GOTO", "IF", "INK", "INPUT", "KEY", "LET", "LINE", "LIST", + "LOAD", "LOCATE", "MEMORY", "MERGE", "MID$", "MODE", "MOVE", "MOVER", + "NEXT", "NEW", "ON", "ON BREAK", "ON ERROR GOTO", "SQ", "OPENIN", + "OPENOUT", "ORIGIN", "OUT", "PAPER", "PEN", "PLOT", "PLOTR", "POKE", + "PRINT", "'", "RAD", "RANDOMIZE", "READ", "RELEASE", "REM", "RENUM", + "RESTORE", "RESUME", "RETURN", "RUN", "SAVE", "SOUND", "SPEED", "STOP", + "SYMBOL", "TAG", "TAGOFF", "TROFF", "TRON", "WAIT", "WEND", "WHILE", + "WIDTH", "WINDOW", "WRITE", "ZONE", "DI", "EI", "FILL", "GRAPHICS", + "MASK", "FRAME", "CURSOR", "#E2", "ERL", "FN", "SPC", "STEP", "SWAP", + "#E8", "#E9", "TAB", "THEN", "TO", "USING", ">", "=", ">=", "<", "<>", + "<=", "+", "-", "*", "/", "^", "\\ ", "AND", "MOD", "OR", "XOR", "NOT", + "#FF" + }; + + static const char * Fcts[ 0x80 ] = + { + "ABS", "ASC", "ATN", "CHR$", "CINT", "COS", "CREAL", "EXP", "FIX", + "FRE", "INKEY", "INP", "INT", "JOY", "LEN", "LOG", "LOG10", "LOWER$", + "PEEK", "REMAIN", "SGN", "SIN", "SPACE$", "SQ", "SQR", "STR$", "TAN", + "UNT", "UPPER$", "VAL", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "EOF", "ERR", "HIMEM", "INKEY$", "PI", "RND", + "TIME", "XPOS", "YPOS", "DERR", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "BIN$", "DEC$", "HEX$", + "INSTR", "LEFT$", "MAX", "MIN", "POS", "RIGHT$", "ROUND", "STRING$", + "TEST", "TESTR", "COPYCHR$", "VPOS" + }; + + + * Listing = 0; + Token = GetByte( BufFile, 0, Deprotect ); + for ( ;; ) + { + //cout << "Listing : " <<Listing << endl; + if ( IsBasic ) + { + int lg = GetWord( BufFile, Pos, Deprotect ); + Pos += 2; + if ( ! lg ) + break; + + int NumLigne = GetWord( BufFile, Pos, Deprotect ); + Pos += 2; + sprintf( Tmp, "%d ", NumLigne ); + strcat( Listing, Tmp ); + } + else + if ( ! Token || Token == 0x1A ) + break; + + int DansChaine = 0; // #### Hum, plus compliqué que ça je pense... + do + { + //cout << "Tmp:"<<Tmp<<endl; + Token = GetByte( BufFile, Pos++, Deprotect ); + if ( ! IsBasic && Token == 0x1A ) + break; + + if ( DansChaine || ! IsBasic ) + { + Tmp[ 0 ] = ( char )Token; + Tmp[ 1 ] = 0; + strcat( Listing, Tmp ); + if ( Token == '"' ) + DansChaine ^= 1; + // cout << " DansChaine Tmp:"<<Tmp<<endl; + } + else + if ( Token > 0x7F && Token < 0xFF ) + { + // #### Traitement particulier du ':' avant le ELSE + if ( Listing[ strlen( Listing ) - 1 ] == ':' + && Token == 0x97 + ) + Listing[ strlen( Listing ) - 1 ] = 0; + + strcat( Listing + , MotsClefs[ Token & 0x7F ] + ); + } + else + if ( Token >= 0x0E && Token <= 0x18 ) + strcat( Listing + , Nbre[ Token - 0x0E ] + ); + else + if ( Token >= 0x20 && Token < 0x7C ) + { + Tmp[ 0 ] = ( char )Token; + Tmp[ 1 ] = 0; + strcat( Listing, Tmp ); + if ( Token == '"' ) + DansChaine ^= 1; + } + else + { + //cout << "Token:" << Token <<endl; + switch( Token ) + { + case 0x01 : + Tmp[ 0 ] = ':'; + Tmp[ 1 ] = 0; + strcat( Listing, Tmp ); + break; + + case 0x02 : // Variable entière (type %) + Pos = AddWord( BufFile + , 2 + Pos + , Listing + , Deprotect + ); + strcat( Listing, "%" ); + break; + + + case 0x03 : // Variable chaine (type $) + Pos = AddWord( BufFile + , 2 + Pos + , Listing + , Deprotect + ); + strcat( Listing, "$" ); + break; + + case 0x04 : // Variable float (type !) + Pos = AddWord( BufFile + , 2 + Pos + , Listing + , Deprotect + ); + strcat( Listing, "!" ); + break; + + case 0x0B : + case 0x0C : + case 0x0D : // Variable "standard" + Pos = AddWord( BufFile + , 2 + Pos + , Listing + , Deprotect + ); + break; + + case 0x19 : // Constante entière 8 bits + sprintf(Listing+strlen(Listing),"%d",(BYTE)GetByte( BufFile, Pos, Deprotect)); + Pos++; + break; + + case 0x1A : + case 0x1E : // Constante entière 16 bits + sprintf(Listing+strlen(Listing),"%d",GetWord( BufFile, Pos, Deprotect)); + Pos += 2; + break; + + case 0x1B : + sprintf( Tmp + , "&X%X" + , GetWord( BufFile, Pos, Deprotect ) + ); + strcat( Listing, Tmp ); + Pos += 2; + break; + + case 0x1C : + sprintf( Tmp + , "&%X" + , GetWord( BufFile, Pos, Deprotect ) + ); + strcat( Listing, Tmp ); + Pos += 2; + break; + + case 0x1F : // Constante flottante + f = ( GetByte( BufFile, Pos + 2, Deprotect ) << 16 ) + + ( GetByte( BufFile, Pos + 1, Deprotect ) << 8 ) + + GetByte( BufFile, Pos, Deprotect ) + + ( ( GetByte( BufFile, Pos + 3, Deprotect ) & 0x7F ) << 24 ); + f = 1 + ( f / 0x80000000 ); + + if ( GetByte( BufFile, Pos + 3, Deprotect ) & 0x80 ) + f = -f; + + exp = GetByte( BufFile, Pos + 4, Deprotect ) - 129; + Pos += 5; + sprintf( Tmp, "%f", f * pow( (double) 2, exp ) ); + // Suppression des '0' inutiles + p = &Tmp[ strlen( Tmp ) - 1 ]; + while( * p == '0' ) + * p-- = 0; + + if ( * p == '.' ) + * p = 0; + + strcat( Listing, Tmp ); + break; + + case 0x7C : + strcat( Listing, "|" ); + Pos = AddWord( BufFile + , 1 + Pos + , Listing + , Deprotect + ); + break; + + case 0xFF : + if ( GetByte( BufFile, Pos, Deprotect ) < 0x80 ) + strcat( Listing + , Fcts[ GetByte( BufFile + , Pos++ + , Deprotect + ) + ] + ); + else + { + Tmp[ 1 ] = 0; + Tmp[ 0 ] = ( char )( GetByte( BufFile + , Pos++ + , Deprotect + ) & 0x7F + ); + strcat( Listing, Tmp ); + } + break; + + default : + Token = Token; + } + } + } + while( Token ); + if ( CrLf ) + { + // + // Retour à la ligne si > 80 caractères + // + EndLigne = strlen( &Listing[ StartLigne ] ); + while( EndLigne > 80 ) + { + memmove( &Listing[ StartLigne + 82 ] + , &Listing[ StartLigne + 80 ] + , EndLigne + ); + memcpy( &Listing[ StartLigne + 80 ], "\r\n", 2 ); + StartLigne += 82; + EndLigne -= 80; + } + } + strcat( Listing, "\r\n" ); + StartLigne = strlen( Listing ); + } + // Conversion des caractères accentués si nécessaire + + for ( int i = strlen( Listing); i--; ) + { + //cout << i << " "; + + if ( ! isprint(Listing[ i ]) && Listing[ i ] != '\n' && Listing[ i ] != '\r' ) Listing[ i ] = '?'; + } +} diff --git a/tools/iDSK/src/Basic.h b/tools/iDSK/src/Basic.h new file mode 100644 index 0000000..4f9cd38 --- /dev/null +++ b/tools/iDSK/src/Basic.h @@ -0,0 +1,8 @@ +#ifndef BASIC_H +#define BASIC_H + + +void Basic( unsigned char * BufFile, char * Listing, bool IsBasic, bool CrLf ); + + +#endif diff --git a/tools/iDSK/src/BitmapCPC.cpp b/tools/iDSK/src/BitmapCPC.cpp new file mode 100644 index 0000000..8eef0d1 --- /dev/null +++ b/tools/iDSK/src/BitmapCPC.cpp @@ -0,0 +1,264 @@ +#include <iostream> +#include <cstdio> +#include "MyType.h" +#include "BitmapCPC.h" +#include "GestDsk.h" +#include <string> +#include <cstring> +using namespace std; + + +// +// Couleurs du CPC converties en composantes r, v, b +// +static StRVB RgbCPC[ 27 ] = + { + { 0x00, 0x00, 0x00, 0x00 }, + { 0x7F, 0x00, 0x00, 0x00 }, + { 0xFF, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x7F, 0x00 }, + { 0x7F, 0x00, 0x7F, 0x00 }, + { 0xFF, 0x00, 0x7F, 0x00 }, + { 0x00, 0x00, 0xFF, 0x00 }, + { 0x7F, 0x00, 0xFF, 0x00 }, + { 0xFF, 0x00, 0xFF, 0x00 }, + { 0x00, 0x7F, 0x00, 0x00 }, + { 0x7F, 0x7F, 0x00, 0x00 }, + { 0xFF, 0x7F, 0x00, 0x00 }, + { 0x00, 0x7F, 0x7F, 0x00 }, + { 0x7F, 0x7F, 0x7F, 0x00 }, + { 0xFF, 0x7F, 0x7F, 0x00 }, + { 0x00, 0x7F, 0xFF, 0x00 }, + { 0x7F, 0x7F, 0xFF, 0x00 }, + { 0xFF, 0x7F, 0xFF, 0x00 }, + { 0x00, 0xFF, 0x00, 0x00 }, + { 0x7F, 0xFF, 0x00, 0x00 }, + { 0xFF, 0xFF, 0x00, 0x00 }, + { 0x00, 0xFF, 0x7F, 0x00 }, + { 0x7F, 0xFF, 0x7F, 0x00 }, + { 0xFF, 0xFF, 0x7F, 0x00 }, + { 0x00, 0xFF, 0xFF, 0x00 }, + { 0x7F, 0xFF, 0xFF, 0x00 }, + { 0xFF, 0xFF, 0xFF, 0x00 } + }; + + +int GetRgbCPC( int Coul ) +{ + if ( Coul >= 0 && Coul < 27 ) + { + StRVB i = RgbCPC[ Coul ]; + return( ( i.b << 16 ) + ( i.v << 8 ) + i.r ); + } + return( -1 ); +} + + +StRVB GetPalCPC( int Coul ) +{ + if ( Coul >= 0 && Coul < 27 ) + return( RgbCPC[ Coul ] ); + + return( RgbCPC[ 0 ] ); +} + + +void InitPalette( unsigned char NewPal[ 16 ], bool SetNewPal ) +{ + /* + Si sauvegard� avec ConvImgCpc, alors la palette se trouve + dans l'image... + */ + int i; + if ( BitmapCPC[ 0x7D0 ] == 0x3A + && BitmapCPC[ 0x7D1 ] == 0xD0 + && BitmapCPC[ 0x7D2 ] == 0xD7 + && BitmapCPC[ 0x7D3 ] == 0xCD + ) + { + Mode = BitmapCPC[ 0x17D0 ]; + for ( i = 0; i < 16; i++ ) + Palette[ i ] = BitmapCPC[ 0x17D1 + i ]; + } + if ( SetNewPal ) + for ( i = 0; i < 16; i++ ) + Palette[ i ] = NewPal[ i ]; +} + + +// +// D�compacter une image au format OCP +// +void DepactOCP( void ) +{ + static unsigned char BufTmp[ 0x4000 ]; + int PosIn = 0, PosOut = 0; + int LgOut, CntBlock = 0; + int c,i; + unsigned char a; + memcpy( BufTmp, BitmapCPC, sizeof( BufTmp ) ); + memset( BitmapCPC, 0, 0x4000 ); + while( PosOut < 0x4000 ) + { + if ( ! strncmp( ( char * )&BufTmp[ PosIn ], "MJH", 3 ) ) + { + PosIn += 3; + LgOut = BufTmp[ PosIn++ ]; + LgOut += ( BufTmp[ PosIn++ ] << 8 ); + CntBlock = 0; + while( CntBlock < LgOut ) + { + if ( ! strncmp( ( char * )&BufTmp[ PosIn ], "MJH", 3 ) ) + break; + + a = BufTmp[ PosIn++ ]; + if ( a == MARKER_OCP ) + { + c = BufTmp[ PosIn++ ]; + a = BufTmp[ PosIn++ ]; + if ( ! c ) + c = 0x100; + + for ( i = 0; i < c && CntBlock < LgOut; i++ ) + { + BitmapCPC[ PosOut++ ] = a; + CntBlock++; + } + } + else + { + BitmapCPC[ PosOut++ ] = a; + CntBlock++; + } + } + } + else + PosOut = 0x4000; + } +} + + +bool LireImage( char * Nom, StRVB * Bitmap ) +{ + static unsigned char Entete[ 0x80 ]; + bool Ret = FALSE; + //DWORD Nb; + FILE* hFile; + + + if ( (hFile=fopen(Nom,"rb"))!=NULL ) + { + fread(Entete,sizeof(Entete),1,hFile); + // ReadFile( hFile, Entete, sizeof( Entete ), &Nb, NULL ); + if ( CheckAmsdos( Entete ) ) + { + fread(BitmapCPC,sizeof( BitmapCPC ),1,hFile); + // ReadFile( hFile, BitmapCPC, sizeof( BitmapCPC ), &Nb, NULL ); + if ( ! strncmp( ( char * )BitmapCPC, "MJH", 3 ) ) + DepactOCP(); + + InitPalette( NULL, FALSE ); + Ret = TRUE; + } + // CloseHandle( hFile ); + fclose(hFile); + if ( Ret ) + Render( Bitmap, 1 ); + } + return( Ret ); + +} + + +// +// Affiche l'image � l'�cran +// +void Render( StRVB * Bitmap, bool Flat ) +{ + int AdrCPC = 0, i, p0, p1, p2, p3; + int y,x,AdrBitmap; + unsigned char Octet; + for ( y = 0; y < NbLignes; y++ ) + { + AdrBitmap = TAILLE_CPC_X * ( y + ( ( 200 - NbLignes ) >> 1 ) ) + + ( ( ( 80 - NbCol ) >> 1 ) << 3 ); + for ( x = 0; x < NbCol; x++ ) + { + Octet = BitmapCPC[ AdrCPC + x ]; + switch( Mode ) + { + case 0 : + case 3 : // Mode 3 = Mode 0 + p0 = ( Octet >> 7 ) + + ( ( Octet & 0x20 ) >> 3 ) + + ( ( Octet & 0x08 ) >> 2 ) + + ( ( Octet & 0x02 ) << 2 ); + p1 = ( ( Octet & 0x40 ) >> 6 ) + + ( ( Octet & 0x10 ) >> 2 ) + + ( ( Octet & 0x04 ) >> 1 ) + + ( ( Octet & 0x01 ) << 3 ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p0 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p0 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p0 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p0 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p1 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p1 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p1 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p1 ] ); + break; + + case 1 : + p0 = ( ( Octet >> 7 ) & 1 ) + ( ( Octet >> 2 ) & 2 ); + p1 = ( ( Octet >> 6 ) & 1 ) + ( ( Octet >> 1 ) & 2 ); + p2 = ( ( Octet >> 5 ) & 1 ) + ( ( Octet >> 0 ) & 2 ); + p3 = ( ( Octet >> 4 ) & 1 ) + ( ( Octet << 1 ) & 2 ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p0 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p0 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p1 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p1 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p2 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p2 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p3 ] ); + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p3 ] ); + break; + + case 2 : + for ( i = 8; i--; ) + Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ ( Octet >> i ) & 1 ] ); + break; + } + } + if ( Flat ) + AdrCPC += NbCol; + else + { + AdrCPC += 0x800; + if ( AdrCPC > 0x3FFF ) + AdrCPC -= 0x3FB0; + } + } +} + + +void SetBitmapCPC( unsigned char * BitmapSource ) +{ + memcpy( BitmapCPC, BitmapSource, 0x4000 ); + if ( ! strncmp( ( char * )BitmapCPC, "MJH", 3 ) ) + DepactOCP(); + + InitPalette( NULL, FALSE ); +} + + +void SetNbCol( int n ) +{ + if ( n > 0 && n <= 80 ) + NbCol = n; +} + + +void SetNbLignes( int n ) +{ + if ( n > 0 && n <= 200 ) + NbLignes = n; +} diff --git a/tools/iDSK/src/BitmapCPC.h b/tools/iDSK/src/BitmapCPC.h new file mode 100644 index 0000000..d18d808 --- /dev/null +++ b/tools/iDSK/src/BitmapCPC.h @@ -0,0 +1,46 @@ +#ifndef BITMAPCPC_H +#define BITMAPCPC_H + + +#define TAILLE_CPC_X 640 + +#define TAILLE_CPC_Y 200 + +#define MARKER_OCP 1 // Marker pour compression RLE +int Mode, NbCol, NbLignes; +unsigned char BitmapCPC[ 0x4000 ]; +unsigned char Palette[ 16 ]; +typedef struct + { + unsigned char b, v, r, a; + } StRVB; + + + +void CBitmapCPC( void ) { NbCol = 80; NbLignes = 200; } +bool LireImage( char * Nom, StRVB * Bitmap ); +void Render( StRVB * Bitmap, bool Flat ); +void SetBitmapCPC( unsigned char * BitmapSource ); +unsigned char * GetBitmapCPC( void ) { return( BitmapCPC ); } +void SetMode( int m ) { Mode = m; } +void InitPalette( unsigned char Pal[ 16 ], bool SetPal ); +unsigned char * GetPalette( void ) { return( Palette ); } +int GetMode( void ) { return( Mode ); } +void SetNbCol( int n ); +void SetNbLignes( int n ); + + +void DepactOCP( void ); +void LisseBitmap( StRVB * Bitmap ); + + + + + + +StRVB GetPalCPC( int Coul ); + +int GetRgbCPC( int Coul ); + + +#endif diff --git a/tools/iDSK/src/Dams.cpp b/tools/iDSK/src/Dams.cpp new file mode 100644 index 0000000..52cad9b --- /dev/null +++ b/tools/iDSK/src/Dams.cpp @@ -0,0 +1,184 @@ +#include <iostream> +#include <cstdio> +#include <cstring> +using namespace std; + + +// +// Convertir le buffer en listing au format Dams +// Adaptation des sources de Thierry JOUIN ( Ramlaid ) +// +void Dams( unsigned char * BufFile, int TailleFic, char * Listing ) +{ + const char * MotCleDams[ 0x80 ] = + { + "LD","INC","DEC","ADD","ADC","SUB","SBC","AND","XOR","OR","CP", + "PUSH","POP","BIT","RES","SET","RLC","RRC","RL","RR","SLA","SRA", + "SRL","IN","OUT","RST","DJNZ","EX","IM","JR","CALL","RET","JP", + "NOP","RLCA","RRCA","RLA","RRA","DAA","CPL","SCF","CCF","HALT", + "EXX","DI","EI","NEG","RETN","RETI","RRD","RLD","LDI","CPI","INI", + "OUTI","LDD","CPD","IND","OUTD","LDIR","CPIR","INIR","OTIR","LDDR", + "CPDR","INDR","OTDR","DB","DW","DM","DS","EQU","ORG","ENT", + "IF","ELSE","END" + }; + char Tmp[ 32 ]; + int PosFile = 0; + int PosDest = 0; + unsigned char c; + + * Listing = 0; + c = BufFile[ PosFile++ ]; + while( c ) + { + if ( c == 0xFF ) + { + // Commentaire ligne + Listing[ PosDest++ ] = ';'; + c = BufFile[ PosFile++ ]; + while( c != 0x0D && PosFile < TailleFic ) + { + Listing[ PosDest++ ] = c; + c = BufFile[ PosFile++ ]; + } + Listing[ PosDest++ ] = '\r'; + Listing[ PosDest++ ] = '\n'; + } + else + { + if ( c >= 0x80 && c != 0x0D ) + { + // Mnemonique sans label + // ENT + if ( c == 0xC9 ) + Listing[ PosDest++ ] = ';'; + + sprintf( Tmp, "\t%s\t", MotCleDams[ c & 0x7F ] ); + int l = strlen( Tmp ); + memcpy( &Listing[ PosDest ], Tmp, l ); + PosDest += l; + // DS ?,? + if ( c == 0xC6 ) + { + c = BufFile[ PosFile++ ]; + // Fin de ligne + while( c != 0x0D && PosFile < TailleFic ) + { + if ( c == ',' ) + { + while( c != 0x0D && c != 0xFF && PosFile < TailleFic ) + c = BufFile[ PosFile++ ]; + } + if ( c != 0x0D ) + { + if ( c == 0xFF ) + Listing[ PosDest++ ] = '\t'; + else + Listing[ PosDest++ ] = c; + + c = BufFile[ PosFile++ ]; + } + } + } + else + { + c = BufFile[ PosFile++ ]; + // Fin de ligne + while( c != 0x0D && PosFile < TailleFic ) + { + if ( c == 0xFF ) + Listing[ PosDest++ ] = '\t'; + else + Listing[ PosDest++ ] = c; + + c = BufFile[ PosFile++ ]; + } + } + Listing[ PosDest++ ] = '\r'; + Listing[ PosDest++ ] = '\n'; + } + else + { + // Label + while( c < 0x80 && c != 0x0D && PosFile < TailleFic ) + { + Listing[ PosDest++ ] = c; + c = BufFile[ PosFile++ ]; + } + if ( c != 0x0D ) + { + // Mnemonique apres label + // ENT + if ( c == 0xC9 ) + Listing[ PosDest++ ] = ';'; + + if ( c != 0xFF ) + { + sprintf( Tmp, "\t%s\t", MotCleDams[ c & 0x7F ] ); + int l = strlen( Tmp ); + memcpy( &Listing[ PosDest ], Tmp, l ); + PosDest += l; + } + else + { + Listing[ PosDest++ ] = '\t'; + Listing[ PosDest++ ] = '\t'; + Listing[ PosDest++ ] = '\t'; + } + // DS ?,? + if ( c == 0xC6 ) + { + c = BufFile[ PosFile++ ]; + // Fin de ligne + while( c != 0x0D && PosFile < TailleFic ) + { + if ( c == ',' ) + { + while( c != 0x0D && c != 0xFF && PosFile < TailleFic ) + c = BufFile[ PosFile++ ]; + } + if ( c != 0x0D ) + { + if ( c == 0xFF ) + { + Listing[ PosDest++ ] = '\t'; + Listing[ PosDest++ ] = ';'; + } + else + Listing[ PosDest++ ] = c; + + c = BufFile[ PosFile++ ]; + } + } + } + else + { + c = BufFile[ PosFile++ ]; + // Fin de ligne + while( c != 0x0D && PosFile < TailleFic ) + { + if ( c == 0xFF ) + { + Listing[ PosDest++ ] = '\t'; + Listing[ PosDest++ ] = ';'; + } + else + Listing[ PosDest++ ] = c; + + c = BufFile[ PosFile++ ]; + } + } + Listing[ PosDest++ ] = '\r'; + Listing[ PosDest++ ] = '\n'; + } + else + { + Listing[ PosDest++ ] = '\r'; + Listing[ PosDest++ ] = '\n'; + } + } + } + c = BufFile[ PosFile++ ]; + if ( PosFile > TailleFic ) + break; + } +} diff --git a/tools/iDSK/src/Dams.h b/tools/iDSK/src/Dams.h new file mode 100644 index 0000000..65dfa9b --- /dev/null +++ b/tools/iDSK/src/Dams.h @@ -0,0 +1,8 @@ +#ifndef DAMS_H +#define DAMS_H + + +void Dams( unsigned char * BufFile, int TailleFic, char * Listing ); + + +#endif diff --git a/tools/iDSK/src/Desass.cpp b/tools/iDSK/src/Desass.cpp new file mode 100644 index 0000000..171c636 --- /dev/null +++ b/tools/iDSK/src/Desass.cpp @@ -0,0 +1,553 @@ +#include <iostream> +#include <cstdio> +#include <cstring> + +#include "Outils.h" +using namespace std; + +// Vecteurs du Firmware CPC +#include "firmware.h" + +// +// Tableau des OP-Codes Z80... +// +const char * const TabInstrCB[ 256 ] = + { + "RLC B","RLC C","RLC D","RLC E", + "RLC H","RLC L","RLC (HL)","RLC A", + "RRC B","RRC C","RRC D","RRC E", + "RRC H","RRC L","RRC (HL)","RRC A", + "RL B","RL C","RL D","RL E", + "RL H","RL L","RL (HL)","RL A", + "RR B","RR C","RR D","RR E", + "RR H","RR L","RR (HL)","RR A", + "SLA B","SLA C","SLA D","SLA E", + "SLA H","SLA L","SLA (HL)","SLA A", + "SRA B","SRA C","SRA D","SRA E", + "SRA H","SRA L","SRA (HL)","SRA A", + "SLL B","SLL C","SLL D","SLL E", + "SLL H","SLL L","SLL (HL)","SLL A", + "SRL B","SRL C","SRL D","SRL E", + "SRL H","SRL L","SRL (HL)","SRL A", + "BIT 0,B","BIT 0,C","BIT 0,D","BIT 0,E", + "BIT 0,H","BIT 0,L","BIT 0,(HL)","BIT 0,A", + "BIT 1,B","BIT 1,C","BIT 1,D","BIT 1,E", + "BIT 1,H","BIT 1,L","BIT 1,(HL)","BIT 1,A", + "BIT 2,B","BIT 2,C","BIT 2,D","BIT 2,E", + "BIT 2,H","BIT 2,L","BIT 2,(HL)","BIT 2,A", + "BIT 3,B","BIT 3,C","BIT 3,D","BIT 3,E", + "BIT 3,H","BIT 3,L","BIT 3,(HL)","BIT 3,A", + "BIT 4,B","BIT 4,C","BIT 4,D","BIT 4,E", + "BIT 4,H","BIT 4,L","BIT 4,(HL)","BIT 4,A", + "BIT 5,B","BIT 5,C","BIT 5,D","BIT 5,E", + "BIT 5,H","BIT 5,L","BIT 5,(HL)","BIT 5,A", + "BIT 6,B","BIT 6,C","BIT 6,D","BIT 6,E", + "BIT 6,H","BIT 6,L","BIT 6,(HL)","BIT 6,A", + "BIT 7,B","BIT 7,C","BIT 7,D","BIT 7,E", + "BIT 7,H","BIT 7,L","BIT 7,(HL)","BIT 7,A", + "RES 0,B","RES 0,C","RES 0,D","RES 0,E", + "RES 0,H","RES 0,L","RES 0,(HL)","RES 0,A", + "RES 1,B","RES 1,C","RES 1,D","RES 1,E", + "RES 1,H","RES 1,L","RES 1,(HL)","RES 1,A", + "RES 2,B","RES 2,C","RES 2,D","RES 2,E", + "RES 2,H","RES 2,L","RES 2,(HL)","RES 2,A", + "RES 3,B","RES 3,C","RES 3,D","RES 3,E", + "RES 3,H","RES 3,L","RES 3,(HL)","RES 3,A", + "RES 4,B","RES 4,C","RES 4,D","RES 4,E", + "RES 4,H","RES 4,L","RES 4,(HL)","RES 4,A", + "RES 5,B","RES 5,C","RES 5,D","RES 5,E", + "RES 5,H","RES 5,L","RES 5,(HL)","RES 5,A", + "RES 6,B","RES 6,C","RES 6,D","RES 6,E", + "RES 6,H","RES 6,L","RES 6,(HL)","RES 6,A", + "RES 7,B","RES 7,C","RES 7,D","RES 7,E", + "RES 7,H","RES 7,L","RES 7,(HL)","RES 7,A", + "SET 0,B","SET 0,C","SET 0,D","SET 0,E", + "SET 0,H","SET 0,L","SET 0,(HL)","SET 0,A", + "SET 1,B","SET 1,C","SET 1,D","SET 1,E", + "SET 1,H","SET 1,L","SET 1,(HL)","SET 1,A", + "SET 2,B","SET 2,C","SET 2,D","SET 2,E", + "SET 2,H","SET 2,L","SET 2,(HL)","SET 2,A", + "SET 3,B","SET 3,C","SET 3,D","SET 3,E", + "SET 3,H","SET 3,L","SET 3,(HL)","SET 3,A", + "SET 4,B","SET 4,C","SET 4,D","SET 4,E", + "SET 4,H","SET 4,L","SET 4,(HL)","SET 4,A", + "SET 5,B","SET 5,C","SET 5,D","SET 5,E", + "SET 5,H","SET 5,L","SET 5,(HL)","SET 5,A", + "SET 6,B","SET 6,C","SET 6,D","SET 6,E", + "SET 6,H","SET 6,L","SET 6,(HL)","SET 6,A", + "SET 7,B","SET 7,C","SET 7,D","SET 7,E", + "SET 7,H","SET 7,L","SET 7,(HL)","SET 7,A" + }; + + +const char * const TabInstrED[ 256 ] = + { + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + "IN B,(C)","OUT (C),B","SBC HL,BC","LD (nnnn),BC", + "NEG","RETN","IM 0","LD I,A", + "IN C,(C)","OUT (C),C","ADC HL,BC","LD BC,(nnnn)", + 0,"RETI",0,"LD R,A", + "IN D,(C)","OUT (C),D","SBC HL,DE","LD (nnnn),DE", + 0,0,"IM 1","LD A,I", + "IN E,(C)","OUT (C),E","ADC HL,DE","LD DE,(nnnn)", + 0,0,"IM 2","LD A,R", + "IN H,(C)","OUT (C),H","SBC HL,HL",0, + 0,0,0,"RRD", + "IN L,(C)","OUT (C),L","ADC HL,HL",0, + 0,0,0,"RLD", + 0,"OUT (C),0","SBC HL,SP","LD (nnnn),SP", + 0,0,0,0, + "IN A,(C)","OUT (C),A","ADC HL,SP","LD SP,(nnnn)", + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + "LDI","CPI","INI","OUTI", + 0,0,0,0, + "LDD","CPD","IND","OUTD", + 0,0,0,0, + "LDIR","CPIR","INIR","OTIR", + 0,0,0,0, + "LDDR","CPDR","INDR","OTDR", + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0 + }; + + +const char * const TabInstrDD[ 256 ] = + { + 0,0,0,0, + 0,0,0,0, + 0,"ADD IX,BC",0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,"ADD IX,DE",0,0, + 0,0,0,0, + 0,"LD IX,nnnn","LD (nnnn),IX","INC IX", + "INC IXh","DEC IXh","LD IXh,nn",0, + 0,"ADD IX,HL","LD IX,(nnnn)","DEC IX", + "INC IXl","DEC IXl","LD IXl,nn",0, + 0,0,0,0, + "INC (IX+nn)","DEC (IX+nn)","LD (IX+nn),nn",0, + 0,"ADD IX,SP",0,0, + 0,0,0,0, + 0,0,0,0, + "LD B,IXh","LD B,IXl","LD B,(IX+nn)",0, + 0,0,0,0, + "LD C,IXh","LD C,IXl","LD C,(IX+nn)",0, + 0,0,0,0, + "LD D,IXh","LD D,IXl","LD D,(IX+nn)",0, + 0,0,0,0, + "LD E,IXh","LD E,IXl","LD E,(IX+nn)",0, + "LD IXh,B","LD IXh,C","LD IXh,D","LD IXh,E", + "LD IXh,IXh","LD IXh,IXl","LD H,(IX+nn)","LD IXh,A", + "LD IXl,B","LD IXl,C","LD IXl,D","LD IXl,E", + "LD IXl,IXh","LD IXl,IXl","LD L,(IX+nn)","LD IXl,A", + "LD (IX+nn),B","LD (IX+nn),C","LD (IX+nn),D","LD (IX+nn),E", + "LD (IX+nn),H","LD (IX+nn),L",0,"LD (IX+nn),A", + 0,0,0,0, + "LD A,IXh","LD A,IXl","LD A,(IX+nn)",0, + 0,0,0,0, + "ADD A,IXh","ADD A,IXl","ADD A,(IX+nn)",0, + 0,0,0,0, + "ADC A,IXh","ADC A,IXl","ADC A,(IX+nn)",0, + 0,0,0,0, + "SUB IXh","SUB IXl","SUB (IX+nn)",0, + 0,0,0,0, + "SBC A,IXh","SBC A,IXl","SBC A,(IX+nn)",0, + 0,0,0,0, + "AND IXh","AND IXl","AND (IX+nn)",0, + 0,0,0,0, + "XOR IXh","XOR IXl","XOR (IX+nn)",0, + 0,0,0,0, + "OR IXh","OR IXl","OR (IX+nn)",0, + 0,0,0,0, + "CP IXh","CP IXl","CP (IX+nn)",0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,"POP IX",0,"EX (SP),IX", + 0,"PUSH IX",0,0, + 0,"JP (IX)",0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,"LD SP,IX",0,0, + 0,0,0,0 + }; + + +const char * const TabInstrDDCB[ 256 ] = + { + 0,0,0,0,0,0,"RLC (IX+nn)",0, + 0,0,0,0,0,0,"RRC (IX+nn)",0, + 0,0,0,0,0,0,"RL (IX+nn)",0, + 0,0,0,0,0,0,"RR (IX+nn)",0, + 0,0,0,0,0,0,"SLA (IX+nn)",0, + 0,0,0,0,0,0,"SRA (IX+nn)",0, + 0,0,0,0,0,0,"SLL (IX+nn)",0, + 0,0,0,0,0,0,"SRL (IX+nn)",0, + 0,0,0,0,0,0,"BIT 0,(IX+nn)",0, + 0,0,0,0,0,0,"BIT 1,(IX+nn)",0, + 0,0,0,0,0,0,"BIT 2,(IX+nn)",0, + 0,0,0,0,0,0,"BIT 3,(IX+nn)",0, + 0,0,0,0,0,0,"BIT 4,(IX+nn)",0, + 0,0,0,0,0,0,"BIT 5,(IX+nn)",0, + 0,0,0,0,0,0,"BIT 6,(IX+nn)",0, + 0,0,0,0,0,0,"BIT 7,(IX+nn)",0, + 0,0,0,0,0,0,"RES 0,(IX+nn)",0, + 0,0,0,0,0,0,"RES 1,(IX+nn)",0, + 0,0,0,0,0,0,"RES 2,(IX+nn)",0, + 0,0,0,0,0,0,"RES 3,(IX+nn)",0, + 0,0,0,0,0,0,"RES 4,(IX+nn)",0, + 0,0,0,0,0,0,"RES 5,(IX+nn)",0, + 0,0,0,0,0,0,"RES 6,(IX+nn)",0, + 0,0,0,0,0,0,"RES 7,(IX+nn)",0, + 0,0,0,0,0,0,"SET 0,(IX+nn)",0, + 0,0,0,0,0,0,"SET 1,(IX+nn)",0, + 0,0,0,0,0,0,"SET 2,(IX+nn)",0, + 0,0,0,0,0,0,"SET 3,(IX+nn)",0, + 0,0,0,0,0,0,"SET 4,(IX+nn)",0, + 0,0,0,0,0,0,"SET 5,(IX+nn)",0, + 0,0,0,0,0,0,"SET 6,(IX+nn)",0, + 0,0,0,0,0,0,"SET 7,(IX+nn)",0 + }; + + +const char * const TabInstrFD[ 256 ] = + { + 0,0,0,0,0,0,0,0, + 0,"ADD IY,BC",0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,"ADD IY,DE",0,0,0,0,0,0, + 0,"LD IY,nnnn","LD (nnnn),IY","INC IY","INC IYh","DEC IYh","LD IYh,nn",0, + 0,"ADD IY,HL","LD IY,(nnnn)","DEC IY","INC IYl","DEC IYl","LD IYl,nn",0, + 0,0,0,0,"INC (IY+nn)","DEC (IY+nn)","LD (IY+nn),nn",0, + 0,"ADD IY,SP",0,0,0,0,0,0, + 0,0,0,0,"LD B,IYh","LD B,IYl","LD B,(IY+nn)",0, + 0,0,0,0,"LD C,IYh","LD C,IYl","LD C,(IY+nn)",0, + 0,0,0,0,"LD D,IYh","LD D,IYl","LD D,(IY+nn)",0, + 0,0,0,0,"LD E,IYh","LD E,IYl","LD E,(IY+nn)",0, + "LD IYh,B","LD IYh,C","LD IYh,D","LD IYh,E","LD IYh,IYh","LD IYh,IYl","LD H,(IY+nn)","LD IYh,A", + "LD IYl,B","LD IYl,C","LD IYl,D","LD IYl,E","LD IYl,IYh","LD IYl,IYl","LD L,(IY+nn)","LD IYl,A", + "LD (IY+nn),B","LD (IY+nn),C","LD (IY+nn),D","LD (IY+nn),E","LD (IY+nn),H","LD (IY+nn),L",0,"LD (IY+nn),A", + 0,0,0,0,"LD A,IYh","LD A,IYl","LD A,(IY+nn)",0, + 0,0,0,0,"ADD A,IYh","ADD A,IYl","ADD A,(IY+nn)",0, + 0,0,0,0,"ADC A,IYh","ADC A,IYl","ADC A,(IY+nn)",0, + 0,0,0,0,"SUB IYh","SUB IYl","SUB (IY+nn)",0, + 0,0,0,0,"SBC A,IYh","SBC A,IYl","SBC A,(IY+nn)",0, + 0,0,0,0,"AND IYh","AND IYl","AND (IY+nn)",0, + 0,0,0,0,"XOR IYh","XOR IYl","XOR (IY+nn)",0, + 0,0,0,0,"OR IYh","OR IYl","OR (IY+nn)",0, + 0,0,0,0,"CP IYh","CP IYl","CP (IY+nn)",0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,"POP IY",0,"EX (SP),IY",0,"PUSH IY",0,0, + 0,"JP (IY)",0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,"LD SP,IY",0,0,0,0,0,0 + }; + + +const char * const TabInstrFDCB[ 256 ] = + { + 0,0,0,0,0,0,"RLC (IY+nn)",0, + 0,0,0,0,0,0,"RRC (IY+nn)",0, + 0,0,0,0,0,0,"RL (IY+nn)",0, + 0,0,0,0,0,0,"RR (IY+nn)",0, + 0,0,0,0,0,0,"SLA (IY+nn)",0, + 0,0,0,0,0,0,"SRA (IY+nn)",0, + 0,0,0,0,0,0,"SLL (IY+nn)",0, + 0,0,0,0,0,0,"SRL (IY+nn)",0, + 0,0,0,0,0,0,"BIT 0,(IY+nn)",0, + 0,0,0,0,0,0,"BIT 1,(IY+nn)",0, + 0,0,0,0,0,0,"BIT 2,(IY+nn)",0, + 0,0,0,0,0,0,"BIT 3,(IY+nn)",0, + 0,0,0,0,0,0,"BIT 4,(IY+nn)",0, + 0,0,0,0,0,0,"BIT 5,(IY+nn)",0, + 0,0,0,0,0,0,"BIT 6,(IY+nn)",0, + 0,0,0,0,0,0,"BIT 7,(IY+nn)",0, + 0,0,0,0,0,0,"RES 0,(IY+nn)",0, + 0,0,0,0,0,0,"RES 1,(IY+nn)",0, + 0,0,0,0,0,0,"RES 2,(IY+nn)",0, + 0,0,0,0,0,0,"RES 3,(IY+nn)",0, + 0,0,0,0,0,0,"RES 4,(IY+nn)",0, + 0,0,0,0,0,0,"RES 5,(IY+nn)",0, + 0,0,0,0,0,0,"RES 6,(IY+nn)",0, + 0,0,0,0,0,0,"RES 7,(IY+nn)",0, + 0,0,0,0,0,0,"SET 0,(IY+nn)",0, + 0,0,0,0,0,0,"SET 1,(IY+nn)",0, + 0,0,0,0,0,0,"SET 2,(IY+nn)",0, + 0,0,0,0,0,0,"SET 3,(IY+nn)",0, + 0,0,0,0,0,0,"SET 4,(IY+nn)",0, + 0,0,0,0,0,0,"SET 5,(IY+nn)",0, + 0,0,0,0,0,0,"SET 6,(IY+nn)",0, + 0,0,0,0,0,0,"SET 7,(IY+nn)",0 + }; + + +const char * const TabInstr[ 256 ] = + { + "NOP","LD BC,nnnn","LD (BC),A","INC BC", + "INC B","DEC B","LD B,nn","RLCA", + "EX AF,AF","ADD HL,BC","LD A,(BC)","DEC BC", + "INC C","DEC C","LD C,nn","RRCA", + "DJNZ eeee","LD DE,nnnn","LD (DE),A","INC DE", + "INC D","DEC D","LD D,nn","RLA", + "JR eeee","ADD HL,DE","LD A,(DE)","DEC DE", + "INC E","DEC E","LD E,nn","RRA", + "JR NZ,eeee","LD HL,nnnn","LD (nnnn),HL","INC HL", + "INC H","DEC H","LD H,nn","DAA", + "JR Z,eeee","ADD HL,HL","LD HL,(nnnn)","DEC HL", + "INC L","DEC L","LD L,nn","CPL", + "JR NC,eeee","LD SP,nnnn","LD (nnnn),A","INC SP", + "INC (HL)","DEC (HL)","LD (HL),nn","SCF", + "JR C,eeee","ADD HL,SP","LD A,(nnnn)","DEC SP", + "INC A","DEC A","LD A,nn","CCF", + "LD B,B","LD B,C","LD B,D","LD B,E", + "LD B,H","LD B,L","LD B,(HL)","LD B,A", + "LD C,B","LD C,C","LD C,D","LD C,E", + "LD C,H","LD C,L","LD C,(HL)","LD C,A", + "LD D,B","LD D,C","LD D,D","LD D,E", + "LD D,H","LD D,L","LD D,(HL)","LD D,A", + "LD E,B","LD E,C","LD E,D","LD E,E", + "LD E,H","LD E,L","LD E,(HL)","LD E,A", + "LD H,B","LD H,C","LD H,D","LD H,E", + "LD H,H","LD H,L","LD H,(HL)","LD H,A", + "LD L,B","LD L,C","LD L,D","LD L,E", + "LD L,H","LD L,L","LD L,(HL)","LD L,A", + "LD (HL),B","LD (HL),C","LD (HL),D","LD (HL),E", + "LD (HL),H","LD (HL),L","HALT","LD (HL),A", + "LD A,B","LD A,C","LD A,D","LD A,E", + "LD A,H","LD A,L","LD A,(HL)","LD A,A", + "ADD A,B","ADD A,C","ADD A,D","ADD A,E", + "ADD A,H","ADD A,L","ADD A,(HL)","ADD A,A", + "ADC A,B","ADC A,C","ADC A,D","ADC A,E", + "ADC A,H","ADC A,L","ADC A,(HL)","ADC A,A", + "SUB B","SUB C","SUB D","SUB E", + "SUB H","SUB L","SUB (HL)","SUB A", + "SBC A,B","SBC A,C","SBC A,D","SBC A,E", + "SBC A,H","SBC A,L","SBC A,(HL)","SBC A,A", + "AND B","AND C","AND D","AND E", + "AND H","AND L","AND (HL)","AND A", + "XOR B","XOR C","XOR D","XOR E", + "XOR H","XOR L","XOR (HL)","XOR A", + "OR B","OR C","OR D","OR E", + "OR H","OR L","OR (HL)","OR A", + "CP B","CP C","CP D","CP E", + "CP H","CP L","CP (HL)","CP A", + "RET NZ","POP BC","JP NZ,nnnn","JP nnnn", + "CALL NZ,nnnn","PUSH BC","ADD A,nn","RST 00", + "RET Z","RET","JP Z,nnnn",0, + "CALL Z,nnnn","CALL nnnn","ADC A,nn","RST 08", + "RET NC","POP DE","JP NC,nnnn","OUT (nn),A", + "CALL NC,nnnn","PUSH DE","SUB nn","RST 10", + "RET C","EXX","JP C,nnnn","IN A,(nn)", + "CALL C,nnnn",0,"SBC A,nn","RST 18", + "RET PE","POP HL","JP PE,nnnn","EX (SP),HL", + "CALL PE,nnnn","PUSH HL","AND nn","RST 20", + "RET PO","JP (HL)","JP PO,nnnn","EX DE,HL", + "CALL PO,nnnn",0,"XOR nn","RST 28", + "RET P","POP AF","JP P,nnnn","DI", + "CALL P,nnnn","PUSH AF","OR nn","RST 30", + "RET M","LD SP,HL","JP M,nnnn","EI", + "CALL M,nnnn",0,"CP nn","RST 38" + }; + +const char * GetFirmWareVectorName(unsigned short address) +{ + for (int i = 0; FirmWareVectors[i].label; i++) { + if (FirmWareVectors[i].address == address) + return FirmWareVectors[i].label; + } + return NULL; +} + +// +// Convertir le buffer en listing désassemblé +// +void Desass( unsigned char * Prg, char * Listing, int Longueur, int Offset ) +{ + int i, Instr, Inst2 = 0, Inst3 = 0, Inst4 = 0, Ad16; + const char * Chaine; + char *p; + char Inst[ 1024 ]; + + int Adr, OldAdr, PosD = 0; + char Ad8; + + * Listing = 0; + for ( Adr = 0; Adr < Longueur; ) + { + OldAdr = Adr; + Instr = Prg[ Adr++ ]; + Chaine = TabInstr[ Instr ]; + if ( Instr == 0xCB ) + { + Inst2 = Prg[ Adr++ ]; + Chaine = TabInstrCB[ Inst2 ]; + } + else + if ( Instr == 0xDD ) + { + Inst2 = Prg[ Adr++ ]; + if ( Inst2 == 0xCB ) + { + Inst3 = Prg[ Adr++ ]; + Inst4 = Prg[ Adr++ ]; + Chaine = TabInstrDDCB[ Inst4 ]; + strcpy( Inst, Chaine ); + p = strstr( Inst, "nn" ); + if ( p ) + { + if ( Inst3 < 0x80 ) + Hex( p, Inst3, 2 ); + else + { + Hex( p, -Inst3, 2 ); + p[ -1 ] = '-'; + } + } + Chaine = Inst; + } + else + Chaine = TabInstrDD[ Inst2 ]; + } + else + if ( Instr == 0xED ) + { + Inst2 = Prg[ Adr++ ]; + Chaine = TabInstrED[ Inst2 ]; + } + else + if ( Instr == 0xFD ) + { + Inst2 = Prg[ Adr++ ]; + if ( Inst2 == 0xCB ) + { + Ad8 = Prg[ Adr++ ]; + Inst3 = Prg[ Adr++ ]; + Chaine = TabInstrFDCB[ Inst3 ]; + if ( Chaine ) + { + strcpy( Inst, Chaine ); + Chaine = Inst; + p = strstr( Inst, "nn" ); + if ( p ) + Hex( p, Ad8, 2 ); + } + } + else + Chaine = TabInstrFD[ Inst2 ]; + } + if ( Chaine ) + { + strcpy( Inst, Chaine ); + p = strstr( Inst, "nnnn" ); + Ad16 = Prg[ Adr++ ]; + Ad16 += Prg[ Adr ] << 8; + Ad8 = ( char ) Ad16; + if ( p ) + { + Hex( p, Ad16, 4 ); + Adr++; + const char * label = GetFirmWareVectorName( Ad16 ); + if (label && 0 == memcmp( Inst, "CALL", 4)) + { + p[4] = ' '; + p[5] = ' '; + p[6] = ' '; + p[7] = ' '; + p[8] = ';'; + p[9] = ' '; + strcpy(p + 10, label); + } + } + else + { + p = strstr( Inst, "nn" ); + if ( p ) + { + Hex( p, Ad16, 2 ); + p = strstr( Inst, "nn" ); + if ( p ) + Hex( p, Ad16 >> 8, 2 ); + } + else + { + p = strstr( Inst, "eeee" ); + if ( p ) + Hex( p, Adr + Ad8 + Offset, 4 ); + else + Adr--; + } + } + } + else + sprintf( Inst, "%02X %02X %02X ????", Instr, Inst2, Inst3 ); + + Hex( &Listing[ PosD ], OldAdr + Offset, 4 ); // current address + Listing[ PosD + 4 ] = ' '; + PosD += 5; + for ( i = OldAdr; i < Adr; i++ ) + { + Hex( &Listing[ PosD ], Prg[ i ], 2 ); + Listing[ PosD + 2 ] = ' '; + PosD += 3; + } + for ( i = 0; i < 5 - Adr + OldAdr; i++ ) + { + Listing[ PosD ] = Listing[ PosD + 1 ] = Listing[ PosD + 2 ] = ' '; + PosD += 3; + } + const char * p = Inst; + while( * p ) + Listing[ PosD++ ] = * p++; + + Listing[ PosD++ ] = '\r'; + Listing[ PosD++ ] = '\n'; + } +} diff --git a/tools/iDSK/src/Desass.h b/tools/iDSK/src/Desass.h new file mode 100644 index 0000000..4df1b82 --- /dev/null +++ b/tools/iDSK/src/Desass.h @@ -0,0 +1,8 @@ +#ifndef DESASS_H +#define DESASS_H + + +void Desass( unsigned char * Prg, char * Desass, int Longueur, int Offset ); + + +#endif diff --git a/tools/iDSK/src/GestDsk.cpp b/tools/iDSK/src/GestDsk.cpp new file mode 100644 index 0000000..99b69d8 --- /dev/null +++ b/tools/iDSK/src/GestDsk.cpp @@ -0,0 +1,1173 @@ +#include <iostream> +#include <string.h> +#include <cstdlib> +#include <cstdio> +#include <algorithm> +#include <sstream> + +#include "MyType.h" +#include "GestDsk.h" +#include "endianPPC.h" +#include "Outils.h" +#include <cerrno> + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +using namespace std; + +char Listing[ 0x280000 ]; +unsigned char BufFile[ 0x10000 ]; +int TailleFic, CurLigne, AdresseCharg, AdresseExec; + + +// +// Verifie si en-tete AMSDOS est valide +// +bool CheckAmsdos( unsigned char * Buf ) { + int i, Checksum = 0; + bool ModeAmsdos = false; + unsigned short CheckSumFile; + CheckSumFile = Buf[ 0x43 ] + Buf[ 0x43 +1 ] *256; + for ( i = 0; i < 67; i++ ) + Checksum += Buf[ i ]; + + if ( ( CheckSumFile == ( unsigned short )Checksum ) && Checksum ) + ModeAmsdos = true; + + return( ModeAmsdos ); +} + + + +// +// Cr�e une en-t�te AMSDOS par d�faut +// +StAmsdos * CreeEnteteAmsdos( char * NomFic, unsigned short Longueur ) { + static char NomReel[ 256 ]; + static StAmsdos Entete; + static char Nom[ 12 ]; + int i; + + strcpy( NomReel, NomFic ); + memset( &Entete, 0, sizeof( Entete ) ); + memset( Nom, ' ', sizeof( Nom ) ); + char * p = NULL; + do { + p = strchr( NomReel, '/' ); //Sous linux c'est le / qu'il faut enlever ... + if ( p ) + strcpy( NomReel, ++p ); + } while( p ); + p = strchr( NomReel, '.' ); + if ( p ) + * p++ = 0; + + int l = strlen( NomReel ); + if ( l > 8 ) + l = 8; + + for ( int i = 0; i < l; i++ ) + Nom[ i ] = ( char )toupper( NomReel[ i ] ); + + if ( p ) + for ( i = 0; i < 3; i++ ) + Nom[ i + 8 ] = ( char )toupper( p[ i ] ); + + memcpy( Entete.FileName, Nom, 11 ); + Entete.Length = 0; //Non renseign� par AMSDos !! + Entete.RealLength = Entete.LogicalLength = Longueur; + Entete.FileType = 2; //Fichier binaire + + SetChecksum(&Entete); + + return( &Entete ); +} + + +// +// Calcule et positionne le checksum AMSDOS +// +void SetChecksum( StAmsdos * pEntete ) { + int i, Checksum = 0; + unsigned char * p = ( unsigned char * )pEntete; + for ( i = 0; i < 67; i++ ) + Checksum += * (p+i); + + pEntete->CheckSum = ( unsigned short )Checksum; +} + + +// +// Effectue un "nettoyage" de l'en-tete Amsdos : +// remet a zero les octets inutilises +// +void ClearAmsdos( unsigned char * Buf ) { + if ( CheckAmsdos( Buf ) ) { + int i, Checksum = 0; + StAmsdos * pEntete = ( StAmsdos * )Buf; + memset( pEntete->Unused, 0, sizeof( pEntete->Unused ) ); + memset( pEntete->Unused2, 0, sizeof( pEntete->Unused2 ) ); + for ( i = 0; i < 67; i++ ) + Checksum += Buf[ i ]; + + Buf[ 0x43 ] = ( unsigned short )Checksum; + } +} + +// +// Recherche le plus petit secteur d'une piste +// +int DSK::GetMinSect( void ) { + int Sect = 0x100; + CPCEMUTrack * tr = ( CPCEMUTrack * )&ImgDsk[ sizeof( CPCEMUEnt ) ]; + for ( int s = 0; s < tr->NbSect; s++ ) + if ( Sect > tr->Sect[ s ].R ) + Sect = tr->Sect[ s ].R; + + return( Sect ); +} + + +// +// Retourne la position d'un secteur dans le fichier DSK +// +int DSK::GetPosData( int track, int sect, bool SectPhysique ) { + // Recherche position secteur + int Pos = sizeof( CPCEMUEnt ); + CPCEMUTrack * tr = ( CPCEMUTrack * )&ImgDsk[ Pos ]; + short SizeByte; + for ( int t = 0; t <= track; t++ ) { + Pos += sizeof( CPCEMUTrack ); + for ( int s = 0; s < tr->NbSect; s++ ) { + if ( t == track ) { + if ( ( ( tr->Sect[ s ].R == sect ) && SectPhysique ) + || ( ( s == sect ) && ! SectPhysique ) + ) + break; + } + SizeByte = tr->Sect[ s ].SizeByte ; + if (SizeByte) + Pos += SizeByte; + else + Pos += ( 128 << tr->Sect[ s ].N ); + } + } + return( Pos ); +} + + +// +// Recherche un bloc libre et le remplit +// +int DSK::RechercheBlocLibre( int MaxBloc ) { + for ( int i = 2; i < MaxBloc; i++ ) + if ( ! Bitmap[ i ] ) { + Bitmap[ i ] = 1; + return( i ); + } + return( 0 ); +} + + +// +// Recherche une entr�e de r�pertoire libre +// +int DSK::RechercheDirLibre( void ) { + for ( int i = 0; i < 64; i++ ) { + StDirEntry * Dir = GetInfoDirEntry( i ); + if ( Dir->User == USER_DELETED ) + return( i ); + } + return( -1 ); +} + + +// +// Retourne les donn�es "brutes" de l'image disquette +// +unsigned char * DSK::GetRawData( int Pos ) { + return( &ImgDsk[ Pos ] ); +} + + +// +// Ecriture de donn�es "brutes" dans l'image disquette +// +void DSK::WriteRawData( int Pos, unsigned char * Data, int Longueur ) { + memcpy( &ImgDsk[ Pos ], Data, Longueur ); +} + + +// +// Retourne la taille du fichier image +// +int DSK::GetTailleDsk( void ) { + CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk; + int NbTracks = Infos->NbTracks; + int Pos = sizeof( CPCEMUEnt ); + CPCEMUTrack * tr = ( CPCEMUTrack * )&ImgDsk[ Pos ]; + for ( int t = 0; t < NbTracks; t++ ) { + Pos += sizeof( CPCEMUTrack ); + for ( int s = 0; s < tr->NbSect; s++ ) { + if ( tr->Sect[ s ].SizeByte ) + Pos += tr->Sect[ s ].SizeByte; + else + Pos += ( 128 << tr->Sect[ s ].N ); + } + } + return( Pos ); +} + + +// +// Retourne le nombre de pistes de la disquette +// +int DSK::GetNbTracks( void ) { + CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk; + return( Infos->NbTracks ); +} + + +// +// Lecture d'un bloc AMSDOS (1 block = 2 secteurs) +// +unsigned char * DSK::ReadBloc( int bloc ) { + static unsigned char BufBloc[ SECTSIZE * 2 ]; + int track = ( bloc << 1 ) / 9; + int sect = ( bloc << 1 ) % 9; + int MinSect = GetMinSect(); + if ( MinSect == 0x41 ) + track += 2; + else + if ( MinSect == 0x01 ) + track++; + + int Pos = GetPosData( track, sect + MinSect, true ); + memcpy( BufBloc, &ImgDsk[ Pos ], SECTSIZE ); + if ( ++sect > 8 ) { + track++; + sect = 0; + } + + Pos = GetPosData( track, sect + MinSect, true ); + memcpy( &BufBloc[ SECTSIZE ], &ImgDsk[ Pos ], SECTSIZE ); + return( BufBloc ); +} + + +// +// Formatter une piste +// +void DSK::FormatTrack( CPCEMUEnt * Infos, int t, int MinSect, int NbSect ) { + CPCEMUTrack * tr = ( CPCEMUTrack * )&ImgDsk[ sizeof( CPCEMUEnt ) + t * Infos->DataSize ]; + memset( &ImgDsk[ sizeof( CPCEMUEnt ) + + sizeof( CPCEMUTrack ) + + ( t * Infos->DataSize ) + ] + , 0xE5 + , 0x200 * NbSect + ); + strcpy( tr->ID, "Track-Info\r\n" ); + tr->Track = ( unsigned char )t; + tr->Head = 0; + tr->SectSize = 2; + tr->NbSect = ( unsigned char )NbSect; + tr->Gap3 = 0x4E; + tr->OctRemp = 0xE5; + int ss = 0; + // + // Gestion "entrelacement" des secteurs + // + for ( int s = 0; s < NbSect; ) { + tr->Sect[ s ].C = ( unsigned char )t; + tr->Sect[ s ].H = 0; + tr->Sect[ s ].R = ( unsigned char )( ss + MinSect ); + tr->Sect[ s ].N = 2; + tr->Sect[ s ].SizeByte = 0x200; + ss++; + if ( ++s < NbSect ) { + tr->Sect[ s ].C = ( unsigned char )t; + tr->Sect[ s ].H = 0; + tr->Sect[ s ].R = ( unsigned char )( ss + MinSect + 4 ); + tr->Sect[ s ].N = 2; + tr->Sect[ s ].SizeByte = 0x200; + s++; + } + } +} + + +// +// Ecriture d'un bloc AMSDOS (1 block = 2 secteurs) +// +void DSK::WriteBloc( int bloc, unsigned char BufBloc[ SECTSIZE * 2 ] ) { + int track = ( bloc << 1 ) / 9; + int sect = ( bloc << 1 ) % 9; + int MinSect = GetMinSect(); + if ( MinSect == 0x41 ) + track += 2; + else + if ( MinSect == 0x01 ) + track++; + + // + // Ajuste le nombre de pistes si d�passement capacit� + // + CPCEMUEnt * Entete = ( CPCEMUEnt * )ImgDsk; + if ( track > Entete->NbTracks - 1 ) { + Entete->NbTracks = ( unsigned char )( track + 1 ); + FormatTrack( Entete, track, MinSect, 9 ); + } + + int Pos = GetPosData( track, sect + MinSect, true ); + memcpy( &ImgDsk[ Pos ], BufBloc, SECTSIZE ); + if ( ++sect > 8 ) { + track++; + sect = 0; + } + Pos = GetPosData( track, sect + MinSect, true ); + memcpy( &ImgDsk[ Pos ], &BufBloc[ SECTSIZE ], SECTSIZE ); +} + + +// +// Ecriture d'un secteur +// +void DSK::WriteSect( int Track, int Sect, unsigned char * Buff, int AmsdosMode ) { + int MinSect = AmsdosMode ? GetMinSect() : 0; + if ( ( MinSect == 0x41 ) && AmsdosMode ) + Track += 2; + else + if ( ( MinSect == 0x01 ) && AmsdosMode ) + Track++; + + int Pos = GetPosData( Track, Sect + MinSect, AmsdosMode ); + memcpy( &ImgDsk[ Pos ], Buff, SECTSIZE ); +} + + +// +// Lecture d'un secteur +// +unsigned char * DSK::ReadSect( int Track, int Sect, int AmsdosMode ) { + int MinSect = AmsdosMode ? GetMinSect() : 0; + if ( ( MinSect == 0x41 ) && AmsdosMode ) + Track += 2; + else + if ( ( MinSect == 0x01 ) && AmsdosMode ) + Track++; + + int Pos = GetPosData( Track, Sect + MinSect, AmsdosMode ); + return( &ImgDsk[ Pos ] ); +} + + +// +// Retourne les informations d'une piste +// +CPCEMUTrack * DSK::GetInfoTrack( int Track ) { + int Pos = sizeof( CPCEMUEnt ); + CPCEMUTrack * tr = ( CPCEMUTrack * )&ImgDsk[ Pos ]; + for ( int t = 0; t < Track; t++ ) { + Pos += sizeof( CPCEMUTrack ); + + for ( int s = 0; s < tr->NbSect; s++ ) { + if ( tr->Sect[ s ].SizeByte ) + Pos += tr->Sect[ s ].SizeByte; + else + Pos += ( 128 << tr->Sect[ s ].N ); + } + } + return( ( CPCEMUTrack * )&ImgDsk[ Pos ] ); +} + +// +// Remplit un "bitmap" pour savoir o� il y a des fichiers sur la disquette +// Retourne �galement le nombre de Ko utilis�s sur la disquette +// +int DSK::FillBitmap( void ) { + int NbKo = 0; + + memset( Bitmap, 0, sizeof( Bitmap ) ); + Bitmap[ 0 ] = Bitmap[ 1 ] = 1; + for ( int i = 0; i < 64; i++ ) { + StDirEntry * Dir = GetInfoDirEntry( i ); + if ( Dir->User != USER_DELETED ) { + for ( int j = 0; j < 16; j++ ) { + int b = Dir->Blocks[ j ]; + if ( b > 1 && ( ! Bitmap[ b ] ) ) { + Bitmap[ b ] = 1; + NbKo++; + } + } + } + } + return( NbKo ); +} + + +// +// Positionne une entr�e dans le r�pertoire +// +void DSK::SetInfoDirEntry( int NumDir, StDirEntry * Dir ) { + int MinSect = GetMinSect(); + int s = ( NumDir >> 4 ) + MinSect; + int t = ( MinSect == 0x41 ? 2 : 0 ); + if ( MinSect == 1 ) + t = 1; + + for (int i =0; i<16; i++) + memcpy( &ImgDsk[ ( ( NumDir & 15 ) << 5 ) + GetPosData( t, s, true ) ] + , Dir + , sizeof( StDirEntry ) + ); +} + + +// +// V�rifie l'existente d'un fichier, retourne l'indice du fichier si existe, +// -1 sinon +// +int DSK::FileExist( char * Nom ) { + int i; + for ( i = 0; i < 64; i++ ) { + StDirEntry * Dir = GetInfoDirEntry( i ); + for(int q=0;q<12;q++) + Dir->Nom[q]=Dir->Nom[q]&127; // Avoid missing hidden files + if ( Dir->User != USER_DELETED + && ! strncmp( Nom, ( char * )Dir->Nom, 11 ) // 11 = 8+3 car le point est enlev� + ) + return( i ); + } + return( -1 ); +} + + +StDirEntry * DSK::GetNomDir( string NomFic ) { + static StDirEntry DirLoc; + int i; + + memset( &DirLoc, 0, sizeof( DirLoc ) ); + memset( DirLoc.Nom, ' ', 8 ); + memset( DirLoc.Ext, ' ', 3 ); + size_t p = NomFic.find('.'); + if ( p!=std::string::npos ) + { + NomFic.copy( DirLoc.Nom, std::min((int)p,8), 0); + p++; + NomFic.copy( DirLoc.Ext, std::min( (int)(NomFic.size()-p), 3 ), p ); + } + else + NomFic.copy( DirLoc.Nom, std::min((int)NomFic.size(), 8 ),0); + + for ( i = 0; i < 11; i++ ) + DirLoc.Nom[ i ] = ( unsigned char )toupper( DirLoc.Nom[ i ] ); + + return( &DirLoc ); +} + + +int DSK::FileIsIn( string FileName ) { + StDirEntry * DirLoc = GetNomDir( FileName ); + return FileExist( ( char*) DirLoc->Nom ); +} + +// +// Copie un fichier sur le DSK +// +// la taille est determine par le nombre de NbPages +// regarder pourquoi different d'une autre DSK +int DSK::CopieFichier( unsigned char * BufFile, char * NomFic, int TailleFic, int MaxBloc, int UserNumber, bool System_file, bool Read_only ) { + int j, l, Bloc, PosFile, NbPages = 0, PosDir, TaillePage; + FillBitmap(); + StDirEntry * DirLoc = GetNomDir( NomFic ); //Construit l'entr�e pour mettre dans le catalogue + for ( PosFile = 0; PosFile < TailleFic; ) { //Pour chaque bloc du fichier + PosDir = RechercheDirLibre(); //Trouve une entr�e libre dans le CAT + if ( PosDir != -1 ) { + DirLoc->User = UserNumber; //Remplit l'entr�e : User 0 + // http://www.cpm8680.com/cpmtools/cpm.htm + if(System_file) DirLoc->Ext[1]|=0x80; + if(Read_only) DirLoc->Ext[0]|=0x80; + DirLoc->NumPage = ( unsigned char )NbPages++; // Num�ro de l'entr�e dans le fichier + TaillePage = (TailleFic - PosFile + 127) >> 7 ; // Taille de la page (on arrondit par le haut) + if ( TaillePage > 128 ) // Si y'a plus de 16k il faut plusieurs pages + TaillePage = 128; + + DirLoc->NbPages = ( unsigned char )TaillePage; + l = ( DirLoc->NbPages + 7 ) >> 3; //Nombre de blocs=TaillePage/8 arrondi par le haut + memset( DirLoc->Blocks, 0, 16 ); + for ( j = 0; j < l; j++ ) { //Pour chaque bloc de la page + Bloc = RechercheBlocLibre( MaxBloc ); //Met le fichier sur la disquette + if ( Bloc ) { + DirLoc->Blocks[ j ] = ( unsigned char )Bloc; + WriteBloc( Bloc, &BufFile[ PosFile ] ); + PosFile += 1024; // Passe au bloc suivant + } + else + return( ERR_NO_BLOCK ); + + } + SetInfoDirEntry( PosDir, DirLoc ); + } + else + return( ERR_NO_DIRENTRY ); + } + return( ERR_NO_ERR ); +} + + +// +// Retourne une entr�e du r�pertoire +// +StDirEntry * DSK::GetInfoDirEntry( int NumDir ) { + static StDirEntry Dir; + int MinSect = GetMinSect(); + int s = ( NumDir >> 4 ) + MinSect; + int t = ( MinSect == 0x41 ? 2 : 0 ); + if ( MinSect == 1 ) + t = 1; + + memcpy( &Dir + , &ImgDsk[ ( ( NumDir & 15 ) << 5 ) + GetPosData( t, s, true ) ] + , sizeof( StDirEntry ) + ); + return( &Dir ); +} + + +// +// V�rifier si DSK est "standard" (DATA ou VENDOR) +// +bool DSK::CheckDsk( void ) { + CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk; + if ( Infos->NbHeads == 1 ) { + int MinSectFirst = GetMinSect(); + if ( MinSectFirst != 0x41 && MinSectFirst != 0xC1 && MinSectFirst != 0x01 ) + { + cout << "DSK has wrong sector number!" << endl; + return( false ); + } + + + if ( Infos->NbTracks > 42 ) + Infos->NbTracks = 42; + + for ( int track = 0; track < Infos->NbTracks; track++ ) { + // Recherche position secteur + int Pos = sizeof( CPCEMUEnt ) + ( 0x1200 + sizeof( CPCEMUTrack ) ) * track; + CPCEMUTrack * tr = ( CPCEMUTrack * )&ImgDsk[ Pos ]; + + int MinSect = 0xFF, MaxSect = 0; + if ( tr->NbSect != 9 ) + { + cout << "Warning : track " << track <<" has "<<(int)tr->NbSect<<" sectors ! (wanted 9)" << endl; + // return( false ); + } + for ( int s = 0; s < (int)tr->NbSect; s++ ) { + if ( MinSect > tr->Sect[ s ].R ) + MinSect = tr->Sect[ s ].R; + + if ( MaxSect < tr->Sect[ s ].R ) + MaxSect = tr->Sect[ s ].R; + } + if ( MaxSect - MinSect != 8 ) + { + cout << "Warning : strange sector numbering in track "<<track<<"!" << endl; + // return( false ); + } + if ( MinSect != MinSectFirst ) + { + cout << "Warning : track "<<track<<" start at sector"<<MinSect<<" while track 0 starts at "<<MinSectFirst << endl; + //return( false ); + } + } + return( true ); + } + cout << "Multi-side dsk ! Expected 1 head, got " << (int)Infos->NbHeads << endl; + return( false ); +} + + +// +// Lire un fichier DSK +// +bool DSK::ReadDsk( std::string NomFic ) { + bool Ret = false; + CPCEMUEnt * Infos; + if(sizeof(CPCEMUEnt) != 0x100) cout << "INVALID DSK BUILD" << endl; + FILE* fp ; + + if ( (fp=fopen(NomFic.c_str(),"rb"))!=NULL ) { + fread(ImgDsk,sizeof(ImgDsk),1,fp); + Infos = ( CPCEMUEnt * )ImgDsk; + if ( isBigEndian( ) ) FixEndianDsk( false ); // fix endian for Big endianness machines (PPC) + if ( ! strncmp( Infos->debut, "MV -", 4 ) + || ! strncmp( Infos->debut, "EXTENDED CPC DSK", 16 ) + ) + Ret = true; + fclose(fp); + } + return( Ret ); +} + + +// +// Formatter une disquette +// +void DSK::FormatDsk( int NbSect, int NbTrack ) { + CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk; + + strcpy( Infos->debut, "MV - CPCEMU Disk-File\r\nDisk-Info\r\n" ); + Infos->DataSize = ( short )( sizeof( CPCEMUTrack ) + (0x200 * NbSect) ); + Infos->NbTracks = ( unsigned char ) NbTrack; + Infos->NbHeads = 1; + for ( int t = 0; t < NbTrack; t++ ) + FormatTrack( Infos, t, 0xC1, NbSect ); + + + FillBitmap(); +} + + + +// +// Modifie le endianness de la disquette +// +void DSK::FixEndianDsk( bool littleToBig) { + CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk; + //std::cerr<< "FixEndianDsk() Infos->DataSize : " << Infos->DataSize <<std::endl; + + if ( ! littleToBig ) + Infos->DataSize = FIX_SHORT( Infos->DataSize ); + for ( int t = 0; t < Infos->NbTracks; t++ ) + FixEndianTrack( Infos, t, 9 ); + if ( littleToBig ) + Infos->DataSize = FIX_SHORT( Infos->DataSize ); + FillBitmap(); +} + +// +// Modifie le endianness de la piste +// +void DSK::FixEndianTrack( CPCEMUEnt * Infos, int t, int NbSect ) { + CPCEMUTrack *tr; + if ( Infos->DataSize != 0 ) + tr = ( CPCEMUTrack * )&ImgDsk[ sizeof( CPCEMUEnt ) + t * Infos->DataSize ]; + else { + int ExtendedDataSize = ImgDsk[ 0x34 + t ] *256; //case of a extended dsk image + tr = ( CPCEMUTrack * )&ImgDsk[ sizeof( CPCEMUEnt ) + t * ExtendedDataSize ]; + } + int ss = 0; + + // + // Gestion "entrelacement" des secteurs + // + for ( int s = 0; s < NbSect; ) { + tr->Sect[ s ].SizeByte = FIX_SHORT( tr->Sect[ s ].SizeByte ); + tr->Sect[ s ].Un1 = FIX_SHORT( tr->Sect[ s ].Un1 ); + ss++; + if ( ++s < NbSect ) { + tr->Sect[ s ].SizeByte = FIX_SHORT( tr->Sect[ s ].SizeByte ); + tr->Sect[ s ].Un1 = FIX_SHORT( tr->Sect[ s ].Un1 ); + s++; + } + } + tr->Unused = FIX_SHORT( tr->Unused ); +} + + +// +// Ecriture du fichier DSK +// +bool DSK::WriteDsk( string NomDsk ) { + CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk; + FILE* fp; + int Taille,Copie; + + + if ( (fp=fopen(NomDsk.c_str(),"wb+")) != NULL) { + if ( ! Infos->DataSize ) Infos->DataSize = 0x100 + SECTSIZE * 9; + Taille = Infos->NbTracks * Infos->DataSize + sizeof( * Infos ); + if ( isBigEndian() ) FixEndianDsk( true ) ; // Fix endianness for Big endian machines (PPC) + + if ( (Copie=(fwrite(ImgDsk,1,Taille,fp))) !=Taille ) + cerr << Copie << "!=" << Taille; + fclose(fp); + // in case of the same DSK image stay in memory + if ( isBigEndian() ) FixEndianDsk( false ) ; // unFix endianness for Big endian machines (PPC) + + return( true ); + } + return( false ); +} + + +void DSK::DskEndian() { + CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk; + for ( int i=1 ; i<(int)Infos->NbTracks ; i++) { + CPCEMUTrack * TrackData = GetInfoTrack( i ); + TrackData = CPCEMUTrackEndian ( TrackData ) ; + } + Infos = CPCEMUEntEndian ( Infos ) ; +} + + +StAmsdos* DSK::StAmsdosEndian ( StAmsdos * pEntete ){ + pEntete->Length = FIX_SHORT( pEntete->Length ); + pEntete->Adress = FIX_SHORT( pEntete->Adress ); + pEntete->LogicalLength = FIX_SHORT( pEntete->LogicalLength); + pEntete->EntryAdress = FIX_SHORT( pEntete->EntryAdress ); + pEntete->RealLength = FIX_SHORT( pEntete->RealLength ); + pEntete->CheckSum = FIX_SHORT( pEntete->CheckSum ) ; + return ( pEntete ); +} + + +CPCEMUEnt* DSK::CPCEMUEntEndian ( CPCEMUEnt* Infos ) { + Infos->DataSize = FIX_SHORT( Infos->DataSize ); + return (Infos); +} + + +CPCEMUTrack* DSK::CPCEMUTrackEndian ( CPCEMUTrack* tr ) { + for ( int i=0;i < (int)tr->NbSect ; i++) { + tr->Sect[i] = CPCEMUSectEndian( tr->Sect[i] ); + } + + return ( tr); + +} + + +CPCEMUSect DSK::CPCEMUSectEndian ( CPCEMUSect Sect) { + Sect.Un1 = FIX_SHORT( Sect.Un1 ); + Sect.SizeByte = FIX_SHORT( Sect.SizeByte ); + return (Sect); +} + +// Retourne le type de fichier sous forme de chaine +// +const char * DSK::GetType( int Langue, StAmsdos * Ams ) { + if ( CheckAmsdos( ( unsigned char * )Ams ) ) { + switch( Ams->FileType ) { + case 0 : // BASIC + return( "BASIC"); //GetTexteLoc( 22, Langue ) ); + + case 1 : // BASIC (P) + return( "BASIC(P)"); // GetTexteLoc( 23, Langue ) ); + + case 2 : // BINAIRE + return("BINAIRE"); // GetTexteLoc( 24, Langue ) ); + + case 3 : // BINAIRE (P) + return( "BINAIRE(P)"); //GetTexteLoc( 25, Langue ) ); + + default : + return( "INCONNU"); // GetTexteLoc( 26, Langue ) ); + } + } + return("ASCII"); // GetTexteLoc( 27, Langue ) ); +} + +char * DSK::GetEntryNameInCatalogue ( int num , char* Nom ) { + int PosItem[ 64 ]; + StDirEntry TabDir[ 64 ]; + + memset( PosItem, 0, sizeof( PosItem ) ); + + for ( int i = 0; i < 64; i++ ) + memcpy( &TabDir[ i ], GetInfoDirEntry( i ), sizeof( StDirEntry )); + + for ( int i = 0; i < 64; i++ ) { + SetInfoDirEntry( i, &TabDir[ i ] ); + + if ( TabDir[ i ].User != USER_DELETED && ! TabDir[ i ].NumPage && num == i) { + memcpy( Nom, TabDir[ i ].Nom, 8 ); + memcpy( &Nom[ 9 ], TabDir[ i ].Ext, 3 ); + Nom[ 8 ] = '.'; + Nom[ 12 ] = 0; + for ( int j = 0; j < 12; j++ ) + Nom[ j ] &= 0x7F; + for ( int j = 0; j < 12; j++ ) + if ( ! isprint( Nom[ j ] ) ) + Nom[ j ] = '?' ; + return Nom; + } + } + return Nom; +} + +char * DSK::GetEntrySizeInCatalogue ( int num , char* Size ) { + int PosItem[ 64 ]; + StDirEntry TabDir[ 64 ]; + + + memset( PosItem, 0, sizeof( PosItem ) ); + + for ( int i = 0; i < 64; i++ ) + memcpy( &TabDir[ i ], GetInfoDirEntry( i ), sizeof( StDirEntry )); + + for ( int i = 0; i < 64; i++ ) { + SetInfoDirEntry( i, &TabDir[ i ] ); + + if ( TabDir[ i ].User != USER_DELETED && ! TabDir[ i ].NumPage && num == i) { + int p = 0, t = 0; + do { + if ( TabDir[ p + i ].User == TabDir[ i ].User ) { + t += TabDir[ p + i ].NbPages; + } + p++; + } + while( TabDir[ p + i ].NumPage && ( p + i ) < 64 ); + sprintf( Size, "%d Ko", ( t + 7 ) >>3 ); + return Size; + } + } + return Size; +} + + +bool DSK::GetFileInDsk( char* path, int Indice ){ + int i = Indice; + char current[ 16 ]; + char NomIndice[ 16 ]; + int lMax = 0x1000000; + int cumul=0; + FILE* f; + StDirEntry TabDir[ 64 ]; + + if ( (f=fopen(path,"wb"))==NULL ) + return false; + + for ( int i = 0; i < 64; i++ ) + memcpy( &TabDir[ i ], GetInfoDirEntry( i ), sizeof( StDirEntry )); + + + memset( NomIndice, 0 , sizeof( NomIndice ) ); + strncpy( NomIndice, GetNomAmsdos( TabDir[ i ].Nom ), 16); + strncat( NomIndice, GetNomAmsdos( TabDir[ i ].Ext), 3); + + do + { + // Longueur du fichier + int l = ( TabDir[ i ].NbPages + 7 ) >> 3; + for ( int j = 0; j < l; j++ ) { + int TailleBloc = 1024; + unsigned char * p = ReadBloc( TabDir[ i ].Blocks[ j ] ); + int NbOctets = min( lMax, TailleBloc ); + if ( NbOctets > 0 ) { + fwrite(p,1,NbOctets,f); + cumul+=NbOctets; + } + lMax -= 1024; + } + memset( current , 0, sizeof( current ) ); + i++; + strncpy(current, GetNomAmsdos( TabDir[ i ].Nom ), 16 ); + strncat(current, GetNomAmsdos( TabDir[ i ].Ext ), 3); + + if ( i > 64 ) return false; + }while (! strncmp( NomIndice, current , max( strlen( NomIndice ), strlen( current ) ))); + + fclose (f); + return true; +} + + +bool DSK::PutFileInDsk(string Masque, int TypeModeImport, + int loadAddress, int exeAddress, int UserNumber, + bool System_file, bool Read_only ) +{ + static unsigned char Buff[0x20000]; + static char *cFileName; + unsigned long Lg; + bool ret; + FILE* Hfile; + + // Get AMSDOS-formatted name + cFileName = GetNomAmsdos(Masque.c_str()); + + // Open and read the input file + if ((Hfile = fopen(Masque.c_str(),"rb")) == NULL) + return false; + Lg=fread(Buff,1, 0x20000 ,Hfile); + fclose( Hfile ); + + // Check if file already has an header + bool IsAmsdos = (TypeModeImport != MODE_RAW) && CheckAmsdos(Buff); + + // Force binary mode if a load or execution address is specified + if (loadAddress != 0 || exeAddress != 0) + TypeModeImport = MODE_BINAIRE; + + switch(TypeModeImport) { + case MODE_ASCII: + // In ASCII mode, delete the header if there is one + if (IsAmsdos) { + memmove(Buff, Buff + sizeof(StAmsdos), Lg - sizeof(StAmsdos)); + Lg -= sizeof(StAmsdos); + } + break; + + case MODE_BINAIRE : + // In binary mode, add an header if there is none + if ( ! IsAmsdos ) { + // Sanity check on file size (we cast to unsigned short) + if ( Lg >= 0x10000 ) { + cerr << "Creating an header for files larger than 64K is not supported yet\n"; + return false; + } + + // Create and fill AMSDOS header + cout << "Automatically generating header for file\n"; + StAmsdos * e; + e = CreeEnteteAmsdos(cFileName, (unsigned short)Lg); + if (loadAddress != 0) + { + e->Adress = (unsigned short)loadAddress; + } + if (exeAddress != 0) + { + e->EntryAdress = (unsigned short)exeAddress; + } + // After changing addresses, recompute header checksum + SetChecksum(e); + // Fix endianness if run on big-endian machine + if (isBigEndian()) e = StAmsdosEndian(e); + + // Insert the header before the file + memmove(&Buff[sizeof(StAmsdos)], Buff, Lg); + memcpy(Buff, e, sizeof(StAmsdos)); + Lg += sizeof(StAmsdos); + } + else + cout << "File already has an header\n"; + break; + case MODE_RAW : + cout << "Using raw mode, no header\n"; + + } + + // Copy the file inside the DSK image. + if (CopieFichier(Buff, cFileName, Lg, 256, UserNumber, System_file, Read_only) != ERR_NO_ERR) + ret = false; + else + ret = true; + + return ret; +} + + +bool DSK::OnViewFic(int nItem) { + int LongFic = 0; + memset( BufFile, 0, sizeof( BufFile ) ); + memset( Listing, 0, sizeof( Listing ) ); + char NomFic[ 16 ]; + char current[ 16 ]; + int i = nItem; + bool FirstBlock = true; + StDirEntry TabDir[ 64 ]; + + for ( int j = 0; j < 64; j++ ) + memcpy( &TabDir[ j ], GetInfoDirEntry( j ), sizeof( StDirEntry )); + + memset( NomFic, 0 , sizeof( NomFic ) ); + strncpy( NomFic, GetNomAmsdos( TabDir[ i ].Nom ), 16); + strncat( NomFic, GetNomAmsdos( TabDir[ i ].Ext), 3); + + int lMax = sizeof( BufFile ); + + TailleFic = 0; + + + do + { + // Longueur du fichier + int l = ( TabDir[ i ].NbPages + 7 ) >> 3; + for ( int j = 0; j < l; j++ ) { + int TailleBloc = 1024; + unsigned char * p = ReadBloc( TabDir[ i ].Blocks[ j ] ); + if ( FirstBlock ) { + if ( CheckAmsdos( p ) ) { + TailleFic = p[ 0x18 +1 ] *256 + p[ 0x18 ]; + AdresseCharg = p[ 0x15 +1 ] *256 + p[ 0x15 ]; + AdresseExec = p[ 0x1a +1 ] *256 + p[ 0x1a ]; + TailleBloc -= sizeof( StAmsdos ); + memcpy( p , &p[ 0x80 ] , TailleBloc ); + } + FirstBlock = false; + + } + int NbOctets = min( lMax, TailleBloc ); + if ( NbOctets > 0 ) { + memcpy( &BufFile[ LongFic ], p, NbOctets ); + LongFic += NbOctets; + } + lMax -= 1024; + } + memset( current , 0, sizeof( current ) ); + i++; + strncpy(current, GetNomAmsdos( TabDir[ i ].Nom ), 16 ); + strncat(current, GetNomAmsdos( TabDir[ i ].Ext ), 3); + if ( i > 64 ) return false; + }while( ! strncmp( NomFic, current, max( strlen( current ), strlen( NomFic ) ) ) ); + + if ( TailleFic == 0 ) + TailleFic = LongFic; + return true; +} + + +bool DSK::Hexdecimal() { + + int TailleCourante=0; + char OffSet[ 7 ]; + const char * CodeHexa = "0123456789ABCDEF"; + + while (TailleCourante <= TailleFic ) { + // display the offset + memset( OffSet, 0 , 7 ); + snprintf( OffSet,6,"#%.4X:", TailleCourante ); + strcat( Listing, OffSet ); + strcat( Listing, " "); + char Ascii[ 18 ]; + char Hex[ 16 *3 +1 ]; + memset( Ascii, 0 , 18 ); + memset( Hex , 0 , ( 16*3 +1) ); + for ( int i=0; i<16 ; ++i ) { + unsigned char cur = BufFile[ TailleCourante + i ]; + // manage the ascii display + if ( cur > 32 && cur < 125 ) + Ascii[ i ] = cur; + else + Ascii[ i ] = '.'; + char Val[ 4 ]; + // manage the hexadeciaml display + Val[ 0 ] = CodeHexa[ cur >> 4 ]; + Val[ 1 ] = CodeHexa[ cur & 0x0F ]; + Val[ 2 ] = ' '; + Val[ 3 ] ='\0'; + strcat( Hex, Val ); + } + Ascii[ 16 ] = '\n'; + strcat( Listing, Hex ); + strcat( Listing, "| "); + strcat( Listing, Ascii ); + TailleCourante += 16; + } + + return true; +} + + +void DSK::RemoveFile ( int item ) { + char NomFic[ 16 ]; + int i = item; + StDirEntry TabDir[ 64 ]; + + for ( int j = 0; j < 64; j++ ) + memcpy( &TabDir[ j ], GetInfoDirEntry( j ), sizeof( StDirEntry )); + + strcpy( NomFic, GetNomAmsdos( TabDir[ i ].Nom ) ); + char *p ; + + do { + TabDir[ i ].User = USER_DELETED; + SetInfoDirEntry( i, &TabDir[ i ]); + p = GetNomAmsdos( TabDir[ ++i ].Nom) ; + } while ( ! strncmp( NomFic, p , max(strlen( p ), strlen( NomFic ) )) ); + + + return ; +} + + + +void DSK::RenameFile( int item , char *NewName) { + char NomFic[ 16 ]; + StDirEntry TabDir[ 64 ]; + StDirEntry DirLoc; + int c = item; + for ( int j = 0; j < 64; j++ ) + memcpy( &TabDir[ j ], GetInfoDirEntry( j ), sizeof( StDirEntry )); + + memset( DirLoc.Nom, ' ', 8); + memset( DirLoc.Ext, ' ', 3); + for ( int i=0; i<(int) strlen( NewName ) ; ++i) + NewName[ i ] = toupper( NewName[ i ] ); + + char *p = strchr( NewName, '.'); + + if ( p ) { + p++; + memcpy( DirLoc.Nom, NewName, p - NewName -1); + memcpy( DirLoc.Ext, p, std::min((int)strlen(p),3) ); + } + else { + memcpy( DirLoc.Nom, NewName, min( (int)strlen( NewName) , 8 ) ); + } + strcpy( NomFic, GetNomAmsdos( TabDir[ c ].Nom )); + + do { + memcpy( TabDir[ c ].Nom , DirLoc.Nom , 8 ); + memcpy( TabDir[ c ].Ext , DirLoc.Ext, 3 ); + SetInfoDirEntry( c, &TabDir[ c ]); + p = GetNomAmsdos( TabDir[ ++c ].Nom ); + }while (!strncmp( NomFic, p , max(strlen(p),strlen(NomFic)))); +} + + +std::string DSK::ReadDskDir( void ) { + StDirEntry TabDir[ 64 ]; + string catalogue; + for ( int i = 0; i < 64; i++ ) { + memcpy( &TabDir[ i ] + , GetInfoDirEntry( i ) + , sizeof( StDirEntry ) + ); + } + // Trier les fichiers + for ( int i = 0; i < 64; i++ ) { + // + // Afficher les fichiers non effac�s + // + if ( TabDir[ i ].User != USER_DELETED && ! TabDir[ i ].NumPage ) { + char Nom[ 13 ]; + memcpy( Nom, TabDir[ i ].Nom, 8 ); + memcpy( &Nom[ 9 ], TabDir[ i ].Ext, 3 ); + Nom[ 8 ] = '.'; + Nom[ 12 ] = 0; + // + // Masquer les bits d'attributs + // + for ( int j = 0; j < 12; j++ ) + { + Nom[ j ] &= 0x7F; + + if ( ! isprint( Nom[ j ] ) ) + Nom[ j ] = '?' ; + } + + catalogue += Nom; + catalogue += " "; + ostringstream c; + c << (int)TabDir[i].User; + catalogue += c.str(); + // + // Calcule la taille du fichier en fonction du nombre de blocs + // + int p = 0, t = 0; + do { + if ( TabDir[ p + i ].User == TabDir[ i ].User ) + t += TabDir[ p + i ].NbPages; + p++; + } while( TabDir[ p + i ].NumPage && ( p + i ) < 64 ); + //string size = GetTaille( ( t + 7 ) >> 3 ); + //catalogue+= " : " + size + "\n"; + catalogue += "\n"; + + } + } + return catalogue; +} diff --git a/tools/iDSK/src/GestDsk.h b/tools/iDSK/src/GestDsk.h new file mode 100644 index 0000000..116e080 --- /dev/null +++ b/tools/iDSK/src/GestDsk.h @@ -0,0 +1,176 @@ +#ifndef GESTDSK_H +#define GESTDSK_H + +#include <string> + +#define USER_DELETED 0xE5 + + +extern char Listing[ 0x280000 ]; +extern unsigned char BufFile[ 0x10000 ]; + + +extern int TailleFic, CurLigne, AdresseCharg, AdresseExec; + +#pragma pack(1) //evite le padding des structures qui sont utilisées dans des memcpy par la suite + +// +// Structure d'une entree AMSDOS +// +typedef struct +{ + unsigned char UserNumber; // 00 User + unsigned char FileName[15]; // 01-0F Nom + extension + unsigned char BlockNum; // 10 Numéro du bloc (disquette) + unsigned char LastBlock; // 11 Flag "dernier bloc" bloc (disquette) + unsigned char FileType; // 12 Type de fichier + unsigned short Length; // 13-14 Longueur + unsigned short Adress; // 15-16 Adresse + unsigned char FirstBlock; // 17 Flag premier bloc de fichier (disquette) + unsigned short LogicalLength; // 18-19 Longueur logique + unsigned short EntryAdress; // 1A-1B Point d'entree + unsigned char Unused[0x24]; + unsigned short RealLength; // 40-42 Longueur reelle + unsigned char BigLength; // Longueur reelle (3 octets) + unsigned short CheckSum; // 43-44 CheckSum Amsdos + unsigned char Unused2[0x3B]; +} StAmsdos; + + +#define SECTSIZE 512 + + +typedef struct +{ + char debut[0x30]; // "MV - CPCEMU Disk-File\r\nDisk-Info\r\n" + unsigned char NbTracks; + unsigned char NbHeads; + unsigned short DataSize; // 0x1300 = 256 + ( 512 * nbsecteurs ) + unsigned char Unused[0xCC]; +} CPCEMUEnt; + + +typedef struct +{ + unsigned char C; // track + unsigned char H; // head + unsigned char R; // sect + unsigned char N; // size + short Un1; + short SizeByte; // Taille secteur en octets +} CPCEMUSect; + + +typedef struct +{ + char ID[0x10]; // "Track-Info\r\n" + unsigned char Track; + unsigned char Head; + short Unused; + unsigned char SectSize; // 2 + unsigned char NbSect; // 9 + unsigned char Gap3; // 0x4E + unsigned char OctRemp; // 0xE5 + CPCEMUSect Sect[29]; +} CPCEMUTrack; + +#ifdef __GNUC__ +#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) +#else +#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) +#endif + +// see http://www.cpcwiki.eu/index.php/Disk_structure#Directory_entries +PACK(typedef struct +{ + unsigned char User; // 00 + char Nom[8]; // 01-08 + char Ext[3]; // 09-0B + unsigned char NumPage; // 0C + unsigned char Unused[2]; // 0D-0E + unsigned char NbPages; // 0F + unsigned char Blocks[16]; // 10-1F +}) StDirEntry; + +#pragma pack() + +enum { ERR_NO_ERR = 0, ERR_NO_DIRENTRY, ERR_NO_BLOCK, ERR_FILE_EXIST }; + +bool CheckAmsdos( unsigned char * Buf ); +StAmsdos * CreeEnteteAmsdos( char * NomFic, unsigned short Length ); +void ClearAmsdos( unsigned char * Buf ); +void SetChecksum( StAmsdos * pEntete ); +bool CheckAmsdos( unsigned char * Buf ); + + +class DSK +{ + unsigned char ImgDsk[ 0x80000 ]; + unsigned char Bitmap[ 256 ]; + + unsigned char * GetRawData( int Pos ); + void WriteRawData( int Pos, unsigned char * Data, int Longueur ); + int GetNbTracks( void ); + void WriteBloc( int bloc, unsigned char * BufBloc ); + void WriteSect( int Track, int Sect, unsigned char * Buff, int AmsdosMode ); + unsigned char * ReadSect( int Track, int Sect, int AmsdosMode ); + CPCEMUTrack * GetInfoTrack( int Track ); + int FillBitmap( void ); + void DskEndian(); + CPCEMUEnt* CPCEMUEntEndian ( CPCEMUEnt* Infos ); + CPCEMUTrack* CPCEMUTrackEndian ( CPCEMUTrack* tr ); + CPCEMUSect CPCEMUSectEndian ( CPCEMUSect Sect); + const char * GetType( int Langue, StAmsdos * Ams ); + int GetMinSect( void ); + int GetPosData( int track, int sect, bool SectPhysique ); + int RechercheBlocLibre( int MaxBloc ); + void FormatTrack( CPCEMUEnt * Infos, int t, int MinSect, int NbSect ); + +public: + DSK() + { + for (int i=0; i< 0x80000; i++) + ImgDsk[i]=0; + for (int j=0; j< 256 ; j++ ) + Bitmap[j]=0; + } + + DSK(const DSK& d) + { + for (int i=0; i< 0x80000; i++) + ImgDsk[i]=d.ImgDsk[i]; + for (int j=0; j< 256 ; j++ ) + Bitmap[j]=d.Bitmap[j]; + } + + ~DSK(){} + + int GetTailleDsk(); + StDirEntry * GetNomDir(std::string Nom ); + int CopieFichier( unsigned char * BufFile, char * NomFic, int TailleFic, int MaxBloc, int, bool,bool ); + bool WriteDsk( std::string NomDsk ); + unsigned char * ReadBloc( int bloc ); + bool ReadDsk( std::string NomFic ); + bool CheckDsk( void ); + int FileExist( char * Nom ); + StDirEntry * GetInfoDirEntry( int NumDir ); + int FileIsIn( std::string FileName ); + int RechercheDirLibre( void ); + void FormatDsk( int NbSect, int NbTrack ); + StAmsdos* StAmsdosEndian ( StAmsdos * pEntete ); + void SetInfoDirEntry( int NumDir, StDirEntry * Dir ); + char * GetEntryNameInCatalogue ( int num , char* Nom ); + char * GetEntrySizeInCatalogue ( int num , char* Size ); + bool GetFileInDsk( char* path, int Indice ); + bool PutFileInDsk( std::string Masque ,int TypeModeImport ,int loadAdress, int exeAdress, int,bool,bool ); + bool OnViewFic(int nItem); + bool Hexdecimal(); + void RemoveFile ( int item ); + void FixEndianDsk( bool LittleToBig ); + void FixEndianTrack( CPCEMUEnt * Infos, int t, int NbSect ); + void RenameFile( int item , char *NewName); + std::string ReadDskDir(void); + +}; + +#endif diff --git a/tools/iDSK/src/Main.cpp b/tools/iDSK/src/Main.cpp new file mode 100644 index 0000000..1bbe6d4 --- /dev/null +++ b/tools/iDSK/src/Main.cpp @@ -0,0 +1,309 @@ +#include <iostream> +#include <cstdlib> +#include <cstring> +#include <algorithm> // pour contourner un bug de std::vector ... + +#include "getopt_pp.h" /* Command line handling */ + +using namespace std; + +#include "MyType.h" +#include "GestDsk.h" +#include "Outils.h" +#include "Main.h" +#include "endianPPC.h" +#include "ViewFile.h" + +int main(int argc, char **argv) +{ + bool IsDskLoc, IsDskSet, + ModeListDsk, ModeImportFile, + ModeRemoveFile, + ModeDisaFile, ModeListBasic, + ModeListDams, ModeListHex, + ModeGetFile, ModeNewDsk, Force_Overwrite, + Read_only, System_file, Split_lines, ModeListAscii, NoOptionSet; + + ModeListDsk = ModeImportFile = ModeListAscii = + ModeRemoveFile = ModeDisaFile = + ModeListBasic = ModeListDams = ModeListHex = ModeNewDsk = + ModeGetFile = IsDskLoc = IsDskSet = Force_Overwrite = Read_only = System_file = false; + NoOptionSet = true; + + string DskFile, AmsdosFile; + vector<string> AmsdosFileList; + + int exeAdress = 0, loadAdress = 0, AmsdosType = 1, UserNumber = 0; + + DSK MyDsk; + + IsDsk = IsDskValid = false; + IsDskSaved = true; + + // Récupération des arguments avec getopt_pp + { + using namespace GetOpt; + GetOpt_pp opts(argc, argv); + + opts >> GlobalOption(DskFile); + if (DskFile != "") + IsDskSet = true; + + opts >> OptionPresent('l', "list", ModeListDsk) + + >> OptionPresent('i', "import", ModeImportFile) >> Option('i', "import", AmsdosFileList) + + >> OptionPresent('r', "remove", ModeRemoveFile) >> Option('r', "remove", AmsdosFileList) + + >> OptionPresent('n', "new", ModeNewDsk) + + >> OptionPresent('z', "disassemble", ModeDisaFile) >> Option('z', "disassemble", AmsdosFileList) + + >> OptionPresent('a', "ascii", ModeListAscii) >> Option('a', "ascii", AmsdosFileList) + + >> OptionPresent('b', "basic", ModeListBasic) >> Option('b', "basic", AmsdosFileList) + + >> OptionPresent('d', "dams", ModeListDams) >> Option('d', "dams", AmsdosFileList) + + >> OptionPresent('h', "hex", ModeListHex) >> Option('h', "hex", AmsdosFileList) + + >> std::hex >> Option('e', "exec", exeAdress) >> Option('c', "load", loadAdress) >> std::dec >> Option('t', "type", AmsdosType) + + >> OptionPresent('g', "get", ModeGetFile) >> Option('g', "get", AmsdosFileList) + + >> OptionPresent('f', "force", Force_Overwrite) >> OptionPresent('o', "write-protect", Read_only) >> OptionPresent('s', "system", System_file) >> OptionPresent('p', "split-lines", Split_lines) >> Option('u', "user", UserNumber); + + if (opts.options_remain()) + { + cout << "Unhandled option ! Check the syntax." << endl; + exit(EXIT_FAILURE); + } + + } //namespace getopt + + if (!IsDskSet) + { + cerr << "You did not select a DSK file to work with !" << endl; + help(); + } + else + cerr << "DSK : " << DskFile << endl; + + if (ModeListBasic || ModeListHex || ModeListDams || ModeDisaFile || ModeListAscii) + { + NoOptionSet = false; + if (!MyDsk.ReadDsk(DskFile)) + { + cerr << "Error reading file (" << DskFile << ")." << endl; + exit(EXIT_FAILURE); + } + if (!MyDsk.CheckDsk()) + { + cerr << "Fichier image non supporté (" << DskFile << ")." << endl; + exit(EXIT_FAILURE); + } + int Indice; + for (vector<string>::iterator iter = AmsdosFileList.begin(); iter != AmsdosFileList.end(); iter++) + { + char *amsdosF = GetNomAmsdos(iter->c_str()); + cerr << "Amsdos file : " << amsdosF << endl; + if ((Indice = MyDsk.FileIsIn(amsdosF)) < 0) + { + cerr << "Error: File " << amsdosF << " not found." << endl; + exit(EXIT_FAILURE); + } + MyDsk.OnViewFic(Indice); + + if (ModeListBasic) + cout << ViewBasic(Split_lines) << endl; + else if (ModeListDams) + cout << "Not yet coded ! Please try a newer version of iDSK ! Sorry !" << endl; + else if (ModeListHex) + { + MyDsk.Hexdecimal(); + cout << Listing << endl; + } + else if (ModeDisaFile) + cout << ViewDesass() << endl; + else if (ModeListAscii) + cout << ViewAscii() << endl; + } + } + + if (ModeNewDsk) + { + NoOptionSet = false; + MyDsk.FormatDsk(9, 42); + if (!MyDsk.WriteDsk(DskFile)) + { + cerr << "Error writing file " << DskFile << endl; + exit(EXIT_FAILURE); + } + } + + + + if (ModeImportFile) + { // Ajouter fichiers sur dsk + NoOptionSet = false; + if (!MyDsk.ReadDsk(DskFile)) + { + cerr << "Error reading file (" << DskFile << ")." << endl; + exit(EXIT_FAILURE); + } + + if (!MyDsk.CheckDsk()) + { + cerr << "Unsupported dsk file (" << DskFile << ")." << endl; + exit(EXIT_FAILURE); + } + + for (vector<string>::iterator iter = AmsdosFileList.begin(); iter != AmsdosFileList.end(); iter++) + { + string amsdosfile = GetNomAmsdos(iter->c_str()); + int Indice; + // Ensure Indice is valid (the file is in the disk already) before atempting to remove it + if ((Indice = MyDsk.FileIsIn(amsdosfile)) != -1) + { + if (!Force_Overwrite) + { + cerr << "(" << amsdosfile << ") File exists, replace ? (Y/N) (try -f switch for autoreplace...):"; + string answer; + cin >> answer; + if (toupper(answer[0]) == 'Y') + MyDsk.RemoveFile(Indice); + else + { + cerr << "Import cancelled, dsk unchanged." << endl; + cout << MyDsk.ReadDskDir(); + exit(EXIT_SUCCESS); + } + } + else + MyDsk.RemoveFile(Indice); + } + cerr << "Amsdos file : " << *iter << endl; + + MyDsk.PutFileInDsk(*iter, AmsdosType, loadAdress, exeAdress, UserNumber, System_file, Read_only); + } + if (MyDsk.WriteDsk(DskFile)) + cout << MyDsk.ReadDskDir(); + else + cerr << "Error writing file : " << DskFile << endl; + } + + if (ModeRemoveFile) + { + NoOptionSet = false; + if (!MyDsk.ReadDsk((char *)DskFile.c_str())) + { + cerr << "Error reading file (" << DskFile << ")." << endl; + exit(EXIT_FAILURE); + } + if (!MyDsk.CheckDsk()) + { + cerr << "unsupported DSK file (" << DskFile << ")." << endl; + exit(EXIT_FAILURE); + } + int Indice; + for (vector<string>::iterator iter = AmsdosFileList.begin(); iter != AmsdosFileList.end(); iter++) + { + char *amsdosF = GetNomAmsdos(iter->c_str()); + cerr << "Amsdos file : " << amsdosF << endl; + if ((Indice = MyDsk.FileIsIn(amsdosF)) < 0) + { + cerr << "Error : file " << amsdosF << " not found." << endl; + exit(EXIT_FAILURE); + } + MyDsk.RemoveFile(Indice); + if (MyDsk.WriteDsk((char *)DskFile.c_str())) + cout << MyDsk.ReadDskDir(); + else + cerr << "Error writing file " << (*iter) << endl; + } + } + + if (ModeGetFile) + { + NoOptionSet = false; + if (!MyDsk.ReadDsk((char *)DskFile.c_str())) + { + cerr << "Error reading dskfile (" << DskFile << ")." << endl; + exit(EXIT_FAILURE); + } + if (!MyDsk.CheckDsk()) + { + cerr << "Unsupported dsk (" << DskFile << ")." << endl; + exit(EXIT_FAILURE); + } + int Indice; + + for (vector<string>::iterator iter = AmsdosFileList.begin(); iter != AmsdosFileList.end(); iter++) + { + char *amsdosF = GetNomAmsdos(iter->c_str()); + cerr << "Fichier Amsdos : " << amsdosF << endl; + if ((Indice = MyDsk.FileIsIn(amsdosF)) < 0) + { + cerr << "Error : file " << amsdosF << " not found." << endl; + exit(EXIT_FAILURE); + } + if (!MyDsk.GetFileInDsk((char *)(*iter).c_str(), Indice)) + { + cerr << "System error : unable to copy (" << AmsdosFile << ")." << endl; + exit(EXIT_FAILURE); + } + } + } + if (ModeListDsk || NoOptionSet) + { // lire Dsk + if (!MyDsk.ReadDsk(DskFile)) + { + cerr << "Error reading file (" << DskFile << ")." << endl; + exit(EXIT_FAILURE); + } + if (!MyDsk.CheckDsk()) + { + cerr << "Unsupported dsk file (" << DskFile << ")." << endl; + exit(EXIT_FAILURE); + } + cout << MyDsk.ReadDskDir(); + } + + cerr << "------------------------------------" << endl; + + return (EXIT_SUCCESS); +} + +void help(void) +{ + cout << endl; + cout << "--------------------------------------------------------------------------------" << endl; + cout << "################################################################################" << endl; + cout << VERSION << " (by Demoniak, Sid, PulkoMandy), http://github.com/cpcsdk " << endl; + cout << "################################################################################" << endl; + cout << endl; + cout << "Usage : " << endl; + cout << "\t" << PROGNAME << " <DSKfile> [OPTIONS] [files to process]" << endl; + cout << "OPTIONS : EXAMPLE" << endl; + cout << "-l : List disk catalog iDSK floppy.dsk -l (default option is no option is set)" << endl; + cout << "-g : export ('Get') file iDSK floppy.dsk -g myprog.bas" << endl; + cout << "-r : Remove file iDSK floppy.dsk -r myprog.bas" << endl; + cout << "-n : create New dsk file iDSK floppy2.dsk -n" << endl; + cout << "-z : disassemble a binary file iDSK floppy.dsk -z myprog.bin" << endl; + cout << "-b : list a Basic file iDSK floppy.dsk -b myprog.bas" << endl + << "-p : split lines after 80 char ... -p" << endl; + cout << "-a : list a Ascii file iDSK floppy.dsk -a myprog.txt" << endl; + cout << "-d : list a Dams file iDSK floppy.dsk -d myprog.dms" << endl; + cout << "-h : list a binary file as Hexadecimal iDSK floppy.dsk -h myprog.bin" << endl; + cout << "-i : Import file iDSK floppy.dsk -i myprog.bas" << endl + << " -t : fileType (0=ASCII/1=BINARY/2=raw) ... -t 1" << endl; + cout << " -e : hex Execute address of file ... -e C000 -t 1" << endl; + cout << " -c : hex loading address of file ... -e C000 -c 4000 -t 1" << endl; + cout << " -f : Force overwriting if file exists ... -f" << endl + << " -o : insert a read-Only file ... -o" << endl + << " -s : insert a System file ... -s" << endl + << " -u : insert file with User number ... -u 3" << endl; + cout << "--------------------------------------------------------------------------------" << endl; + cout << "Please report bugs ! - Demoniak/Sid/PulkoMandy" << endl; + exit(0); +} diff --git a/tools/iDSK/src/Main.h b/tools/iDSK/src/Main.h new file mode 100644 index 0000000..325eda1 --- /dev/null +++ b/tools/iDSK/src/Main.h @@ -0,0 +1,16 @@ +#ifndef __MAIN_CPP__ +#define __MAIN_CPP__ +#define VERSION "iDSK version 0.20" +#define PROGNAME "iDSK" +char Nom[256]; +char Msg[128]; +StDirEntry TabDir[64]; +int PosItem[64]; +int Langue; +bool IsDsk, IsDskValid, IsDskSaved; +int TypeModeImport, TypeModeExport; + +void help(void); +void DecomposeArg(char **argv, int argc); + +#endif diff --git a/tools/iDSK/src/MyType.h b/tools/iDSK/src/MyType.h new file mode 100644 index 0000000..0112428 --- /dev/null +++ b/tools/iDSK/src/MyType.h @@ -0,0 +1,20 @@ +#ifndef MYTYPE_H_ +#define MYTYPE_H_ + +/* types definitions to be coherent with Visual Basic C++ types */ + +typedef unsigned char BYTE; /* unsigned 8-bit type */ +typedef unsigned short WORD; /* unsigned 16-bit type */ +typedef unsigned long DWORD; /* unsigned 32-bit type */ + + +/* constant defintion usefull in the code */ + +#define TRUE 1 +#define FALSE 0 +#define MODE_ASCII 0 +#define MODE_BINAIRE 1 +#define MODE_RAW 2 + + +#endif /*MYTYPE_H_*/ diff --git a/tools/iDSK/src/Outils.cpp b/tools/iDSK/src/Outils.cpp new file mode 100644 index 0000000..54e3c22 --- /dev/null +++ b/tools/iDSK/src/Outils.cpp @@ -0,0 +1,165 @@ +#include <iostream> +#include <cstring> +#include <cstdio> +using namespace std; +#include "Outils.h" + +// +// Initialise une chaine au format hexad�cimal en fonction de la valeur d'entr�e +// +void Hex( char Chaine[], int Valeur, int Digit ) +{ + static char TabDigit[ 17 ] = "0123456789ABCDEF"; + + while( Digit ) + * Chaine++ = TabDigit[ ( Valeur >> ( 4 * ( --Digit ) ) ) & 0x0F ]; +} + + +// +// Conversion hexa->d�cimal +// +int HexToDec( char * Valeur ) +{ + char * p = strchr( Valeur, 'X' ); + if ( p ) + Valeur = ++p; + + p = strchr( Valeur, 'x' ); + if ( p ) + Valeur = ++p; + + p = strchr( Valeur, '#' ); + if ( p ) + Valeur = ++p; + + p = strchr( Valeur, '$' ); + if ( p ) + Valeur = ++p; + + p = strchr( Valeur, '&' ); + if ( p ) + Valeur = ++p; + + int Ret = 0, i = 0; + while( Valeur[ i ] ) + { + Ret <<= 4; + char c = Valeur[ i++ ]; + if ( c >= '0' && c <= '9' ) + Ret += c - '0'; + else + Ret += ( c & 0x5F ) - 0x37; + } + return( Ret ); +} + + +// +// Conversion d'un secteur (512 octets) en affichage Hexa et ASCII +// +void SetBuffViewHexa( unsigned char * src, char * Hex, char * Ascii, unsigned short Offset, int AddOffset) +{ + const char * CodeHexa = "0123456789ABCDEF"; + int q = 0,i; + + // + // Parcourir les 512 octets de la source et remplir les buffers + // + for ( i = 0; i < 512; i++ ) + { + unsigned char b = * src++; + if ( b > 32 && b < 127 ) + { + Ascii[ i ] = b; + // cout << "b32:" << (int)b <<" Ascii["<<i<<"]:"<< Ascii[ i ] << endl; + } + else + { + Ascii[ i ] = '.'; + } + if ( AddOffset && ( ! ( i & 0x0F ) ) ) + { + Hex[ q++ ] = '#'; + Hex[ q++ ] = CodeHexa[ Offset >> 12 ]; + Hex[ q++ ] = CodeHexa[ ( Offset >> 8 ) & 0x0F ]; + Hex[ q++ ] = CodeHexa[ ( Offset >> 4 ) & 0x0F ]; + Hex[ q++ ] = CodeHexa[ Offset & 0x0F ]; + Hex[ q++ ] = ':'; + } + Offset++; + Hex[ q++ ] = CodeHexa[ b >> 4 ]; + Hex[ q++ ] = CodeHexa[ b & 0x0F ]; + Hex[ q++ ] = ' '; + } + Hex[ q ] = 0; + Ascii[ i ] = 0; +} + + +// +// Retourne le num�ro d'user sous forme de chaine +// +char * GetUser( int u ) +{ + static char User[ 8 ]; + sprintf(User, "%d", u); + return( User); +} + + + +// +// Retourne la taille du fichier sous forme de chaine +// +char * GetTaille( int t ) +{ + static char Taille[ 16 ]; + + sprintf( Taille, "%d Ko", t ); + return( Taille ); +} + + +// +// Retourne le nom du fichier formatt� amsdos (8+3) +// +char * GetNomAmsdos(const char * AmsName ) +{ + // Extract the name (without directory components) + const char* lastSlash = strrchr(AmsName, '/'); + const char* lastBackslash = strrchr(AmsName, '\\'); + if (lastSlash > lastBackslash) + AmsName = lastSlash + 1; + else if (lastSlash < lastBackslash) + AmsName = lastBackslash + 1; + + static char NomAmsdos[ 16 ]; + int i; + + char * p = NomAmsdos; + for ( i = 0; i < 8; i++ ) { + if ( * AmsName != ' ' && *AmsName != '.' ) + * p++ = * AmsName++; + /*if ( * AmsName == '-' ) + * p++ = * AmsName++;*/ + } + + while( * AmsName != '.' && * AmsName ) + AmsName++; + + AmsName++; + + * p = 0; + strcat( NomAmsdos, "." ); + + for ( i = 0; * AmsName && i < 3; i++ ) + *++p = * AmsName++; + + * ++p = 0; + i = 0; + while( NomAmsdos[ i ] ) + NomAmsdos[ i++ ] &= 0x7F; + + return( NomAmsdos ); +} diff --git a/tools/iDSK/src/Outils.h b/tools/iDSK/src/Outils.h new file mode 100644 index 0000000..911346f --- /dev/null +++ b/tools/iDSK/src/Outils.h @@ -0,0 +1,19 @@ +#ifndef __OUTILS_H__ +#define __OUTILS_H__ + + +void Hex( char Chaine[], int Valeur, int Digit ); + +int HexToDec( char * Valeur ); + +void SetBuffViewHexa( unsigned char * src, char * Hex, char * Ascii,unsigned short Offset, int AddOffset); + +char * GetNomAmsdos( const char * AmsName ); + +char * GetUser( int u ); + +char * GetTaille( int t ); + + + +#endif diff --git a/tools/iDSK/src/ViewFile.cpp b/tools/iDSK/src/ViewFile.cpp new file mode 100644 index 0000000..733bba6 --- /dev/null +++ b/tools/iDSK/src/ViewFile.cpp @@ -0,0 +1,44 @@ +#include <iostream> +using namespace std; +#include "GestDsk.h" +#include "Outils.h" +#include "Basic.h" +#include "Desass.h" +#include "Dams.h" +#include "endianPPC.h" +#include "ViewFile.h" +#include "Ascii.h" + +string ViewDams() +{ + cerr << "Taille du fichier : " << TailleFic << endl; + Dams(BufFile, TailleFic, Listing); + return Listing; + //cout << Listing << endl; +} + +string ViewDesass() +{ + cerr << "Taille du fichier : " << TailleFic << endl; + Desass(BufFile, Listing, TailleFic, AdresseCharg); + return Listing; + //cout << Listing << endl; +} + +string ViewBasic(bool AddCrLf) +{ + bool IsBasic = true; + //cout << "Entre Ici\n"; + cerr << "Taille du fichier : " << TailleFic << endl; + Basic(BufFile, Listing, IsBasic, AddCrLf); + //cout << Listing << endl; + return Listing; +} + +string ViewAscii() +{ + cerr << "Taille du fichier : " << TailleFic << endl; + Ascii(BufFile, Listing, TailleFic); + //cout << Listing << endl; + return Listing; +} diff --git a/tools/iDSK/src/ViewFile.h b/tools/iDSK/src/ViewFile.h new file mode 100644 index 0000000..1f5ed1f --- /dev/null +++ b/tools/iDSK/src/ViewFile.h @@ -0,0 +1,10 @@ +#ifndef __VIEWFILE_H__ +#define __VIEWFILE_H__ + +string ViewDams(); +string ViewLine(); +string ViewDesass(); +string ViewAscii(); +string ViewBasic(bool AddCrLf); + +#endif diff --git a/tools/iDSK/src/endianPPC.cpp b/tools/iDSK/src/endianPPC.cpp new file mode 100644 index 0000000..f3146d6 --- /dev/null +++ b/tools/iDSK/src/endianPPC.cpp @@ -0,0 +1,24 @@ +#include <iostream> +#include <cstdlib> +using namespace std; +#include "endianPPC.h" + +#ifndef _MSC_VER +#include <sys/param.h> +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__MORPHOS__) +#include <machine/endian.h> +#else +#include <endian.h> +#endif +#endif + +bool isBigEndian(void) +{ +#ifdef BYTE_ORDER + return BYTE_ORDER == BIG_ENDIAN; +#elif defined _MSC_VER + return false; // Modern VC++ only runs on x86, x64 and ARM, doesn't require big/little endian conversion +#else + return __BYTE_ORDER == __BIG_ENDIAN; +#endif +} diff --git a/tools/iDSK/src/endianPPC.h b/tools/iDSK/src/endianPPC.h new file mode 100644 index 0000000..9def637 --- /dev/null +++ b/tools/iDSK/src/endianPPC.h @@ -0,0 +1,22 @@ +#ifndef __ENDIANPPC_H__ +#define __ENDIANPPC_H__ + +/* macros convertion little endian convertion to big endian convertion */ + + +#define SWAP_2(x) ( (((x) & 0xff) << 8) | ((unsigned short)(x) >> 8) ) +#define SWAP_4(x) ( ((x) << 24) | \ + (((x) << 8) & 0x00ff0000) | \ + (((x) >> 8) & 0x0000ff00) | \ + ((x) >> 24) ) +#define FIX_SHORT(x) (*(unsigned short *)&(x) = SWAP_2(*(unsigned short *)&(x))) +#define FIX_INT(x) (*(unsigned int *)&(x) = SWAP_4(*(unsigned int *)&(x))) +#define FIX_FLOAT(x) FIX_INT(x) + + + +/* endianness test function */ + +bool isBigEndian(void); + +#endif diff --git a/tools/iDSK/src/firmware.h b/tools/iDSK/src/firmware.h new file mode 100644 index 0000000..13ecc7d --- /dev/null +++ b/tools/iDSK/src/firmware.h @@ -0,0 +1,308 @@ +struct { + unsigned short address; + const char * label; +} FirmWareVectors[] = { +{0x0000, "RESET_ENTRY"}, +{0x0008, "LOW_JUMP"}, +{0x000B, "KL_LOW_PCHL"}, +{0x000E, "PCBC"}, +{0x0010, "SIDE_CALL"}, +{0x0013, "KL_SIDE_PCHL"}, +{0x0016, "PCDE"}, +{0x0018, "FAR_CALL"}, +{0x001B, "KL_FAR_PCHL"}, +{0x001E, "PCHL"}, +{0x0020, "RAM_LAM"}, +{0x0023, "KL_FAR_CALL"}, +{0x0028, "FIRM_JUMP"}, +{0x0030, "USER_RESTART"}, +{0x0038, "INTERRUPT_ENTRY"}, +{0x003B, "EXT_INTERRUPT"}, +{0xB900, "KL_U_ROM_ENABLE"}, +{0xB903, "KL_U_ROM_DISABLE"}, +{0xB906, "KL_L_ROM_ENABLE"}, +{0xB909, "KL_L_ROM_DISABLE"}, +{0xB90C, "KL_ROM_RESTORE"}, +{0xB90F, "KL_ROM_SELECT"}, +{0xB912, "KL_CURR_SELECTION"}, +{0xB915, "KL_PROBE_ROM"}, +{0xB918, "KL_ROM_DESELECT"}, +{0xB91B, "KL_LDIR"}, +{0xB91E, "KL_LDDR"}, +{0xB921, "KL_POLL_SYNCHRONOUS"}, +{0xB92A, "KL_SCAN_NEEDED"}, +{0xBB00, "KM_INITIALISE"}, +{0xBB03, "KM_RESET"}, +{0xBB06, "KM_WAIT_CHAR"}, +{0xBB09, "KM_READ_CHAR"}, +{0xBB0C, "KM_CHAR_RETURN"}, +{0xBB0F, "KM_SET_EXPAND"}, +{0xBB12, "KM_GET_EXPAND"}, +{0xBB15, "KM_EXP_BUFFER"}, +{0xBB18, "KM_WAIT_KEY"}, +{0xBB1B, "KM_READ_KEY"}, +{0xBB1E, "KM_TEST_KEY"}, +{0xBB21, "KM_GET_STATE"}, +{0xBB24, "KM_GET_JOYSTICK"}, +{0xBB27, "KM_SET_TRANSLATE"}, +{0xBB2A, "KM_GET_TRANSLATE"}, +{0xBB2D, "KM_SET_SHIFT"}, +{0xBB30, "KM_GET_SHIFT"}, +{0xBB33, "KM_SET_CONTROL"}, +{0xBB36, "KM_GET_CONTROL"}, +{0xBB39, "KM_SET_REPEAT"}, +{0xBB3C, "KM_GET_REPEAT"}, +{0xBB3F, "KM_SET_DELAY"}, +{0xBB42, "KM_GET_DELAY"}, +{0xBB45, "KM_ARM_BREAKS"}, +{0xBB48, "KM_DISARM_BREAK"}, +{0xBB4B, "KM_BREAK_EVENT"}, +{0xBB4E, "TXT_INITIALISE"}, +{0xBB51, "TXT_RESET"}, +{0xBB54, "TXT_VDU_ENABLE"}, +{0xBB57, "TXT_VDU_DISABLE"}, +{0xBB5A, "TXT_OUTPUT"}, +{0xBB5D, "TXT_WR_CHAR"}, +{0xBB60, "TXT_RD_CHAR"}, +{0xBB63, "TXT_SET_GRAPHIC"}, +{0xBB66, "TXT_WIN_ENABLE"}, +{0xBB69, "TXT_GET_WINDOW"}, +{0xBB6C, "TXT_CLEAR_WINDOW"}, +{0xBB6F, "TXT_SET_COLUMN"}, +{0xBB72, "TXT_SET_ROW"}, +{0xBB75, "TXT_SET_CURSOR"}, +{0xBB78, "TXT_GET_CURSOR"}, +{0xBB7B, "TXT_CUR_ENABLE"}, +{0xBB7E, "TXT_CUR_DISABLE"}, +{0xBB81, "TXT_CUR_ON"}, +{0xBB84, "TXT_CUR_OFF"}, +{0xBB87, "TXT_VALIDATE"}, +{0xBB8A, "TXT_PLACE_CURSOR"}, +{0xBB8D, "TXT_REMOVE_CURSOR"}, +{0xBB90, "TXT_SET_PEN"}, +{0xBB93, "TXT_GET_PEN"}, +{0xBB96, "TXT_SET_PAPER"}, +{0xBB99, "TXT_GET_PAPER"}, +{0xBB9C, "TXT_INVERSE"}, +{0xBB9F, "TXT_SET_BACK"}, +{0xBBA2, "TXT_GET_BACK"}, +{0xBBA5, "TXT_GET_MATRIX"}, +{0xBBA8, "TXT_SET_MATRIX"}, +{0xBBAB, "TXT_SET_M_TABLE"}, +{0xBBAE, "TXT_GET_M_TABLE"}, +{0xBBB1, "TXT_GET_CONTROLS"}, +{0xBBB4, "TXT_STR_SELECT"}, +{0xBBB7, "TXT_SWAP_STREAMS"}, +{0xBBBA, "GRA_INITIALISE"}, +{0xBBBD, "GRA_RESET"}, +{0xBBC0, "GRA_MOVE_ABSOLUTE"}, +{0xBBC3, "GRA_MOVE_RELATIVE"}, +{0xBBC6, "GRA_ASK_CURSOR"}, +{0xBBC9, "GRA_SET_ORIGIN"}, +{0xBBCC, "GRA_GET_ORIGIN"}, +{0xBBCF, "GRA_WIN_WIDTH"}, +{0xBBD2, "GRA_WIN_HEIGHT"}, +{0xBBD5, "GRA_GET_W_WIDTH"}, +{0xBBD8, "GRA_GET_W_HEIGHT"}, +{0xBBDB, "GRA_CLEAR_WINDOW"}, +{0xBBDE, "GRA_SET_PEN"}, +{0xBBE1, "GRA_GET_PEN"}, +{0xBBE4, "GRA_SET_PAPER"}, +{0xBBE7, "GRA_GET_PAPER"}, +{0xBBEA, "GRA_PLOT_ABSOLUTE"}, +{0xBBED, "GRA_PLOT_RELATIVE"}, +{0xBBF0, "GRA_TEST_ABSOLUTE"}, +{0xBBF3, "GRA_TEST_RELATIVE"}, +{0xBBF6, "GRA_LINE_ABSOLUTE"}, +{0xBBF9, "GRA_LINE_RELATIVE"}, +{0xBBFC, "GRA_WR_CHAR"}, +{0xBBFF, "SCR_INITIALISE"}, +{0xBC02, "SCR_RESET"}, +{0xBC05, "SCR_SET_OFFSET"}, +{0xBC08, "SCR_SET_BASE"}, +{0xBC0B, "SCR_GET_LOCATION"}, +{0xBC0E, "SCR_SET_MODE"}, +{0xBC11, "SCR_GET_MODE"}, +{0xBC14, "SCR_CLEAR"}, +{0xBC17, "SCR_CHAR_LIMITS"}, +{0xBC1A, "SCR_CHAR_POSITION"}, +{0xBC1D, "SCR_DOT_POSITION"}, +{0xBC20, "SCR_NEXT_BYTE"}, +{0xBC23, "SCR_PREV_BYTE"}, +{0xBC26, "SCR_NEXT_LINE"}, +{0xBC29, "SCR_PREV_LINE"}, +{0xBC2C, "SCR_INK_ENCODE"}, +{0xBC2F, "SCR_INK_DECODE"}, +{0xBC32, "SCR_SET_INK"}, +{0xBC35, "SCR_GET_INK"}, +{0xBC38, "SCR_SET_BORDER"}, +{0xBC3B, "SCR_GET_BORDER"}, +{0xBC3E, "SCR_SET_FLASHING"}, +{0xBC41, "SCR_GET_FLASHING"}, +{0xBC44, "SCR_FILL_BOX"}, +{0xBC47, "SCR_FLOOD_BOX"}, +{0xBC4A, "SCR_CHAR_INVERT"}, +{0xBC4D, "SCR_HW_ROLL"}, +{0xBC50, "SCR_SW_ROLL"}, +{0xBC53, "SCR_UNPACK"}, +{0xBC56, "SCR_REPACK"}, +{0xBC59, "SCR_ACCESS"}, +{0xBC5C, "SCR_PIXELS"}, +{0xBC5F, "SCR_HORIZONTAL"}, +{0xBC62, "SCR_VERTICAL"}, +{0xBC65, "CAS_INITIALISE"}, +{0xBC68, "CAS_SET_SPEED"}, +{0xBC6B, "CAS_NOISY"}, +{0xBC6E, "CAS_START_MOTOR"}, +{0xBC71, "CAS_STOP_MOTOR"}, +{0xBC74, "CAS_RESTORE_MOTOR"}, +{0xBC77, "CAS_IN_OPEN"}, +{0xBC7A, "CAS_IN_CLOSE"}, +{0xBC7D, "CAS_IN_ABANDON"}, +{0xBC80, "CAS_IN_CHAR"}, +{0xBC83, "CAS_IN_DIRECT"}, +{0xBC86, "CAS_RETURN"}, +{0xBC89, "CAS_TEST_EOF"}, +{0xBC8C, "CAS_OUT_OPEN"}, +{0xBC8F, "CAS_OUT_CLOSE"}, +{0xBC92, "CAS_OUT_ABANDON"}, +{0xBC95, "CAS_OUT_CHAR"}, +{0xBC98, "CAS_OUT_DIRECT"}, +{0xBC9B, "CAS_CATALOG"}, +{0xBC9E, "CAS_WRITE"}, +{0xBCA1, "CAS_READ"}, +{0xBCA4, "CAS_CHECK"}, +{0xBCA7, "SOUND_RESET"}, +{0xBCAA, "SOUND_QUEUE"}, +{0xBCAD, "SOUND_CHECK"}, +{0xBCB0, "SOUND_ARM_EVENT"}, +{0xBCB3, "SOUND_RELEASE"}, +{0xBCB6, "SOUND_HOLD"}, +{0xBCB9, "SOUND_CONTINUE"}, +{0xBCBC, "SOUND_AMPL_ENVELOPE"}, +{0xBCBF, "SOUND_TONE_ENVELOPE"}, +{0xBCC2, "SOUND_A_ADDRESS"}, +{0xBCC5, "SOUND_T_ADDRESS"}, +{0xBCC8, "KL_CHOKE_OFF"}, +{0xBCCB, "KL_ROM_WALK"}, +{0xBCCE, "KL_INIT_BACK"}, +{0xBCD1, "KL_LOG_EXT"}, +{0xBCD4, "KL_FIND_COMMAND"}, +{0xBCD7, "KL_NEW_FRAME_FLY"}, +{0xBCDA, "KL_ADD_FRAME_FLY"}, +{0xBCDD, "KL_DEL_FRAME_FLY"}, +{0xBCE0, "KL_NEW_FAST_TICKER"}, +{0xBCE3, "KL_ADD_FAST_TICKER"}, +{0xBCE6, "KL_DEL_FAST_TICKER"}, +{0xBCE9, "KL_ADD_TICKER"}, +{0xBCEC, "KL_DEL_TICKER"}, +{0xBCEF, "KL_INIT_EVENT"}, +{0xBCF2, "KL_EVENT"}, +{0xBCF5, "KL_SYNC_RESET"}, +{0xBCF8, "KL_DEL_SYNCHRONOUS"}, +{0xBCFB, "KL_NEXT_SYNCH"}, +{0xBCFE, "KL_DO_SYNCH"}, +{0xBD01, "KL_DONE_SYNCH"}, +{0xBD04, "KL_EVENT_DISABLE"}, +{0xBD07, "KL_EVENT_ENABLE"}, +{0xBD0A, "KL_DISARM_EVENT"}, +{0xBD0D, "KL_TIME_PLEASE"}, +{0xBD10, "KL_TIME_SET"}, +{0xBD13, "MC_BOOT_PROGRAM"}, +{0xBD16, "MC_START_PROGRAM"}, +{0xBD19, "MC_WAIT_FLYBACK"}, +{0xBD1C, "MC_SET_MODE"}, +{0xBD1F, "MC_SCREEN_OFFSET"}, +{0xBD22, "MC_CLEAR_INKS"}, +{0xBD25, "MC_SET_INKS"}, +{0xBD28, "MC_RESET_PRINTER"}, +{0xBD2B, "MC_PRINT_CHAR"}, +{0xBD2E, "MC_PRINTER_BUSY"}, +{0xBD31, "MC_SEND_PRINTER"}, +{0xBD34, "MC_SOUND_REGISTER"}, +{0xBD37, "JUMP_RESTORE"}, +{0xBD3A, "KM_SET_LOCKS"}, +{0xBD40, "TXT_ASK_STATE"}, +{0xBD43, "GRA_DEFAULT"}, +{0xBD46, "GRA_SET_BACK"}, +{0xBD49, "GRA_SET_FIRST"}, +{0xBD4C, "GRA_SET_LINE_MASK"}, +{0xBD4F, "GRA_FROM_USER"}, +{0xBD52, "GRA_FILL"}, +{0xBD55, "SCR_SET_POSITION"}, +{0xBD58, "MC_PRINT_TRANSLATION"}, +{0xBD5B, "KL_BANK_SWITCH"}, +{0xBDCD, "IND_TXT_DRAW_CURSOR"}, +{0xBDD0, "IND_TXT_UNDRAW_CURSOR"}, +{0xBDD3, "IND_TXT_WRITE_CHAR"}, +{0xBDD6, "IND_TXT_UNWRITE"}, +{0xBDD9, "IND_TXT_OUT_ACTION"}, +{0xBDDC, "IND_GRA_PLOT"}, +{0xBDDF, "IND_GRA_TEST"}, +{0xBDE2, "IND_GRA_LINE"}, +{0xBDE5, "IND_SCR_READ"}, +{0xBDE8, "IND_SCR_WRITE"}, +{0xBDEB, "IND_SCR_MODE_CLEAR"}, +{0xBDEE, "IND_KM_TEST_BREAK"}, +{0xBDF1, "IND_MC_WAIT_PRINTER"}, +{0xBDF4, "IND_KM_SCAN_KEYS"}, +{0xBD61, "MOVE_REAL"}, +{0xBD64, "INTEGER_TO_REAL"}, +{0xBD67, "BINARY_TO_REAL"}, +{0xBD6A, "REAL_TO_INTEGER"}, +{0xBD6D, "REAL_TO_BINARY"}, +{0xBD70, "REAL_FIX"}, +{0xBD73, "REAL_INT"}, +{0xBD76, "INTERNAL_SUBROUTINE"}, +{0xBD79, "REAL_x10POWA"}, +{0xBD7C, "REAL_ADDITION"}, +{0xBD82, "REAL_REVERSE_SUBTRACTION"}, +{0xBD85, "REAL_MULTIPLICATION"}, +{0xBD88, "REAL_DIVISION"}, +{0xBD8E, "REAL_COMPARISON"}, +{0xBD91, "REAL_UNARY_MINUS"}, +{0xBD94, "REAL_SIGNUM_SGN"}, +{0xBD97, "SET_ANGLE_MODE"}, +{0xBD9A, "REAL_PI"}, +{0xBD9D, "REAL_SQR"}, +{0xBDA0, "REAL_POWER"}, +{0xBDA3, "REAL_LOG"}, +{0xBDA6, "REAL_LOG_10"}, +{0xBDA9, "REAL_EXP"}, +{0xBDAC, "REAL_SINE"}, +{0xBDAF, "REAL_COSINE"}, +{0xBDB2, "REAL_TANGENT"}, +{0xBDB5, "REAL_ARCTANGENT"}, +{0xBD5B, "REAL_SUBTRACTION"}, +{0xBD67, "REAL_EXPONENT_ADDITION"}, +{0xBDAC, "INTEGER_ADDITION"}, +{0xBDAF, "INTEGER_SUBTRACTION"}, +{0xBDB2, "INTEGER_REVERSE_SUBTRACTION"}, +{0xBDB5, "INTEGER_MULTIPLICATION"}, +{0xBDB8, "INTEGER_DIVISION"}, +{0xBDBB, "INTEGER_DIVISION_2"}, +{0xBDC4, "INTEGER_COMPARISON"}, +{0xBDC7, "INTEGER_UNARY_MINUS"}, +{0xBDCA, "INTEGER_SIGNUM_SGN"}, +{0xBD5E, "TEXT_INPUT"}, +{0xBD7F, "REAL_RND"}, +{0xBD8B, "REAL_RND0"}, +{0xC033, "BIOS_SET_MESSAGE"}, +{0xC036, "BIOS_SETUP_DISC"}, +{0xC039, "BIOS_SELECT_FORMAT"}, +{0xC03C, "BIOS_READ_SECTOR"}, +{0xC03F, "BIOS_WRITE_SECTOR"}, +{0xC042, "BIOS_FORMAT_TRACK"}, +{0xC045, "BIOS_MOVE_TRACK"}, +{0xC048, "BIOS_GET_STATUS"}, +{0xC04B, "BIOS_SET_RETRY_COUNT"}, +{0xC56C, "GET_SECTOR_DATA"}, +{0xBE53, "AMSDOS_DRIVE_HSUS"}, +{0xBE54, "AMSDOS_DRIVE_TRACK"}, +{0xBE5E, "AMSDOS_FLAG_RW_SECTOR"}, +{0xBE5F, "AMSDOS_FLAG_MOTOR"}, +{0xBE7D, "AMSDOS_RESERVED_AREA"}, +{0xBE7D, "AMSDOS_MEMORY_POOL"}, +{0xBE7F, "AMSDOS_HOOK"}, +{0, 0} +}; diff --git a/tools/iDSK/src/getopt_pp.cpp b/tools/iDSK/src/getopt_pp.cpp new file mode 100644 index 0000000..a497c14 --- /dev/null +++ b/tools/iDSK/src/getopt_pp.cpp @@ -0,0 +1,269 @@ +/* +GetOpt_pp: Yet another C++ version of getopt. + This file is part of GetOpt_pp. + + Copyright (C) Daniel Gutson, FuDePAN 2007-2010 + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt in the root directory or + copy at http://www.boost.org/LICENSE_1_0.txt) + + GetOpt_pp IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include <fstream> + +#if __APPLE__ +#include <crt_externs.h> +#elif _WIN32 +#include <Stdio.h> +#else +#include <unistd.h> +#endif + +#include "getopt_pp.h" + +namespace GetOpt +{ + +GETOPT_INLINE Token* GetOpt_pp::_add_token(const std::string& value, Token::Type type) +{ + Token* const ret = new Token(value, type); + if (_first_token == NULL) + _first_token = ret; + else + _last_token->link_to(ret); + _last_token = ret; + return ret; +} + +GETOPT_INLINE void GetOpt_pp::_init_flags() +{ + std::stringstream ss; + _flags = ss.flags(); +} + +GETOPT_INLINE void GetOpt_pp::_parse_sub_file(const std::string& file) +{ + std::ifstream ifile(file.c_str()); + if (!ifile) + throw OptionsFileNotFoundEx(file); + + std::vector<std::string> args; + std::string arg; + + while (ifile >> arg) + args.push_back(arg); + + _parse(args); +} + +GETOPT_INLINE void GetOpt_pp::_parse(const std::vector<std::string>& args) +{ + bool any_option_processed = false; + const size_t argc = args.size(); + + size_t start = 0; + if ( _app_name.empty() ) + { + _app_name = args[0]; + start = 1; + } + + // parse arguments by their '-' or '--': + // (this will be a state machine soon) + for (size_t i = start; i < argc; i++) + { + const std::string& currentArg = args[i]; + + if (currentArg[0] == '-' && currentArg.size() > 1) + { + // see what's next, differentiate whether it's short or long: + if (currentArg[1] == '-') + { + if ( currentArg.size() > 2 ) + { + // long option + _longOps[currentArg.substr(2)].token = _add_token(currentArg.substr(2), Token::LongOption); + } + else + { + // it's the -- option alone + _longOps[currentArg].token = _add_token(currentArg, Token::GlobalArgument); + } + + any_option_processed = true; + } + else + { + // check if it is a negative number: rules + // * floating point negative numbers are straight classified as 'arguments' + // * integer negative numbers of more than 1 digit length are also 'arguments' + // * integer negatives of 1 digit length can be either arguments or short options. + // * anything else: short options. + int anInt; + float aFloat; + std::stringstream dummy; + if ( convert(currentArg, anInt, dummy.flags()) == _Option::OK ) + { + if ( currentArg.size() > 2 ) // if it's larger than -d (d=digit), then assume it's a negative number: + _add_token(currentArg, any_option_processed ? Token::UnknownYet : Token::GlobalArgument); + else // size == 2: it's a 1 digit negative number + _shortOps[currentArg[1]].token = _add_token(currentArg, Token::PossibleNegativeArgument); + } + else if ( convert(currentArg, aFloat, dummy.flags()) == _Option::OK ) + _add_token(currentArg, any_option_processed ? Token::UnknownYet : Token::GlobalArgument); + else + { + // short option + // iterate over all of them, keeping the last one in currentData + // (so the intermediates will generate 'existent' arguments, as of '-abc') + for( size_t j = 1; j < currentArg.size(); j++ ) + _shortOps[currentArg[j]].token = _add_token(std::string(currentArg, j, 1), Token::ShortOption); + } + + any_option_processed = true; + } + } + else if ( currentArg[0] == '@' && currentArg.size() > 1 ) + { + // suboptions file + _parse_sub_file(currentArg.substr(1)); + } + else + { + _add_token(currentArg, any_option_processed ? Token::UnknownYet : Token::GlobalArgument); + } + } + + _last = _Option::OK; // TODO: IMPROVE!! +} + +GETOPT_INLINE void GetOpt_pp::_argc_argv_to_vector(int argc, const char* const* const argv, std::vector<std::string>& args) +{ + for (int i = 0; i < argc; i++) + args.push_back(argv[i]); +} + +GETOPT_INLINE GetOpt_pp::TokensDeleter::~TokensDeleter() +{ + Token* next; + Token* current(_first); + while (current != NULL) + { + next = current->next; + delete current; + current = next; + } +} + +GETOPT_INLINE GetOpt_pp::GetOpt_pp(int argc, const char* const* const argv) + : _exc(std::ios_base::goodbit), _first_token(NULL), _last_token(NULL), _tokens_deleter(_first_token) +{ + _init_flags(); + std::vector<std::string> args; + _argc_argv_to_vector(argc, argv, args); + _parse(args); +} + +GETOPT_INLINE GetOpt_pp::GetOpt_pp(int argc, const char* const* const argv, _EnvTag) + : _first_token(NULL), _last_token(NULL), _tokens_deleter(_first_token) +{ + _init_flags(); + std::vector<std::string> args; + _argc_argv_to_vector(argc, argv, args); + _parse(args); +} + +GETOPT_INLINE GetOpt_pp& GetOpt_pp::operator >> (const _Option& opt) +{ + if (_last != _Option::ParsingError) + { + _last = opt(_shortOps, _longOps, _first_token, _flags); + + switch (_last) + { + case _Option::OK: + break; + + case _Option::OptionNotFound: + if (_exc & std::ios_base::eofbit) + throw OptionNotFoundEx(); + break; + + case _Option::BadType: + if (_exc & std::ios_base::failbit) + throw InvalidFormatEx(); + break; + + case _Option::NoArgs: + if (_exc & std::ios_base::eofbit) + throw ArgumentNotFoundEx(); + break; + + case _Option::TooManyArgs: + if (_exc & std::ios_base::failbit) + throw TooManyArgumentsEx(); + break; + + case _Option::OptionNotFound_NoEx: + break; // Ok, it will be read by casting to bool + + case _Option::ParsingError: + break; // just to disable warning + } + } + else if (_exc & std::ios_base::failbit) + throw ParsingErrorEx(); + + return *this; +} + +GETOPT_INLINE GetOpt_pp& GetOpt_pp::operator >> (std::ios_base & (*iomanip)(std::ios_base&)) +{ + std::stringstream ss; + ss.flags(_flags); + _flags = (ss << iomanip).flags(); + return *this; +} + +GETOPT_INLINE bool GetOpt_pp::options_remain() const +{ + bool remain = false; + ShortOptions::const_iterator it = _shortOps.begin(); + while (it != _shortOps.end() && !remain) + { + remain = (it->second.flags == OptionData::CmdLine_NotExtracted); + ++it; + } + + if (!remain) + { + LongOptions::const_iterator it = _longOps.begin(); + while (it != _longOps.end() && !remain) + { + remain = (it->second.flags == OptionData::CmdLine_NotExtracted); + ++it; + } + } + + if (!remain) + { + // check for the global arguments: + Token* token = _first_token; + while (!remain && token != NULL) + { + remain = (token->type == Token::GlobalArgument || token->type == Token::UnknownYet); + token = token->next; + } + } + + return remain; +} + +} diff --git a/tools/iDSK/src/getopt_pp.h b/tools/iDSK/src/getopt_pp.h new file mode 100644 index 0000000..117575f --- /dev/null +++ b/tools/iDSK/src/getopt_pp.h @@ -0,0 +1,745 @@ +/* +GetOpt_pp: Yet another C++ version of getopt. + This file is part of GetOpt_pp. + + Copyright (C) Daniel Gutson, FuDePAN 2007-2010 + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt in the root directory or + copy at http://www.boost.org/LICENSE_1_0.txt) + + GetOpt_pp IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#ifndef GETOPT_PP_H +#define GETOPT_PP_H + +#include <string> +#include <vector> // candidate to be removed +#include <map> +#include <sstream> +#include <list> + +/* + DESIGN GOALS: + - EASY to use + - EASY to learn + - mimc STL's streams + - EASY to extend +*/ + +#ifndef GETOPT_INLINE +# define GETOPT_INLINE +#endif + +namespace GetOpt +{ + +struct Token +{ + enum Type + { + ShortOption, + LongOption, + GlobalArgument, + GlobalArgumentUsed, // already read, skip in the next read + OptionArgument, + PossibleNegativeArgument, + UnknownYet // can be a global option, or an option of the previous one + }; + + Type type; + std::string value; + Token* next; + + Token(const std::string& value, Type type = UnknownYet) + : type(type), value(value), next(NULL) + {} + + bool is_last() const + { + return next == NULL; + } + + void link_to(Token* new_next) + { + next = new_next; + } + + Token* get_next_option_argument() const + { + if (is_last()) + return NULL; + else + { + if (next->type == UnknownYet || next->type == OptionArgument || next->type == PossibleNegativeArgument) + return next; + else + return NULL; + } + } +}; + +struct OptionData +{ + enum _Flags + { + CmdLine_NotExtracted, + CmdLine_Extracted, + Envir + }; + + _Flags flags; + Token* token; + OptionData() : flags(CmdLine_NotExtracted) {} +}; + +typedef std::map<std::string, OptionData> LongOptions; +typedef std::map<char, OptionData> ShortOptions; + + +struct _Option +{ + enum Result + { + OK, + ParsingError, + OptionNotFound, + BadType, + NoArgs, + TooManyArgs, + OptionNotFound_NoEx + }; + + virtual Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* first, std::ios::fmtflags flags) const = 0; + virtual ~_Option() {} + + static const char NO_SHORT_OPT = 0; +protected: + static void setTokenAsUsed(Token* token, ShortOptions& short_ops, Token::Type usedAs) + { + if (token->type == Token::PossibleNegativeArgument) + short_ops.erase(token->value[1]); + + token->type = usedAs; + } +}; + +template <class T> inline _Option::Result convert(const std::string& s, T& result, std::ios::fmtflags flags) +{ + std::stringstream ss; + ss.clear(); + ss.flags(flags); + ss << s; + ss >> result; + if (ss.fail() || !ss.eof()) + return _Option::BadType; + else + return _Option::OK; +} + +template <> inline _Option::Result convert<std::string>(const std::string& s, std::string& result, std::ios::fmtflags /*flags*/) +{ + result = s; + return _Option::OK; +} + + +template <class T> class _OptionTBase : public _Option +{ + const char short_opt; + const std::string long_opt; +protected: + T& target; + virtual Result _assign(Token* token, std::ios::fmtflags flags, ShortOptions& short_ops) const = 0; + +public: + _OptionTBase(const _OptionTBase<T>& other) + : _Option(), short_opt(other.short_opt), long_opt(other.long_opt), target(other.target) + {} + + _OptionTBase(char short_opt, const std::string& long_opt, T& target) + : short_opt(short_opt), long_opt(long_opt), target(target) + {} + + virtual Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* /*first*/, std::ios::fmtflags flags) const + { + Result ret = OptionNotFound; + ShortOptions::iterator it; + if (short_opt == _Option::NO_SHORT_OPT) + it = short_ops.end(); + else + it = short_ops.find(short_opt); + + if (it != short_ops.end()) + { + it->second.flags = OptionData::CmdLine_Extracted; + ret = _assign(it->second.token, flags, short_ops); + } + else if (!long_opt.empty()) + { + LongOptions::iterator it = long_ops.find(long_opt); + if (it != long_ops.end()) + { + it->second.flags = OptionData::CmdLine_Extracted; + ret = _assign(it->second.token, flags, short_ops); + } + } + + return ret; + } +}; + + +template <class T> class _OptionT : public _OptionTBase<T> +{ +protected: + virtual _Option::Result _assign(Token* token, std::ios::fmtflags flags, ShortOptions& short_ops) const + { + Token* const option_token = token->get_next_option_argument(); + if (option_token == NULL) + return _Option::NoArgs; + else + { + this->setTokenAsUsed(option_token, short_ops, Token::OptionArgument); + return convert<T>(option_token->value, this->target, flags); + } + } +public: + _OptionT(const _OptionT<T>& other) + : _OptionTBase<T>(other) + {} + + _OptionT(char short_opt, const std::string& long_opt, T& target) + : _OptionTBase<T>(short_opt, long_opt, target) + {} + +}; + +template <class T> class _OptionT<std::vector<T> > : public _OptionTBase<std::vector<T> > +{ +protected: + virtual _Option::Result _assign(Token* token, std::ios::fmtflags flags, ShortOptions& short_ops) const + { + Token* option_token = token->get_next_option_argument(); + if (option_token != NULL) + { + _Option::Result result; + //OptionArgs::const_iterator it = args.begin(); + T temp; + + do + { + this->setTokenAsUsed(option_token, short_ops, Token::OptionArgument); + result = convert<T>(option_token->value, temp, flags); + if (result == _Option::OK) + this->target.push_back(temp); + + option_token = option_token->get_next_option_argument(); + } + while (option_token != NULL && result == _Option::OK); + + return result; + } + else + return _Option::NoArgs; + } + +public: + _OptionT(const _OptionT<std::vector<T> >& other) + : _OptionTBase<std::vector<T> >(other) + {} + + _OptionT(char short_opt, const std::string& long_opt, std::vector<T>& target) + : _OptionTBase<std::vector<T> >(short_opt, long_opt, target) + {} +}; + + +template <class T, class BaseOption> +class _DefValOption : public BaseOption +{ + const T default_value; +public: + + _DefValOption(const _DefValOption<T, BaseOption>& other) + : BaseOption(other), default_value(other.default_value) + {} + + _DefValOption(char short_opt, const std::string& long_opt, T& target, const T& default_value) + : BaseOption(short_opt, long_opt, target), default_value(default_value) + {} + + virtual _Option::Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* first, std::ios::fmtflags flags) const + { + _Option::Result ret = BaseOption::operator()(short_ops, long_ops, first, flags); + + if (ret == _Option::OptionNotFound) + { + this->target = default_value; + ret = _Option::OK; + } + + return ret; + } +}; + +template <class T> +class _GlobalOption : public _Option +{ + T& target; + virtual Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* first, std::ios::fmtflags flags) const + { + // find first token GlobalArgument or UnknownYet (candidate) or PossibleNegativeArgument (candidate too) + Token* token(first); + bool found(false); + while (token != NULL && !found) + { + found = (token->type == Token::GlobalArgument || token->type == Token::UnknownYet || token->type == Token::PossibleNegativeArgument); + if (!found) + token = token->next; + } + if (found) + { + this->setTokenAsUsed(token, short_ops, Token::GlobalArgumentUsed); + return convert<T>(token->value, target, flags); + } + else + return OptionNotFound; + } +public: + _GlobalOption(const _GlobalOption<T>& other) + : target(other.target) + {} + + _GlobalOption(T& target) + : target(target) + {} +}; + +template <class T> +class _GlobalOption<std::vector<T> > : public _Option +{ + std::vector<T>& target; + virtual Result operator()(ShortOptions& short_ops, LongOptions& /*long_ops*/, Token* first, std::ios::fmtflags flags) const + { + // find first token GlobalArgument or UnknownYet (candidate) or PossibleNegativeArgument (candidate too) + Token* token(first); + bool found_any(false); + T tmp; + Result res(OK); + + while (token != NULL && res == OK) + { + if (token->type == Token::GlobalArgument || token->type == Token::UnknownYet || token->type == Token::PossibleNegativeArgument) + { + res = convert<T>(token->value, tmp, flags); + if (res == OK) + { + this->setTokenAsUsed(token, short_ops, Token::GlobalArgumentUsed); + found_any = true; + target.push_back(tmp); + } + } + token = token->next; + } + if (res == OK) + { + if (found_any) + return res; + else + return OptionNotFound; + } + else + return res; + } +public: + _GlobalOption(const _GlobalOption<std::vector<T> >& other) + : target(other.target) + {} + + _GlobalOption(std::vector<T>& target) + : target(target) + {} +}; + +template <class T> +inline _OptionT<T> Option(char short_opt, const std::string& long_opt, T& target) +{ + return _OptionT<T>(short_opt, long_opt, target); +} + +template <class T> +inline _OptionT<T> Option(char short_opt, T& target) +{ + return _OptionT<T>(short_opt, std::string(), target); +} + +// LongOpt only +template <class T> +inline _OptionT<T> Option(const std::string& long_opt, T& target) +{ + return _OptionT<T>(_Option::NO_SHORT_OPT, long_opt, target); +} + +// Defaulted version +template <class T> +inline _DefValOption<T, _OptionT<T> > +Option(char short_opt, const std::string& long_opt, T& target, const T& def) +{ + return _DefValOption<T, _OptionT<T> >(short_opt, long_opt, target, def); +} + +template <class T> +inline _DefValOption<T, _OptionT<T> > Option(char short_opt, T& target, const T& def) +{ + return _DefValOption<T, _OptionT<T> >(short_opt, std::string(), target, def); +} + +// no short opt. +template <class T> +inline _DefValOption<T, _OptionT<T> > +Option(const std::string& long_opt, T& target, const T& def) +{ + return _DefValOption<T, _OptionT<T> >(_Option::NO_SHORT_OPT, long_opt, target, def); +} + +// Defaults for strings: +inline _DefValOption<std::string, _OptionT<std::string> > +Option(char short_opt, const std::string& long_opt, std::string& target, const char* def) +{ + return _DefValOption<std::string, _OptionT<std::string> >(short_opt, long_opt, target, def); +} + +inline _OptionT<std::string> Option(char short_opt, std::string& target, const char* def) +{ + return _DefValOption<std::string, _OptionT<std::string> >(short_opt, std::string(), target, def); +} + +// no short opt. +inline _DefValOption<std::string, _OptionT<std::string> > +Option(const std::string& long_opt, std::string& target, const char* def) +{ + return _DefValOption<std::string, _OptionT<std::string> >(_Option::NO_SHORT_OPT, long_opt, target, def); +} + +// Global Option: +template <class T> +inline _GlobalOption<T> GlobalOption(T& target) +{ + return _GlobalOption<T>(target); +} + +class OptionPresent : public _Option +{ + const char short_opt; + const std::string long_opt; + bool* const present; +public: + // two combinations: with/without target, and with/without long opt. + + // WITH long_opt: + OptionPresent(char short_opt, const std::string& long_opt, bool& present) + : short_opt(short_opt), long_opt(long_opt), present(&present) + {} + + OptionPresent(char short_opt, const std::string& long_opt) + : short_opt(short_opt), long_opt(long_opt), present(NULL) + {} + + // WITHOUT long_opt: + OptionPresent(char short_opt, bool& present) + : short_opt(short_opt), present(&present) + {} + + OptionPresent(char short_opt) + : short_opt(short_opt), present(NULL) + {} + + // WITHOUT short_opt + OptionPresent(const std::string& long_opt, bool& present) + : short_opt(_Option::NO_SHORT_OPT), long_opt(long_opt), present(&present) + {} + + OptionPresent(const std::string& long_opt) + : short_opt(_Option::NO_SHORT_OPT), long_opt(long_opt), present(NULL) + {} +protected: + virtual Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* /*first*/, std::ios::fmtflags /*flags*/) const + { + bool found; + ShortOptions::iterator it = short_ops.find(short_opt); + + found = (it != short_ops.end()); + if (found) + { + it->second.flags = OptionData::CmdLine_Extracted; + } + else if (!long_opt.empty()) + { + LongOptions::iterator it = long_ops.find(long_opt); + found = (it != long_ops.end()); + if (found) + { + it->second.flags = OptionData::CmdLine_Extracted; + } + } + + if (present != NULL) + { + *present = found; + return OK; + } + else + { + return found ? OK : OptionNotFound_NoEx; + } + } +}; + +class GetOptEx : public std::exception {}; +struct ParsingErrorEx : GetOptEx {}; +struct InvalidFormatEx : GetOptEx {}; +struct ArgumentNotFoundEx : GetOptEx {}; +struct TooManyArgumentsEx : GetOptEx {}; +struct OptionNotFoundEx : GetOptEx {}; +struct TooManyOptionsEx : GetOptEx {}; +struct OptionsFileNotFoundEx : GetOptEx +{ + const std::string targetFile; + OptionsFileNotFoundEx(const std::string& file) : targetFile(file) {} + ~OptionsFileNotFoundEx() throw() {} +}; + +enum _EnvTag +{ + Include_Environment +}; + +class GetOpt_pp +{ + ShortOptions _shortOps; + LongOptions _longOps; + std::ios_base::iostate _exc; + _Option::Result _last; + std::ios::fmtflags _flags; + std::string _app_name; + Token* _first_token; + Token* _last_token; + + class TokensDeleter + { + Token*& _first; + public: + TokensDeleter(Token*& first) : _first(first) {} + + GETOPT_INLINE ~TokensDeleter(); + }; + + TokensDeleter _tokens_deleter; + + GETOPT_INLINE Token* _add_token(const std::string& value, Token::Type type); + GETOPT_INLINE void _init_flags(); + GETOPT_INLINE void _parse(const std::vector<std::string>& args); + GETOPT_INLINE void _parse_env(); + static GETOPT_INLINE void _argc_argv_to_vector(int argc, const char* const* const argv, std::vector<std::string>& args); + GETOPT_INLINE void _parse_sub_file(const std::string& file); +public: + GETOPT_INLINE GetOpt_pp(int argc, const char* const* const argv); + GETOPT_INLINE GetOpt_pp(int argc, const char* const* const argv, _EnvTag); + + std::ios_base::iostate exceptions() const + { + return _exc; + } + void exceptions(std::ios_base::iostate except) + { + _exc = except; + } + void exceptions_all() + { + _exc = std::ios_base::failbit | std::ios_base::eofbit; + } + + operator bool() const + { + return _last == _Option::OK; + } + + GETOPT_INLINE bool options_remain() const; + + void end_of_options() const + { + if (options_remain() && (_exc & std::ios_base::eofbit)) + throw TooManyOptionsEx(); + } + + std::ios::fmtflags flags() const + { + return _flags; + } + void flags(std::ios::fmtflags flags) + { + _flags = flags; + } + + const std::string& app_name() const + { + return _app_name; + } + + GETOPT_INLINE GetOpt_pp& operator >> (const _Option& opt); + + GETOPT_INLINE GetOpt_pp& operator >> (std::ios_base& (*iomanip)(std::ios_base&)); + + // Alternative to manipulators, for those who don't like them: the 'getopt' method :) + // Combination 1: with long option: + template <class T> inline T getopt(char short_opt, const std::string& long_opt) + { + T result; + operator >> (Option(short_opt, long_opt, result)); + return result; + } + + template <class T> inline T getopt(char short_opt, const std::string& long_opt, const T& def_value) + { + T result; + operator >> (Option(short_opt, long_opt, result, def_value)); + return result; + } + + // Combination 2: without long option: + template <class T> inline T getopt(char short_opt) + { + T result; + operator >> (Option(short_opt, result)); + return result; + } + + template <class T> inline T getopt(char short_opt, const T& def_value) + { + T result; + operator >> (Option(short_opt, result, def_value)); + return result; + } + + struct ItCtorData + { + ShortOptions::const_iterator short_iter; + LongOptions::const_iterator long_iter; + GetOpt_pp* getopt_pp; + }; + + template <class Container, class Adapter, class OptionType> + class _iterator + { + typename Container::const_iterator _it; + GetOpt_pp* _getopt_pp; + public: + _iterator(const ItCtorData& ctor_data) + { + _it = Adapter::adapt(ctor_data); + _getopt_pp = ctor_data.getopt_pp; + } + + _iterator() : _getopt_pp(NULL) + {} + + _iterator<Container, Adapter, OptionType>& operator = (const _iterator<Container, Adapter, OptionType>& other) + { + _it = other._it; + _getopt_pp = other._getopt_pp; + return *this; + } + + bool operator != (const _iterator<Container, Adapter, OptionType>& other) const + { + return _it != other._it; + } + + OptionType option() const + { + return _it->first; + } + OptionType operator*() const + { + return option(); + } + + _iterator<Container, Adapter, OptionType>& operator ++() + { + ++_it; + return *this; + } + + template <class T> + GetOpt_pp& operator >> (T& t) + { + Adapter::extract(t, *_getopt_pp, option()); + return *_getopt_pp; + } + }; + + ItCtorData begin() + { + ItCtorData ret; + ret.short_iter = _shortOps.begin(); + ret.long_iter = _longOps.begin(); + ret.getopt_pp = this; + return ret; + } + + ItCtorData end() + { + ItCtorData ret; + ret.short_iter = _shortOps.end(); + ret.long_iter = _longOps.end(); + ret.getopt_pp = this; + return ret; + } + + struct ShortAdapter + { + static ShortOptions::const_iterator adapt(const ItCtorData& data) + { + return data.short_iter; + } + + template <class T> + static void extract(T& t, GetOpt_pp& getopt_pp, char option) + { + getopt_pp >> Option(option, t); + } + }; + + struct LongAdapter + { + static LongOptions::const_iterator adapt(const ItCtorData& data) + { + return data.long_iter; + } + + template <class T> + static void extract(T& t, GetOpt_pp& getopt_pp, const std::string& option) + { + getopt_pp >> Option('\0', option, t); + } + }; + + typedef _iterator<ShortOptions, ShortAdapter, char> short_iterator; + typedef _iterator<LongOptions, LongAdapter, const std::string&> long_iterator; +}; + +class Environment +{ + // Coming soon! +}; + +} + +#endif |