Previous 199869 Revisions Next

r22066 Sunday 24th March, 2013 at 23:58:53 UTC by Carl
(mess) psxcd: simplify the cdrom [Carl]
---
I haven't found any regressions but I wouldn't be surprised to see some.  The only improvements so far is better CD audio and disk change support.
[src/emu/imagedev]chd_cd.c chd_cd.h
[src/mess]mess.mak
[src/mess/drivers]psx.c
[src/mess/machine]psxcd.c psxcd.h psxcddrv.c psxcddrv.h

trunk/src/emu/imagedev/chd_cd.c
r22065r22066
3030{
3131}
3232
33cdrom_image_device::cdrom_image_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
34   : device_t(mconfig, type, name,  tag, owner, clock),
35      device_image_interface(mconfig, *this)
36{
37}
3338//-------------------------------------------------
3439//  cdrom_image_device - destructor
3540//-------------------------------------------------
trunk/src/emu/imagedev/chd_cd.h
r22065r22066
3131public:
3232   // construction/destruction
3333   cdrom_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
34   cdrom_image_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
3435   virtual ~cdrom_image_device();
3536
3637   // image-level overrides
trunk/src/mess/machine/psxcddrv.c
r22065r22066
1#include "emu.h"
2#include "psxcd.h"
3#include "psxcddrv.h"
4
5//#define debug_mess_driver
6
7//
8//
9//
10
11static const unsigned int   num_pf_sectors=32, num_pf_buffers=16;
12
13//
14//
15//
16
17cdrom_driver::cdrom_driver()
18{
19   pf_head = 0;
20   pf_tail = 0;
21   num_pf = 0;
22   pf_head_sector = 0;
23   pf_status = NULL;
24   native_sector_size = raw_sector_size;
25   last_pf_status = NULL;
26   m_cd = NULL;
27   m_machine = NULL;
28
29//  printf("cdrom_driver base class init, pf_buffer size is %d\n", num_pf_sectors*num_pf_buffers*raw_sector_size);
30
31   pf_buffer=new unsigned char [num_pf_sectors*num_pf_buffers*raw_sector_size];
32
33   timestamp_frequency = 1;
34}
35
36cdrom_driver::~cdrom_driver()
37{
38   global_free(pf_buffer);
39}
40
41//
42//
43//
44
45void cdrom_driver::set_native_sector_size(const unsigned int sz)
46{
47   native_sector_size=sz;
48}
49
50//
51//
52//
53
54void cdrom_driver::cancel_io()
55{
56   if (pf_status)
57   {
58      pf_status->cancel();
59      pf_status->release();
60   }
61
62   pf_status=NULL;
63}
64
65//
66//
67//
68
69void cdrom_driver::prefetch_sector(const unsigned int sec)
70{
71   int numpfsec=num_pf*num_pf_sectors,
72         pfsec=sec-pf_head_sector;
73
74//  printf("prefetch_sector: %d\n", sec);
75
76   if ((pfsec<0) || (pfsec>numpfsec))
77   {
78      // Sector is not in prefetch buffer, abort current prefetch
79
80      if (pf_status)
81      {
82         pf_status->cancel();
83         pf_status->release();
84      }
85
86      // Reset the buffer and begin a new prefetch
87
88      pf_head=0;
89      pf_tail=0;
90      num_pf=1;
91      pf_head_sector=sec;
92
93      last_pf_status=NULL;
94      pf_status=read_sectors(sec, num_pf_sectors, pf_buffer);
95   }
96}
97
98//
99//
100//
101
102bool cdrom_driver::is_prefetch_sector_loaded(const unsigned int sec)
103{
104   int numpfsec=num_pf*num_pf_sectors,
105         pfsec=sec-pf_head_sector;
106
107   if ((pfsec<0) || (pfsec>=numpfsec))
108   {
109      // Requested sector is not in prefetch buffer, begin a new prefetch
110
111      prefetch_sector(sec);
112      pfsec=sec-pf_head_sector;
113      numpfsec=num_pf*num_pf_sectors;
114   }
115
116   int blk=pfsec/num_pf_sectors;
117
118   if (blk>0)
119   {
120      // Discard blocks below the prefetch point
121
122      pf_head=(pf_head+blk)%num_pf_buffers;
123      pf_head_sector+=num_pf_sectors*blk;
124      pfsec-=num_pf_sectors*blk;
125      num_pf-=blk;
126      blk=0;
127   }
128
129   bool comp=((! pf_status) || (pf_status->complete()));
130
131   if (! comp)
132   {
133      INT64 curtime=m_machine->device<cpu_device>("maincpu")->total_cycles();
134
135      if (last_pf_status!=pf_status)
136      {
137         last_pf_status=pf_status;
138         pf_timeout_begin=curtime;
139      }
140
141      INT64 timeout=curtime-pf_timeout_begin;
142      int timeout_sec=(int)(timeout/timestamp_frequency);
143      if (timeout_sec>20)
144      {
145         printf("cdrom: prefetch timed out, trying again...\n");
146         num_pf=0;
147         pf_head_sector=-1;
148         prefetch_sector(sec);
149         return is_prefetch_sector_loaded(sec);
150      }
151   }
152
153   if ((num_pf<num_pf_buffers) && (comp))
154   {
155      // The prefetch buffer is not full and we are not waiting on IO,
156      // prefetch the next block
157
158      pf_tail=(pf_tail+1)%num_pf_buffers;
159      num_pf++;
160
161      int nxtsec=pf_head_sector+((num_pf-1)*num_pf_sectors);
162      unsigned char *ptr=pf_buffer+((pf_tail*num_pf_sectors)*native_sector_size);
163
164      if (pf_status)
165      {
166         pf_status->release();
167         pf_status=last_pf_status=NULL;
168      }
169
170      pf_status=read_sectors(nxtsec, num_pf_sectors, ptr);
171   }
172
173   if (blk==(num_pf-1))
174   {
175      // The sector we want is in the last block in the prefetch buffer
176      // which might still be loading, check if the sector we want is loaded
177#if 0 // we do not load async in MESS
178      INT64 trans=pf_status->bytes_transferred();
179      unsigned int secmod=pfsec%num_pf_sectors,
180                           needbytes=(secmod+1)*native_sector_size;
181
182      if (trans<needbytes)
183      {
184         // The sector is not loaded yet
185
186         return false;
187      } else
188#endif
189      {
190         // The sector is loaded
191
192         return true;
193      }
194   } else
195   {
196      // The sector is not in the last block so it must be loaded
197
198      return true;
199   }
200}
201
202//
203//
204//
205
206unsigned char *cdrom_driver::get_prefetch_sector(const unsigned int sec, unsigned int *sz)
207{
208   int numpfsec=num_pf*num_pf_sectors,
209         pfsec=sec-pf_head_sector;
210   if ((pfsec>=0) && (pfsec<numpfsec))
211   {
212      int blk=(pf_head+(pfsec/num_pf_sectors))%num_pf_buffers,
213            off=((blk*num_pf_sectors)+(pfsec%num_pf_sectors))*native_sector_size;
214      *sz=native_sector_size;
215      return pf_buffer+off;
216   } else
217   {
218      return NULL;
219   }
220}
221
222//
223//
224//
225
226bool cdrom_driver::read_sector(const unsigned int sec, unsigned char *buf, const bool block)
227{
228   bool loaded=is_prefetch_sector_loaded(sec);
229
230//  printf("read_sector: %d (loaded=%c)\n", sec, loaded ? 'Y' : 'N');
231
232   if ((! loaded) && (block))
233   {
234      pf_status->block_until_complete();
235      loaded=true;
236   }
237
238   if (loaded)
239   {
240      unsigned int secsz=0;
241      unsigned char *ptr=get_prefetch_sector(sec,&secsz);
242      assert(ptr);
243
244//      printf("got sector %d @ %p, size %d = %02x %02x | %02x %02x\n", sec, ptr, secsz, ptr[0], ptr[1], ptr[0x20], ptr[0x21]);
245
246      if (secsz<2352)
247      {
248         // Add sector header
249
250         buf[0]=0;
251         memset(buf+1,0xff,10);
252         buf[11]=0;
253         sector_to_msf(sec,buf+12);
254         buf[12]=decimal_to_bcd(buf[12]);
255         buf[13]=decimal_to_bcd(buf[13]);
256         buf[14]=decimal_to_bcd(buf[14]);
257         buf[15]=2;
258
259         if (secsz<2336)
260         {
261            memset(buf+16,0xff,8);
262         }
263      }
264
265      switch (secsz)
266      {
267         case 2048:
268            memcpy(buf+24,ptr,2048);
269            break;
270
271         case 2336:
272            memcpy(buf+16,ptr,2336);
273            break;
274
275         case 2352:
276            memcpy(buf,ptr,raw_sector_size);
277            break;
278      }
279
280      return true;
281   } else
282   {
283      return false;
284   }
285}
286
287void cdrom_driver::set_machine(const running_machine &machine)
288{
289   m_machine = (running_machine *)&machine;
290
291   timestamp_frequency = m_machine->device<cpu_device>("maincpu")->clock();
292
293//  printf("cdrom_driver::set_machine: timestamp frequency = %d\n", timestamp_frequency);
294}
295
296/*
297    MAME/MESS driver implementation
298*/
299
300class mess_cdrom_driver : public cdrom_driver
301{
302   enum track_type
303   {
304      track_illegal=-1,
305      track_mode1_2048=0,
306      track_mode2_2352,
307      track_mode2_2336,
308      track_audio
309   };
310
311   struct toc_entry
312   {
313      unsigned int type;
314      unsigned char address[3];
315   };
316
317   int num_sectors, num_tracks;
318   toc_entry toc[100];
319   int bin_sector_size;
320   //const char *err;
321
322   io_status *read_sectors(const unsigned int startsec, const unsigned int numsec, unsigned char *buf);
323
324public:
325   mess_cdrom_driver();
326   ~mess_cdrom_driver();
327
328   bool is_usable(char *error_msg, const int msglen) const
329   {
330      return true;
331   }
332
333   bool read_toc();
334   unsigned int get_first_track() const;
335   unsigned int get_num_tracks() const;
336   bool get_track_address(const unsigned int track,unsigned char *address) const;
337   tracktype get_track_type(const unsigned int track) const;
338   unsigned int find_track(const unsigned int sector, unsigned int *start_sector, unsigned int *end_sector) const;
339   cdromtype get_type() const;
340};
341
342mess_cdrom_driver::mess_cdrom_driver()
343   //: err(NULL)
344{
345   for (int i=0; i<100; i++)
346      toc[i].type=track_illegal;
347   num_tracks=0;
348   num_sectors=0;
349}
350
351//
352//
353//
354
355mess_cdrom_driver::~mess_cdrom_driver()
356{
357   cancel_io();
358}
359
360//
361//
362//
363
364bool mess_cdrom_driver::read_toc()
365{
366   if (m_cd)
367   {
368      const cdrom_toc *toc = cdrom_get_toc(m_cd);
369
370      num_tracks = cdrom_get_last_track(m_cd);
371
372      switch (toc->tracks[0].trktype)
373      {
374         case CD_TRACK_MODE1: bin_sector_size=2048; break;
375         case CD_TRACK_MODE2_FORM1: bin_sector_size=2048; break;
376         case CD_TRACK_MODE2: bin_sector_size=2336; break;
377         case CD_TRACK_MODE2_FORM_MIX: bin_sector_size=2336; break;
378         default: bin_sector_size=2352; break;
379      }
380
381      set_native_sector_size(bin_sector_size);
382      num_sectors = cdrom_get_track_start(m_cd, num_tracks) + toc->tracks[num_tracks].frames;
383
384//      printf("mess_cdrom_driver: %d sectors, native size %d\n",num_sectors, bin_sector_size);
385
386      return true;
387   }
388
389   return false;
390}
391
392//
393//
394//
395
396io_status *mess_cdrom_driver::read_sectors(const unsigned int startsec, const unsigned int numsec, unsigned char *buf)
397{
398   const cdrom_toc *toc = cdrom_get_toc(m_cd);
399   UINT32 track = cdrom_get_track(m_cd, startsec);
400   UINT32 secsize = toc->tracks[track].datasize;
401
402   #ifdef debug_mess_driver
403   printf("mess: read %d sectors from %d (secsize %d)\n",numsec,startsec,secsize);
404   #endif
405
406   if (1) // && ((int)startsec<num_sectors))
407   {
408//      fin->seek((INT64)startsec*(INT64)bin_sector_size);
409
410//      io_status *ios=fin->async_read(buf,numsec*bin_sector_size);
411//      if (! ios)
412      for (int i = 0; i < numsec; i++)
413      {
414//          printf("[%d/%d] Reading to pf_buffer %p at offset %d, size %d\n", i, numsec, &buf[secsize*i], secsize*i, secsize);
415         cdrom_read_data(m_cd, startsec+i, &buf[secsize*i], CD_TRACK_RAW_DONTCARE);
416      }
417
418      return NULL;
419
420//      return ios;
421   }
422   else
423   {
424      printf("mess: read sector out of range (%d, max=%d)\n",
425                  startsec,
426                  num_sectors);
427
428      memset(buf,0xff,numsec*bin_sector_size);
429      return NULL;
430   }
431}
432
433//
434//
435//
436
437unsigned int mess_cdrom_driver::get_first_track() const
438{
439   return 1;
440}
441
442unsigned int mess_cdrom_driver::get_num_tracks() const
443{
444//  printf("get_num_tracks = %d\n", num_tracks);
445   return num_tracks;
446}
447
448bool mess_cdrom_driver::get_track_address(const unsigned int track, unsigned char *address) const
449{
450   if ((track>=1) && ((int)track<=num_tracks))
451   {
452      UINT32 trkstart = cdrom_get_track_start(m_cd, track);
453
454      sector_to_msf(trkstart, address);
455
456      address[0] = address[0];
457      address[1] = address[1];
458      address[2] = address[2];
459
460//      printf("get_track_address %d = %02x:%02x:%02x\n", track, address[0], address[1], address[2]);
461
462      return true;
463   }
464   else
465   {
466      address[0]=address[1]=address[2]=0;
467      return false;
468   }
469}
470
471unsigned int mess_cdrom_driver::find_track(const unsigned int sector, unsigned int *start_sector, unsigned int *end_sector) const
472{
473   const cdrom_toc *toc = cdrom_get_toc(m_cd);
474   UINT32 track = cdrom_get_track(m_cd, sector);
475   int start;
476
477   start = cdrom_get_track_start(m_cd, track);
478
479   if (start_sector != NULL)
480   {
481      *start_sector = start;
482   }
483
484   if (end_sector != NULL)
485   {
486      *end_sector = start + toc->tracks[track].frames;
487   }
488
489   printf("find_track: track %d start %d end %d\n", track, start, start + toc->tracks[track].frames);
490
491   return -1;
492}
493
494//
495//
496//
497
498cdromtype mess_cdrom_driver::get_type() const
499{
500//  printf("get_type\n");
501   return cdromtype_cd;
502}
503
504//
505//
506//
507
508tracktype mess_cdrom_driver::get_track_type(const unsigned int track) const
509{
510   const cdrom_toc *toc = cdrom_get_toc(m_cd);
511
512//  printf("get_track_type %d = %d\n", track, toc->tracks[track].trktype);
513
514   switch (toc->tracks[track].trktype)
515   {
516      case CD_TRACK_MODE1: return tracktype_mode1;
517      case CD_TRACK_MODE2_RAW: return tracktype_mode2;
518      case CD_TRACK_MODE2_FORM_MIX: return tracktype_mode2;
519      case CD_TRACK_AUDIO: return tracktype_audio;
520      default: return tracktype_unknown;
521   }
522}
523
524//
525//
526//
527
528cdrom_driver *open_mess_drv()
529{
530   return new mess_cdrom_driver();
531}
trunk/src/mess/machine/psxcddrv.h
r22065r22066
1#ifndef _included_psxcddriver_
2#define _included_psxcddriver_
3
4const unsigned int raw_sector_size=2352;
5
6class io_status
7{
8protected:
9   virtual ~io_status() {}
10
11public:
12   io_status() { }
13
14   virtual void cancel()=0;
15   virtual void release()=0;
16   virtual bool complete() const=0;
17   virtual bool block_until_complete() const=0;
18   virtual INT64 bytes_transferred() const=0;
19};
20
21enum cdromtype
22{
23   cdromtype_cd=0,
24   cdromtype_dvd
25};
26
27enum tracktype
28{
29   tracktype_unknown=0,
30   tracktype_mode1,
31   tracktype_mode2,
32   tracktype_audio
33};
34
35class cdrom_driver
36{
37   int pf_head,
38         pf_tail,
39         num_pf,
40         pf_head_sector;
41   unsigned char *pf_buffer;
42   io_status *pf_status,
43                  *last_pf_status;
44   INT64 pf_timeout_begin;
45
46   int native_sector_size;
47
48   virtual io_status *read_sectors(const unsigned int sec, const unsigned int numsec, unsigned char *buf)=0;
49
50   bool is_prefetch_sector_loaded(const unsigned int pfsec);
51
52protected:
53   void cancel_io();
54   void set_native_sector_size(const unsigned int sz);
55   UINT32 timestamp_frequency;
56   cdrom_file  *m_cd;
57private:
58   running_machine *m_machine;
59
60public:
61   cdrom_driver();
62   virtual ~cdrom_driver();
63
64   void set_machine(const running_machine &machine);
65   void set_cdrom_file(cdrom_file *cdfile) { m_cd = cdfile; }
66
67   virtual bool is_usable(char *error_msg=NULL, const int msglen=0) const=0;
68   virtual bool read_toc()=0;
69
70   void prefetch_sector(const unsigned int sec);
71   bool read_sector(const unsigned int sec,
72                              unsigned char *buf,
73                              const bool block=true);
74   unsigned char *get_prefetch_sector(const unsigned int pfsec,
75                                                         unsigned int *sz);
76
77   virtual unsigned int get_first_track() const=0;
78   virtual unsigned int get_num_tracks() const=0;
79   virtual bool get_track_address(const unsigned int track,
80                                                   unsigned char *address) const=0;
81   virtual tracktype get_track_type(const unsigned int track) const=0;
82   virtual unsigned int find_track(const unsigned int sector,
83                                                   unsigned int *start_sector=NULL,
84                                                   unsigned int *end_sector=NULL) const=0;
85
86   virtual cdromtype get_type() const { return cdromtype_cd; }
87};
88
89//
90//
91//
92
93inline unsigned int msf_to_sector(const unsigned char *msf)
94{
95   unsigned int sec=msf[2]+(msf[1]*75)+(msf[0]*(60*75));
96   if (sec>=150)
97   {
98      return sec-150;
99   }
100   else
101   {
102      return 0;
103   }
104}
105
106inline void sector_to_msf(const unsigned int sec, unsigned char *msf)
107{
108   unsigned int s=sec+150;
109   msf[0]=s/(60*75);
110   s-=msf[0]*(60*75);
111   msf[1]=s/75;
112   s-=msf[1]*75;
113   msf[2]=s;
114}
115
116//
117//
118//
119
120inline unsigned char bcd_to_decimal(const unsigned char bcd)
121{
122   return ((bcd>>4)*10)+(bcd&0xf);
123}
124
125inline unsigned char decimal_to_bcd(const unsigned char dec)
126{
127   //assert(dec<100);
128   return ((dec/10)<<4)|(dec%10);
129}
130
131cdrom_driver *open_mess_drv();
132
133#endif
trunk/src/mess/machine/psxcd.c
r22065r22066
1
21#include "emu.h"
32#include "psxcd.h"
43#include "debugger.h"
r22065r22066
1110//#define debug_cdrom_registers
1211//#define skip_reads
1312//#define dump_subheader
14//#define disable_xa_prefetch
15//#define disable_cdda_prefetch
1613
1714//
1815//
r22065r22066
2320   event_cmd_complete=0,
2421   event_preread_sector,
2522   event_read_sector,
26   event_play_sector
23   event_play_sector,
24   event_change_disk
2725};
2826
2927//
r22065r22066
8987//
9088//
9189
92static const unsigned int max_xa_prefetch_distance=32,
93                                       max_cdda_prefetch_distance=32;
94
9590//**************************************************************************
9691//  DEVICE DEFINITIONS
9792//**************************************************************************
9893
9994const device_type PSXCD = &device_creator<psxcd_device>;
10095
101void psxcd_device::static_set_devname(device_t &device, const char *devname)
96static struct cdrom_interface psx_cdrom =
10297{
103   psxcd_device &psxcd = downcast<psxcd_device &>(device);
104   psxcd.m_devname = devname;
105}
98   "psx_cdrom",
99   NULL
100};
106101
107102psxcd_device::psxcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
108   device_t(mconfig, PSXCD, "PSXCD", tag, owner, clock),
103   cdrom_image_device(mconfig, PSXCD, "Cdrom", tag, owner, clock),
109104   m_irq_handler(*this)
110105{
106   static_set_static_config(*this, &psx_cdrom);
111107}
112108
109
113110void psxcd_device::device_start()
114111{
112   cdrom_image_device::device_start();
115113   m_irq_handler.resolve_safe();
116114
117115   m_maincpu = machine().device<cpu_device>("maincpu");
r22065r22066
134132   sectail = 0;
135133   secin = 0;
136134   secskip = 0;
137   next_read_event = NULL;
135   next_read_event = -1;
138136   cbp = cmdbuf;
139137   first_open = true;
140138
r22065r22066
144142   ir=0;
145143   mode=0;
146144
147   driver = NULL;
148
149145   for (int i = 0; i < MAX_PSXCD_TIMERS; i++)
150146   {
151      m_timers[i] = timer_alloc(i, NULL);
147      m_timers[i] = timer_alloc(i);
152148      m_timerinuse[i] = false;
153149   }
154150
155   for(int i = 0; i < 3; ++i)
156      curpos[i] = 0;
151   curpos.w = 0;
152   m_param_count = 0;
157153}
158154
159155//
r22065r22066
170166      m_timerinuse[i] = false;
171167   }
172168
173   m_cddevice = machine().device<cdrom_image_device>(m_devname);
174   if (m_cddevice)
169   if(cur_res)
175170   {
176      m_cd = m_cddevice->get_cdrom_file();
177
178      if (m_cd)
179      {
180//          printf("psxcd: found disc!\n");
181         driver = open_mess_drv();
182         driver->set_machine(machine());
183         driver->set_cdrom_file(m_cd);
184      }
185      else
186      {
187         driver = NULL;
188//          printf("psxcd: Found device, but no disc\n");
189      }
171      global_free(cur_res);
172      cur_res = NULL;
190173   }
191   else
174
175   while(res_queue)
192176   {
193      driver = NULL;
194//      printf("psxcd: Device [%s] not found!\n", m_devname);
177      cur_res = res_queue->next;
178      global_free(res_queue);
179      res_queue = cur_res;
195180   }
196181
182   m_param_count = 0;
197183}
198184
199185//
200186//
201187//
202188
189bool psxcd_device::call_load()
190{
191   bool ret = cdrom_image_device::call_load();
192   open = true;
193   if(ret == IMAGE_INIT_PASS)
194      add_system_event(event_change_disk, m_sysclock, NULL); // 1 sec to spin up the disk
195   return ret;
196}
197
198void psxcd_device::call_unload()
199{
200   stop_read();
201   cdrom_image_device::call_unload();
202   open = true;
203   send_result(intr_diskerror);
204}
205
203206READ8_MEMBER( psxcd_device::read )
204207{
205208   unsigned char ret = 0;
r22065r22066
320323         if (cmdmode==0)
321324         {
322325            *cbp++=data;
326            m_param_count++;
323327         } else
324328         {
325329            // ?flush buffer?
r22065r22066
349353            }
350354            ir=0;
351355         }
352         break;
353356   }
354357}
355358
r22065r22066
396399{
397400   assert(byte<num_commands);
398401   (this->*cmd_table[byte].func)();
402   m_param_count = 0;
399403}
400404
401405//
r22065r22066
412416   send_result(intr_acknowledge);
413417}
414418
415static int open_nops=0;
419static int open_nops=10;
416420
417421void psxcd_device::cdcmd_nop()
418422{
r22065r22066
422426
423427   //stop_read();
424428
425   if ((! open) && (driver))
429   if (!open)
426430   {
427      if (open_nops==0)
428      {
429         open=driver->read_toc();
430      } else
431      {
431      if (open_nops!=0)
432432         open_nops--;
433      }
434433   }
435434
436435   send_result(intr_complete);
r22065r22066
447446
448447   stop_read();
449448
450   unsigned char l[3];
451   l[0]=bcd_to_decimal(cmdbuf[0]);
452   l[1]=bcd_to_decimal(cmdbuf[1]);
453   l[2]=bcd_to_decimal(cmdbuf[2]);
454449
455   if ((l[0]>0) || (l[1]>=2))
456   {
457      loc[0]=l[0];
458      loc[1]=l[1];
459      loc[2]=l[2];
460   } else
461   {
462      printf("setloc out of range: %02d:%02d:%02d\n",
463                  l[0],l[1],l[2]);
464   }
450   CDPOS l;
451   l.b[M]=bcd_to_decimal(cmdbuf[0]);
452   l.b[S]=bcd_to_decimal(cmdbuf[1]);
453   l.b[F]=bcd_to_decimal(cmdbuf[2]);
465454
455   if ((l.b[M]>0) || (l.b[S]>=2))
456      loc.w=l.w;
457   else
458      logerror("setloc out of range: %02d:%02d:%02d\n",l.b[M],l.b[S],l.b[F]);
459
466460   send_result(intr_complete);
467461}
468462
469463void psxcd_device::cdcmd_play()
470464{
471   #ifdef debug_cdrom
472      printf("cdrom: play %02x %02x %02x => %d\n", loc[0], loc[1], loc[2], msf_to_sector(loc));
473   #endif
465   if(cmdbuf[0] && m_param_count)
466       loc.w = lba_to_msf_ps(cdrom_get_track_start(m_cdrom_handle, bcd_to_decimal(cmdbuf[0]) - 1));
474467
475   curpos[0]=loc[0];
476   curpos[1]=loc[1];
477   curpos[2]=loc[2];
468   curpos.w = loc.w;
469   if (!curpos.w)
470      curpos.b[S] = 2;
478471
479   if ((curpos[0]==0) &&
480         (curpos[1]==0) &&
481         (curpos[2]==0))
482   {
483      send_result(intr_acknowledge);
484   } else
485   {
486      stop_read();
487      start_play();
488      send_result(intr_acknowledge);
489   }
472#ifdef debug_cdrom
473   printf("cdrom: play %02x %02x %02x => %d\n", loc.b[M], loc.b[S], loc.b[F], msf_to_lba_ps(loc.w));
474#endif
475
476   stop_read();
477   start_play();
478   send_result(intr_complete);
490479}
491480
492481void psxcd_device::cdcmd_forward()
r22065r22066
505494
506495void psxcd_device::cdcmd_readn()
507496{
508   if (driver)
497   if(!open)
509498   {
510499      #ifdef debug_cdrom
511500         printf("cdrom: readn\n");
512501      #endif
513502
514      curpos[0]=loc[0];
515      curpos[1]=loc[1];
516      curpos[2]=loc[2];
503      curpos.w=loc.w;
517504
518505      stop_read();
519506      start_read();
520507      send_result(intr_complete);
521508   } else
522509   {
523      printf("read without driver\n");
524510      send_result(intr_diskerror);
525511   }
526512}
r22065r22066
653639   send_result(intr_complete,data,6);
654640}
655641
656#if 0
657static void add_loc(unsigned char *dst, const unsigned char *src1, const unsigned char *src2)
642UINT32 psxcd_device::sub_loc(CDPOS src1, CDPOS src2)
658643{
659   int f=src1[2]+src2[2],
660         s=src1[1]+src2[1],
661         m=src1[0]+src2[0];
662   while (f>=75) { s++; f-=75; }
663   while (s>=60) { m++; s-=60; }
664
665   dst[0]=m;
666   dst[1]=s;
667   dst[2]=f;
668}
669#endif
670static void sub_loc(unsigned char *dst, const unsigned char *src1, const unsigned char *src2)
671{
672   int f=src1[2]-src2[2],
673         s=src1[1]-src2[1],
674         m=src1[0]-src2[0];
644   CDPOS dst;
645   int f=src1.b[F]-src2.b[F],
646         s=src1.b[S]-src2.b[S],
647         m=src1.b[M]-src2.b[M];
675648   while (f<0) { s--; f+=75; }
676649   while (s<0) { m--; s+=60; }
677650
678651   if (m<0)
679652      m=s=f=0;
680653
681   dst[0]=m;
682   dst[1]=s;
683   dst[2]=f;
654   dst.b[M]=m;
655   dst.b[S]=s;
656   dst.b[F]=f;
657
658   return dst.w;
684659}
685660
686661void psxcd_device::cdcmd_getlocl()
r22065r22066
706681
707682void psxcd_device::cdcmd_getlocp()
708683{
709   unsigned char tloc[3],
710                        twosec[3]={ 0,2,0 };
711   sub_loc(tloc,loc,twosec);
684   CDPOS tloc, start;
685   UINT8 track = cdrom_get_track(m_cdrom_handle, msf_to_lba_ps(loc.w) + 150) + 1;
686   start.w = (track == 1) ? 0x000200 : lba_to_msf_ps(cdrom_get_track_start(m_cdrom_handle, track - 1));
687   tloc.w = sub_loc(loc, start);
712688
713689   unsigned char data[8]=
714690   {
715      0x01,                           // track
691      decimal_to_bcd(track),                          // track
716692      0x01,                           // index
717      decimal_to_bcd(tloc[0]),    // min
718      decimal_to_bcd(tloc[1]),    // sec
719      decimal_to_bcd(tloc[2]),    // frame
720      decimal_to_bcd(loc[0]), // amin
721      decimal_to_bcd(loc[1]), // asec
722      decimal_to_bcd(loc[2])  // aframe
693      decimal_to_bcd(tloc.b[M]),    // min
694      decimal_to_bcd(tloc.b[S]),    // sec
695      decimal_to_bcd(tloc.b[F]),    // frame
696      decimal_to_bcd(loc.b[M]), // amin
697      decimal_to_bcd(loc.b[S]), // asec
698      decimal_to_bcd(loc.b[F])  // aframe
723699   };
724700
725701   //unsigned char data[8]={ 2,1,0,0xff,0xff,0xff,0xff,0xff };
r22065r22066
750726      printf("cdrom: gettn\n");
751727   #endif
752728
753   assert(driver);
754729
755   unsigned char data[3]=
730   if(!open)
756731   {
757      status,
758      decimal_to_bcd(driver->get_first_track()),
759      decimal_to_bcd(driver->get_num_tracks())
760   };
732      unsigned char data[3]=
733      {
734            status,
735            decimal_to_bcd(1),
736            decimal_to_bcd(cdrom_get_last_track(m_cdrom_handle))
737      };
761738
762   //stop_read();
763   send_result(intr_acknowledge,data,3);
739      //stop_read();
740      send_result(intr_complete,data,3);
741   }
742   else
743      send_result(intr_diskerror);
764744}
765745
766746void psxcd_device::cdcmd_gettd()
767747{
768   unsigned char addr[3];
769   driver->get_track_address(bcd_to_decimal(cmdbuf[0]), addr);
770
771   unsigned char data[3]=
748   UINT8 track = bcd_to_decimal(cmdbuf[0]);
749   UINT8 last = cdrom_get_last_track(m_cdrom_handle);
750   if(track <= last)
772751   {
773      status,
774      decimal_to_bcd(addr[0]),
775      decimal_to_bcd(addr[1])
776   };
752      CDPOS trkstart;
753      if(!track) // length of disk
754         trkstart.w = lba_to_msf_ps(cdrom_get_track_start(m_cdrom_handle, 0xaa));
755      else
756         trkstart.w = lba_to_msf_ps(cdrom_get_track_start(m_cdrom_handle, track - 1));
777757
778   #ifdef debug_cdrom
779      printf("cdrom: gettd %02x [%02x %02x %02x]\n",
780                                       cmdbuf[0],
781                                       data[0],
782                                       data[1],
783                                       data[2]);
784   #endif
758      unsigned char data[3]=
759      {
760         status,
761         decimal_to_bcd(trkstart.b[M]),
762         decimal_to_bcd(trkstart.b[S])
763      };
785764
786   //stop_read();
787   send_result(intr_acknowledge,data,3);
765      #ifdef debug_cdrom
766         printf("cdrom: gettd %02x [%02x %02x %02x]\n",
767                                          cmdbuf[0],
768                                          data[0],
769                                          data[1],
770                                          data[2]);
771      #endif
772
773      //stop_read();
774      send_result(intr_acknowledge,data,3);
775   }
776   else
777   {
778      status |= status_error;
779      send_result(intr_diskerror);
780   }
788781}
789782
790783void psxcd_device::cdcmd_seekl()
791784{
792785   #ifdef debug_cdrom
793      printf("cdrom: seekl [%02d:%02d:%02d]\n",loc[0],loc[1],loc[2]);
786      printf("cdrom: seekl [%02d:%02d:%02d]\n",loc.b[M],loc.b[S],loc.b[F]);
794787   #endif
795788
796   curpos[0]=loc[0];
797   curpos[1]=loc[1];
798   curpos[2]=loc[2];
789   curpos.w=loc.w;
799790
800791   send_result(intr_acknowledge);
801792}
r22065r22066
806797      printf("cdrom: seekp\n");
807798   #endif
808799
809   curpos[0]=loc[0];
810   curpos[1]=loc[1];
811   curpos[2]=loc[2];
800   curpos.w=loc.w;
812801
813802   send_result(intr_acknowledge);
814803}
r22065r22066
836825      printf("cdrom: id\n");
837826   #endif
838827
839   if (! open)
828   if (!open)
840829   {
841      if (driver)
842         open=driver->read_toc();
843   }
830      static unsigned char gamedata[8] = { 0x00, 0x00, 0x00, 0x00, 'S', 'C', 'E', 'A' };
831      static unsigned char audiodata[8] = { 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // drops into the audio CD player.  08 80 goes to the menu.
844832
845   if (open)
846   {
847      static unsigned char gamedata[8] = { 0x08, 0x00, 0x00, 0x00, 'S', 'C', 'E', 'A' };
848      static unsigned char audiodata[8] = { 0x08, 0x90, 0x00, 0x00, 'S', 'C', 'E', 'A' }; // drops into the audio CD player.  08 80 goes to the menu.
849
850      if (cdrom_get_track_type(m_cd, 0) == CD_TRACK_AUDIO)
833      if (cdrom_get_track_type(m_cdrom_handle, 0) == CD_TRACK_AUDIO)
851834      {
835         audiodata[0] = status | 8;
852836         send_result(intr_acknowledge,audiodata,8);
853837      }
854838      else
855839      {
840         gamedata[0] = status;
856841         send_result(intr_acknowledge,gamedata,8);
857842      }
858843   } else
r22065r22066
864849
865850void psxcd_device::cdcmd_reads()
866851{
867   curpos[0]=loc[0];
868   curpos[1]=loc[1];
869   curpos[2]=loc[2];
852   curpos.w=loc.w;
870853
871854   #ifdef skip_reads
872855      #ifdef debug_cdrom
r22065r22066
961944//
962945//
963946
964event *psxcd_device::send_result(const unsigned int res,
947void psxcd_device::send_result(const unsigned int res,
965948                                          const unsigned char *data,
966949                                          const unsigned int sz,
967950                                             const unsigned int delay)
968951{
969952   // Update shell open status
970953
971   if (! open)
954   if (open)
972955   {
973956      status=status_error|status_shellopen;
974957   }
r22065r22066
978961         status=status_standby;
979962   }
980963
981   // Prepare event
982964
983   event *ev=new event;
984   ev->t=delay;
985   ev->type=event_cmd_complete;
965   command_result *cr=global_alloc(command_result);
986966
987   command_result *cr=(command_result *)ev->data;
988
989967   cr->res=res;
990968   if (sz)
991969   {
r22065r22066
997975      cr->data[0]=status;
998976      cr->sz=1;
999977   }
978   status &= ~status_error;
1000979
1001980   // Avoid returning results after sector read results -
1002981   // delay the sector read slightly if necessary
1003982
1004983   UINT64 systime = m_maincpu->total_cycles();
1005   if ((next_read_event) && ((systime+ev->t)>(next_sector_t)))
984   if ((next_read_event != -1) && ((systime+delay)>(next_sector_t)))
1006985   {
1007986      UINT32 hz = m_sysclock / (delay + 2000);
1008      next_read_event->timer->adjust(attotime::from_hz(hz), 0, attotime::never);
1009
1010      for (int i = 0; i < MAX_PSXCD_TIMERS; i++)
1011      {
1012         if (m_eventfortimer[i] == next_read_event)
1013         {
1014            printf("Adjusting timer %d to %d hz]n", i, hz);
1015         }
1016      }
987      m_timers[next_read_event]->adjust(attotime::from_hz(hz), 0, attotime::never);
1017988   }
1018989
1019   add_system_event(ev);
1020   return ev;
990   add_system_event(event_cmd_complete, delay, (void *)cr);
1021991}
1022992
1023993//
r22065r22066
1028998{
1029999   if ((int)size>secleft)
10301000   {
1031      printf("cdrom: dma past end of sector (secleft=%d sz=%d)\n",secleft,size);
1001      logerror("cdrom: dma past end of sector (secleft=%d sz=%d)\n",secleft,size);
10321002   }
10331003
10341004//  printf("cdrom: start dma %d bytes, %d remaining, secptr %p\n", size, secleft, secptr);
r22065r22066
10551025   if (secleft==0) sr&=~0x40;
10561026}
10571027
1058//
1059//
1060//
1061
1062void psxcd_device::prefetch_next_sector()
1028bool psxcd_device::read_next_sector()
10631029{
1064   unsigned int pos=msf_to_sector(curpos);
1065   assert(driver);
1066   driver->prefetch_sector(pos);
1067}
1068
1069//
1070//
1071//
1072
1073bool psxcd_device::read_next_sector(const bool block)
1074{
1075   unsigned int pos=msf_to_sector(curpos);
1030   UINT32 pos=msf_to_lba_ps(curpos.w);
10761031   unsigned char *buf=&secbuf[sechead*raw_sector_size];
1077   assert(driver);
10781032   assert(secin<sector_buffer_size);
10791033
10801034//  printf("read_next_sector: sec %d, sechead %d, raw_sector_size %d\n", pos, sechead, raw_sector_size);
1081   if (driver->read_sector(pos, buf, block))
1035   if (cdrom_read_data(m_cdrom_handle, pos, buf, CD_TRACK_RAW_DONTCARE))
10821036   {
10831037//      printf("buf contents = %02x %02x | %02x %02x\n", buf[0], buf[1], buf[0x20], buf[0x21]);
10841038
r22065r22066
11001054
11011055void psxcd_device::read_sector()
11021056{
1103   next_read_event=NULL;
1057   next_read_event=-1;
11041058
11051059   if (status & status_reading)
11061060   {
11071061      bool isend=false;
11081062
1109      if (read_next_sector(false))
1063      if (read_next_sector())
11101064      {
11111065         unsigned char *rawsec;
11121066
r22065r22066
11231077            secleft=secsize;
11241078         }
11251079
1080         bool isxa=false;
1081
11261082         secin--;
11271083         sectail=(sectail+1)&(sector_buffer_size-1);
11281084
1129         //
1130
1131         bool isxa=false;
1132
11331085         subheader *sub=(subheader *)(rawsec+16);
11341086
11351087         #ifdef dump_subheader
r22065r22066
11571109                  isend=true;
11581110                  //printf("end of file\n");
11591111               }
1112               m_spu->play_xa(0,rawsec+16);
11601113
1161               #ifndef disable_xa_prefetch
1162                  unsigned int cursec=msf_to_sector(curpos);
1163
1164                  if (xa_prefetch_sector==-1)
1165                  {
1166                     xa_prefetch_sector=cursec;
1167                     m_spu->flush_xa();
1168                  }
1169
1170                  unsigned char *xaptr;
1171                  unsigned int xasecsz;
1172
1173                  while (1)
1174                  {
1175                     int dist=xa_prefetch_sector-cursec;
1176                     if (dist>max_xa_prefetch_distance) break;
1177
1178                     xaptr=driver->get_prefetch_sector(xa_prefetch_sector,&xasecsz);
1179                     if (! xaptr) break;
1180
1181                     switch (xasecsz)
1182                     {
1183                        case 2336:
1184                           break;
1185
1186                        default:
1187                           xaptr+=16;
1188                           break;
1189                     }
1190
1191                     subheader *xasub=(subheader *)xaptr;
1192
1193                     if ((xasub->submode&submode_audio) &&
1194                           (((mode&mode_channel)==0) ||
1195                              ((xasub->file==sub->file) &&
1196                              (xasub->channel==sub->channel))))
1197                     {
1198                        if (! m_spu->play_xa(xa_prefetch_sector,xaptr))
1199                           break;
1200                     }
1201                     xa_prefetch_sector++;
1202                  }
1203               #else
1204                  m_spu->play_xa(0,rawsec+16);
1205               #endif
1206
12071114               status|=status_playing;
12081115            }
12091116         }
r22065r22066
12131120
12141121         //
12151122
1216         curpos[2]++;
1217         if (curpos[2]==75)
1123         curpos.b[F]++;
1124         if (curpos.b[F]==75)
12181125         {
1219            curpos[2]=0;
1220            curpos[1]++;
1221            if (curpos[1]==60)
1126            curpos.b[F]=0;
1127            curpos.b[S]++;
1128            if (curpos.b[S]==60)
12221129            {
1223               curpos[1]=0;
1224               curpos[0]++;
1130               curpos.b[S]=0;
1131               curpos.b[M]++;
12251132            }
12261133         }
12271134
1228         loc[0]=curpos[0];
1229         loc[1]=curpos[1];
1230         loc[2]=curpos[2];
1135         loc.w=curpos.w;
12311136
1232         //
1233
1234         command_result *res=new command_result;
1235         res->res=isend?intr_dataend:intr_dataready;
1236         res->data[0]=status;
1237         res->sz=1;
1238
12391137         sr|=0x40;
12401138
1241         if ((streaming) && (isxa))
1139         if(!(streaming && isxa))
12421140         {
1243            global_free(res);
1244            res=NULL;
1245         }
1246
1247         if (res)
1248         {
1249            #ifdef debug_cdrom
1250               printf("cdrom:: data ready\n");
1251            #endif
1252
1141            command_result *res=global_alloc(command_result);
1142            res->res=isend?intr_dataend:intr_dataready;
1143            res->data[0]=status;
1144            res->sz=1;
12531145            cmd_complete(res);
12541146         }
12551147      }
r22065r22066
12611153
12621154         next_sector_t+=cyc;
12631155
1264         event *ev=new event;
1265         ev->t=cyc;
1266         ev->type=event_read_sector;
1267         next_read_event=ev;
1268         add_system_event(ev);
1156         next_read_event = add_system_event(event_read_sector, cyc, NULL);
12691157
12701158         //read_next_sector();
12711159      } else
r22065r22066
12911179
12921180void psxcd_device::play_sector()
12931181{
1294   next_read_event=NULL;
1182   next_read_event=-1;
12951183
12961184   if (status&status_playing)
12971185   {
1298      #ifdef disable_cdda_prefetch
12991186      unsigned char *rawsec=&secbuf[raw_sector_size*sectail];
1300      #endif
13011187      secin--;
13021188      sectail=(sectail+1)&(sector_buffer_size-1);
1189      play_cdda_sector(0,rawsec);
13031190
1304      //
1305
1306      #ifndef disable_cdda_prefetch
1307         unsigned int cursec=msf_to_sector(curpos);
1308
1309         if (cdda_prefetch_sector==-1)
1310         {
1311            cdda_prefetch_sector=cursec;
1312            m_spu->flush_cdda();
1313         }
1314
1315         unsigned char *cddaptr;
1316//          bool full=false;
1317         unsigned int cddasecsz;
1318
1319         while (1)
1320         {
1321            int dist=cdda_prefetch_sector-cursec;
1322            if (dist>max_cdda_prefetch_distance) break;
1323
1324            cddaptr=driver->get_prefetch_sector(cdda_prefetch_sector,&cddasecsz);
1325            if (! cddaptr) break;
1326
1327            if (! play_cdda_sector(cdda_prefetch_sector,cddaptr))
1328               break;
1329
1330            cdda_prefetch_sector++;
1331         }
1332      #else
1333         play_cdda_sector(0,rawsec);
1334      #endif
1335
1336      //
1337
1338      curpos[2]++;
1339      if (curpos[2]==75)
1191      curpos.b[F]++;
1192      if (curpos.b[F]==75)
13401193      {
1341         curpos[2]=0;
1342         curpos[1]++;
1343         if (curpos[1]==60)
1194         curpos.b[F]=0;
1195         curpos.b[S]++;
1196         if (curpos.b[S]==60)
13441197         {
1345            curpos[1]=0;
1346            curpos[0]++;
1198            curpos.b[S]=0;
1199            curpos.b[M]++;
13471200         }
13481201      }
13491202
1350      loc[0]=curpos[0];
1351      loc[1]=curpos[1];
1352      loc[2]=curpos[2];
1203      loc.w=curpos.w;
13531204
13541205      //
13551206
1207      UINT32 sector = msf_to_lba_ps(loc.w);
1208
13561209      if (mode&mode_autopause)
13571210      {
1358         if (msf_to_sector(loc)>=autopause_sector)
1211         if (sector>=autopause_sector)
13591212         {
13601213            printf("autopause cdda\n");
13611214
1362            command_result *res=new command_result;
1215            command_result *res=global_alloc(command_result);
13631216            res->res=intr_dataend;
13641217            res->data[0]=status_standby;
13651218            res->sz=1;
r22065r22066
13691222         }
13701223      }
13711224
1372      if (mode&mode_report)
1225      if ((mode&mode_report) && !(sector & 15)) // slow the int rate
13731226      {
1374         command_result *res=new command_result;
1375         res->res=intr_complete; //dataready;
1227         command_result *res=global_alloc(command_result);
1228         UINT8 track = cdrom_get_track(m_cdrom_handle, sector) + 1;
1229         res->res=intr_dataready;
13761230
13771231         res->data[0]=status_playing|status_standby;
1378         res->data[1]=0x01;
1379         res->data[2]=0x80;
1380         res->data[3]=decimal_to_bcd(loc[0]);
1381         res->data[4]=decimal_to_bcd(loc[1])|0x80;
1382         res->data[5]=decimal_to_bcd(loc[2]);
1232         res->data[1]=decimal_to_bcd(track);
1233         res->data[2]=1;
1234         if(sector & 0x10)
1235         {
1236            CDPOS tloc, start;
1237            start.w = (track == 1) ? 0x000200 : lba_to_msf_ps(cdrom_get_track_start(m_cdrom_handle, track - 1));
1238            tloc.w = sub_loc(loc, start);
1239            res->data[3]=decimal_to_bcd(tloc.b[M]);
1240            res->data[4]=decimal_to_bcd(tloc.b[S]) | 0x80;
1241            res->data[5]=decimal_to_bcd(tloc.b[F]);
1242         }
1243         else
1244         {
1245            res->data[3]=decimal_to_bcd(loc.b[M]);
1246            res->data[4]=decimal_to_bcd(loc.b[S]);
1247            res->data[5]=decimal_to_bcd(loc.b[F]);
1248         }
13831249
13841250         res->sz=8;
13851251
r22065r22066
13881254
13891255      unsigned int cyc=read_sector_cycles;
13901256
1391      event *ev=new event;
1392      ev->t=next_sector_t - m_maincpu->total_cycles();
1393      ev->type=event_play_sector;
1394
13951257      next_sector_t+=cyc>>1;
13961258
1397      next_read_event=ev;
1398      add_system_event(ev);
1259      next_read_event = add_system_event(event_play_sector, next_sector_t - m_maincpu->total_cycles(), NULL);
13991260
1400      read_next_sector();
1261      if(!read_next_sector())
1262      {
1263         command_result *res=global_alloc(command_result);
1264         res->res=intr_dataend;
1265         res->data[0]=status_standby;
1266         res->sz=1;
1267         cmd_complete(res);
1268         stop_read(); // assume we've reached the end
1269      }
14011270   }
14021271}
14031272
r22065r22066
14081277
14091278void psxcd_device::preread_sector()
14101279{
1411   next_read_event=NULL;
1280   UINT64 next_clock;
1281   int type;
1282   next_read_event=-1;
14121283
14131284   //
14141285
1415   event *ev=new event;
1416
1417   unsigned int pos=msf_to_sector(curpos);
1286   UINT32 pos=msf_to_lba_ps(curpos.w);
14181287   unsigned char *buf=&secbuf[sechead*raw_sector_size];
1419   if (! driver->read_sector(pos,buf,false))
1288   if (! cdrom_read_data(m_cdrom_handle, pos, buf, CD_TRACK_RAW_DONTCARE))
14201289   {
1421      ev->t=(m_sysclock/60);
1422      ev->type=event_preread_sector;
1290      next_clock=(m_sysclock/60);
1291      type=event_preread_sector;
14231292
14241293      unsigned int cyc=read_sector_cycles;
14251294      if (mode&mode_double_speed) cyc>>=1;
1426      next_sector_t=ev->t+(cyc-preread_delay)+m_maincpu->total_cycles();
1295      next_sector_t=next_clock+(cyc-preread_delay)+m_maincpu->total_cycles();
14271296   } else
14281297   {
14291298      memcpy(lastsechdr,buf+12,8);
14301299
14311300      //
14321301
1433      command_result *res=new command_result;
1302      command_result *res=global_alloc(command_result);
14341303      res->res=intr_complete;
14351304      res->data[0]=status;
14361305      res->sz=1;
r22065r22066
14431312
14441313      //
14451314
1446      ev->t=next_sector_t - m_maincpu->total_cycles();
1447      ev->type=event_read_sector;
1315      next_clock=next_sector_t - m_maincpu->total_cycles();
1316      type=event_read_sector;
14481317
14491318      //read_next_sector();
14501319   }
14511320
1452   next_read_event=ev;
1453   add_system_event(ev);
1321   next_read_event = add_system_event(type, next_clock, NULL);
14541322}
14551323
14561324//
r22065r22066
14681336   status|=status_reading;
14691337
14701338   secin=sechead=sectail=0;
1471   xa_prefetch_sector=-1;
14721339
14731340   unsigned int cyc=read_sector_cycles;
14741341   if (mode&mode_double_speed) cyc>>=1;
r22065r22066
14771344
14781345   systime+=start_read_delay;
14791346
1480   event *ev=new event;
1481   ev->t=start_read_delay+preread_delay;
1482   ev->type=event_preread_sector;
1483
14841347   next_sector_t=systime+cyc;
1485   next_read_event=ev;
1486   add_system_event(ev);
1487
1488   prefetch_next_sector();
1348   next_read_event = add_system_event(event_preread_sector, start_read_delay+preread_delay, NULL);
14891349}
14901350
14911351//
r22065r22066
15131373   status|=status_playing;
15141374
15151375   secin=sechead=sectail=0;
1516   cdda_prefetch_sector=-1;
15171376
15181377   if (mode&mode_autopause)
15191378   {
1520      unsigned int pos=msf_to_sector(curpos);
1521      driver->find_track(pos+150,NULL,&autopause_sector);
1379      UINT8 track = cdrom_get_track(m_cdrom_handle, msf_to_lba_ps(curpos.w) + 150);
1380      autopause_sector = cdrom_get_track_start(m_cdrom_handle, track) + cdrom_get_toc(m_cdrom_handle)->tracks[track].frames;
15221381//      printf("pos=%d auto=%d\n",pos,autopause_sector);
15231382   }
15241383
r22065r22066
15261385
15271386   next_sector_t=m_maincpu->total_cycles()+cyc;
15281387
1529   event *ev=new event;
1530   ev->t=next_sector_t - m_maincpu->total_cycles();
1531   ev->type=event_play_sector;
1532
15331388   next_sector_t+=cyc>>1;
15341389
1535   next_read_event=ev;
1536   add_system_event(ev);
1390   next_read_event = add_system_event(event_play_sector, next_sector_t - m_maincpu->total_cycles(), NULL);
15371391
15381392   read_next_sector();
15391393}
r22065r22066
15511405   status&=~(status_reading|status_playing);
15521406   streaming=false;
15531407
1554   if (next_read_event)
1408   if (next_read_event != -1)
15551409   {
1556      next_read_event->timer->adjust(attotime::never, 0, attotime::never);
1557      for (int i = 0; i < MAX_PSXCD_TIMERS; i++)
1558      {
1559         if (m_timers[i] == next_read_event->timer)
1560         {
1561            m_timerinuse[i] = false;
1562            m_eventfortimer[i] = NULL;
1563            break;
1564         }
1565      }
1566      global_free(next_read_event);
1567      next_read_event=NULL;
1410      m_timers[next_read_event]->adjust(attotime::never, 0, attotime::never);
1411      m_timerinuse[next_read_event] = false;
1412      next_read_event = -1;
15681413   }
15691414
1570   unsigned int sector=msf_to_sector(curpos);
1415   UINT32 sector=msf_to_lba_ps(curpos.w);
15711416   m_spu->flush_xa(sector);
15721417   m_spu->flush_cdda(sector);
15731418}
r22065r22066
15751420//
15761421//
15771422//
1578
1579void psxcd_device::set_driver(cdrom_driver *d)
1580{
1581   char err[1024];
1582
1583   if (d)
1584   {
1585      if (d->is_usable(err,1024))
1586      {
1587         driver=d;
1588         open=false;
1589
1590         if (! first_open)
1591         {
1592            command_result *res=new command_result;
1593            res->res=intr_acknowledge;
1594            res->data[0]=status_standby;
1595            res->sz=1;
1596
1597            cmd_complete(res);
1598
1599            open_nops=10;
1600         }
1601
1602         first_open=false;
1603      }
1604   } else
1605   {
1606      driver=NULL;
1607      open=false;
1608
1609      command_result *res=new command_result;
1610      res->res=intr_acknowledge;
1611      res->data[0]=status_shellopen;
1612      res->sz=1;
1613
1614      cmd_complete(res);
1615   }
1616}
1617
1618//
1619//
1620//
16211423void psxcd_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
16221424{
1623   event *ev = m_eventfortimer[tid];
1624
1625//  printf("timer %d fired, performing event type %d\n", tid, ev->type);
1626
1627   switch (ev->type)
1425   m_timerinuse[tid] = false;
1426   switch (param)
16281427   {
16291428      case event_cmd_complete:
16301429      {
r22065r22066
16321431            printf("cdrom:: event cmd complete\n");
16331432         #endif
16341433
1635         command_result *res=new command_result;
1636         memcpy(res,ev->data,sizeof(command_result));
1637         cmd_complete(res);
1434         cmd_complete((command_result *)ptr);
16381435         break;
16391436      }
16401437
r22065r22066
16491446      case event_play_sector:
16501447         play_sector();
16511448         break;
1652   }
16531449
1654   // free the timer
1655//  printf("Freeing timer %d\n", tid);
1656   m_timers[tid]->adjust(attotime::never, 0, attotime::never);
1657   m_timerinuse[tid] = false;
1658   m_eventfortimer[tid] = NULL;
1659
1660   global_free(ev);
1450      case event_change_disk:
1451         open = false;
1452         break;
1453   }
16611454}
16621455
1663void psxcd_device::add_system_event(event *ev)
1456int psxcd_device::add_system_event(int type, UINT64 t, void *ptr)
16641457{
1665   emu_timer *timer = NULL;
1666   int tnum = -1;
1667
1668   // allocate a timer for this event
1669   for (int i = 0; i < MAX_PSXCD_TIMERS; i++)
1458   // t is in maincpu clock cycles
1459   UINT32 hz = m_sysclock / t;
1460//  printf("add_system_event: event type %d for %d hz (using timer %d)\n", ev->type, hz, tnum);
1461   for(int i = 0; i < MAX_PSXCD_TIMERS; i++)
16701462   {
1671      if (!m_timerinuse[i])
1463      if(!m_timerinuse[i])
16721464      {
1673         tnum = i;
1674         timer = m_timers[i];
1465         m_timers[i]->adjust(attotime::from_hz(hz), type, attotime::never);
1466         m_timers[i]->set_ptr(ptr);
16751467         m_timerinuse[i] = true;
1676         m_eventfortimer[i] = ev;
1677         break;
1468         return i;
16781469      }
16791470   }
1680
1681   if (tnum == -1)
1682   {
1683      fatalerror("PSXCD: ran out of timers!\n");
1684   }
1685
1686   // ev->t is in maincpu clock cycles
1687   UINT32 hz = m_sysclock / ev->t;
1688//  printf("add_system_event: event type %d for %d hz (using timer %d)\n", ev->type, hz, tnum);
1689   timer->adjust(attotime::from_hz(hz), tnum, attotime::never);
1690
1691   // back-reference the timer from the event
1692   ev->timer = timer;
1471   fatalerror("psxcd: out of timers\n");
1472   return 0;
16931473}
trunk/src/mess/machine/psxcd.h
r22065r22066
22#define _included_psxcdrom_
33
44#include "imagedev/chd_cd.h"
5#include "psxcddrv.h"
65#include "sound/spu.h"
76
87#define MAX_PSXCD_TIMERS    (4)
9
10class event;
11
12//
13//
14//
15
168const int num_commands=0x20;
179
1810//
r22065r22066
2416//**************************************************************************
2517
2618#define MCFG_PSXCD_ADD(_tag, _devname) \
27   MCFG_DEVICE_ADD(_tag, PSXCD, 0) \
28   MCFG_PSXCD_DEVNAME(_devname)
19   MCFG_DEVICE_ADD(_tag, PSXCD, 0)
2920
3021#define MCFG_PSXCD_IRQ_HANDLER(_devcb) \
3122   devcb = &psxcd_device::set_irq_handler(*device, DEVCB2_##_devcb);
3223
33#define MCFG_PSXCD_DEVNAME(_name) \
34   psxcd_device::static_set_devname(*device, _name);
35
36struct psxcd_interface
24class psxcd_device : public cdrom_image_device
3725{
38};
39
40class psxcd_device : public device_t,
41                  public psxcd_interface
42{
4326public:
4427
4528   psxcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
r22065r22066
5538   };
5639
5740   static const unsigned int sector_buffer_size=16, default_irq_delay=16000;   //480;  //8000; //2000<<2;
41   static const unsigned int raw_sector_size=2352;
5842
5943   unsigned char sr,res,ir,cmdmode,
6044                        cmdbuf[64],*cbp,
6145                        mode,
62                        loc[3],
63                        curpos[3],
6446                        secbuf[raw_sector_size*sector_buffer_size],
6547                        *secptr,
6648                        filter_file,
r22065r22066
7254         secin;
7355   command_result *res_queue,
7456                           *cur_res;
57
58   union CDPOS {
59      UINT8 b[4];
60      UINT32 w;
61   };
62   CDPOS loc, curpos;
63
64#ifdef LSB_FIRST
65   enum {
66      M = 2,
67      S = 1,
68      F = 0
69   };
70#else
71   enum {
72      M = 1,
73      S = 2,
74      F = 3
75   };
76#endif
77
7578   bool open,
7679            streaming,
7780            first_open;
78   event *next_read_event;
81   device_timer_id next_read_event;
7982   INT64 next_sector_t;
8083   unsigned int autopause_sector,
8184                        xa_prefetch_sector,
8285                        cdda_prefetch_sector;
8386
84   cdrom_driver *driver;
85
8687   unsigned int start_read_delay,
8788                        read_sector_cycles,
8889                        preread_delay;
r22065r22066
128129
129130   void cmd_complete(command_result *res);
130131   void add_result(command_result *res);
131   event *send_result(const unsigned int res,
132   void send_result(const unsigned int res,
132133                                 const unsigned char *data=NULL,
133134                                 const unsigned int sz=0,
134135                                 const unsigned int delay=default_irq_delay);
r22065r22066
138139   void start_streaming();
139140   void stop_read();
140141   void read_sector();
141   void prefetch_next_sector();
142   bool read_next_sector(const bool block=true);
142   bool read_next_sector();
143143   bool play_cdda_sector(const unsigned int sector, unsigned char *rawsec);
144144   void play_sector();
145145   void preread_sector();
146   UINT32 sub_loc(CDPOS src1, CDPOS src2);
146147
147148public:
148   void set_driver(cdrom_driver *d);
149   cdrom_driver *get_driver() const { return driver; }
150149
151150   virtual void device_start();
152151   virtual void device_reset();
153152   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
153   virtual bool call_load();
154   virtual void call_unload();
154155
155156   void start_dma(UINT8 *mainram, UINT32 size);
156157
r22065r22066
158159   DECLARE_READ8_MEMBER( read );
159160
160161private:
161   //emu_timer *m_timer;
162   UINT32 m_param_count;
162163   UINT32 m_sysclock;
163   const char *m_devname;
164   cdrom_image_device *m_cddevice;
165   cdrom_file  *m_cd;
166164   emu_timer *m_timers[MAX_PSXCD_TIMERS];
167   event *m_eventfortimer[MAX_PSXCD_TIMERS];
168165   bool m_timerinuse[MAX_PSXCD_TIMERS];
169166
170   void add_system_event(event *ev);
167   int add_system_event(int type, UINT64 t, void *ptr);
171168
172169   devcb2_write_line m_irq_handler;
173170   cpu_device *m_maincpu;
174171   spu_device *m_spu;
175};
176172
173   UINT8 bcd_to_decimal(const UINT8 bcd) { return ((bcd>>4)*10)+(bcd&0xf); }
174   UINT8 decimal_to_bcd(const UINT8 dec) { return ((dec/10)<<4)|(dec%10); }
175   UINT32 msf_to_lba_ps(UINT32 msf) { msf = msf_to_lba(msf); return (msf>150)?(msf-150):msf; }
176   UINT32 lba_to_msf_ps(UINT32 lba) { return lba_to_msf_alt(lba+150); }
177177
178// miniature version of pSX's event class, which we emulate with device timers
179const int max_event_data=64;
180
181class event
182{
183public:
184   UINT64 t;               // expire time
185   unsigned int type;
186   unsigned char data[max_event_data];
187   emu_timer *timer;
188178};
189179
190
191180// device type definition
192181extern const device_type PSXCD;
193182
trunk/src/mess/drivers/psx.c
r22065r22066
498498{
499499}
500500
501struct cdrom_interface psx_cdrom =
502{
503   "psx_cdrom",
504   NULL
505};
506
507501static MACHINE_CONFIG_START( psxntsc, psx1_state )
508502   /* basic machine hardware */
509503   MCFG_CPU_ADD( "maincpu", CXD8530CQ, XTAL_67_7376MHz )
r22065r22066
525519   /* quickload */
526520   MCFG_QUICKLOAD_ADD("quickload", psx_exe_load, "cpe,exe,psf,psx", 0)
527521
528   MCFG_CDROM_ADD("cdrom",psx_cdrom)
529522   MCFG_SOFTWARE_LIST_ADD("cd_list","psx")
530523
531524   MCFG_DEVICE_MODIFY( "maincpu" )
r22065r22066
560553   /* quickload */
561554   MCFG_QUICKLOAD_ADD("quickload", psx_exe_load, "cpe,exe,psf,psx", 0)
562555
563   MCFG_CDROM_ADD("cdrom", psx_cdrom)
564556   MCFG_SOFTWARE_LIST_ADD("cd_list","psx")
565557
566558   MCFG_DEVICE_MODIFY( "maincpu" )
trunk/src/mess/mess.mak
r22065r22066
17201720   $(MESS_DRIVERS)/psx.o       \
17211721   $(MESS_MACHINE)/psxcport.o  \
17221722   $(MESS_MACHINE)/psxcd.o     \
1723   $(MESS_MACHINE)/psxcddrv.o  \
17241723   $(MESS_MACHINE)/psxcard.o   \
17251724   $(MESS_MACHINE)/psxanalog.o \
17261725   $(MESS_DRIVERS)/pockstat.o  \

Previous 199869 Revisions Next


© 1997-2024 The MAME Team