Previous 199869 Revisions Next

r19979 Monday 31st December, 2012 at 22:47:32 UTC by Nathan Woods
[COCO1/2]  Rewrote the 6883 SAM memory management; should not be as slow when
switching between 64k RAM and ROM/RAM mode anymore.
[src/mess/machine]6883sam.c 6883sam.h

trunk/src/mess/machine/6883sam.c
r19978r19979
4949
5050#include "machine/6883sam.h"
5151
52
53//**************************************************************************
54//  CONSTANTS
55//**************************************************************************
56
57#define LOG_SAM      0
58
5259const device_type SAM6883 = &device_creator<sam6883_device>;
5360
5461
62
63//**************************************************************************
64//  DEVICE SETUP
65//**************************************************************************
66
5567//-------------------------------------------------
5668//  ctor
5769//-------------------------------------------------
5870
5971sam6883_device::sam6883_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
60   : device_t(mconfig, SAM6883, "SAM6883", tag, owner, clock)
72   : device_t(mconfig, SAM6883, "SAM6883", tag, owner, clock),
73     m_space_0000(*this),
74     m_space_8000(*this),
75     m_space_A000(*this),
76     m_space_C000(*this),
77     m_space_FF00(*this),
78     m_space_FF20(*this),
79     m_space_FF40(*this),
80     m_space_FF60(*this),
81     m_space_FFE0(*this)
6182{
6283   memset(m_banks, '\0', sizeof(m_banks));
6384}
r19978r19979
7293{
7394   const sam6883_interface *config = (const sam6883_interface *) static_config();
7495
75   /* find the CPU */
96   // find the CPU
7697   m_cpu = machine().device<cpu_device>(config->m_cpu_tag);
7798   m_cpu_space = &m_cpu->space(config->m_cpu_space);
7899
79   /* resolve callbacks */
100   // resolve callbacks
80101   m_res_input_func.resolve(config->m_input_func, *this);
81102
82   /* install SAM handlers */
103   // install SAM handlers
83104   m_cpu_space->install_read_handler(0xFFC0, 0xFFDF, 0, 0, read8_delegate(FUNC(sam6883_device::read), this));
84105   m_cpu_space->install_write_handler(0xFFC0, 0xFFDF, 0, 0, write8_delegate(FUNC(sam6883_device::write), this));
85106
86   /* save state support */
107   // save state support
87108   save_item(NAME(m_sam_state));
88109   save_item(NAME(m_counter));
89110   save_item(NAME(m_counter_xdiv));
r19978r19979
131152   switch(bank)
132153   {
133154      case 4:
134         update_bank(4, 0xFF00, 0xFF1F, 0x0000);
155         m_space_FF00.point(&m_banks[4], 0x0000);
135156         break;
136157      case 5:
137         update_bank(5, 0xFF20, 0xFF3F, 0x0000);
158         m_space_FF20.point(&m_banks[5], 0x0000);
138159         break;
139160      case 6:
140         update_bank(6, 0xFF40, 0xFF5F, 0x0000);
161         m_space_FF40.point(&m_banks[6], 0x0000);
141162         break;
142163      case 7:
143         update_bank(7, 0xFF60, 0xFFBF, 0x0000);
164         m_space_FF60.point(&m_banks[7], 0x0000);
144165         break;
145166      case 2:
146         update_bank(2, 0xFFE0, 0xFFFF, 0x1FE0);
167         m_space_FFE0.point(&m_banks[2], 0x1FE0);
147168         break;
148169   }
149170}
r19978r19979
195216
196217void sam6883_device::update_memory(void)
197218{
198   /* Memory size - allowed restricting memory accesses to something less than
199     * 32k
200     *
201     * This was a SAM switch that occupied 4 addresses:
202     *
203     *      $FFDD   (set)   R1
204     *      $FFDC   (clear) R1
205     *      $FFDB   (set)   R0
206     *      $FFDA   (clear) R0
207     *
208     * R1:R0 formed the following states:
209     *      00  - 4k
210     *      01  - 16k
211     *      10  - 64k
212     *      11  - static RAM (??)
213     *
214     * If something less than 64k was set, the low RAM would be smaller and
215     * mirror the other parts of the RAM
216     *
217     * TODO:  Find out what "static RAM" is
218     * TODO:  This should affect _all_ memory accesses, not just video ram
219     * TODO:  Verify that the CoCo 3 ignored this
220     */
219   // Memory size - allowed restricting memory accesses to something less than
220    // 32k
221    //
222    // This was a SAM switch that occupied 4 addresses:
223    //
224    //      $FFDD   (set)   R1
225    //      $FFDC   (clear) R1
226    //      $FFDB   (set)   R0
227    //      $FFDA   (clear) R0
228    //
229    // R1:R0 formed the following states:
230    //      00  - 4k
231    //      01  - 16k
232    //      10  - 64k
233    //      11  - static RAM (??)
234    //
235    // If something less than 64k was set, the low RAM would be smaller and
236    // mirror the other parts of the RAM
237    //
238    // TODO:  Find out what "static RAM" is
239    // TODO:  This should affect _all_ memory accesses, not just video ram
240    // TODO:  Verify that the CoCo 3 ignored this
221241
222   /* update $0000-$7FFF */
223   update_bank(0, 0x0000, 0x7FFF, m_sam_state & SAM_STATE_P1 ? 0x8000 : 0x0000);
242   // for now, lets assume that the caller is nice and made m_memory_size
243   // a power of two
244   UINT16 ram_mask = (UINT16) m_banks[0].m_memory_size - 1;
224245
225   if (m_sam_state & SAM_STATE_TY)
246   // switch depending on the M1/M0 variables
247   bool setup_rom = true;
248   switch(m_sam_state & (SAM_STATE_M1|SAM_STATE_M0))
226249   {
227      update_bank(0, 0x8000, 0xFEFF, 0x8000);
228   }
229   else
230   {
231      update_bank(1, 0x8000, 0x9FFF, 0x0000);
232      update_bank(2, 0xA000, 0xBFFF, 0x0000);
233      update_bank(3, 0xC000, 0xFEFF, 0x0000);
234   }
235}
250      case 0:
251         // 4K mode
252         m_space_0000.point(&m_banks[0], 0x0000, ram_mask);
253         m_counter_mask = 0x0FFF;
254         m_counter_or = 0x0000;
255         break;
236256
257      case SAM_STATE_M0:
258         // 16K mode
259         m_space_0000.point(&m_banks[0], 0x0000, ram_mask);
260         m_counter_mask = 0x3FFF;
261         m_counter_or = 0x0000;
262         break;
237263
264      case SAM_STATE_M1:
265      case SAM_STATE_M1|SAM_STATE_M0:
266         // 64k mode
267         if (m_sam_state & SAM_STATE_TY)
268         {
269            // full 64k RAM
270            m_space_0000.point(&m_banks[0], 0x0000, ram_mask);
271            m_space_8000.point(&m_banks[0], 0x8000);
272            m_space_A000.point(&m_banks[0], 0xA000);
273            m_space_C000.point(&m_banks[0], 0xC000);
274            m_counter_mask = 0xFFFF;
275            m_counter_or = 0x0000;
276            setup_rom = false;
277         }
278         else
279         {
280            // ROM/RAM
281            UINT16 ram_base = (m_sam_state & SAM_STATE_P1) ? 0x8000 : 0x0000;
282            m_space_0000.point(&m_banks[0], ram_base, ram_mask);
283            m_counter_mask = 0x7FFF;
284            m_counter_or = ram_base;
285         }
286         break;
287   }
238288
239//-------------------------------------------------
240//  install_memory
241//-------------------------------------------------
242
243void sam6883_device::install_memory(offs_t addrstart, offs_t addrend, void *memory, bool is_read_only)
244{
245   if (addrend >= addrstart)
289   if (setup_rom)
246290   {
247      if (memory == NULL)
248         m_cpu_space->unmap_readwrite(addrstart, addrend);
249      else if (is_read_only)
250         m_cpu_space->install_rom(addrstart, addrend, memory);
251      else
252         m_cpu_space->install_ram(addrstart, addrend, memory);
291      m_space_8000.point(&m_banks[1], 0x0000);
292      m_space_A000.point(&m_banks[2], 0x0000);
293      m_space_C000.point(&m_banks[3], 0x0000);
253294   }
254}
255295
256
257
258//-------------------------------------------------
259//  update_bank
260//-------------------------------------------------
261
262void sam6883_device::update_bank(int bank, offs_t addrstart, offs_t addrend, offs_t offset)
263{
264   assert((bank >= 0) && (bank < sizeof(m_banks) / sizeof(m_banks[0])));
265
266   if (m_banks[bank].m_memory != NULL)
267   {
268      /* this bank is a memory bank */
269      install_memory(addrstart, MIN(addrend, addrstart + m_banks[bank].m_memory_size - 1), m_banks[bank].m_memory + m_banks[bank].m_memory_offset + offset, m_banks[bank].m_memory_read_only);
270      install_memory(addrstart + m_banks[bank].m_memory_size, addrend, NULL, m_banks[bank].m_memory_read_only);
271   }
272   else
273   {
274      /* this bank uses handlers */
275      assert(offset == 0);   /* changes to the offset are not supported */
276      if (!m_banks[bank].m_rhandler.isnull())
277         m_cpu_space->install_read_handler(addrstart, addrend, 0, 0, m_banks[bank].m_rhandler);
278      if (!m_banks[bank].m_whandler.isnull())
279         m_cpu_space->install_write_handler(addrstart, addrend, 0, 0, m_banks[bank].m_whandler);
280   }
296   // update $FFE0-$FFFF
297   m_space_FFE0.point(&m_banks[2], 0x1FE0);
281298}
282299
283300
r19978r19979
289306
290307void sam6883_friend_device::update_cpu_clock(void)
291308{
292   /* The infamous speed up poke.
293     *
294     * This was a SAM switch that occupied 4 addresses:
295     *
296     *      $FFD9   (set)   R1
297     *      $FFD8   (clear) R1
298     *      $FFD7   (set)   R0
299     *      $FFD6   (clear) R0
300     *
301     * R1:R0 formed the following states:
302     *      00  - slow          0.89 MHz
303     *      01  - dual speed    ???
304     *      1x  - fast          1.78 MHz
305     *
306     * R1 controlled whether the video addressing was speeded up and R0
307     * did the same for the CPU.  On pre-CoCo 3 machines, setting R1 caused
308     * the screen to display garbage because the M6847 could not display
309     * fast enough.
310     *
311     * TODO:  Make the overclock more accurate.  In dual speed, ROM was a fast
312     * access but RAM was not.  I don't know how to simulate this.
313     */
309   // The infamous speed up poke.
310    //
311    // This was a SAM switch that occupied 4 addresses:
312    //
313    //      $FFD9   (set)   R1
314    //      $FFD8   (clear) R1
315    //      $FFD7   (set)   R0
316    //      $FFD6   (clear) R0
317    //
318    // R1:R0 formed the following states:
319    //      00  - slow          0.89 MHz
320    //      01  - dual speed    ???
321    //      1x  - fast          1.78 MHz
322    //
323    // R1 controlled whether the video addressing was speeded up and R0
324    // did the same for the CPU.  On pre-CoCo 3 machines, setting R1 caused
325    // the screen to display garbage because the M6847 could not display
326    // fast enough.
327    //
328    // TODO:  Make the overclock more accurate.  In dual speed, ROM was a fast
329    // access but RAM was not.  I don't know how to simulate this.
330
314331   int speed = (m_sam_state & (SAM_STATE_R1|SAM_STATE_R0)) / SAM_STATE_R0;
315332
316   /* the line below is weird because we are not strictly emulating the M6809E with emphasis on the 'E' */
333   // the line below is weird because we are not strictly emulating the M6809E with emphasis on the 'E'
317334   m_cpu->set_clock_scale(speed ? 2 : 1);
318335}
319336
r19978r19979
329346   {
330347      m_banks[bank].m_memory_offset = offset;
331348      update_memory();
332      update_bank(2, 0xFFE0, 0xFFFF, 0x1FE0);
333349   }
334350}
335351
r19978r19979
425441      horizontal_sync();
426442   }
427443}
444
445
446
447//-------------------------------------------------
448//  sam_space::ctor
449//-------------------------------------------------
450
451template<UINT16 _addrstart, UINT16 _addrend>
452sam6883_device::sam_space<_addrstart, _addrend>::sam_space(sam6883_device &owner)
453   : m_owner(owner)
454{
455   m_read_bank = NULL;
456   m_write_bank = NULL;
457   m_mask = 0;
458}
459
460
461
462//-------------------------------------------------
463//  sam_space::cpu_space
464//-------------------------------------------------
465
466template<UINT16 _addrstart, UINT16 _addrend>
467address_space &sam6883_device::sam_space<_addrstart, _addrend>::cpu_space() const
468{
469   assert(m_owner.m_cpu_space != NULL);
470   return *m_owner.m_cpu_space;
471}
472
473
474
475//-------------------------------------------------
476//  sam_space::point
477//-------------------------------------------------
478
479template<UINT16 _addrstart, UINT16 _addrend>
480void sam6883_device::sam_space<_addrstart, _addrend>::point(const sam_bank *bank, UINT16 offset, UINT16 mask)
481{
482   if (LOG_SAM)
483   {
484      logerror("sam6883_device::sam_space::point():  addrstart=0x%04X addrend=0x%04X offset=0x%04X mask=0x%04X bank->m_memory=0x%p bank->m_memory_read_only=%s\n",
485         (unsigned) _addrstart,
486         (unsigned) _addrend,
487         (unsigned) offset,
488         (unsigned) mask,
489         bank->m_memory,
490         bank->m_memory_read_only ? "true" : "false");
491   }
492
493   point_specific_bank(bank, offset, mask, m_read_bank, _addrstart, _addrend, false);
494   point_specific_bank(bank, offset, mask, m_write_bank, _addrstart, _addrend, true);
495}
496
497
498
499//-------------------------------------------------
500//  sam_space::point_specific_bank
501//-------------------------------------------------
502template<UINT16 _addrstart, UINT16 _addrend>
503void sam6883_device::sam_space<_addrstart, _addrend>::point_specific_bank(const sam_bank *bank, UINT16 offset, UINT16 mask, memory_bank *&memory_bank, INT32 addrstart, INT32 addrend, bool is_write)
504{
505   char buffer[16];
506
507   if (bank->m_memory != NULL)
508   {
509      // normalize offset
510      if (mask != 0)
511         offset &= mask;
512
513      // this bank is a memory bank - first ensure that we have a bank
514      if (!memory_bank || !memory_bank->matches_exactly(addrstart, addrend) || (mask != m_mask))
515      {
516         // name the bank
517         snprintf(buffer, ARRAY_LENGTH(buffer), "bank%04X_%c", addrstart, is_write ? 'w' : 'r');
518
519         // install it
520         if (is_write)
521            cpu_space().install_write_bank(addrstart, addrend, mask, 0, buffer);
522         else
523            cpu_space().install_read_bank(addrstart, addrend, mask, 0, buffer);
524         m_mask = mask;
525
526         // and get it
527         memory_bank = cpu_space().device().owner()->membank(buffer);
528      }
529
530      // point the bank
531      if (memory_bank != NULL)
532      {
533         if (is_write && bank->m_memory_read_only)
534            memory_bank->set_base(m_owner.m_dummy);
535         else
536            memory_bank->set_base(bank->m_memory + offset);
537      }
538   }
539   else
540   {
541      // this bank uses handlers
542      assert((offset == 0) && (mask == 0));   // changes to the offset are not supported
543
544      if (is_write)
545      {
546         if (!bank->m_whandler.isnull())
547            cpu_space().install_write_handler(addrstart, addrend, 0, 0, bank->m_whandler);
548      }
549      else
550      {
551         if (!bank->m_rhandler.isnull())
552            cpu_space().install_read_handler(addrstart, addrend, 0, 0, bank->m_rhandler);
553      }
554   }
555}
trunk/src/mess/machine/6883sam.h
r19978r19979
120120         if (bit3_carry)
121121            counter_carry_bit3();
122122      }
123      return m_res_input_func(m_counter);
123      return m_res_input_func((m_counter & m_counter_mask) | m_counter_or);
124124   }
125125
126126   DECLARE_WRITE_LINE_MEMBER( hs_w );
r19978r19979
136136   virtual void device_post_load();
137137
138138private:
139   // represents an external memory bank - memory or IO that the SAM
140   // points to with the S2/S1/S0 output
139141   struct sam_bank
140142   {
141      UINT8 *         m_memory;
142      UINT32         m_memory_size;
143      offs_t         m_memory_offset;
144      bool         m_memory_read_only;
145      read8_delegate   m_rhandler;
146      write8_delegate   m_whandler;
143      UINT8 *            m_memory;
144      UINT32            m_memory_size;
145      offs_t            m_memory_offset;
146      bool            m_memory_read_only;
147      read8_delegate      m_rhandler;
148      write8_delegate      m_whandler;
147149   };
148150
151   // represents one of the memory "spaces" (e.g. - $8000-$9FFF) that
152   // can ultimately point to a bank
153   template<UINT16 _addrstart, UINT16 _addrend>
154   class sam_space
155   {
156   public:
157      sam_space(sam6883_device &owner);
158      void point(const sam_bank *bank, UINT16 offset, UINT16 mask = 0);
159
160   private:
161      sam6883_device &   m_owner;
162      memory_bank *      m_read_bank;
163      memory_bank *      m_write_bank;
164      UINT16            m_mask;
165
166      address_space &cpu_space() const;
167      void point_specific_bank(const sam_bank *bank, UINT16 offset, UINT16 mask, memory_bank *&memory_bank, INT32 addrstart, INT32 addrend, bool is_write);
168   };
169
149170   // incidentals
150   address_space *         m_cpu_space;
151   devcb_resolved_read8   m_res_input_func;
152   sam_bank            m_banks[8];
171   address_space *            m_cpu_space;
172   devcb_resolved_read8      m_res_input_func;
173   sam_bank               m_banks[8];
174   sam_space<0x0000, 0x7FFF>   m_space_0000;
175   sam_space<0x8000, 0x9FFF>   m_space_8000;
176   sam_space<0xA000, 0xBFFF>   m_space_A000;
177   sam_space<0xC000, 0xFEFF>   m_space_C000;
178   sam_space<0xFF00, 0xFF1F>   m_space_FF00;
179   sam_space<0xFF20, 0xFF3F>   m_space_FF20;
180   sam_space<0xFF40, 0xFF5F>   m_space_FF40;
181   sam_space<0xFF60, 0xFFBF>   m_space_FF60;
182   sam_space<0xFFE0, 0xFFFF>   m_space_FFE0;
183   UINT16                  m_counter_mask;
184   UINT16                  m_counter_or;
153185
154186   // SAM state
155   UINT16               m_counter;
156   UINT8               m_counter_xdiv;
157   UINT8               m_counter_ydiv;
187   UINT16                  m_counter;
188   UINT8                  m_counter_xdiv;
189   UINT8                  m_counter_ydiv;
158190
191   // dummy scratch memory
192   UINT8                  m_dummy[0x8000];
193
159194   // typically called by CPU
160195    DECLARE_READ8_MEMBER( read );
161196    DECLARE_WRITE8_MEMBER( write );
r19978r19979
219254   void horizontal_sync(void);
220255   void update_state(void);
221256   void update_memory(void);
222   void update_bank(int bank, offs_t addrstart, offs_t addrend, offs_t offset);
223   void install_memory(offs_t addrstart, offs_t addrend, void *memory, bool is_read_only);
224257};
225258
226259extern const device_type SAM6883;

Previous 199869 Revisions Next


© 1997-2024 The MAME Team