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

Comparing BasiliskII/src/cdrom.cpp (file contents):
Revision 1.6 by cebix, 2000-07-14T21:29:07Z vs.
Revision 1.16 by cebix, 2002-01-15T14:58:32Z

# Line 1 | Line 1
1   /*
2   *  cdrom.cpp - CD-ROM driver
3   *
4 < *  Basilisk II (C) 1997-2000 Christian Bauer
4 > *  Basilisk II (C) 1997-2002 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 28 | Line 28
28   *    Technote FL 36: "Apple Extensions to ISO 9660"
29   */
30  
31 + #include "sysdeps.h"
32 +
33   #include <string.h>
34 + #include <vector>
35 +
36 + #ifndef NO_STD_NAMESPACE
37 + using std::vector;
38 + #endif
39  
33 #include "sysdeps.h"
40   #include "cpu_emulation.h"
41   #include "main.h"
42   #include "macos_util.h"
# Line 97 | Line 103 | static const uint8 bin2bcd[256] = {
103   };
104  
105   static const uint8 bcd2bin[256] = {
106 <        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
106 >         0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
107          10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
108          20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
109          30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
# Line 117 | Line 123 | static const uint8 bcd2bin[256] = {
123  
124  
125   // Struct for each drive
126 < struct DriveInfo {
127 <        DriveInfo()
128 <        {
129 <                next = NULL;
130 <                num = 0;
125 <                fh = NULL;
126 <                start_byte = 0;
127 <                status = 0;
128 <        }
126 > struct cdrom_drive_info {
127 >        cdrom_drive_info() : num(0), fh(NULL), start_byte(0), status(0) {}
128 >        cdrom_drive_info(void *fh_) : num(0), fh(fh_), start_byte(0), status(0) {}
129 >
130 >        void close_fh(void) { SysAllowRemoval(fh); Sys_close(fh); }
131  
130        DriveInfo *next;        // Pointer to next DriveInfo (must be first in struct!)
132          int num;                        // Drive number
133          void *fh;                       // File handle
134          int block_size;         // CD-ROM block size
135          int twok_offset;        // Offset of beginning of 2K block to last Prime position
136 <        uint32 start_byte;      // Start of HFS partition on disk
136 >        loff_t start_byte;      // Start of HFS partition on disk
137          bool to_be_mounted;     // Flag: drive must be mounted in accRun
138          bool mount_non_hfs;     // Flag: Issue disk-inserted events for non-HFS disks
139  
# Line 145 | Line 146 | struct DriveInfo {
146          uint32 status;          // Mac address of drive status record
147   };
148  
149 < // Linked list of DriveInfos
150 < static DriveInfo *first_drive_info;
149 > // List of drives handled by this driver
150 > typedef vector<cdrom_drive_info> drive_vec;
151 > static drive_vec drives;
152  
153   // Icon address (Mac address space, set by PatchROM())
154   uint32 CDROMIconAddr;
# Line 156 | Line 158 | static bool acc_run_called = false;
158  
159  
160   /*
161 < *  Get pointer to drive info, NULL = invalid drive number
161 > *  Get pointer to drive info or drives.end() if not found
162   */
163  
164 < static DriveInfo *get_drive_info(int num)
164 > static drive_vec::iterator get_drive_info(int num)
165   {
166 <        DriveInfo *info = first_drive_info;
167 <        while (info != NULL) {
166 >        drive_vec::iterator info, end = drives.end();
167 >        for (info = drives.begin(); info != end; ++info) {
168                  if (info->num == num)
169                          return info;
168                info = info->next;
170          }
171 <        return NULL;
171 >        return info;
172   }
173  
174  
# Line 175 | Line 176 | static DriveInfo *get_drive_info(int num
176   *  Find HFS partition, set info->start_byte (0 = no HFS partition)
177   */
178  
179 < static void find_hfs_partition(DriveInfo *info)
179 > static void find_hfs_partition(cdrom_drive_info &info)
180   {
181 <        info->start_byte = 0;
181 >        info.start_byte = 0;
182          uint8 *map = new uint8[512];
183  
184          // Search first 64 blocks for HFS partition
185          for (int i=0; i<64; i++) {
186 <                if (Sys_read(info->fh, map, i * 512, 512) != 512)
186 >                if (Sys_read(info.fh, map, i * 512, 512) != 512)
187                          break;
188  
189 <                // Skip driver descriptor
190 <                uint16 sig = ntohs(((uint16 *)map)[0]);
191 <                if (sig == 'ER')
191 <                        continue;
192 <
193 <                // No partition map? Then look at next block
194 <                if (sig != 'PM')
189 >                // Not a partition map block? Then look at next block
190 >                uint16 sig = (map[0] << 8) | map[1];
191 >                if (sig != 0x504d)
192                          continue;
193  
194 <                // Partition map found, Apple HFS partition?
194 >                // Partition map block found, Apple HFS partition?
195                  if (strcmp((char *)(map + 48), "Apple_HFS") == 0) {
196 <                        info->start_byte = ntohl(((uint32 *)map)[2]) << 9;
197 <                        D(bug(" HFS partition found at %ld, %ld blocks\n", info->start_byte, ntohl(((uint32 *)map)[3])));
196 >                        info.start_byte = ntohl(((uint32 *)map)[2]) << 9;
197 >                        D(bug(" HFS partition found at %d, %d blocks\n", info.start_byte, ntohl(((uint32 *)map)[3])));
198                          break;
199                  }
200          }
# Line 209 | Line 206 | static void find_hfs_partition(DriveInfo
206   *  Read TOC of disk and set lead_out
207   */
208  
209 < static void read_toc(DriveInfo *info)
209 > static void read_toc(cdrom_drive_info &info)
210   {
211          // Read TOC
212 <        memset(&info->toc, 0, sizeof(info->toc));
213 <        SysCDReadTOC(info->fh, info->toc);
214 <        D(bug(" TOC: %08lx %08lx\n", ntohl(((uint32 *)info->toc)[0]), ntohl(((uint32 *)info->toc)[1])));
212 >        memset(info.toc, 0, sizeof(info.toc));
213 >        SysCDReadTOC(info.fh, info.toc);
214 >        D(bug(" TOC: %08lx %08lx\n", ntohl(((uint32 *)info.toc)[0]), ntohl(((uint32 *)info.toc)[1])));
215  
216          // Find lead-out track
217 <        info->lead_out[0] = 0;
218 <        info->lead_out[1] = 0;
219 <        info->lead_out[2] = 0;
217 >        info.lead_out[0] = 0;
218 >        info.lead_out[1] = 0;
219 >        info.lead_out[2] = 0;
220          for (int i=4; i<804; i+=8) {
221 <                if (info->toc[i+2] == 0xaa) {
222 <                        info->stop_at[0] = info->lead_out[0] = info->toc[i+5];
223 <                        info->stop_at[1] = info->lead_out[1] = info->toc[i+6];
224 <                        info->stop_at[2] = info->lead_out[2] = info->toc[i+7];
221 >                if (info.toc[i+2] == 0xaa) {
222 >                        info.stop_at[0] = info.lead_out[0] = info.toc[i+5];
223 >                        info.stop_at[1] = info.lead_out[1] = info.toc[i+6];
224 >                        info.stop_at[2] = info.lead_out[2] = info.toc[i+7];
225                          break;
226                  }
227          }
228 <        D(bug(" Lead-Out M %d S %d F %d\n", info->lead_out[0], info->lead_out[1], info->lead_out[2]));
228 >        D(bug(" Lead-Out M %d S %d F %d\n", info.lead_out[0], info.lead_out[1], info.lead_out[2]));
229   }
230  
231  
# Line 237 | Line 234 | static void read_toc(DriveInfo *info)
234   *  Return: false = error
235   */
236  
237 < static bool position2msf(DriveInfo *info, uint16 postype, uint32 pos, bool stopping, uint8 &m, uint8 &s, uint8 &f)
237 > static bool position2msf(const cdrom_drive_info &info, uint16 postype, uint32 pos, bool stopping, uint8 &m, uint8 &s, uint8 &f)
238   {
239          switch (postype) {
240                  case 0:
# Line 255 | Line 252 | static bool position2msf(DriveInfo *info
252                          if (stopping)
253                                  track++;
254                          for (int i=4; i<804; i+=8) {
255 <                                if (info->toc[i+2] == track || info->toc[i+2] == 0xaa) {
256 <                                        m = info->toc[i+5];
257 <                                        s = info->toc[i+6];
258 <                                        f = info->toc[i+7];
255 >                                if (info.toc[i+2] == track || info.toc[i+2] == 0xaa) {
256 >                                        m = info.toc[i+5];
257 >                                        s = info.toc[i+6];
258 >                                        f = info.toc[i+7];
259                                          return true;
260                                  }
261                          }
# Line 276 | Line 273 | static bool position2msf(DriveInfo *info
273  
274   void CDROMInit(void)
275   {
279        first_drive_info = NULL;
280
276          // No drives specified in prefs? Then add defaults
277          if (PrefsFindString("cdrom", 0) == NULL)
278                  SysAddCDROMPrefs();
279  
280          // Add drives specified in preferences
281 <        int32 index = 0;
281 >        int index = 0;
282          const char *str;
283          while ((str = PrefsFindString("cdrom", index++)) != NULL) {
284                  void *fh = Sys_open(str, true);
285 <                if (fh) {
286 <                        DriveInfo *info = new DriveInfo;
292 <                        info->fh = fh;
293 <                        DriveInfo *p = (DriveInfo *)&first_drive_info;
294 <                        while (p->next != NULL)
295 <                                p = p->next;
296 <                        p->next = info;
297 <                }
285 >                if (fh)
286 >                        drives.push_back(cdrom_drive_info(fh));
287          }
288   }
289  
# Line 305 | Line 294 | void CDROMInit(void)
294  
295   void CDROMExit(void)
296   {
297 <        DriveInfo *info = first_drive_info, *next;
298 <        while (info != NULL) {
299 <                SysAllowRemoval(info->fh);
300 <                Sys_close(info->fh);
312 <                next = info->next;
313 <                delete info;
314 <                info = next;
315 <        }
297 >        drive_vec::iterator info, end = drives.end();
298 >        for (info = drives.begin(); info != end; ++info)
299 >                info->close_fh();
300 >        drives.clear();
301   }
302  
303  
# Line 322 | Line 307 | void CDROMExit(void)
307  
308   bool CDROMMountVolume(void *fh)
309   {
310 <        DriveInfo *info;
311 <        for (info = first_drive_info; info != NULL && info->fh != fh; info = info->next) ;
312 <        if (info) {
310 >        drive_vec::iterator info = drives.begin(), end = drives.end();
311 >        while (info != end && info->fh != fh)
312 >                ++info;
313 >        if (info != end) {
314                  if (SysIsDiskInserted(info->fh)) {
315                          SysPreventRemoval(info->fh);
316                          WriteMacInt8(info->status + dsDiskInPlace, 1);
317 <                        read_toc(info);
318 <                        find_hfs_partition(info);
317 >                        read_toc(*info);
318 >                        find_hfs_partition(*info);
319                          if (info->start_byte != 0 || info->mount_non_hfs)
320                                  info->to_be_mounted = true;
321                  }
# Line 346 | Line 332 | bool CDROMMountVolume(void *fh)
332  
333   static void mount_mountable_volumes(void)
334   {
335 <        DriveInfo *info = first_drive_info;
336 <        while (info != NULL) {
335 >        drive_vec::iterator info, end = drives.end();
336 >        for (info = drives.begin(); info != end; ++info) {
337  
338                  // Disk in drive?
339                  if (ReadMacInt8(info->status + dsDiskInPlace) == 0) {
# Line 366 | Line 352 | static void mount_mountable_volumes(void
352                          Execute68kTrap(0xa02f, &r);             // PostEvent()
353                          info->to_be_mounted = false;
354                  }
369
370                info = info->next;
355          }
356   }
357  
# Line 385 | Line 369 | int16 CDROMOpen(uint32 pb, uint32 dce)
369          acc_run_called = false;
370  
371          // Install drives
372 <        for (DriveInfo *info = first_drive_info; info; info = info->next) {
372 >        drive_vec::iterator info, end = drives.end();
373 >        for (info = drives.begin(); info != end; ++info) {
374  
375                  info->num = FindFreeDriveNumber(1);
376                  info->to_be_mounted = false;
# Line 415 | Line 400 | int16 CDROMOpen(uint32 pb, uint32 dce)
400                          if (SysIsDiskInserted(info->fh)) {
401                                  SysPreventRemoval(info->fh);
402                                  WriteMacInt8(info->status + dsDiskInPlace, 1);
403 <                                read_toc(info);
404 <                                find_hfs_partition(info);
403 >                                read_toc(*info);
404 >                                find_hfs_partition(*info);
405                                  info->to_be_mounted = true;
406                          }
407  
# Line 440 | Line 425 | int16 CDROMPrime(uint32 pb, uint32 dce)
425          WriteMacInt32(pb + ioActCount, 0);
426  
427          // Drive valid and disk inserted?
428 <        DriveInfo *info;
429 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
428 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
429 >        if (info == drives.end())
430                  return nsDrvErr;
431          if (ReadMacInt8(info->status + dsDiskInPlace) == 0)
432                  return offLinErr;
# Line 507 | Line 492 | int16 CDROMControl(uint32 pb, uint32 dce
492          }
493  
494          // Drive valid?
495 <        DriveInfo *info;
496 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
497 <                if (first_drive_info == NULL)
495 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
496 >        if (info == drives.end()) {
497 >                if (drives.empty())
498                          return nsDrvErr;
499                  else
500 <                        info = first_drive_info;        // This is needed for Apple's Audio CD program
500 >                        info = drives.begin();  // This is needed for Apple's Audio CD program
501 >        }
502  
503          // Drive-specific codes
504          switch (code) {
# Line 539 | Line 525 | int16 CDROMControl(uint32 pb, uint32 dce
525                          WriteMacInt32(pb + csParam, CDROMIconAddr);
526                          return noErr;
527  
528 <                case 23:                // DriveInfo
528 >                case 23:                // drive_info
529                          WriteMacInt32(pb + csParam, 0x00000b01);        // Unspecified external removable SCSI disk
530                          return noErr;
531  
# Line 674 | Line 660 | int16 CDROMControl(uint32 pb, uint32 dce
660                          return controlErr;
661  
662                  case 103: {             // AudioTrackSearch
663 <                        D(bug(" AudioTrackSearch postype %d, pos %08lx, hold %d\n", ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), ReadMacInt16(pb + csParam + 6)));
663 >                        D(bug(" AudioTrackSearch postype %d, pos %08x, hold %d\n", ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), ReadMacInt16(pb + csParam + 6)));
664                          if (ReadMacInt8(info->status + dsDiskInPlace) == 0)
665                                  return offLinErr;
666  
667                          uint8 start_m, start_s, start_f;
668 <                        if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
668 >                        if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
669                                  return paramErr;
670                          info->play_mode = ReadMacInt8(pb + csParam + 9) & 0x0f;
671                          if (!SysCDPlay(info->fh, start_m, start_s, start_f, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
# Line 696 | Line 682 | int16 CDROMControl(uint32 pb, uint32 dce
682  
683                          if (ReadMacInt16(pb + csParam + 6)) {
684                                  // Given stopping address
685 <                                if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
685 >                                if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
686                                          return paramErr;
687                          } else {
688                                  // Given starting address
689                                  uint8 start_m, start_s, start_f;
690 <                                if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
690 >                                if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
691                                          return paramErr;
692                                  info->play_mode = ReadMacInt8(pb + csParam + 9) & 0x0f;
693                                  if (!SysCDPlay(info->fh, start_m, start_s, start_f, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
# Line 738 | Line 724 | int16 CDROMControl(uint32 pb, uint32 dce
724                                          return paramErr;
725                          } else {
726                                  // Given stopping address
727 <                                if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
727 >                                if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
728                                          return paramErr;
729                          }
730                          return noErr;
# Line 783 | Line 769 | int16 CDROMControl(uint32 pb, uint32 dce
769                                  return offLinErr;
770  
771                          uint8 start_m, start_s, start_f;
772 <                        if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
772 >                        if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
773                                  return paramErr;
774  
775                          if (!SysCDScan(info->fh, start_m, start_s, start_f, ReadMacInt16(pb + csParam + 6)))
# Line 861 | Line 847 | int16 CDROMControl(uint32 pb, uint32 dce
847  
848   int16 CDROMStatus(uint32 pb, uint32 dce)
849   {
850 <        DriveInfo *info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
850 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
851          uint16 code = ReadMacInt16(pb + csCode);
852          D(bug("CDROMStatus %d\n", code));
853  
854 <        // General codes
854 >        // General codes (we can get these even if the drive was invalid)
855          switch (code) {
856                  case 43: {      // DriverGestalt
857                          uint32 sel = ReadMacInt32(pb + csParam);
858                          D(bug(" driver gestalt %c%c%c%c\n", sel >> 24, sel >> 16,  sel >> 8, sel));
859                          switch (sel) {
860 <                                case 'vers':    // Version
860 >                                case FOURCC('v','e','r','s'):   // Version
861                                          WriteMacInt32(pb + csParam + 4, 0x05208000);
862                                          break;
863 <                                case 'devt':    // Device type
864 <                                        WriteMacInt32(pb + csParam + 4, 'cdrm');
863 >                                case FOURCC('d','e','v','t'):   // Device type
864 >                                        WriteMacInt32(pb + csParam + 4, FOURCC('c','d','r','m'));
865                                          break;
866 <                                case 'intf':    // Interface type
867 <                                        WriteMacInt32(pb + csParam + 4, 'basi');
866 >                                case FOURCC('i','n','t','f'):   // Interface type
867 >                                        WriteMacInt32(pb + csParam + 4, EMULATOR_ID_4);
868                                          break;
869 <                                case 'sync':    // Only synchronous operation?
869 >                                case FOURCC('s','y','n','c'):   // Only synchronous operation?
870                                          WriteMacInt32(pb + csParam + 4, 0x01000000);
871                                          break;
872 <                                case 'boot':    // Boot ID
873 <                                        if (info != NULL)
872 >                                case FOURCC('b','o','o','t'):   // Boot ID
873 >                                        if (info != drives.end())
874                                                  WriteMacInt16(pb + csParam + 4, info->num);
875                                          else
876                                                  WriteMacInt16(pb + csParam + 4, 0);
877                                          WriteMacInt16(pb + csParam + 6, (uint16)CDROMRefNum);
878                                          break;
879 <                                case 'wide':    // 64-bit access supported?
879 >                                case FOURCC('w','i','d','e'):   // 64-bit access supported?
880                                          WriteMacInt16(pb + csParam + 4, 0);
881                                          break;
882 <                                case 'purg':    // Purge flags
882 >                                case FOURCC('p','u','r','g'):   // Purge flags
883                                          WriteMacInt32(pb + csParam + 4, 0);
884                                          break;
885 <                                case 'ejec':    // Eject flags
885 >                                case FOURCC('e','j','e','c'):   // Eject flags
886                                          WriteMacInt32(pb + csParam + 4, 0x00030003);    // Don't eject on shutdown/restart
887                                          break;
888 <                                case 'flus':    // Flush flags
888 >                                case FOURCC('f','l','u','s'):   // Flush flags
889                                          WriteMacInt16(pb + csParam + 4, 0);
890                                          break;
891 <                                case 'vmop':    // Virtual memory attributes
891 >                                case FOURCC('v','m','o','p'):   // Virtual memory attributes
892                                          WriteMacInt32(pb + csParam + 4, 0);     // Drive not available for VM
893                                          break;
894                                  default:
# Line 913 | Line 899 | int16 CDROMStatus(uint32 pb, uint32 dce)
899          }
900  
901          // Drive valid?
902 <        if (info == NULL)
903 <                if (first_drive_info == NULL)
902 >        if (info == drives.end()) {
903 >                if (drives.empty())
904                          return nsDrvErr;
905                  else
906 <                        info = first_drive_info;        // This is needed for Apple's Audio CD program
906 >                        info = drives.begin();  // This is needed for Apple's Audio CD program
907 >        }
908  
909          // Drive-specific codes
910          switch (code) {
911 +                case 6:                 // Return format list
912 +                        if (ReadMacInt16(pb + csParam) > 0) {
913 +                                uint32 adr = ReadMacInt32(pb + csParam + 2);
914 +                                WriteMacInt16(pb + csParam, 1);                                         // 1 format
915 +                                WriteMacInt32(adr, SysGetFileSize(info->fh) / 512);     // Number of blocks
916 +                                WriteMacInt32(adr + 4, 0);                                                      // heads/track/sectors
917 +                                return noErr;
918 +                        } else
919 +                                return paramErr;
920 +
921                  case 8:                 // DriveStatus
922                          Mac2Mac_memcpy(pb + csParam, info->status, 22);
923                          return noErr;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines