Previous 199869 Revisions Next

r20797 Thursday 7th February, 2013 at 13:53:42 UTC by Nathan Woods
[COCO/MC6847] Made the MC6847 emulation support mid-scanline video mode changes.
This will enable the video in the CoCo 2 game "Dragon Fire" to work correctly
when we get a cycle exact 6809 emulation.
[src/mess/video]gime.c gime.h mc6847.c mc6847.h

trunk/src/mess/video/gime.c
r20796r20797
107107//-------------------------------------------------
108108
109109gime_base_device::gime_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const UINT8 *fontdata)
110   :   mc6847_friend_device(mconfig, type, name, tag, owner, clock, fontdata, true, 263, 25+192+26+3)
110   :   mc6847_friend_device(mconfig, type, name, tag, owner, clock, fontdata, true, 263, 25+192+26+3, false)
111111{
112112}
113113
r20796r20797
15471547
15481548
15491549//-------------------------------------------------
1550//  record_partial_body_scanline
1551//-------------------------------------------------
1552
1553void gime_base_device::record_partial_body_scanline(UINT16 physical_scanline, UINT16 logical_scanline, INT32 start_clock, INT32 end_clock)
1554{
1555   fatalerror("NYI");
1556}
1557
1558
1559
1560//-------------------------------------------------
15501561//  update_geometry
15511562//-------------------------------------------------
15521563
trunk/src/mess/video/gime.h
r20796r20797
100100   virtual void enter_bottom_border(void);
101101   virtual void record_border_scanline(UINT16 physical_scanline);
102102   virtual void record_body_scanline(UINT16 physical_scanline, UINT16 logical_scanline);
103   virtual void record_partial_body_scanline(UINT16 physical_scanline, UINT16 logical_scanline, INT32 start_clock, INT32 end_clock);
103104
104105private:
105106   typedef mc6847_friend_device super;
trunk/src/mess/video/mc6847.c
r20796r20797
3131    suggestions.  Mismatching modes is responsible for the semigraphic modes
3232    on the CoCo.
3333
34    Timing:
35    (source Motorola M6847 Manual)
34    Timing:    (source Motorola M6847 Manual, experimentation, SockMaster)
3635
37    Horizontal Sync:  Total Period: 227.5 clock cycles
36    Horizontal Sync:  Total Period: 228 clock cycles
3837        @ CLK(0) + DHS_F            - falling edge (high to low)
3938        @ CLK(16.5) + DHS_R         - rising edge (low to high)
4039        @ CLK(42)                   - left border start
4140        @ CLK(71.5)                 - body start
4241        @ CLK(199.5)                - right border start
43        @ CLK(227.5) + DHS_F        - falling edge (high to low)
42        @ CLK(228) + DHS_F          - falling edge (high to low)
4443        ...
4544
46    Field Sync: Total Period 262*227.5 clock cycles
45    Field Sync: Total Period 262*228 clock cycles
4746        @ CLK(0) + DFS_F            - falling edge (high to low)
48        @ CLK(32*227.5) + DFS_R     - rising edge (low to high)
49        @ CLK(262*227.5) + DFS_F    - falling edge (high to low) (262.5 for the M6847Y)
47        @ CLK(32*228) + DFS_R       - rising edge (low to high)
48        @ CLK(262*228) + DFS_F      - falling edge (high to low) (262.5 for the M6847Y)
5049
5150    DHS_F:  550ns
5251    DHS_R:  740ns
r20796r20797
5958    assuming that the extra text modes on the CoCo 2B are activated by the
6059    GM2-0 pins.  This needs to be confirmed.
6160
61   The MC6847 datasheet states that a scanline is 227.5 clock cycles,
62   but experimentation suggests that it is 228.  The game "Dragon Fire"
63   has a fine tuned loop that runs in 57 clock cycles by the CPU's
64   reckoning (228 actual clock cycles) and would not function correctly
65   if skew existed.  SockMaster has confirmed that scanlines are in
66   fact 228 clock cycles.
67
6268**********************************************************************/
6369
6470
r20796r20797
7379#define TOP_BORDER              25
7480#define USE_HORIZONTAL_CLIP     false
7581
76#define TIMER_HSYNC_PERIOD      (227.5)
82#define TIMER_HSYNC_PERIOD      (228)
7783#define TIMER_HSYNC_OFF_TIME    (10.0)
7884#define TIMER_HSYNC_ON_TIME     (TIMER_HSYNC_OFF_TIME + 16.5)
7985#define TIMER_FSYNC_OFF_TIME    (TIMER_HSYNC_PERIOD * TOP_BORDER + TIMER_HSYNC_ON_TIME)
r20796r20797
8187
8288#define LOG_SCANLINE            0
8389#define LOG_HSYNC               0
84#define LOG_FSYNC               0
90#define LOG_FSYNC               1
91#define LOG_FLUSH            1
92#define LOG_INPUT            0
8593
8694
8795const UINT32 mc6847_base_device::s_palette[mc6847_base_device::PALETTE_LENGTH] =
r20796r20797
117125//-------------------------------------------------
118126
119127mc6847_friend_device::mc6847_friend_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock,
120      const UINT8 *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline)
128      const UINT8 *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, bool supports_partial_body_scanlines)
121129   : device_t(mconfig, type, name, tag, owner, clock),
122      m_character_map(fontdata, is_mc6847t1)
130     m_character_map(fontdata, is_mc6847t1)
123131{
124132   m_tpfs = tpfs;
133   m_supports_partial_body_scanlines = supports_partial_body_scanlines;
125134
126135   // The MC6847 and the GIME apply field sync on different scanlines
127136   m_field_sync_falling_edge_scanline = field_sync_falling_edge_scanline;
r20796r20797
161170   m_top_border_scanlines = 0;
162171   m_body_scanlines = 0;
163172   m_wide = false;
173   m_recording_scanline = false;
164174   set_geometry(25, 192, false);
165175
166176   /* save states */
r20796r20797
295305            break;
296306
297307         case SCANLINE_ZONE_BODY:
298            record_body_scanline(m_physical_scanline, m_logical_scanline);
308            m_recording_scanline = true;
309            if (m_partial_scanline_clocks > 0)
310               record_partial_body_scanline(m_physical_scanline, m_logical_scanline, m_partial_scanline_clocks, 228);
311            else
312               record_body_scanline(m_physical_scanline, m_logical_scanline);
313            m_recording_scanline = false;
299314            break;
300315
301316         case SCANLINE_ZONE_RETRACE:
r20796r20797
369384   /* advance to next scanline */
370385   m_physical_scanline++;
371386   m_logical_scanline++;
387   m_partial_scanline_clocks = 0;
372388
373389   /* check for movement into the next "zone" */
374390   if (m_logical_scanline_zone == SCANLINE_ZONE_FRAME_END)
r20796r20797
447463
448464
449465//-------------------------------------------------
466//  get_clocks_since_hsync
467//-------------------------------------------------
468
469INT32 mc6847_friend_device::get_clocks_since_hsync()
470{
471   UINT64 hsync_on_clocks = attotime_to_clocks(m_hsync_on_timer->start());
472   UINT64 current_clocks = attotime_to_clocks(machine().time());
473   return (INT32) (current_clocks - hsync_on_clocks);
474}
475
476
477
478//-------------------------------------------------
450479//  video_flush
451480//-------------------------------------------------
452481
453void mc6847_friend_device::video_flush(void)
482void mc6847_friend_device::video_flush()
454483{
484   // first, only flush if...
485   //   1.  We support partial scanlines
486   //   2.  We're not already recording
487   //   3.  We're in the body
488   if (m_supports_partial_body_scanlines && !m_recording_scanline && (m_logical_scanline_zone == SCANLINE_ZONE_BODY))
489   {
490      UINT32 new_partial_scanline_clocks = get_clocks_since_hsync();
491      if (m_partial_scanline_clocks < new_partial_scanline_clocks)
492      {
493         if (LOG_FLUSH)
494            logerror("%s: new_partial_scanline_clocks=%u\n", describe_context(), new_partial_scanline_clocks);
495
496         m_recording_scanline = true;
497         record_partial_body_scanline(m_physical_scanline, m_logical_scanline, m_partial_scanline_clocks, new_partial_scanline_clocks);
498         m_recording_scanline = false;
499
500         m_partial_scanline_clocks = new_partial_scanline_clocks;
501      }
502   }
455503}
456504
457505
r20796r20797
481529//-------------------------------------------------
482530
483531mc6847_base_device::mc6847_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const UINT8 *fontdata, double tpfs)
484   :   mc6847_friend_device(mconfig, type, name, tag, owner, clock, fontdata, (type == MC6847T1_NTSC) || (type == MC6847T1_PAL), tpfs, 25+191)
532   :   mc6847_friend_device(mconfig, type, name, tag, owner, clock, fontdata, (type == MC6847T1_NTSC) || (type == MC6847T1_PAL), tpfs, 25+191, true)
485533{
486534   m_palette = s_palette;
487535
r20796r20797
576624
577625
578626//-------------------------------------------------
627//  input
628//-------------------------------------------------
629
630UINT8 mc6847_base_device::input(UINT16 address)
631{
632   UINT8 data = m_res_input_func(address);
633   if (LOG_INPUT)
634      logerror("%s: input: address=0x%04X data=0x%02X\n", describe_context(), address, data);
635   return data;
636}
637
638
639
640//-------------------------------------------------
579641//  record_scanline_res
580642//-------------------------------------------------
581643
582644template<int sample_count, int yres>
583void mc6847_base_device::record_scanline_res(int scanline)
645void mc6847_base_device::record_scanline_res(int scanline, INT32 start_pos, INT32 end_pos)
584646{
585   int i, column;
586   UINT8 data;
647   UINT8 current_sample_count = (start_pos > 0) ? m_data[scanline].m_sample_count : 0;
587648
588   /* calculate offset */
589   offs_t offset = scanline / (192 / yres) * sample_count;
590
591   /* main loop */
592   for (column = 0; column < sample_count; column++)
649   // main loop
650   for (INT32 pos = start_pos; pos < end_pos; pos++)
593651   {
594      /* input data */
595      data = m_res_input_func(offset++);
652      // set address at beginning of line
653      if (pos == 0)
654         m_video_address = scanline / (192 / yres) * sample_count;
596655
597      /* update values */
598      update_value(&m_data[scanline].m_mode[column], simplify_mode(data, m_mode));
599      update_value(&m_data[scanline].m_data[column], data);
600   }
656      if ((sample_count == 32) || ((pos % 1) == 0))
657      {
658         // input data
659         UINT8 data = input(m_video_address++);
601660
602   /* several more inputs occur after hblank */
603   for (i = 0; i < sample_count * 5 / 16; i++)
604   {
605      data = m_res_input_func(offset++);
661         if (pos < 32)
662         {
663            // update values
664            assert(current_sample_count >= 0);
665            assert(current_sample_count < ARRAY_LENGTH(m_data[scanline].m_mode));
666            update_value(&m_data[scanline].m_mode[current_sample_count], simplify_mode(data, m_mode));
667            update_value(&m_data[scanline].m_data[current_sample_count], data);
668            current_sample_count++;
669         }
670      }
606671   }
607672
608   /* update sample count */
609   update_value(&m_data[scanline].m_sample_count, (UINT8) sample_count);
673   // update sample count
674   update_value(&m_data[scanline].m_sample_count, current_sample_count);
610675}
611676
612677
r20796r20797
615680//  record_body_scanline
616681//-------------------------------------------------
617682
618void mc6847_base_device::record_body_scanline(UINT16 physical_scanline, UINT16 scanline)
683ATTR_FORCE_INLINE void mc6847_base_device::record_body_scanline(UINT16 physical_scanline, UINT16 scanline, INT32 start_pos, INT32 end_pos)
619684{
620685   // sanity checks
621686   assert(scanline < 192);
r20796r20797
626691      {
627692         case 0:
628693         case MODE_GM0:
629            record_scanline_res<16, 64>(scanline);
694            record_scanline_res<16, 64>(scanline, start_pos, end_pos);
630695            break;
631696
632697         case MODE_GM1:
633            record_scanline_res<32, 64>(scanline);
698            record_scanline_res<32, 64>(scanline, start_pos, end_pos);
634699            break;
635700
636701         case MODE_GM1|MODE_GM0:
637            record_scanline_res<16, 96>(scanline);
702            record_scanline_res<16, 96>(scanline, start_pos, end_pos);
638703            break;
639704
640705         case MODE_GM2:
641            record_scanline_res<32, 96>(scanline);
706            record_scanline_res<32, 96>(scanline, start_pos, end_pos);
642707            break;
643708
644709         case MODE_GM2|MODE_GM0:
645            record_scanline_res<16, 192>(scanline);
710            record_scanline_res<16, 192>(scanline, start_pos, end_pos);
646711            break;
647712
648713         case MODE_GM2|MODE_GM1:
649714         case MODE_GM2|MODE_GM1|MODE_GM0:
650            record_scanline_res<32, 192>(scanline);
715            record_scanline_res<32, 192>(scanline, start_pos, end_pos);
651716            break;
652717
653718         default:
r20796r20797
658723   }
659724   else
660725   {
661      record_scanline_res<32, 16>(scanline);
726      record_scanline_res<32, 16>(scanline, start_pos, end_pos);
662727   }
663728}
664729
665730
666731
667732//-------------------------------------------------
733//  record_body_scanline
734//-------------------------------------------------
735
736void mc6847_base_device::record_body_scanline(UINT16 physical_scanline, UINT16 scanline)
737{
738   record_body_scanline(physical_scanline, scanline, 0, 32);
739}
740
741
742
743//-------------------------------------------------
744//  record_partial_body_scanline
745//-------------------------------------------------
746
747void mc6847_base_device::record_partial_body_scanline(UINT16 physical_scanline, UINT16 scanline, INT32 start_clock, INT32 end_clock)
748{
749   INT32 start_pos = MAX(scanline_position_from_clock(start_clock), 0);
750   INT32 end_pos = MIN(scanline_position_from_clock(end_clock), 42);
751
752   if (start_pos < end_pos)
753      record_body_scanline(physical_scanline, scanline, start_pos, end_pos);
754}
755
756
757
758//-------------------------------------------------
759//  scanline_position_from_clock
760//-------------------------------------------------
761
762INT32 mc6847_base_device::scanline_position_from_clock(INT32 clocks_since_hsync)
763{
764   return (clocks_since_hsync - 20) / 4;
765}
766
767
768
769//-------------------------------------------------
668770//  field_sync_changed
669771//-------------------------------------------------
670772
r20796r20797
15641666//-------------------------------------------------
15651667
15661668mc6847_ntsc_device::mc6847_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1567   : mc6847_base_device(mconfig, MC6847_NTSC, "MC6847_NTSC", tag, owner, clock, ntsc_square_fontdata8x12, 227.0)
1669   : mc6847_base_device(mconfig, MC6847_NTSC, "MC6847_NTSC", tag, owner, clock, ntsc_square_fontdata8x12, 262.0)
15681670{
15691671}
15701672
r20796r20797
15751677//-------------------------------------------------
15761678
15771679mc6847_pal_device::mc6847_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1578   : mc6847_base_device(mconfig, MC6847_PAL, "MC6847_PAL", tag, owner, clock, pal_square_fontdata8x12, 227.0)
1680   : mc6847_base_device(mconfig, MC6847_PAL, "MC6847_PAL", tag, owner, clock, pal_square_fontdata8x12, 262.0)
15791681{
15801682}
15811683
r20796r20797
15861688//-------------------------------------------------
15871689
15881690mc6847y_ntsc_device::mc6847y_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1589   : mc6847_base_device(mconfig, MC6847Y_NTSC, "MC6847Y_NTSC", tag, owner, clock, ntsc_square_fontdata8x12, 227.5)
1691   : mc6847_base_device(mconfig, MC6847Y_NTSC, "MC6847Y_NTSC", tag, owner, clock, ntsc_square_fontdata8x12, 262.5)
15901692{
15911693}
15921694
r20796r20797
15971699//-------------------------------------------------
15981700
15991701mc6847y_pal_device::mc6847y_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1600   : mc6847_base_device(mconfig, MC6847Y_PAL, "MC6847Y_PAL", tag, owner, clock, pal_square_fontdata8x12, 227.5)
1702   : mc6847_base_device(mconfig, MC6847Y_PAL, "MC6847Y_PAL", tag, owner, clock, pal_square_fontdata8x12, 262.5)
16011703{
16021704}
16031705
r20796r20797
16081710//-------------------------------------------------
16091711
16101712mc6847t1_ntsc_device::mc6847t1_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1611   : mc6847_base_device(mconfig, MC6847T1_NTSC, "MC6847T1_NTSC", tag, owner, clock, ntsc_round_fontdata8x12, 227.0)
1713   : mc6847_base_device(mconfig, MC6847T1_NTSC, "MC6847T1_NTSC", tag, owner, clock, ntsc_round_fontdata8x12, 262.0)
16121714{
16131715}
16141716
r20796r20797
16191721//-------------------------------------------------
16201722
16211723mc6847t1_pal_device::mc6847t1_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1622   : mc6847_base_device(mconfig, MC6847T1_PAL, "MC6847T1_PAL", tag, owner, clock, pal_round_fontdata8x12, 227.0)
1724   : mc6847_base_device(mconfig, MC6847T1_PAL, "MC6847T1_PAL", tag, owner, clock, pal_round_fontdata8x12, 262.0)
16231725{
16241726}
trunk/src/mess/video/mc6847.h
r20796r20797
9191
9292protected:
9393   mc6847_friend_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock,
94      const UINT8 *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline);
94      const UINT8 *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, bool supports_partial_body_scanlines);
9595
9696   // video mode constants
9797   static const UINT8 MODE_AG      = 0x80;
r20796r20797
288288   virtual void enter_bottom_border(void);
289289   virtual void record_border_scanline(UINT16 physical_scanline);
290290   virtual void record_body_scanline(UINT16 physical_scanline, UINT16 logical_scanline) = 0;
291   virtual void record_partial_body_scanline(UINT16 physical_scanline, UINT16 logical_scanline, INT32 start_clock, INT32 end_clock) = 0;
291292
292293   // miscellaneous
293294   void video_flush(void);
r20796r20797
443444      return result;
444445   }
445446
446
447447private:
448448   enum scanline_zone
449449   {
r20796r20797
468468   bool m_video_changed;
469469   UINT16 m_top_border_scanlines;
470470   UINT16 m_body_scanlines;
471   bool m_recording_scanline;
472   bool m_supports_partial_body_scanlines;
471473
472474   // video state
473475   UINT16 m_physical_scanline;
r20796r20797
475477   UINT16 m_logical_scanline_zone;
476478   bool m_horizontal_sync;
477479   bool m_field_sync;
480   UINT32 m_partial_scanline_clocks;
478481
479482   // functions
480483   void change_horizontal_sync(bool line);
481484   void change_field_sync(bool line);
482485   void update_field_sync_timer(void);
483486   void next_scanline(void);
487   INT32 get_clocks_since_hsync();
484488
485489   // debugging
486490   const char *scanline_zone_string(scanline_zone zone);
r20796r20797
515519
516520   // other overrides
517521   virtual void field_sync_changed(bool line);
522   virtual void record_body_scanline(UINT16 physical_scanline, UINT16 scanline);
523   virtual void record_partial_body_scanline(UINT16 physical_scanline, UINT16 logical_scanline, INT32 start_clock, INT32 end_clock);
518524
519525private:
520526   struct video_scanline
r20796r20797
540546
541547   // state
542548   UINT8 m_mode;
549   UINT16 m_video_address;
550   bool m_dirty;
543551   video_scanline m_data[192];
544   bool m_dirty;
545552
546553   void change_mode(UINT8 mode, int state)
547554   {
r20796r20797
559566      if (new_mode != m_mode)
560567      {
561568         // it has!  check dirty flag
569         video_flush();
562570         if (!m_dirty)
563571         {
564            video_flush();
565572            m_dirty = true;
566573         }
567574
r20796r20797
574581   void setup_fixed_mode(struct devcb_read_line callback, UINT8 mode);
575582
576583   // runtime functions
577   virtual void record_body_scanline(UINT16 physical_scanline, UINT16 scanline);
584   void record_body_scanline(UINT16 physical_scanline, UINT16 scanline, INT32 start_pos, INT32 end_pos);
578585   pixel_t border_value(UINT8 mode, const pixel_t *palette, bool is_mc6847t1);
579586
580587   template<int xscale>
r20796r20797
582589
583590   // template function for doing video update collection
584591   template<int sample_count, int yres>
585   void record_scanline_res(int scanline);
592   void record_scanline_res(int scanline, INT32 start_pos, INT32 end_pos);
593
594   // miscellaneous
595   UINT8 input(UINT16 address);
596   INT32 scanline_position_from_clock(INT32 clocks_since_hsync);
586597};
587598
588599

Previous 199869 Revisions Next


© 1997-2024 The MAME Team