aboutsummaryrefslogtreecommitdiff
path: root/tools/iDSK/src
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2023-11-05 11:22:55 +0000
committerJuan J. Martinez <jjm@usebox.net>2023-11-05 11:31:28 +0000
commit2fbdf974338bde8576efdae40a819a76b2391033 (patch)
tree64d41a37470143f142344f9a439d96de3e7918c2 /tools/iDSK/src
downloadkitsunes-curse-2fbdf974338bde8576efdae40a819a76b2391033.tar.gz
kitsunes-curse-2fbdf974338bde8576efdae40a819a76b2391033.zip
Initial import of the open source release
Diffstat (limited to 'tools/iDSK/src')
-rw-r--r--tools/iDSK/src/Ascii.cpp16
-rw-r--r--tools/iDSK/src/Ascii.h6
-rw-r--r--tools/iDSK/src/Basic.cpp359
-rw-r--r--tools/iDSK/src/Basic.h8
-rw-r--r--tools/iDSK/src/BitmapCPC.cpp264
-rw-r--r--tools/iDSK/src/BitmapCPC.h46
-rw-r--r--tools/iDSK/src/Dams.cpp184
-rw-r--r--tools/iDSK/src/Dams.h8
-rw-r--r--tools/iDSK/src/Desass.cpp553
-rw-r--r--tools/iDSK/src/Desass.h8
-rw-r--r--tools/iDSK/src/GestDsk.cpp1173
-rw-r--r--tools/iDSK/src/GestDsk.h176
-rw-r--r--tools/iDSK/src/Main.cpp309
-rw-r--r--tools/iDSK/src/Main.h16
-rw-r--r--tools/iDSK/src/MyType.h20
-rw-r--r--tools/iDSK/src/Outils.cpp165
-rw-r--r--tools/iDSK/src/Outils.h19
-rw-r--r--tools/iDSK/src/ViewFile.cpp44
-rw-r--r--tools/iDSK/src/ViewFile.h10
-rw-r--r--tools/iDSK/src/endianPPC.cpp24
-rw-r--r--tools/iDSK/src/endianPPC.h22
-rw-r--r--tools/iDSK/src/firmware.h308
-rw-r--r--tools/iDSK/src/getopt_pp.cpp269
-rw-r--r--tools/iDSK/src/getopt_pp.h745
24 files changed, 4752 insertions, 0 deletions
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