|
|
1.1 root 1: /*
1.1.1.5 root 2: Hatari - floppy.c
1.1 root 3:
1.1.1.19 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1.1.5 root 6:
1.1.1.12 root 7: This is where we read/write sectors to/from the disk image buffers.
8: NOTE: these buffers are in memory so we only need to write routines for
9: the .ST format. When the buffer is to be saved (ie eject disk) we save
10: it back to the original file in the correct format (.ST or .MSA).
1.1.1.5 root 11:
12: There are some important notes about image accessing - as we use TOS and the
1.1.1.9 root 13: FDC to access the disk the boot-sector MUST be valid. Sometimes this is NOT
14: the case! In these situations we must guess at the disk format. Eg, some disk
1.1.1.5 root 15: images have a a boot sector which states single-sided, but the images have
16: been created as double-sided. As sides are interleaved we need to read the
17: image as if it was double-sided. Also note that 'NumBytesPerSector' is ALWAYS
18: 512 bytes, even if the boot-sector states otherwise.
1.1.1.4 root 19: Also note that old versions of the MAKEDISK utility do not set the correct
20: boot sector structure for a real ST (and also Hatari) to read it correctly.
21: (PaCifiST will, however, read/write to these images as it does not perform
22: FDC access as on a real ST)
1.1 root 23: */
1.1.1.13 root 24: const char Floppy_fileid[] = "Hatari floppy.c : " __DATE__ " " __TIME__;
1.1.1.8 root 25:
26: #include <sys/stat.h>
1.1.1.12 root 27: #include <assert.h>
1.1.1.4 root 28: #include <SDL_endian.h>
29:
1.1 root 30: #include "main.h"
1.1.1.6 root 31: #include "configuration.h"
1.1 root 32: #include "file.h"
33: #include "floppy.h"
1.1.1.9 root 34: #include "gemdos.h"
35: #include "hdc.h"
1.1.1.8 root 36: #include "log.h"
1.1 root 37: #include "memorySnapShot.h"
38: #include "st.h"
1.1.1.20 root 39: #include "msa.h"
40: #include "dim.h"
41: #include "floppy_ipf.h"
42: #include "floppy_stx.h"
1.1.1.6 root 43: #include "zip.h"
1.1.1.18 root 44: #include "screen.h"
1.1.1.24! root 45: #include "str.h"
1.1.1.18 root 46: #include "video.h"
1.1.1.20 root 47: #include "fdc.h"
1.1 root 48:
1.1.1.10 root 49:
1.1.1.12 root 50: /* Emulation drive details, eg FileName, Inserted, Changed etc... */
51: EMULATION_DRIVE EmulationDrives[MAX_FLOPPYDRIVES];
52: /* Drive A is the default */
53: int nBootDrive = 0;
1.1 root 54:
1.1.1.18 root 55:
1.1.1.9 root 56: /* Possible disk image file extensions to scan for */
1.1.1.10 root 57: static const char * const pszDiskImageNameExts[] =
1.1.1.5 root 58: {
1.1.1.10 root 59: ".msa",
60: ".st",
61: ".dim",
1.1.1.20 root 62: ".ipf",
63: ".raw",
64: ".ctr",
65: ".stx",
1.1.1.10 root 66: NULL
1.1 root 67: };
68:
69:
1.1.1.13 root 70: /* local functions */
1.1.1.18 root 71: static bool Floppy_EjectBothDrives(void);
72: static void Floppy_DriveTransitionSetState ( int Drive , int State );
1.1.1.13 root 73:
74:
1.1.1.2 root 75: /*-----------------------------------------------------------------------*/
1.1.1.11 root 76: /**
77: * Initialize emulation floppy drives
78: */
1.1 root 79: void Floppy_Init(void)
80: {
1.1.1.10 root 81: int i;
1.1 root 82:
1.1.1.10 root 83: /* Clear drive structures */
1.1.1.12 root 84: for (i = 0; i < MAX_FLOPPYDRIVES; i++)
1.1.1.10 root 85: {
1.1.1.12 root 86: /* Clear structs and if floppies available, insert them */
1.1.1.10 root 87: memset(&EmulationDrives[i], 0, sizeof(EMULATION_DRIVE));
1.1.1.12 root 88: if (strlen(ConfigureParams.DiskImage.szDiskFileName[i]) > 0)
89: Floppy_InsertDiskIntoDrive(i);
1.1.1.10 root 90: }
1.1 root 91: }
92:
1.1.1.2 root 93:
94: /*-----------------------------------------------------------------------*/
1.1.1.11 root 95: /**
96: * UnInitialize drives
97: */
1.1 root 98: void Floppy_UnInit(void)
99: {
1.1.1.10 root 100: Floppy_EjectBothDrives();
1.1 root 101: }
102:
1.1.1.2 root 103:
104: /*-----------------------------------------------------------------------*/
1.1.1.11 root 105: /**
1.1.1.18 root 106: * Called on Warm/Cold Reset
107: */
108: void Floppy_Reset(void)
109: {
110: int i;
111:
112: /* Cancel any pending disk change transitions */
113: for (i = 0; i < MAX_FLOPPYDRIVES; i++)
114: {
115: EmulationDrives[i].TransitionState1 = 0;
116: EmulationDrives[i].TransitionState2 = 0;
117: }
118: }
119:
120:
121: /*-----------------------------------------------------------------------*/
122: /**
1.1.1.11 root 123: * Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
124: */
1.1.1.12 root 125: void Floppy_MemorySnapShot_Capture(bool bSave)
1.1 root 126: {
1.1.1.10 root 127: int i;
1.1 root 128:
1.1.1.10 root 129: /* If restoring then eject old drives first! */
130: if (!bSave)
131: Floppy_EjectBothDrives();
132:
133: /* Save/Restore details */
1.1.1.12 root 134: for (i = 0; i < MAX_FLOPPYDRIVES; i++)
1.1.1.10 root 135: {
1.1.1.20 root 136: MemorySnapShot_Store(&EmulationDrives[i].ImageType, sizeof(EmulationDrives[i].ImageType));
1.1.1.10 root 137: MemorySnapShot_Store(&EmulationDrives[i].bDiskInserted, sizeof(EmulationDrives[i].bDiskInserted));
138: MemorySnapShot_Store(&EmulationDrives[i].nImageBytes, sizeof(EmulationDrives[i].nImageBytes));
139: if (!bSave && EmulationDrives[i].bDiskInserted)
140: {
141: EmulationDrives[i].pBuffer = malloc(EmulationDrives[i].nImageBytes);
142: if (!EmulationDrives[i].pBuffer)
143: perror("Floppy_MemorySnapShot_Capture");
144: }
145: if (EmulationDrives[i].pBuffer)
146: MemorySnapShot_Store(EmulationDrives[i].pBuffer, EmulationDrives[i].nImageBytes);
1.1.1.13 root 147: MemorySnapShot_Store(EmulationDrives[i].sFileName, sizeof(EmulationDrives[i].sFileName));
1.1.1.10 root 148: MemorySnapShot_Store(&EmulationDrives[i].bContentsChanged,sizeof(EmulationDrives[i].bContentsChanged));
149: MemorySnapShot_Store(&EmulationDrives[i].bOKToSave,sizeof(EmulationDrives[i].bOKToSave));
1.1.1.18 root 150: MemorySnapShot_Store(&EmulationDrives[i].TransitionState1,sizeof(EmulationDrives[i].TransitionState1));
151: MemorySnapShot_Store(&EmulationDrives[i].TransitionState1_VBL,sizeof(EmulationDrives[i].TransitionState1_VBL));
152: MemorySnapShot_Store(&EmulationDrives[i].TransitionState2,sizeof(EmulationDrives[i].TransitionState2));
153: MemorySnapShot_Store(&EmulationDrives[i].TransitionState2_VBL,sizeof(EmulationDrives[i].TransitionState2_VBL));
1.1.1.20 root 154:
155: /* Because Floppy_EjectBothDrives() was called above before restoring (which cleared */
156: /* FDC_DRIVES[].DiskInserted that was restored just before), we must call FDC_InsertFloppy */
157: /* for each restored drive with an inserted disk to set FDC_DRIVES[].DiskInserted=true */
158: if ( !bSave && ( EmulationDrives[i].bDiskInserted ) )
159: FDC_InsertFloppy ( i );
1.1.1.10 root 160: }
1.1 root 161: }
162:
1.1.1.2 root 163:
164: /*-----------------------------------------------------------------------*/
1.1.1.11 root 165: /**
166: * Find which device to boot from (hard drive or floppy).
167: */
1.1 root 168: void Floppy_GetBootDrive(void)
169: {
1.1.1.15 root 170: /* Default to drive A: */
171: nBootDrive = 0;
172:
173: /* Boot only from hard drive if user wants this */
174: if (!ConfigureParams.HardDisk.bBootFromHardDisk)
175: return;
176:
1.1.1.24! root 177: if (ACSI_EMU_ON || ConfigureParams.Ide[0].bUseDevice)
1.1.1.15 root 178: {
1.1.1.10 root 179: nBootDrive = 2; /* Drive C */
1.1.1.15 root 180: }
181: else if (GEMDOS_EMU_ON)
182: {
183: int i;
184: for (i = 0; i < MAX_HARDDRIVES; i++)
185: {
186: if (emudrives[i])
187: {
1.1.1.16 root 188: nBootDrive = emudrives[i]->drive_number;
1.1.1.15 root 189: break;
190: }
191: }
192: }
1.1 root 193: }
194:
1.1.1.2 root 195:
196: /*-----------------------------------------------------------------------*/
1.1.1.11 root 197: /**
198: * Test if disk image is write protected. Write protection can be configured
199: * in the GUI. When set to "automatic", we check the file permissions of the
200: * floppy disk image to decide.
201: */
1.1.1.12 root 202: bool Floppy_IsWriteProtected(int Drive)
1.1.1.8 root 203: {
1.1.1.10 root 204: if (ConfigureParams.DiskImage.nWriteProtection == WRITEPROT_OFF)
205: {
1.1.1.14 root 206: return false;
1.1.1.10 root 207: }
208: else if (ConfigureParams.DiskImage.nWriteProtection == WRITEPROT_ON)
209: {
1.1.1.14 root 210: return true;
1.1.1.10 root 211: }
212: else
213: {
214: struct stat FloppyStat;
215: /* Check whether disk is writable */
1.1.1.13 root 216: if (stat(EmulationDrives[Drive].sFileName, &FloppyStat) == 0
1.1.1.12 root 217: && (FloppyStat.st_mode & S_IWUSR))
1.1.1.14 root 218: return false;
1.1.1.10 root 219: else
1.1.1.14 root 220: return true;
1.1.1.10 root 221: }
1.1.1.8 root 222: }
223:
224:
225: /*-----------------------------------------------------------------------*/
1.1.1.11 root 226: /**
1.1.1.22 root 227: * Test disk image for executable boot sector.
228: * The boot sector is executable if the 16 bit sum of its 256 words
229: * gives the value 0x1234.
230: */
231: static bool Floppy_IsBootSectorExecutable(int Drive)
232: {
233: Uint8 *pDiskBuffer;
234: int sum , i;
235:
236: if (EmulationDrives[Drive].bDiskInserted)
237: {
238: pDiskBuffer = EmulationDrives[Drive].pBuffer;
239:
240: sum = 0;
241: for ( i=0 ; i<256 ; i++ )
242: {
243: sum += ( ( *pDiskBuffer << 8 ) + *(pDiskBuffer+1) );
244: pDiskBuffer += 2;
245: }
246:
247: if ( ( sum & 0xffff ) == FLOPPY_BOOT_SECTOR_EXE_SUM ) /* 0x1234 */
248: return true;
249: }
250:
251: return false; /* Not executable */
252: }
253:
254:
255: /*-----------------------------------------------------------------------*/
256: /**
1.1.1.11 root 257: * Test disk image for valid boot-sector.
258: * It has been noticed that some disks, eg blank images made by the MakeDisk
259: * utility or PaCifiST emulator fill in the boot-sector with incorrect information.
260: * Such images cannot be read correctly using a real ST, and also Hatari.
261: * To try and prevent data loss, we check for this error and flag the drive so
262: * the image will not be saved back to the file.
263: */
1.1.1.12 root 264: static bool Floppy_IsBootSectorOK(int Drive)
1.1 root 265: {
1.1.1.10 root 266: Uint8 *pDiskBuffer;
1.1 root 267:
1.1.1.10 root 268: /* Does our drive have a disk in? */
269: if (EmulationDrives[Drive].bDiskInserted)
270: {
271: pDiskBuffer = EmulationDrives[Drive].pBuffer;
272:
273: /* Check SPC (byte 13) for !=0 value. If is '0', invalid image and Hatari
274: * won't be-able to read (nor will a real ST)! */
1.1.1.22 root 275: if ( (pDiskBuffer[13] != 0) || ( Floppy_IsBootSectorExecutable ( Drive ) == true ) )
1.1.1.10 root 276: {
1.1.1.14 root 277: return true; /* Disk sector is OK! */
1.1.1.10 root 278: }
279: else
280: {
281: Log_AlertDlg(LOG_WARN, "Disk in drive %c: maybe suffers from the Pacifist/Makedisk bug.\n"
282: "If it does not work, please repair the disk first!\n", 'A' + Drive);
283: }
284: }
1.1 root 285:
1.1.1.14 root 286: return false; /* Bad sector */
1.1 root 287: }
288:
1.1.1.2 root 289:
290: /*-----------------------------------------------------------------------*/
1.1.1.11 root 291: /**
292: * Try to create disk B filename, eg 'auto_100a' becomes 'auto_100b'
293: * Return new filename if think we should try, otherwise NULL
1.1.1.12 root 294: *
295: * TODO: doesn't work with images in ZIP archives
1.1.1.11 root 296: */
297: static char* Floppy_CreateDiskBFileName(const char *pSrcFileName)
1.1 root 298: {
1.1.1.10 root 299: char *szDir, *szName, *szExt;
1.1.1.12 root 300:
1.1.1.10 root 301: /* Allocate temporary memory for strings: */
302: szDir = malloc(3 * FILENAME_MAX);
303: if (!szDir)
304: {
305: perror("Floppy_CreateDiskBFileName");
1.1.1.21 root 306: return NULL;
1.1.1.10 root 307: }
308: szName = szDir + FILENAME_MAX;
309: szExt = szName + FILENAME_MAX;
310:
311: /* So, first split name into parts */
1.1.1.11 root 312: File_SplitPath(pSrcFileName, szDir, szName, szExt);
1.1.1.10 root 313:
314: /* All OK? */
315: if (strlen(szName) > 0)
316: {
1.1.1.12 root 317: char *last = &(szName[strlen(szName)-1]);
318: /* Now, did filename end with an 'A' or 'a' */
319: if (*last == 'A' || *last == 'a')
1.1.1.10 root 320: {
1.1.1.11 root 321: char *szFull;
1.1.1.10 root 322: /* Change 'A' to a 'B' */
1.1.1.12 root 323: *last += 1;
1.1.1.10 root 324: /* And re-build name into destination */
1.1.1.11 root 325: szFull = File_MakePath(szDir, szName, szExt);
326: if (szFull)
327: {
328: /* Does file exist? */
329: if (File_Exists(szFull))
330: {
331: free(szDir);
332: return szFull;
333: }
334: free(szFull);
335: }
1.1.1.10 root 336: }
337: }
338: free(szDir);
1.1.1.11 root 339: return NULL;
1.1 root 340: }
341:
1.1.1.2 root 342:
343: /*-----------------------------------------------------------------------*/
1.1.1.11 root 344: /**
1.1.1.12 root 345: * Set floppy image to be ejected
346: */
347: const char* Floppy_SetDiskFileNameNone(int Drive)
348: {
349: assert(Drive >= 0 && Drive < MAX_FLOPPYDRIVES);
350: ConfigureParams.DiskImage.szDiskFileName[Drive][0] = '\0';
351: return ConfigureParams.DiskImage.szDiskFileName[Drive];
1.1.1.6 root 352: }
353:
1.1.1.12 root 354: /*-----------------------------------------------------------------------*/
355: /**
356: * Set given floppy drive image file name and handle
357: * different image extensions.
358: * Return corrected file name on success and NULL on failure.
1.1.1.11 root 359: */
1.1.1.12 root 360: const char* Floppy_SetDiskFileName(int Drive, const char *pszFileName, const char *pszZipPath)
1.1.1.6 root 361: {
1.1.1.11 root 362: char *filename;
1.1.1.16 root 363: int i;
1.1 root 364:
1.1.1.12 root 365: /* setting to empty or "none" ejects */
366: if (!*pszFileName || strcasecmp(pszFileName, "none") == 0)
367: {
368: return Floppy_SetDiskFileNameNone(Drive);
369: }
1.1.1.11 root 370: /* See if file exists, and if not, get/add correct extension */
1.1.1.12 root 371: if (!File_Exists(pszFileName))
1.1.1.11 root 372: filename = File_FindPossibleExtFileName(pszFileName, pszDiskImageNameExts);
373: else
374: filename = strdup(pszFileName);
1.1.1.12 root 375: if (!filename)
376: {
377: Log_AlertDlg(LOG_INFO, "Image '%s' not found", pszFileName);
378: return NULL;
379: }
380:
381: /* If we insert a disk into Drive A, should we try to put disk 2 into drive B? */
382: if (Drive == 0 && ConfigureParams.DiskImage.bAutoInsertDiskB)
383: {
384: /* Attempt to make up second filename, eg was 'auto_100a' to 'auto_100b' */
385: char *szDiskBFileName = Floppy_CreateDiskBFileName(filename);
386: if (szDiskBFileName)
387: {
388: /* recurse with Drive B */
389: Floppy_SetDiskFileName(1, szDiskBFileName, pszZipPath);
390: free(szDiskBFileName);
391: }
392: }
393:
1.1.1.16 root 394: /* validity checks */
1.1.1.12 root 395: assert(Drive >= 0 && Drive < MAX_FLOPPYDRIVES);
1.1.1.16 root 396: for (i = 0; i < MAX_FLOPPYDRIVES; i++)
397: {
398: if (i == Drive)
399: continue;
400: /* prevent inserting same image to multiple drives */
401: if (strcmp(filename, ConfigureParams.DiskImage.szDiskFileName[i]) == 0)
402: {
403: Log_AlertDlg(LOG_ERROR, "ERROR: Cannot insert same floppy to multiple drives!");
1.1.1.21 root 404: free(filename);
1.1.1.16 root 405: return NULL;
406: }
407: }
408:
409: /* do the changes */
1.1.1.12 root 410: if (pszZipPath)
411: strcpy(ConfigureParams.DiskImage.szDiskZipPath[Drive], pszZipPath);
412: else
413: ConfigureParams.DiskImage.szDiskZipPath[Drive][0] = '\0';
1.1.1.24! root 414: strlcpy(ConfigureParams.DiskImage.szDiskFileName[Drive], filename,
! 415: sizeof(ConfigureParams.DiskImage.szDiskFileName[Drive]));
1.1.1.12 root 416: free(filename);
417: //File_MakeAbsoluteName(ConfigureParams.DiskImage.szDiskFileName[Drive]);
418: return ConfigureParams.DiskImage.szDiskFileName[Drive];
419: }
420:
421: /*-----------------------------------------------------------------------*/
422: /**
1.1.1.18 root 423: * Update the drive when a disk is inserted or ejected. Depending on the state,
424: * we change the Write Protect bit for the drive (the TOS and other programs
425: * monitor this bit to detect that a disk was changed in the drive ; see fdc.c)
426: * The floppy drive transition can be a single action ("eject" or "insert"), or
427: * two actions ("eject then insert" or "insert then eject").
428: * First action is stored in State1 ; State2 store the second (or last) action.
429: * In case the user eject/insert several disks before returning to emulation,
430: * State1 will contain the first action, and State2 the latest action (intermediate
431: * actions are ignored, as they wouldn't be seen while the emulation is paused).
1.1.1.22 root 432: * Each action will take FLOPPY_DRIVE_TRANSITION_DELAY_VBL VBLs to execute,
1.1.1.18 root 433: * see fdc.c for details.
434: */
435: static void Floppy_DriveTransitionSetState ( int Drive , int State )
436: {
437: /* First, update State1 and State2 depending on the current VBL number */
438: /* (we discard the return value as we don't want to update FDC.STR now) */
439: Floppy_DriveTransitionUpdateState ( Drive );
440:
441: /* If State1 is not defined yet, we set it */
442: if ( EmulationDrives[Drive].TransitionState1 == 0 )
443: {
444: EmulationDrives[Drive].TransitionState1 = State;
445: EmulationDrives[Drive].TransitionState1_VBL = nVBLs;
446: /* Cancel State2 in case we start a new transition before State2 was over */
447: EmulationDrives[Drive].TransitionState2 = 0;
448: }
449:
450: /* State1 is already set, so we set State2 */
451: else
452: {
453: /* If State2 == State1, ignore it (eg : two inserts in a row) */
454: if ( EmulationDrives[Drive].TransitionState1 == State )
455: EmulationDrives[Drive].TransitionState2 = 0;
456: else
457: {
458: /* Set State2 just after State1 ends */
459: EmulationDrives[Drive].TransitionState2 = State;
1.1.1.22 root 460: EmulationDrives[Drive].TransitionState2_VBL = EmulationDrives[Drive].TransitionState1_VBL + FLOPPY_DRIVE_TRANSITION_DELAY_VBL;
1.1.1.18 root 461: }
462: }
463: //fprintf ( stderr , "drive transition state1 %d %d state2 %d %d\n" ,
464: // EmulationDrives[Drive].TransitionState1 , EmulationDrives[Drive].TransitionState1_VBL,
465: // EmulationDrives[Drive].TransitionState2 , EmulationDrives[Drive].TransitionState2_VBL );
466: }
467:
468:
469: /*-----------------------------------------------------------------------*/
470: /**
471: * When a disk is inserted or ejected, each transition has 2 phases that
472: * lasts FLOPPY_DRIVE_TRANSITION_DELAY_VBL VBLs. This function checks if
473: * we're during one of these transition phases and tells if the Write
474: * Protect signal should be overwritten.
475: * Returns 0 if there's no change, 1 if WPRT should be forced to 1 and
476: * -1 if WPRT should be forced to 0 (see fdc.c for details).
477: */
478: int Floppy_DriveTransitionUpdateState ( int Drive )
479: {
480: int Force = 0;
481:
482: if ( EmulationDrives[Drive].TransitionState1 != 0 )
483: {
1.1.1.22 root 484: if ( nVBLs >= EmulationDrives[Drive].TransitionState1_VBL + FLOPPY_DRIVE_TRANSITION_DELAY_VBL )
1.1.1.18 root 485: EmulationDrives[Drive].TransitionState1 = 0; /* State1's delay elapsed */
486: else
487: {
488: if ( EmulationDrives[Drive].TransitionState1 == FLOPPY_DRIVE_TRANSITION_STATE_INSERT )
1.1.1.22 root 489: Force = 0; /* Insert : keep WPRT */
1.1.1.18 root 490: else
1.1.1.22 root 491: Force = 1; /* Eject : set WPRT */
1.1.1.18 root 492: }
493: }
494:
495: if ( ( EmulationDrives[Drive].TransitionState2 != 0 )
496: && ( nVBLs >= EmulationDrives[Drive].TransitionState2_VBL ) )
497: {
1.1.1.22 root 498: if ( nVBLs >= EmulationDrives[Drive].TransitionState2_VBL + FLOPPY_DRIVE_TRANSITION_DELAY_VBL )
1.1.1.18 root 499: EmulationDrives[Drive].TransitionState2 = 0; /* State2's delay elapsed */
500: else
501: {
502: if ( EmulationDrives[Drive].TransitionState2 == FLOPPY_DRIVE_TRANSITION_STATE_INSERT )
1.1.1.22 root 503: Force = 0; /* Insert : keep WPRT */
1.1.1.18 root 504: else
1.1.1.22 root 505: Force = 1; /* Eject : set WPRT */
1.1.1.18 root 506: }
507: }
508:
509:
510: return Force;
511: }
512:
513:
514: /*-----------------------------------------------------------------------*/
515: /**
1.1.1.12 root 516: * Insert previously set disk file image into floppy drive.
517: * The WHOLE image is copied into Hatari drive buffers, and
518: * uncompressed if necessary.
519: * Return TRUE on success, false otherwise.
520: */
521: bool Floppy_InsertDiskIntoDrive(int Drive)
522: {
1.1.1.20 root 523: long nImageBytes = 0;
524: char *filename;
525: int ImageType = FLOPPY_IMAGE_TYPE_NONE;
1.1.1.12 root 526:
527: /* Eject disk, if one is inserted (doesn't inform user) */
528: assert(Drive >= 0 && Drive < MAX_FLOPPYDRIVES);
529: Floppy_EjectDiskFromDrive(Drive);
530:
531: filename = ConfigureParams.DiskImage.szDiskFileName[Drive];
532: if (!filename[0])
533: {
1.1.1.14 root 534: return true; /* only do eject */
1.1.1.12 root 535: }
536: if (!File_Exists(filename))
537: {
538: Log_AlertDlg(LOG_INFO, "Image '%s' not found", filename);
1.1.1.14 root 539: return false;
1.1.1.12 root 540: }
541:
1.1.1.10 root 542: /* Check disk image type and read the file: */
1.1.1.14 root 543: if (MSA_FileNameIsMSA(filename, true))
1.1.1.20 root 544: EmulationDrives[Drive].pBuffer = MSA_ReadDisk(Drive, filename, &nImageBytes, &ImageType);
1.1.1.14 root 545: else if (ST_FileNameIsST(filename, true))
1.1.1.20 root 546: EmulationDrives[Drive].pBuffer = ST_ReadDisk(Drive, filename, &nImageBytes, &ImageType);
1.1.1.14 root 547: else if (DIM_FileNameIsDIM(filename, true))
1.1.1.20 root 548: EmulationDrives[Drive].pBuffer = DIM_ReadDisk(Drive, filename, &nImageBytes, &ImageType);
549: else if (IPF_FileNameIsIPF(filename, true))
550: EmulationDrives[Drive].pBuffer = IPF_ReadDisk(Drive, filename, &nImageBytes, &ImageType);
551: else if (STX_FileNameIsSTX(filename, true))
552: EmulationDrives[Drive].pBuffer = STX_ReadDisk(Drive, filename, &nImageBytes, &ImageType);
1.1.1.11 root 553: else if (ZIP_FileNameIsZIP(filename))
1.1.1.12 root 554: {
555: const char *zippath = ConfigureParams.DiskImage.szDiskZipPath[Drive];
1.1.1.20 root 556: EmulationDrives[Drive].pBuffer = ZIP_ReadDisk(Drive, filename, zippath, &nImageBytes, &ImageType);
1.1.1.12 root 557: }
1.1.1.11 root 558:
1.1.1.20 root 559: if ( (EmulationDrives[Drive].pBuffer == NULL) || ( ImageType == FLOPPY_IMAGE_TYPE_NONE ) )
1.1.1.11 root 560: {
1.1.1.24! root 561: Log_AlertDlg(LOG_INFO, "Image '%s' filename extension, or content unrecognized", filename);
1.1.1.14 root 562: return false;
1.1.1.11 root 563: }
1.1.1.13 root 564:
1.1.1.20 root 565: /* For IPF, call specific function to handle the inserted image */
566: if ( ImageType == FLOPPY_IMAGE_TYPE_IPF )
567: {
568: if ( IPF_Insert ( Drive , EmulationDrives[Drive].pBuffer , nImageBytes ) == false )
569: {
570: free ( EmulationDrives[Drive].pBuffer );
1.1.1.23 root 571: EmulationDrives[Drive].pBuffer = NULL;
1.1.1.24! root 572: Log_AlertDlg(LOG_INFO, "IPF image '%s' loading failed", filename);
1.1.1.20 root 573: return false;
574: }
575: }
576:
577: /* For STX, call specific function to handle the inserted image */
578: else if ( ImageType == FLOPPY_IMAGE_TYPE_STX )
579: {
580: if ( STX_Insert ( Drive , filename , EmulationDrives[Drive].pBuffer , nImageBytes ) == false )
581: {
582: free ( EmulationDrives[Drive].pBuffer );
1.1.1.23 root 583: EmulationDrives[Drive].pBuffer = NULL;
1.1.1.24! root 584: Log_AlertDlg(LOG_INFO, "STX image '%s' loading failed", filename);
1.1.1.20 root 585: return false;
586: }
587: }
588:
1.1.1.13 root 589: /* Store image filename (required for ejecting the disk later!) */
590: strcpy(EmulationDrives[Drive].sFileName, filename);
591:
592: /* Store size and set drive states */
1.1.1.20 root 593: EmulationDrives[Drive].ImageType = ImageType;
1.1.1.11 root 594: EmulationDrives[Drive].nImageBytes = nImageBytes;
1.1.1.14 root 595: EmulationDrives[Drive].bDiskInserted = true;
596: EmulationDrives[Drive].bContentsChanged = false;
1.1.1.20 root 597:
598: if ( ( ImageType == FLOPPY_IMAGE_TYPE_ST ) || ( ImageType == FLOPPY_IMAGE_TYPE_MSA )
599: || ( ImageType == FLOPPY_IMAGE_TYPE_DIM ) )
600: EmulationDrives[Drive].bOKToSave = Floppy_IsBootSectorOK(Drive);
601: else if ( ImageType == FLOPPY_IMAGE_TYPE_STX )
602: EmulationDrives[Drive].bOKToSave = true;
603: else if ( ImageType == FLOPPY_IMAGE_TYPE_IPF )
604: EmulationDrives[Drive].bOKToSave = false;
605: else
606: EmulationDrives[Drive].bOKToSave = false;
607:
1.1.1.18 root 608: Floppy_DriveTransitionSetState ( Drive , FLOPPY_DRIVE_TRANSITION_STATE_INSERT );
1.1.1.20 root 609: FDC_InsertFloppy ( Drive );
610:
1.1.1.12 root 611: Log_Printf(LOG_INFO, "Inserted disk '%s' to drive %c:.",
612: filename, 'A'+Drive);
1.1.1.14 root 613: return true;
1.1 root 614: }
615:
1.1.1.2 root 616:
617: /*-----------------------------------------------------------------------*/
1.1.1.11 root 618: /**
619: * Eject disk from floppy drive, save contents back to PCs hard-drive if
620: * they have been changed.
1.1.1.14 root 621: * Return true if there was something to eject.
1.1.1.11 root 622: */
1.1.1.12 root 623: bool Floppy_EjectDiskFromDrive(int Drive)
1.1 root 624: {
1.1.1.14 root 625: bool bEjected = false;
1.1.1.12 root 626:
1.1.1.10 root 627: /* Does our drive have a disk in? */
628: if (EmulationDrives[Drive].bDiskInserted)
629: {
1.1.1.16 root 630: bool bSaved = false;
1.1.1.13 root 631: char *psFileName = EmulationDrives[Drive].sFileName;
1.1.1.12 root 632:
1.1.1.10 root 633: /* OK, has contents changed? If so, need to save */
634: if (EmulationDrives[Drive].bContentsChanged)
635: {
636: /* Is OK to save image (if boot-sector is bad, don't allow a save) */
1.1.1.20 root 637: if (EmulationDrives[Drive].bOKToSave)
1.1.1.10 root 638: {
1.1.1.20 root 639: /* Save as .MSA, .ST, .DIM, .IPF or .STX image? */
1.1.1.14 root 640: if (MSA_FileNameIsMSA(psFileName, true))
1.1.1.20 root 641: bSaved = MSA_WriteDisk(Drive, psFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
1.1.1.14 root 642: else if (ST_FileNameIsST(psFileName, true))
1.1.1.20 root 643: bSaved = ST_WriteDisk(Drive, psFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
1.1.1.14 root 644: else if (DIM_FileNameIsDIM(psFileName, true))
1.1.1.20 root 645: bSaved = DIM_WriteDisk(Drive, psFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
646: else if (IPF_FileNameIsIPF(psFileName, true))
647: bSaved = IPF_WriteDisk(Drive, psFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
648: else if (STX_FileNameIsSTX(psFileName, true))
649: bSaved = STX_WriteDisk(Drive, psFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
1.1.1.12 root 650: else if (ZIP_FileNameIsZIP(psFileName))
1.1.1.20 root 651: bSaved = ZIP_WriteDisk(Drive, psFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
1.1.1.16 root 652: if (bSaved)
653: Log_Printf(LOG_INFO, "Updated the contents of floppy image '%s'.", psFileName);
654: else
655: Log_Printf(LOG_INFO, "Writing of this format failed or not supported, discarded the contents\n of floppy image '%s'.", psFileName);
656: } else
657: Log_Printf(LOG_INFO, "Writing not possible, discarded the contents of floppy image\n '%s'.", psFileName);
1.1.1.10 root 658: }
659:
660: /* Inform user that disk has been ejected! */
1.1.1.12 root 661: Log_Printf(LOG_INFO, "Floppy %c: has been removed from drive.",
662: 'A'+Drive);
663:
1.1.1.18 root 664: Floppy_DriveTransitionSetState ( Drive , FLOPPY_DRIVE_TRANSITION_STATE_EJECT );
1.1.1.20 root 665: FDC_EjectFloppy ( Drive );
1.1.1.14 root 666: bEjected = true;
1.1.1.10 root 667: }
668:
1.1.1.20 root 669: /* Free data used by this IPF image */
670: if ( EmulationDrives[Drive].ImageType == FLOPPY_IMAGE_TYPE_IPF )
671: IPF_Eject ( Drive );
672: /* Free data used by this STX image */
673: else if ( EmulationDrives[Drive].ImageType == FLOPPY_IMAGE_TYPE_STX )
674: STX_Eject ( Drive );
675:
676:
1.1.1.10 root 677: /* Drive is now empty */
678: if (EmulationDrives[Drive].pBuffer != NULL)
679: {
680: free(EmulationDrives[Drive].pBuffer);
681: EmulationDrives[Drive].pBuffer = NULL;
682: }
1.1.1.12 root 683:
1.1.1.13 root 684: EmulationDrives[Drive].sFileName[0] = '\0';
1.1.1.20 root 685: EmulationDrives[Drive].ImageType = FLOPPY_IMAGE_TYPE_NONE;
1.1.1.10 root 686: EmulationDrives[Drive].nImageBytes = 0;
1.1.1.14 root 687: EmulationDrives[Drive].bDiskInserted = false;
688: EmulationDrives[Drive].bContentsChanged = false;
689: EmulationDrives[Drive].bOKToSave = false;
1.1.1.12 root 690:
691: return bEjected;
1.1 root 692: }
693:
1.1.1.2 root 694:
695: /*-----------------------------------------------------------------------*/
1.1.1.11 root 696: /**
697: * Eject all disk image from floppy drives - call when quit.
1.1.1.14 root 698: * Return true if there was something to eject.
1.1.1.11 root 699: */
1.1.1.13 root 700: static bool Floppy_EjectBothDrives(void)
1.1 root 701: {
1.1.1.12 root 702: bool bEjectedA, bEjectedB;
703:
1.1.1.10 root 704: /* Eject disk images from drives 'A' and 'B' */
1.1.1.12 root 705: bEjectedA = Floppy_EjectDiskFromDrive(0);
706: bEjectedB = Floppy_EjectDiskFromDrive(1);
707:
708: return bEjectedA || bEjectedB;
1.1 root 709: }
710:
1.1.1.2 root 711:
712: /*-----------------------------------------------------------------------*/
1.1.1.11 root 713: /**
714: * Double-check information read from boot-sector as this is sometimes found to
1.1.1.17 root 715: * be incorrect. The .ST image file should be divisible by the sector size,
716: * the sectors per track. the number of tracks and the number of sides.
1.1.1.11 root 717: * NOTE - Pass information from boot-sector to this function (if we can't
718: * decide we leave it alone).
719: */
1.1.1.17 root 720: static void Floppy_DoubleCheckFormat(long nDiskSize, long nSectorsPerDisk, Uint16 *pnSides, Uint16 *pnSectorsPerTrack)
1.1 root 721: {
1.1.1.17 root 722: long TotalSectors;
723: int Sides_fixed;
724: int SectorsPerTrack_fixed;
1.1 root 725:
1.1.1.10 root 726: /* Now guess at number of sides */
1.1.1.17 root 727: if ( nDiskSize < (500*1024) ) /* If size >500k assume 2 sides */
728: Sides_fixed = 1;
1.1.1.10 root 729: else
1.1.1.17 root 730: Sides_fixed = 2;
1.1.1.10 root 731:
1.1.1.17 root 732: /* Number of 512 bytes sectors for this disk image */
733: TotalSectors = nDiskSize / 512;
734:
735: /* Check some common values */
736: if ( TotalSectors == 80*9*Sides_fixed ) { SectorsPerTrack_fixed = 9; }
737: else if ( TotalSectors == 81*9*Sides_fixed ) { SectorsPerTrack_fixed = 9; }
738: else if ( TotalSectors == 82*9*Sides_fixed ) { SectorsPerTrack_fixed = 9; }
1.1.1.18 root 739: else if ( TotalSectors == 83*9*Sides_fixed ) { SectorsPerTrack_fixed = 9; }
740: else if ( TotalSectors == 84*9*Sides_fixed ) { SectorsPerTrack_fixed = 9; }
1.1.1.17 root 741: else if ( TotalSectors == 80*10*Sides_fixed ) { SectorsPerTrack_fixed = 10; }
742: else if ( TotalSectors == 81*10*Sides_fixed ) { SectorsPerTrack_fixed = 10; }
743: else if ( TotalSectors == 82*10*Sides_fixed ) { SectorsPerTrack_fixed = 10; }
1.1.1.18 root 744: else if ( TotalSectors == 83*10*Sides_fixed ) { SectorsPerTrack_fixed = 10; }
745: else if ( TotalSectors == 84*10*Sides_fixed ) { SectorsPerTrack_fixed = 10; }
1.1.1.17 root 746: else if ( TotalSectors == 80*11*Sides_fixed ) { SectorsPerTrack_fixed = 11; }
747: else if ( TotalSectors == 81*11*Sides_fixed ) { SectorsPerTrack_fixed = 11; }
748: else if ( TotalSectors == 82*11*Sides_fixed ) { SectorsPerTrack_fixed = 11; }
1.1.1.18 root 749: else if ( TotalSectors == 83*11*Sides_fixed ) { SectorsPerTrack_fixed = 11; }
750: else if ( TotalSectors == 84*11*Sides_fixed ) { SectorsPerTrack_fixed = 11; }
1.1.1.17 root 751: else if ( TotalSectors == 80*12*Sides_fixed ) { SectorsPerTrack_fixed = 12; }
752: else if ( TotalSectors == 81*12*Sides_fixed ) { SectorsPerTrack_fixed = 12; }
753: else if ( TotalSectors == 82*12*Sides_fixed ) { SectorsPerTrack_fixed = 12; }
1.1.1.18 root 754: else if ( TotalSectors == 83*12*Sides_fixed ) { SectorsPerTrack_fixed = 12; }
755: else if ( TotalSectors == 84*12*Sides_fixed ) { SectorsPerTrack_fixed = 12; }
1.1.1.17 root 756:
757: /* unknown combination, assume boot sector is correct */
758: else { SectorsPerTrack_fixed = *pnSectorsPerTrack; }
759:
760: /* Valid new values if necessary */
761: if ( ( *pnSides != Sides_fixed ) || ( *pnSectorsPerTrack != SectorsPerTrack_fixed ) )
1.1.1.10 root 762: {
1.1.1.17 root 763: #if 0
764: int TracksPerDisk_fixed = TotalSectors / ( SectorsPerTrack_fixed * Sides_fixed );
765: Log_Printf(LOG_WARN, "Floppy_DoubleCheckFormat: boot sector doesn't match disk image's size :"
766: " total sectors %ld->%ld sides %d->%d sectors %d->%d tracks %d\n",
767: nSectorsPerDisk , TotalSectors , *pnSides , Sides_fixed , *pnSectorsPerTrack , SectorsPerTrack_fixed , TracksPerDisk_fixed );
768: #endif
769: *pnSides = Sides_fixed;
770: *pnSectorsPerTrack = SectorsPerTrack_fixed;
1.1.1.10 root 771: }
1.1 root 772: }
773:
1.1.1.2 root 774:
775: /*-----------------------------------------------------------------------*/
1.1.1.11 root 776: /**
777: * Find details of disk image. We need to do this via a function as sometimes the boot-block
778: * is not actually correct with the image - some demos/game disks have incorrect bytes in the
779: * boot sector and this attempts to find the correct values.
780: */
1.1.1.9 root 781: void Floppy_FindDiskDetails(const Uint8 *pBuffer, int nImageBytes,
1.1.1.12 root 782: Uint16 *pnSectorsPerTrack, Uint16 *pnSides)
1.1 root 783: {
1.1.1.17 root 784: Uint16 nSectorsPerTrack, nSides, nSectorsPerDisk;
1.1 root 785:
1.1.1.10 root 786: /* First do check to find number of sectors and bytes per sector */
787: nSectorsPerTrack = SDL_SwapLE16(*(const Uint16 *)(pBuffer+24)); /* SPT */
788: nSides = SDL_SwapLE16(*(const Uint16 *)(pBuffer+26)); /* SIDE */
1.1.1.17 root 789: nSectorsPerDisk = pBuffer[19] | (pBuffer[20] << 8); /* total sectors */
1.1.1.10 root 790:
791: /* If the number of sectors announced is incorrect, the boot-sector may
792: * contain incorrect information, eg the 'Eat.st' demo, or wrongly imaged
793: * single/double sided floppies... */
1.1.1.17 root 794: if (nSectorsPerDisk != nImageBytes/512)
795: Floppy_DoubleCheckFormat(nImageBytes, nSectorsPerDisk, &nSides, &nSectorsPerTrack);
1.1.1.10 root 796:
797: /* And set values */
798: if (pnSectorsPerTrack)
799: *pnSectorsPerTrack = nSectorsPerTrack;
800: if (pnSides)
801: *pnSides = nSides;
1.1 root 802: }
803:
1.1.1.2 root 804:
805: /*-----------------------------------------------------------------------*/
1.1.1.11 root 806: /**
807: * Read sectors from floppy disk image, return TRUE if all OK
808: * NOTE Pass -ve as Count to read whole track
809: */
1.1.1.20 root 810: bool Floppy_ReadSectors(int Drive, Uint8 **pBuffer, Uint16 Sector,
1.1.1.12 root 811: Uint16 Track, Uint16 Side, short Count,
1.1.1.18 root 812: int *pnSectorsPerTrack, int *pSectorSize)
1.1 root 813: {
1.1.1.10 root 814: Uint8 *pDiskBuffer;
1.1.1.12 root 815: Uint16 nSectorsPerTrack, nSides, nBytesPerTrack;
1.1.1.10 root 816: long Offset;
817: int nImageTracks;
818:
819: /* Do we have a disk in our drive? */
820: if (EmulationDrives[Drive].bDiskInserted)
821: {
822: /* Looks good */
823: pDiskBuffer = EmulationDrives[Drive].pBuffer;
824:
825: /* Find #sides and #sectors per track */
826: Floppy_FindDiskDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides);
827: nImageTracks = ((EmulationDrives[Drive].nImageBytes / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides;
828:
829: /* Need to read whole track? */
830: if (Count<0)
831: Count = nSectorsPerTrack;
832: /* Write back number of sector per track */
833: if (pnSectorsPerTrack)
834: *pnSectorsPerTrack = nSectorsPerTrack;
835:
1.1.1.18 root 836: if (pSectorSize)
837: *pSectorSize = NUMBYTESPERSECTOR; /* Size is 512 bytes for ST/MSA */
838:
1.1.1.10 root 839: /* Debug check as if we read over the end of a track we read into side 2! */
840: if (Count > nSectorsPerTrack)
841: {
842: Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: reading over single track\n");
843: }
844:
845: /* Check that the side number (0 or 1) does not exceed the amount of sides (1 or 2).
846: * (E.g. some games like Drakkhen or Bolo can load additional data from the
847: * second disk side, but they also work with single side floppy drives) */
848: if (Side >= nSides)
849: {
850: Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from side %i "
851: "of a disk image with %i sides!\n", Side+1, nSides);
1.1.1.14 root 852: return false;
1.1.1.10 root 853: }
854:
855: /* Check if track number is in range */
856: if (Track >= nImageTracks)
857: {
858: Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from track %i "
859: "of a disk image with only %i tracks!\n", Track, nImageTracks);
1.1.1.14 root 860: return false;
1.1.1.10 root 861: }
862:
863: /* Check if sector number is in range */
864: if (Sector <= 0 || Sector > nSectorsPerTrack)
865: {
866: Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from sector %i "
867: "of a disk image with %i sectors per track!\n", Sector, nSectorsPerTrack);
1.1.1.14 root 868: return false;
1.1.1.10 root 869: }
870:
871: /* Seek to sector */
872: nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack;
873: Offset = nBytesPerTrack*Side; /* First seek to side */
874: Offset += (nBytesPerTrack*nSides)*Track; /* Then seek to track */
875: Offset += (NUMBYTESPERSECTOR*(Sector-1)); /* And finally to sector */
1.1.1.6 root 876:
1.1.1.20 root 877: /* Return a pointer to the sectors data (usually 512 bytes per sector) */
878: *pBuffer = pDiskBuffer+Offset;
1.1 root 879:
1.1.1.14 root 880: return true;
1.1.1.10 root 881: }
1.1 root 882:
1.1.1.14 root 883: return false;
1.1 root 884: }
885:
1.1.1.2 root 886:
887: /*-----------------------------------------------------------------------*/
1.1.1.11 root 888: /**
889: * Write sectors from floppy disk image, return TRUE if all OK
890: * NOTE Pass -ve as Count to write whole track
891: */
1.1.1.12 root 892: bool Floppy_WriteSectors(int Drive, Uint8 *pBuffer, Uint16 Sector,
893: Uint16 Track, Uint16 Side, short Count,
1.1.1.18 root 894: int *pnSectorsPerTrack, int *pSectorSize)
1.1 root 895: {
1.1.1.10 root 896: Uint8 *pDiskBuffer;
1.1.1.12 root 897: Uint16 nSectorsPerTrack, nSides, nBytesPerTrack;
1.1.1.10 root 898: long Offset;
899: int nImageTracks;
900:
901: /* Do we have a writable disk in our drive? */
902: if (EmulationDrives[Drive].bDiskInserted && !Floppy_IsWriteProtected(Drive))
903: {
904: /* Looks good */
905: pDiskBuffer = EmulationDrives[Drive].pBuffer;
906:
907: /* Find #sides and #sectors per track */
908: Floppy_FindDiskDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides);
909: nImageTracks = ((EmulationDrives[Drive].nImageBytes / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides;
910:
911: /* Need to write whole track? */
912: if (Count<0)
913: Count = nSectorsPerTrack;
914: /* Write back number of sector per track */
915: if (pnSectorsPerTrack)
916: *pnSectorsPerTrack = nSectorsPerTrack;
917:
1.1.1.18 root 918: if (pSectorSize)
919: *pSectorSize = NUMBYTESPERSECTOR; /* Size is 512 bytes for ST/MSA */
920:
1.1.1.10 root 921: /* Debug check as if we write over the end of a track we write into side 2! */
922: if (Count > nSectorsPerTrack)
923: {
924: Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: writing over single track\n");
925: }
926:
927: /* Check that the side number (0 or 1) does not exceed the amount of sides (1 or 2). */
928: if (Side >= nSides)
929: {
930: Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to side %i "
931: "of a disk image with %i sides!\n", Side+1, nSides);
1.1.1.14 root 932: return false;
1.1.1.10 root 933: }
934:
935: /* Check if track number is in range */
936: if (Track >= nImageTracks)
937: {
938: Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to track %i "
939: "of a disk image with only %i tracks!\n", Track, nImageTracks);
1.1.1.14 root 940: return false;
1.1.1.10 root 941: }
942:
943: /* Check if sector number is in range */
944: if (Sector <= 0 || Sector > nSectorsPerTrack)
945: {
946: Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to sector %i "
947: "of a disk image with %i sectors per track!\n", Sector, nSectorsPerTrack);
1.1.1.14 root 948: return false;
1.1.1.10 root 949: }
950:
951: /* Seek to sector */
952: nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack;
953: Offset = nBytesPerTrack*Side; /* First seek to side */
954: Offset += (nBytesPerTrack*nSides)*Track; /* Then seek to track */
955: Offset += (NUMBYTESPERSECTOR*(Sector-1)); /* And finally to sector */
956:
957: /* Write sectors (usually 512 bytes per sector) */
958: memcpy(pDiskBuffer+Offset, pBuffer, (int)Count*NUMBYTESPERSECTOR);
959: /* And set 'changed' flag */
1.1.1.14 root 960: EmulationDrives[Drive].bContentsChanged = true;
1.1 root 961:
1.1.1.14 root 962: return true;
1.1.1.10 root 963: }
1.1 root 964:
1.1.1.14 root 965: return false;
1.1 root 966: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.