Previous 15994 Revisions Next

r15985 Monday 20th August, 2012 at 20:06:29 UTC by Wilbert Pol
huc6261.c: Added skeleton-ish for the huc6261. (nw)
[src/emu]emu.mak
[src/emu/video]huc6261.c* huc6261.h*

src/emu/video/huc6261.c
r0r15985
1/**********************************************************************
2
3    Hudson/NEC HuC6261 Video Colour Encoder
4
5    The HuC6261 generates the tv control signals. A full line lasts
6    1365 "master" cycles (typically at 21.47727Mhz).
7
8    HSync is low for 237 and high for 1128 master cycles.
9    VSync is low for 4095 master cycles (3 lines).
10    VSync changes 30 master cycles after HSync would go low.
11
12**********************************************************************/
13
14#include "emu.h"
15#include "profiler.h"
16#include "huc6261.h"
17
18#define LOG   0
19
20#define HUC6261_HSYNC_LENGTH   237
21#define HUC6261_HSYNC_START      ( HUC6261_WPF - HUC6261_HSYNC_LENGTH )
22
23
24const device_type HUC6261 = &device_creator<huc6261_device>;
25
26
27void huc6261_device::device_config_complete()
28{
29   const huc6261_interface *intf = reinterpret_cast<const huc6261_interface *>(static_config());
30
31   if ( intf != NULL )
32   {
33      *static_cast<huc6261_interface *>(this) = *intf;
34   }
35   else
36   {
37   }
38}
39
40
41huc6261_device::huc6261_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
42   : device_t(mconfig, HUC6261, "HuC6261", tag, owner, clock)
43{
44}
45
46
47void huc6261_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
48{
49   int vpos = m_screen->vpos();
50   int hpos = m_screen->hpos();
51   int h = m_last_h;
52   int v = m_last_v;
53   UINT32 *bitmap_line = &m_bmp->pix32(v);
54
55   while ( h != hpos || v != vpos )
56   {
57      if ( m_pixel_clock == 0 )
58      {
59         g_profiler.start( PROFILER_VIDEO );
60         /* Get next pixel information */
61         m_pixel_data = 0; //m_get_next_pixel_data( 0, 0xffff );
62         g_profiler.stop();
63      }
64
65      bitmap_line[ h ] = m_palette[ m_pixel_data ];
66      m_pixel_clock = ( m_pixel_clock + 1 ) % m_pixels_per_clock;
67      h = ( h + 1 ) % HUC6261_WPF;
68
69      switch( h )
70      {
71      case HUC6261_HSYNC_START:      /* Start of HSync */
72         m_huc6270_a->hsync_changed( 0 );
73         m_huc6270_b->hsync_changed( 0 );
74//          if ( v == 0 )
75//          {
76//              /* Check if the screen should be resized */
77//              m_height = HUC6261_LPF - ( m_blur ? 1 : 0 );
78//              if ( m_height != video_screen_get_height( m_screen ) )
79//              {
80//                  rectangle visible_area;
81//
82//                  /* TODO: Set proper visible area parameters */
83//                  visible_area.min_x = 64;
84//                  visible_area.min_y = 18;
85//                  visible_area.max_x = 64 + 1024 + 64 - 1;
86//                  visible_area.max_y = 18 + 242 - 1;
87//
88//                  video_screen_configure( m_screen, HUC6261_WPF, m_height, &visible_area, HZ_TO_ATTOSECONDS( device->clock / ( HUC6261_WPF * m_height ) ) );
89//              }
90//          }
91         break;
92
93      case 0:      /* End of HSync */
94         m_huc6270_a->hsync_changed( 1 );
95         m_huc6270_b->hsync_changed( 1 );
96         m_pixel_clock = 0;
97         v = ( v + 1 ) % m_height;
98         bitmap_line = &m_bmp->pix32(v);
99         break;
100
101      case HUC6261_HSYNC_START + 30:      /* End/Start of VSync */
102         if ( v>= m_height - 4 )
103         {
104            int vsync = ( v >= m_height - 4 && v < m_height - 1 ) ? 0 : 1;
105
106            m_huc6270_a->vsync_changed( vsync );
107            m_huc6270_b->vsync_changed( vsync );
108         }
109         break;
110      }
111   }
112
113   m_last_h = h;
114   m_last_v = v;
115
116   /* Reschedule timer */
117   if ( m_last_h < HUC6261_HSYNC_START )
118   {
119      /* Next event is start of HSync signal */
120      v = m_last_v;
121      h = HUC6261_HSYNC_START;
122   }
123   else if ( ( m_last_v == m_height - 4 || m_last_v == m_height - 1 ) && m_last_h < HUC6261_HSYNC_START + 30 )
124   {
125      /* Next event is start/end of VSync signal */
126      v = m_last_v;
127      h = HUC6261_HSYNC_START + 30;
128   }
129   else
130   {
131      /* Next event is end of HSync signal */
132      v = ( m_last_v + 1 ) % m_height;
133      h = 0;
134   }
135
136   /* Ask our slave device for time until next possible event */
137   {
138      UINT16 next_event_clocks = HUC6261_WPF; //m_get_time_til_next_event( 0, 0xffff );
139      int event_hpos, event_vpos;
140
141      /* Adjust for pixel clocks per pixel */
142      next_event_clocks *= m_pixels_per_clock;
143
144      /* Adjust for clocks left to go for current pixel */
145      next_event_clocks += ( m_pixels_per_clock - ( m_pixel_clock + 1 ) );
146
147      event_hpos = hpos + next_event_clocks;
148      event_vpos = vpos;
149      while ( event_hpos > HUC6261_WPF )
150      {
151         event_vpos += 1;
152         event_hpos -= HUC6261_WPF;
153      }
154
155      if ( event_vpos < v || ( event_vpos == v && event_hpos <= h ) )
156      {
157         if ( event_vpos > vpos || ( event_vpos == vpos && event_hpos > hpos ) )
158         {
159            v = event_vpos;
160            h = event_hpos;
161         }
162      }
163   }
164
165   m_timer->adjust( m_screen->time_until_pos( v, h ) );
166}
167
168
169void huc6261_device::video_update( bitmap_rgb32 &bitmap, const rectangle &cliprect )
170{
171   copybitmap( bitmap, *m_bmp, 0, 0, 0, 0, cliprect );
172}
173
174
175READ16_MEMBER( huc6261_device::read )
176{
177   UINT16 data = 0xFFFF;
178
179   switch ( offset & 1 )
180   {
181      /* Status info */
182      case 0x00:
183         {
184            UINT16 vpos = m_screen->vpos();
185            UINT16 hpos = m_screen->hpos();
186
187            data = ( vpos << 5 ) | ( m_register & 0x1F);
188
189            if ( vpos >= 22 && vpos < 262 && hpos < HUC6261_HSYNC_START )
190            {
191               data |= 0x8000;
192            }
193         }
194         break;
195
196      /* Register contents(?) */
197      case 0x01:
198         switch( m_register )
199         {
200            case 0x00:
201               data = m_control;
202               break;
203
204            case 0x01:
205               data = m_address;
206               break;
207
208            case 0x02:
209            case 0x03:
210               data = m_palette_latch;
211               m_address = ( m_address + 1 ) & 0x1FF;
212               m_palette_latch = m_palette[ m_address ];
213               break;
214
215            case 0x08:
216               data = m_priority[4] | ( m_priority[5] << 4 ) | ( m_priority[6] << 8 );
217               break;
218
219            case 0x09:
220               data = m_priority[0] | ( m_priority[1] << 4 ) | ( m_priority[2] << 8 ) | ( m_priority[3] << 12 );;
221               break;
222         }
223         break;
224   }
225
226   return data;
227}
228
229
230WRITE16_MEMBER( huc6261_device::write )
231{
232   switch ( offset & 1 )
233   {
234      /* Register */
235      case 0x00:
236         m_register = data;
237         break;
238
239      case 0x01:
240         logerror("huc6261: writing 0x%04x to register 0x%02x\n", data, m_register );
241         switch( m_register )
242         {
243            /* Control register */
244            // -x-------------- Enable HuC6271: 0 - disabled, 1 - enabled
245            // --x------------- Enable HuC6272 BG3: 0 - disabled, 1 - enabled
246            // ---x------------ Enable HuC6272 BG2: 0 - disabled, 1 - enabled
247            // ----x----------- Enable Huc6272 BG1: 0 - disabled, 1 - enabled
248            // -----x---------- Enable HuC6272 BG0: 0 - disabled, 1 - enabled
249            // ------x--------- Enable HuC6270 SPR: 0 - disabled, 1 - enabled
250            // -------x-------- Enable HuC6270 BG: 0 - disabled, 1 - enabled
251            // --------x------- Number of SPR colors?: 0 - 16, 1 - 256
252            // ---------x------ Number of BG colors?: 0 - 16, 1 - 256
253            // ------------x--- Dot clock: 0 - 5MHz, 1 - 7MHz
254            // -------------x-- Synchronization: 0 - internal, 1 - external
255            // --------------xx Screen height: 00 - 262 lines, 01 - 263 lines, 10 - interlace, 11 - unknown/undefined
256            case 0x00:
257               m_control = data;
258               m_pixels_per_clock = ( data & 0x04 ) ? 3 : 4;
259               break;
260
261            // Palette address
262            case 0x01:
263               m_address = data & 0x1FF;
264               m_palette_latch = m_palette[ m_address ];
265               break;
266
267            // Palette data
268            case 0x02:
269               m_palette_latch = data;
270               m_palette[ m_address ] = m_palette_latch;
271               m_address = ( m_address + 1 ) & 0x1FF;
272               break;
273
274            // Palette offset 0
275            case 0x04:
276               break;
277
278            // Palette offset 1
279            case 0x05:
280               break;
281
282            // Palette offset 2
283            case 0x06:
284               break;
285
286            // Palette offset 3
287            case 0x07:
288               break;
289
290            // Priority 0
291            // -----xxx-------- HuC6271 Rainbow priority
292            // ---------xxx---- HuC6270 SPR priority
293            // -------------xxx HuC6270 BG priority
294            case 0x08:
295               m_priority[4] = ( data >> 0 ) & 0x07;
296               m_priority[5] = ( data >> 4 ) & 0x07;
297               m_priority[6] = ( data >> 8 ) & 0x07;
298               break;
299
300            // Priority 1
301            // -xxx------------ HuC6272 BG3 priority
302            // -----xxx-------- HuC6272 BG2 priority
303            // ---------xxx---- HuC6272 BG1 priority
304            // -------------xxx HuC6272 BG0 priority
305            case 0x09:
306               m_priority[0] = ( data >>  0 ) & 0x07;
307               m_priority[1] = ( data >>  4 ) & 0x07;
308               m_priority[2] = ( data >>  8 ) & 0x07;
309               m_priority[3] = ( data >> 12 ) & 0x07;
310               break;
311
312            // Chroma key Y
313            case 0x0A:
314               break;
315
316            // Chroma key U
317            case 0x0B:
318               break;
319
320            // Chroma key V
321            case 0x0C:
322               break;
323
324            //
325            case 0x0D:
326               break;
327
328            //
329            case 0x0E:
330               break;
331
332            //
333            case 0x0F:
334               break;
335
336            //
337            case 0x10:
338               break;
339
340            //
341            case 0x11:
342               break;
343
344            //
345            case 0x12:
346               break;
347
348            //
349            case 0x13:
350               break;
351
352            //
353            case 0x14:
354               break;
355
356            //
357            case 0x15:
358               break;
359         }
360         break;
361   }
362}
363
364
365void huc6261_device::device_start()
366{
367   /* Make sure we are supplied all our mandatory tags */
368   assert( screen_tag != NULL );
369   assert( huc6270_a_tag != NULL );
370   assert( huc6270_b_tag != NULL );
371
372   m_timer = timer_alloc();
373   m_screen = machine().device<screen_device>( screen_tag );
374   m_huc6270_a = machine().device<huc6270_device>( huc6270_a_tag );
375   m_huc6270_b = machine().device<huc6270_device>( huc6270_b_tag );
376
377   m_bmp = auto_bitmap_rgb32_alloc( machine(), HUC6261_WPF, HUC6261_LPF );
378
379   /* We want to have valid devices */
380   assert( m_screen != NULL );
381   assert( m_huc6270_a != NULL );
382   assert( m_huc6270_b != NULL );
383
384   save_item(NAME(m_last_h));
385   save_item(NAME(m_last_v));
386   save_item(NAME(m_height));
387   save_item(NAME(m_palette));
388   save_item(NAME(m_palette_latch));
389   save_item(NAME(m_address));
390   save_item(NAME(m_register));
391   save_item(NAME(m_control));
392   save_item(NAME(m_priority));
393   save_item(NAME(m_pixels_per_clock));
394   save_item(NAME(m_pixel_data));
395   save_item(NAME(m_pixel_clock));
396}
397
398
399void huc6261_device::device_reset()
400{
401   m_register = 0;
402   m_pixels_per_clock = 4;
403   m_height = 263;
404
405   m_last_v = m_screen->vpos();
406   m_last_h = m_screen->hpos();
407   m_timer->adjust( m_screen->time_until_pos( ( m_screen->vpos() + 1 ) % 263, 0 ) );
408}
409
src/emu/video/huc6261.h
r0r15985
1/**********************************************************************
2
3    Hudson/NEC HuC6261 interface and definitions
4
5**********************************************************************/
6
7
8#ifndef __HUC6261_H_
9#define __HUC6261_H_
10
11#include "emu.h"
12#include "machine/devhelpr.h"
13#include "video/huc6270.h"
14
15
16/* Screen timing stuff */
17#define HUC6261_WPF         1365   /* width of a line in frame including blanking areas */
18#define HUC6261_LPF         263      /* max number of lines in a single frame */
19
20
21#define MCFG_HUC6261_ADD( _tag, clock, _intrf )   \
22   MCFG_DEVICE_ADD( _tag, HUC6261, clock )      \
23   MCFG_DEVICE_CONFIG( _intrf )
24
25
26typedef struct _huc6261_interface huc6261_interface;
27struct _huc6261_interface
28{
29   /* Tag for the screen we will be drawing on */
30   const char *screen_tag;
31
32   /* Tags for the 2 HuC6270 devices */
33   const char *huc6270_a_tag;
34   const char *huc6270_b_tag;
35};
36
37
38class huc6261_device :   public device_t,
39                  public huc6261_interface
40{
41public:
42   // construction/destruction
43   huc6261_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
44
45   void video_update(bitmap_rgb32 &bitmap, const rectangle &cliprect);
46   DECLARE_READ16_MEMBER( read );
47   DECLARE_WRITE16_MEMBER( write );
48
49protected:
50   // device-level overrides
51   virtual void device_config_complete();
52   virtual void device_start();
53   virtual void device_reset();
54   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
55
56private:
57   screen_device *m_screen;
58   huc6270_device *m_huc6270_a;
59   huc6270_device *m_huc6270_b;
60   int      m_last_h;
61   int      m_last_v;
62   int      m_height;
63
64   UINT16   m_palette[512];
65   UINT16   m_address;
66   UINT16   m_palette_latch;
67   UINT16   m_register;
68   UINT16   m_control;
69   UINT8   m_priority[7];
70
71   UINT8   m_pixels_per_clock;   /* Number of pixels to output per colour clock */
72   UINT16   m_pixel_data;
73   UINT8   m_pixel_clock;
74
75   emu_timer   *m_timer;
76   bitmap_rgb32   *m_bmp;
77};
78
79
80extern const device_type HUC6261;
81
82
83#endif
src/emu/emu.mak
r15984r15985
287287   $(EMUVIDEO)/hd63484.o      \
288288   $(EMUVIDEO)/huc6202.o      \
289289   $(EMUVIDEO)/huc6260.o      \
290   $(EMUVIDEO)/huc6261.o      \
290291   $(EMUVIDEO)/huc6270.o      \
291292   $(EMUVIDEO)/i8275.o         \
292293   $(EMUVIDEO)/k053250.o      \

Previous 15994 Revisions Next


© 1998-2018 The MESS Team