Previous 199869 Revisions Next

r29576 Saturday 12th April, 2014 at 20:20:11 UTC by R. Belmont
(MESS) Apple II: implemented cycle-exact Disk II floppy controller using the modern floppy subsystem. [O. Galibert, R. Belmont]
[src/emu/bus]bus.mak
[src/emu/bus/a2bus]a2diskiing.c* a2diskiing.h*
[src/emu/machine]machine.mak wozfdc.c* wozfdc.h*
[src/lib/formats]ap2_dsk.c ap2_dsk.h
[src/mess]mess.mak
[src/mess/drivers]apple2.c

trunk/src/emu/bus/bus.mak
r29575r29576
653653BUSOBJS += $(BUSOBJ)/a2bus/a2eext80col.o
654654BUSOBJS += $(BUSOBJ)/a2bus/a2eramworks3.o
655655BUSOBJS += $(BUSOBJ)/a2bus/a2corvus.o
656BUSOBJS += $(BUSOBJ)/a2bus/a2diskiing.o
656657endif
657658
658659#-------------------------------------------------
trunk/src/emu/bus/a2bus/a2diskiing.c
r0r29576
1/*********************************************************************
2
3    a2diskii.c
4
5    Implementation of the Apple II Disk II controller card
6
7*********************************************************************/
8
9#include "emu.h"
10#include "imagedev/floppy.h"
11#include "formats/ap2_dsk.h"
12#include "a2diskiing.h"
13#include <assert.h>
14
15/***************************************************************************
16    PARAMETERS
17***************************************************************************/
18
19//**************************************************************************
20//  GLOBAL VARIABLES
21//**************************************************************************
22
23const device_type A2BUS_DISKIING = &device_creator<a2bus_diskiing_device>;
24
25#define WOZFDC_TAG         "wozfdc"
26#define DISKII_ROM_REGION  "diskii_rom"
27
28static SLOT_INTERFACE_START( a2_floppies )
29   SLOT_INTERFACE( "525", FLOPPY_525_SD )
30SLOT_INTERFACE_END
31
32static MACHINE_CONFIG_FRAGMENT( diskiing )
33   MCFG_DEVICE_ADD(WOZFDC_TAG, DISKII_FDC, 1021800*2)
34   MCFG_FLOPPY_DRIVE_ADD("0", a2_floppies, "525", a2bus_diskiing_device::floppy_formats)
35   MCFG_FLOPPY_DRIVE_ADD("1", a2_floppies, "525", a2bus_diskiing_device::floppy_formats)
36MACHINE_CONFIG_END
37
38ROM_START( diskiing )
39   ROM_REGION(0x100, DISKII_ROM_REGION, 0)
40   ROM_LOAD( "341-0027-a.p5",  0x0000, 0x0100, CRC(ce7144f6) SHA1(d4181c9f046aafc3fb326b381baac809d9e38d16) ) /* 341-0027-a: 16-sector disk drive (older version), PROM P5 */
41ROM_END
42
43FLOPPY_FORMATS_MEMBER( a2bus_diskiing_device::floppy_formats )
44   FLOPPY_A216S_FORMAT, FLOPPY_RWTS18_FORMAT
45FLOPPY_FORMATS_END
46
47//-------------------------------------------------
48//  machine_config_additions - device-specific
49//  machine configurations
50//-------------------------------------------------
51
52machine_config_constructor a2bus_diskiing_device::device_mconfig_additions() const
53{
54   return MACHINE_CONFIG_NAME( diskiing );
55}
56
57//-------------------------------------------------
58//  rom_region - device-specific ROM region
59//-------------------------------------------------
60
61const rom_entry *a2bus_diskiing_device::device_rom_region() const
62{
63   return ROM_NAME( diskiing );
64}
65
66//**************************************************************************
67//  LIVE DEVICE
68//**************************************************************************
69
70a2bus_diskiing_device::a2bus_diskiing_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
71   device_t(mconfig, A2BUS_DISKIING, "Apple Disk II NG controller", tag, owner, clock, "a2diskiing", __FILE__),
72   device_a2bus_card_interface(mconfig, *this),
73   m_wozfdc(*this, WOZFDC_TAG),
74   floppy0(*this, "0"),
75   floppy1(*this, "1")
76{
77}
78
79//-------------------------------------------------
80//  device_start - device-specific startup
81//-------------------------------------------------
82
83void a2bus_diskiing_device::device_start()
84{
85   // set_a2bus_device makes m_slot valid
86   set_a2bus_device();
87
88   astring tempstring;
89   m_rom = device().machine().root_device().memregion(this->subtag(tempstring, DISKII_ROM_REGION))->base();
90}
91
92void a2bus_diskiing_device::device_reset()
93{
94   m_wozfdc->set_floppies(floppy0, floppy1);
95}
96
97/*-------------------------------------------------
98    read_c0nx - called for reads from this card's c0nx space
99-------------------------------------------------*/
100
101UINT8 a2bus_diskiing_device::read_c0nx(address_space &space, UINT8 offset)
102{
103   return m_wozfdc->read(space, offset);
104}
105
106
107/*-------------------------------------------------
108    write_c0nx - called for writes to this card's c0nx space
109-------------------------------------------------*/
110
111void a2bus_diskiing_device::write_c0nx(address_space &space, UINT8 offset, UINT8 data)
112{
113   m_wozfdc->write(space, offset, data);
114}
115
116/*-------------------------------------------------
117    read_cnxx - called for reads from this card's cnxx space
118-------------------------------------------------*/
119
120UINT8 a2bus_diskiing_device::read_cnxx(address_space &space, UINT8 offset)
121{
122   return m_rom[offset];
123}
124
Property changes on: trunk/src/emu/bus/a2bus/a2diskiing.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/bus/a2bus/a2diskiing.h
r0r29576
1/*********************************************************************
2
3    a2diskiing.h
4
5    Apple II Disk II Controller Card, new floppy
6
7*********************************************************************/
8
9#ifndef __A2BUS_DISKIING__
10#define __A2BUS_DISKIING__
11
12#include "emu.h"
13#include "a2bus.h"
14#include "imagedev/floppy.h"
15#include "formats/flopimg.h"
16#include "machine/wozfdc.h"
17
18//**************************************************************************
19//  TYPE DEFINITIONS
20//**************************************************************************
21
22
23class a2bus_diskiing_device:
24   public device_t,
25   public device_a2bus_card_interface
26{
27public:
28   // construction/destruction
29   a2bus_diskiing_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
30
31   // optional information overrides
32   virtual machine_config_constructor device_mconfig_additions() const;
33   virtual const rom_entry *device_rom_region() const;
34
35   DECLARE_FLOPPY_FORMATS( floppy_formats );
36
37protected:
38   virtual void device_start();
39   virtual void device_reset();
40
41   // overrides of standard a2bus slot functions
42   virtual UINT8 read_c0nx(address_space &space, UINT8 offset);
43   virtual void write_c0nx(address_space &space, UINT8 offset, UINT8 data);
44   virtual UINT8 read_cnxx(address_space &space, UINT8 offset);
45
46private:
47   required_device<diskii_fdc> m_wozfdc;
48   required_device<floppy_connector> floppy0;
49   required_device<floppy_connector> floppy1;
50
51   const UINT8 *m_rom;
52};
53
54// device type definition
55extern const device_type A2BUS_DISKIING;
56
57#endif  /* __A2BUS_DISKIING__ */
Property changes on: trunk/src/emu/bus/a2bus/a2diskiing.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/machine.mak
r29575r29576
18471847MACHINEOBJS += $(MACHINEOBJ)/corvushd.o
18481848endif
18491849
1850#-------------------------------------------------
1851#
1852#@src/emu/machine/wozfdc.h,MACHINES += WOZFDC
1853#-------------------------------------------------
1854ifneq ($(filter WOZFDC,$(MACHINES)),)
1855MACHINEOBJS += $(MACHINEOBJ)/wozfdc.o
1856endif
1857
trunk/src/emu/machine/wozfdc.c
r0r29576
1/*********************************************************************
2
3    wozfdc.c
4
5    Implementation of the Apple Disk II floppy disk controller
6
7*********************************************************************/
8
9#include "emu.h"
10#include "imagedev/floppy.h"
11#include "formats/ap2_dsk.h"
12#include "wozfdc.h"
13#include <assert.h>
14
15/***************************************************************************
16    PARAMETERS
17***************************************************************************/
18
19//**************************************************************************
20//  GLOBAL VARIABLES
21//**************************************************************************
22
23const device_type DISKII_FDC = &device_creator<diskii_fdc>;
24const device_type APPLEIII_FDC = &device_creator<appleiii_fdc>;
25
26#define DISKII_P6_REGION  "diskii_rom_p6"
27
28ROM_START( diskiing )
29   ROM_REGION(0x100, DISKII_P6_REGION, 0)
30   ROM_LOAD( "341-0028-a.rom", 0x0000, 0x0100, CRC(b72a2c70) SHA1(bc39fbd5b9a8d2287ac5d0a42e639fc4d3c2f9d4)) /* 341-0028: 16-sector disk drive (older version), PROM P6 */
31ROM_END
32
33//-------------------------------------------------
34//  rom_region - device-specific ROM region
35//-------------------------------------------------
36
37const rom_entry *wozfdc_device::device_rom_region() const
38{
39   return ROM_NAME( diskiing );
40}
41
42//**************************************************************************
43//  LIVE DEVICE
44//**************************************************************************
45
46wozfdc_device::wozfdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
47   device_t(mconfig, type, name, tag, owner, clock, shortname, source)
48{
49}
50
51diskii_fdc::diskii_fdc(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
52   wozfdc_device(mconfig, DISKII_FDC, "Apple Disk II floppy controller", tag, owner, clock, "d2fdc", __FILE__)
53{
54}
55
56appleiii_fdc::appleiii_fdc(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
57   wozfdc_device(mconfig, DISKII_FDC, "Apple III floppy controller", tag, owner, clock, "a3fdc", __FILE__)
58{
59}
60
61//-------------------------------------------------
62//  device_start - device-specific startup
63//-------------------------------------------------
64
65void wozfdc_device::device_start()
66{
67   astring tempstring;
68   m_rom_p6 = machine().root_device().memregion(this->subtag(tempstring, DISKII_P6_REGION))->base();
69
70   timer = timer_alloc(0);
71   delay_timer = timer_alloc(1);
72}
73
74void wozfdc_device::device_reset()
75{
76   current_cyl = 0;
77   floppy = NULL;
78   active = MODE_IDLE;
79   phases = 0x00;
80   mode_write = false;
81   mode_load = false;
82   last_6502_write = 0x00;
83   cur_lss.tm = machine().time();
84   cur_lss.cycles = time_to_cycles(cur_lss.tm);
85   cur_lss.data_reg = 0x00;
86   cur_lss.address = 0x00;
87   cur_lss.write_start_time = attotime::never;
88   cur_lss.write_position = 0;
89   predicted_lss.tm = attotime::never;
90}
91
92void wozfdc_device::a3_update_drive_sel()
93{
94   floppy_image_device *newflop;
95
96   if (enable1)
97   {
98      newflop = floppy0->get_device();
99   }
100   else
101   {
102      switch (drvsel & 3)
103      {
104         case 0:
105            newflop = floppy0->get_device();
106            break;
107
108         case 1:
109            newflop = floppy1->get_device();
110            break;
111
112         case 2:
113            newflop = floppy2->get_device();
114            break;
115
116         case 3:
117            newflop = floppy3->get_device();
118            break;
119      }
120   }
121
122   if (floppy != newflop)
123   {
124      if(active) {
125         lss_sync();
126         floppy->mon_w(true);
127      }
128      floppy = newflop;
129      if(active) {
130         floppy->mon_w(false);
131         lss_predict();
132      }
133   }
134}
135
136void diskii_fdc::device_reset()
137{
138   wozfdc_device::device_reset();
139   external_drive_select = false;
140
141   if (floppy0 != NULL)
142   {
143      floppy = floppy0->get_device();
144   }
145}
146
147void appleiii_fdc::device_reset()
148{
149   wozfdc_device::device_reset();
150   external_drive_select = true;
151   drvsel = 0;
152   enable1 = 1;
153}
154
155void wozfdc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
156{
157   if(active)
158      lss_sync();
159
160   if(id == 1 && active == MODE_DELAY) {
161      if(floppy)
162         floppy->mon_w(true);
163      active = MODE_IDLE;
164   }
165
166   if(active)
167      lss_predict();
168}
169
170/*-------------------------------------------------
171    read - called to read the FDC's registers
172-------------------------------------------------*/
173
174READ8_MEMBER(wozfdc_device::read)
175{
176   control(offset);
177
178   if(!(offset & 1))
179      return cur_lss.data_reg;
180   return 0xff;
181}
182
183
184/*-------------------------------------------------
185    write - called to write the FDC's registers
186-------------------------------------------------*/
187
188WRITE8_MEMBER(wozfdc_device::write)
189{
190   control(offset);
191   last_6502_write = data;
192   lss_predict();
193}
194
195void wozfdc_device::phase(int ph, bool on)
196{
197   if(on)
198      phases |= 1 << ph;
199   else
200      phases &= ~(1 << ph);
201
202   if(floppy && active) {
203      int cph = current_cyl & 3;
204      int pcyl = current_cyl;
205      if(!(phases & (1 << cph))) {
206         if(current_cyl < 70 && (phases & (1 << ((cph+1) & 3))))
207            current_cyl++;
208         if(current_cyl && (phases & (1 << ((cph+3) & 3))))
209            current_cyl--;
210         if(current_cyl != pcyl && !(current_cyl & 1)) {
211            floppy->dir_w(current_cyl < pcyl);
212            floppy->stp_w(true);
213            floppy->stp_w(false);
214            floppy->stp_w(true);
215         }
216      }               
217   }
218}
219
220void wozfdc_device::control(int offset)
221{
222   if(offset < 8) {
223      if(active)
224         lss_sync();
225      phase(offset >> 1, offset & 1);
226      if(active)
227         lss_predict();
228
229   } else
230      switch(offset) {
231      case 0x8:
232         if(active == MODE_ACTIVE) {
233            lss_sync();
234            delay_timer->adjust(attotime::from_seconds(1));
235            active = MODE_DELAY;
236         }
237         break;
238      case 0x9:
239         switch(active) {
240         case MODE_IDLE:
241            if(floppy) {
242               floppy->mon_w(false);
243               current_cyl = floppy->get_cyl() << 1;
244            }
245            active = MODE_ACTIVE;
246            if(floppy)
247               lss_start();
248            break;
249         case MODE_DELAY:
250            active = MODE_ACTIVE;
251            delay_timer->adjust(attotime::never);
252            break;
253         }
254         break;
255      case 0xa:
256         if(floppy != floppy0->get_device()) {
257            if(active) {
258               lss_sync();
259               floppy->mon_w(true);
260            }
261            floppy = floppy0->get_device();
262            if(active) {
263               floppy->mon_w(false);
264               lss_predict();
265            }
266         }
267         break;
268      case 0xb:
269         if (!external_drive_select)
270         {
271            if (floppy != floppy1->get_device())
272            {
273               if(active) {
274                  lss_sync();
275                  floppy->mon_w(true);
276               }
277               floppy = floppy1->get_device();
278               if(active) {
279                  floppy->mon_w(false);
280                  lss_predict();
281               }
282            }
283         }
284         else
285         {
286            a3_update_drive_sel();
287         }
288         break;
289      case 0xc:
290         if(mode_load) {
291            if(active) {
292               lss_sync();
293               cur_lss.address &= ~0x04;
294            }
295            mode_load = false;
296            if(active)
297               lss_predict();
298         }
299         break;
300      case 0xd:
301         if(!mode_load) {
302            if(active) {
303               lss_sync();
304               cur_lss.address |= 0x04;
305            }
306            mode_load = true;
307            if(active)
308               lss_predict();
309         }
310         break;
311      case 0xe:
312         if(mode_write) {
313            if(active) {
314               lss_sync();
315               cur_lss.address &= ~0x08;
316            }
317            mode_write = false;
318            if(active)
319               lss_predict();
320         }
321         break;
322      case 0xf:
323         if(!mode_write) {
324            if(active) {
325               lss_sync();
326               cur_lss.address |= 0x08;
327               cur_lss.write_start_time = machine().time();
328               if(floppy)
329                  floppy->set_write_splice(cur_lss.write_start_time);
330            }
331            mode_write = true;
332            if(active)
333               lss_predict();
334         }
335         break;
336      }
337}
338
339UINT64 wozfdc_device::time_to_cycles(attotime tm)
340{
341   // Clock is falling edges of the ~2Mhz clock
342   // The 1021800 must be the controlling 6502's speed
343
344   UINT64 cycles = tm.as_ticks(1021800*2*2);
345   cycles = (cycles+1) >> 1;
346   return cycles;
347}
348
349attotime wozfdc_device::cycles_to_time(UINT64 cycles)
350{
351   return attotime::from_ticks(cycles*2+1, 1021800*2*2);
352}
353
354void wozfdc_device::lss_start()
355{
356   cur_lss.tm = machine().time();
357   cur_lss.cycles = time_to_cycles(cur_lss.tm);
358   cur_lss.data_reg = 0x00;
359   cur_lss.address &= ~0x0e;
360   cur_lss.write_position = 0;
361   cur_lss.write_start_time = mode_write ? machine().time() : attotime::never;
362   cur_lss.write_line_active = false;
363   if(mode_write && floppy)
364      floppy->set_write_splice(cur_lss.write_start_time);
365   lss_predict();
366}
367
368void wozfdc_device::lss_delay(UINT64 cycles, attotime tm, UINT8 data_reg, UINT8 address, bool write_line_active)
369{
370   if(data_reg & 0x80)
371      address |= 0x02;
372   else
373      address &= ~0x02;
374   predicted_lss.cycles = cycles;
375   predicted_lss.tm = tm;
376   predicted_lss.data_reg = data_reg;
377   predicted_lss.address = address;
378   predicted_lss.write_line_active = write_line_active;
379   attotime mtm = machine().time();
380   if(predicted_lss.tm > mtm)
381      timer->adjust(predicted_lss.tm - mtm);
382}
383
384void wozfdc_device::lss_delay(UINT64 cycles, UINT8 data_reg, UINT8 address, bool write_line_active)
385{
386   lss_delay(cycles, cycles_to_time(cycles), data_reg, address, write_line_active);
387}
388
389void wozfdc_device::commit_predicted()
390{
391   cur_lss = predicted_lss;
392   assert(!mode_write || (cur_lss.write_line_active && (cur_lss.address & 0x80)) || ((!cur_lss.write_line_active) && !(cur_lss.address & 0x80)));
393   if(mode_write) {
394      if(floppy)
395         floppy->write_flux(cur_lss.write_start_time, cur_lss.tm, cur_lss.write_position, cur_lss.write_buffer);
396      cur_lss.write_start_time = cur_lss.tm;
397      cur_lss.write_position = 0;
398   }
399   
400   predicted_lss.tm = attotime::never;
401}
402
403void wozfdc_device::lss_sync()
404{
405   attotime tm = machine().time();
406   if(!predicted_lss.tm.is_never() && predicted_lss.tm <= tm)
407      commit_predicted();
408
409   while(cur_lss.tm < tm) {
410      lss_predict(tm);
411      commit_predicted();
412   }     
413}
414
415void wozfdc_device::lss_predict(attotime limit)
416{
417   predicted_lss.write_start_time = cur_lss.write_start_time;
418   predicted_lss.write_position = cur_lss.write_position;
419   memcpy(predicted_lss.write_buffer, cur_lss.write_buffer, cur_lss.write_position * sizeof(attotime));
420   bool write_line_active = cur_lss.write_line_active;
421
422   attotime next_flux = floppy ? floppy->get_next_transition(cur_lss.tm - attotime::from_usec(1)) : attotime::never;
423   attotime next_flux_down = next_flux != attotime::never ? next_flux + attotime::from_usec(1) : attotime::never;
424
425   if(limit == attotime::never)
426      limit = machine().time() + attotime::from_usec(50);
427
428   UINT64 cycles = cur_lss.cycles;
429   UINT64 cycles_limit = time_to_cycles(limit);
430   UINT64 cycles_next_flux = next_flux != attotime::never ? time_to_cycles(next_flux) : UINT64(-1);
431   UINT64 cycles_next_flux_down = next_flux_down != attotime::never ? time_to_cycles(next_flux_down) : UINT64(-1);
432
433   UINT8 address = cur_lss.address;
434   UINT8 data_reg = cur_lss.data_reg;
435
436   if(cycles >= cycles_next_flux && cycles < cycles_next_flux_down)
437      address &= ~0x10;
438   else
439      address |= 0x10;
440
441   while(cycles < cycles_limit) {
442      UINT64 cycles_next_trans = cycles_limit;
443      if(cycles_next_trans > cycles_next_flux && cycles < cycles_next_flux)
444         cycles_next_trans = cycles_next_flux;
445      if(cycles_next_trans > cycles_next_flux_down && cycles < cycles_next_flux_down)
446         cycles_next_trans = cycles_next_flux_down;
447
448      while(cycles < cycles_next_trans) {
449         UINT8 opcode = m_rom_p6[address];
450
451         if(mode_write) {
452            if((write_line_active && !(address & 0x80)) ||
453               (!write_line_active && (address & 0x80))) {
454               write_line_active = !write_line_active;
455               assert(predicted_lss.write_position != 32);
456               predicted_lss.write_buffer[predicted_lss.write_position++] = cycles_to_time(cycles);
457            }
458         }
459
460         address = (address & 0x1e) | (opcode & 0xc0) | ((opcode & 0x20) >> 5) | ((opcode & 0x10) << 1);
461         switch(opcode & 0x0f) {
462         case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
463            if(data_reg) {
464               lss_delay(cycles+1, 0x00, address, write_line_active);
465               return;
466            }
467            break;
468         case 0x8: case 0xc:
469            break;
470         case 0x9:
471            lss_delay(cycles+1, data_reg << 1, address, write_line_active);
472            return;
473         case 0xa: case 0xe:
474            lss_delay(cycles+1, (data_reg >> 1) | (floppy && floppy->wpt_r() ? 0x80 : 0x00), address, write_line_active);
475            return;
476         case 0xb: case 0xf:
477            lss_delay(cycles+1, last_6502_write, address, write_line_active);
478            return;
479         case 0xd:
480            lss_delay(cycles+1, (data_reg << 1) | 0x01, address, write_line_active);
481            return;
482         }
483         cycles++;
484      }
485
486      if(cycles == cycles_next_flux)
487         address &= ~0x10;
488      else if(cycles == cycles_next_flux_down) {
489         address |= 0x10;
490         next_flux = floppy ? floppy->get_next_transition(cycles_to_time(cycles)) : attotime::never;
491         next_flux_down = next_flux != attotime::never ? next_flux + attotime::from_usec(1) : attotime::never;
492         cycles_next_flux = next_flux != attotime::never ? time_to_cycles(next_flux) : UINT64(-1);
493         cycles_next_flux_down = next_flux_down != attotime::never ? time_to_cycles(next_flux_down) : UINT64(-1);
494      }
495   }
496
497   lss_delay(cycles, limit, data_reg, address, write_line_active);
498}
499
500// set the two images for the Disk II
501void diskii_fdc::set_floppies(floppy_connector *f0, floppy_connector *f1)
502{
503   floppy0 = f0;
504   floppy1 = f1;
505
506   if (floppy0)
507   {
508      floppy = floppy0->get_device();
509   }
510}
511
512void appleiii_fdc::set_floppies_4(floppy_connector *f0, floppy_connector *f1, floppy_connector *f2, floppy_connector *f3)
513{
514   floppy0 = f0;
515   floppy1 = f1;
516   floppy2 = f2;
517   floppy3 = f3;
518
519   if (floppy0)
520   {
521      floppy = floppy0->get_device();
522   }
523}
524
525READ8_MEMBER(appleiii_fdc::read_c0dx)
526{
527   control_dx(offset);
528
529   return 0xff;
530}
531
532WRITE8_MEMBER(appleiii_fdc::write_c0dx)
533{
534   control_dx(offset);
535}
536
537void appleiii_fdc::control_dx(int offset)
538{
539   switch (offset)
540   {
541      case 0:   // clear drive select bit 0
542         drvsel &= ~1;
543         break;
544
545      case 1:   // set drive select bit 0
546         drvsel |= 1;
547         break;
548
549      case 2:   // clear drive select bit 1
550         drvsel &= ~2;
551         break;
552
553      case 3:   // set drive select bit 1
554         drvsel |= 2;
555         break;
556
557      case 4:   // clear enable 1
558         enable1 = 0;
559         break;
560
561      case 5:   // set enable 1
562         enable1 = 1;
563         break;
564
565      case 6:   // clear side 2
566      case 7: // set side 2
567         break;
568
569      default:   // cod8-c0df are not FDC related
570         break;
571   }
572}
573
Property changes on: trunk/src/emu/machine/wozfdc.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/wozfdc.h
r0r29576
1/*********************************************************************
2
3    wozfdc.h
4
5    Apple Disk II floppy disk controller
6
7*********************************************************************/
8
9#pragma once
10
11#ifndef __WOZFDC_H__
12#define __WOZFDC_H__
13
14#include "emu.h"
15#include "imagedev/floppy.h"
16#include "formats/flopimg.h"
17
18//**************************************************************************
19//  TYPE DEFINITIONS
20//**************************************************************************
21
22
23class wozfdc_device:
24   public device_t
25{
26   friend class diskii_fdc;
27   friend class appleiii_fdc;
28
29public:
30   // construction/destruction
31   wozfdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
32
33   // optional information overrides
34   virtual const rom_entry *device_rom_region() const;
35
36   DECLARE_READ8_MEMBER(read);
37   DECLARE_WRITE8_MEMBER(write);
38
39protected:
40   virtual void device_start();
41   virtual void device_reset();
42   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
43
44   floppy_connector *floppy0, *floppy1, *floppy2, *floppy3;
45   floppy_image_device *floppy;
46
47private:
48   enum {
49      MODE_IDLE, MODE_ACTIVE, MODE_DELAY
50   };
51
52   struct lss {
53      attotime tm;
54      UINT64 cycles;
55      UINT8 data_reg, address;
56      attotime write_start_time;
57      attotime write_buffer[32];
58      int write_position;
59      bool write_line_active;
60   };
61
62   const UINT8 *m_rom_p6;
63   UINT8 current_cyl, last_6502_write;
64   bool mode_write, mode_load;
65   int active;
66   UINT8 phases;
67   emu_timer *timer, *delay_timer;
68   bool external_drive_select;
69
70   lss cur_lss, predicted_lss;
71
72   int drvsel;
73   int enable1;
74
75   void control(int offset);
76   void phase(int ph, bool on);
77   UINT64 time_to_cycles(attotime tm);
78   attotime cycles_to_time(UINT64 cycles);
79   void a3_update_drive_sel();
80
81   void lss_start();
82   void lss_delay(UINT64 cycles, attotime tm, UINT8 data_reg, UINT8 address, bool write_line_active);
83   void lss_delay(UINT64 cycles, UINT8 data_reg, UINT8 address, bool write_line_active);
84   void lss_sync();
85   void lss_predict(attotime limit = attotime::never);
86   void commit_predicted();
87};
88
89class diskii_fdc : public wozfdc_device
90{
91public:
92   diskii_fdc(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
93
94   virtual void device_reset();
95
96   void set_floppies(floppy_connector *f0, floppy_connector *f1);
97};
98
99class appleiii_fdc : public wozfdc_device
100{
101public:
102   appleiii_fdc(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
103
104   virtual void device_reset();
105
106   void set_floppies_4(floppy_connector *f0, floppy_connector *f1, floppy_connector *f2, floppy_connector *f3);
107
108   DECLARE_READ8_MEMBER(read_c0dx);
109   DECLARE_WRITE8_MEMBER(write_c0dx);
110
111private:
112   void control_dx(int offset);
113};
114
115// device type definition
116extern const device_type DISKII_FDC;
117extern const device_type APPLEIII_FDC;
118
119#endif  /* __WOZFDC_H__ */
Property changes on: trunk/src/emu/machine/wozfdc.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/lib/formats/ap2_dsk.c
r29575r29576
520520
521521****************************************************************************/
522522
523static const UINT8 dos_skewing[] =
524{
525   0x00, 0x07, 0x0E, 0x06, 0x0D, 0x05, 0x0C, 0x04,
526   0x0B, 0x03, 0x0A, 0x02, 0x09, 0x01, 0x08, 0x0F
527};
523528
529static const UINT8 prodos_skewing[] =
530{
531   0x00, 0x08, 0x01, 0x09, 0x02, 0x0A, 0x03, 0x0B,
532   0x04, 0x0C, 0x05, 0x0D, 0x06, 0x0E, 0x07, 0x0F
533};
534
535
524536a2_16sect_format::a2_16sect_format() : floppy_image_format_t()
525537{
526538}
r29575r29576
537549
538550const char *a2_16sect_format::extensions() const
539551{
540      return "dsk";
552      return "dsk,do,po";
541553}
542554
543555bool a2_16sect_format::supports_save() const
r29575r29576
582594      { END },
583595};
584596
585
586597bool a2_16sect_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
587598{
588/*      TODO: rewrite me properly
589        UINT8 sector_data[(256)*16];
590        memset(sector_data, 0, sizeof(sector_data));
599   m_prodos_order = false;
591600
592        desc_s sectors[16];
593        int format = 0;
594        int pos_data = 0;
601   int fpos = 0;
602   for(int track=0; track < 35; track++) {
603      UINT32 track_data[51090*2];
604      UINT8 sector_data[256*16];
605      int offset = 0;
595606
596        int head_count = 1;
607      io_generic_read(io, sector_data, fpos, 256*16);
597608
598        for(int track=0; track < 35; track++) {
599                for(int head=0; head < head_count; head++) {
600                        for(int si=0; si<16; si++) {
601                                UINT8 *data = sector_data + (256)*si;
602                                sectors[si].data = data;
603                                sectors[si].size = 256;
604                                sectors[si].sector_id = si;
605                                sectors[si].sector_info = format;
606                                io_generic_read(io, data, pos_data, 256);
607                                pos_data += 256;
608                        }
609                        generate_track(mac_gcr, track, head, sectors, 16, 3104*16, image);
610                }
611        }
612        return true;*/
613      return false; // I hope that throws an error...
609      if (track == 0 && fpos == 0)
610      {
611         // check ProDOS boot block
612         if (!memcmp("PRODOS", &sector_data[0x103], 6))
613         {
614            m_prodos_order = true;
615         }   // check SOS boot block
616         else if (!memcmp("SOS BOOT", &sector_data[0x3], 8))
617         {
618            m_prodos_order = true;
619         }   // check Apple II Pascal
620         else if (!memcmp("SYSTEM.APPLE", &sector_data[0xd7], 12))
621         {
622            unsigned char pascal_block1[4] = { 0x08, 0xa5, 0x0f, 0x29 };
623
624            // Pascal discs can still be DOS order.
625            // Check for the second half of the boot code at 0x100
626            // (which means ProDOS order)
627            if (!memcmp(pascal_block1, &sector_data[0x100], 4))
628            {
629               m_prodos_order = true;
630            }
631         }
632      }
633
634      fpos += 256*16;
635      for(int i=0; i<51; i++)
636         raw_w(track_data, offset, 10, 0x3fc);
637      for(int i=0; i<16; i++) {
638         int sector;
639
640         if (m_prodos_order)
641         {
642            sector = prodos_skewing[i];
643         }
644         else
645         {
646            sector = dos_skewing[i];
647         }
648
649         const UINT8 *sdata = sector_data + 256 * sector;
650         for(int j=0; j<20; j++)
651            raw_w(track_data, offset, 10, 0x3fc);
652         raw_w(track_data, offset,  8, 0xff);
653         raw_w(track_data, offset, 24, 0xd5aa96);
654         raw_w(track_data, offset, 16, gcr4_encode(0xfe));
655         raw_w(track_data, offset, 16, gcr4_encode(track));
656         raw_w(track_data, offset, 16, gcr4_encode(i));
657         raw_w(track_data, offset, 16, gcr4_encode(0xfe ^ track ^ i));
658         raw_w(track_data, offset, 24, 0xdeaaeb);
659
660         for(int j=0; j<4; j++)
661            raw_w(track_data, offset, 10, 0x3fc);
662
663         raw_w(track_data, offset,  9, 0x01fe);
664         raw_w(track_data, offset, 24, 0xd5aaad);
665
666         UINT8 pval = 0x00;
667         for(int i=0; i<342; i++) {
668            UINT8 nval;
669            if(i >= 0x56)
670               nval = sdata[i - 0x56] >> 2;
671            else {
672               nval =
673                  ((sdata[i+0x00] & 0x01) << 1) |
674                  ((sdata[i+0x00] & 0x02) >> 1) |
675                  ((sdata[i+0x56] & 0x01) << 3) |
676                  ((sdata[i+0x56] & 0x02) << 1);
677               if(i < 256-0xac)
678                  nval |=
679                     ((sdata[i+0xac] & 0x01) << 5) |
680                     ((sdata[i+0xac] & 0x02) << 3);
681            }
682            raw_w(track_data, offset, 8, translate6[nval ^ pval]);
683            pval = nval;
684         }
685         raw_w(track_data, offset, 8, translate6[pval]);
686         raw_w(track_data, offset, 24, 0xdeaaeb);
687      }
688      raw_w(track_data, offset, 4, 0xff);
689      assert(offset == 51090);
690
691      generate_track_from_levels(track, 0, track_data, 51090, 0, image);
692   }         
693   return true;
614694}
615695
616696UINT8 a2_16sect_format::gb(const UINT8 *buf, int ts, int &pos, int &wrap)
r29575r29576
632712{
633713}
634714
715//#define VERBOSE_SAVE
716
635717bool a2_16sect_format::save(io_generic *io, floppy_image *image)
636718{
637719      int g_tracks, g_heads;
638720      int visualgrid[16][35]; // visualizer grid, cleared/initialized below
721
639722// lenient addr check: if unset, only accept an addr mark if the checksum was good
640723// if set, accept an addr mark if the track and sector values are both sane
641724#undef LENIENT_ADDR_CHECK
642725// if set, use the old, not as robust logic for choosing which copy of a decoded sector to write
643726// to the resulting image if the sector has a bad checksum and/or postamble
644727#undef USE_OLD_BEST_SECTOR_PRIORITY
645// select a sector order for resulting file: 0 = logical, 1 = dos3.3, 2 = prodos
646#define SECTOR_ORDER 1
647728// nothing found
648729#define NOTFOUND 0
649730// address mark was found
r29575r29576
667748
668749      int pos_data = 0;
669750
670      for(int track=0; track < 70; track+=2) {
751      for(int track=0; track < 35; track++) {
671752            UINT8 sectdata[(256)*16];
672753            memset(sectdata, 0, sizeof(sectdata));
673754            int nsect = 16;
674            UINT8 buf[130000]; // originally 13000, multiread dfi disks need larger
755            UINT8 buf[10000]; // normal is 51090 cells, e.g. 6387 bytes, add 50% and round up for denser than normal disks
675756            int ts;
676//fprintf(stderr,"DEBUG: a2_16sect_format::save() about to generate bitstream from physical track %d (logical %d)...", track, track/2);
677            //~332 samples per cell, times 3+8+3 (14) for address mark, 24 for sync, 3+343+3 (349) for data mark, 24 for sync is around 743, near 776 expected
678            generate_bitstream_from_track(track, head, 200000000/((3004*nsect*6)/2), buf, ts, image); // 3104 needs tweaking
679//fprintf(stderr,"done.\n");
757            #ifdef VERBOSE_SAVE
758            fprintf(stderr,"DEBUG: a2_16sect_format::save() about to generate bitstream from track %d...", track);
759            #endif
760            generate_bitstream_from_track(track, head, 3915, buf, ts, image);
761            #ifdef VERBOSE_SAVE
762            fprintf(stderr,"done.\n");
763            #endif
680764            int pos = 0;
681765            int wrap = 0;
682766            int hb = 0;
683767            int dosver = 0; // apple dos version; 0 = >=3.3, 1 = <3.3
684768            for(;;) {
685769                  UINT8 v = gb(buf, ts, pos, wrap);
686                  if(v == 0xff)
770                  if(v == 0xff)            {
687771                        hb = 1;
688                  else if(hb == 1 && v == 0xd5)
772                     }
773                     else if(hb == 1 && v == 0xd5){
689774                        hb = 2;
690                  else if(hb == 2 && v == 0xaa)
775                        }
776                     else if(hb == 2 && v == 0xaa) {
691777                        hb = 3;
692                  else if(hb == 3 && ((v == 0x96) || (v == 0xab))) { // 0x96 = dos 3.3/16sec, 0xab = dos 3.21 and below/13sec
778                     }
779                     else if(hb == 3 && ((v == 0x96) || (v == 0xab))) { // 0x96 = dos 3.3/16sec, 0xab = dos 3.21 and below/13sec
693780                        hb = 4;
694781                        if (v == 0xab) dosver = 1;
695782                        }
696                  else
783                     else
697784                        hb = 0;
698785
699786                  if(hb == 4) {
787                        printf("hb = 4\n");
700788                        UINT8 h[11];
701789                        for(int i=0; i<11; i++)
702790                              h[i] = gb(buf, ts, pos, wrap);
r29575r29576
706794                        UINT8 se = gcr4_decode(h[4],h[5]);
707795                        UINT8 chk = gcr4_decode(h[6],h[7]);
708796                        UINT32 post = (h[8]<<16)|(h[9]<<8)|h[10];
797                        #ifdef VERBOSE_SAVE
709798                        printf("Address Mark:\tVolume %d, Track %d, Sector %2d, Checksum %02X: %s, Postamble %03X: %s\n", vl, tr, se, chk, (chk ^ vl ^ tr ^ se)==0?"OK":"BAD", post, (post&0xFFFF00)==0xDEAA00?"OK":"BAD");
799                        #endif
710800                        // sanity check
711                        if (tr == track/2 && se < nsect) {
712                        visualgrid[se][track/2] |= ADDRFOUND;
713                        visualgrid[se][track/2] |= ((chk ^ vl ^ tr ^ se)==0)?ADDRGOOD:0;
801                        if (tr == track && se < nsect) {
802                        visualgrid[se][track] |= ADDRFOUND;
803                        visualgrid[se][track] |= ((chk ^ vl ^ tr ^ se)==0)?ADDRGOOD:0;
714804#ifdef LENIENT_ADDR_CHECK
715                           if ((visualgrid[se][track/2] & ADDRFOUND) == ADDRFOUND) {
805                           if ((visualgrid[se][track] & ADDRFOUND) == ADDRFOUND) {
716806#else
717                           if ((visualgrid[se][track/2] & ADDRGOOD) == ADDRGOOD) {
807                           if ((visualgrid[se][track] & ADDRGOOD) == ADDRGOOD) {
718808#endif
719809                              int opos = pos;
720810                              int owrap = wrap;
r29575r29576
733823                                          hb = 0;
734824                              }
735825                              if((hb == 4)&&(dosver == 0)) {
736                                    visualgrid[se][track/2] |= DATAFOUND;
737                                    int sector_translate[16] = {
738#if SECTOR_ORDER == 0
739                                    // logical order (0-15)
740                                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
741                                    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
742#elif SECTOR_ORDER == 1
743                                    // DOS order (*.do)
744                                    0x00, 0x07, 0x0E, 0x06, 0x0D, 0x05, 0x0C, 0x04,
745                                    0x0B, 0x03, 0x0A, 0x02, 0x09, 0x01, 0x08, 0x0F
746#elif SECTOR_ORDER == 2
747                                    // prodos order (*.po)
748                                    0x00, 0x08, 0x01, 0x09, 0x02, 0x0A, 0x03, 0x0B,
749                                    0x04, 0x0C, 0x05, 0x0D, 0x06, 0x0E, 0x07, 0x0F
750#endif
751                                    };
752                                    UINT8 *dest = sectdata+(256)*sector_translate[se];
826                                    visualgrid[se][track] |= DATAFOUND;
827                                    UINT8 *dest;
753828                                    UINT8 data[0x157];
754829                                    UINT32 dpost = 0;
755830                                    UINT8 c = 0;
831
832                                    if (m_prodos_order)
833                                    {
834                                       dest = sectdata+(256)*prodos_skewing[se];
835                                    }
836                                    else
837                                    {
838                                       dest = sectdata+(256)*dos_skewing[se];
839                                    }
840
756841                                    // first read in sector and decode to 6bit form
757842                                    for(int i=0; i<0x156; i++) {
758843                                          data[i] = gcr6bw_tb[gb(buf, ts, pos, wrap)] ^ c;
r29575r29576
780865                                    // if it is set we don't want to overwrite a guaranteed good read with a bad one
781866                                    // if past read had a bad checksum or bad postamble...
782867#ifndef USE_OLD_BEST_SECTOR_PRIORITY
783                                    if (((visualgrid[se][track/2]&DATAGOOD)==0)||((visualgrid[se][track/2]&DATAPOST)==0)) {
868                                    if (((visualgrid[se][track]&DATAGOOD)==0)||((visualgrid[se][track]&DATAPOST)==0)) {
784869                                       // if the current read is good, and postamble is good, write it in, no matter what.
785870                                       // if the current read is good and the current postamble is bad, write it in unless the postamble was good before
786871                                       // if the current read is bad and the current postamble is good and the previous read had neither good, write it in
787872                                       // if the current read isn't good and neither is the postamble but nothing better
788873                                       // has been written before, write it anyway.
789874                                       if ( ((data[0x156] == c) && (dpost&0xFFFF00)==0xDEAA00) ||
790                                       (((data[0x156] == c) && (dpost&0xFFFF00)!=0xDEAA00) && ((visualgrid[se][track/2]&DATAPOST)==0)) ||
791                                       (((data[0x156] != c) && (dpost&0xFFFF00)==0xDEAA00) && (((visualgrid[se][track/2]&DATAGOOD)==0)&&(visualgrid[se][track/2]&DATAPOST)==0)) ||
792                                       (((data[0x156] != c) && (dpost&0xFFFF00)!=0xDEAA00) && (((visualgrid[se][track/2]&DATAGOOD)==0)&&(visualgrid[se][track/2]&DATAPOST)==0))
875                                       (((data[0x156] == c) && (dpost&0xFFFF00)!=0xDEAA00) && ((visualgrid[se][track]&DATAPOST)==0)) ||
876                                       (((data[0x156] != c) && (dpost&0xFFFF00)==0xDEAA00) && (((visualgrid[se][track]&DATAGOOD)==0)&&(visualgrid[se][track]&DATAPOST)==0)) ||
877                                       (((data[0x156] != c) && (dpost&0xFFFF00)!=0xDEAA00) && (((visualgrid[se][track]&DATAGOOD)==0)&&(visualgrid[se][track]&DATAPOST)==0))
793878                                       ) {
794879                                          for(int i=0x56; i<0x156; i++) {
795880                                             UINT8 dv = data[i];
r29575r29576
798883                                       }
799884                                    }
800885#else
801                                    if ((visualgrid[se][track/2]&DATAGOOD)==0) {
886                                    if ((visualgrid[se][track]&DATAGOOD)==0) {
802887                                          for(int i=0x56; i<0x156; i++) {
803888                                             UINT8 dv = data[i];
804889                                             *dest++ = dv;
r29575r29576
806891                                    }
807892#endif
808893                                    // do some checking
894                                    #ifdef VERBOSE_SAVE
809895                                    if ((data[0x156] != c) || (dpost&0xFFFF00)!=0xDEAA00)
810896                                       fprintf(stderr,"Data Mark:\tChecksum xpctd %d found %d: %s, Postamble %03X: %s\n", data[0x156], c, (data[0x156]==c)?"OK":"BAD", dpost, (dpost&0xFFFF00)==0xDEAA00?"OK":"BAD");
811                                    if (data[0x156] == c) visualgrid[se][track/2] |= DATAGOOD;
812                                    if ((dpost&0xFFFF00)==0xDEAA00) visualgrid[se][track/2] |= DATAPOST;
897                                    #endif
898                                    if (data[0x156] == c) visualgrid[se][track] |= DATAGOOD;
899                                    if ((dpost&0xFFFF00)==0xDEAA00) visualgrid[se][track] |= DATAPOST;
813900                              } else if ((hb == 4)&&(dosver == 1)) {
814901                                 fprintf(stderr,"ERROR: We don't handle dos sectors below 3.3 yet!\n");
815902                              } else {
r29575r29576
832919            //printf("\n");
833920      }
834921      // display a little table of which sectors decoded ok
922      #ifdef VERBOSE_SAVE
835923      int total_good = 0;
836924      for (int j = 0; j < 35; j++) {
837925         printf("T%2d: ",j);
r29575r29576
848936         printf("\n");
849937      }
850938      printf("Total Good Sectors: %d\n", total_good);
939      #endif
851940
852941      return true;
853942}
trunk/src/lib/formats/ap2_dsk.h
r29575r29576
5151
5252      UINT8 gb(const UINT8 *buf, int ts, int &pos, int &wrap);
5353      void update_chk(const UINT8 *data, int size, UINT32 &chk);
54
55      bool m_prodos_order;
5456};
5557
5658extern const floppy_format_type FLOPPY_A216S_FORMAT;
trunk/src/mess/drivers/apple2.c
r29575r29576
190190#include "bus/a2bus/a2bus.h"
191191#include "bus/a2bus/a2lang.h"
192192#include "bus/a2bus/a2diskii.h"
193#include "bus/a2bus/a2diskiing.h"
193194#include "bus/a2bus/a2mockingboard.h"
194195#include "bus/a2bus/a2cffa.h"
195196#include "bus/a2bus/a2memexp.h"
r29575r29576
968969
969970static SLOT_INTERFACE_START(apple2_cards)
970971   SLOT_INTERFACE("diskii", A2BUS_DISKII)  /* Disk II Controller Card */
972   SLOT_INTERFACE("diskiing", A2BUS_DISKIING)  /* Disk II Controller Card, cycle-accurate version */
971973   SLOT_INTERFACE("mockingboard", A2BUS_MOCKINGBOARD)  /* Sweet Micro Systems Mockingboard */
972974   SLOT_INTERFACE("phasor", A2BUS_PHASOR)  /* Applied Engineering Phasor */
973975   SLOT_INTERFACE("cffa2", A2BUS_CFFA2)  /* CFFA2000 Compact Flash for Apple II (www.dreher.net), 65C02/65816 firmware */
r29575r29576
10571059   MCFG_A2BUS_SLOT_ADD("a2bus", "sl3", apple2_cards, NULL)
10581060   MCFG_A2BUS_SLOT_ADD("a2bus", "sl4", apple2_cards, "mockingboard")
10591061   MCFG_A2BUS_SLOT_ADD("a2bus", "sl5", apple2_cards, NULL)
1060   MCFG_A2BUS_SLOT_ADD("a2bus", "sl6", apple2_cards, "diskii")
1062   MCFG_A2BUS_SLOT_ADD("a2bus", "sl6", apple2_cards, "diskiing")
10611063   MCFG_A2BUS_SLOT_ADD("a2bus", "sl7", apple2_cards, NULL)
10621064
10631065   MCFG_SOFTWARE_LIST_ADD("flop525_list","apple2")
r29575r29576
11701172   // TODO: populate the IIc's other virtual slots with ONBOARD_ADD
11711173   MCFG_A2BUS_ONBOARD_ADD("a2bus", "sl1", A2BUS_SSC, NULL)
11721174   MCFG_A2BUS_ONBOARD_ADD("a2bus", "sl2", A2BUS_SSC, NULL)
1173   MCFG_A2BUS_ONBOARD_ADD("a2bus", "sl6", A2BUS_DISKII, NULL)
1175   MCFG_A2BUS_ONBOARD_ADD("a2bus", "sl6", A2BUS_DISKIING, NULL)
11741176
11751177   MCFG_A2EAUXSLOT_SLOT_REMOVE("aux")
11761178   MCFG_A2EAUXSLOT_BUS_REMOVE(AUXSLOT_TAG)
trunk/src/mess/mess.mak
r29575r29576
515515MACHINES += TI99_HD
516516MACHINES += STRATA
517517MACHINES += CORVUSHD
518MACHINES += WOZFDC
518519
519520#-------------------------------------------------
520521# specify available bus cores

Previous 199869 Revisions Next


© 1997-2024 The MAME Team