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.8 by cebix, 2000-07-24T20:39:33Z 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                  // Not a partition map block? Then look at next block
# Line 192 | Line 193 | static void find_hfs_partition(DriveInfo
193  
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 = 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 205 | 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 233 | 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 251 | 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 272 | Line 273 | static bool position2msf(DriveInfo *info
273  
274   void CDROMInit(void)
275   {
275        first_drive_info = NULL;
276
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;
288 <                        info->fh = fh;
289 <                        DriveInfo *p = (DriveInfo *)&first_drive_info;
290 <                        while (p->next != NULL)
291 <                                p = p->next;
292 <                        p->next = info;
293 <                }
285 >                if (fh)
286 >                        drives.push_back(cdrom_drive_info(fh));
287          }
288   }
289  
# Line 301 | 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);
308 <                next = info->next;
309 <                delete info;
310 <                info = next;
311 <        }
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 318 | 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 342 | 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 362 | Line 352 | static void mount_mountable_volumes(void
352                          Execute68kTrap(0xa02f, &r);             // PostEvent()
353                          info->to_be_mounted = false;
354                  }
365
366                info = info->next;
355          }
356   }
357  
# Line 381 | 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 411 | 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 436 | 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 503 | 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 535 | 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 675 | Line 665 | int16 CDROMControl(uint32 pb, uint32 dce
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 692 | 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 734 | 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 779 | 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 857 | 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);
# Line 874 | Line 864 | int16 CDROMStatus(uint32 pb, uint32 dce)
864                                          WriteMacInt32(pb + csParam + 4, FOURCC('c','d','r','m'));
865                                          break;
866                                  case FOURCC('i','n','t','f'):   // Interface type
867 <                                        WriteMacInt32(pb + csParam + 4, FOURCC('b','a','s','i'));
867 >                                        WriteMacInt32(pb + csParam + 4, EMULATOR_ID_4);
868                                          break;
869                                  case FOURCC('s','y','n','c'):   // Only synchronous operation?
870                                          WriteMacInt32(pb + csParam + 4, 0x01000000);
871                                          break;
872                                  case FOURCC('b','o','o','t'):   // Boot ID
873 <                                        if (info != NULL)
873 >                                        if (info != drives.end())
874                                                  WriteMacInt16(pb + csParam + 4, info->num);
875                                          else
876                                                  WriteMacInt16(pb + csParam + 4, 0);
# Line 909 | 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