ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/disk.cpp
(Generate patch)

Comparing BasiliskII/src/disk.cpp (file contents):
Revision 1.7 by cebix, 2000-07-22T16:07:15Z vs.
Revision 1.11 by cebix, 2001-07-14T20:01:18Z

# Line 1 | Line 1
1   /*
2   *  disk.cpp - Generic disk driver
3   *
4 < *  Basilisk II (C) 1997-2000 Christian Bauer
4 > *  Basilisk II (C) 1997-2001 Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 27 | Line 27
27   */
28  
29   #include <string.h>
30 + #include <vector>
31 +
32 + #ifndef NO_STD_NAMESPACE
33 + using std::vector;
34 + #endif
35  
36   #include "sysdeps.h"
37   #include "cpu_emulation.h"
# Line 65 | Line 70 | const uint8 DiskIcon[258] = {
70  
71  
72   // Struct for each drive
73 < struct DriveInfo {
74 <        DriveInfo()
75 <        {
76 <                next = NULL;
77 <                num = 0;
73 <                fh = NULL;
74 <                read_only = false;
75 <                status = 0;
76 <        }
73 > struct disk_drive_info {
74 >        disk_drive_info() : num(0), fh(NULL), start_byte(0), read_only(false), status(0) {}
75 >        disk_drive_info(void *fh_, bool ro) : num(0), fh(fh_), read_only(ro), status(0) {}
76 >
77 >        void close_fh(void) { Sys_close(fh); }
78  
78        DriveInfo *next;        // Pointer to next DriveInfo (must be first in struct!)
79          int num;                        // Drive number
80          void *fh;                       // File handle
81 +        loff_t start_byte;      // Start of HFS partition on disk
82          uint32 num_blocks;      // Size in 512-byte blocks
83          bool to_be_mounted;     // Flag: drive must be mounted in accRun
84          bool read_only;         // Flag: force write protection
85          uint32 status;          // Mac address of drive status record
86   };
87  
88 < // Linked list of DriveInfos
89 < static DriveInfo *first_drive_info;
88 > // List of drives handled by this driver
89 > typedef vector<disk_drive_info> drive_vec;
90 > static drive_vec drives;
91  
92   // Icon address (Mac address space, set by PatchROM())
93   uint32 DiskIconAddr;
# Line 95 | Line 97 | static bool acc_run_called = false;
97  
98  
99   /*
100 < *  Get pointer to drive info, NULL = invalid drive number
100 > *  Get pointer to drive info or drives.end() if not found
101   */
102  
103 < static DriveInfo *get_drive_info(int num)
103 > static drive_vec::iterator get_drive_info(int num)
104   {
105 <        DriveInfo *info = first_drive_info;
106 <        while (info != NULL) {
105 >        drive_vec::iterator info, end = drives.end();
106 >        for (info = drives.begin(); info != end; ++info) {
107                  if (info->num == num)
108                          return info;
107                info = info->next;
109          }
110 <        return NULL;
110 >        return info;
111 > }
112 >
113 >
114 > /*
115 > *  Find HFS partition, set info->start_byte and info->num_blocks
116 > *  (0 = no partition map or HFS partition found, assume flat disk image)
117 > */
118 >
119 > static void find_hfs_partition(disk_drive_info &info)
120 > {
121 >        info.start_byte = 0;
122 >        info.num_blocks = 0;
123 >        uint8 *map = new uint8[512];
124 >
125 >        // Search first 64 blocks for HFS partition
126 >        for (int i=0; i<64; i++) {
127 >                if (Sys_read(info.fh, map, i * 512, 512) != 512)
128 >                        break;
129 >
130 >                // Not a partition map block? Then look at next block
131 >                uint16 sig = (map[0] << 8) | map[1];
132 >                if (sig != 0x504d)
133 >                        continue;
134 >
135 >                // Partition map block found, Apple HFS partition?
136 >                if (strcmp((char *)(map + 48), "Apple_HFS") == 0) {
137 >                        info.start_byte = ntohl(((uint32 *)map)[2]) << 9;
138 >                        info.num_blocks = ntohl(((uint32 *)map)[3]);
139 >                        D(bug(" HFS partition found at %d, %d blocks\n", info.start_byte, info.num_blocks));
140 >                        break;
141 >                }
142 >        }
143 >        delete[] map;
144   }
145  
146  
# Line 116 | Line 150 | static DriveInfo *get_drive_info(int num
150  
151   void DiskInit(void)
152   {
119        first_drive_info = NULL;
120
153          // No drives specified in prefs? Then add defaults
154          if (PrefsFindString("disk", 0) == NULL)
155                  SysAddDiskPrefs();
156  
157          // Add drives specified in preferences
158 <        int32 index = 0;
158 >        int index = 0;
159          const char *str;
160          while ((str = PrefsFindString("disk", index++)) != NULL) {
161                  bool read_only = false;
# Line 132 | Line 164 | void DiskInit(void)
164                          str++;
165                  }
166                  void *fh = Sys_open(str, read_only);
167 <                if (fh) {
168 <                        D(bug(" adding drive '%s'\n", str));
137 <                        DriveInfo *info = new DriveInfo;
138 <                        info->fh = fh;
139 <                        info->read_only = SysIsReadOnly(fh);
140 <                        DriveInfo *p = (DriveInfo *)&first_drive_info;
141 <                        while (p->next != NULL)
142 <                                p = p->next;
143 <                        p->next = info;
144 <                }
167 >                if (fh)
168 >                        drives.push_back(disk_drive_info(fh, SysIsReadOnly(fh)));
169          }
170   }
171  
# Line 152 | Line 176 | void DiskInit(void)
176  
177   void DiskExit(void)
178   {
179 <        DriveInfo *info = first_drive_info, *next;
180 <        while (info != NULL) {
181 <                Sys_close(info->fh);
182 <                next = info->next;
159 <                delete info;
160 <                info = next;
161 <        }
179 >        drive_vec::iterator info, end = drives.end();
180 >        for (info = drives.begin(); info != end; ++info)
181 >                info->close_fh();
182 >        drives.clear();
183   }
184  
185  
# Line 168 | Line 189 | void DiskExit(void)
189  
190   bool DiskMountVolume(void *fh)
191   {
192 <        DriveInfo *info;
193 <        for (info = first_drive_info; info != NULL && info->fh != fh; info = info->next) ;
194 <        if (info) {
192 >        drive_vec::iterator info = drives.begin(), end = drives.end();
193 >        while (info != end && info->fh != fh)
194 >                ++info;
195 >        if (info != end) {
196                  if (SysIsDiskInserted(info->fh)) {
197                          info->read_only = SysIsReadOnly(info->fh);
198                          WriteMacInt8(info->status + dsDiskInPlace, 1);  // Inserted removable disk
199                          WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
200 <                        info->num_blocks = SysGetFileSize(info->fh) / 512;
200 >                        find_hfs_partition(*info);
201 >                        if (info->start_byte == 0)
202 >                                info->num_blocks = SysGetFileSize(info->fh) / 512;
203                          WriteMacInt16(info->status + dsDriveSize, info->num_blocks & 0xffff);
204                          WriteMacInt16(info->status + dsDriveS1, info->num_blocks >> 16);
205                          info->to_be_mounted = true;
# Line 193 | Line 217 | bool DiskMountVolume(void *fh)
217  
218   static void mount_mountable_volumes(void)
219   {
220 <        DriveInfo *info = first_drive_info;
221 <        while (info != NULL) {
220 >        drive_vec::iterator info, end = drives.end();
221 >        for (info = drives.begin(); info != end; ++info) {
222  
223                  // Disk in drive?
224                  if (!ReadMacInt8(info->status + dsDiskInPlace)) {
# Line 213 | Line 237 | static void mount_mountable_volumes(void
237                          Execute68kTrap(0xa02f, &r);             // PostEvent()
238                          info->to_be_mounted = false;
239                  }
216
217                info = info->next;
240          }
241   }
242  
# Line 232 | Line 254 | int16 DiskOpen(uint32 pb, uint32 dce)
254          acc_run_called = false;
255  
256          // Install drives
257 <        for (DriveInfo *info = first_drive_info; info; info = info->next) {
257 >        drive_vec::iterator info, end = drives.end();
258 >        for (info = drives.begin(); info != end; ++info) {
259  
260                  info->num = FindFreeDriveNumber(1);
261                  info->to_be_mounted = false;
# Line 262 | Line 285 | int16 DiskOpen(uint32 pb, uint32 dce)
285                          if (disk_in_place) {
286                                  D(bug(" disk inserted\n"));
287                                  WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0x80 : 0);
288 <                                info->num_blocks = SysGetFileSize(info->fh) / 512;
288 >                                find_hfs_partition(*info);
289 >                                if (info->start_byte == 0)
290 >                                        info->num_blocks = SysGetFileSize(info->fh) / 512;
291                                  info->to_be_mounted = true;
292                          }
293                          D(bug(" %d blocks\n", info->num_blocks));
# Line 289 | Line 314 | int16 DiskPrime(uint32 pb, uint32 dce)
314          WriteMacInt32(pb + ioActCount, 0);
315  
316          // Drive valid and disk inserted?
317 <        DriveInfo *info;
318 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
317 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
318 >        if (info == drives.end())
319                  return nsDrvErr;
320          if (!ReadMacInt8(info->status + dsDiskInPlace))
321                  return offLinErr;
# Line 308 | Line 333 | int16 DiskPrime(uint32 pb, uint32 dce)
333          if ((ReadMacInt16(pb + ioTrap) & 0xff) == aRdCmd) {
334  
335                  // Read
336 <                actual = Sys_read(info->fh, buffer, position, length);
336 >                actual = Sys_read(info->fh, buffer, position + info->start_byte, length);
337                  if (actual != length)
338                          return readErr;
339  
# Line 317 | Line 342 | int16 DiskPrime(uint32 pb, uint32 dce)
342                  // Write
343                  if (info->read_only)
344                          return wPrErr;
345 <                actual = Sys_write(info->fh, buffer, position, length);
345 >                actual = Sys_write(info->fh, buffer, position + info->start_byte, length);
346                  if (actual != length)
347                          return writErr;
348          }
# Line 352 | Line 377 | int16 DiskControl(uint32 pb, uint32 dce)
377          }
378  
379          // Drive valid?
380 <        DriveInfo *info;
381 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
380 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
381 >        if (info == drives.end())
382                  return nsDrvErr;
383  
384          // Drive-specific codes
# Line 417 | Line 442 | int16 DiskControl(uint32 pb, uint32 dce)
442  
443   int16 DiskStatus(uint32 pb, uint32 dce)
444   {
445 <        DriveInfo *info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
445 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
446          uint16 code = ReadMacInt16(pb + csCode);
447          D(bug("DiskStatus %d\n", code));
448  
449 <        // General codes
449 >        // General codes (we can get these even if the drive was invalid)
450          switch (code) {
451                  case 43: {      // Driver gestalt
452                          uint32 sel = ReadMacInt32(pb + csParam);
# Line 431 | Line 456 | int16 DiskStatus(uint32 pb, uint32 dce)
456                                          WriteMacInt32(pb + csParam + 4, 0x01008000);
457                                          break;
458                                  case FOURCC('d','e','v','t'):   // Device type
459 <                                        if (info != NULL) {
459 >                                        if (info != drives.end()) {
460                                                  if (ReadMacInt8(info->status + dsDiskInPlace) == 8)
461                                                          WriteMacInt32(pb + csParam + 4, FOURCC('d','i','s','k'));
462                                                  else
# Line 440 | Line 465 | int16 DiskStatus(uint32 pb, uint32 dce)
465                                                  WriteMacInt32(pb + csParam + 4, FOURCC('d','i','s','k'));
466                                          break;
467                                  case FOURCC('i','n','t','f'):   // Interface type
468 <                                        WriteMacInt32(pb + csParam + 4, FOURCC('b','a','s','i'));
468 >                                        WriteMacInt32(pb + csParam + 4, EMULATOR_ID_4);
469                                          break;
470                                  case FOURCC('s','y','n','c'):   // Only synchronous operation?
471                                          WriteMacInt32(pb + csParam + 4, 0x01000000);
472                                          break;
473                                  case FOURCC('b','o','o','t'):   // Boot ID
474 <                                        if (info != NULL)
474 >                                        if (info != drives.end())
475                                                  WriteMacInt16(pb + csParam + 4, info->num);
476                                          else
477                                                  WriteMacInt16(pb + csParam + 4, 0);
# Line 475 | Line 500 | int16 DiskStatus(uint32 pb, uint32 dce)
500          }
501  
502          // Drive valid?
503 <        if (info == NULL)
503 >        if (info == drives.end())
504                  return nsDrvErr;
505  
506          // Drive-specific codes

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines