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.7 by cebix, 2000-07-22T16:07:15Z vs.
Revision 1.17 by cebix, 2002-02-07T16:10:54Z

# 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]);
190 <                if (sig == 0x4552)
191 <                        continue;
192 <
193 <                // No partition map? Then look at next block
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 %d, %d blocks\n", info->start_byte, ntohl(((uint32 *)map)[3])));
196 >                        info.start_byte = (loff_t)((map[8] << 24) | (map[9] << 16) | (map[10] << 8) | map[11]) << 9;
197 >                        uint32 num_blocks = (map[12] << 24) | (map[13] << 16) | (map[14] << 8) | map[15];
198 >                        D(bug(" HFS partition found at %d, %d blocks\n", info.start_byte, num_blocks));
199                          break;
200                  }
201          }
# Line 209 | Line 207 | static void find_hfs_partition(DriveInfo
207   *  Read TOC of disk and set lead_out
208   */
209  
210 < static void read_toc(DriveInfo *info)
210 > static void read_toc(cdrom_drive_info &info)
211   {
212          // Read TOC
213 <        memset(&info->toc, 0, sizeof(info->toc));
214 <        SysCDReadTOC(info->fh, info->toc);
215 <        D(bug(" TOC: %08lx %08lx\n", ntohl(((uint32 *)info->toc)[0]), ntohl(((uint32 *)info->toc)[1])));
213 >        memset(info.toc, 0, sizeof(info.toc));
214 >        SysCDReadTOC(info.fh, info.toc);
215 >        D(bug(" TOC: %08lx %08lx\n", ntohl(((uint32 *)info.toc)[0]), ntohl(((uint32 *)info.toc)[1])));
216  
217          // Find lead-out track
218 <        info->lead_out[0] = 0;
219 <        info->lead_out[1] = 0;
220 <        info->lead_out[2] = 0;
218 >        info.lead_out[0] = 0;
219 >        info.lead_out[1] = 0;
220 >        info.lead_out[2] = 0;
221          for (int i=4; i<804; i+=8) {
222 <                if (info->toc[i+2] == 0xaa) {
223 <                        info->stop_at[0] = info->lead_out[0] = info->toc[i+5];
224 <                        info->stop_at[1] = info->lead_out[1] = info->toc[i+6];
225 <                        info->stop_at[2] = info->lead_out[2] = info->toc[i+7];
222 >                if (info.toc[i+2] == 0xaa) {
223 >                        info.stop_at[0] = info.lead_out[0] = info.toc[i+5];
224 >                        info.stop_at[1] = info.lead_out[1] = info.toc[i+6];
225 >                        info.stop_at[2] = info.lead_out[2] = info.toc[i+7];
226                          break;
227                  }
228          }
229 <        D(bug(" Lead-Out M %d S %d F %d\n", info->lead_out[0], info->lead_out[1], info->lead_out[2]));
229 >        D(bug(" Lead-Out M %d S %d F %d\n", info.lead_out[0], info.lead_out[1], info.lead_out[2]));
230   }
231  
232  
# Line 237 | Line 235 | static void read_toc(DriveInfo *info)
235   *  Return: false = error
236   */
237  
238 < static bool position2msf(DriveInfo *info, uint16 postype, uint32 pos, bool stopping, uint8 &m, uint8 &s, uint8 &f)
238 > static bool position2msf(const cdrom_drive_info &info, uint16 postype, uint32 pos, bool stopping, uint8 &m, uint8 &s, uint8 &f)
239   {
240          switch (postype) {
241                  case 0:
# Line 255 | Line 253 | static bool position2msf(DriveInfo *info
253                          if (stopping)
254                                  track++;
255                          for (int i=4; i<804; i+=8) {
256 <                                if (info->toc[i+2] == track || info->toc[i+2] == 0xaa) {
257 <                                        m = info->toc[i+5];
258 <                                        s = info->toc[i+6];
259 <                                        f = info->toc[i+7];
256 >                                if (info.toc[i+2] == track || info.toc[i+2] == 0xaa) {
257 >                                        m = info.toc[i+5];
258 >                                        s = info.toc[i+6];
259 >                                        f = info.toc[i+7];
260                                          return true;
261                                  }
262                          }
# Line 276 | Line 274 | static bool position2msf(DriveInfo *info
274  
275   void CDROMInit(void)
276   {
279        first_drive_info = NULL;
280
277          // No drives specified in prefs? Then add defaults
278          if (PrefsFindString("cdrom", 0) == NULL)
279                  SysAddCDROMPrefs();
280  
281          // Add drives specified in preferences
282 <        int32 index = 0;
282 >        int index = 0;
283          const char *str;
284          while ((str = PrefsFindString("cdrom", index++)) != NULL) {
285                  void *fh = Sys_open(str, true);
286 <                if (fh) {
287 <                        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 <                }
286 >                if (fh)
287 >                        drives.push_back(cdrom_drive_info(fh));
288          }
289   }
290  
# Line 305 | Line 295 | void CDROMInit(void)
295  
296   void CDROMExit(void)
297   {
298 <        DriveInfo *info = first_drive_info, *next;
299 <        while (info != NULL) {
300 <                SysAllowRemoval(info->fh);
301 <                Sys_close(info->fh);
312 <                next = info->next;
313 <                delete info;
314 <                info = next;
315 <        }
298 >        drive_vec::iterator info, end = drives.end();
299 >        for (info = drives.begin(); info != end; ++info)
300 >                info->close_fh();
301 >        drives.clear();
302   }
303  
304  
# Line 322 | Line 308 | void CDROMExit(void)
308  
309   bool CDROMMountVolume(void *fh)
310   {
311 <        DriveInfo *info;
312 <        for (info = first_drive_info; info != NULL && info->fh != fh; info = info->next) ;
313 <        if (info) {
311 >        drive_vec::iterator info = drives.begin(), end = drives.end();
312 >        while (info != end && info->fh != fh)
313 >                ++info;
314 >        if (info != end) {
315                  if (SysIsDiskInserted(info->fh)) {
316                          SysPreventRemoval(info->fh);
317                          WriteMacInt8(info->status + dsDiskInPlace, 1);
318 <                        read_toc(info);
319 <                        find_hfs_partition(info);
318 >                        read_toc(*info);
319 >                        find_hfs_partition(*info);
320                          if (info->start_byte != 0 || info->mount_non_hfs)
321                                  info->to_be_mounted = true;
322                  }
# Line 346 | Line 333 | bool CDROMMountVolume(void *fh)
333  
334   static void mount_mountable_volumes(void)
335   {
336 <        DriveInfo *info = first_drive_info;
337 <        while (info != NULL) {
336 >        drive_vec::iterator info, end = drives.end();
337 >        for (info = drives.begin(); info != end; ++info) {
338  
339                  // Disk in drive?
340                  if (ReadMacInt8(info->status + dsDiskInPlace) == 0) {
# Line 366 | Line 353 | static void mount_mountable_volumes(void
353                          Execute68kTrap(0xa02f, &r);             // PostEvent()
354                          info->to_be_mounted = false;
355                  }
369
370                info = info->next;
356          }
357   }
358  
# Line 385 | Line 370 | int16 CDROMOpen(uint32 pb, uint32 dce)
370          acc_run_called = false;
371  
372          // Install drives
373 <        for (DriveInfo *info = first_drive_info; info; info = info->next) {
373 >        drive_vec::iterator info, end = drives.end();
374 >        for (info = drives.begin(); info != end; ++info) {
375  
376                  info->num = FindFreeDriveNumber(1);
377                  info->to_be_mounted = false;
# Line 415 | Line 401 | int16 CDROMOpen(uint32 pb, uint32 dce)
401                          if (SysIsDiskInserted(info->fh)) {
402                                  SysPreventRemoval(info->fh);
403                                  WriteMacInt8(info->status + dsDiskInPlace, 1);
404 <                                read_toc(info);
405 <                                find_hfs_partition(info);
404 >                                read_toc(*info);
405 >                                find_hfs_partition(*info);
406                                  info->to_be_mounted = true;
407                          }
408  
# Line 440 | Line 426 | int16 CDROMPrime(uint32 pb, uint32 dce)
426          WriteMacInt32(pb + ioActCount, 0);
427  
428          // Drive valid and disk inserted?
429 <        DriveInfo *info;
430 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
429 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
430 >        if (info == drives.end())
431                  return nsDrvErr;
432          if (ReadMacInt8(info->status + dsDiskInPlace) == 0)
433                  return offLinErr;
# Line 507 | Line 493 | int16 CDROMControl(uint32 pb, uint32 dce
493          }
494  
495          // Drive valid?
496 <        DriveInfo *info;
497 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
498 <                if (first_drive_info == NULL)
496 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
497 >        if (info == drives.end()) {
498 >                if (drives.empty())
499                          return nsDrvErr;
500                  else
501 <                        info = first_drive_info;        // This is needed for Apple's Audio CD program
501 >                        info = drives.begin();  // This is needed for Apple's Audio CD program
502 >        }
503  
504          // Drive-specific codes
505          switch (code) {
# Line 539 | Line 526 | int16 CDROMControl(uint32 pb, uint32 dce
526                          WriteMacInt32(pb + csParam, CDROMIconAddr);
527                          return noErr;
528  
529 <                case 23:                // DriveInfo
529 >                case 23:                // drive_info
530                          WriteMacInt32(pb + csParam, 0x00000b01);        // Unspecified external removable SCSI disk
531                          return noErr;
532  
# Line 679 | Line 666 | int16 CDROMControl(uint32 pb, uint32 dce
666                                  return offLinErr;
667  
668                          uint8 start_m, start_s, start_f;
669 <                        if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
669 >                        if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
670                                  return paramErr;
671                          info->play_mode = ReadMacInt8(pb + csParam + 9) & 0x0f;
672                          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 683 | int16 CDROMControl(uint32 pb, uint32 dce
683  
684                          if (ReadMacInt16(pb + csParam + 6)) {
685                                  // Given stopping address
686 <                                if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
686 >                                if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
687                                          return paramErr;
688                          } else {
689                                  // Given starting address
690                                  uint8 start_m, start_s, start_f;
691 <                                if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
691 >                                if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
692                                          return paramErr;
693                                  info->play_mode = ReadMacInt8(pb + csParam + 9) & 0x0f;
694                                  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 725 | int16 CDROMControl(uint32 pb, uint32 dce
725                                          return paramErr;
726                          } else {
727                                  // Given stopping address
728 <                                if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
728 >                                if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
729                                          return paramErr;
730                          }
731                          return noErr;
# Line 783 | Line 770 | int16 CDROMControl(uint32 pb, uint32 dce
770                                  return offLinErr;
771  
772                          uint8 start_m, start_s, start_f;
773 <                        if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
773 >                        if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
774                                  return paramErr;
775  
776                          if (!SysCDScan(info->fh, start_m, start_s, start_f, ReadMacInt16(pb + csParam + 6)))
# Line 861 | Line 848 | int16 CDROMControl(uint32 pb, uint32 dce
848  
849   int16 CDROMStatus(uint32 pb, uint32 dce)
850   {
851 <        DriveInfo *info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
851 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
852          uint16 code = ReadMacInt16(pb + csCode);
853          D(bug("CDROMStatus %d\n", code));
854  
855 <        // General codes
855 >        // General codes (we can get these even if the drive was invalid)
856          switch (code) {
857                  case 43: {      // DriverGestalt
858                          uint32 sel = ReadMacInt32(pb + csParam);
# Line 878 | Line 865 | int16 CDROMStatus(uint32 pb, uint32 dce)
865                                          WriteMacInt32(pb + csParam + 4, FOURCC('c','d','r','m'));
866                                          break;
867                                  case FOURCC('i','n','t','f'):   // Interface type
868 <                                        WriteMacInt32(pb + csParam + 4, FOURCC('b','a','s','i'));
868 >                                        WriteMacInt32(pb + csParam + 4, EMULATOR_ID_4);
869                                          break;
870                                  case FOURCC('s','y','n','c'):   // Only synchronous operation?
871                                          WriteMacInt32(pb + csParam + 4, 0x01000000);
872                                          break;
873                                  case FOURCC('b','o','o','t'):   // Boot ID
874 <                                        if (info != NULL)
874 >                                        if (info != drives.end())
875                                                  WriteMacInt16(pb + csParam + 4, info->num);
876                                          else
877                                                  WriteMacInt16(pb + csParam + 4, 0);
# Line 913 | Line 900 | int16 CDROMStatus(uint32 pb, uint32 dce)
900          }
901  
902          // Drive valid?
903 <        if (info == NULL)
904 <                if (first_drive_info == NULL)
903 >        if (info == drives.end()) {
904 >                if (drives.empty())
905                          return nsDrvErr;
906                  else
907 <                        info = first_drive_info;        // This is needed for Apple's Audio CD program
907 >                        info = drives.begin();  // This is needed for Apple's Audio CD program
908 >        }
909  
910          // Drive-specific codes
911          switch (code) {
912 +                case 6:                 // Return format list
913 +                        if (ReadMacInt16(pb + csParam) > 0) {
914 +                                uint32 adr = ReadMacInt32(pb + csParam + 2);
915 +                                WriteMacInt16(pb + csParam, 1);                                         // 1 format
916 +                                WriteMacInt32(adr, SysGetFileSize(info->fh) / 512);     // Number of blocks
917 +                                WriteMacInt32(adr + 4, 0);                                                      // heads/track/sectors
918 +                                return noErr;
919 +                        } else
920 +                                return paramErr;
921 +
922                  case 8:                 // DriveStatus
923                          Mac2Mac_memcpy(pb + csParam, info->status, 22);
924                          return noErr;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines