Annotation of hatari/src/floppy_stx.c, revision 1.1.1.4

1.1       root        1: /*
                      2:   Hatari - floppy_stx.c
                      3: 
                      4:   This file is distributed under the GNU General Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
                      6: 
                      7:   STX disk image support.
                      8: 
                      9:   STX files are created using the program 'Pasti' made by Jorge Cwik (Ijor).
                     10:   As no official documentation exists, this file is based on the reverse
                     11:   engineering and docs made by the following people, mainly using Pasti 0.4b :
                     12:    - Markus Fritze (Sarnau)
                     13:    - P. Putnik
                     14:    - Jean Louis Guerin (Dr CoolZic)
                     15:    - Nicolas Pomarede
                     16: */
                     17: const char floppy_stx_fileid[] = "Hatari floppy_stx.c : " __DATE__ " " __TIME__;
                     18: 
                     19: #include "main.h"
                     20: #include "file.h"
                     21: #include "floppy.h"
                     22: #include "floppy_stx.h"
                     23: #include "fdc.h"
                     24: #include "log.h"
                     25: #include "memorySnapShot.h"
                     26: #include "screen.h"
                     27: #include "video.h"
                     28: #include "cycles.h"
                     29: #include "str.h"
                     30: #include "utils.h"
                     31: 
                     32: 
                     33: #define        STX_DEBUG_FLAG_STRUCTURE        1
                     34: #define        STX_DEBUG_FLAG_DATA             2
                     35: 
                     36: #define        STX_DEBUG_FLAG                  0
                     37: // #define     STX_DEBUG_FLAG                  ( STX_DEBUG_FLAG_STRUCTURE )
                     38: // #define     STX_DEBUG_FLAG                  ( STX_DEBUG_FLAG_STRUCTURE | STX_DEBUG_FLAG_DATA )
                     39: 
                     40: 
                     41: #define FDC_DELAY_CYCLE_MFM_BIT                        ( 4 * 8 )       /* 4 us per bit, 8 MHz clock -> 32 cycles */
                     42: #define FDC_DELAY_CYCLE_MFM_BYTE               ( 4 * 8 * 8 )   /* 4 us per bit, 8 bits per byte, 8 MHz clock -> 256 cycles */
                     43: 
                     44: #define FDC_TRACK_BYTES_STANDARD       6250
                     45: 
                     46: 
                     47: #define        WD1772_SAVE_FILE_EXT            ".wd1772"
                     48: #define        WD1772_SAVE_FILE_ID             "WD1772"                /* 6 bytes */
                     49: #define        WD1772_SAVE_VERSION             1
                     50: #define        WD1772_SAVE_REVISION            0
                     51: #define        WD1772_SAVE_SECTOR_ID           "SECT"                  /* 4 bytes */
                     52: #define        WD1772_SAVE_TRACK_ID            "TRCK"                  /* 4 bytes */
                     53: 
                     54: 
                     55: typedef struct
                     56: {
                     57:        STX_MAIN_STRUCT         *ImageBuffer[ MAX_FLOPPYDRIVES ];       /* For the STX disk images */
                     58: 
                     59:        Uint32                  NextSectorStruct_Nbr;           /* Sector Number in pSectorsStruct after a call to FDC_NextSectorID_FdcCycles_STX() */
                     60:        Uint8                   NextSector_ID_Field_TR;         /* Track value in the next ID Field after a call to FDC_NextSectorID_FdcCycles_STX() */
                     61:        Uint8                   NextSector_ID_Field_SR;         /* Sector value in the next ID Field after a call to FDC_NextSectorID_FdcCycles_STX() */
                     62:        Uint8                   NextSector_ID_Field_LEN;        /* Sector's length in the next ID Field after a call to FDC_NextSectorID_FdcCycles_STX() */
                     63:        Uint8                   NextSector_ID_Field_CRC_OK;     /* CRC OK or not in the next ID Field after a call to FDC_NextSectorID_FdcCycles_STX() */
                     64: 
                     65: } STX_STRUCT;
                     66: 
                     67: 
                     68: static STX_STRUCT      STX_State;                      /* All variables related to the STX support */
                     69: 
                     70: static STX_SAVE_STRUCT STX_SaveStruct[ MAX_FLOPPYDRIVES ];     /* To save 'write sector' data */
                     71: 
                     72: 
                     73: 
                     74: /* Default timing table for Macrodos when revision=0 */
                     75: /* 1 unit of timing means 32 FDC cycles ; + 28 cycles every 16 bytes, so a standard block of 16 bytes */
                     76: /* should have a value of 0x7f or 0x80, which gives 4092-4124 cycles */
1.1.1.2   root       77: static Uint8   TimingDataDefault[] = {
1.1       root       78:        0x00,0x7f,0x00,0x7f,0x00,0x7f,0x00,0x7f,0x00,0x7f,0x00,0x7f,0x00,0x7f,0x00,0x7f,
                     79:        0x00,0x85,0x00,0x85,0x00,0x85,0x00,0x85,0x00,0x85,0x00,0x85,0x00,0x85,0x00,0x85,
                     80:        0x00,0x79,0x00,0x79,0x00,0x79,0x00,0x79,0x00,0x79,0x00,0x79,0x00,0x79,0x00,0x79,
                     81:        0x00,0x7f,0x00,0x7f,0x00,0x7f,0x00,0x7f,0x00,0x7f,0x00,0x7f,0x00,0x7f,0x00,0x7f
                     82:        };
                     83: 
                     84: 
                     85: 
                     86: /*--------------------------------------------------------------*/
                     87: /* Local functions prototypes                                  */
                     88: /*--------------------------------------------------------------*/
                     89: 
                     90: static bool    STX_LoadSaveFile ( int Drive , const char *FilenameSave );
                     91: static bool    STX_LoadSaveFile_SECT ( int Drive, STX_SAVE_SECTOR_STRUCT *pStxSaveSector , Uint8 *p );
                     92: static bool    STX_LoadSaveFile_TRCK ( int Drive , STX_SAVE_TRACK_STRUCT *pStxSaveTrack , Uint8 *p );
                     93: 
                     94: static bool    STX_Insert_internal ( int Drive , const char *FilenameSTX , Uint8 *pImageBuffer , long ImageSize );
                     95: 
                     96: static Uint16  STX_ReadU16_LE ( Uint8 *p );
                     97: static Uint32  STX_ReadU32_LE ( Uint8 *p );
                     98: static Uint16  STX_ReadU16_BE ( Uint8 *p );
                     99: static Uint32  STX_ReadU32_BE ( Uint8 *p );
                    100: static void    STX_WriteU16_BE ( Uint8 *p , Uint16 val );
                    101: static void    STX_WriteU32_BE ( Uint8 *p , Uint32 val );
                    102: 
                    103: static void    STX_FreeStruct ( STX_MAIN_STRUCT *pStxMain );
                    104: static void    STX_FreeSaveStruct ( int Drive );
                    105: static void    STX_FreeSaveSectorsStructAll ( STX_SAVE_SECTOR_STRUCT *pSaveSectorsStruct , Uint32 SaveSectorsCount );
                    106: static void    STX_FreeSaveSectorsStruct ( STX_SAVE_SECTOR_STRUCT *pSaveSectorsStruct , int Nb );
                    107: static void    STX_FreeSaveTracksStructAll ( STX_SAVE_TRACK_STRUCT *pSaveTracksStruct , Uint32 SaveTracksCount );
                    108: static void    STX_FreeSaveTracksStruct ( STX_SAVE_TRACK_STRUCT *pSaveTracksStruct , int Nb );
                    109: 
                    110: static void    STX_BuildSectorsSimple ( STX_TRACK_STRUCT *pStxTrack , Uint8 *p );
                    111: static Uint16  STX_BuildSectorID_CRC ( STX_SECTOR_STRUCT *pStxSector );
                    112: static STX_TRACK_STRUCT        *STX_FindTrack ( Uint8 Drive , Uint8 Track , Uint8 Side );
                    113: static STX_SECTOR_STRUCT *STX_FindSector ( Uint8 Drive , Uint8 Track , Uint8 Side , Uint8 SectorStruct_Nb );
                    114: static STX_SECTOR_STRUCT *STX_FindSector_By_Position ( Uint8 Drive , Uint8 Track , Uint8 Side , Uint16 BitPosition );
                    115: 
                    116: 
                    117: 
                    118: /*-----------------------------------------------------------------------*/
                    119: /**
                    120:  * Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                    121:  */
                    122: void STX_MemorySnapShot_Capture(bool bSave)
                    123: {
                    124:        int     Drive;
                    125:        Uint32  i;
                    126:        STX_SECTOR_STRUCT       *pStxSector;
                    127:        STX_TRACK_STRUCT        *pStxTrack;
                    128: 
                    129:        if ( bSave )                                    /* Saving snapshot */
                    130:        {
                    131:                MemorySnapShot_Store( &STX_State , sizeof (STX_State) );
                    132: 
                    133:                /* Also save the 'write sector' and 'write track' buffers */
                    134:                for ( Drive=0 ; Drive < MAX_FLOPPYDRIVES ; Drive++ )
                    135:                {
                    136:                        /* Save the sectors' buffer */
                    137:                        MemorySnapShot_Store ( &STX_SaveStruct[ Drive ].SaveSectorsCount , sizeof ( STX_SaveStruct[ Drive ].SaveSectorsCount ) );
                    138:                        if ( STX_SaveStruct[ Drive ].SaveSectorsCount > 0 )
                    139:                        {
                    140:                                /* Save all sectors in the memory state */
                    141:                                /* For each sector, we save the structure, then the data */
                    142:                                for ( i=0 ; i<STX_SaveStruct[ Drive ].SaveSectorsCount ; i++ )
                    143:                                {
                    144: //Str_Dump_Hex_Ascii ( (char *) &STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ], sizeof( STX_SAVE_SECTOR_STRUCT ), 16, "" , stderr );
                    145:                                        /* Save the structure */
                    146:                                        MemorySnapShot_Store ( &STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ] , sizeof( STX_SAVE_SECTOR_STRUCT ) );
                    147:                                        /* Save the sector's data */
                    148:                                        MemorySnapShot_Store ( STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ].pData ,
                    149:                                                        STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ].SectorSize );
                    150:                                }
                    151:                        }
                    152: //fprintf ( stderr , "stx save write buffer drive=%d count=%d buf=%p\n" , Drive , STX_SaveStruct[ Drive ].SaveSectorsCount , STX_SaveStruct[ Drive ].pSaveSectorsStruct );
                    153: 
                    154:                        /* Save the tracks' buffer */
                    155:                        MemorySnapShot_Store ( &STX_SaveStruct[ Drive ].SaveTracksCount , sizeof ( STX_SaveStruct[ Drive ].SaveTracksCount ) );
                    156:                        if ( STX_SaveStruct[ Drive ].SaveTracksCount > 0 )
                    157:                        {
                    158:                                /* Save all tracks in the memory state */
                    159:                                /* For each track, we save the structure, then the data */
                    160:                                for ( i=0 ; i<STX_SaveStruct[ Drive ].SaveTracksCount ; i++ )
                    161:                                {
                    162: //Str_Dump_Hex_Ascii ( (char *) &STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ], sizeof( STX_SAVE_TRACK_STRUCT ), 16, "" , stderr );
                    163:                                        /* Save the structure */
                    164:                                        MemorySnapShot_Store ( &STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ] , sizeof( STX_SAVE_TRACK_STRUCT ) );
                    165:                                        /* Save the track's data (as it was written, don't save the interpreted track) */
                    166:                                        MemorySnapShot_Store ( STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ].pDataWrite ,
                    167:                                                        STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ].TrackSizeWrite );
                    168:                                }
                    169:                        }
                    170:                }
                    171:        }
                    172: 
                    173:        else                                            /* Restoring snapshot */
                    174:        {
                    175:                MemorySnapShot_Store ( &STX_State , sizeof (STX_State) );
                    176: 
                    177:                /* Call STX_Insert_internal to recompute STX_State */
                    178:                /* (without loading an optional ".wd1772" file) */
                    179:                for ( Drive=0 ; Drive < MAX_FLOPPYDRIVES ; Drive++ )
                    180:                        if ( EmulationDrives[Drive].ImageType == FLOPPY_IMAGE_TYPE_STX )
                    181:                                if ( STX_Insert_internal ( Drive , EmulationDrives[Drive].sFileName , EmulationDrives[Drive].pBuffer ,
                    182:                                        EmulationDrives[Drive].nImageBytes ) == false )
                    183:                                {
                    184:                                        Log_AlertDlg(LOG_ERROR, "Error restoring STX image %s in drive %d" ,
                    185:                                                EmulationDrives[Drive].sFileName , Drive );
                    186:                                        return;
                    187:                                }
                    188: 
                    189:                /* Also restore the 'write sector' and 'write track' buffers */
                    190:                for ( Drive=0 ; Drive < MAX_FLOPPYDRIVES ; Drive++ )
                    191:                {
                    192:                        /* Restore the sectors' buffer */
                    193:                        MemorySnapShot_Store ( &STX_SaveStruct[ Drive ].SaveSectorsCount , sizeof ( STX_SaveStruct[ Drive ].SaveSectorsCount ) );
                    194:                        if ( STX_SaveStruct[ Drive ].SaveSectorsCount > 0 )
                    195:                        {
                    196:                                /* Alloc a buffer for all the sectors */
                    197:                                STX_SaveStruct[ Drive ].pSaveSectorsStruct = malloc ( STX_SaveStruct[ Drive ].SaveSectorsCount * sizeof ( STX_SAVE_SECTOR_STRUCT ) );
                    198:                                if ( !STX_SaveStruct[ Drive ].pSaveSectorsStruct )
                    199:                                {
                    200:                                        Log_AlertDlg(LOG_ERROR, "Error restoring STX sectors save buffer malloc size=%d in drive %d" ,
                    201:                                                STX_SaveStruct[ Drive ].SaveSectorsCount , Drive );
                    202:                                        return;
                    203:                                }
                    204: 
                    205:                                /* Load all the sectors from the memory state */
                    206:                                /* For each sector, we load the structure, then the data */
                    207:                                for ( i=0 ; i<STX_SaveStruct[ Drive ].SaveSectorsCount ; i++ )
                    208:                                {
                    209:                                        /* Load the structure */
                    210:                                        MemorySnapShot_Store ( &STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ] , sizeof( STX_SAVE_SECTOR_STRUCT ) );
                    211: //Str_Dump_Hex_Ascii ( (char *) &STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ], sizeof( STX_SAVE_SECTOR_STRUCT ), 16, "" , stderr );
                    212: 
                    213:                                        /* Load the sector's data */
                    214:                                        STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ].pData = malloc ( STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ].SectorSize );
                    215:                                        if ( !STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ].pData )
                    216:                                        {
                    217:                                                Log_AlertDlg(LOG_ERROR, "Error restoring STX save buffer for sector=%d in drive %d" ,
                    218:                                                        i , Drive );
                    219:                                                return;
                    220:                                        }
                    221:                                        MemorySnapShot_Store ( STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ].pData ,
                    222:                                                        STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ].SectorSize );
                    223: 
                    224:                                        /* Find the original sector to associate it with this saved sector */
                    225:                                        pStxSector = STX_FindSector_By_Position ( Drive , STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ].Track ,
                    226:                                                        STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ].Side ,
                    227:                                                        STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i ].BitPosition );
                    228:                                        if ( !pStxSector )
                    229:                                        {
                    230:                                                Log_AlertDlg(LOG_ERROR, "Error restoring STX save buffer for sector=%d in drive %d" ,
                    231:                                                        i , Drive );
                    232:                                                return;
                    233:                                        }
                    234:                                        pStxSector->SaveSectorIndex = i;
                    235:                                }
                    236:                        }
                    237: 
                    238:                        else
                    239:                                STX_SaveStruct[ Drive ].pSaveSectorsStruct = NULL;
                    240: //fprintf ( stderr , "stx load write buffer drive=%d count=%d buf=%p\n" , Drive , STX_SaveStruct[ Drive ].SaveSectorsCount , STX_SaveStruct[ Drive ].pSaveSectorsStruct );
                    241: 
                    242:                        /* Restore the tracks' buffer */
                    243:                        MemorySnapShot_Store ( &STX_SaveStruct[ Drive ].SaveTracksCount , sizeof ( STX_SaveStruct[ Drive ].SaveTracksCount ) );
                    244:                        if ( STX_SaveStruct[ Drive ].SaveTracksCount > 0 )
                    245:                        {
                    246:                                /* Alloc a buffer for all the tracks */
                    247:                                STX_SaveStruct[ Drive ].pSaveTracksStruct = malloc ( STX_SaveStruct[ Drive ].SaveTracksCount * sizeof ( STX_SAVE_TRACK_STRUCT ) );
                    248:                                if ( !STX_SaveStruct[ Drive ].pSaveTracksStruct )
                    249:                                {
                    250:                                        Log_AlertDlg(LOG_ERROR, "Error restoring STX tracks save buffer malloc size=%d in drive %d" ,
                    251:                                                STX_SaveStruct[ Drive ].SaveTracksCount , Drive );
                    252:                                        return;
                    253:                                }
                    254: 
                    255:                                /* Load all the tracks from the memory state */
                    256:                                /* For each track, we load the structure, then the data */
                    257:                                for ( i=0 ; i<STX_SaveStruct[ Drive ].SaveTracksCount ; i++ )
                    258:                                {
                    259:                                        /* Load the structure */
                    260:                                        MemorySnapShot_Store ( &STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ] , sizeof( STX_SAVE_TRACK_STRUCT ) );
                    261: //Str_Dump_Hex_Ascii ( (char *) &STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ], sizeof( STX_SAVE_TRACK_STRUCT ), 16, "" , stderr );
                    262: 
                    263:                                        /* Load the track's data (as it was written, don't load the interpreted track) */
                    264:                                        STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ].pDataWrite = malloc ( STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ].TrackSizeWrite );
                    265:                                        if ( !STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ].pDataWrite )
                    266:                                        {
                    267:                                                Log_AlertDlg(LOG_ERROR, "Error restoring STX save buffer for track=%d in drive %d" ,
                    268:                                                        i , Drive );
                    269:                                                return;
                    270:                                        }
                    271:                                        MemorySnapShot_Store ( STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ].pDataWrite ,
                    272:                                                        STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ].TrackSizeWrite );
                    273: 
                    274:                                        STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ].pDataRead = NULL;        /* TODO : compute interpreted track */
                    275:                                        STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ].TrackSizeRead = 0;       /* TODO : compute interpreted track */
                    276: 
                    277:                                        /* Find the original track to associate it with this saved track */
                    278:                                        pStxTrack = STX_FindTrack ( Drive , STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ].Track ,
                    279:                                                        STX_SaveStruct[ Drive ].pSaveTracksStruct[ i ].Side );
                    280:                                        if ( !pStxTrack )
                    281:                                        {
                    282:                                                Log_AlertDlg(LOG_ERROR, "Error restoring STX save buffer for track=%d in drive %d" ,
                    283:                                                        i , Drive );
                    284:                                                return;
                    285:                                        }
                    286:                                        pStxTrack->SaveTrackIndex = i;
                    287:                                }
                    288:                        }
                    289: 
                    290:                        else
                    291:                                STX_SaveStruct[ Drive ].pSaveTracksStruct = NULL;
                    292:                }
                    293: 
                    294:                fprintf ( stderr , "stx load ok\n" );
                    295:        }
                    296: }
                    297: 
                    298: 
                    299: /*-----------------------------------------------------------------------*/
                    300: /**
                    301:  * Does filename end with a .STX extension? If so, return true.
                    302:  */
                    303: bool STX_FileNameIsSTX(const char *pszFileName, bool bAllowGZ)
                    304: {
                    305:        return(File_DoesFileExtensionMatch(pszFileName,".stx")
                    306:               || (bAllowGZ && File_DoesFileExtensionMatch(pszFileName,".stx.gz")));
                    307: }
                    308: 
                    309: 
                    310: /*-----------------------------------------------------------------------*/
                    311: /**
                    312:  * Create a filename to save modifications made to an STX file
                    313:  * We replace the ".stx" or ".stx.gz" extension with ".wd1772"
                    314:  * Return true if OK
                    315:  */
                    316: bool   STX_FileNameToSave ( const char *FilenameSTX , char *FilenameSave )
                    317: {
                    318:        if ( File_ChangeFileExtension ( FilenameSTX , ".stx.gz" , FilenameSave , WD1772_SAVE_FILE_EXT ) )
                    319:                return true;
                    320:        
                    321:        else if ( File_ChangeFileExtension ( FilenameSTX , ".stx" , FilenameSave , WD1772_SAVE_FILE_EXT ) )
                    322:                return true;
                    323: 
                    324:        return false;
                    325: }
                    326: 
                    327: 
                    328: /*-----------------------------------------------------------------------*/
                    329: /**
                    330:  * Load .STX file into memory, set number of bytes loaded and return a pointer
                    331:  * to the buffer.
                    332:  */
                    333: Uint8 *STX_ReadDisk(int Drive, const char *pszFileName, long *pImageSize, int *pImageType)
                    334: {
                    335:        Uint8           *pSTXFile;
                    336: 
                    337:        *pImageSize = 0;
                    338: 
                    339:        /* Just load directly a buffer, and set ImageSize accordingly */
                    340:        pSTXFile = File_Read(pszFileName, pImageSize, NULL);
                    341:        if (!pSTXFile)
                    342:        {
                    343:                *pImageSize = 0;
                    344:                return NULL;
                    345:        }
1.1.1.2   root      346: 
                    347:        /* Check the file's header is "RSY\0" */
                    348:        if ( ( *pImageSize <= STX_HEADER_ID_LEN )
                    349:          || ( memcmp ( STX_HEADER_ID , pSTXFile , STX_HEADER_ID_LEN ) ) )
                    350:        {
                    351:                fprintf ( stderr , "Error : %s is not a valid STX image\n" , pszFileName );
                    352:                free ( pSTXFile );
                    353:                *pImageSize = 0;
                    354:                return NULL;
                    355:        }
1.1       root      356:        
                    357:        *pImageType = FLOPPY_IMAGE_TYPE_STX;
                    358:        return pSTXFile;
                    359: }
                    360: 
                    361: 
                    362: /*-----------------------------------------------------------------------*/
                    363: /**
                    364:  * Save .STX file from memory buffer. Returns true if all OK.
                    365:  * We create a file based on the initial filename by replacing the ".stx" extension
                    366:  * with ".wd1172".
                    367:  * We save all sectors, then all tracks.
                    368:  * If there're no sector and no track to save, return true and don't create
                    369:  * the save file
                    370:  */
                    371: bool STX_WriteDisk ( int Drive , const char *pszFileName , Uint8 *pBuffer , int ImageSize )
                    372: {
                    373:        FILE            *FileOut;
                    374:        char            FilenameSave[ FILENAME_MAX ];
                    375:        Uint8           buf[ 100 ];
                    376:        Uint8           *p;
                    377:        Uint32          Sector;
                    378:        Uint32          Track;
                    379:        Uint32          BlockLen;
                    380:         Uint32                  SaveSectorsCount_real;
                    381:        STX_SAVE_SECTOR_STRUCT  *pStxSaveSector;
                    382:        STX_SAVE_TRACK_STRUCT   *pStxSaveTrack;
                    383:        Uint32          i;
                    384: 
                    385: fprintf ( stderr , "stx write <%s>\n" , pszFileName );
                    386: 
                    387: 
                    388:        /* We can only save if the filename ends with ".stx" (or ".stx.gz"), not if it's a ".zip" file */
                    389:        if ( STX_FileNameIsSTX ( pszFileName , true ) == false )
                    390:        {
                    391:                Log_AlertDlg ( LOG_INFO , "WARNING : can't save changes made to this STX disk, bad file extension" );
                    392:                return false;
                    393:        }
                    394: 
                    395:        /* Count the saved sectors that are really used */
                    396:        SaveSectorsCount_real = 0;
                    397:        i = 0;
                    398:        while ( i < STX_SaveStruct[ Drive ].SaveSectorsCount )
                    399:                if ( STX_SaveStruct[ Drive ].pSaveSectorsStruct[ i++ ].StructIsUsed != 0 )
                    400:                        SaveSectorsCount_real++;
                    401: 
                    402:        /* Do we have data to save ? */
                    403:        if ( ( SaveSectorsCount_real == 0 )
                    404:          && ( STX_SaveStruct[ Drive ].SaveTracksCount == 0 ) )
                    405:                return true;
                    406: 
                    407: 
                    408:        if ( STX_FileNameToSave ( pszFileName , FilenameSave ) == false )
                    409:        {
                    410:                fprintf ( stderr , "STX_WriteDisk drive=%d file=%s, error STX_FileNameToSave\n" , Drive , pszFileName );
                    411:                return false;
                    412:        }
                    413: fprintf ( stderr , "stx write <%s>\n" , FilenameSave );
                    414: 
                    415:        
                    416:        FileOut = fopen ( FilenameSave , "wb+" );
                    417:        if ( !FileOut )
                    418:        {
                    419:                fprintf ( stderr , "STX_WriteDisk drive=%d file=%s, error fopen\n" , Drive , pszFileName );
                    420:                return false;
                    421:        }
                    422: 
                    423:        /* Write the file's header : 6 + 1 + 1 + 4 + 4 = 16 bytes */
                    424:        p = buf;
                    425:        strcpy ( (char *) p , WD1772_SAVE_FILE_ID );                            /* +0 .. +5 */
                    426:        p += strlen ( WD1772_SAVE_FILE_ID );
                    427:        *p++ = WD1772_SAVE_VERSION;                                             /* +6 */
                    428:        *p++ = WD1772_SAVE_REVISION;                                            /* +7 */
                    429: 
                    430:        STX_WriteU32_BE ( p , SaveSectorsCount_real );                          /* +8 ... +11 */
                    431:        p += 4;
                    432:        
                    433:        STX_WriteU32_BE ( p , STX_SaveStruct[ Drive ].SaveTracksCount );        /* +12 ... +15 */
                    434:        p += 4;
                    435:        
                    436:        if ( fwrite ( buf , p-buf , 1 , FileOut ) != 1 )
                    437:        {
                    438:                fprintf ( stderr , "STX_WriteDisk drive=%d file=%s, error fwrite header\n" , Drive , pszFileName );
1.1.1.2   root      439:                fclose(FileOut);
1.1       root      440:                return false;
                    441:        }
                    442: 
                    443: 
                    444:        /* Write the sectors' buffer */
                    445:        Sector = 0;
                    446:        while ( Sector < STX_SaveStruct[ Drive ].SaveSectorsCount )
                    447:        {
                    448:                pStxSaveSector = &STX_SaveStruct[ Drive ].pSaveSectorsStruct[ Sector ];
                    449: 
                    450:                if ( pStxSaveSector->StructIsUsed == 0 )
                    451:                {
                    452:                        Sector++;
                    453:                        continue;                                               /* This structure is not used anymore, ignore it */
                    454:                }
                    455: 
                    456:                /* Build the sector's header : 20 bytes */
                    457:                p = buf;
                    458:                strcpy ( (char *) p , WD1772_SAVE_SECTOR_ID );                  /* +0 .. +3 */
                    459:                p += strlen ( WD1772_SAVE_SECTOR_ID );
                    460: 
                    461:                BlockLen = 20-4 + pStxSaveSector->SectorSize;
                    462:                STX_WriteU32_BE ( p , BlockLen );                               /* +4 ... +7 */
                    463:                p += 4;
                    464: 
                    465:                *p++ = pStxSaveSector->Track;                                   /* +8 */
                    466:                *p++ = pStxSaveSector->Side;                                    /* +9 */
                    467:                STX_WriteU16_BE ( p , pStxSaveSector->BitPosition );            /* +10 ... +11 */
                    468:                p += 2;
                    469:                *p++ = pStxSaveSector->ID_Track;                                /* +12 */
                    470:                *p++ = pStxSaveSector->ID_Head;                                 /* +13 */
                    471:                *p++ = pStxSaveSector->ID_Sector;                               /* +14 */
                    472:                *p++ = pStxSaveSector->ID_Size;                                 /* +15 */
                    473:                STX_WriteU16_BE ( p , pStxSaveSector->ID_CRC );                 /* +16 ... +17 */
                    474:                p += 2;
                    475:                
                    476:                STX_WriteU16_BE ( p , pStxSaveSector->SectorSize );             /* +18 ... +19 */
                    477:                p += 2;
                    478: 
                    479:                /* Write the header */
                    480: //Str_Dump_Hex_Ascii ( (char *) buf , p-buf, 16, "" , stderr );
                    481:                if ( fwrite ( buf , p-buf , 1 , FileOut ) != 1 )
                    482:                {
                    483:                        fprintf ( stderr , "STX_WriteDisk drive=%d file=%s, error fwrite sector header\n" , Drive , pszFileName );
1.1.1.2   root      484:                        fclose(FileOut);
1.1       root      485:                        return false;
                    486:                }
                    487: 
                    488:                /* Write the data */
                    489: //Str_Dump_Hex_Ascii ( (char *) pStxSaveSector->pData , pStxSaveSector->SectorSize, 16, "" , stderr );
                    490:                if ( fwrite ( pStxSaveSector->pData , pStxSaveSector->SectorSize , 1 , FileOut ) != 1 )
                    491:                {
                    492:                        fprintf ( stderr , "STX_WriteDisk drive=%d file=%s, error fwrite sector data\n" , Drive , pszFileName );
1.1.1.2   root      493:                        fclose(FileOut);
1.1       root      494:                        return false;
                    495:                }
                    496: 
                    497:                Sector++;
                    498:        }
                    499: 
                    500: 
                    501:        /* Write the tracks' buffer */
                    502:        Track = 0;
                    503:        while ( Track < STX_SaveStruct[ Drive ].SaveTracksCount )
                    504:        {
                    505:                pStxSaveTrack = &STX_SaveStruct[ Drive ].pSaveTracksStruct[ Track ];
                    506: 
                    507:                /* Build the track's header : 12 bytes */
                    508:                p = buf;
                    509:                strcpy ( (char *) p , WD1772_SAVE_TRACK_ID );                   /* +0 ... +3 */
                    510:                p += strlen ( WD1772_SAVE_TRACK_ID );
                    511: 
                    512:                BlockLen = 12-4 + pStxSaveTrack->TrackSizeWrite;
                    513:                STX_WriteU32_BE ( p , BlockLen );                               /* +4 ... +7 */
                    514:                p += 4;
                    515: 
                    516:                *p++ = pStxSaveTrack->Track;                                    /* +8 */                        
                    517:                *p++ = pStxSaveTrack->Side;                                     /* +9 */
                    518: 
                    519:                STX_WriteU16_BE ( p , pStxSaveTrack->TrackSizeWrite );          /* +10 ... +11 */
                    520:                p += 2;
                    521: 
                    522:                /* Write the header */
                    523: //Str_Dump_Hex_Ascii ( (char *) buf , p-buf, 16, "" , stderr );
                    524:                if ( fwrite ( buf , p-buf , 1 , FileOut ) != 1 )
                    525:                {
                    526:                        fprintf ( stderr , "STX_WriteDisk drive=%d file=%s, error fwrite track header\n" , Drive , pszFileName );
1.1.1.2   root      527:                        fclose(FileOut);
1.1       root      528:                        return false;
                    529:                }
                    530: 
                    531:                /* Write the data at +12 */
                    532: //Str_Dump_Hex_Ascii ( (char *) pStxSaveTrack->pDataWrite , pStxSaveTrack->TrackSizeWrite, 16, "" , stderr );
                    533:                if ( fwrite ( pStxSaveTrack->pDataWrite , pStxSaveTrack->TrackSizeWrite , 1 , FileOut ) != 1 )
                    534:                {
                    535:                        fprintf ( stderr , "STX_WriteDisk drive=%d file=%s, error fwrite track data\n" , Drive , pszFileName );
1.1.1.2   root      536:                        fclose(FileOut);
1.1       root      537:                        return false;
                    538:                }
                    539: 
                    540:                Track++;
                    541:        }
                    542: 
                    543: 
                    544:        fclose ( FileOut );
                    545: 
                    546:        return true;
                    547: }
                    548: 
                    549: 
                    550: /*-----------------------------------------------------------------------*/
                    551: /*
                    552:  * Load a ".wd1772" save file and add it to the STX structures
                    553:  * Return true if OK.
                    554:  */
                    555: static bool    STX_LoadSaveFile ( int Drive , const char *FilenameSave )
                    556: {
                    557:        Uint8           *SaveFileBuffer;
                    558:        long            SaveFileSize;
                    559:        Uint8           *p;
                    560:        Uint8           *p_save;
                    561:        Uint8           version , revision;
                    562:        Uint32          SectorNb;
                    563:        Uint32          TrackNb;
                    564:        STX_SECTOR_STRUCT       *pStxSector;
                    565:        STX_TRACK_STRUCT        *pStxTrack;
                    566: 
                    567: 
                    568:        SaveFileBuffer = File_Read ( FilenameSave, &SaveFileSize, NULL );
                    569:        if (!SaveFileBuffer)
                    570:        {
                    571:                fprintf ( stderr , "STX_LoadSaveFile drive=%d file=%s error\n" , Drive , FilenameSave );
                    572:                return false;
                    573:        }
                    574: 
                    575:        p = SaveFileBuffer;
                    576: 
                    577:        if ( strncmp ( (char *) p , WD1772_SAVE_FILE_ID , strlen ( WD1772_SAVE_FILE_ID ) ) )    /* +0 ... +5 */
                    578:        {
                    579:                fprintf ( stderr , "STX_LoadSaveFile drive=%d file=%s bad header\n" , Drive , FilenameSave );
                    580:                free ( SaveFileBuffer );
                    581:                return false;
                    582:        }
                    583:        p += strlen ( WD1772_SAVE_FILE_ID );
                    584: 
                    585:        version = *p++;                                                         /* +6 */
                    586:        revision = *p++;                                                        /* +7 */
                    587:        if ( ( version != WD1772_SAVE_VERSION ) || ( revision != WD1772_SAVE_REVISION ) )
                    588:        {
                    589:                fprintf ( stderr , "STX_LoadSaveFile drive=%d file=%s bad version 0x%x revision 0x%x\n" , Drive , FilenameSave , version , revision );
                    590:                free ( SaveFileBuffer );
                    591:                return false;
                    592:        }
                    593: 
                    594:        STX_SaveStruct[ Drive ].SaveSectorsCount = STX_ReadU32_BE ( p );        /* +8 ... +11 */
                    595:        p += 4;
                    596: 
                    597:        STX_SaveStruct[ Drive ].SaveTracksCount = STX_ReadU32_BE ( p );         /* +12 ... +15 */
                    598:        p += 4;
                    599: 
                    600: 
                    601:        /* Alloc a buffer for all the sectors */
                    602:        if ( STX_SaveStruct[ Drive ].SaveSectorsCount > 0 )
                    603:        {
                    604:                STX_SaveStruct[ Drive ].pSaveSectorsStruct = malloc ( STX_SaveStruct[ Drive ].SaveSectorsCount * sizeof ( STX_SAVE_SECTOR_STRUCT ) );
                    605:                if ( !STX_SaveStruct[ Drive ].pSaveSectorsStruct )
                    606:                {
                    607:                        Log_AlertDlg(LOG_ERROR, "Error loading STX sectors save file malloc size=%d in drive %d" ,
                    608:                                STX_SaveStruct[ Drive ].SaveSectorsCount , Drive );
                    609:                        STX_FreeSaveStruct ( Drive );
                    610:                        free ( SaveFileBuffer );
                    611:                        return false;
                    612:                }
                    613:        }
                    614: 
                    615:        /* Alloc a buffer for all the tracks */
                    616:        if ( STX_SaveStruct[ Drive ].SaveTracksCount > 0 )
                    617:        {
                    618:                STX_SaveStruct[ Drive ].pSaveTracksStruct = malloc ( STX_SaveStruct[ Drive ].SaveTracksCount * sizeof ( STX_SAVE_TRACK_STRUCT ) );
                    619:                if ( !STX_SaveStruct[ Drive ].pSaveTracksStruct )
                    620:                {
                    621:                        Log_AlertDlg(LOG_ERROR, "Error loading STX tracks save file malloc size=%d in drive %d" ,
                    622:                                STX_SaveStruct[ Drive ].SaveTracksCount , Drive );
                    623:                        STX_FreeSaveStruct ( Drive );
                    624:                        free ( SaveFileBuffer );
                    625:                        return false;
                    626:                }
                    627:        }
                    628: 
                    629: 
                    630:        SectorNb = 0;
                    631:        TrackNb = 0;
                    632:        while ( p < SaveFileBuffer + SaveFileSize )
                    633:        {
                    634:                /* Start of a block */
                    635:                p_save = p;
                    636: //Str_Dump_Hex_Ascii ( (char *) p , 32, 16, "" , stderr );
                    637: 
                    638:                /* Check the name of this block */
                    639:                if ( strncmp ( (char *) p , WD1772_SAVE_SECTOR_ID , 4 ) == 0 )
                    640:                {
                    641: //fprintf ( stderr , "STX_LoadSaveFile drive=%d SECT block %d\n" , Drive , SectorNb );
                    642:                        if ( STX_LoadSaveFile_SECT ( Drive , &STX_SaveStruct[ Drive ].pSaveSectorsStruct[ SectorNb ] , p+4+4 ) == false )
                    643:                        {
                    644:                                Log_AlertDlg(LOG_ERROR, "Error loading STX save file SECT block %d in drive %d" ,
                    645:                                        SectorNb , Drive );
                    646:                                STX_FreeSaveStruct ( Drive );
                    647:                                free ( SaveFileBuffer );
                    648:                                return false;
                    649:                        }
                    650: 
                    651: //Str_Dump_Hex_Ascii ( (char *) &STX_SaveStruct[ Drive ].pSaveSectorsStruct[ SectorNb ] , sizeof(STX_SAVE_SECTOR_STRUCT) , 16, "" , stderr );
                    652: //Str_Dump_Hex_Ascii ( (char *) STX_SaveStruct[ Drive ].pSaveSectorsStruct[ SectorNb ].pData , 32, 16, "" , stderr );
                    653: 
                    654:                        /* Find the original sector to associate it with this saved sector */
                    655:                        pStxSector = STX_FindSector_By_Position ( Drive , STX_SaveStruct[ Drive ].pSaveSectorsStruct[ SectorNb ].Track ,
                    656:                                        STX_SaveStruct[ Drive ].pSaveSectorsStruct[ SectorNb ].Side ,
                    657:                                        STX_SaveStruct[ Drive ].pSaveSectorsStruct[ SectorNb ].BitPosition );
                    658:                        if ( !pStxSector )
                    659:                        {
                    660:                                Log_AlertDlg(LOG_ERROR, "Error restoring STX save buffer for sector=%d in drive %d" ,
                    661:                                        SectorNb , Drive );
                    662:                                STX_FreeSaveStruct ( Drive );
                    663:                                free ( SaveFileBuffer );
                    664:                                return false;
                    665:                        }
                    666:                        pStxSector->SaveSectorIndex = SectorNb;
                    667: 
                    668:                        SectorNb++;
                    669:                }
                    670:        
                    671:                else if ( strncmp ( (char *) p , WD1772_SAVE_TRACK_ID , 4 ) == 0 )
                    672:                {
                    673: //fprintf ( stderr , "STX_LoadSaveFile drive=%d TRCK block %d\n" , Drive , TrackNb );
                    674:                        if ( STX_LoadSaveFile_TRCK ( Drive , &STX_SaveStruct[ Drive ].pSaveTracksStruct[ TrackNb ] , p+4+4 ) == false )
                    675:                        {
                    676:                                Log_AlertDlg(LOG_ERROR, "Error loading STX save file TRCK block %d in drive %d" ,
                    677:                                        TrackNb , Drive );
                    678:                                STX_FreeSaveStruct ( Drive );
                    679:                                free ( SaveFileBuffer );
                    680:                                return false;
                    681:                        }
                    682:        
                    683:                        /* Find the original track to associate it with this saved track */
                    684:                        pStxTrack = STX_FindTrack ( Drive , STX_SaveStruct[ Drive ].pSaveTracksStruct[ TrackNb ].Track ,
                    685:                                                STX_SaveStruct[ Drive ].pSaveTracksStruct[ TrackNb ].Side );
                    686:                        if ( !pStxTrack )
                    687:                        {
                    688:                                Log_AlertDlg(LOG_ERROR, "Error loading STX save file TRCK block %d in drive %d" ,
                    689:                                        TrackNb , Drive );
                    690:                                STX_FreeSaveStruct ( Drive );
                    691:                                free ( SaveFileBuffer );
                    692:                                return false;
                    693:                        }
                    694:                        pStxTrack->SaveTrackIndex = TrackNb;
                    695:        
                    696:                        TrackNb++;
                    697:                }
                    698: 
                    699:                else
                    700:                {
                    701:                        fprintf ( stderr , "STX_LoadSaveFile drive=%d file=%s, unknown block %4.4s, skipping\n" , Drive , FilenameSave , p );
                    702:                }
                    703: 
                    704:                /* Next block */
                    705:                p = p_save + 4;
                    706:                p += STX_ReadU32_BE ( p );
                    707:        }
                    708: 
                    709:        free ( SaveFileBuffer );
                    710:        return true;
                    711: }
                    712: 
                    713: 
                    714: /*-----------------------------------------------------------------------*/
                    715: /*
                    716:  * Parse the "SECT" block from a ".wd1772" save file
                    717:  * Return true if OK.
                    718:  */
                    719: static bool    STX_LoadSaveFile_SECT ( int Drive, STX_SAVE_SECTOR_STRUCT *pStxSaveSector , Uint8 *p )
                    720: {
                    721:        pStxSaveSector->Track = *p++;
                    722:        pStxSaveSector->Side = *p++;
                    723: 
                    724:        pStxSaveSector->BitPosition = STX_ReadU16_BE ( p );
                    725:        p += 2;
                    726: 
                    727:        pStxSaveSector->ID_Track = *p++;
                    728:        pStxSaveSector->ID_Head = *p++;
                    729:        pStxSaveSector->ID_Sector = *p++;
                    730:        pStxSaveSector->ID_Size = *p++;
                    731:        pStxSaveSector->ID_CRC = STX_ReadU16_BE ( p );
                    732:        p += 2;
                    733: 
                    734:        pStxSaveSector->SectorSize = STX_ReadU16_BE ( p );
                    735:        p += 2;
                    736: 
                    737:        /* Copy the sector's data */
                    738:        pStxSaveSector->pData = malloc ( pStxSaveSector->SectorSize );
                    739:        if ( !pStxSaveSector->pData )
                    740:        {
                    741:                Log_AlertDlg(LOG_ERROR, "Error loading STX save buffer for track=%d side=%d bitposition=%d in drive %d" ,
                    742:                        pStxSaveSector->Track , pStxSaveSector->Side , pStxSaveSector->BitPosition , Drive );
                    743:                return false;
                    744:        }
                    745: 
                    746:        memcpy ( pStxSaveSector->pData , p , pStxSaveSector->SectorSize );
                    747: 
                    748:        pStxSaveSector->StructIsUsed = 1;
                    749: 
                    750:        return true;
                    751: }
                    752: 
                    753: 
                    754: /*-----------------------------------------------------------------------*/
                    755: /*
                    756:  * Parse the "TRCK" block from a ".wd1772" save file
                    757:  * Return true if OK.
                    758:  */
                    759: static bool    STX_LoadSaveFile_TRCK ( int Drive , STX_SAVE_TRACK_STRUCT *pStxSaveTrack , Uint8 *p )
                    760: {
                    761:        pStxSaveTrack->Track = *p++;
                    762:        pStxSaveTrack->Side = *p++;
                    763: 
                    764:        pStxSaveTrack->TrackSizeWrite = STX_ReadU16_BE ( p );
                    765:        p += 2;
                    766: 
                    767:        /* Copy the track's data */
                    768:        pStxSaveTrack->pDataWrite = malloc ( pStxSaveTrack->TrackSizeWrite );
                    769:        if ( !pStxSaveTrack->pDataWrite )
                    770:        {
                    771:                Log_AlertDlg(LOG_ERROR, "Error loading STX save buffer for track=%d side=%d in drive %d" ,
                    772:                        pStxSaveTrack->Track , pStxSaveTrack->Side , Drive );
                    773:                return false;
                    774:        }
                    775: 
                    776:        memcpy ( pStxSaveTrack->pDataWrite , p , pStxSaveTrack->TrackSizeWrite );
                    777: 
                    778:        pStxSaveTrack->pDataRead = NULL;        /* TODO : compute interpreted track */
                    779:        pStxSaveTrack->TrackSizeRead = 0;       /* TODO : compute interpreted track */
                    780: 
                    781:        return true;
                    782: }
                    783: 
                    784: 
                    785: 
                    786: /*-----------------------------------------------------------------------*/
                    787: /*
                    788:  * Init variables used to handle STX images
                    789:  */
                    790: bool   STX_Init ( void )
                    791: {
                    792:        int     i;
                    793: 
                    794:        for ( i=0 ; i<MAX_FLOPPYDRIVES ; i++ )
                    795:        {
                    796:                STX_State.ImageBuffer[ i ] = NULL;
                    797: 
                    798:                STX_SaveStruct[ i ].SaveSectorsCount = 0;
                    799:                STX_SaveStruct[ i ].pSaveSectorsStruct = NULL;
                    800:                STX_SaveStruct[ i ].SaveTracksCount = 0;
                    801:                STX_SaveStruct[ i ].pSaveTracksStruct = NULL;
                    802:        }
                    803: 
                    804:        return true;
                    805: }
                    806: 
                    807: 
                    808: /*-----------------------------------------------------------------------*/
                    809: /*
                    810:  * Init the ressources to handle the STX image inserted into a drive (0=A: 1=B:)
                    811:  * We also look for an optional save file with the ".wd1772" extension.
                    812:  * If this file exists, then we load it too.
                    813:  */
                    814: bool   STX_Insert ( int Drive , const char *FilenameSTX , Uint8 *pImageBuffer , long ImageSize )
                    815: {
                    816:        char            FilenameSave[ FILENAME_MAX ];
                    817: 
                    818:        /* Process the current STX image */
                    819:        if ( STX_Insert_internal ( Drive , FilenameSTX , pImageBuffer , ImageSize ) == false )
                    820:                return false;
                    821: 
                    822:        /* Try to load an optional ".wd1772" save file. In case of error, we continue anyway with the current STX image */
                    823:        if ( ( STX_FileNameToSave ( FilenameSTX , FilenameSave ) )
                    824:          && ( File_Exists ( FilenameSave ) ) )
                    825:        {
                    826: fprintf ( stderr , "STX : STX_Insert drive=%d file=%s buf=%p size=%ld load wd1172 %s\n" , Drive , FilenameSTX , pImageBuffer , ImageSize , FilenameSave );
                    827:                if ( STX_LoadSaveFile ( Drive , FilenameSave ) == false )
                    828:                {
                    829:                        Log_AlertDlg ( LOG_ERROR , "Can't read the STX save file '%s'. Ignore it" , FilenameSave );
                    830:                }
                    831:        }
                    832: 
                    833:        return true;
                    834: }
                    835: 
                    836: 
                    837: /*-----------------------------------------------------------------------*/
                    838: /*
                    839:  * Init the ressources to handle the STX image inserted into a drive (0=A: 1=B:)
                    840:  * This function is used when restoring a memory snapshot and does not load
                    841:  * an optional ".wd1772" save file (the saved data are already in the memory
                    842:  * snapshot)
                    843:  */
                    844: static bool    STX_Insert_internal ( int Drive , const char *FilenameSTX , Uint8 *pImageBuffer , long ImageSize )
                    845: {
                    846:        fprintf ( stderr , "STX : STX_Insert_internal drive=%d file=%s buf=%p size=%ld\n" , Drive , FilenameSTX , pImageBuffer , ImageSize );
                    847: 
                    848:        STX_State.ImageBuffer[ Drive ] = STX_BuildStruct ( pImageBuffer , STX_DEBUG_FLAG );
                    849:        if ( STX_State.ImageBuffer[ Drive ] == NULL )
                    850:        {
                    851:                fprintf ( stderr , "STX : STX_Insert_internal drive=%d file=%s buf=%p size=%ld, error in STX_BuildStruct\n" , Drive , FilenameSTX , pImageBuffer , ImageSize );
                    852:                return false;
                    853:        }
                    854: 
                    855:        return true;
                    856: }
                    857: 
                    858: 
                    859: /*-----------------------------------------------------------------------*/
                    860: /*
                    861:  * When ejecting a disk, free the ressources associated with an STX image
                    862:  */
                    863: bool   STX_Eject ( int Drive )
                    864: {
                    865:        fprintf ( stderr , "STX : STX_Eject drive=%d\n" , Drive );
                    866: 
                    867:        if ( STX_State.ImageBuffer[ Drive ] )
                    868:        {
                    869:                STX_FreeStruct ( STX_State.ImageBuffer[ Drive ] );
                    870:                STX_State.ImageBuffer[ Drive ] = NULL;
                    871:        }
                    872: 
                    873:        STX_FreeSaveStruct ( Drive );
                    874: 
                    875:        return true;
                    876: }
                    877: 
                    878: 
                    879: /*-----------------------------------------------------------------------*/
                    880: /*
                    881:  * Read words and longs stored in little endian order
                    882:  */
                    883: static Uint16  STX_ReadU16_LE ( Uint8 *p )
                    884: {
                    885:        return (p[1]<<8) +p [0];
                    886: }
                    887: 
                    888: static Uint32  STX_ReadU32_LE ( Uint8 *p )
                    889: {
                    890:        return (p[3]<<24) + (p[2]<<16) + (p[1]<<8) +p[0];
                    891: }
                    892: 
                    893: 
                    894: /*-----------------------------------------------------------------------*/
                    895: /*
                    896:  * Read words and longs stored in big endian order
                    897:  */
                    898: static Uint16  STX_ReadU16_BE ( Uint8 *p )
                    899: {
                    900:        return (p[0]<<8) + p[1];
                    901: }
                    902: 
                    903: static Uint32  STX_ReadU32_BE ( Uint8 *p )
                    904: {
                    905:        return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) +p[3];
                    906: }
                    907: 
                    908: 
                    909: /*-----------------------------------------------------------------------*/
                    910: /*
                    911:  * Store words and longs in big endian order
                    912:  */
                    913: static void    STX_WriteU16_BE ( Uint8 *p , Uint16 val )
                    914: {
                    915:        p[ 1 ] = val & 0xff;
                    916:        val >>= 8;
                    917:        p[ 0 ] = val & 0xff;
                    918: }
                    919: 
                    920: static void    STX_WriteU32_BE ( Uint8 *p , Uint32 val )
                    921: {
                    922:        p[ 3 ] = val & 0xff;
                    923:        val >>= 8;
                    924:        p[ 2 ] = val & 0xff;
                    925:        val >>= 8;
                    926:        p[ 1 ] = val & 0xff;
                    927:        val >>= 8;
                    928:        p[ 0 ] = val & 0xff;
                    929: }
                    930: 
                    931: /*-----------------------------------------------------------------------*/
                    932: /**
                    933:  * Free all the memory allocated to store an STX file
                    934:  */
                    935: static void    STX_FreeStruct ( STX_MAIN_STRUCT *pStxMain )
                    936: {
                    937:        int                     Track;
                    938: 
                    939:        if ( !pStxMain )
                    940:                return;
                    941: 
                    942:        for ( Track = 0 ; Track < pStxMain->TracksCount ; Track++ )
                    943:        {
                    944:                free ( (pStxMain->pTracksStruct[ Track ]).pSectorsStruct );
                    945:        }
                    946: 
                    947:        free ( pStxMain->pTracksStruct );
                    948:        free ( pStxMain );
                    949: }
                    950: 
                    951: 
                    952: /*-----------------------------------------------------------------------*/
                    953: /**
                    954:  * Free all the memory allocated to store saved sectors / tracks
                    955:  */
                    956: static void    STX_FreeSaveStruct ( int Drive )
                    957: {
                    958:        if ( STX_SaveStruct[ Drive ].pSaveSectorsStruct )
                    959:        {
                    960:                STX_FreeSaveSectorsStructAll ( STX_SaveStruct[ Drive ].pSaveSectorsStruct , STX_SaveStruct[ Drive ].SaveSectorsCount );
                    961:                STX_SaveStruct[ Drive ].SaveSectorsCount = 0;
                    962:                STX_SaveStruct[ Drive ].pSaveSectorsStruct = NULL;
                    963:        }
                    964: 
                    965:        if ( STX_SaveStruct[ Drive ].pSaveTracksStruct )
                    966:        {
                    967:                STX_FreeSaveTracksStructAll ( STX_SaveStruct[ Drive ].pSaveTracksStruct , STX_SaveStruct[ Drive ].SaveTracksCount );
                    968:                STX_SaveStruct[ Drive ].SaveTracksCount = 0;
                    969:                STX_SaveStruct[ Drive ].pSaveTracksStruct = NULL;
                    970:        }
                    971: }
                    972: 
                    973: 
                    974: /*-----------------------------------------------------------------------*/
                    975: /**
                    976:  * Free the memory allocated to store all the STX_SAVE_SECTOR_STRUCT
                    977:  */
                    978: static void    STX_FreeSaveSectorsStructAll ( STX_SAVE_SECTOR_STRUCT *pSaveSectorsStruct , Uint32 SaveSectorsCount )
                    979: {
                    980:        Uint32  i;
                    981: 
                    982:        if ( !pSaveSectorsStruct )
                    983:                return;
                    984: 
                    985:        for ( i = 0 ; i < SaveSectorsCount ; i++ )
                    986:        {
                    987:                STX_FreeSaveSectorsStruct ( pSaveSectorsStruct , i );
                    988:        }
                    989: 
                    990:        free ( pSaveSectorsStruct );
                    991: }
                    992: 
                    993: 
                    994: /*-----------------------------------------------------------------------*/
                    995: /**
                    996:  * Free the memory allocated to store one STX_SAVE_SECTOR_STRUCT
                    997:  */
                    998: static void    STX_FreeSaveSectorsStruct ( STX_SAVE_SECTOR_STRUCT *pSaveSectorsStruct , int Nb )
                    999: {
                   1000:        if ( pSaveSectorsStruct[ Nb ].StructIsUsed == 0 )
                   1001:                return;                                         /* This structure is already free */
                   1002: 
1.1.1.3   root     1003:        free(pSaveSectorsStruct[Nb].pData);
1.1       root     1004: 
                   1005:        pSaveSectorsStruct[ Nb ].StructIsUsed = 0;
                   1006: }
                   1007: 
                   1008: 
                   1009: /*-----------------------------------------------------------------------*/
                   1010: /**
                   1011:  * Free the memory allocated to store all the STX_SAVE_TRACK_STRUCT
                   1012:  */
                   1013: static void    STX_FreeSaveTracksStructAll ( STX_SAVE_TRACK_STRUCT *pSaveTracksStruct , Uint32 SaveTracksCount )
                   1014: {
                   1015:        Uint32  i;
                   1016: 
                   1017:        if ( !pSaveTracksStruct )
                   1018:                return;
                   1019: 
                   1020:        for ( i = 0 ; i < SaveTracksCount ; i++ )
                   1021:        {
                   1022:                STX_FreeSaveTracksStruct ( pSaveTracksStruct , i );
                   1023:        }
                   1024: 
                   1025:        free ( pSaveTracksStruct );
                   1026: }
                   1027: 
                   1028: 
                   1029: /*-----------------------------------------------------------------------*/
                   1030: /**
                   1031:  * Free the memory allocated to store one STX_SAVE_TRACK_STRUCT
                   1032:  */
                   1033: static void    STX_FreeSaveTracksStruct ( STX_SAVE_TRACK_STRUCT *pSaveTracksStruct , int Nb )
                   1034: {
1.1.1.3   root     1035:        free(pSaveTracksStruct[Nb].pDataWrite);
                   1036:        free(pSaveTracksStruct[Nb].pDataRead);
1.1       root     1037: }
                   1038: 
                   1039: 
                   1040: /*-----------------------------------------------------------------------*/
                   1041: /**
                   1042:  * Parse an STX file.
                   1043:  * The file is in pFileBuffer and we dynamically allocate memory to store
                   1044:  * the components (main header, tracks, sectors).
                   1045:  * Some internal variables/pointers are also computed, to speed up
                   1046:  * data access when the FDC emulates an STX file.
                   1047:  */
                   1048: STX_MAIN_STRUCT        *STX_BuildStruct ( Uint8 *pFileBuffer , int Debug )
                   1049: {
                   1050: 
                   1051:        STX_MAIN_STRUCT         *pStxMain;
                   1052:        STX_TRACK_STRUCT        *pStxTrack;
                   1053:        STX_SECTOR_STRUCT       *pStxSector;
                   1054:        Uint8                   *p;
                   1055:        Uint8                   *p_cur;
                   1056:        int                     Track;
                   1057:        int                     Sector;
                   1058:        Uint8                   *pFuzzyData;
                   1059:        Uint8                   *pTimingData;
                   1060:        Uint32                  MaxOffsetSectorEnd;
                   1061:        int                     VariableTimings;
                   1062: 
                   1063:        pStxMain = malloc ( sizeof ( STX_MAIN_STRUCT ) );
                   1064:        if ( !pStxMain )
                   1065:                return NULL;
                   1066:        memset ( pStxMain , 0 , sizeof ( STX_MAIN_STRUCT ) );
                   1067: 
                   1068:        p = pFileBuffer;
                   1069: 
                   1070:        /* Read file's header */
                   1071:        memcpy ( pStxMain->FileID , p , 4 ); p += 4;
                   1072:        pStxMain->Version       =       STX_ReadU16_LE ( p ); p += 2;
                   1073:        pStxMain->ImagingTool   =       STX_ReadU16_LE ( p ); p += 2;
                   1074:        pStxMain->Reserved_1    =       STX_ReadU16_LE ( p ); p += 2;
                   1075:        pStxMain->TracksCount   =       *p++;;
                   1076:        pStxMain->Revision      =       *p++;
                   1077:        pStxMain->Reserved_2    =       STX_ReadU32_LE ( p ); p += 4;
                   1078: 
                   1079:        if ( Debug & STX_DEBUG_FLAG_STRUCTURE )
                   1080:                fprintf ( stderr , "STX header ID='%.4s' Version=%4.4x ImagingTool=%4.4x Reserved1=%4.4x"
                   1081:                        " TrackCount=%d Revision=%2.2x Reserved2=%x\n" , pStxMain->FileID , pStxMain->Version ,
                   1082:                        pStxMain->ImagingTool  , pStxMain->Reserved_1 , pStxMain->TracksCount , pStxMain->Revision ,
                   1083:                        pStxMain->Reserved_2 );
                   1084: 
                   1085:        pStxMain->WarnedWriteSector = false;
                   1086:        pStxMain->WarnedWriteTrack = false;
                   1087: 
                   1088:        pStxTrack = malloc ( sizeof ( STX_TRACK_STRUCT ) * pStxMain->TracksCount );
                   1089:        if ( !pStxTrack )
                   1090:        {
                   1091:                STX_FreeStruct ( pStxMain );
                   1092:                return NULL;
                   1093:        }
                   1094:        memset ( pStxTrack , 0 , sizeof ( STX_TRACK_STRUCT ) * pStxMain->TracksCount );
                   1095:        pStxMain->pTracksStruct = pStxTrack;
                   1096: 
                   1097:        /* Parse all the track blocks */
                   1098:        for ( Track = 0 ; Track < pStxMain->TracksCount ; Track++ )
                   1099:        {
                   1100:                p_cur = p;
                   1101: 
                   1102:                pStxTrack->BlockSize            =       STX_ReadU32_LE ( p ); p += 4;
                   1103:                pStxTrack->FuzzySize            =       STX_ReadU32_LE ( p ); p += 4;
                   1104:                pStxTrack->SectorsCount         =       STX_ReadU16_LE ( p ); p += 2;
                   1105:                pStxTrack->Flags                =       STX_ReadU16_LE ( p ); p += 2;
                   1106:                pStxTrack->MFMSize              =       STX_ReadU16_LE ( p ); p += 2;
                   1107:                pStxTrack->TrackNumber          =       *p++;
                   1108:                pStxTrack->RecordType           =       *p++;
                   1109: 
                   1110:                pStxTrack->SaveTrackIndex = -1;
                   1111: 
                   1112:                if ( pStxTrack->SectorsCount == 0 )                     /* No sector (track image only, or empty / non formatted track) */
                   1113:                {
                   1114:                        pStxTrack->pSectorsStruct = NULL;
                   1115:                }
                   1116:                else
                   1117:                {
                   1118:                        /* Track contains some sectors */
                   1119:                        pStxSector = malloc ( sizeof ( STX_SECTOR_STRUCT ) * pStxTrack->SectorsCount );
                   1120:                        if ( !pStxSector )
                   1121:                        {
                   1122:                                STX_FreeStruct ( pStxMain );
                   1123:                                return NULL;
                   1124:                        }
                   1125:                        memset ( pStxSector , 0 , sizeof ( STX_SECTOR_STRUCT ) * pStxTrack->SectorsCount );
                   1126:                        pStxTrack->pSectorsStruct = pStxSector;
                   1127: 
                   1128:                        /* Do we have some sector infos after the track header or only sector data ? */
                   1129:                        if ( ( pStxTrack->Flags & STX_TRACK_FLAG_SECTOR_BLOCK ) == 0 )
                   1130:                        {
                   1131:                                /* The track only contains SectorsCount sectors of 512 bytes */
                   1132:                                /* NOTE |NP] : in that case, pStxTrack->MFMSize seems to be in bits instead of bytes */
                   1133:                                STX_BuildSectorsSimple ( pStxTrack , p );
                   1134:                                goto next_track;
                   1135:                        }
                   1136:                }
                   1137: 
                   1138:                /* Start of the optional fuzzy bits data */
                   1139:                pStxTrack->pFuzzyData = p + pStxTrack->SectorsCount * STX_SECTOR_BLOCK_SIZE;
                   1140: 
                   1141:                /* Start of the optional track data */
                   1142:                pStxTrack->pTrackData = pStxTrack->pFuzzyData + pStxTrack->FuzzySize;
                   1143: 
                   1144:                if ( ( pStxTrack->Flags & STX_TRACK_FLAG_TRACK_IMAGE ) == 0 )
                   1145:                {
                   1146:                        pStxTrack->TrackImageSyncPosition = 0;
                   1147:                        pStxTrack->TrackImageSize = 0;
                   1148:                        pStxTrack->pTrackImageData = NULL;
                   1149:                        pStxTrack->pSectorsImageData = pStxTrack->pTrackData;
                   1150:                }
                   1151:                else if ( ( pStxTrack->Flags & STX_TRACK_FLAG_TRACK_IMAGE_SYNC ) == 0 ) /* Track with size+data */
                   1152:                {
                   1153:                        pStxTrack->TrackImageSyncPosition = 0;
                   1154:                        pStxTrack->TrackImageSize = STX_ReadU16_LE ( pStxTrack->pTrackData );
                   1155:                        pStxTrack->pTrackImageData = pStxTrack->pTrackData + 2;
                   1156:                        pStxTrack->pSectorsImageData = pStxTrack->pTrackImageData + pStxTrack->TrackImageSize;
                   1157:                }
                   1158:                else                                                                    /* Track with sync offset + size + data */
                   1159:                {
                   1160:                        pStxTrack->TrackImageSyncPosition = STX_ReadU16_LE ( pStxTrack->pTrackData );
                   1161:                        pStxTrack->TrackImageSize = STX_ReadU16_LE ( pStxTrack->pTrackData + 2 );
                   1162:                        pStxTrack->pTrackImageData = pStxTrack->pTrackData + 4;
                   1163:                        pStxTrack->pSectorsImageData = pStxTrack->pTrackImageData + pStxTrack->TrackImageSize;
                   1164:                }
                   1165: 
                   1166:                if ( pStxTrack->SectorsCount == 0 )                     /* No sector (track image only, or empty / non formatted track) */
                   1167:                        goto next_track;
                   1168: 
                   1169:                /* Parse all the sectors in this track */
                   1170:                pFuzzyData = pStxTrack->pFuzzyData;
                   1171:                VariableTimings = 0;
                   1172:                MaxOffsetSectorEnd = 0;
                   1173:                for ( Sector = 0 ; Sector < pStxTrack->SectorsCount ; Sector++ )
                   1174:                {
                   1175:                        pStxSector = &(pStxTrack->pSectorsStruct[ Sector ]);
                   1176: 
                   1177:                        pStxSector->DataOffset = STX_ReadU32_LE ( p ); p += 4;
                   1178:                        pStxSector->BitPosition = STX_ReadU16_LE ( p ); p += 2;
                   1179:                        pStxSector->ReadTime = STX_ReadU16_LE ( p ); p += 2;
                   1180:                        pStxSector->ID_Track = *p++;
                   1181:                        pStxSector->ID_Head = *p++;
                   1182:                        pStxSector->ID_Sector = *p++;
                   1183:                        pStxSector->ID_Size = *p++;
                   1184:                        pStxSector->ID_CRC = ( p[0] << 8 ) | p[1] ; p +=2;
                   1185:                        pStxSector->FDC_Status = *p++;
                   1186:                        pStxSector->Reserved = *p++;
                   1187: 
                   1188:                        /* Check if sector has data */
                   1189:                        if ( ( pStxSector->FDC_Status & STX_SECTOR_FLAG_RNF ) == 0 )
                   1190:                        {
                   1191:                                /* Check if SectorSize is valid (this is just a warning, we keep only bits 0-1 anyway) */
                   1192:                                if ( pStxSector->ID_Size & ~FDC_SECTOR_SIZE_MASK )
                   1193:                                {
                   1194: //                                     fprintf ( stderr , "STX : invalid ID_Size=%d on track %d sector %d\n" ,
                   1195: //                                               pStxSector->ID_Size , Track , Sector );
                   1196:                                }
                   1197: 
                   1198:                                pStxSector->SectorSize = 128 << ( pStxSector->ID_Size & FDC_SECTOR_SIZE_MASK );
                   1199: 
                   1200:                                pStxSector->pData = pStxTrack->pTrackData + pStxSector->DataOffset;
                   1201:                                if ( pStxSector->FDC_Status & STX_SECTOR_FLAG_FUZZY )
                   1202:                                {
                   1203:                                        pStxSector->pFuzzyData = pFuzzyData;
                   1204:                                        pFuzzyData += pStxSector->SectorSize;
                   1205:                                }
                   1206: 
                   1207:                                /* Max offset of the end of all sectors image in the track */
                   1208:                                if ( MaxOffsetSectorEnd < pStxSector->DataOffset + pStxSector->SectorSize )
                   1209:                                        MaxOffsetSectorEnd = pStxSector->DataOffset + pStxSector->SectorSize;
                   1210: 
                   1211:                                if ( pStxSector->FDC_Status & STX_SECTOR_FLAG_VARIABLE_TIME )
                   1212:                                        VariableTimings = 1;
                   1213:                        }
                   1214: 
                   1215:                        pStxSector->SaveSectorIndex = -1;
                   1216:                }
                   1217: 
                   1218:                /* Start of the optional timings data, after the optional sectors image data */
                   1219:                pStxTrack->pTiming = pStxTrack->pTrackData + MaxOffsetSectorEnd;
                   1220:                if ( pStxTrack->pTiming < pStxTrack->pSectorsImageData )        /* If all sectors image were inside the track image */
                   1221:                        pStxTrack->pTiming = pStxTrack->pSectorsImageData;      /* then timings data are just after the track image */
                   1222: 
                   1223:                if ( VariableTimings == 1 )                             /* Track has at least one variable sector */
                   1224:                {
                   1225:                        if ( pStxMain->Revision == 2 )                  /* Specific timing table  */
                   1226:                        {
                   1227:                                pStxTrack->TimingFlags = STX_ReadU16_LE ( pStxTrack->pTiming ); /* always '5' ? */
                   1228:                                pStxTrack->TimingSize = STX_ReadU16_LE ( pStxTrack->pTiming + 2 );
                   1229:                                pStxTrack->pTimingData = pStxTrack->pTiming + 4;        /* 2 bytes of timing for each block of 16 bytes */
                   1230:                        }
                   1231: 
                   1232:                        /* Compute the address of the timings data for each sector with variable timings */
                   1233:                        pTimingData = pStxTrack->pTimingData;
                   1234:                        for ( Sector = 0 ; Sector < pStxTrack->SectorsCount ; Sector++ )
                   1235:                        {
                   1236:                                pStxSector = &(pStxTrack->pSectorsStruct[ Sector ]);
                   1237:                                pStxSector->pTimingData = NULL;                         /* No timings by default */
                   1238: 
                   1239:                                /* Check if sector has data + variable timings */
                   1240:                                if ( ( ( pStxSector->FDC_Status & STX_SECTOR_FLAG_RNF ) == 0 )
                   1241:                                    && ( pStxSector->FDC_Status & STX_SECTOR_FLAG_VARIABLE_TIME ) )
                   1242:                                {
                   1243:                                        if ( pStxMain->Revision == 2 )                          /* Specific table for revision 2 */
                   1244:                                        {
                   1245:                                                pStxSector->pTimingData = pTimingData;
                   1246:                                                pTimingData += ( pStxSector->SectorSize / 16 ) * 2;
                   1247:                                        }
                   1248:                                        else
                   1249:                                                pStxSector->pTimingData = TimingDataDefault;    /* Fixed table for revision 0 */
                   1250:                                }
                   1251:                        }
                   1252:                }
                   1253: 
                   1254: next_track:
                   1255:                if ( Debug & STX_DEBUG_FLAG_STRUCTURE )
                   1256:                {
                   1257:                        fprintf ( stderr , "  track %3d BlockSize=%d FuzzySize=%d Sectors=%4.4x Flags=%4.4x"
                   1258:                                " MFMSize=%d TrackNb=%2.2x Side=%d RecordType=%x"
                   1259:                                " TrackImage=%s (%d bytes, sync=%4.4x) Timings=%d,%d\n" ,
                   1260:                                Track , pStxTrack->BlockSize ,
                   1261:                                pStxTrack->FuzzySize , pStxTrack->SectorsCount , pStxTrack->Flags , pStxTrack->MFMSize ,
                   1262:                                pStxTrack->TrackNumber & 0x7f , ( pStxTrack->TrackNumber >> 7 ) & 0x01 , pStxTrack->RecordType ,
                   1263:                                pStxTrack->pTrackImageData ? "yes" : "no" , pStxTrack->TrackImageSize , pStxTrack->TrackImageSyncPosition ,
                   1264:                                pStxTrack->TimingFlags , pStxTrack->TimingSize );
                   1265: 
                   1266:                                if ( ( Debug & STX_DEBUG_FLAG_DATA ) && pStxTrack->pTrackImageData )
                   1267:                                {
                   1268:                                        fprintf ( stderr , "    track image data :\n" );
                   1269:                                        Str_Dump_Hex_Ascii ( (char *)pStxTrack->pTrackImageData , pStxTrack->TrackImageSize ,
                   1270:                                                        16 , "        " , stderr );
                   1271:                                }
                   1272: 
                   1273:                        if ( pStxTrack->SectorsCount == 0 )
                   1274:                                fprintf ( stderr , "    no sector in this track, %s\n" ,
                   1275:                                       pStxTrack->pTrackImageData ? "only track image" : "track empty / not formatted" );
                   1276:                        else
                   1277:                                for ( Sector = 0 ; Sector < pStxTrack->SectorsCount ; Sector++ )
                   1278:                                {
                   1279:                                        /* If the sector use the internal timing table, we print TimingsOffset=-1 */
                   1280:                                        pStxSector = &(pStxTrack->pSectorsStruct[ Sector ]);
                   1281:                                        fprintf ( stderr , "    sector %2d DataOffset=%d BitPosition=%d ReadTime=%d"
                   1282:                                                " [track=%2.2x head=%2.2x sector=%2.2x size=%2.2x crc=%4.4x]"
                   1283:                                                " FdcStatus=%2.2x Reserved=%2.2x TimingsOffset=%d\n" ,
                   1284:                                                Sector , pStxSector->DataOffset , pStxSector->BitPosition ,
                   1285:                                                pStxSector->ReadTime ,  pStxSector->ID_Track ,  pStxSector->ID_Head ,
                   1286:                                                pStxSector->ID_Sector , pStxSector->ID_Size , pStxSector->ID_CRC ,
                   1287:                                                pStxSector->FDC_Status , pStxSector->Reserved ,
                   1288:                                                pStxSector->pTimingData ?
                   1289:                                                        ( pStxTrack->TimingSize > 0 ? (int)(pStxSector->pTimingData - pStxTrack->pTrackData) : -1 )
                   1290:                                                        : 0 );
                   1291: 
                   1292:                                        if ( ( Debug & STX_DEBUG_FLAG_DATA ) && pStxSector->pData )
                   1293:                                        {
                   1294:                                                fprintf ( stderr , "      sector data :\n" );
                   1295:                                                Str_Dump_Hex_Ascii ( (char *)pStxSector->pData , pStxSector->SectorSize ,
                   1296:                                                                16 , "        " , stderr );
                   1297:                                        }
                   1298:                                        if ( ( Debug & STX_DEBUG_FLAG_DATA ) && pStxSector->pFuzzyData )
                   1299:                                        {
                   1300:                                                fprintf ( stderr , "      fuzzy data :\n" );
                   1301:                                                Str_Dump_Hex_Ascii ( (char *)pStxSector->pFuzzyData , pStxSector->SectorSize ,
                   1302:                                                                16 , "        " , stderr );
                   1303:                                        }
                   1304:                                        if ( ( Debug & STX_DEBUG_FLAG_DATA ) && pStxSector->pTimingData )
                   1305:                                        {
                   1306:                                                fprintf ( stderr , "      timing data :\n" );
                   1307:                                                Str_Dump_Hex_Ascii ( (char *)pStxSector->pTimingData , ( pStxSector->SectorSize / 16 ) * 2 ,
                   1308:                                                                16 , "        " , stderr );
                   1309:                                        }
                   1310:                                }
                   1311:                }
                   1312: 
                   1313:                p = p_cur + pStxTrack->BlockSize;                       /* Next Track block */
                   1314:                pStxTrack++;
                   1315:        }
                   1316: 
                   1317: 
                   1318:        return pStxMain;
                   1319: }
                   1320: 
                   1321: 
                   1322: /*-----------------------------------------------------------------------*/
                   1323: /**
                   1324:  * When a track only consists of the content of each 512 bytes sector and
                   1325:  * no timings informations, we must compute some default values for each
                   1326:  * sector, as well as the position of the corresponding 512 bytes of data.
                   1327:  * This is only used when storing unprotected tracks.
                   1328:  */
                   1329: static void    STX_BuildSectorsSimple ( STX_TRACK_STRUCT *pStxTrack , Uint8 *p )
                   1330: {
                   1331:        int     Sector;
                   1332:        int     BytePosition;
                   1333:        Uint16  CRC;
                   1334: 
                   1335:        BytePosition = FDC_TRACK_LAYOUT_STANDARD_GAP1 + FDC_TRACK_LAYOUT_STANDARD_GAP2;         /* Points to the 3x$A1 before the 1st IDAM $FE */
                   1336:        BytePosition += 4;                                              /* Pasti seems to point after the 3x$A1 and the IDAM $FE */
                   1337:        
                   1338:        for ( Sector = 0 ; Sector < pStxTrack->SectorsCount ; Sector++ )
                   1339:        {
                   1340:                pStxTrack->pSectorsStruct[ Sector ].SaveSectorIndex = -1;
                   1341:                pStxTrack->pSectorsStruct[ Sector ].DataOffset = 0;
                   1342:                pStxTrack->pSectorsStruct[ Sector ].BitPosition = BytePosition * 8;
                   1343:                pStxTrack->pSectorsStruct[ Sector ].ReadTime = 0;
                   1344: 
                   1345:                /* Build the ID Field */
                   1346:                pStxTrack->pSectorsStruct[ Sector ].ID_Track = pStxTrack->TrackNumber & 0x7f;
                   1347:                pStxTrack->pSectorsStruct[ Sector ].ID_Head = ( pStxTrack->TrackNumber >> 7 ) & 0x01;
                   1348:                pStxTrack->pSectorsStruct[ Sector ].ID_Sector = Sector + 1;
                   1349:                pStxTrack->pSectorsStruct[ Sector ].ID_Size = FDC_SECTOR_SIZE_512;
                   1350:                CRC = STX_BuildSectorID_CRC ( &(pStxTrack->pSectorsStruct[ Sector ]) );
                   1351:                pStxTrack->pSectorsStruct[ Sector ].ID_CRC = CRC;
                   1352: 
                   1353:                pStxTrack->pSectorsStruct[ Sector ].FDC_Status = 0;
                   1354:                pStxTrack->pSectorsStruct[ Sector ].Reserved = 0;
                   1355:                pStxTrack->pSectorsStruct[ Sector ].pData = p + Sector * 512;
                   1356:                pStxTrack->pSectorsStruct[ Sector ].SectorSize = 128 << pStxTrack->pSectorsStruct[ Sector ].ID_Size;
                   1357: 
                   1358:                BytePosition += FDC_TRACK_LAYOUT_STANDARD_RAW_SECTOR_512;
                   1359:        }
                   1360: }
                   1361: 
                   1362: 
                   1363: 
                   1364: /*-----------------------------------------------------------------------*/
                   1365: /**
                   1366:  * Compute the CRC of the Address Field for a given sector.
                   1367:  */
                   1368: static Uint16  STX_BuildSectorID_CRC ( STX_SECTOR_STRUCT *pStxSector )
                   1369: {
                   1370:         Uint16  CRC;
                   1371: 
                   1372:        crc16_reset ( &CRC );
                   1373:        crc16_add_byte ( &CRC , 0xa1 );
                   1374:        crc16_add_byte ( &CRC , 0xa1 );
                   1375:        crc16_add_byte ( &CRC , 0xa1 );
                   1376:        crc16_add_byte ( &CRC , 0xfe );
                   1377:        crc16_add_byte ( &CRC , pStxSector->ID_Track );
                   1378:        crc16_add_byte ( &CRC , pStxSector->ID_Head );
                   1379:        crc16_add_byte ( &CRC , pStxSector->ID_Sector );
                   1380:        crc16_add_byte ( &CRC , pStxSector->ID_Size );
                   1381: 
                   1382:        return CRC;
                   1383: }
                   1384: 
                   1385: 
                   1386: 
                   1387: /*-----------------------------------------------------------------------*/
                   1388: /**
                   1389:  * Find a track in the floppy image inserted into a drive.
                   1390:  */
                   1391: static STX_TRACK_STRUCT        *STX_FindTrack ( Uint8 Drive , Uint8 Track , Uint8 Side )
                   1392: {
                   1393:        int     i;
                   1394: 
                   1395:        if ( STX_State.ImageBuffer[ Drive ] == NULL )
                   1396:                return NULL;
                   1397: 
                   1398:        for ( i=0 ; i<STX_State.ImageBuffer[ Drive ]->TracksCount ; i++ )
                   1399:                if ( STX_State.ImageBuffer[ Drive ]->pTracksStruct[ i ].TrackNumber == ( ( Track & 0x7f ) | ( Side << 7 ) ) )
                   1400:                        return &(STX_State.ImageBuffer[ Drive ]->pTracksStruct[ i ]);
                   1401: 
                   1402:        return NULL;
                   1403: }
                   1404: 
                   1405: 
                   1406: 
                   1407: /*-----------------------------------------------------------------------*/
                   1408: /**
                   1409:  * Find a sector in the floppy image inserted into a drive.
                   1410:  * SectorStruct_Nb is a value set by a previous call to FDC_NextSectorID_FdcCycles_STX()
                   1411:  */
                   1412: static STX_SECTOR_STRUCT       *STX_FindSector ( Uint8 Drive , Uint8 Track , Uint8 Side , Uint8 SectorStruct_Nb )
                   1413: {
                   1414:        STX_TRACK_STRUCT        *pStxTrack;
                   1415: 
                   1416:        if ( STX_State.ImageBuffer[ Drive ] == NULL )
                   1417:                return NULL;
                   1418: 
                   1419:        pStxTrack = STX_FindTrack ( Drive , Track , Side );
                   1420:        if ( pStxTrack == NULL )
                   1421:                return NULL;
                   1422: 
                   1423:        if ( pStxTrack->pSectorsStruct == NULL )
                   1424:                return NULL;
                   1425: 
                   1426:        return &(pStxTrack->pSectorsStruct[ SectorStruct_Nb ]);
                   1427: }
                   1428: 
                   1429: 
                   1430: 
                   1431: /*-----------------------------------------------------------------------*/
                   1432: /**
                   1433:  * Find a sector in the floppy image inserted into a drive.
                   1434:  * The sector is identified by its BitPosition which is unique per track/side
                   1435:  */
                   1436: static STX_SECTOR_STRUCT       *STX_FindSector_By_Position ( Uint8 Drive , Uint8 Track , Uint8 Side , Uint16 BitPosition )
                   1437: {
                   1438:        STX_TRACK_STRUCT        *pStxTrack;
                   1439:        int                     Sector;
                   1440: 
                   1441:        if ( STX_State.ImageBuffer[ Drive ] == NULL )
                   1442:                return NULL;
                   1443: 
                   1444:        pStxTrack = STX_FindTrack ( Drive , Track , Side );
                   1445:        if ( pStxTrack == NULL )
                   1446:                return NULL;
                   1447: 
                   1448:        if ( pStxTrack->pSectorsStruct == NULL )
                   1449:                return NULL;
                   1450: 
                   1451:        for ( Sector=0 ; Sector<pStxTrack->SectorsCount ; Sector++ )
                   1452:                if ( pStxTrack->pSectorsStruct[ Sector ].BitPosition == BitPosition )
                   1453:                        return &(pStxTrack->pSectorsStruct[ Sector ]);
                   1454:        
                   1455:        return NULL;
                   1456: }
                   1457: 
                   1458: 
                   1459: 
                   1460: /*-----------------------------------------------------------------------*/
                   1461: /**
                   1462:  * Return the number of FDC cycles to go from one index pulse to the next
                   1463:  * one on a given drive/track/side.
                   1464:  * We take the TrackSize into account to return this delay.
                   1465:  */
1.1.1.2   root     1466: Uint32 FDC_GetCyclesPerRev_FdcCycles_STX ( Uint8 Drive , Uint8 Track , Uint8 Side )
1.1       root     1467: {
                   1468:        STX_TRACK_STRUCT        *pStxTrack;
                   1469:        int                     TrackSize;
                   1470: 
                   1471:        pStxTrack = STX_FindTrack ( Drive , Track , Side );
                   1472:        if ( pStxTrack == NULL )
                   1473:                TrackSize =  FDC_TRACK_BYTES_STANDARD;                  /* Use a standard track length is track is not available */
                   1474: 
                   1475:        else if ( pStxTrack->pTrackImageData )
                   1476:                TrackSize = pStxTrack->TrackImageSize;
                   1477:        else if ( ( pStxTrack->Flags & STX_TRACK_FLAG_SECTOR_BLOCK ) == 0 )
                   1478:                TrackSize = pStxTrack->MFMSize / 8;             /* When the track contains only sector data, MFMSize is in bits */
                   1479:        else
                   1480:                TrackSize = pStxTrack->MFMSize;
                   1481: 
                   1482: //fprintf ( stderr , "fdc stx drive=%d track=0x%x side=%d size=%d\n" , Drive , Track, Side , TrackSize );
                   1483:        return TrackSize * FDC_DELAY_CYCLE_MFM_BYTE;
                   1484: }
                   1485: 
                   1486: 
                   1487: 
                   1488: /*-----------------------------------------------------------------------*/
                   1489: /**
                   1490:  * Return the number of FDC cycles to wait before reaching the next
                   1491:  * sector's ID Field in the track ($A1 $A1 $A1 $FE TR SIDE SR LEN CRC1 CRC2)
                   1492:  * If no ID Field is found before the end of the track, we use the 1st
                   1493:  * ID Field of the track (which simulates a full spin of the floppy).
                   1494:  * We also store the next sector's number into NextSectorStruct_Nbr,
                   1495:  * the next sector's number into NextSector_ID_Field_SR, the next track's number
1.1.1.3   root     1496:  * into NextSector_ID_Field_TR, the next sector's length into
1.1       root     1497:  * NextSector_ID_Field_LEN and if the CRC is correct or not into NextSector_ID_Field_CRC_OK.
                   1498:  * This function assumes the sectors of each track are sorted in ascending order
                   1499:  * using BitPosition.
                   1500:  * If there's no available drive/floppy or no ID field in the track, we return -1
                   1501:  */
1.1.1.2   root     1502: int    FDC_NextSectorID_FdcCycles_STX ( Uint8 Drive , Uint8 NumberOfHeads , Uint8 Track , Uint8 Side )
1.1       root     1503: {
                   1504:        STX_TRACK_STRUCT        *pStxTrack;
                   1505:        int                     CurrentPos_FdcCycles;
                   1506:        int                     i;
                   1507:        int                     Delay_FdcCycles;
                   1508:        int                     TrackSize;
                   1509: 
                   1510:        CurrentPos_FdcCycles = FDC_IndexPulse_GetCurrentPos_FdcCycles ( NULL );
                   1511:        if ( CurrentPos_FdcCycles < 0 )                                 /* No drive/floppy available at the moment */
                   1512:                return -1;
                   1513: 
                   1514:        if ( ( Side == 1 ) && ( NumberOfHeads == 1 ) )                  /* Can't read side 1 on a single sided drive */
                   1515:                return -1;
                   1516: 
                   1517:        pStxTrack = STX_FindTrack ( Drive , Track , Side );
                   1518:        if ( pStxTrack == NULL )                                        /* Track/Side don't exist in this STX image */
                   1519:                return -1;
                   1520: 
                   1521:        if ( pStxTrack->SectorsCount == 0 )                             /* No sector (track image only, or empty / non formatted track) */
                   1522:                return -1;
                   1523: 
                   1524:        /* Compare CurrentPos_FdcCycles with each sector's position in ascending order */
1.1.1.4 ! root     1525:        /* (minus 4 bytes, see below) */
1.1       root     1526:        for ( i=0 ; i<pStxTrack->SectorsCount ; i++ )
                   1527:        {
1.1.1.4 ! root     1528:                if ( CurrentPos_FdcCycles < (int)pStxTrack->pSectorsStruct[ i ].BitPosition*FDC_DELAY_CYCLE_MFM_BIT /* 1 bit = 32 cycles at 8 MHz */
        !          1529:                                         - 4 * FDC_DELAY_CYCLE_MFM_BYTE )
1.1       root     1530:                        break;                                          /* We found the next sector */
                   1531:        }
                   1532: 
                   1533:        if ( i == pStxTrack->SectorsCount )                             /* CurrentPos_FdcCycles is after the last ID Field of this track */
                   1534:        {
                   1535:                /* Reach end of track (new index pulse), then go to 1st sector from current position */
                   1536:                if ( pStxTrack->pTrackImageData )
                   1537:                        TrackSize = pStxTrack->TrackImageSize;
                   1538:                else if ( ( pStxTrack->Flags & STX_TRACK_FLAG_SECTOR_BLOCK ) == 0 )
                   1539:                        TrackSize = pStxTrack->MFMSize / 8;             /* When the track contains only sector data, MFMSize is in bits */
                   1540:                else
                   1541:                        TrackSize = pStxTrack->MFMSize;
                   1542: 
                   1543:                Delay_FdcCycles = TrackSize * FDC_DELAY_CYCLE_MFM_BYTE - CurrentPos_FdcCycles
                   1544:                                + pStxTrack->pSectorsStruct[ 0 ].BitPosition*FDC_DELAY_CYCLE_MFM_BIT;
                   1545:                STX_State.NextSectorStruct_Nbr = 0;
                   1546: //fprintf ( stderr , "size=%d pos=%d pos0=%d delay=%d\n" , TrackSize, CurrentPos_FdcCycles, pStxTrack->pSectorsStruct[ 0 ].BitPosition , Delay_FdcCycles );
                   1547:        }
                   1548:        else                                                            /* There's an ID Field before end of track */
                   1549:        {
                   1550:                Delay_FdcCycles = (int)pStxTrack->pSectorsStruct[ i ].BitPosition*FDC_DELAY_CYCLE_MFM_BIT - CurrentPos_FdcCycles;
                   1551:                STX_State.NextSectorStruct_Nbr = i;
                   1552: //fprintf ( stderr , "i=%d pos=%d posi=%d delay=%d\n" , i, CurrentPos_FdcCycles, pStxTrack->pSectorsStruct[ i ].BitPosition*FDC_DELAY_CYCLE_MFM_BIT , Delay_FdcCycles );
                   1553:        }
                   1554: 
                   1555:        /* Store the value of the track/sector numbers in the next ID field */
                   1556:        STX_State.NextSector_ID_Field_TR = pStxTrack->pSectorsStruct[ STX_State.NextSectorStruct_Nbr ].ID_Track;
                   1557:        STX_State.NextSector_ID_Field_SR = pStxTrack->pSectorsStruct[ STX_State.NextSectorStruct_Nbr ].ID_Sector;
                   1558:        STX_State.NextSector_ID_Field_LEN = pStxTrack->pSectorsStruct[ STX_State.NextSectorStruct_Nbr ].ID_Size;
                   1559: 
                   1560:        /* If RNF is set and CRC error is set, then this ID field has a CRC error */
                   1561:        if ( ( pStxTrack->pSectorsStruct[ STX_State.NextSectorStruct_Nbr ].FDC_Status & STX_SECTOR_FLAG_RNF )
                   1562:          && ( pStxTrack->pSectorsStruct[ STX_State.NextSectorStruct_Nbr ].FDC_Status & STX_SECTOR_FLAG_CRC ) )
                   1563:                STX_State.NextSector_ID_Field_CRC_OK = 0;               /* CRC bad */
                   1564:        else
                   1565:                STX_State.NextSector_ID_Field_CRC_OK = 1;               /* CRC correct */
                   1566: 
                   1567:        /* BitPosition in STX seems to point just after the IDAM $FE ; we need to point 4 bytes earlier at the 1st $A1 */
                   1568:        Delay_FdcCycles -= 4 * FDC_DELAY_CYCLE_MFM_BYTE;                /* Correct delay to point to $A1 $A1 $A1 $FE */
                   1569:        
                   1570: //fprintf ( stderr , "fdc bytes next sector pos=%d delay=%d maxsr=%d nextsr=%d\n" , CurrentPos_FdcCycles, Delay_FdcCycles, pStxTrack->SectorsCount, STX_State.NextSectorStruct_Nbr );
                   1571:        return Delay_FdcCycles;
                   1572: }
                   1573: 
                   1574: 
                   1575: 
                   1576: /*-----------------------------------------------------------------------*/
                   1577: /**
                   1578:  * Return the value of the track number in the next ID field set by
                   1579:  * FDC_NextSectorID_FdcCycles_STX.
                   1580:  */
1.1.1.2   root     1581: Uint8  FDC_NextSectorID_TR_STX ( void )
1.1       root     1582: {
                   1583:        return STX_State.NextSector_ID_Field_TR;
                   1584: }
                   1585: 
                   1586: 
                   1587: /*-----------------------------------------------------------------------*/
                   1588: /**
                   1589:  * Return the value of the sector number in the next ID field set by
                   1590:  * FDC_NextSectorID_FdcCycles_STX.
                   1591:  */
1.1.1.2   root     1592: Uint8  FDC_NextSectorID_SR_STX ( void )
1.1       root     1593: {
                   1594:        return STX_State.NextSector_ID_Field_SR;
                   1595: }
                   1596: 
                   1597: 
                   1598: /*-----------------------------------------------------------------------*/
                   1599: /**
                   1600:  * Return the value of the sector's length in the next ID field set by
                   1601:  * FDC_NextSectorID_FdcCycles_STX.
                   1602:  */
1.1.1.2   root     1603: Uint8  FDC_NextSectorID_LEN_STX ( void )
1.1       root     1604: {
                   1605:        return STX_State.NextSector_ID_Field_LEN;
                   1606: }
                   1607: 
                   1608: 
                   1609: /*-----------------------------------------------------------------------*/
                   1610: /**
                   1611:  * Return the status of the CRC in the next ID field set by
                   1612:  * FDC_NextSectorID_FdcCycles_STX.
                   1613:  * If '0', CRC is bad, else CRC is OK
                   1614:  */
1.1.1.2   root     1615: Uint8  FDC_NextSectorID_CRC_OK_STX ( void )
1.1       root     1616: {
                   1617:        return STX_State.NextSector_ID_Field_CRC_OK;
                   1618: }
                   1619: 
                   1620: 
                   1621: /*-----------------------------------------------------------------------*/
                   1622: /**
                   1623:  * Read a sector from a floppy image in STX format (used in type II command)
                   1624:  * We return the sector NextSectorStruct_Nbr, whose value was set
                   1625:  * by the latest call to FDC_NextSectorID_FdcCycles_STX
                   1626:  * Each byte of the sector is added to the FDC buffer with a default timing
                   1627:  * (32 microsec) or a variable timing, depending on the sector's flags.
                   1628:  * Some sectors can also contains "fuzzy" bits.
                   1629:  * Special care must be taken to compute the timing of each byte, which can
                   1630:  * be a decimal value and must be rounded to the best possible integer.
                   1631:  *
                   1632:  * If the sector's data were changed by a 'write sector' command, then we assume
                   1633:  * a sector with no fuzzy byte and standard timings.
                   1634:  *
                   1635:  * Return RNF if sector was not found, else return CRC and RECORD_TYPE values
                   1636:  * for the status register.
                   1637:  */
1.1.1.2   root     1638: Uint8  FDC_ReadSector_STX ( Uint8 Drive , Uint8 Track , Uint8 Sector , Uint8 Side , int *pSectorSize )
1.1       root     1639: {
                   1640:        STX_SECTOR_STRUCT       *pStxSector;
                   1641:        int                     i;
                   1642:        Uint8                   Byte;
                   1643:        Uint16                  Timing;
                   1644:        Uint32                  Sector_ReadTime;
                   1645:        double                  Total_cur;                              /* To compute closest integer timings for each byte */
                   1646:        double                  Total_prev;
                   1647:        Uint8                   *pSector_WriteData;
                   1648: 
                   1649:        pStxSector = STX_FindSector ( Drive , Track , Side , STX_State.NextSectorStruct_Nbr );
                   1650:        if ( pStxSector == NULL )
                   1651:        {
                   1652:                fprintf ( stderr , "FDC_ReadSector_STX drive=%d track=%d side=%d sector=%d returns null !\n" ,
                   1653:                                Drive , Track , Side , STX_State.NextSectorStruct_Nbr );
                   1654:                return STX_SECTOR_FLAG_RNF;                             /* Should not happen if FDC_NextSectorID_FdcCycles_STX succeeded before */
                   1655:        }
                   1656: 
                   1657:        /* If RNF is set, return FDC_STR_BIT_RNF */
                   1658:        if ( pStxSector->FDC_Status & STX_SECTOR_FLAG_RNF )
                   1659:                return STX_SECTOR_FLAG_RNF;                             /* RNF in FDC's status register */
                   1660: 
                   1661:        *pSectorSize = pStxSector->SectorSize;
                   1662:        Sector_ReadTime = pStxSector->ReadTime;
                   1663: 
                   1664:        /* Check if this sector was changed by a 'write sector' command */
                   1665:        /* If so, we use this recent buffer instead of the original STX content */
                   1666:        if (STX_SaveStruct[Drive].SaveSectorsCount > 0 && pStxSector->SaveSectorIndex >= 0)
                   1667:        {
                   1668:                pSector_WriteData = STX_SaveStruct[ Drive ].pSaveSectorsStruct[ pStxSector->SaveSectorIndex ].pData;
                   1669:                Sector_ReadTime = 0;                                    /* Standard timings */
                   1670: 
                   1671:                LOG_TRACE(TRACE_FDC, "fdc stx read sector drive=%d track=%d sect=%d side=%d using saved sector=%d\n" ,
                   1672:                        Drive, Track, Sector, Side , pStxSector->SaveSectorIndex );
                   1673:        }
                   1674:        else
                   1675:                pSector_WriteData = NULL;
                   1676: 
                   1677:        if ( Sector_ReadTime == 0 )                                     /* Sector has a standard delay (32 us per byte) */
                   1678:                Sector_ReadTime = 32 * pStxSector->SectorSize;          /* Use the real standard value instead of 0 */
                   1679:        Sector_ReadTime *= 8;                                           /* Convert delay in us to a number of FDC cycles at 8 MHz */
                   1680: 
                   1681:        Total_prev = 0;
                   1682:        for ( i=0 ; i<pStxSector->SectorSize ; i++ )
                   1683:        {
                   1684:                /* Get the value of each byte, with possible fuzzy bits */
                   1685:                if ( pSector_WriteData == NULL )                        /* Use original STX content */
                   1686:                {
                   1687:                        Byte = pStxSector->pData[ i ];
                   1688:                        if ( pStxSector->pFuzzyData )
                   1689:                                Byte = ( Byte & pStxSector->pFuzzyData[ i ] ) | ( rand() & ~pStxSector->pFuzzyData[ i ] );
                   1690:                }
                   1691: 
                   1692:                else                                                    /* Use data from 'write sector' */
                   1693:                        Byte = pSector_WriteData[ i ];
                   1694: 
                   1695:                /* Compute the timing in FDC cycles to transfer this byte */
                   1696:                if ( ( pStxSector->pTimingData )                        /* Specific timing for each block of 16 bytes */
                   1697:                  && ( pSector_WriteData == NULL ) )
                   1698:                {
                   1699:                        Timing = ( pStxSector->pTimingData[ ( i>>4 ) * 2 ] << 8 )
                   1700:                                + pStxSector->pTimingData[ ( i>>4 ) * 2 + 1 ];  /* Get big endian timing for this block of 16 bytes */
                   1701: 
                   1702:                        /* [NP] Formula to convert timing data comes from Pasti.prg 0.4b : */
                   1703:                        /* 1 unit of timing = 32 FDC cycles at 8 MHz + 28 cycles to complete each block of 16 bytes */
                   1704:                        Timing = Timing * 32 + 28;
                   1705: 
                   1706:                        if ( i % 16 == 0 )      Total_prev = 0;         /* New block of 16 bytes */
                   1707:                        Total_cur = ( (double)Timing * ( ( i % 16 ) + 1 ) ) / 16;
                   1708:                        Timing = rint ( Total_cur - Total_prev );
                   1709:                        Total_prev += Timing;
                   1710:                }
                   1711:                else                                                    /* Specific timing in us for the whole sector */
                   1712:                {
                   1713:                        Total_cur = ( (double)Sector_ReadTime * ( i+1 ) ) / pStxSector->SectorSize;
                   1714:                        Timing = rint ( Total_cur - Total_prev );
                   1715:                        Total_prev += Timing;
                   1716:                }
                   1717: 
                   1718:                /* Add the Byte to the buffer, Timing should be a number of FDC cycles at 8 MHz */
                   1719:                FDC_Buffer_Add_Timing ( Byte , Timing );
                   1720:        }
                   1721: 
                   1722:        /* Return only bits 3 and 5 of the FDC_Status */
                   1723:        return pStxSector->FDC_Status & ( STX_SECTOR_FLAG_CRC | STX_SECTOR_FLAG_RECORD_TYPE );
                   1724: }
                   1725: 
                   1726: 
                   1727: /*-----------------------------------------------------------------------*/
                   1728: /**
                   1729:  * Write a sector to a floppy image in STX format (used in type II command)
                   1730:  *
                   1731:  * STX format doesn't support write command. For each 'write sector' we
                   1732:  * store the sector data in a dedicated buffer STX_SaveStruct[].pSaveSectorsStruct.
                   1733:  * When the sector is read later, we return the data from STX_SaveStruct[].pSaveSectorsStruct
                   1734:  * instead of returning the data from the original STX file.
                   1735:  *
                   1736:  * We only allow writing for sectors whose ID field has a correct CRC and
                   1737:  * where RNF is not set.
                   1738:  * Any valid size can be written : 128, 256, 512 or 1024 bytes
                   1739:  *
                   1740:  * NOTE : data will saved in memory snapshot, as well as in an additional
                   1741:  * file with the extension .wd1772.
                   1742:  *
                   1743:  * Return RNF if sector was not found or CRC if ID field has a CRC error.
                   1744:  * Return 0 if OK.
                   1745:  */
1.1.1.2   root     1746: Uint8  FDC_WriteSector_STX ( Uint8 Drive , Uint8 Track , Uint8 Sector , Uint8 Side , int SectorSize )
1.1       root     1747: {
                   1748:        STX_SECTOR_STRUCT       *pStxSector;
                   1749:        int                     i;
                   1750:        Uint8                   *pSector_WriteData;
                   1751:        void                    *pNewBuf;
                   1752:        STX_SAVE_SECTOR_STRUCT  *pStxSaveSector;
                   1753: 
                   1754:        pStxSector = STX_FindSector ( Drive , Track , Side , STX_State.NextSectorStruct_Nbr );
                   1755:        if ( pStxSector == NULL )
                   1756:        {
                   1757:                fprintf ( stderr , "FDC_WriteSector_STX drive=%d track=%d side=%d sector=%d returns null !\n" ,
                   1758:                                Drive , Track , Side , STX_State.NextSectorStruct_Nbr );
                   1759:                return STX_SECTOR_FLAG_RNF;                             /* Should not happen if FDC_NextSectorID_FdcCycles_STX succeeded before */
                   1760:        }
                   1761: 
                   1762:        /* If RNF is set, return FDC_STR_BIT_RNF */
                   1763:        if ( pStxSector->FDC_Status & STX_SECTOR_FLAG_RNF )
                   1764:                return STX_SECTOR_FLAG_RNF;                             /* RNF in FDC's status register */
                   1765: 
                   1766:        /* If CRC is set, return FDC_STR_BIT_RNF */
                   1767:        if ( pStxSector->FDC_Status & STX_SECTOR_FLAG_CRC )
                   1768:                return STX_SECTOR_FLAG_CRC;                             /* CRC in FDC's status register */
                   1769: 
                   1770: 
                   1771:        /* Check if this sector was already changed by a 'write sector' command */
                   1772:        /* If so, we use the same buffer. Else we alloc a new buffer for this sector */
                   1773:        if ( pStxSector->SaveSectorIndex < 0 )
                   1774:        {
                   1775: //fprintf ( stderr , "realloc\n" );
                   1776:                /* Increase save buffer by 1 */
                   1777:                pNewBuf = realloc ( STX_SaveStruct[ Drive ].pSaveSectorsStruct ,
                   1778:                                    ( STX_SaveStruct[ Drive ].SaveSectorsCount + 1 ) * sizeof ( STX_SAVE_SECTOR_STRUCT ) );
                   1779:                if ( pNewBuf == NULL )
                   1780:                {
                   1781:                        fprintf ( stderr , "FDC_WriteSector_STX drive=%d track=%d side=%d sector=%d realloc error !\n" ,
                   1782:                                        Drive , Track , Side , STX_State.NextSectorStruct_Nbr );
                   1783:                        return STX_SECTOR_FLAG_RNF;
                   1784:                }
                   1785: 
                   1786:                /* Save the new buffer values */
                   1787:                STX_SaveStruct[ Drive ].pSaveSectorsStruct = (STX_SAVE_SECTOR_STRUCT *) pNewBuf;;
                   1788:                STX_SaveStruct[ Drive ].SaveSectorsCount++;
                   1789: 
                   1790:                /* Create the new entry in pSaveSectorsStruct */
                   1791:                pNewBuf = malloc ( SectorSize );
                   1792:                if ( pNewBuf == NULL )
                   1793:                {
                   1794:                        fprintf ( stderr , "FDC_WriteSector_STX drive=%d track=%d side=%d sector=%d malloc error !\n" ,
                   1795:                                        Drive , Track , Side , STX_State.NextSectorStruct_Nbr );
                   1796:                        return STX_SECTOR_FLAG_RNF;
                   1797:                }
                   1798: 
                   1799:                pStxSector->SaveSectorIndex = STX_SaveStruct[ Drive ].SaveSectorsCount - 1;
                   1800: 
                   1801:                /* Fill the new SaveSectorStruct. We copy some of the original sector's values */
                   1802:                /* in the saved sector */
                   1803:                pStxSaveSector = &STX_SaveStruct[ Drive ].pSaveSectorsStruct[ pStxSector->SaveSectorIndex ];
                   1804: 
                   1805:                pStxSaveSector->Track           = Track;
                   1806:                pStxSaveSector->Side            = Side;
                   1807:                pStxSaveSector->BitPosition     = pStxSector->BitPosition;
                   1808:                pStxSaveSector->ID_Track        = pStxSector->ID_Track;
                   1809:                pStxSaveSector->ID_Head         = pStxSector->ID_Head;
                   1810:                pStxSaveSector->ID_Sector       = pStxSector->ID_Sector;
                   1811:                pStxSaveSector->ID_Size         = pStxSector->ID_Size;
                   1812:                pStxSaveSector->ID_CRC          = pStxSector->ID_CRC;
                   1813: 
                   1814:                pStxSaveSector->SectorSize      = SectorSize;
                   1815:                pStxSaveSector->pData           = (Uint8 *) pNewBuf;
                   1816: 
                   1817:                pStxSaveSector->StructIsUsed    = 1;
                   1818:        }
                   1819: 
                   1820:        pSector_WriteData = STX_SaveStruct[ Drive ].pSaveSectorsStruct[ pStxSector->SaveSectorIndex ].pData;
                   1821: 
                   1822:        /* Get the sector's data (ignore timings) */
                   1823:        for ( i=0 ; i<SectorSize ; i++ )
                   1824:                pSector_WriteData[ i ] = FDC_Buffer_Read_Byte_pos ( i );
                   1825: 
                   1826: //fprintf ( stderr , "write drive=%d track=%d side=%d sector=%d size=%d index=%d\n", Drive, Track, Side, Sector, SectorSize , pStxSector->SaveSectorIndex );
                   1827: //Str_Dump_Hex_Ascii ( (char *) pSector_WriteData, SectorSize, 16, "" , stderr );
                   1828: 
                   1829:        /* Warn that 'write sector' data will be lost or saved (if zipped or not) */
                   1830:        if ( STX_State.ImageBuffer[ Drive ]->WarnedWriteSector == false )
                   1831:        {
                   1832:                if ( File_DoesFileExtensionMatch ( EmulationDrives[ Drive ].sFileName , ".zip" ) )
                   1833:                        Log_AlertDlg ( LOG_INFO , "WARNING : can't save changes made with 'write sector' to an STX disk inside a zip file" );
                   1834:                else
                   1835:                        Log_AlertDlg ( LOG_INFO , "Changes made with 'write sector' to an STX disk will be saved into an additional .wd1772 file" );
                   1836:                STX_State.ImageBuffer[ Drive ]->WarnedWriteSector = true;
                   1837:        }
                   1838: 
                   1839: 
                   1840:        /* No error */
                   1841:        EmulationDrives[Drive].bContentsChanged = true;
                   1842:        return 0;
                   1843: }
                   1844: 
                   1845: 
                   1846: /*-----------------------------------------------------------------------*/
                   1847: /**
                   1848:  * Read an address field from a floppy image in STX format (used in type III command)
                   1849:  * We return the address field NextSectorStruct_Nbr, whose value was set
                   1850:  * by the latest call to FDC_NextSectorID_FdcCycles_STX
                   1851:  * Each byte of the ID field is added to the FDC buffer with a default timing
                   1852:  * (32 microsec)
                   1853:  * Return 0 if OK, or a CRC error
                   1854:  */
1.1.1.2   root     1855: Uint8  FDC_ReadAddress_STX ( Uint8 Drive , Uint8 Track , Uint8 Sector , Uint8 Side )
1.1       root     1856: {
                   1857:        STX_SECTOR_STRUCT       *pStxSector;
                   1858: 
                   1859:        pStxSector = STX_FindSector ( Drive , Track , Side , STX_State.NextSectorStruct_Nbr );
                   1860:        if ( pStxSector == NULL )
                   1861:        {
                   1862:                fprintf ( stderr , "FDC_ReadAddress_STX drive=%d track=%d side=%d sector=%d returns null !\n" ,
                   1863:                                Drive , Track , Side , STX_State.NextSectorStruct_Nbr );
                   1864:                return STX_SECTOR_FLAG_RNF;                             /* Should not happen if FDC_NextSectorID_FdcCycles_STX succeeded before */
                   1865:        }
                   1866: 
                   1867:        FDC_Buffer_Add ( pStxSector->ID_Track );
                   1868:        FDC_Buffer_Add ( pStxSector->ID_Head );
                   1869:        FDC_Buffer_Add ( pStxSector->ID_Sector );
                   1870:        FDC_Buffer_Add ( pStxSector->ID_Size );
                   1871:        FDC_Buffer_Add ( pStxSector->ID_CRC >> 8 );
                   1872:        FDC_Buffer_Add ( pStxSector->ID_CRC & 0xff );
                   1873: 
                   1874:        /* If RNF is set and CRC error is set, then this ID field has a CRC error */
                   1875:        if ( ( pStxSector->FDC_Status & STX_SECTOR_FLAG_RNF ) && ( pStxSector->FDC_Status & STX_SECTOR_FLAG_CRC ) )
                   1876:                return STX_SECTOR_FLAG_CRC;
                   1877: 
                   1878:        return 0;                                                       /* No error */
                   1879: }
                   1880: 
                   1881: 
                   1882: /*-----------------------------------------------------------------------*/
                   1883: /**
                   1884:  * Read a track from a floppy image in STX format (used in type III command)
                   1885:  * This function is called after an index pulse was encountered, and it will
                   1886:  * always succeeds and fill the track buffer.
                   1887:  * If the Track/Side infos exist in the STX image, then the corresponding
                   1888:  * bytes from the track's image are returned.
                   1889:  * If these Track/Side infos don't exist, we return some random bytes
                   1890:  * (empty / not formatted track).
                   1891:  * If the Track/Side infos exist but there's no track's image, then we build
                   1892:  * a standard track by using the available sectors and standard GAP values.
                   1893:  * Return 0 if OK
                   1894:  */
