/** * Restore 'snapshot' of memory/chips/emulation variables */ void MemorySnapShot_Restore(const char *pszFileName, bool bConfirm) { /* Set to 'restore' */ if (MemorySnapShot_OpenFile(pszFileName, false)) { Configuration_MemorySnapShot_Capture(false); /* Reset emulator to get things running */ IoMem_UnInit(); IoMem_Init(); Reset_Cold(); /* Capture each files details */ // STMemory_MemorySnapShot_Capture(false); CycInt_MemorySnapShot_Capture(false); Cycles_MemorySnapShot_Capture(false); M68000_MemorySnapShot_Capture(false); Video_MemorySnapShot_Capture(false); DebugUI_MemorySnapShot_Capture(pszFileName, false); // IoMem_MemorySnapShot_Capture(false); /* And close */ MemorySnapShot_CloseFile(); /* changes may affect also info shown in statusbar */ Statusbar_UpdateInfo(); } /* Did error? */ if (bCaptureError) Log_AlertDlg(LOG_ERROR, "Unable to restore memory state from file."); else if (bConfirm) Log_AlertDlg(LOG_INFO, "Memory state file restored."); }
/** * Save 'snapshot' of memory/chips/emulation variables */ void MemorySnapShot_Capture(const char *pszFileName, bool bConfirm) { /* Set to 'saving' */ if (MemorySnapShot_OpenFile(pszFileName, true)) { /* Capture each files details */ Configuration_MemorySnapShot_Capture(true); // STMemory_MemorySnapShot_Capture(true); CycInt_MemorySnapShot_Capture(true); Cycles_MemorySnapShot_Capture(true); M68000_MemorySnapShot_Capture(true); Video_MemorySnapShot_Capture(true); DebugUI_MemorySnapShot_Capture(pszFileName, true); // IoMem_MemorySnapShot_Capture(true); /* And close */ MemorySnapShot_CloseFile(); } else { /* just canceled? */ if (!bCaptureError) return; } /* Did error */ if (bCaptureError) Log_AlertDlg(LOG_ERROR, "Unable to save memory state to file."); else if (bConfirm) Log_AlertDlg(LOG_INFO, "Memory state file saved."); }
/** * Set given floppy drive image file name and handle * different image extensions. * Return corrected file name on success and NULL on failure. */ const char* Floppy_SetDiskFileName(int Drive, const char *pszFileName, const char *pszZipPath) { char *filename; int i; /* setting to empty or "none" ejects */ if (!*pszFileName || strcasecmp(pszFileName, "none") == 0) { return Floppy_SetDiskFileNameNone(Drive); } /* See if file exists, and if not, get/add correct extension */ if (!File_Exists(pszFileName)) filename = File_FindPossibleExtFileName(pszFileName, pszDiskImageNameExts); else filename = strdup(pszFileName); if (!filename) { Log_AlertDlg((const char *)LOG_INFO, "Image '%s' not found", pszFileName); return NULL; } #if 0 /* If we insert a disk into Drive A, should we try to put disk 2 into drive B? */ if (Drive == 0 && ConfigureParams.DiskImage.bAutoInsertDiskB) { /* Attempt to make up second filename, eg was 'auto_100a' to 'auto_100b' */ char *szDiskBFileName = Floppy_CreateDiskBFileName(filename); if (szDiskBFileName) { /* recurse with Drive B */ Floppy_SetDiskFileName(1, szDiskBFileName, pszZipPath); free(szDiskBFileName); } } #endif /* validity checks */ assert(Drive >= 0 && Drive < MAX_FLOPPYDRIVES); for (i = 0; i < MAX_FLOPPYDRIVES; i++) { if (i == Drive) continue; /* prevent inserting same image to multiple drives */ if (strcmp(filename, /*ConfigureParams.DiskImage.*/szDiskFileName[i]) == 0) { Log_AlertDlg((const char *)LOG_ERROR, "ERROR: Cannot insert same floppy to multiple drives!"); return NULL; } } /* do the changes */ if (pszZipPath) strcpy(szDiskZipPath[Drive], pszZipPath); else szDiskZipPath[Drive][0] = '\0'; strcpy(szDiskFileName[Drive], filename); free(filename); //File_MakeAbsoluteName(ConfigureParams.DiskImage.szDiskFileName[Drive]); return szDiskFileName[Drive]; }
/** * Open WAV output file and write header. */ bool WAVFormat_OpenFile(char *pszWavFileName) { Uint32 nSampleFreq, nBytesPerSec; bRecordingWav = false; nWavOutputBytes = 0; /* Set frequency (11Khz, 22Khz or 44Khz) */ nSampleFreq = ConfigureParams.Sound.nPlaybackFreq; /* multiply by 4 for 16 bit stereo */ nBytesPerSec = nSampleFreq * 4; /* Create our file */ WavFileHndl = fopen(pszWavFileName, "wb"); if (!WavFileHndl) { perror("WAVFormat_OpenFile"); Log_AlertDlg(LOG_ERROR, "WAV recording: Failed to open file!"); return false; } /* Patch sample frequency in header structure */ WavHeader[24] = (Uint8)nSampleFreq; WavHeader[25] = (Uint8)(nSampleFreq >> 8); WavHeader[26] = (Uint8)(nSampleFreq >> 16); WavHeader[27] = (Uint8)(nSampleFreq >> 24); /* Patch bytes per second in header structure */ WavHeader[28] = (Uint8)nBytesPerSec; WavHeader[29] = (Uint8)(nBytesPerSec >> 8); WavHeader[30] = (Uint8)(nBytesPerSec >> 16); WavHeader[31] = (Uint8)(nBytesPerSec >> 24); /* Write header to file */ if (fwrite(&WavHeader, sizeof(WavHeader), 1, WavFileHndl) == 1) { bRecordingWav = true; Log_AlertDlg(LOG_INFO, "WAV sound data recording has been started."); } else { perror("WAVFormat_OpenFile"); Log_AlertDlg(LOG_ERROR, "WAV recording: Failed to write header!"); } /* Ok, or failed? */ return bRecordingWav; }
/** * Pass byte from emulator to printer. Opens the printer file appending * if it isn't already open. Returns false if connection to "printer" * failed */ bool Printer_TransferByteTo(Uint8 Byte) { /* Do we want to output to a printer/file? */ if (!ConfigureParams.Printer.bEnablePrinting) return false; /* Failed if printing disabled */ /* Have we made a connection to our printer/file? */ if (!pPrinterHandle) { /* open printer file... */ pPrinterHandle = File_Open(ConfigureParams.Printer.szPrintToFileName, "a+"); if (!pPrinterHandle) { Log_AlertDlg(LOG_ERROR, "Printer output file open failed. Printing disabled."); ConfigureParams.Printer.bEnablePrinting = false; return false; } } if (fputc(Byte, pPrinterHandle) != Byte) { fprintf(stderr, "ERROR: Printer_TransferByteTo() writing failed!\n"); return false; } bUnflushed = true; return true; }
/** * Handle creation of a the "new blank disk image". * return true if disk created, false otherwise. */ static bool DlgNewDisk_CreateDisk(const char *path) { int nSectors, nSides; /* (potentially non-existing) filename? */ if (File_DirExists(path)) { Log_AlertDlg(LOG_ERROR, "ERROR: '%s' isn't a file!", path); return false; } /* Get number of sectors */ if (newdiskdlg[DLGNEWDISK_SECTORS36].state & SG_SELECTED) nSectors = 36; else if (newdiskdlg[DLGNEWDISK_SECTORS18].state & SG_SELECTED) nSectors = 18; else if (newdiskdlg[DLGNEWDISK_SECTORS11].state & SG_SELECTED) nSectors = 11; else if (newdiskdlg[DLGNEWDISK_SECTORS10].state & SG_SELECTED) nSectors = 10; else nSectors = 9; /* Get number of sides */ if (newdiskdlg[DLGNEWDISK_SIDES1].state & SG_SELECTED) nSides = 1; else nSides = 2; return CreateBlankImage_CreateFile(path, nTracks, nSectors, nSides, dlgLabel); }
/** * Save program setting to configuration file */ void Configuration_Save(void) { if (Configuration_SaveSection(sConfigFileName, configs_Log, "[Log]") < 0) { Log_AlertDlg(LOG_ERROR, "Error saving config file."); return; } Configuration_SaveSection(sConfigFileName, configs_ConfigDialog, "[ConfigDialog]"); Configuration_SaveSection(sConfigFileName, configs_Debugger, "[Debugger]"); Configuration_SaveSection(sConfigFileName, configs_Screen, "[Screen]"); Configuration_SaveSection(sConfigFileName, configs_Keyboard, "[Keyboard]"); Configuration_SaveSection(sConfigFileName, configs_ShortCutWithMod, "[ShortcutsWithModifiers]"); Configuration_SaveSection(sConfigFileName, configs_ShortCutWithoutMod, "[ShortcutsWithoutModifiers]"); Configuration_SaveSection(sConfigFileName, configs_Mouse, "[Mouse]"); Configuration_SaveSection(sConfigFileName, configs_Sound, "[Sound]"); Configuration_SaveSection(sConfigFileName, configs_Memory, "[Memory]"); Configuration_SaveSection(sConfigFileName, configs_Boot, "[Boot]"); Configuration_SaveSection(sConfigFileName, configs_SCSI, "[HardDisk]"); Configuration_SaveSection(sConfigFileName, configs_MO, "[MagnetoOptical]"); Configuration_SaveSection(sConfigFileName, configs_Floppy, "[Floppy]"); Configuration_SaveSection(sConfigFileName, configs_Ethernet, "[Ethernet]"); Configuration_SaveSection(sConfigFileName, configs_Rom, "[ROM]"); Configuration_SaveSection(sConfigFileName, configs_Printer, "[Printer]"); Configuration_SaveSection(sConfigFileName, configs_System, "[System]"); Configuration_SaveSection(sConfigFileName, configs_Dimension, "[Dimension]"); }
/** * Open/Create snapshot file, and set flag so 'MemorySnapShot_Store' knows * how to handle data. */ static bool MemorySnapShot_OpenFile(const char *pszFileName, bool bSave) { char VersionString[] = VERSION_STRING; /* Set error */ bCaptureError = false; /* after opening file, set bCaptureSave to indicate whether * 'MemorySnapShot_Store' should load from or save to a file */ if (bSave) { if (!File_QueryOverwrite(pszFileName)) return false; /* Save */ CaptureFile = MemorySnapShot_fopen(pszFileName, "wb"); if (!CaptureFile) { fprintf(stderr, "Failed to open save file '%s': %s\n", pszFileName, strerror(errno)); bCaptureError = true; return false; } bCaptureSave = true; /* Store version string */ MemorySnapShot_Store(VersionString, sizeof(VersionString)); } else { /* Restore */ CaptureFile = MemorySnapShot_fopen(pszFileName, "rb"); if (!CaptureFile) { fprintf(stderr, "Failed to open file '%s': %s\n", pszFileName, strerror(errno)); bCaptureError = true; return false; } bCaptureSave = false; /* Restore version string */ MemorySnapShot_Store(VersionString, sizeof(VersionString)); /* Does match current version? */ if (strcasecmp(VersionString, VERSION_STRING)) { /* No, inform user and error */ Log_AlertDlg(LOG_ERROR, "Unable to restore Hatari memory state. File\n" "is compatible only with Hatari version %s.", VersionString); bCaptureError = true; return false; } } /* All OK */ return true; }
/** * Save 'snapshot' of memory/chips/emulation variables */ void MemorySnapShot_Capture(const char *pszFileName, bool bConfirm) { /* Set to 'saving' */ if (MemorySnapShot_OpenFile(pszFileName, true)) { /* Capture each files details */ Configuration_MemorySnapShot_Capture(true); TOS_MemorySnapShot_Capture(true); STMemory_MemorySnapShot_Capture(true); FDC_MemorySnapShot_Capture(true); Floppy_MemorySnapShot_Capture(true); GemDOS_MemorySnapShot_Capture(true); ACIA_MemorySnapShot_Capture(true); IKBD_MemorySnapShot_Capture(true); CycInt_MemorySnapShot_Capture(true); Cycles_MemorySnapShot_Capture(true); M68000_MemorySnapShot_Capture(true); MFP_MemorySnapShot_Capture(true); PSG_MemorySnapShot_Capture(true); Sound_MemorySnapShot_Capture(true); Video_MemorySnapShot_Capture(true); Blitter_MemorySnapShot_Capture(true); DmaSnd_MemorySnapShot_Capture(true); Crossbar_MemorySnapShot_Capture(true); VIDEL_MemorySnapShot_Capture(true); DSP_MemorySnapShot_Capture(true); DebugUI_MemorySnapShot_Capture(pszFileName, true); IoMem_MemorySnapShot_Capture(true); /* And close */ MemorySnapShot_CloseFile(); } else { /* just canceled? */ if (!bCaptureError) return; } /* Did error */ if (bCaptureError) Log_AlertDlg(LOG_ERROR, "Unable to save memory state to file."); else if (bConfirm) Log_AlertDlg(LOG_INFO, "Memory state file saved."); }
/** * Start recording animation */ void ScreenSnapShot_BeginRecording(bool bCaptureChange) { /* Set in globals */ bGrabWhenChange = bCaptureChange; /* Start animation */ bRecordingAnimation = TRUE; /* And inform user */ Log_AlertDlg(LOG_INFO, "Screenshot recording started."); }
/** * Stop recording animation */ void ScreenSnapShot_EndRecording() { /* Were we recording? */ if (bRecordingAnimation) { /* Stop animation */ bRecordingAnimation = FALSE; /* And inform user */ Log_AlertDlg(LOG_INFO, "Screenshot recording stopped."); } }
/** * Insert previously set disk file image into floppy drive. * The WHOLE image is copied into Hatari drive buffers, and * uncompressed if necessary. * Return TRUE on success, false otherwise. */ bool Floppy_InsertDiskIntoDrive(int Drive) { long nImageBytes = 0; char *filename; /* Eject disk, if one is inserted (doesn't inform user) */ assert(Drive >= 0 && Drive < MAX_FLOPPYDRIVES); Floppy_EjectDiskFromDrive(Drive); filename = ConfigureParams.DiskImage.szDiskFileName[Drive]; if (!filename[0]) { return true; /* only do eject */ } if (!File_Exists(filename)) { Log_AlertDlg(LOG_INFO, "Image '%s' not found", filename); return false; } /* Check disk image type and read the file: */ if (MSA_FileNameIsMSA(filename, true)) EmulationDrives[Drive].pBuffer = MSA_ReadDisk(filename, &nImageBytes); else if (ST_FileNameIsST(filename, true)) EmulationDrives[Drive].pBuffer = ST_ReadDisk(filename, &nImageBytes); else if (DIM_FileNameIsDIM(filename, true)) EmulationDrives[Drive].pBuffer = DIM_ReadDisk(filename, &nImageBytes); else if (ZIP_FileNameIsZIP(filename)) { const char *zippath = ConfigureParams.DiskImage.szDiskZipPath[Drive]; EmulationDrives[Drive].pBuffer = ZIP_ReadDisk(filename, zippath, &nImageBytes); } if (EmulationDrives[Drive].pBuffer == NULL) { return false; } /* Store image filename (required for ejecting the disk later!) */ strcpy(EmulationDrives[Drive].sFileName, filename); /* Store size and set drive states */ EmulationDrives[Drive].nImageBytes = nImageBytes; EmulationDrives[Drive].bDiskInserted = true; EmulationDrives[Drive].bContentsChanged = false; EmulationDrives[Drive].bOKToSave = Floppy_IsBootSectorOK(Drive); Floppy_DriveTransitionSetState ( Drive , FLOPPY_DRIVE_TRANSITION_STATE_INSERT ); Log_Printf(LOG_INFO, "Inserted disk '%s' to drive %c:.", filename, 'A'+Drive); return true; }
/** * Load .IPF file into memory, set number of bytes loaded and return a pointer * to the buffer. */ Uint8 *IPF_ReadDisk(int Drive, const char *pszFileName, long *pImageSize, int *pImageType) { #ifndef HAVE_CAPSIMAGE Log_AlertDlg(LOG_ERROR, "This version of Hatari was not built with IPF support, this disk image can't be handled."); return NULL; #else Uint8 *pIPFFile; *pImageSize = 0; /* Just load directly a buffer, and set ImageSize accordingly */ pIPFFile = File_Read(pszFileName, pImageSize, NULL); if (!pIPFFile) { *pImageSize = 0; return NULL; } *pImageType = FLOPPY_IMAGE_TYPE_IPF; return pIPFFile; #endif }
/** * Initialise Printer */ void Printer_Init(void) { char *separator; Dprintf((stderr, "Printer_Init()\n")); /* disabled from config/command line? */ if (!ConfigureParams.Printer.szPrintToFileName[0]) return; /* printer name without path? */ separator = strrchr(ConfigureParams.Printer.szPrintToFileName, PATHSEP); if (!separator) return; *separator = '\0'; if (!File_DirExists(ConfigureParams.Printer.szPrintToFileName)) { Log_AlertDlg(LOG_ERROR, "Printer output file directory inaccessible. Printing disabled."); ConfigureParams.Printer.bEnablePrinting = false; } *separator = PATHSEP; Dprintf((stderr, "Filename for printing: %s \n", ConfigureParams.Printer.szPrintToFileName)); }
/** * Write sizes to WAV header, then close the WAV file. */ void WAVFormat_CloseFile(void) { if (bRecordingWav) { Uint32 nWavFileBytes; Uint32 nWavLEOutBytes; bRecordingWav = false; /* Update headers with sizes */ nWavFileBytes = SDL_SwapLE32((12+24+8+nWavOutputBytes)-8); /* File length, less 8 bytes for 'RIFF' and length */ fseek(WavFileHndl, 4, SEEK_SET); /* 'Total Length Of Package' element */ /* Write total length of package in 'RIFF' chunk */ if (fwrite(&nWavFileBytes, sizeof(Uint32), 1, WavFileHndl) != 1) { perror("WAVFormat_CloseFile"); fclose(WavFileHndl); WavFileHndl = NULL; return; } fseek(WavFileHndl, 12+24+4, SEEK_SET); /* 'Length' element */ nWavLEOutBytes = SDL_SwapLE32(nWavOutputBytes); /* Write length of data in 'DATA' chunk */ if (fwrite(&nWavLEOutBytes, sizeof(Uint32), 1, WavFileHndl) != 1) { perror("WAVFormat_CloseFile"); } /* Close file */ fclose(WavFileHndl); WavFileHndl = NULL; /* And inform user */ Log_AlertDlg(LOG_INFO, "WAV Sound data recording has been stopped."); } }
/** * Test disk image for valid boot-sector. * It has been noticed that some disks, eg blank images made by the MakeDisk * utility or PaCifiST emulator fill in the boot-sector with incorrect information. * Such images cannot be read correctly using a real ST, and also Hatari. * To try and prevent data loss, we check for this error and flag the drive so * the image will not be saved back to the file. */ static bool Floppy_IsBootSectorOK(int Drive) { Uint8 *pDiskBuffer; /* Does our drive have a disk in? */ if (EmulationDrives[Drive].bDiskInserted) { pDiskBuffer = EmulationDrives[Drive].pBuffer; /* Check SPC (byte 13) for !=0 value. If is '0', invalid image and Hatari * won't be-able to read (nor will a real ST)! */ if (pDiskBuffer[13] != 0) { return true; /* Disk sector is OK! */ } else { Log_AlertDlg(LOG_WARN, "Disk in drive %c: maybe suffers from the Pacifist/Makedisk bug.\n" "If it does not work, please repair the disk first!\n", 'A' + Drive); } } return false; /* Bad sector */ }
/** * Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type) * We must take care of whether Hatari was compiled with IPF support of not * when saving/restoring snapshots to avoid incompatibilies. */ void IPF_MemorySnapShot_Capture(bool bSave) { int StructSize; int Drive; if ( bSave ) /* Saving snapshot */ { StructSize = sizeof ( IPF_State ); /* 0 if HAVE_CAPSIMAGE is not defined */ MemorySnapShot_Store(&StructSize, sizeof(StructSize)); fprintf ( stderr , "ipf save %d\n" , StructSize ); if ( StructSize > 0 ) MemorySnapShot_Store(&IPF_State, sizeof(IPF_State)); } else /* Restoring snapshot */ { MemorySnapShot_Store(&StructSize, sizeof(StructSize)); fprintf ( stderr , "ipf load %d\n" , StructSize ); if ( ( StructSize == 0 ) && ( sizeof ( IPF_State ) > 0 ) ) { Log_AlertDlg(LOG_ERROR, "This memory snapshot doesn't include IPF data but this version of Hatari was built with IPF support"); return; /* Continue restoring the rest of the memory snapshot */ } else if ( ( StructSize > 0 ) && ( sizeof ( IPF_State ) == 0 ) ) { Log_AlertDlg(LOG_ERROR, "This memory snapshot includes IPF data but this version of Hatari was not built with IPF support"); MemorySnapShot_Skip( StructSize ); /* Ignore the IPF data */ return; /* Continue restoring the rest of the memory snapshot */ } else if ( ( StructSize > 0 ) && ( StructSize != sizeof ( IPF_State ) ) ) { Log_AlertDlg(LOG_ERROR, "This memory snapshot includes IPF data different from the ones handled in this version of Hatari"); MemorySnapShot_Skip( StructSize ); /* Ignore the IPF data */ return; /* Continue restoring the rest of the memory snapshot */ } if ( StructSize > 0 ) { MemorySnapShot_Store(&IPF_State, sizeof(IPF_State)); #ifdef HAVE_CAPSIMAGE /* For IPF structures, we need to update some pointers in Fdc/Drive/CapsImage */ /* drive : PUBYTE trackbuf, PUDWORD timebuf */ /* fdc : PCAPSDRIVE driveprc, PCAPSDRIVE drive, CAPSFDCHOOK callback functions */ CAPSFdcInvalidateTrack ( &IPF_State.Fdc , 0 ); /* Invalidate buffered track data for drive 0 */ CAPSFdcInvalidateTrack ( &IPF_State.Fdc , 1 ); /* Invalidate buffered track data for drive 1 */ IPF_State.Fdc.drive = IPF_State.Drive; /* Connect drives array to the FDC */ if ( IPF_State.Fdc.driveprc != NULL ) /* Recompute active drive's pointer */ IPF_State.Fdc.driveprc = IPF_State.Fdc.drive + IPF_State.Fdc.driveact; /* Set callback functions */ IPF_State.Fdc.cbirq = IPF_CallBack_Irq; IPF_State.Fdc.cbdrq = IPF_CallBack_Drq; IPF_State.Fdc.cbtrk = IPF_CallBack_Trk; #endif /* Call IPF_Insert to recompute IPF_State.CapsImage[ Drive ] */ for ( Drive=0 ; Drive < MAX_FLOPPYDRIVES ; Drive++ ) if ( EmulationDrives[Drive].ImageType == FLOPPY_IMAGE_TYPE_IPF ) if ( IPF_Insert ( Drive , EmulationDrives[Drive].pBuffer , EmulationDrives[Drive].nImageBytes ) == false ) { Log_AlertDlg(LOG_ERROR, "Error restoring IPF image %s in drive %d" , EmulationDrives[Drive].sFileName , Drive ); return; } fprintf ( stderr , "ipf load ok\n" ); } } }
/* * Init the ressources to handle the IPF image inserted into a drive (0=A: 1=B:) */ bool IPF_Insert ( int Drive , Uint8 *pImageBuffer , long ImageSize ) { #ifndef HAVE_CAPSIMAGE return false; #else CapsLong ImageId; CapsLong ImageType; ImageId = CAPSAddImage(); if ( ImageId < 0 ) { fprintf ( stderr , "IPF : error CAPSAddImage\n" ); return false; } #if CAPS_LIB_REL_REV >= 501 ImageType = CAPSGetImageTypeMemory ( pImageBuffer , ImageSize ); if ( ImageType == citError ) { fprintf ( stderr , "IPF : error CAPSGetImageTypeMemory\n" ); return false; } else if ( ImageType == citUnknown ) { fprintf ( stderr , "IPF : unknown image type\n" ); return false; } fprintf ( stderr , "IPF : IPF_Insert drive=%d buf=%p size=%ld imageid=%d type=" , Drive , pImageBuffer , ImageSize , ImageId ); switch ( ImageType ) { case citIPF: fprintf ( stderr , "IPF\n" ); break; case citCTRaw: fprintf ( stderr , "CT RAW\n" ); break; case citKFStream: fprintf ( stderr , "KF STREAM\n" ) ; break; case citDraft: fprintf ( stderr , "DRAFT\n" ) ; break; default : fprintf ( stderr , "NOT SUPPORTED\n" ); return false; } #endif if ( CAPSLockImageMemory ( ImageId , pImageBuffer , (CapsULong)ImageSize , DI_LOCK_MEMREF ) == imgeOk ) { struct CapsImageInfo cii; int i; /* Print some debug infos */ if ( CAPSGetImageInfo ( &cii , ImageId ) == imgeOk ) { printf("Type: %d\n", (int)cii.type); printf("Release: %d\n", (int)cii.release); printf("Revision: %d\n", (int)cii.revision); printf("Min Cylinder: %d\n", (int)cii.mincylinder); printf("Max Cylinder: %d\n", (int)cii.maxcylinder); printf("Min Head: %d\n", (int)cii.minhead); printf("Max Head: %d\n", (int)cii.maxhead); printf("Creation Date: %04d/%02d/%02d %02d:%02d:%02d.%03d\n", (int)cii.crdt.year, (int)cii.crdt.month, (int)cii.crdt.day, (int)cii.crdt.hour, (int)cii.crdt.min, (int)cii.crdt.sec, (int)cii.crdt.tick); printf("Platforms:"); for (i = 0; i < CAPS_MAXPLATFORM; i++) if (cii.platform[i] != ciipNA) printf ( " %s" , CAPSGetPlatformName(cii.platform[i]) ); printf("\n"); /* Some IPF disks are not correctly supported yet : display a warning */ if ( (int)cii.release == 3222 ) /* Sundog */ Log_AlertDlg ( LOG_INFO , "'Sundog' is not correctly supported yet, it requires write access." ); else if ( (int)cii.release == 3058 ) /* Lethal Xcess */ Log_AlertDlg ( LOG_INFO , "'Lethal Xcess' is not correctly supported yet, protection will fail" ); } } else { CAPSRemImage ( ImageId ) ; return false; } if ( CAPSLoadImage ( ImageId , DI_LOCK_DENALT | DI_LOCK_DENVAR | DI_LOCK_UPDATEFD ) != imgeOk ) { fprintf ( stderr , "IPF : error CAPSLoadImage\n" ); CAPSUnlockImage ( ImageId ); CAPSRemImage ( ImageId ) ; return false; } IPF_State.CapsImage[ Drive ] = ImageId; IPF_State.Drive[ Drive ].diskattr |= CAPSDRIVE_DA_IN; /* Disk inserted, keep the value for "write protect" */ CAPSFdcInvalidateTrack ( &IPF_State.Fdc , Drive ); /* Invalidate previous buffered track data for drive, if any */ IPF_State.Rev_Track[ Drive ] = -1; /* Invalidate previous track/side to handle revolution's count */ IPF_State.Rev_Side[ Drive ] = -1; return true; #endif }
/** * Load disk image from a .ZIP archive into memory, set the number * of bytes loaded into pImageSize and return the data or NULL on error. */ Uint8 *ZIP_ReadDisk(int Drive, const char *pszFileName, const char *pszZipPath, long *pImageSize, int *pImageType) { uLong ImageSize=0; unzFile uf=NULL; Uint8 *buf; char *path; Uint8 *pDiskBuffer = NULL; *pImageSize = 0; *pImageType = FLOPPY_IMAGE_TYPE_NONE; uf = unzOpen(pszFileName); if (uf == NULL) { Log_Printf(LOG_ERROR, "Cannot open %s\n", pszFileName); return NULL; } if (pszZipPath == NULL || pszZipPath[0] == 0) { path = ZIP_FirstFile(pszFileName, pszDiskNameExts); if (path == NULL) { Log_Printf(LOG_ERROR, "Cannot open %s\n", pszFileName); unzClose(uf); return NULL; } } else { path = malloc(ZIP_PATH_MAX); if (path == NULL) { perror("ZIP_ReadDisk"); unzClose(uf); return NULL; } strncpy(path, pszZipPath, ZIP_PATH_MAX); path[ZIP_PATH_MAX-1] = '\0'; } ImageSize = ZIP_CheckImageFile(uf, path, ZIP_PATH_MAX, pImageType); if (ImageSize <= 0) { unzClose(uf); free(path); return NULL; } /* extract to buf */ buf = ZIP_ExtractFile(uf, path, ImageSize); unzCloseCurrentFile(uf); unzClose(uf); free(path); path = NULL; if (buf == NULL) { return NULL; /* failed extraction, return error */ } switch(*pImageType) { case FLOPPY_IMAGE_TYPE_IPF: #ifndef HAVE_CAPSIMAGE Log_AlertDlg(LOG_ERROR, "This version of Hatari was not built with IPF support, this disk image can't be handled."); return NULL; #else /* return buffer */ pDiskBuffer = buf; break; #endif case FLOPPY_IMAGE_TYPE_STX: /* return buffer */ pDiskBuffer = buf; break; case FLOPPY_IMAGE_TYPE_MSA: /* uncompress the MSA file */ pDiskBuffer = MSA_UnCompress(buf, (long *)&ImageSize, ImageSize); free(buf); buf = NULL; break; case FLOPPY_IMAGE_TYPE_DIM: /* Skip DIM header */ ImageSize -= 32; memmove(buf, buf+32, ImageSize); /* return buffer */ pDiskBuffer = buf; break; case FLOPPY_IMAGE_TYPE_ST: /* ST image => return buffer directly */ pDiskBuffer = buf; break; } if (pDiskBuffer) { *pImageSize = ImageSize; } return pDiskBuffer; }