Previous 199869 Revisions Next

r32068 Thursday 11th September, 2014 at 21:06:56 UTC by Fabio Priuli
setting the correct properties helps to commit new files. nw.
[src/emu/bus/nes]disksys.c* disksys.h*

trunk/src/emu/bus/nes/disksys.c
r0r32068
1/***********************************************************************************************************
2
3
4 NES/Famicom cartridge emulation for Disk System expansion
5
6 Copyright MESS Team.
7 Visit http://mamedev.org for licensing and usage restrictions.
8
9
10 Here we emulate the RAM expansion + Disk Drive which form the
11 Famicom Disk System.
12
13 Based on info from NESDev wiki ( http://wiki.nesdev.com/w/index.php/Family_Computer_Disk_System )
14 
15 TODO:
16   - convert floppy drive + fds format to modern code!
17   - add sound bits
18   - stop IRQ from using HOLD_LINE
19
20 ***********************************************************************************************************/
21
22
23#include "emu.h"
24#include "disksys.h"
25#include "cpu/m6502/m6502.h"
26#include "imagedev/flopdrv.h"
27#include "formats/nes_dsk.h"
28
29#ifdef NES_PCB_DEBUG
30   #define VERBOSE 1
31#else
32   #define VERBOSE 0
33#endif
34
35#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
36
37
38//-----------------------------------------------
39//
40//  Disk drive implementation
41//
42//-----------------------------------------------
43
44static const floppy_interface nes_floppy_interface =
45{
46   FLOPPY_STANDARD_5_25_DSHD,
47   LEGACY_FLOPPY_OPTIONS_NAME(nes_only),
48   "floppy_5_25"
49};
50
51static MACHINE_CONFIG_FRAGMENT( nes_disksys )
52   MCFG_LEGACY_FLOPPY_DRIVE_ADD(FLOPPY_0, nes_floppy_interface)
53MACHINE_CONFIG_END
54
55//-------------------------------------------------
56//  machine_config_additions - device-specific
57//  machine configurations
58//-------------------------------------------------
59
60machine_config_constructor nes_disksys_device::device_mconfig_additions() const
61{
62   return MACHINE_CONFIG_NAME( nes_disksys );
63}
64
65
66
67ROM_START( disksys )
68   ROM_REGION(0x2000, "drive", 0)
69   ROM_SYSTEM_BIOS( 0, "2c33a-01a", "Famicom Disk System Bios")
70   ROMX_LOAD( "rp2c33a-01a.bin", 0x0000, 0x2000, CRC(5e607dcf) SHA1(57fe1bdee955bb48d357e463ccbf129496930b62), ROM_BIOS(1)) // newer, Nintendo logo has no shadow
71   ROM_SYSTEM_BIOS( 1, "2c33-01", "Famicom Disk System Bios, older")
72   ROMX_LOAD( "rp2c33-01.bin", 0x0000, 0x2000, CRC(1c7ae5d5) SHA1(af5af53f66982e749643fdf8b2acbb7d4d3ed229), ROM_BIOS(2)) // older, Nintendo logo has shadow
73ROM_END
74
75//-------------------------------------------------
76//  rom_region - device-specific ROM region
77//-------------------------------------------------
78
79const rom_entry *nes_disksys_device::device_rom_region() const
80{
81   return ROM_NAME( disksys );
82}
83
84
85void nes_disksys_device::load_proc(device_image_interface &image)
86{
87   nes_disksys_device *disk_sys = static_cast<nes_disksys_device *>(image.device().owner());
88   disk_sys->load_disk(image);
89}
90
91void nes_disksys_device::unload_proc(device_image_interface &image)
92{
93   nes_disksys_device *disk_sys = static_cast<nes_disksys_device *>(image.device().owner());
94   disk_sys->unload_disk(image);
95}
96
97
98//------------------------------------------------
99//
100//  RAM expansion cart implementation
101//
102//------------------------------------------------
103
104const device_type NES_DISKSYS = &device_creator<nes_disksys_device>;
105
106
107nes_disksys_device::nes_disksys_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
108               : nes_nrom_device(mconfig, NES_DISKSYS, "FC RAM Expansion + Disk System PCB", tag, owner, clock, "fc_disksys", __FILE__),
109                  m_fds_data(NULL),
110                  m_disk(*this, FLOPPY_0),
111                  m_fds_sides(0)
112{
113}
114
115
116void nes_disksys_device::device_start()
117{
118   common_start();
119
120   m_2c33_rom = (UINT8*)memregion("drive")->base();
121
122   m_disk->floppy_install_load_proc(nes_disksys_device::load_proc);
123   m_disk->floppy_install_unload_proc(nes_disksys_device::unload_proc);
124
125   irq_timer = timer_alloc(TIMER_IRQ);
126   irq_timer->adjust(attotime::zero, 0, machine().device<cpu_device>("maincpu")->cycles_to_attotime(1));
127   
128   save_item(NAME(m_fds_motor_on));
129   save_item(NAME(m_fds_door_closed));
130   save_item(NAME(m_fds_current_side));
131   save_item(NAME(m_fds_head_position));
132   save_item(NAME(m_fds_status0));
133   save_item(NAME(m_read_mode));
134   save_item(NAME(m_drive_ready));   
135   save_item(NAME(m_irq_enable));
136   save_item(NAME(m_irq_transfer));
137   save_item(NAME(m_irq_count));
138   save_item(NAME(m_irq_count_latch));
139
140   save_item(NAME(m_fds_last_side));
141   save_item(NAME(m_fds_count));
142}
143
144void nes_disksys_device::pcb_reset()
145{
146   // read accesses in 0x6000-0xffff are always handled by
147   // cutom code below, so no need to setup the prg...
148   chr8(0, CHRRAM);
149   set_nt_mirroring(PPU_MIRROR_VERT);
150
151   m_fds_motor_on = 0;
152   m_fds_door_closed = 0;
153   m_fds_current_side = 1;
154   m_fds_head_position = 0;
155   m_fds_status0 = 0;
156   m_read_mode = 0;
157   m_drive_ready = 0;
158   m_irq_count = 0;
159   m_irq_count_latch = 0;
160   m_irq_enable = 0;
161   m_irq_transfer = 0;
162
163   m_fds_count = 0;
164   m_fds_last_side = 0;
165}
166
167
168/*-------------------------------------------------
169 mapper specific handlers
170 -------------------------------------------------*/
171
172/*-------------------------------------------------
173
174 RAM is in 0x6000-0xdfff (32K)
175 ROM is in 0xe000-0xffff (8K)
176 
177 registers + disk drive are accessed in
178 0x4020-0x403f (read_ex/write_ex below)
179
180 -------------------------------------------------*/
181
182WRITE8_MEMBER(nes_disksys_device::write_h)
183{
184   LOG_MMC(("Famicom Disk System write_h, offset %04x, data: %02x\n", offset, data));
185
186   if (offset < 0x6000)
187      m_prgram[offset + 0x2000] = data;
188}
189
190READ8_MEMBER(nes_disksys_device::read_h)
191{
192   LOG_MMC(("Famicom Disk System read_h, offset: %04x\n", offset));
193
194   if (offset < 0x6000)
195      return m_prgram[offset + 0x2000];
196   else
197      return m_2c33_rom[offset & 0x1fff];
198}
199
200WRITE8_MEMBER(nes_disksys_device::write_m)
201{
202   LOG_MMC(("Famicom Disk System write_m, offset: %04x, data: %02x\n", offset, data));
203   m_prgram[offset] = data;
204}
205
206READ8_MEMBER(nes_disksys_device::read_m)
207{
208   LOG_MMC(("Famicom Disk System read_m, offset: %04x\n", offset));
209   return m_prgram[offset];
210}
211
212void nes_disksys_device::hblank_irq(int scanline, int vblank, int blanked)
213{   
214   if (m_irq_transfer)
215      machine().device("maincpu")->execute().set_input_line(M6502_IRQ_LINE, HOLD_LINE);
216}
217
218WRITE8_MEMBER(nes_disksys_device::write_ex)
219{
220   LOG_MMC(("Famicom Disk System write_ex, offset: %04x, data: %02x\n", offset, data));
221   
222   if (offset >= 0x20 && offset < 0x60)
223   {
224      // wavetable
225   }
226
227   switch (offset)
228   {
229      case 0x00:
230         m_irq_count_latch = (m_irq_count_latch & 0xff00) | data;
231         break;
232      case 0x01:
233         m_irq_count_latch = (m_irq_count_latch & 0x00ff) | (data << 8);
234         break;
235      case 0x02:
236         m_irq_count = m_irq_count_latch;
237         m_irq_enable = BIT(data, 1);
238         break;
239      case 0x03:
240         // bit0 - Enable disk I/O registers
241         // bit1 - Enable sound I/O registers
242         break;
243      case 0x04:
244         // write data out to disk
245         // TEST!
246         if (m_fds_data && m_fds_current_side && !m_read_mode)
247            m_fds_data[(m_fds_current_side - 1) * 65500 + m_fds_head_position++] = data;
248         break;
249      case 0x05:
250         // $4025 - FDS Control
251         // bit0 - Drive Motor Control (0: Stop motor; 1: Turn on motor)
252         // bit1 - Transfer Reset (Set 1 to reset transfer timing to the initial state)
253         // bit2 - Read / Write mode (0: write; 1: read)
254         // bit3 - Mirroring (0: horizontal; 1: vertical)
255         // bit4 - CRC control (set during CRC calculation of transfer)
256         // bit5 - Always set to '1'
257         // bit6 - Read/Write Start (Set to 1 when the drive becomes ready for read/write)
258         // bit7 - Interrupt Transfer (0: Transfer without using IRQ; 1: Enable IRQ when
259         //        the drive becomes ready)
260         m_fds_motor_on = BIT(data, 0);
261         
262         if (BIT(data, 1))
263            m_fds_head_position = 0;
264         
265         if (!(data & 0x40) && m_drive_ready && m_fds_head_position > 2)
266            m_fds_head_position -= 2; // ??? is this some sort of compensation??
267         
268         m_read_mode = BIT(data, 2);
269         set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);         
270         m_drive_ready = data & 0x40;
271         m_irq_transfer = BIT(data, 7);
272         break;
273      case 0x06:
274         // external connector
275         break;
276      case 0x60:   // $4080 - Volume envelope - read through $4090
277      case 0x62:   // $4082 - Frequency low
278      case 0x63:   // $4083 - Frequency high
279      case 0x64:   // $4084 - Mod envelope - read through $4092
280      case 0x65:   // $4085 - Mod counter
281      case 0x66:   // $4086 - Mod frequency low
282      case 0x67:   // $4087 - Mod frequency high
283      case 0x68:   // $4088 - Mod table write
284      case 0x69:   // $4089 - Wave write / master volume
285      case 0x6a:   // $408a - Envelope speed
286         break;
287   }
288}
289
290READ8_MEMBER(nes_disksys_device::read_ex)
291{
292   LOG_MMC(("Famicom Disk System read_ex, offset: %04x\n", offset));
293   UINT8 ret = 0x00;
294
295   if (offset >= 0x20 && offset < 0x60)
296   {
297      // wavetable
298   }
299
300   switch (offset)
301   {
302      case 0x10:
303         // $4030 - disk status 0
304         // bit0 - Timer Interrupt (1: an IRQ occurred)
305         // bit1 - Byte transfer flag (Set to 1 every time 8 bits have been transfered between
306         //        the RAM adaptor & disk drive through $4024/$4031; Reset to 0 when $4024,
307         //        $4031, or $4030 has been serviced)
308         // bit4 - CRC control (0: CRC passed; 1: CRC error)
309         // bit6 - End of Head (1 when disk head is on the most inner track)
310         // bit7 - Disk Data Read/Write Enable (1 when disk is readable/writable)
311         ret = m_fds_status0 | 0x80;
312         // clear the disk IRQ detect flag
313         m_fds_status0 &= ~0x01;
314         break;
315      case 0x11:
316         // $4031 - data latch
317         // don't read data if disk is unloaded
318         if (!m_fds_data)
319            ret = 0;
320         else if (m_fds_current_side && m_read_mode)
321         {
322            ret = m_fds_data[(m_fds_current_side - 1) * 65500 + m_fds_head_position++];
323            if (m_fds_head_position == 65500)
324            {
325               printf("end of disk reached!\n");
326               m_fds_status0 |= 0x40;
327               m_fds_head_position -= 2;
328            }
329         }
330         else
331            ret = 0;
332         break;
333      case 0x12:
334         // $4032 - disk status 1:
335         // bit0 - Disk flag  (0: Disk inserted; 1: Disk not inserted)
336         // bit1 - Ready flag (0: Disk ready; 1: Disk not ready)
337         // bit2 - Protect flag (0: Not write protected; 1: Write protected or disk ejected)
338         if (!m_fds_data)
339            ret = 1;
340         else if (m_fds_last_side != m_fds_current_side)
341         {
342            // If we've switched disks, report "no disk" for a few reads
343            ret = 1;
344            m_fds_count++;
345            if (m_fds_count == 50)
346            {
347               m_fds_last_side = m_fds_current_side;
348               m_fds_count = 0;
349            }
350         }
351         else
352            ret = (m_fds_current_side == 0) ? 1 : 0; // 0 if a disk is inserted
353         break;
354      case 0x13:
355         // $4033 - external connector (bits 0-6) + battery status (bit 7)
356         ret = 0x80;
357         break;
358      case 0x70:   // $4090 - Volume gain - write through $4080
359      case 0x72:    // $4092 - Mod gain - read through $4084
360      default:
361         ret = 0x00;
362         break;
363   }
364   
365   return ret;
366}
367
368//-------------------------------------------------
369//  device_timer - handler timer events
370//-------------------------------------------------
371
372void nes_disksys_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
373{
374   if (id == TIMER_IRQ)
375   {     
376      if (m_irq_enable && m_irq_count)
377      {
378         m_irq_count--;
379         if (!m_irq_count)
380         {
381            machine().device("maincpu")->execute().set_input_line(M6502_IRQ_LINE, HOLD_LINE);
382            m_irq_enable = 0;
383            m_fds_status0 |= 0x01;
384            m_irq_count_latch = 0;   // used in Kaettekita Mario Bros
385         }
386      }
387   }
388}
389
390
391// Hacky helper to allow user to switch disk side with a simple key
392
393void nes_disksys_device::disk_flip_side()
394{
395   m_fds_current_side++;
396   if (m_fds_current_side > m_fds_sides)
397      m_fds_current_side = 0;
398
399   if (m_fds_current_side == 0)
400      popmessage("No disk inserted.");
401   else
402      popmessage("Disk set to side %d", m_fds_current_side);   
403}
404
405
406
407// Disk Loading / Unloading
408
409void nes_disksys_device::load_disk(device_image_interface &image)
410{
411   int header = 0;
412   m_fds_sides = 0;
413   
414   if (image.length() % 65500)
415      header = 0x10;
416   
417   m_fds_sides = (image.length() - header) / 65500;
418   
419   if (!m_fds_data)
420      m_fds_data = auto_alloc_array(machine(), UINT8, m_fds_sides * 65500);
421   
422   // if there is an header, skip it
423   image.fseek(header, SEEK_SET);
424   image.fread(m_fds_data, 65500 * m_fds_sides);
425   return;
426}
427
428void nes_disksys_device::unload_disk(device_image_interface &image)
429{
430   /* TODO: should write out changes here as well */
431   m_fds_sides =  0;
432}
433
Property changes on: trunk/src/emu/bus/nes/disksys.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/bus/nes/disksys.h
r0r32068
1#ifndef __NES_DISKSYS_H
2#define __NES_DISKSYS_H
3
4#include "nxrom.h"
5#include "imagedev/flopdrv.h"
6
7
8// ======================> nes_disksys_device
9
10class nes_disksys_device : public nes_nrom_device
11{
12public:
13   // construction/destruction
14   nes_disksys_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
15
16   // device-level overrides
17   virtual void device_start();
18   virtual machine_config_constructor device_mconfig_additions() const;
19   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
20   virtual const rom_entry *device_rom_region() const;
21
22   virtual DECLARE_READ8_MEMBER(read_ex);
23   virtual DECLARE_READ8_MEMBER(read_m);
24   virtual DECLARE_READ8_MEMBER(read_h);
25   virtual DECLARE_WRITE8_MEMBER(write_ex);
26   virtual DECLARE_WRITE8_MEMBER(write_m);
27   virtual DECLARE_WRITE8_MEMBER(write_h);
28
29   virtual void disk_flip_side();
30
31   virtual void hblank_irq(int scanline, int vblank, int blanked);
32   virtual void pcb_reset();
33
34   static void load_proc(device_image_interface &image);
35   static void unload_proc(device_image_interface &image);
36
37private:
38   UINT8 *m_2c33_rom;
39   UINT8 *m_fds_data;    // here, we store a copy of the disk
40   required_device<legacy_floppy_image_device> m_disk;
41
42   static const device_timer_id TIMER_IRQ = 0;
43   emu_timer *irq_timer;
44
45   void load_disk(device_image_interface &image);
46   void unload_disk(device_image_interface &image);
47
48   UINT16 m_irq_count, m_irq_count_latch;
49   int m_irq_enable, m_irq_transfer;
50
51   UINT8 m_fds_motor_on;
52   UINT8 m_fds_door_closed;
53   UINT8 m_fds_current_side;
54   UINT32 m_fds_head_position;
55   UINT8 m_fds_status0;
56   UINT8 m_read_mode;
57   UINT8 m_drive_ready;
58
59   UINT8 m_fds_sides;
60   int m_fds_last_side;
61   int m_fds_count;
62};
63
64
65
66// device type definition
67extern const device_type NES_DISKSYS;
68
69#endif
Property changes on: trunk/src/emu/bus/nes/disksys.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Previous 199869 Revisions Next


© 1997-2024 The MAME Team