1.1.1.2   root     1895: Uint8  FDC_ReadTrack_STX ( Uint8 Drive , Uint8 Track , Uint8 Side )
1.1       root     1896: {
                   1897:        STX_TRACK_STRUCT        *pStxTrack;
                   1898:        STX_SECTOR_STRUCT       *pStxSector;
                   1899:        int                     i;
                   1900:        Uint16                  Timing;
                   1901:        Uint32                  Track_ReadTime;
                   1902:        double                  Total_cur;                              /* To compute closest integer timings for each byte */
                   1903:        double                  Total_prev;
                   1904:        int                     TrackSize;
                   1905:        int                     Sector;
                   1906:        int                     SectorSize;
                   1907:        Uint16                  CRC;
                   1908:        Uint8                   *pData;
                   1909:        Uint8                   Byte;
                   1910:        
                   1911:        if ( STX_State.ImageBuffer[ Drive ] == NULL )
                   1912:        {
                   1913:                fprintf ( stderr , "FDC_ReadTrack_STX drive=%d track=%d side=%d, no image buffer !\n" , Drive , Track , Side );
                   1914:                return STX_SECTOR_FLAG_RNF;                             /* Should not happen, just in case of a bug */
                   1915:        }
                   1916: 
                   1917:        pStxTrack = STX_FindTrack ( Drive , Track , Side );
                   1918:        if ( pStxTrack == NULL )                                        /* Track/Side don't exist in this STX image */
                   1919:        {
                   1920:                fprintf ( stderr , "fdc stx : track info not found for read track drive=%d track=%d side=%d, returning random bytes\n" , Drive , Track , Side );
                   1921:                for ( i=0 ; i<FDC_GetBytesPerTrack ( Drive ) ; i++ )
                   1922:                        FDC_Buffer_Add ( rand() & 0xff );               /* Fill the track buffer with random bytes */
                   1923:                return 0;
                   1924:        }
                   1925: 
                   1926:        /* If the Track block contains a complete dump of the track image, use it directly */
                   1927:        /* The timing for each byte is the average timing based on TrackImageSize */
                   1928:        if ( pStxTrack->pTrackImageData )
                   1929:        {
                   1930:                Track_ReadTime = 8000000 / 5;                           /* 300 RPM, gives 5 RPS and 1600000 cycles per revolution at 8 MHz */
                   1931:                Total_prev = 0;
                   1932:                for ( i=0 ; i<pStxTrack->TrackImageSize ; i++ )
                   1933:                {
                   1934:                        Total_cur = ( (double)Track_ReadTime * ( i+1 ) ) / pStxTrack->TrackImageSize;
                   1935:                        Timing = rint ( Total_cur - Total_prev );
                   1936:                        Total_prev += Timing;
                   1937:                        /* Add each byte to the buffer, Timing should be a number of FDC cycles at 8 MHz */
                   1938:                        FDC_Buffer_Add_Timing ( pStxTrack->pTrackImageData[ i ] , Timing );
                   1939:                }
                   1940:        }
                   1941: 
                   1942:        /* If the track block doesn't contain a dump of the track image, we must build a track */
                   1943:        /* using the sector blocks and some standard GAP values */
                   1944:        /* [NP] NOTE : we build a track of pStxTrack->MFMSize bytes, as this seems to always be != 0 */
                   1945:        /* even for empty / not formatted track */
                   1946:        /* [NP] NOTE : instead of using standard GAP values, we could compute GAP based on pStxSector->BitPosition */
                   1947:        /* but this seems unnecessary, as a track image would certainly be present if precise GAP values */
                   1948:        /* were required */
                   1949:        else
                   1950:        {
                   1951:                TrackSize = pStxTrack->MFMSize;
                   1952:                if ( ( pStxTrack->Flags & STX_TRACK_FLAG_SECTOR_BLOCK ) == 0 )
                   1953:                        TrackSize /= 8;                                 /* When the track contains only sector data, MFMSize is in bits */
                   1954: 
                   1955:                /* If there's no image for this track, and no sector as well, then track is empty / not formatted */
                   1956:                if ( pStxTrack->SectorsCount == 0 )
                   1957:                {
                   1958:                        fprintf ( stderr , "fdc stx : no track image and no sector for read track drive=%d track=%d side=%d, building an unformatted track\n" , Drive , Track , Side );
                   1959:                        for ( i=0 ; i<TrackSize ; i++ )
                   1960:                                FDC_Buffer_Add ( rand() & 0xff );       /* Fill the track buffer with random bytes */
                   1961:                        return 0;
                   1962:                }
                   1963: 
                   1964:                /* Use the available sectors and add some default GAPs to build the track */
                   1965:                fprintf ( stderr , "fdc stx : no track image for read track drive=%d track=%d side=%d, building a standard track\n" , Drive , Track , Side );
                   1966: 
                   1967:                for ( i=0 ; i<FDC_TRACK_LAYOUT_STANDARD_GAP1 ; i++ )    /* GAP1 */
                   1968:                        FDC_Buffer_Add ( 0x4e );
                   1969: 
                   1970:                for ( Sector=0 ; Sector < pStxTrack->SectorsCount ; Sector++ )
                   1971:                {
                   1972:                        pStxSector = &(pStxTrack->pSectorsStruct[ Sector ]);
                   1973:                        SectorSize = pStxSector->SectorSize;
                   1974: 
                   1975:                        /* Check that the data+GAPs for this sector will not be above track's length */
                   1976:                        /* (in case we build a track with a high / non standard number of sectors) */
                   1977:                        if ( FDC_Buffer_Get_Size () + SectorSize + FDC_TRACK_LAYOUT_STANDARD_GAP2 + 10 + FDC_TRACK_LAYOUT_STANDARD_GAP3a
                   1978:                                + FDC_TRACK_LAYOUT_STANDARD_GAP3b + 4 + 2 + FDC_TRACK_LAYOUT_STANDARD_GAP4 >= TrackSize )
                   1979:                        {
                   1980:                                fprintf ( stderr , "fdc stx : no track image for read track drive=%d track=%d side=%d, too many data sector=%d\n" , Drive , Track , Side , Sector );
                   1981:                                break;                                  /* Exit the loop and fill the rest of the track */
                   1982:                        }
                   1983: 
                   1984:                        for ( i=0 ; i<FDC_TRACK_LAYOUT_STANDARD_GAP2 ; i++ )    /* GAP2 */
                   1985:                                FDC_Buffer_Add ( 0x00 );
                   1986: 
                   1987:                        /* Add the ID field for the sector */
                   1988:                        for ( i=0 ; i<3 ; i++ )
                   1989:                                FDC_Buffer_Add ( 0xa1 );                /* SYNC (write $F5) */
                   1990:                        FDC_Buffer_Add ( 0xfe );                        /* Index Address Mark */
                   1991:                        FDC_Buffer_Add ( pStxSector->ID_Track );
                   1992:                        FDC_Buffer_Add ( pStxSector->ID_Head );
                   1993:                        FDC_Buffer_Add ( pStxSector->ID_Sector );
                   1994:                        FDC_Buffer_Add ( pStxSector->ID_Size );
                   1995:                        FDC_Buffer_Add ( pStxSector->ID_CRC >> 8 );
                   1996:                        FDC_Buffer_Add ( pStxSector->ID_CRC & 0xff );
                   1997: 
                   1998:                        for ( i=0 ; i<FDC_TRACK_LAYOUT_STANDARD_GAP3a ; i++ )   /* GAP3a */
                   1999:                                FDC_Buffer_Add ( 0x4e );
                   2000:                        for ( i=0 ; i<FDC_TRACK_LAYOUT_STANDARD_GAP3b ; i++ )   /* GAP3b */
                   2001:                                FDC_Buffer_Add ( 0x00 );
                   2002: 
                   2003:                        /* Add the data for the sector + build the CRC */
                   2004:                        crc16_reset ( &CRC );
                   2005:                        for ( i=0 ; i<3 ; i++ )
                   2006:                        {
                   2007:                                FDC_Buffer_Add ( 0xa1 );                /* SYNC (write $F5) */
                   2008:                                crc16_add_byte ( &CRC , 0xa1 );
                   2009:                        }
                   2010: 
                   2011:                        FDC_Buffer_Add ( 0xfb );                        /* Data Address Mark */
                   2012:                        crc16_add_byte ( &CRC , 0xfb );
                   2013: 
                   2014:                        /* [NP] NOTE : when building the sector, we assume there's no specific timing or fuzzy bytes */
                   2015:                        /* If it was not the case, there would certainly be a real track image (and STX format doesn't */
                   2016:                        /* support fuzzy bytes or specific timing for a track image anyway) */
                   2017:                        /* If the sector was changed by a 'write sector' command, we use the data from pSaveSectorsStruct */
                   2018:                        if ( pStxSector->SaveSectorIndex < 0 )          /* Use original data from the STX */
                   2019:                                pData = pStxSector->pData;
                   2020:                        else                                            /* Use data from the 'write sector' */
                   2021:                                pData = STX_SaveStruct[ Drive ].pSaveSectorsStruct[ pStxSector->SaveSectorIndex ].pData;
                   2022: 
                   2023:                        for ( i=0 ; i<SectorSize ; i++ )
                   2024:                        {
                   2025:                                Byte = pData[ i ];
                   2026:                                FDC_Buffer_Add ( Byte );
                   2027:                                crc16_add_byte ( &CRC , Byte );
                   2028:                        }
                   2029: 
                   2030:                        FDC_Buffer_Add ( CRC >> 8 );                    /* CRC1 (write $F7) */
                   2031:                        FDC_Buffer_Add ( CRC & 0xff );                  /* CRC2 */
                   2032: 
                   2033:                        for ( i=0 ; i<FDC_TRACK_LAYOUT_STANDARD_GAP4 ; i++ )    /* GAP4 */
                   2034:                                FDC_Buffer_Add ( 0x4e );
                   2035:                }
                   2036: 
                   2037:                while ( FDC_Buffer_Get_Size () < TrackSize )            /* Complete the track buffer */
                   2038:                      FDC_Buffer_Add ( 0x4e );                          /* GAP5 */
                   2039:        }
                   2040: 
                   2041:        return 0;                                                       /* No error */
                   2042: }
                   2043: 
                   2044: 
                   2045: /*-----------------------------------------------------------------------*/
                   2046: /**
                   2047:  * Write a track to a floppy image in STX format (used in type III command)
                   2048:  *
                   2049:  * STX format doesn't support write command. For each 'write track' we
                   2050:  * store the track data in a dedicated buffer STX_SaveStruct[].pSaveTracksStruct.
                   2051:  * When the track is read later, we return the data from STX_SaveStruct[].pSaveTracksStruct
                   2052:  * instead of returning the data from the original STX file.
                   2053:  *
                   2054:  * NOTE : data will saved in memory snapshot, as well as in an additional
                   2055:  * file with the extension .wd1772.
                   2056:  *
                   2057:  * Return 0 if track was written without error, or LOST_DATA if an error occurred
                   2058:  */
1.1.1.2   root     2059: Uint8  FDC_WriteTrack_STX ( Uint8 Drive , Uint8 Track , Uint8 Side , int TrackSize )
1.1       root     2060: {
                   2061:        STX_TRACK_STRUCT        *pStxTrack;
                   2062:        int                     i;
                   2063:        Uint8                   *pTrack_DataWrite;
                   2064:        void                    *pNewBuf;
                   2065:        STX_SAVE_TRACK_STRUCT   *pStxSaveTrack;
                   2066:        int                     Sector;
                   2067: 
                   2068:        pStxTrack = STX_FindTrack ( Drive , Track , Side );
                   2069:        if ( pStxTrack == NULL )
                   2070:        {
                   2071:                fprintf ( stderr , "FDC_WriteTrack_STX drive=%d track=%d side=%d returns null !\n" ,
                   2072:                                Drive , Track , Side );
                   2073:                return STX_SECTOR_FLAG_LOST_DATA;
                   2074:        }
                   2075: 
                   2076:        /* Check if this track was already changed by a 'write track' command */
                   2077:        /* If so, we use the same structure. Else we alloc a new structure for this track */
                   2078:        if ( pStxTrack->SaveTrackIndex < 0 )
                   2079:        {
                   2080: //fprintf ( stderr , "realloc\n" );
                   2081:                /* Increase save buffer by 1 */
                   2082:                pNewBuf = realloc ( STX_SaveStruct[ Drive ].pSaveTracksStruct ,
                   2083:                                    ( STX_SaveStruct[ Drive ].SaveTracksCount + 1 ) * sizeof ( STX_SAVE_TRACK_STRUCT ) );
                   2084:                if ( pNewBuf == NULL )
                   2085:                {
                   2086:                        fprintf ( stderr , "FDC_WriteTrack_STX drive=%d track=%d side=%d realloc error !\n" ,
                   2087:                                        Drive , Track , Side );
                   2088:                        return STX_SECTOR_FLAG_LOST_DATA;
                   2089:                }
                   2090: 
                   2091:                /* Save the new buffer values */
                   2092:                STX_SaveStruct[ Drive ].pSaveTracksStruct = (STX_SAVE_TRACK_STRUCT *) pNewBuf;;
                   2093:                STX_SaveStruct[ Drive ].SaveTracksCount++;
                   2094: 
                   2095:                pStxTrack->SaveTrackIndex = STX_SaveStruct[ Drive ].SaveTracksCount - 1;
                   2096:        }
                   2097: 
                   2098:        /* Use the same structure : free previous DataWrite buffer */
                   2099:        else
                   2100:        {
                   2101:                free ( STX_SaveStruct[ Drive ].pSaveTracksStruct[ pStxTrack->SaveTrackIndex ].pDataWrite );
                   2102:                STX_SaveStruct[ Drive ].pSaveTracksStruct[ pStxTrack->SaveTrackIndex ].pDataWrite = NULL;
                   2103:                /* TODO : also free pDataRead */
                   2104:        }
                   2105:                
                   2106:        /* Create the new DataWrite buffer in pSaveTracksStruct */
                   2107:        pNewBuf = malloc ( TrackSize );
                   2108:        if ( pNewBuf == NULL )
                   2109:        {
                   2110:                fprintf ( stderr , "FDC_WriteTrack_STX drive=%d track=%d side=%d malloc error !\n" ,
                   2111:                                Drive , Track , Side );
                   2112:                return STX_SECTOR_FLAG_LOST_DATA;
                   2113:        }
                   2114: 
                   2115:        /* Fill the new SaveTrackStruct */
                   2116:        pStxSaveTrack = &STX_SaveStruct[ Drive ].pSaveTracksStruct[ pStxTrack->SaveTrackIndex ];
                   2117: 
                   2118:        pStxSaveTrack->Track = Track;
                   2119:        pStxSaveTrack->Side = Side;
                   2120: 
                   2121:        pStxSaveTrack->TrackSizeWrite = TrackSize;
                   2122:        pStxSaveTrack->pDataWrite = (Uint8 *) pNewBuf;
                   2123: 
                   2124: 
                   2125:        /* Get the track's data (ignore timings) */
                   2126:        pTrack_DataWrite = STX_SaveStruct[ Drive ].pSaveTracksStruct[ pStxTrack->SaveTrackIndex ].pDataWrite;
                   2127: 
                   2128:        for ( i=0 ; i<pStxSaveTrack->TrackSizeWrite ; i++ )
                   2129:                pTrack_DataWrite[ i ] = FDC_Buffer_Read_Byte_pos ( i );
                   2130: 
                   2131: //fprintf ( stderr , "write drive=%d track=%d side=%d size=%d index=%d\n", Drive, Track, Side, pStxSaveTrack->TrackSizeWrite , pStxTrack->SaveTrackIndex );
                   2132: //Str_Dump_Hex_Ascii ( (char *) pTrack_DataWrite, pStxSaveTrack->TrackSizeWrite, 16, "" , stderr );
                   2133: 
                   2134:        // TODO : convert pDataWrite into pDataRead
                   2135:        pStxSaveTrack->TrackSizeRead = 0;       /* TODO : compute interpreted track */
                   2136:        pStxSaveTrack->pDataRead = NULL;        /* TODO : compute interpreted track */
                   2137: 
                   2138:        
                   2139:        /* If some sectors were already saved for that track, we must remove them */
                   2140:        /* as the 'write track' takes precedence over the previous 'write sector' */
                   2141:        for ( Sector=0 ; Sector < pStxTrack->SectorsCount ; Sector++ )
                   2142:        {
                   2143:                if ( pStxTrack->pSectorsStruct[ Sector ].SaveSectorIndex >= 0 )
                   2144:                {
                   2145:                        STX_FreeSaveSectorsStruct ( STX_SaveStruct[ Drive ].pSaveSectorsStruct ,
                   2146:                                        pStxTrack->pSectorsStruct[ Sector ].SaveSectorIndex );
                   2147:                        pStxTrack->pSectorsStruct[ Sector ].SaveSectorIndex = -1;
                   2148:                }
                   2149:        }
                   2150: 
                   2151: 
                   2152:        /* Warn that 'write track' data will be lost or saved (if zipped or not) */
                   2153:        if ( STX_State.ImageBuffer[ Drive ]->WarnedWriteTrack == false )
                   2154:        {
                   2155:                if ( File_DoesFileExtensionMatch ( EmulationDrives[ Drive ].sFileName , ".zip" ) )
                   2156:                        Log_AlertDlg ( LOG_INFO , "WARNING : can't save changes made with 'write track' to an STX disk inside a zip file" );
                   2157:                else
                   2158:                        Log_AlertDlg ( LOG_INFO , "Changes made with 'write track' to an STX disk will be saved into an additional .wd1772 file" );
                   2159:                STX_State.ImageBuffer[ Drive ]->WarnedWriteTrack = true;
                   2160:        }
                   2161: 
                   2162: 
                   2163:        /* No error */
                   2164:        EmulationDrives[Drive].bContentsChanged = true;
                   2165:        return 0;
                   2166: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.