/*******************************************************************************
PROGRAM NAME    : ATARI XFD FILE MONITOR
                 written by Philippe VUILLERME (c) PVBest 2001
--------------------------------------------------------------------------------
  -Made in Savoie- (France)
  Atari XFD ROM FILE MONITOR is for education and fun purpose only...
  I make no profit. It's a freeware for the Atari fans and lovers !
--------------------------------------------------------------------------------
USAGE           : DISASSEMBLY AND OTHER STUFFS...
                  for the Atari 8 bits XFD format Rom files !!!
SYSTEM          : PC MS-DOS
NOTA            : XFD PC FILE FORMAT 1040*128 byte max (133120)
                  = Max File Lenght for the OPEN Command
SPECIAL COMMENT : ATARI IS STILL ALIVE! So Use and Enjoy!
NORMAL COMMENT  : XFD FILE MONITOR is currently under Revision 2.00
                  The revision 2.00 is the first public released for Beta Test
CREDITS         : Thanks to the following people who help me:
- All people from the Atari 800 Emulator Project : parts of desassembly
  code of my monitor.cpp is based upon the 'monitor.c' of the
  Atari 800 Emulator by David Firth and his Emulator development team.
  "This code and my software are yours !"
- Disassembly address mnemonic table is part of disassembler by Erich BACHER
- Bug reported; COLPM0 at $0012 instead of $D012,
  addresses comments added, 6502 opcode name and type charts merged.
- Thanks for all people making Atari lives through our PC computers!

REM             : Atari is a registered trademark.
                  MS-DOS and Windows are registered Trademarsk of Microsoft Corp
------------------------------------------------------------------------------*/
//
//<--------------------------**| REVISION HISTORY |**-------------------------->
// Revision     | Date:     | What:
//<-------------|-----------|-------------------------------------------------->
// 2.00         | June 2001 | First Public Released for Beta Test
//<---------------------------------------------------------------------------->

#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <conio.h>


// #include "com.h"

#define FALSE   0
#define TRUE    1
#define MAX_FILE_LENGTH 133120
#define UWORD short unsigned int
#define UBYTE unsigned char
#define UINT unsigned int

void Disassemble(int dflag);
UWORD Show_Instruction(UWORD inad, UINT pm, int wid);
void Show_Disassembly(int flag_label);
int Show_Label(UWORD dis_addr);
UBYTE Current_Instruction();

static UINT lastpos;
static UINT currpos = 0;
static UWORD curraddr = 0x700;
static UWORD lastaddr;
static UWORD currsect = 1;
static UWORD numbersect = 0;
static UWORD xbytsect = 0x80;
char   open_filename[32];
static int FILE_SIZE = -1;  //for futur use...
 //-1 : pas de fichier ouvert
 //>= 0 : fichier XFD ouvert et taille en memoire

UBYTE file_in_memory[MAX_FILE_LENGTH];
UBYTE tmp_file_mem[65536]; // pour les fichiers Atari

//UWORD assembler(UWORD addr);

typedef struct {
	UWORD file_header;
	UWORD file_startaddr;
	UWORD file_endaddr;
	UWORD file_firstsect;
	UINT  file_firstpos;
	UWORD file_size;
	UWORD file_nbsect;
	} ATR_FILE;

/* FOR MONITOR_HINTS : Taken for Atari Emulator        *****************************/
typedef struct {
    char name[9];  /* max. 8 characters */
    UWORD addr;
  } symtable_rec;

  /*SYMBOL NAMES TAKEN FROM atari.equ - part of disassembler by Erich BACHER 
    and from GTIA.H, POKEY.H, PIA.H & ANTIC.H                                */
  /*Note: all symbols must be sorted by address (binary search is used).
    Maximal length of symbol name is 8 characters (can be changed above).
    If the adress has different names when reading/writting to it (GTIA ports),
    put the READ NAME FIRST. */
    
symtable_rec symtable[] = {
    {"NGFLAG",  0x0001}, {"CASINI",  0x0002}, {"CASINI+1",0x0003}, {"RAMLO",   0x0004},
    {"RAMLO+1", 0x0005}, {"TRAMSZ",  0x0006}, {"CMCMD",   0x0007}, {"WARMST",  0x0008},
    {"BOOT",    0x0009}, {"DOSVEC",  0x000a}, {"DOSVEC+1",0x000b}, {"DOSINI",  0x000c},
    {"DOSINI+1",0x000d}, {"APPMHI",  0x000e}, {"APPMHI+1",0x000f}, {"POKMSK",  0x0010},
    {"BRKKEY",  0x0011}, {"RTCLOK",  0x0012}, {"RTCLOK+1",0x0013}, {"RTCLOK+2",0x0014},
    {"BUFADR",  0x0015}, {"BUFADR+1",0x0016}, {"ICCOMT",  0x0017}, {"DSKFMS",  0x0018},
    {"DSKFMS+1",0x0019}, {"DSKUTL",  0x001a}, {"DSKUTL+1",0x001b}, {"ABUFPT",  0x001c},
    {"ABUFPT+1",0x001d}, {"ABUFPT+2",0x001e}, {"ABUFPT+3",0x001f},
    {"ICHIDZ",  0x0020}, {"ICDNOZ",  0x0021}, {"ICCOMZ",  0x0022}, {"ICSTAZ",  0x0023},
    {"ICBALZ",  0x0024}, {"ICBAHZ",  0x0025}, {"ICPTLZ",  0x0026}, {"ICPTHZ",  0x0027},
    {"ICBLLZ",  0x0028}, {"ICBLHZ",  0x0029}, {"ICAX1Z",  0x002A}, {"ICAX2Z",  0x002B},
    {"ICAX3Z",  0x002C}, {"ICAX4Z",  0x002D}, {"ICAX5Z",  0x002E}, {"ICAX6Z",  0x002F},
    {"STATUS",  0x0030}, {"CHKSUM",  0x0031}, {"BUFRLO",  0x0032}, {"BUFRHI",  0x0033},
    {"BFENLO",  0x0034}, {"BFENHI",  0x0035}, {"LTEMP" ,  0x0036}, {"LTEMP+1", 0x0037},
    {"BUFRFL",  0x0038}, {"RECVDN",  0x0039}, {"XMTDON",  0x003A}, {"CHKSNT",  0x003B},
    {"NOCKSM",  0x003C}, {"BPTR"  ,  0x003D}, {"FTYPE" ,  0x003E}, {"FEOF"  ,  0x003F},
    {"FREQ"  ,  0x0040}, {"SOUNDR",  0x0041}, {"CRITIC",  0x0042}, {"FMSZPG",  0x0043},
    {"FMSZPG+1",0x0044}, {"FMSZPG+2",0x0045}, {"FMSZPG+3",0x0046}, {"FMSZPG+4",0x0047},
    {"FMSZPG+5",0x0048}, {"FMSZPG+6",0x0049}, {"ZCHAIN",  0x004A}, {"ZCHAIN+1",0x004B},
    {"DSTAT" ,  0x004C}, {"ATRACT",  0x004D}, {"DRKMSK",  0x004E}, {"COLRSH",  0x004F},
    {"TEMP"  ,  0x0050}, {"HOLD1" ,  0x0051}, {"LMARGN",  0x0052}, {"RMARGN",  0x0053},
    {"ROWCRS",  0x0054}, {"COLCRS",  0x0055}, {"COLCRS+1",0x0056}, {"DINDEX",  0x0057},
    {"SAVMSC",  0x0058}, {"SAVMSC+1",0x0059}, {"OLDROW",  0x005A}, {"OLDCOL",  0x005B},
    {"OLDCOL+1",0x005C}, {"OLDCHR",  0x005D}, {"OLDADR",  0x005E}, {"OLDADR+1",0x005F},
    {"FKDEF" ,  0x0060}, {"FKDEF+1", 0x0061}, {"PALNTS",  0x0062}, {"LOGCOL",  0x0063},
    {"ADRESS",  0x0064}, {"ADRESS+1",0x0065}, {"MLTTMP",  0x0066}, {"MLTTMP+1",0x0067},
    {"SAVADR",  0x0068}, {"SAVADR+1",0x0069}, {"RAMTOP",  0x006A}, {"BUFCNT",  0x006B},
    {"BUFSTR",  0x006C}, {"BUFSTR+1",0x006D}, {"BITMSK",  0x006E}, {"SHFAMT",  0x006F},
    {"ROWAC" ,  0x0070}, {"ROWAC+1", 0x0071}, {"COLAC" ,  0x0072}, {"COLAC+1", 0x0073},
    {"ENDPT" ,  0x0074}, {"ENDPT+1", 0x0075}, {"DELTAR",  0x0076}, {"DELTAC",  0x0077},
    {"DELTAC+1",0x0078}, {"KEYDEF",  0x0079}, {"KEYDEF+1",0x007A}, {"SWPFLG",  0x007B},
    {"HOLDCH",  0x007C}, {"INSDAT",  0x007D}, {"COUNTR",  0x007E}, {"COUNTR+1",0x007F},
    {"LOMEM" ,  0x0080}, {"LOMEM+1", 0x0081}, {"VNTP"  ,  0x0082}, {"VNTP+1",  0x0083},
    {"VNTD"  ,  0x0084}, {"VNTD+1",  0x0085}, {"VVTP"  ,  0x0086}, {"VVTP+1",  0x0087},
    {"STMTAB",  0x0088}, {"STMTAB+1",0x0089}, {"STMCUR",  0x008A}, {"STMCUR+1",0x008B},
    {"STARP" ,  0x008C}, {"STARP+1", 0x008D}, {"RUNSTK",  0x008E}, {"RUNSTK+1",0x008F},
    {"TOPSTK",  0x0090}, {"TOPSTK+1",0x0091}, {"MEOLFLG", 0x0092}, {"POKADR",  0x0095},
    {"POKADR+1",0x0096}, {"DATAD" ,  0x00B6}, {"DATALN",  0x00B7}, {"DATALN+1",0x00B8},
    {"STOPLN",  0x00BA}, {"STOPLN+1",0x00BB}, {"SAVCUR",  0x00BE}, {"IOCMD" ,  0x00C0},
    {"IODVC" ,  0x00C1}, {"PROMPT",  0x00C2}, {"ERRSAVE", 0x00C3}, {"COLOUR",  0x00C8},
    {"PTABW" ,  0x00C9}, {"LOADFLG", 0x00CA}, {"FR0"   ,  0x00D4}, {"FR0+1" ,  0x00D5},
    {"FR0+2" ,  0x00D6}, {"FR0+3" ,  0x00D7}, {"FR0+4" ,  0x00D8}, {"FR0+5" ,  0x00D9},
    {"FRE"   ,  0x00DA}, {"FRE+1" ,  0x00DB}, {"FRE+2" ,  0x00DC}, {"FRE+3" ,  0x00DD},
    {"FRE+4" ,  0x00DE}, {"FRE+5" ,  0x00DF}, {"FR1"   ,  0x00E0}, {"FR1+1" ,  0x00E1},
    {"FR1+2" ,  0x00E2}, {"FR1+3" ,  0x00E3}, {"FR1+4" ,  0x00E4}, {"FR1+5" ,  0x00E5},
    {"FR2"   ,  0x00E6}, {"FR2+1" ,  0x00E7}, {"FR2+2" ,  0x00E8}, {"FR2+3" ,  0x00E9},
    {"FR2+4" ,  0x00EA}, {"FR2+5" ,  0x00EB}, {"FRX"   ,  0x00EC}, {"EEXP"  ,  0x00ED},
    {"NSIGN" ,  0x00EE}, {"ESIGN" ,  0x00EF}, {"FCHRFLG", 0x00F0}, {"DIGRT" ,  0x00F1},
    {"CIX"   ,  0x00F2}, {"INBUFF",  0x00F3}, {"INBUFF+1",0x00F4}, {"ZTEMP1",  0x00F5},
    {"ZTEMP1+1",0x00F6}, {"ZTEMP4",  0x00F7}, {"ZTEMP4+1",0x00F8}, {"ZTEMP3",  0x00F9},
    {"ZTEMP3+1",0x00FA}, {"RADFLG",  0x00FB}, {"FLPTR" ,  0x00FC}, {"FLPTR+1", 0x00FD},
    {"FPTR2" ,  0x00FE}, {"FPTR2+1", 0x00FF}, {"STACK" ,  0x0100}, /*Stack up to 1FF */

    {"VDSLST",  0x0200}, {"VDSLST+1",0x0201}, {"VPRCED",  0x0202}, {"VPRCED+1",0x0203},
    {"VINTER",  0x0204}, {"VINTER+1",0x0205}, {"VBREAK",  0x0206}, {"VBREAK+1",0x0207},
    {"VKEYBD",  0x0208}, {"VKEYBD+1",0x0209}, {"VSERIN",  0x020A}, {"VSERIN+1",0x020B},
    {"VSEROR",  0x020C}, {"VSEROR+1",0x020D}, {"VSEROC",  0x020E}, {"VSEROC+1",0x020F},
    {"VTIMR1",  0x0210}, {"VTIMR1+1",0x0211}, {"VTIMR2",  0x0212}, {"VTIMR2+1",0x0213},
    {"VTIMR4",  0x0214}, {"VTIMR4+1",0x0215}, {"VIMIRQ",  0x0216}, {"VIMIRQ+1",0x0217},
    {"CDTMV1",  0x0218}, {"CDTMV1+1",0x0219}, {"CDTMV2",  0x021A}, {"CDTMV2+1",0x021B},
    {"CDTMV3",  0x021C}, {"CDTMV3+1",0x021D}, {"CDTMV4",  0x021E}, {"CDTMV4+1",0x021F},
    {"CDTMV5",  0x0220}, {"CDTMV5+1",0x0221}, {"VVBLKI",  0x0222}, {"VVBLKI+1",0x0223},
    {"VVBLKD",  0x0224}, {"VVBLKD+1",0x0225}, {"CDTMA1",  0x0226}, {"CDTMA1+1",0x0227},
    {"CDTMA2",  0x0228}, {"CDTMA2+1",0x0229}, {"CDTMF3",  0x022A}, {"SRTIMR",  0x022B},
    {"CDTMF4",  0x022C}, {"INTEMP",  0x022D}, {"CDTMF5",  0x022E}, {"SDMCTL",  0x022F},
    {"SDLSTL",  0x0230}, {"SDLSTH",  0x0231}, {"SSKCTL",  0x0232}, {"SPARE" ,  0x0233},
    {"LPENH" ,  0x0234}, {"LPENV" ,  0x0235}, {"BRKKY" ,  0x0236}, {"BRKKY+1", 0x0237},
    {"VPIRQ" ,  0x0238}, {"VPIRQ+1", 0x0239}, {"CDEVIC",  0x023A}, {"CCOMND",  0x023B},
    {"CAUX1" ,  0x023C}, {"CAUX2" ,  0x023D}, {"TMPSIO",  0x023E}, {"ERRFLG",  0x023F},
    {"DFLAGS",  0x0240}, {"DBSECT",  0x0241}, {"BOOTAD",  0x0242}, {"BOOTAD+1",0x0243},
    {"COLDST",  0x0244}, {"RECLEN",  0x0245}, {"DSKTIM",  0x0246}, {"PDVMSK",  0x0247},
    {"SHPDVS",  0x0248}, {"PDMSK" ,  0x0249}, {"RELADR",  0x024A}, {"RELADR+1",0x024B},
    {"PPTMPA",  0x024C}, {"PPTMPX",  0x024D}, {"CHSALT",  0x026B}, {"VSFLAG",  0x026C},
    {"KEYDIS",  0x026D}, {"FINE"  ,  0x026E}, {"GPRIOR",  0x026F}, {"PADDL0",  0x0270},
    {"PADDL1",  0x0271}, {"PADDL2",  0x0272}, {"PADDL3",  0x0273}, {"PADDL4",  0x0274},
    {"PADDL5",  0x0275}, {"PADDL6",  0x0276}, {"PADDL7",  0x0277}, {"STICK0",  0x0278},
    {"STICK1",  0x0279}, {"STICK2",  0x027A}, {"STICK3",  0x027B}, {"PTRIG0",  0x027C},
    {"PTRIG1",  0x027D}, {"PTRIG2",  0x027E}, {"PTRIG3",  0x027F}, {"PTRIG4",  0x0280},
    {"PTRIG5",  0x0281}, {"PTRIG6",  0x0282}, {"PTRIG7",  0x0283}, {"STRIG0",  0x0284},
    {"STRIG1",  0x0285}, {"STRIG2",  0x0286}, {"STRIG3",  0x0287}, {"HIBYTE",  0x0288},
    {"WMODE" ,  0x0289}, {"BLIM"  ,  0x028A}, {"IMASK" ,  0x028B}, {"JVECK" ,  0x028C},
    {"NEWADR",  0x028E}, {"TXTROW",  0x0290}, {"TXTCOL",  0x0291}, {"TXTCOL+1",0x0292},
    {"TINDEX",  0x0293}, {"TXTMSC",  0x0294}, {"TXTMSC+1",0x0295}, {"TXTOLD",  0x0296},
    {"TXTOLD+1",0x0297}, {"TXTOLD+2",0x0298}, {"TXTOLD+3",0x0299}, {"TXTOLD+4",0x029A},
    {"TXTOLD+5",0x029B}, {"CRETRY",  0x029C}, {"HOLD3" ,  0x029D}, {"SUBTMP",  0x029E},
    {"HOLD2" ,  0x029F}, {"DMASK" ,  0x02A0}, {"TMPLBT",  0x02A1}, {"ESCFLG",  0x02A2},
    {"TABMAP",  0x02A3}, {"TABMAP+1",0x02A4}, {"TABMAP+2",0x02A5}, {"TABMAP+3",0x02A6},
    {"TABMAP+4",0x02A7}, {"TABMAP+5",0x02A8}, {"TABMAP+6",0x02A9}, {"TABMAP+7",0x02AA},
    {"TABMAP+8",0x02AB}, {"TABMAP+9",0x02AC}, {"TABMAP+A",0x02AD}, {"TABMAP+B",0x02AE},
    {"TABMAP+C",0x02AF}, {"TABMAP+D",0x02B0}, {"TABMAP+E",0x02B1}, {"LOGMAP",  0x02B2},
    {"LOGMAP+1",0x02B3}, {"LOGMAP+2",0x02B4}, {"LOGMAP+3",0x02B5}, {"INVFLG",  0x02B6},
    {"FILFLG",  0x02B7}, {"TMPROW",  0x02B8}, {"TMPCOL",  0x02B9}, {"TMPCOL+1",0x02BA},
    {"SCRFLG",  0x02BB}, {"HOLD4" ,  0x02BC}, {"DRETRY",  0x02BD}, {"SHFLOC",  0x02BE},
    {"BOTSCR",  0x02BF}, {"PCOLR0",  0x02C0}, {"PCOLR1",  0x02C1}, {"PCOLR2",  0x02C2},
    {"PCOLR3",  0x02C3}, {"COLOR0",  0x02C4}, {"COLOR1",  0x02C5}, {"COLOR2",  0x02C6},
    {"COLOR3",  0x02C7}, {"COLOR4",  0x02C8}, {"RUNADR",  0x02C9}, {"RUNADR+1",0x02CA},
    {"HIUSED",  0x02CB}, {"HIUSED+1",0x02CC}, {"ZHIUSE",  0x02CD}, {"ZHIUSE+1",0x02CE},
    {"GBYTEA",  0x02CF}, {"GBYTEA+1",0x02D0}, {"LOADAD",  0x02D1}, {"LOADAD+1",0x02D2},
    {"ZLOADA",  0x02D3}, {"ZLOADA+1",0x02D4}, {"DSCTLN",  0x02D5}, {"DSCTLN+1",0x02D6},
    {"ACMISR",  0x02D7}, {"ACMISR+1",0x02D8}, {"KRPDER",  0x02D9}, {"KEYREP",  0x02DA},
    {"NOCLIK",  0x02DB}, {"HELPFG",  0x02DC}, {"DMASAV",  0x02DD}, {"PBPNT" ,  0x02DE},
    {"PBUFSZ",  0x02DF}, {"RUNAD" ,  0x02E0}, {"RUNAD+1", 0x02E1}, {"INITAD",  0x02E2},
    {"INITAD+1",0x02E3}, {"RAMSIZ",  0x02E4}, {"MEMTOP",  0x02E5}, {"MEMTOP+1",0x02E6},
    {"MEMLO" ,  0x02E7}, {"MEMLO+1", 0x02E8}, {"HNDLOD",  0x02E9}, {"DVSTAT",  0x02EA},
    {"DVSTAT+1",0x02EB}, {"DVSTAT+2",0x02EC}, {"DVSTAT+3",0x02ED}, {"CBAUDL",  0x02EE},
    {"CBAUDH",  0x02EF}, {"CRSINH",  0x02F0}, {"KEYDEL",  0x02F1}, {"CH1"   ,  0x02F2},
    {"CHACT" ,  0x02F3}, {"CHBAS" ,  0x02F4}, {"NEWROW",  0x02F5}, {"NEWCOL",  0x02F6},
    {"NEWCOL+1",0x02F7}, {"ROWINC",  0x02F8}, {"COLINC",  0x02F9}, {"CHAR"  ,  0x02FA},
    {"ATACHR",  0x02FB}, {"CH"    ,  0x02FC}, {"FILDAT",  0x02FD}, {"DSPFLG",  0x02FE},
    {"SSFLAG",  0x02FF},


    {"DDEVIC",  0x0300}, {"DUNIT"   ,0x0301}, {"DCOMND"  ,0x0302}, {"DSTATS"  ,0x0303},
    {"DBUFLO"  ,0x0304}, {"DBUFHI"  ,0x0305}, {"DTIMLO"  ,0x0306}, {"DUNUSE"  ,0x0307},
    {"DBYTLO"  ,0x0308}, {"DBYTHI"  ,0x0309}, {"DAUX1"   ,0x030A}, {"DAUX2"   ,0x030B},
    {"TIMER1"  ,0x030C}, {"TIMER1+1",0x030D}, {"ADDCOR"  ,0x030E}, {"CASFLG"  ,0x030F},
    {"TIMER2"  ,0x0310}, {"TIMER2+1",0x0311}, {"TEMP1"   ,0x0312}, {"TEMP1+1", 0x0313},
    {"TEMP2"   ,0x0314}, {"TEMP3"   ,0x0315}, {"SAVIO"   ,0x0316}, {"TIMFLG",  0x0317},
    {"STACKP",  0x0318}, {"TSTAT"   ,0x3019},
    {"HATABS",  0x0301a},  /*HATABS 1-34*/
    {"PUTBT1",  0x033d}, {"PUTBT2",  0x033e}, {"PUTBT3",  0x033f},
    {"B0-ICHID",0x0340}, {"B0-ICDNO",0x0341}, {"B0-ICCOM",0x0342}, {"B0-ICSTA",0x0343},
    {"B0-ICBAL",0x0344}, {"B0-ICBAH",0x0345}, {"B0-ICPTL",0x0346}, {"B0-ICPTH",0x0347},
    {"B0-ICBLL",0x0348}, {"B0-ICBLH",0x0349}, {"B0-ICAX1",0x034a}, {"B0-ICAX2",0x034b},
    {"B0-ICAX3",0x034c}, {"B0-ICAX4",0x034d}, {"B0-ICAX5",0x034e}, {"B0-ICAX6",0x034f},
    {"B1-ICHID",0x0350}, {"B1-ICDNO",0x0351}, {"B1-ICCOM",0x0352}, {"B1-ICSTA",0x0353},
    {"B1-ICBAL",0x0354}, {"B1-ICBAH",0x0355}, {"B1-ICPTL",0x0356}, {"B1-ICPTH",0x0357},
    {"B1-ICBLL",0x0358}, {"B1-ICBLH",0x0359}, {"B1-ICAX1",0x035a}, {"B1-ICAX2",0x035b},
    {"B1-ICAX3",0x035c}, {"B1-ICAX4",0x035d}, {"B1-ICAX5",0x035e}, {"B1-ICAX6",0x035f},
    {"B2-ICHID",0x0360}, {"B2-ICDNO",0x0361}, {"B2-ICCOM",0x0362}, {"B2-ICSTA",0x0363},
    {"B2-ICBAL",0x0364}, {"B2-ICBAH",0x0365}, {"B2-ICPTL",0x0366}, {"B2-ICPTH",0x0367},
    {"B2-ICBLL",0x0368}, {"B2-ICBLH",0x0369}, {"B2-ICAX1",0x036a}, {"B2-ICAX2",0x036b},
    {"B2-ICAX3",0x036c}, {"B2-ICAX4",0x036d}, {"B2-ICAX5",0x036e}, {"B2-ICAX6",0x036f},
    {"B3-ICHID",0x0370}, {"B3-ICDNO",0x0371}, {"B3-ICCOM",0x0372}, {"B3-ICSTA",0x0373},
    {"B3-ICBAL",0x0374}, {"B3-ICBAH",0x0375}, {"B3-ICPTL",0x0376}, {"B3-ICPTH",0x0377},
    {"B3-ICBLL",0x0378}, {"B3-ICBLH",0x0379}, {"B3-ICAX1",0x037a}, {"B3-ICAX2",0x037b},
    {"B3-ICAX3",0x037c}, {"B3-ICAX4",0x037d}, {"B3-ICAX5",0x037e}, {"B3-ICAX6",0x037f},
    {"B4-ICHID",0x0380}, {"B4-ICDNO",0x0381}, {"B4-ICCOM",0x0382}, {"B4-ICSTA",0x0383},
    {"B4-ICBAL",0x0384}, {"B4-ICBAH",0x0385}, {"B4-ICPTL",0x0386}, {"B4-ICPTH",0x0387},
    {"B4-ICBLL",0x0388}, {"B4-ICBLH",0x0389}, {"B4-ICAX1",0x038a}, {"B4-ICAX2",0x038b},
    {"B4-ICAX3",0x038c}, {"B4-ICAX4",0x038d}, {"B4-ICAX5",0x038e}, {"B4-ICAX6",0x038f},
    {"B5-ICHID",0x0390}, {"B5-ICDNO",0x0391}, {"B5-ICCOM",0x0392}, {"B5-ICSTA",0x0393},
    {"B5-ICBAL",0x0394}, {"B5-ICBAH",0x0395}, {"B5-ICPTL",0x0396}, {"B5-ICPTH",0x0397},
    {"B5-ICBLL",0x0398}, {"B5-ICBLH",0x0399}, {"B5-ICAX1",0x039a}, {"B5-ICAX2",0x039b},
    {"B5-ICAX3",0x039c}, {"B5-ICAX4",0x039d}, {"B5-ICAX5",0x039e}, {"B5-ICAX6",0x039f},
    {"B6-ICHID",0x03a0}, {"B6-ICDNO",0x03a1}, {"B6-ICCOM",0x03a2}, {"B6-ICSTA",0x03a3},
    {"B6-ICBAL",0x03a4}, {"B6-ICBAH",0x03a5}, {"B6-ICPTL",0x03a6}, {"B6-ICPTH",0x03a7},
    {"B6-ICBLL",0x03a8}, {"B6-ICBLH",0x03a9}, {"B6-ICAX1",0x03aa}, {"B6-ICAX2",0x03ab},
    {"B6-ICAX3",0x03ac}, {"B6-ICAX4",0x03ad}, {"B6-ICAX5",0x03ae}, {"B6-ICAX6",0x03af},
    {"B7-ICHID",0x03b0}, {"B7-ICDNO",0x03b1}, {"B7-ICCOM",0x03b2}, {"B7-ICSTA",0x03b3},
    {"B7-ICBAL",0x03b4}, {"B7-ICBAH",0x03b5}, {"B7-ICPTL",0x03b6}, {"B7-ICPTH",0x03b7},
    {"B7-ICBLL",0x03b8}, {"B7-ICBLH",0x03b9}, {"B7-ICAX1",0x03ba}, {"B7-ICAX2",0x03bb},
    {"B7-ICAX3",0x03bc}, {"B7-ICAX4",0x03bd}, {"B7-ICAX5",0x03be}, {"B7-ICAX6",0x03bf},
    {"PRNBUF",  0x03c0},  /*PRNBUF 1-39 */
    {"SUPERF",  0x03e8}, {"CKEY",    0x03e9}, {"CASSBT",  0x03ea}, {"CARTCK",  0x03eb},
    {"DERRF",   0x03ec}, {"ACMVAR",  0x03ed}, /*ACMVAR 1-10*/
    {"BASICF",  0x03f8}, {"MINTLK",  0x03f9}, {"GINTLK",  0x03fa}, {"CHLINK",  0x03fb},
    {"CHLINK+1",0x03fc}, {"CASBUF",  0x03fd}, /*CASBUF up to ?? 0x047F ??*/
    /* 0480 - 04FF not used ??? */
    /* 0500 - 057D spare ???    */
    /* 057E - 05FF tampon basic et virgule flottante */
    /* 0600 - 9FFF FREE RAM   */
    /* A000 - BFFF ROM BASIC or FREE RAM*/
    /* COOO - CFFF ROM O/S   */
    /* D000 - D0FF : GTIA    */
    {"M0PF"  ,0xd000}, {"HPOSP0",0xd000}, {"M1PF"  ,0xd001}, {"HPOSP1",0xd001}, 
    {"M2PF"  ,0xd002}, {"HPOSP2",0xd002}, {"M3PF"  ,0xd003}, {"HPOSP3",0xd003},
    {"P0PF"  ,0xd004}, {"HPOSM0",0xd004}, {"P1PF"  ,0xd005}, {"HPOSM1",0xd005},
    {"P2PF"  ,0xd006}, {"HPOSM2",0xd006}, {"P3PF"  ,0xd007}, {"HPOSM3",0xd007},
    {"M0PL"  ,0xd008}, {"SIZEP0",0xd008}, {"M1PL"  ,0xd009}, {"SIZEP1",0xd009}, 
    {"M2PL"  ,0xd00a}, {"HPOSP2",0xd00a}, {"M3PL"  ,0xd00b}, {"HPOSP3",0xd00b},
    {"P0PL"  ,0xd00c}, {"SIZEM", 0xd00c}, {"P1PL"  ,0xd00d}, {"GRAFP0",0xd00d}, 
    {"P2PL"  ,0xd00e}, {"GRAFP1",0xd00e}, {"P3PL"  ,0xd00f}, {"GRAFP2",0xd00f},
    {"TRIG0" ,0xd010}, {"GRAFP3",0xd010}, {"TRIG1" ,0xd011}, {"GRAFM", 0xd011}, 
    {"TRIG2" ,0xd012}, {"COLPM0",0xd012}, {"TRIG3" ,0xd013}, {"COLPM1",0xd013},
    {"PAL"   ,0xd014}, {"COLPM2",0xd014}, {"COLPM3",0xd015}, {"COLPF0",0xd016},
    {"COLPF1",0xd017},
    {"COLPF2",0xd018}, {"COLPF3",0xd019}, {"COLBK", 0xd01a}, {"PRIOR", 0xd01b},
    {"VDELAY",0xd01c}, {"GRACTL",0xd01d}, {"HITCLR",0xd01e}, {"CONSOL",0xd01f},
    /* D100 - D1FF : NOT USED */
    /* D200 - D2FF : POKEY    */    
    {"POT0"  ,0xd200}, {"AUDF1", 0xd200}, {"POT1"  ,0xd201}, {"AUDC1", 0xd201}, 
    {"POT2"  ,0xd202}, {"AUDF2", 0xd202}, {"POT3"  ,0xd203}, {"AUDC2", 0xd203},
    {"POT4"  ,0xd204}, {"AUDF3", 0xd204}, {"POT5"  ,0xd205}, {"AUDC3", 0xd205}, 
    {"POT6"  ,0xd206}, {"AUDF4", 0xd206}, {"POT7"  ,0xd207}, {"AUDC4", 0xd207},
    {"ALLPOT",0xd208}, {"AUDCTL",0xd208}, {"KBCODE",0xd209}, {"STIMER",0xd209}, 
    {"RANDOM",0xd20a}, {"SKREST",0xd20a}, {"POTGO", 0xd20b},
    {"SERIN", 0xd20d}, {"SEROUT",0xd20d}, {"IRQST", 0xd20e}, {"IRQEN", 0xd20e}, 
    {"SKSTAT",0xd20f}, {"SKCTL", 0xd20f},
    /* D300 - D3FF : PIA     */    
    {"PORTA", 0xd300}, {"PORTB", 0xd301}, {"PACTL", 0xd302}, {"PBCTL", 0xd303},
    /* D400 - D4FF : ANTIC   */       
    {"DMACLT",0xd400}, {"CHACTL",0xd401}, {"DLISTL",0xd402}, {"DLISTH",0xd403},
    {"HSCROL",0xd404}, {"VSCROL",0xd405}, {"PMBASE",0xd407}, {"CHBASE",0xd409},
    {"WSYNC", 0xd40a}, {"VCOUNT",0xd40b}, {"PENH",  0xd40c}, {"PENL",  0xd40d},
    {"NMIEN", 0xd40e}, {"NMIST" ,0xd40f}, {"NMIRES",0xd40f},
    /* D500 - D7FF : NOT USED   */ 
    /* D800 - DFFF : ROM VIRGULE FLOTTANTE */                     
    {"AFP",   0xd800}, {"FASC",  0xd8e6}, {"IFP",   0xd9aa}, {"FPI",   0xd9d2},
    {"ZPRO",  0xda44}, {"ZF1",   0xda46}, {"FSUB",  0xda60}, {"FADD",  0xda66},
    {"FMUL",  0xdadb}, {"FDIV",  0xdb28}, {"PLYEVL",0xdd40}, {"FLD0R", 0xdd89},
    {"FLD0R", 0xdd8d}, {"FLD1R", 0xdd98}, {"FLD1P", 0xdd9c}, {"FST0R", 0xdda7},
    {"FST0P", 0xddab}, {"FMOVE", 0xddb6}, {"EXP",   0xddc0}, {"EXP10", 0xddcc},
    {"LOG",   0xdecd}, {"LOG10", 0xded1},
    /* E000 - FFFF : ROM OS E/S */                        
    {"DSKINV",0xe453}, {"CIOV",  0xe456}, {"SIOV",  0xe459}, {"SETVBV",0xe45c},
    {"SYSVBV",0xe45f}, {"XITVBV",0xe462}, {"SIOINV",0xe465}, {"SENDEV",0xe468},
    {"INTINV",0xe46b}, {"CIOINV",0xe46e}, {"SELFSV",0xe471}, {"WARMSV",0xe474},
    {"COLDSV",0xe477}, {"RBLOKV",0xe47a}, {"CSOPIV",0xe47d}, {"PUPDIV",0xe480},
    {"SELFTSV",0xe483},{"PENTV", 0xe486}, {"PHUNLV",0xe489}, {"PHINIV",0xe48c},
    {"GPDVV", 0xe48f}
    };

int symtable_size=sizeof(symtable)/sizeof(symtable_rec);


/* Opcode type:
   bits 1-0 = instruction length ( 1, 2 or 3 bytes)
   bit 2    = not used // accumulator manipulation ???
   bit 3    = instruction writes to memory (without stack-manipulating instructions)

   bits 7-4 = adressing type:
     0 = NONE (implicit)     like NOP			/length = 1
     1 = ABSOLUTE            like JSR $4C0F		/length = 3
     2 = ZPAGE               like STA $14			/length = 2
     3 = ABSOLUTE_X          like STA $1250,X		/length = 3
     4 = ABSOLUTE_Y          like STA $1250,Y		/length = 3
     5 = INDIRECT_X          like STA ($12,X)		/length = 2
     6 = INDIRECT_Y          like STA ($12),Y		/length = 2
     7 = ZPAGE_X             like STA $40,X		/length = 2
     8 = ZPAGE_Y             like STA $40,Y		/length = 2
     9 = RELATIVE            like BNE $FE (-2)		/length = 2
     A = IMMEDIATE           like LDA #$CF		/length = 2
     B = ACCUMULATOR         like ROR  A              /length = 1
     C = STACK 2 or 3        RTI or RTS			/length = 1
     D = INDIRECT            like JMP ($FFFE) //only one opcode for the 6502 / Length = 3
     E = ESC RTS             // special opcode
     F = ESC                 // special opcode
*/  
   
typedef struct {
    char mnemonic[4];  /* max. 3 characters */
    UBYTE optype;
  } optable6502_rec;

optable6502_rec opcode[256] =
{
/* 00 - 0F */
{"BRK", 0x01},{"ORA", 0x52},{"CIM", 0x01},{"ASO", 0x52},{"SKB", 0x01},{"ORA", 0x22},{"ASL", 0x2a},{"ASO", 0x22},
{"PHP", 0x01},{"ORA", 0xa2},{"ASL", 0xb1},{"ASO", 0xa2},{"SKW", 0x01},{"ORA", 0x13},{"ASL", 0x1b},{"ASO", 0x13},

/* 10 - 1F */
{"BPL", 0x92},{"ORA", 0x62},{"CIM", 0x01},{"ASO", 0x62},{"SKB", 0x01},{"ORA", 0x72},{"ASL", 0x7a},{"ASO", 0x72}, 
{"CLC", 0x01},{"ORA", 0x43},{"NOP", 0x01},{"ASO", 0x43},{"SKW", 0x01},{"ORA", 0x33},{"ASL", 0x3b},{"ASO", 0x33},

/* 20 - 2F */
{"JSR", 0x13},{"AND", 0x52},{"CIM", 0x01},{"RLA", 0x5a},{"BIT", 0x22},{"AND", 0x22},{"ROL", 0x2a},{"RLA", 0x2a},
{"PLP", 0x01},{"AND", 0xa2},{"ROL", 0xb1},{"RLA", 0xa2},{"BIT", 0x13},{"AND", 0x13},{"ROL", 0x1b},{"RLA", 0x1b},

/* 30 - 3F */  
{"BMI", 0x92},{"AND", 0x62},{"CIM", 0x01},{"RLA", 0x6a},{"SKB", 0x01},{"AND", 0x72},{"ROL", 0x7a},{"RLA", 0x7a},
{"SEC", 0x01},{"AND", 0x43},{"NOP", 0x01},{"RLA", 0x4b},{"SKW", 0x01},{"AND", 0x33},{"ROL", 0x3b},{"RLA", 0x3b},

/* 40 - 4F */
{"RTI", 0xc1},{"EOR", 0x52},{"CIM", 0x01},{"LSE", 0x52},{"SKB", 0x01},{"EOR", 0x22},{"LSR", 0x2a},{"LSE", 0x22},
{"PHA", 0x01},{"EOR", 0xa2},{"LSR", 0xb1},{"ALR", 0xa2},{"JMP", 0x13},{"EOR", 0x13},{"LSR", 0x1b},{"LSE", 0x13},

/* 50 - 5F */
{"BVC", 0x92},{"EOR", 0x62},{"CIM", 0x01},{"LSE", 0x62},{"SKB", 0x01},{"EOR", 0x72},{"LSR", 0x7a},{"LSE", 0x72},
{"CLI", 0x01},{"EOR", 0x43},{"NOP", 0x01},{"LSE", 0x43},{"SKW", 0x01},{"EOR", 0x33},{"LSR", 0x3b},{"LSE", 0x33},

/* 60 - 6F */
{"RTS", 0xc1},{"ADC", 0x52},{"CIM", 0x01},{"RRA", 0x5a},{"SKB", 0x01},{"ADC", 0x22},{"ROR", 0x2a},{"RRA", 0x2a},
{"PLA", 0x01},{"ADC", 0xa2},{"ROR", 0xb1},{"ARR", 0xa2},{"JMP", 0xd3},{"ADC", 0x13},{"ROR", 0x1b},{"RRA", 0x1b},

/* 70 - 7F */ 
{"BVS", 0x92},{"ADC", 0x62},{"CIM", 0x01},{"RRA", 0x6a},{"SKB", 0x01},{"ADC", 0x72},{"ROR", 0x7a},{"RRA", 0x7a},
{"SEI", 0x01},{"ADC", 0x43},{"NOP", 0x01},{"RRA", 0x4b},{"SKW", 0x01},{"ADC", 0x33},{"ROR", 0x3b},{"RRA", 0x3b},

/* 80 - 8F */
{"SKB", 0x01},{"STA", 0x5a},{"SKB", 0x01},{"AXS", 0x5a},{"STY", 0x2a},{"STA", 0x2a},{"STX", 0x2a},{"AXS", 0x2a},
{"DEY", 0x01},{"SKB", 0x01},{"TXA", 0x01},{"XAA", 0xa2},{"STY", 0x1b},{"STA", 0x1b},{"STX", 0x1b},{"AXS", 0x1b},

/* 90 - 9F */
{"BCC", 0x92},{"STA", 0x6a},{"CIM", 0x01},{"AXS", 0x6a},{"STY", 0x7a},{"STA", 0x7a},{"STX", 0x8a},{"AXS", 0x8a},
{"TYA", 0x01},{"STA", 0x4b},{"TXS", 0x01},{"XAA", 0x43},{"SKW", 0x01},{"STA", 0x3b},{"MKX", 0x13},{"MKA", 0x13},

/* A0 - AF */
{"LDY", 0xa2},{"LDA", 0x52},{"LDX", 0xa2},{"LAX", 0x52},{"LDY", 0x22},{"LDA", 0x22},{"LDX", 0x22},{"LAX", 0x22},
{"TAY", 0x01},{"LDA", 0xa2},{"TAX", 0x01},{"OAL", 0xa2},{"LDY", 0x13},{"LDA", 0x13},{"LDX", 0x13},{"LAX", 0x13},

/* B0 - BF */  
{"BCS", 0x92},{"LDA", 0x62},{"CIM", 0x01},{"LAX", 0x62},{"LDY", 0x72},{"LDA", 0x72},{"LDX", 0x82},{"LAX", 0x72},
{"CLV", 0x01},{"LDA", 0x43},{"TSX", 0x01},{"AXA", 0x43},{"LDY", 0x33},{"LDA", 0x33},{"LDX", 0x43},{"LAX", 0x43},

/* C0 - CF */
{"CPY", 0xa2},{"CMP", 0x52},{"SKB", 0x01},{"DCM", 0x5a},{"CPY", 0x22},{"CMP", 0x22},{"DEC", 0x2a},{"DCM", 0x2a},
{"INY", 0x01},{"CMP", 0xa2},{"DEX", 0x01},{"SAX", 0xa2},{"CPY", 0x13},{"CMP", 0x13},{"DEC", 0x1b},{"DCM", 0x1b},

/* D0 - DF */
{"BNE", 0x92},{"CMP", 0x62},{"CIM", 0xe2},{"DCM", 0x6a},{"SKB", 0x01},{"CMP", 0x72},{"DEC", 0x7a},{"DCM", 0x7a},
{"CLD", 0x01},{"CMP", 0x43},{"NOP", 0x01},{"DCM", 0x4b},{"SKW", 0x01},{"CMP", 0x33},{"DEC", 0x3b},{"DCM", 0x3b},

/* E0 - EF */
{"CPX", 0xa2},{"SBC", 0x52},{"SKB", 0x01},{"INS", 0x5a},{"CPX", 0x22},{"SBC", 0x22},{"INC", 0x2a},{"INS", 0x2a},
{"INX", 0x01},{"SBC", 0xa2},{"NOP", 0x01},{"SBC", 0xa2},{"CPX", 0x13},{"SBC", 0x13},{"INC", 0x1b},{"INS", 0x1b},

/* E0 - EF */
{"BEQ", 0x92},{"SBC", 0x62},{"CIM", 0xf2},{"INS", 0x6a},{"SKB", 0x01},{"SBC", 0x72},{"INC", 0x7a},{"INS", 0x7a},
{"SED", 0x01},{"SBC", 0x43},{"NOP", 0x01},{"INS", 0x4b},{"SKW", 0x01},{"SBC", 0x33},{"INC", 0x3b},{"INS", 0x3b} 
};

char *get_token(char *string)
{
	static char *s;
	char *t;
	if (string)
		s = string;			/* New String */
	while (*s == ' ')
		s++;				/* Skip Leading Spaces */
	if (*s)
	{
		t = s;				/* Start of String */
		while (*s != ' ' && *s)
		{				/* Locate End of String */
			s++;
		}
		if (*s == ' ')
		{				/* Space Terminated ? */
			*s = '\0';		/* C String Terminator */
			s++;			/* Point to Next Char */
		}
	}
	else
	{
		t = NULL;
	}
	return t;				/* Pointer to String */
}

int get_hex(char *string, UWORD *hexval)
{
	int ihexval;
	char *t;

	t = get_token(string);
	if (t)
	{
		sscanf(t, "%X", &ihexval);
		*hexval = ihexval;
		return 1;
	}
	return 0;
}

int get_sect_offs(char *string, UWORD *sectval, UBYTE *offsval)
{
	int ihexval;
	char *t;
	char *v;
	t = get_token(string);
	if (t)
	{
		v = t;				/* Start of String */
		while ((*t != ':') && *t)
		{	/* Locate End of String */
			t++;
		}
		if (*t == ':') 			/* : located? */
		{
			*t = '\0';		/* C String Terminator */
			t++;			/* Point to Next Char */
		}
	}
	else return -1;
	if (*v)   // premiere valeur
	{
		if (!sscanf(v, "%X", &ihexval)) return 0;
		*sectval = ihexval;
	}
	else
	{
		return 0;  //erreur pas de valeur !!
	}
	if (*t)     // deuxieme valeur
	{
		if (!sscanf(t, "%X", &ihexval)) return 0;
		*offsval = ihexval;
		return 1;
	}
	else       // pas de deuxieme valeur
	{
		ihexval = 0;
		*offsval = ihexval;
		return 1;
	}
}

UINT get_position(UWORD sector, UBYTE offset)
{
	return((sector-1)*128 + offset);
}

int is_wrong_sector_offset(UWORD sector, UBYTE offset)
{	// test de sector & offset
	if (sector > 0 && sector < 1041 && offset < 129)
		return 0;
	else	
		printf("Invalid sector or offset !! [$%03X:%02X]\n",sector,offset);
	return 1;
}

UWORD get_sector(UINT position)
{
	return(position/128 + 1);
}

UBYTE get_offset(UINT position)
{
	return(position % 128);
}

void view_sector(void)
{
	int i,count;
	UINT cksect;
	UWORD nxtsector;
	UBYTE char_ascii;
	cksect = 0;
	if (currsect > 1040 ) currsect = 1;
	if (currsect < 1)     currsect = 1040;
	printf("\nVIEW SECTOR # $%03X (d%04d) \n",currsect,currsect);
	printf("BYT#>00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
	printf(" CH>0123456789ABCDEF\n");
	currpos = get_position(currsect,0);
	for (count=0 ; count<8; count++)
	{
		printf("%02X : ", count*16);
		//textattr(0x0E);
		for (i = 0; i < 16; i++)
		{
			printf("%02X ", file_in_memory[currpos+i]);
		}
		printf("\t");
		for (i = 0; i < 16; i++)
		{
                  char_ascii = file_in_memory[(currpos+i)];
			cksect += char_ascii;
			if (cksect > 256) cksect = cksect - 256 +1;
			if (iscntrl(char_ascii ))
			{
				printf(".");
			}
			else
			{
			      printf("%c", char_ascii );
			}
		}
		printf("\n");
		//textattr(0x0F);
		currpos += 16;
	}
	printf("\n Checksum = $%02X,",cksect);
	nxtsector = (file_in_memory[currpos-2]+256*file_in_memory[currpos-3]) & 0x3FF;
	printf(" Next sector = $%03X,",nxtsector);
	printf(" Bytes per sector = $%02X",file_in_memory[currpos-1] & 0x7F);
	printf("\n\n");
}

int get_atr_file_info(ATR_FILE * afile, UWORD asect)
{
	UINT cpos;
	cpos = get_position(asect,0);
	afile->file_header = file_in_memory[cpos+1] * 256 + file_in_memory[cpos];
	afile->file_startaddr = file_in_memory[cpos+3] * 256 + file_in_memory[cpos+2];
	afile->file_endaddr = file_in_memory[cpos+5] * 256 + file_in_memory[cpos+4];
	afile->file_firstsect = asect;
	afile->file_firstpos = cpos;
	afile->file_size = afile->file_endaddr - afile->file_startaddr + 1;
	afile->file_nbsect = (afile->file_size + 6) / 125 + 1;
	if (afile->file_header == 0xFFFF && afile->file_size < 0x10000) return 1;
	return 0;
}

/*************************************************************************************
* MAIN PROCEDURE // ATaRi MONITOR
*************************************************************************************/
int main (void)
{
  UWORD addr;
  char s[128];
  static char old_s[sizeof(s)]="";
  int p;
  addr = 0;
  memset(&file_in_memory, 255,MAX_FILE_LENGTH);
  printf("WELCOME TO ATaRi XFD FILE MONITOR !\n");
  printf("Written by Philippe VUILLERME (c) PVBest 2001\n");
  printf("Based on the 'monitor' from the Atari 800 Emulator\n");
  printf(" written by David Firth and his Emulator development team.\n");
  printf("We will still keep ATARI alive...\n");
  printf("Rev 2.00 - Disassembly in enhanced 6502 opcode set\n");
  printf("Type '?' or 'HELP' for command help\n");
  while (TRUE)
  {
	char *t;
	printf("ATR Monitor> ");
	fflush(stdout);
	if (gets(s) == NULL)
	{	/* this never happens ??? */
		printf("\n> QUIT \n");
		strcpy(s, "QUIT");
	}
	if (s[0])
		memcpy(old_s, s, sizeof(s));
	else
	{
		UINT i;
		/* if no command is given, restart the last one, but remove all
		 * arguments, so after a 'm 600' we will see 'm 700' ...
		 */
		memcpy(s, old_s, sizeof(s));
		for (i = 0; i < sizeof(s); ++i)
			if (isspace(s[i]))
			{
				s[i] = '\0';
				break;
			}
	}
	/* LECTURE DE LA COMMANDE */
	t = get_token(s);
	if (t == NULL)
	{
		continue;
	}
	/* Mise en majuscule de la chaine de commande */
	for (p = 0; t[p] != 0; p++)
		if (islower(t[p]))
			s[p] = toupper(t[p]);

	/******************* TRAITEMENT DES COMMANDES *************************/
	/* QUITTER */
	if (strcmp(t, "QUIT") == 0)
	{
		return 1;
	}
	/* AIDE */
	else if (strcmp(t, "HELP") == 0 || strcmp(t, "?") == 0)
	{
	printf("QUIT or EXIT   - Quit MONITOR\n");
	printf("HELP or ?      - This text\n");
	printf("OPEN filename  - Open an XFD or other file 'filename' in memory\n");
	printf("SAVE [filename] [nbrsect] - Save the memory into file\n");
	printf("V [sector]     - View and display 'sector'\n");
	printf("+              - Next sector view\n");
	printf("-              - Previous sector view\n");
      printf("DIR?           - Show ATaRi disk directory\n");
	printf("BOOT?          - Describe ATaRi boot sector\n");
	printf("FILE? [sector] - Show ATaRi file info header at 'sector' and Utilities for file\n");
	printf("                 tracking verification and file saving into 'ATRFILE.COM'\n");
	printf("D [sector[:offset]] [addr] [byte/sect] - Normal sectors disassembly\n");
	printf("DF sector[:offset] endsect [addr] [byte/sect] - Disassemble to ATRDIS.TXT file\n");
	printf("DS [idem D]    - Disassembly without memory mnemonic labels\n");
	printf("DD             - Redisplay 24 current disassembly lines\n");
	printf("D-             - Disassemble at previous 128 bytes\n");
	printf("S startsector endsector hexval1 ... [hexval16]      - Search in sectors\n");
	printf("C sector:offset hexval1 ... [hexval16]              - Change sector data\n");
	printf("F sector:offset endposition hexval                  - Fill within a sector\n");
	printf("READ filename sector[:offset] [nbrsect] [byte/sect] - Read file into memory\n");
	printf("WRITE sector[:offset] endsector [byte/sect]         - Write specified data\n");
 	printf("                                                      into SECTDUMP.DAT\n");
      printf("ALL NUMBERS ARE HEXADECIMAL (except the displayed noted with 'd')\n");
	//printf("A [startaddr] - Start simple assembler\n");
	}
	/* QUITTER */
	else if (strcmp(t, "EXIT") == 0)
	{
		return 0;
	}

	/* Ouvrir un fichier XFD ou Autre*/
	else if (strcmp(t, "OPEN") == 0)
	{
		int fsze;
		char *filename;
		filename = get_token(NULL);
		if (filename)
		{
			int fd;
			fd = open(filename, O_RDONLY | O_BINARY); //
			if (fd == -1)
			{
				//afficher l'erreur
				perror(open_filename);
				continue;
			}
			fsze = read(fd, &file_in_memory, MAX_FILE_LENGTH);
			if (fsze == -1)
			{
				//afficher l'erreur
				perror("read");
				continue;					
			}
			close(fd);
			printf("OK : File %s in memory !\n", filename);
			if (fsze == 0)
				numbersect = 0;
			else numbersect = ((fsze-1)/128)+1;
			printf("File size = d%d ($%03X sectors)\n",fsze,numbersect);
			strcpy(open_filename,filename);
			FILE_SIZE = fsze;
		}
	}

	/* Save the open file which is in memory */
	else if (strcmp(t, "SAVE") == 0)
	{
		char *save_filename;		
		int fd,flsize,wsize;
                UWORD nbrsect;
		save_filename = get_token(NULL);
		flsize = MAX_FILE_LENGTH;
		if (!save_filename) save_filename = "SAVEFILE.XFD";
		else if (strcmp(save_filename,open_filename) == 0)
		{
			printf("Are you sure to want to overwrite %s ? (Y/N) [N]\n",save_filename);
			if (getch() != 'Y') continue;
			flsize = FILE_SIZE;
		}
		else
		  if (get_hex(NULL, &nbrsect))
		    if ((nbrsect*128 <= MAX_FILE_LENGTH) && nbrsect)
		      flsize = nbrsect * 128;
		    else
		    {
			printf("Invalid number of sector [$%03X]!!\n",nbrsect);
			continue;
		    }
		fd = open(save_filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0777);
		if (fd == -1)
		{
			perror("open");
			continue;
		}
		wsize = write(fd, &file_in_memory[0], flsize);
		close(fd);
		printf("OK ! File XFD in memory saved in '%s'\n",save_filename);
		printf("Written bytes (file size) = d%d ($%03X sectors)\n",wsize,(wsize-1)/128+1);
	}
	/* Write data from sector into SECTDUMP.DAT */
	else if (strcmp(t, "WRITE") == 0)
	{
		FILE *pf;
            UINT ipos,k;
		UWORD xsector,endsect,bytsect,j;
		UBYTE xoffset;
		int res;
		res = get_sect_offs(NULL, &xsector, &xoffset);
		if (res < 1)
		{
			printf("Invalid data !!\n");
			continue;
		}
		else //if (res == 1)  // secteur:offset OK ?
		{
			if (is_wrong_sector_offset(xsector,xoffset))
				continue;
		}
		if (!get_hex(NULL, &endsect))
		{
			printf("No end sector !!\n");
			continue;
		}
		if (endsect < xsector || endsect > 0x410 || endsect < 1)
		{
			printf("Wrong last sector data !!\n");
			continue;
		}
		if (!get_hex(NULL, &bytsect))
			bytsect = 0x80;
		if (bytsect > 0x80 || bytsect < 1)
			bytsect = 0x80;
		printf("Write the following sector data:\n");
            printf("from sector $%03X:%02X to sector $%03X",xsector,xoffset,endsect);
		printf(" with $%02X bytes/sector\n",bytsect);
		pf = fopen("SECTDUMP.DAT","wb");
		if (pf == NULL)
		{
			perror("write");
			continue;
		}
		k = xoffset;
		for(j=xsector;j<=endsect;j++)
            {
			ipos = get_position(j,0);
			while (k < bytsect)
			{
				fputc(file_in_memory[ipos+k],pf);
				k++;
			}
			k = 0;
            }
		//fseek longueur ???
		fclose(pf);
		printf("OK DONE !! Sector Data saved in 'SECTDUMP.DAT'\n");
	}

	else if (strcmp(t, "READ") == 0)
	{
		int fsze;
		FILE *pf;
                UINT ipos;
		UWORD xsector,nbbytes,bytsect,j;
		UBYTE xoffset;
		int res;
		char *filename;
		filename = get_token(NULL);
		if (!filename)
			continue;
		pf = fopen(filename,"rb");
		if (pf == NULL)
		{
			perror("read");
			continue;
		}
                fseek(pf, 0L, SEEK_END);
		fsze = ftell(pf);
                printf("File '%s', size d%d ($%X)\n",filename,fsze,fsze);
		res = get_sect_offs(NULL, &xsector, &xoffset);
		if (res < 1)
		{
			printf("Invalid data !!\n");
                        fclose(pf);
			continue;
		}
		else //if (res == 1)  // secteur:offset OK ?
		{
			if (is_wrong_sector_offset(xsector,xoffset))
                        {
                            fclose(pf);
                            continue;
                        }
		}
		if (!get_hex(NULL, &nbbytes))
		{
			printf("No mumber of bytes specified !!\n");
                        fclose(pf);
			continue;
		}
		if (nbbytes < 1 || nbbytes > MAX_FILE_LENGTH || nbbytes > fsze)
		{
			printf("Wrong number of bytes (%d) !!\n",nbbytes);
                        fclose(pf);
			continue;
		}
		if (!get_hex(NULL, &bytsect))
			bytsect = 0x80;
		if (bytsect > 0x80 || bytsect < 1)
			bytsect = 0x80;
		printf("Read the following data from file into memory:\n");
                printf("file = %s, into memory from sector $%03X:%02X , \n",filename,xsector,xoffset);
		printf(" $%X (d%d) bytes, with $%02X bytes/sector\n",nbbytes,nbbytes,bytsect);
		ipos = get_position(xsector,xoffset);
		fseek(pf, 0L, SEEK_SET);
		for(j=0;j<nbbytes;j++)
                {
				file_in_memory[ipos+j] = fgetc(pf);
            }
		fclose (pf);
		printf("OK : Data are into memory !\n");
	}


	/* Display boot sector information */
	else if (strcmp(t, "BOOT?") == 0)
	{
		UWORD stradr;
		UWORD bootini;
		stradr = (UWORD) (file_in_memory[2] + file_in_memory[3]*256);
		bootini = (UWORD) (file_in_memory[4] + file_in_memory[5]*256);
		printf("Boot sector information - secteur $001 - octet nř:\n");
		printf(" #00: BOOTFLAG = $%02X (Premier octet du boot)\n",file_in_memory[0]);
		printf(" #01: NBSECTOR = $%02X (Nombre de secteurs a lire)\n",file_in_memory[1]);
		printf(" #02/03: STARTADR = $%04X (Adresse de stockage memoire)\n",stradr);
		printf(" #04/05: BOOTINIT = $%04X (Adresse de lancement apres RTS)\n",bootini);
		printf(" #06 = Premiere instruction a STARTADR + 6 = $%04X\n",((stradr + 6) & 0xFFFF));
		printf("\n");
	}
	/* Display the Atari disk directory */
	else if (strcmp(t, "DIR?") == 0)
	{
		UWORD tmpv;
		UINT dpos,i,j;
		dpos = get_position(0x169,0);
		printf("ATARI DISK DIRECTORY - secteur $169 (360):\n");
                printf("FILE# Flag: Nb_block: First_sect:  Name:\n");
                i = 1;
		while (TRUE)
		{
			if (!file_in_memory[dpos]) break;
			printf("#%02X   ",i);
			printf("$%02X   ",file_in_memory[dpos]);
			tmpv = (UWORD) (file_in_memory[dpos+1] + file_in_memory[dpos+2]*256);
			printf("$%04X     ",tmpv);
			tmpv = (UWORD) (file_in_memory[dpos+3] + file_in_memory[dpos+4]*256);
			printf("$%04X        ",tmpv);
          		//printf("");
			for (j=5;j<16;j++)
				printf("%c",file_in_memory[dpos+j]);
			i++;
			printf("\n");
			dpos +=16;
			if (i>23) break;
		}
	}

	/* Display and test the Atari File in given sector */
	else if (strcmp(t, "FILE?") == 0)
	{
		UWORD xsect1;
		UWORD nextsector,nboctblock,stad,enad;
		UBYTE nboctsect,b;
		int okflag,xit;
		UINT ipos,jpos,headerflag;
		ATR_FILE thefile;
		if (get_hex(NULL, &xsect1))
		currsect = xsect1;
		okflag = TRUE;
		if (get_atr_file_info(&thefile,currsect))
			printf("It may be a valid Atari file header...\n");
		else
		{
			printf("This is not a valid Atari file header !!\n");
			okflag = FALSE;
		}
		printf("Atari File Header on Sector $%03X information\n",currsect);
		printf(" Information following for the first block only :\n");
		printf(" - HEADER BYTES = $%04X (2 first header bytes)\n",thefile.file_header);
		printf(" - FIRSTADD = $%04X (First block memory address)\n",thefile.file_startaddr);
		printf(" - LASTADD = $%04X (Last block memory address)\n",thefile.file_endaddr);
		printf(" - FILESIZE = $%04X (Size in bytes)\n",thefile.file_size);
		printf(" - Expected size in sector = $%04X\n",thefile.file_nbsect) ;
		printf("\n");
		if (!okflag) continue;

		printf("Would you like to trace the atari file ? (Y/N) [N]\n");
		if (getch() != 'Y') continue;

 		ipos = get_position(currsect,0);
		nboctsect = file_in_memory[ipos+127];
		jpos = 0;
		xit = FALSE;
		headerflag = TRUE;
		nboctblock = 4;
		nextsector = 256 * (file_in_memory[ipos+125] & 0x03) + file_in_memory[ipos+126];
		printf("CURRENT SECTOR-byte per sector:\n$%03X-%02X",currsect,nboctsect);
		if (nboctsect>128)
			printf("Invalid sector size %02X on sector %03X!!\n",nboctsect,currsect);
		nboctsect &= 0x7F;
		while (!xit)
		{
		   if (headerflag) // != 0 Lecture de l'entete du bloc
		   {
			//printf("\Entete #%d",nboctblock);
			tmp_file_mem[jpos] = file_in_memory[ipos];
			jpos++;
			ipos++;
			nboctsect--;
			nboctblock--;
			if (nboctblock == 0) // == 0 : passage a zero : 4 octets de l'entete lus
			{
			   stad = tmp_file_mem[jpos-4] + 256 * tmp_file_mem[jpos-3];
			   enad = tmp_file_mem[jpos-2] + 256 * tmp_file_mem[jpos-1];
			   if (stad == 0xFFFF && enad == 0xFFFF)
			   {
				okflag = FALSE;
				printf("Invalid block start/end address: $%04X-$%04X!!\n",stad,enad);
				break;
			   }
			   if (stad == 0xFFFF)
			   {
				nboctblock = 2; // il en faut encore 2 !
				printf("<Header:$FFFF>\n");
			   }
			   else
			   {
				nboctblock = enad - stad + 1;
				headerflag = FALSE;
				printf("[BLOCK:$%04X-$%04X SIZE:$%04X]\n",stad,enad,nboctblock);
				if (stad > enad)
				{
				   okflag = FALSE;
				   printf("Invalid block start/end address (Block Length: $%04X)!!\n",nboctblock);
				   //break;
			      }
			   }
			   getch();
			}
		   }
		   else //header flag == 0 : lecture du block
		   {
			b = file_in_memory[ipos];
			tmp_file_mem[jpos] = b;
			jpos++;
			ipos++;
			nboctsect--;
			nboctblock--;
		   	//printf("#%02X",b);
		   }

		   if (!nboctsect && !nextsector && !nboctblock)
		   // si les 3 sont a zero -> OK, c'est fini !! 
		   {
			printf("\nTracking over !! Exiting\n");
			xit = TRUE;
			break;
		   }
		   else if (!nboctsect && !nextsector && nboctblock)
		   // is plus d'octet a lire et plus de secteur, mais tjrs un block -> ERREUR !
		   {
			okflag = FALSE;
			printf("ERROR : WRONG FILE ENDING !!\n");
			printf("(Number of byte from block missing: $%04X)\n", nboctblock);
			break;
		   }
		   else if (!nboctsect && nextsector)
		   // plus d'octet a lire et pas fini (secteur suivant non nul) -> secteur suivant
		   {
			currsect = nextsector;
			ipos = get_position(currsect,0);
			nboctsect = file_in_memory[ipos+127];
			nextsector = 256 * (file_in_memory[ipos+125] & 0x03) + file_in_memory[ipos+126];
			printf("$%03X-%02X ",currsect,nboctsect);
			if (is_wrong_sector_offset(currsect,0))
			{
				okflag = FALSE;
				printf("Invalid sector number $%04X !!\n",nextsector);
				break;
			}
			//getch();
		   }
		   if (!nboctblock)
		   // on est pas sorti sur fin de fichier, ou sur erreur, alors
		   // on vérifie le nombre d'octet restant du block, si nul -> nouveau block a lire
		   {
			nboctblock = 4;
			headerflag = TRUE;
			//printf("\n OCTET RESTANT DU SECTEUR %d\n",nboctsect);
		   }
		}

		if (!okflag)
		{
			printf("Sorry, this was not a valid file !!\n");
			continue;
		}

		if (xit == TRUE)
		{
			printf("OK, Atari file tracking succesful !!\n");
			printf("Would you like to SAVE the atari file ? (Y/N) [N]\n");
			if (getch() != 'Y') continue;
			int fd;
			fd = open("ATRFILE.COM", O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0777);
			if (fd == -1)
			{
				perror("open");
				continue;
			}
			write(fd, &tmp_file_mem[0], jpos);
			close(fd);
			printf("Saving into ATRFILE.COM successful !! ($%04X bytes written)\n",ipos);
		}
		else printf("SORRY, AN ERROR HAS OCCURED ON TRACKING FILE !!!\n");
	}

	/* VIEW display sector */
	else if (strcmp(t, "V") == 0)
	{
		UWORD xsect1;
		// pas de sector specifie, on affiche le suivant...
		if (get_hex(NULL, &xsect1))
		currsect = xsect1;
		view_sector();
	}
	/* Display previous sector */
	else if (strcmp(t, "-") == 0)
	{
		currsect--;
		view_sector();
	}
	/* Display next sector */
	else if (strcmp(t, "+") == 0)
	{
		currsect++;
		view_sector();
	}
	/* Special test */
	else if (strcmp(t, "TEST") == 0)
	{
		UWORD xsector;
		UBYTE xoffset;
		if (!get_sect_offs(NULL, &xsector, &xoffset))
			printf("Donnee non valide !\n");
		else
		{
			printf("Secteur = %03X : Offset = %02X \n",xsector,xoffset);
			if (is_wrong_sector_offset(xsector,xoffset))
			printf("variables hors plage !!\n");
			//else
		}
	}
	/* Special test 1 */
	else if (strcmp(t, "TEST1") == 0)
	{
		int i,j;
		j = 2;
		file_in_memory[0] = 0xA9;
		file_in_memory[1] = 0xAA;
		for (i=0;i<256;i++)
		{
			file_in_memory[j] = 0x85;
			file_in_memory[j+1] = (UBYTE) i;
			j += 2;
		}
		for (i=0x100;i<0x600;i++)
		{
			file_in_memory[j] = 0x8D;
			file_in_memory[j+1] = (UBYTE) (i & 0xFF);
				file_in_memory[j+2] = (UBYTE) (i >> 8);
			j += 3;
		}
		for (i=0xA000;i<0x10000;i++)
		{
			file_in_memory[j] = 0x8D;
			file_in_memory[j+1] = (UBYTE) (i & 0xFF);
			file_in_memory[j+2] = (UBYTE) (i >> 8);
			j += 3;
		}
	}
	/* Special test 2*/
	else if (strcmp(t, "TEST2") == 0)
	{
		int i,j,k;
		k=0;
		for (i=0;i<256;i++)	
		{
			for (j=0;j<6;j++)
			{
				file_in_memory[k+j] = i;
			}
			k += 6;
		}
	}
	/* Disassemble to screen normal and simplify (no mnemonic) */
	else if ( (strcmp(t, "D")==0) || (strcmp(t, "DS")==0) )
	{
		UWORD xsector,xaddr;
		UBYTE xoffset;
		int res, sflg;
		lastpos = currpos;
		lastaddr = curraddr;
		if (strcmp(t, "DS")==0) sflg = 0;
		 else sflg = 1;
		res = get_sect_offs(NULL, &xsector, &xoffset);
		switch (res)
		{
			case 0:
			printf("Invalid data !\n");
			break;
			case 1:  // secteur:offset OK ?
			if (is_wrong_sector_offset(xsector,xoffset))
				break;
			currpos = get_position(xsector,xoffset);
			res = -1;
			case -1: // pas de secteur
			if (get_hex(NULL,&xaddr))
				curraddr = xaddr;
			if (get_hex(NULL,&xbytsect))
				xbytsect &= 0x7F;
			if (xbytsect == 0)
				xbytsect = 0x80;
			if (xbytsect< xoffset)
				xbytsect = 0x80;
			Disassemble(sflg);
		}
	}
	/* Disassemble into a file ATRDIS.TXT */
      else if (strcmp(t, "DF") == 0)
	{
		UWORD xsector,xtmp;
		UBYTE xoffset;
		int res;
		lastpos = currpos;
		lastaddr = curraddr;
		res = get_sect_offs(NULL, &xsector, &xoffset);
		switch (res)
		{
                  case 0:
			printf("Invalid data !\n");
			break;
                  case 1:  // secteur:offset OK ?
			if (is_wrong_sector_offset(xsector,xoffset))
				break;
			currpos = get_position(xsector,xoffset);
			res = -1;
                  case -1: // pas de secteur
                        if (get_hex(NULL,&xtmp))
                        {
                           if ((xtmp < xsector) || (xtmp > 0x410))
                           {
                              printf("Last sector not valid !!\n");
                              break;
                           }
                           numbersect = xtmp - xsector + 2;
                        }
				else
				{
					printf("Command line not valid !!\n");
					break;
				}
			if (get_hex(NULL,&xtmp))
				curraddr = xtmp;
			if (get_hex(NULL,&xbytsect))
				xbytsect &= 0x7F;
			if (xbytsect == 0)
				xbytsect = 0x80;
			if (xbytsect < xoffset)
				xbytsect = 0x80;
                        printf("Dissasemble to file :\n");
                        printf("From Sector: $%03X, Offset: %02X, ",xsector,xoffset);
                        printf("last Sector: $%03X,\n", xsector+numbersect-1);
                        printf("Nb of Sector $%03X, from Memory: $%04X\n",numbersect,curraddr);
				printf("> Are you sure to continue ? (Y/N) [N]\n");
				if (getch() != 'Y') break;
				Disassemble(3);
                        printf("OK, Done : Dissembly into the ATRDIS.TXT file !\n");
		}
	}
	/* Redisplay current disassembly */
	else if (strcmp(t, "DD") == 0)
	{
		currpos = lastpos;
		curraddr = lastaddr;
		Disassemble(1);
	}
	/* Redisplay disassembly at previous 128 bytes  */
	else if (strcmp(t, "D-") == 0)
	{
		int xpos;
		xpos = (int) (currpos - 128);
		if (xpos < 0)
			currpos = (UINT) (MAX_FILE_LENGTH + xpos);
		else  currpos = (UINT) xpos;
		curraddr -= 128;
		Disassemble(1);
	}
	/* Search up to 16 data into given sectors */
	else if (strcmp(t, "S") == 0)
	{
		UINT ipos,j,nbval,pos1,pos2,xit;
		UWORD xsec1;
		UWORD xsec2;
		UBYTE hexval[16];
		UWORD inval;
		if (!get_hex(NULL, &xsec1) || !get_hex(NULL, &xsec2) || (xsec1>xsec2))
		{
			printf("Missing or incorrect parameters !!\n");
			continue;
		}
		if ((xsec2 > 1040 ) || (xsec1 < 1))
		{
			printf("Over-ranged sectors number !!\n");
			continue;
		}
		for (nbval=0;nbval<16;nbval++)
		{
			if (!get_hex(NULL, &inval)) break;
			if (inval > 255)
				printf("Nota : over-ranged value will be trucated...\n");
			hexval[nbval] = (UBYTE) (inval);
		}
		if (nbval==0)
		{
			printf("No data to be found !!\n");
			continue;
		}
		pos1 = 128*(xsec1-1);
		pos2 = (128*xsec2)-1;
		printf("Seeking from d%d a d%d > ", pos1,pos2); //afficher secteur ???
		for (j=0;j<nbval;j++)
		{
			printf(" $%02X",hexval[j]);
		}
		printf("\n");
		ipos = pos1;
		xit = 0;
		while (!xit && (ipos <= pos2))
		{
			if (file_in_memory[ipos] == hexval[0])
			{
                       	for(j=0;j<nbval;j++)
				if (file_in_memory[ipos+j] != hexval[j]) break;
				if (j == nbval)
				{
					currsect = get_sector(ipos);
                              printf("\nFound at [sector:offset] $%03X:%02X\n", currsect ,get_offset(ipos));
					//printf("ipos:$%X,j:%d,nbval:%d\n",ipos,j,nbval);
                       		view_sector();
					printf("\n> Continue searching ? (Y/N) [N]\n");
					if (getch() != 'Y') xit = 1;
					else ipos += j;
				}
				else ipos++;
			}
			else ipos++;
		}
		if (xit == 0) printf("\nSorry : not found !!\n\n");
	}
	/* Change/modify up to 16 data into the given sector */
	else if (strcmp(t, "C") == 0)
	{
		UINT j,nbval,cpos;
		UBYTE hexval[16];
		UWORD xsector,inval;
		UBYTE xoffset;
		int res;
		res = get_sect_offs(NULL, &xsector, &xoffset);
		if (res < 1)
		{
			printf("Invalid data !!\n");
			continue;
		}
		else //if (res == 1)  // secteur:offset OK ?
		{
			if (is_wrong_sector_offset(xsector,xoffset))
				continue;
			cpos = get_position(xsector,xoffset);
			currsect = xsector;
		}
		for (nbval=0;nbval<16;nbval++)
		{
			if (!get_hex(NULL, &inval)) break;
			if (inval > 255)
				printf("Nota : over-ranged value will be trucated...\n");
			hexval[nbval] = (UBYTE) (inval);
		}
		if (nbval==0)
		{
			printf("No data to be replaced !!\n");
			continue;
		}
		view_sector();
		//printf("Remplace from d%d >\n", cpos);
		printf("Remplace from sector:offset > data :\n");
		printf("[$%03X:%02X] >",xsector,xoffset);
		for (j=0;j<nbval;j++)
			printf(" $%02X",hexval[j]);
		printf("\n");
		printf("\n> Are you sure ? (Y/N) [N]\n");
		if (getch() != 'Y') continue;
		for(j=0;j<nbval;j++)
                {
			file_in_memory[cpos+j] = hexval[j];
                        //printf("\n<d%d - d%d>#$%02X",cpos,j,hexval[j]);
                }
		printf("OK DONE !!\n");
		view_sector();	
	}
	/* Fill the given data into the given sector */
	else if (strcmp(t, "F") == 0)
	{
		UINT j,cpos;
		UWORD xsector,fildat,offsend;
		UBYTE xoffset;
		int res;
		res = get_sect_offs(NULL, &xsector, &xoffset);
		if (res < 1)
		{
			printf("Invalid data !!\n");
			continue;
		}
		else //if (res == 1)  // secteur:offset OK ?
		{
			if (is_wrong_sector_offset(xsector,xoffset))
				continue;
			cpos = get_position(xsector,0);
			currsect = xsector;
		}
		if (!get_hex(NULL, &offsend)) offsend = 0x007F;
		if (!get_hex(NULL, &fildat))
		{
			printf("No data to be filled !!\n");
			continue;
		}
		if (fildat > 255 || offsend > 127)
			printf("Nota : over-ranged value will be trucated...\n");

		offsend &= 0x007F;
		fildat &= 0x00FF;
		view_sector();
		printf("Fill from d%d >\n", cpos);
		printf("Fill sector:offset-lastbyte with hexval: ");
                printf("$%03X:%02X-%02X",xsector,xoffset,offsend);
		printf(" with : $%02X\n",fildat);
		printf("\n> Are you sure ? (Y/N) [N]\n");
		if (getch() != 'Y') continue;
		for(j=xoffset;j<=offsend;j++)
                {
                  file_in_memory[cpos+j] = (UBYTE) fildat;
                  printf("\n<%d - %d>#%02X",cpos,j,fildat);
                }
		printf("OK DONE !!\n");
		view_sector();	
	}
	/* Unknown command */
	else
	{
		printf("Invalid command.\n");
	}
   }
}

/************** DECLARATION VARIABLE FOR DISASSEMBLE FUNCTIONS ****************/
static int cycles[256] =
{
	7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6,		// 0x
	2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7,		// 1x
	6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 4, 4, 6, 6,		// 2x
	2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7,		// 3x

	6, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 3, 4, 6, 6,		// 4x
	2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7,		// 5x
	6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 5, 4, 6, 6,		// 6x
	2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7,		// 7x

	2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4,		// 8x
	2, 6, 2, 6, 4, 4, 4, 4, 2, 5, 2, 5, 5, 5, 5, 5,		// 9x
	2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4,		// Ax
	2, 5, 2, 5, 4, 4, 4, 4, 2, 4, 2, 4, 4, 4, 4, 4,		// Bx

	2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6,		// Cx
	2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7,		// Dx
	2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6,		// Ex
	2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7  	// Fx
};

UBYTE instr1,instr2,instr3;
int nbinstr,typeinstr,winstr,cinstr;
UWORD dis_addr;
int dis_pos;
UWORD dis_sector;
UBYTE dis_offset;
char dis_label[9];
char dis_line[76];

/************* MAIN FUNCTION : DISASSEMBLY IN ENHANCED 6502 CODES ***********/
void Disassemble(int dflag)
{
    	int count,ns;
	UWORD xs;
	FILE *pf;
	char tmpchr[10];
	char ligne_ascii[4] = "   "; //ligne vide
	dis_addr = curraddr; // ???
	dis_pos = currpos; // ??
	count = 24;
	ns = numbersect;
	if (dflag >= 2)
	{
		pf = fopen("ATRDIS.TXT","w");
		if (pf == NULL)
		{
			perror("write");
			return;
		}
	}
	while (count)
	{
		xs =  get_sector(dis_pos);
		if (dis_sector != xs) ns--;
			dis_sector = xs;
		dis_offset = get_offset(dis_pos);
		sprintf(dis_line,"[%03X:%02X] %04X \t",dis_sector,dis_offset,dis_addr);
 		instr1 = Current_Instruction();
		nbinstr = opcode[instr1].optype & 0x03;
		winstr = opcode[instr1].optype & 0x08;
		cinstr = FALSE;
		typeinstr = (opcode[instr1].optype & 0xF0) / 16;
		sprintf(tmpchr,"%02X ", instr1);
                strcat(dis_line,tmpchr);
		ligne_ascii[0] = (iscntrl(instr1) ? '.' : instr1);   
		if (nbinstr < 2)
		{
			strcat(dis_line,"      ");
			ligne_ascii[1] = ' ';
			ligne_ascii[2] = ' ';
		}
		else
		{
			instr2 = Current_Instruction();
			sprintf(tmpchr,"%02X ", instr2);
                        strcat(dis_line,tmpchr);
			ligne_ascii[1] = (iscntrl(instr2) ? '.' : instr2);

			if (nbinstr == 3)
			{
				instr3 = Current_Instruction();
				sprintf(tmpchr,"%02X ", instr3);
                                strcat(dis_line,tmpchr);
				ligne_ascii[2] = (iscntrl(instr3) ? '.' : instr3);
			}
			else
			{
				strcat(dis_line,"   ");
				ligne_ascii[2] = ' ';
			}
		}
		Show_Disassembly(dflag);
		sprintf(tmpchr,"; %X", cycles[instr1]);
                strcat(dis_line,tmpchr);
		if (cinstr) strcat(dis_line,"+");
		else strcat(dis_line," ");
		strcat(dis_line," cycles; ");
		sprintf(tmpchr,"%s\t",ligne_ascii);
                strcat(dis_line,tmpchr);
		/* Fin de la ligne */
		strcat(dis_line,"\n");
   		dis_addr += (UWORD) (nbinstr & 0x03);
		if (dflag <= 1)
		{
			printf("%s",dis_line);
			count--;
		}
		else
		{
			fputs(dis_line,pf);
			if (ns == 0)
			{
				fclose(pf);
				break;
			}
		}
	}
	curraddr = dis_addr;
	currpos = dis_pos;
}

/*************** PROCEDURE & FUNCTION FOR DISASSEMBLE ***********************/
UBYTE Current_Instruction()
{
	UBYTE tmp;
	tmp = file_in_memory[dis_pos];
	dis_offset ++;
	if (dis_offset == xbytsect)
	{
		dis_pos += (0x80 - xbytsect + 1);
		dis_offset = 0;
	}
	else dis_pos++;
	if (dis_pos >= MAX_FILE_LENGTH)
		dis_pos = 0;
      	return tmp;
}
void Show_Disassembly(int flag_label)
{
	UWORD value1, value2;
	int wid,i;
	char atr_dis[25]="                        ";
	char atr_disi[8]="       ";
	sprintf(atr_disi,"   %s ", opcode[instr1].mnemonic);
	if (nbinstr == 3) value2 = (instr2 + (instr3 * 256));
	else value2 = (UWORD) instr2 & 0x00FF;
	wid = 0;
	switch (typeinstr)
	{
          case 0 :  // Implicit
          case 12:  // Stack 3 (RTI) or Stack 2 (RTS)
             sprintf(atr_dis,"                    ");
             break;
          case 1 :  // absolu
             wid = Show_Label(value2);
             if (flag_label && wid)
                  sprintf(atr_dis," %s  <$%04X>  ",dis_label,value2);
             else sprintf(atr_dis," $%04X              ", value2);
             break;
          case 2 :  // Z page
             wid = Show_Label(value2);
             if (flag_label && wid)
                  sprintf(atr_dis," %s  <$%02X>    ",dis_label,value2);
             else sprintf(atr_dis," $%02X                ", instr2);
             break;
          case 3 :  //Absolu,X
             cinstr = TRUE;
             wid = Show_Label(value2);
             if (flag_label && wid)
                  sprintf(atr_dis," %s,X  <$%04X>",dis_label,value2);
             else sprintf(atr_dis," $%04X,X            ", value2);
             break;
          case 4 :  //Absolu,Y
             cinstr= TRUE;
             wid = Show_Label(value2);
             if (flag_label && wid)
                  sprintf(atr_dis," %s,Y  <$%04X>",dis_label,value2);
             else sprintf(atr_dis," $%04X,Y            ", value2);
             break;
          case 5 :  //(Indirect,X)
             wid = Show_Label(value2);
             if (flag_label && wid)
                  sprintf(atr_dis,"(%s,X)  <$%02X> ",dis_label,value2);
             else sprintf(atr_dis,"($%02X,X)             ", value2);
             break;
          case 6 :  //(Indirect),Y
             wid = Show_Label(value2);
             if (flag_label && wid)
                  sprintf(atr_dis,"(%s),Y  <$%02X> ",dis_label,value2);
             else sprintf(atr_dis,"($%02X),Y             ", value2);
             break;
          case 7 :  // Z page,X
             wid = Show_Label(value2);
             if (flag_label && wid)
                  sprintf(atr_dis," %s,X  <$%02X>  ",dis_label,value2);
             else sprintf(atr_dis," $%02X,X              ", value2);
             break;
          case 8 :  // Z page,Y
             wid = Show_Label(value2);
             if (flag_label && wid)
                  sprintf(atr_dis," %s,Y  <$%02X>  ",dis_label,value2);
             else sprintf(atr_dis," $%02X,Y              ", value2);
             break;
          case 9 :  // saut relatif
		 cinstr = TRUE;
             value1 = (UWORD) (dis_addr + (char) instr2 + 2);
             sprintf(atr_dis," $%04X              ", value1);
             break;
          case 10:  // immediat
             sprintf(atr_dis,"#$%02X                ", instr2);
             break;
          case 11:
             sprintf(atr_dis,"  A                 ");
             break;
          case 13:  //(Indirect)
             wid = Show_Label(value2);
             if (flag_label && wid)
                  sprintf(atr_dis,"(%s)  <$%04X> ",dis_label,value2);
             else sprintf(atr_dis,"($%04X)             ", value2);
             break;
          case 14:
             sprintf(atr_dis," [ESC RTS]          ");
             break;
          case 15:
             sprintf(atr_dis," [ESC    ]          ");
             break;
          default:
          ;
	}
	// completer avec des espaces
	if (flag_label && wid)
		for (i = wid; i < 8; i++)
			strcat(atr_dis," ");
	strcat(dis_line,atr_disi);
	strcat(dis_line,atr_dis);
}
int find_symbol(UWORD addr)
{
  int lo,hi,mi;

  lo=0;hi=symtable_size-1;
  while (lo<hi)
  {
    mi=(lo+hi)/2;
    if (symtable[mi].addr==addr) break;
      else if (symtable[mi].addr>addr) hi=mi;
        else lo=mi+1;
  }
  if (symtable[mi].addr==addr) 
         /* return the lowest index of symbol with given address */
         if (mi>0 && symtable[mi-1].addr==addr) return mi-1; else return mi;
    else return -1;
}
int Show_Label(UWORD addrmem)
{
     int result,wid,i,ret;
     wid = 8;
     i = 0;
     ret = 0;
     dis_label = "        ";
     result = find_symbol(addrmem);
     // test // printf("%X",result);
     if (result >=0 )
        {
          //different names when reading/writting memory
	    //nota : winstr = 0 if read instruction
          if ( winstr && (symtable[result+1].addr == addrmem))
             result+=1;
          strcpy(dis_label,symtable[result].name);
          while (symtable[result].name[i++] != 0)
             ret++;
        }
      return ret; // nombre de caracteres du label (si 0 : pas de label)

}


