Previous 199869 Revisions Next

r20209 Friday 11th January, 2013 at 20:52:37 UTC by Wilbert Pol
i8244.c: Added a device implementation for the i8244/i8245.  [Wilbert Pol]

(MESS)g7400: Changed driver to use the i8244/i8245 device implementation.  [Wilbert Pol]
[src/emu]emu.mak
[src/emu/video]i8244.c* i8244.h*
[src/mess/drivers]odyssey2.c
[src/mess/includes]odyssey2.h
[src/mess/machine]odyssey2.c
[src/mess/video]odyssey2.c

trunk/src/emu/video/i8244.c
r0r20209
1/***************************************************************************
2
3    i8244.c
4
5    Intel 8244 (NTSC)/8245 (PAL) Graphics and sound chip
6
7
8***************************************************************************/
9
10#include "emu.h"
11#include "i8244.h"
12
13
14// device type definition
15const device_type I8244 = &device_creator<i8244_device>;
16const device_type I8245 = &device_creator<i8245_device>;
17
18
19static const UINT8 c_shape[0x40 * 8]={
20   0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, // 0
21   0x18,0x38,0x18,0x18,0x18,0x18,0x3C,0x00,
22   0x3C,0x66,0x0C,0x18,0x30,0x60,0x7E,0x00,
23   0x7C,0xC6,0x06,0x3C,0x06,0xC6,0x7C,0x00,
24   0xCC,0xCC,0xCC,0xFE,0x0C,0x0C,0x0C,0x00,
25   0xFE,0xC0,0xC0,0x7C,0x06,0xC6,0x7C,0x00,
26   0x7C,0xC6,0xC0,0xFC,0xC6,0xC6,0x7C,0x00,
27   0xFE,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,
28   0x7C,0xC6,0xC6,0x7C,0xC6,0xC6,0x7C,0x00,
29   0x7C,0xC6,0xC6,0x7E,0x06,0xC6,0x7C,0x00,
30   0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00,
31   0x18,0x7E,0x58,0x7E,0x1A,0x7E,0x18,0x00,
32   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
33   0x3C,0x66,0x0C,0x18,0x18,0x00,0x18,0x00,
34   0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFE,0x00,
35   0xFC,0xC6,0xC6,0xFC,0xC0,0xC0,0xC0,0x00,
36   0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,
37   0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00,
38   0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xFE,0x00,
39   0xFC,0xC6,0xC6,0xFC,0xD8,0xCC,0xC6,0x00,
40   0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00,
41   0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
42   0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,
43   0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
44   0x7C,0xC6,0xC6,0xC6,0xDE,0xCC,0x76,0x00,
45   0x7C,0xC6,0xC0,0x7C,0x06,0xC6,0x7C,0x00,
46   0xFC,0xC6,0xC6,0xC6,0xC6,0xC6,0xFC,0x00,
47   0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xC0,0x00,
48   0x7C,0xC6,0xC0,0xC0,0xCE,0xC6,0x7E,0x00,
49   0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,
50   0x06,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00,
51   0xC6,0xCC,0xD8,0xF0,0xD8,0xCC,0xC6,0x00,
52   0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00,
53   0x7E,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00,
54   0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00,
55   0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,
56   0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,
57   0xFC,0xC6,0xC6,0xFC,0xC6,0xC6,0xFC,0x00,
58   0xC6,0xEE,0xFE,0xD6,0xC6,0xC6,0xC6,0x00,
59   0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,
60   0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,
61   0x00,0x66,0x3C,0x18,0x3C,0x66,0x00,0x00,
62   0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00,
63   0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00,
64   0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00,
65   0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0x00,
66   0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,
67   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,
68   0xCE,0xDB,0xDB,0xDB,0xDB,0xDB,0xCE,0x00,
69   0x00,0x00,0x3C,0x7E,0x7E,0x7E,0x3C,0x00,
70   0x1C,0x1C,0x18,0x1E,0x18,0x18,0x1C,0x00,
71   0x1C,0x1C,0x18,0x1E,0x18,0x34,0x26,0x00,
72   0x38,0x38,0x18,0x78,0x18,0x2C,0x64,0x00,
73   0x38,0x38,0x18,0x78,0x18,0x18,0x38,0x00,
74   0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,
75   0x18,0x3C,0x7E,0xFF,0xFF,0x18,0x18,0x00,
76   0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0x00,
77   0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0x00,
78   0x38,0x38,0x12,0xFE,0xB8,0x28,0x6C,0x00,
79   0xC0,0x60,0x30,0x18,0x0C,0x06,0x03,0x00,
80   0x00,0x00,0x0C,0x08,0x08,0x7F,0x3E,0x00,
81   0x00,0x03,0x63,0xFF,0xFF,0x18,0x08,0x00,
82   0x00,0x00,0x00,0x10,0x38,0xFF,0x7E,0x00
83};
84
85
86// Background and grid information is stored in RGB format
87// while the character and sprite colors are stored in BGR
88// format.
89static const UINT8 bgr2rgb[8] =
90{
91   0x00, 0x04, 0x02, 0x06, 0x01, 0x05, 0x03, 0x07
92};
93
94
95//-------------------------------------------------
96//  i8243_device - constructor
97//-------------------------------------------------
98
99i8244_device::i8244_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
100   : device_t(mconfig, I8244, "I8244", tag, owner, clock)
101   , device_sound_interface(mconfig, *this)
102   , m_irq_func(*this)
103   , m_postprocess_func(*this)
104   , m_screen_tag(NULL)
105   , m_screen(NULL)
106   , m_start_vpos(START_Y)
107   , m_start_vblank(START_Y + SCREEN_HEIGHT)
108   , m_screen_lines(LINES)
109{
110}
111
112
113i8244_device::i8244_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int lines)
114   : device_t(mconfig, type, name, tag, owner, clock)
115   , device_sound_interface(mconfig, *this)
116   , m_irq_func(*this)
117   , m_postprocess_func(*this)
118   , m_screen_tag(NULL)
119   , m_screen(NULL)
120   , m_start_vpos(START_Y)
121   , m_start_vblank(START_Y + SCREEN_HEIGHT)
122   , m_screen_lines(lines)
123{
124}
125
126
127i8245_device::i8245_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
128   : i8244_device(mconfig, I8245, "I8245", tag, owner, clock, i8245_device::LINES)
129{
130}
131
132
133//-------------------------------------------------
134//  device_start - device-specific startup
135//-------------------------------------------------
136
137void i8244_device::device_start()
138{
139   assert( m_screen_tag != NULL );
140   m_screen = machine().device<screen_device>(m_screen_tag);
141   assert( m_screen != NULL );
142
143   // Let the screen create our temporary bitmap with the screen's dimensions
144   m_screen->register_screen_bitmap(m_tmp_bitmap);
145
146   m_line_timer = timer_alloc(TIMER_LINE);
147   m_line_timer->adjust( m_screen->time_until_pos(1, START_ACTIVE_SCAN ), 0,  m_screen->scan_period() );
148
149   m_hblank_timer = timer_alloc(TIMER_HBLANK);
150   m_hblank_timer->adjust( m_screen->time_until_pos(1, END_ACTIVE_SCAN + 18 ), 0, m_screen->scan_period() );
151
152   m_irq_func.resolve_safe();
153   m_postprocess_func.resolve_safe();
154
155   // allocate a stream
156   m_stream = stream_alloc( 0, 1, clock()/(LINE_CLOCKS*4) );
157
158   // register our state
159   save_pointer(NAME(m_vdc.reg), 0x100);
160   save_item(NAME(m_sh_count));
161   save_item(NAME(m_x_beam_pos));
162   save_item(NAME(m_y_beam_pos));
163   save_item(NAME(m_control_status));
164   save_item(NAME(m_collision_status));
165   save_item(NAME(m_iff));
166}
167
168
169//-------------------------------------------------
170//  device_reset - device-specific reset
171//-------------------------------------------------
172
173void i8244_device::device_reset()
174{
175   memset(m_vdc.reg, 0, 0x100);
176
177   m_sh_count = 0;
178   m_x_beam_pos = 0;
179   m_y_beam_pos = 0;
180   m_control_status = 0;
181   m_collision_status = 0;
182   m_iff = 0;
183}
184
185
186void i8244_device::palette_init()
187{
188   static const UINT8 i8244_colors[3*16] =
189   {
190      0x00, 0x00, 0x00, // i r g b
191      0x00, 0x00, 0xAA, // i r g B
192      0x00, 0xAA, 0x00, // i r G b
193      0x00, 0xAA, 0xAA, // i r G B
194      0xAA, 0x00, 0x00, // i R g b
195      0xAA, 0x00, 0xAA, // i R g B
196      0xAA, 0xAA, 0x00, // i R G b
197      0xAA, 0xAA, 0xAA, // i R G B
198      0x55, 0x55, 0x55, // I r g b
199      0x55, 0x55, 0xFF, // I r g B
200      0x55, 0xFF, 0x55, // I r G b
201      0x55, 0xFF, 0xFF, // I r G B
202      0xFF, 0x55, 0x55, // I R g b
203      0xFF, 0x55, 0xFF, // I R g B
204      0xFF, 0xFF, 0x55, // I R G b
205      0xFF, 0xFF, 0xFF, // I R G B
206   };
207
208   for ( int i = 0; i < 16; i++ )
209   {
210      palette_set_color_rgb( machine(), i, i8244_colors[i*3], i8244_colors[i*3+1], i8244_colors[i*3+2] );
211   }
212}
213
214
215void i8244_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
216{
217   int vpos = m_screen->vpos();
218
219   switch ( id )
220   {
221      case TIMER_LINE:
222         // handle i824x line timer
223         render_scanline(vpos);
224         break;
225
226      case TIMER_HBLANK:
227         // handle i824x HBlank timer
228         if ( vpos < m_start_vpos - 1 )
229         {
230            return;
231         }
232
233         if ( vpos < m_start_vblank - 1 )
234         {
235            m_control_status |= 0x01;
236         }
237         break;
238   }
239}
240
241
242int i8244_device::get_y_beam()
243{
244   int y = m_screen->vpos() - m_start_vpos;
245
246   // The Y register becomes 0 only when the VBlank signal is turned off!
247   if ( y < 0 || ( y == 0 && m_screen->hpos() < 366+42 ) )
248   {
249      y += m_screen_lines;
250   }
251
252   return y;
253}
254
255
256int i8244_device::get_x_beam()
257{
258   int x = m_screen->hpos() - START_ACTIVE_SCAN;
259
260   if ( x < 0 )
261   {
262      x += LINE_CLOCKS;
263   }
264
265   return x >> 1;
266}
267
268
269offs_t i8244_device::fix_register_mirrors( offs_t offset )
270{
271   // registers $40,$41 are mirrored at $44,$45, $48,$49, and $4C,$4D
272   if ( ( offset & 0xF2 ) == 0x40 )
273   {
274      offset &= ~0x0C;
275   }
276
277   // registers $A0-$AF are mirrored at $B0-$BF
278   if ( ( offset & 0xF0 ) == 0xB0 )
279   {
280      offset &= ~0x10;
281   }
282
283   return offset;
284}
285
286
287READ8_MEMBER(i8244_device::read)
288{
289   UINT8 data = 0;
290
291   offset = fix_register_mirrors( offset );
292
293   switch (offset)
294   {
295      case 0xa1:
296         data = m_control_status & 0xFE;
297         m_iff = 0;
298         m_irq_func(CLEAR_LINE);
299         m_control_status &= ~0x08;
300         if ( hblank() )
301         {
302            data |= 1;
303         }
304         break;
305
306      case 0xa2:
307         data = m_collision_status;
308         m_collision_status = 0;
309         break;
310
311      case 0xa4:
312         if (m_vdc.s.control & VDC_CONTROL_REG_STROBE_XY)
313         {
314            m_y_beam_pos = get_y_beam();
315         }
316         data = m_y_beam_pos;
317         break;
318
319
320        case 0xa5:
321            if ((m_vdc.s.control & VDC_CONTROL_REG_STROBE_XY))
322         {
323                m_x_beam_pos = get_x_beam();
324         }
325            data = m_x_beam_pos;
326            break;
327
328        default:
329            data = m_vdc.reg[offset];
330         break;
331    }
332
333    return data;
334}
335
336
337WRITE8_MEMBER(i8244_device::write)
338{
339   offset = fix_register_mirrors( offset );
340
341   /* Update the sound */
342   if( offset >= 0xa7 && offset <= 0xaa )
343   {
344      m_stream->update();
345   }
346
347   if (offset == 0xa0)
348   {
349      if ( ( m_vdc.s.control & VDC_CONTROL_REG_STROBE_XY )
350         && !(data & VDC_CONTROL_REG_STROBE_XY))
351      {
352         /* Toggling strobe bit, tuck away values */
353         m_x_beam_pos = get_x_beam();
354         m_y_beam_pos = get_y_beam();
355      }
356   }
357
358   m_vdc.reg[offset] = data;
359}
360
361
362READ_LINE_MEMBER(i8244_device::vblank)
363{
364   if ( m_screen->vpos() > m_start_vpos && m_screen->vpos() < m_start_vblank )
365   {
366      return 0;
367   }
368   return 1;
369}
370
371
372READ_LINE_MEMBER(i8244_device::hblank)
373{
374   int hpos = m_screen->hpos();
375   int vpos = m_screen->vpos();
376
377   if ( hpos >= START_ACTIVE_SCAN && hpos < END_ACTIVE_SCAN )
378   {
379      return 0;
380   }
381
382   // Before active area?
383   if ( vpos < m_start_vpos - 1 )
384   {
385      return 0;
386   }
387
388   // During active area?
389   if ( vpos < m_start_vblank - 1 )
390   {
391      return 1;
392   }
393
394   // After active area
395   return 0;
396}
397
398
399void i8244_device::render_scanline(int vpos)
400{
401   // Some local constants for this method
402   //static const UINT8 COLLISION_SPRITE_0        = 0x01;
403   //static const UINT8 COLLISION_SPRITE_1        = 0x02;
404   //static const UINT8 COLLISION_SPRITE_2        = 0x04;
405   //static const UINT8 COLLISION_SPRITE_3        = 0x08;
406   static const UINT8 COLLISION_VERTICAL_GRID   = 0x10;
407   static const UINT8 COLLISION_HORIZ_GRID_DOTS = 0x20;
408   //static const UINT8 COLLISION_EXTERNAL_UNUSED = 0x40;
409   static const UINT8 COLLISION_CHARACTERS      = 0x80;
410
411   UINT8   collision_map[160];
412
413
414   if ( vpos == m_start_vpos )
415   {
416      m_control_status &= ~0x08;
417   }
418
419   if ( m_start_vpos < vpos && vpos < m_start_vblank )
420   {
421      rectangle rect;
422      int scanline = vpos - m_start_vpos;
423
424      m_control_status &= ~ 0x01;
425
426      /* Draw a line */
427      rect.set(START_ACTIVE_SCAN, END_ACTIVE_SCAN - 1, vpos, vpos);
428      m_tmp_bitmap.fill( (m_vdc.s.color >> 3) & 0x7, rect );
429
430      /* Clear collision map */
431      memset( collision_map, 0, sizeof( collision_map ) );
432
433      /* Display grid if enabled */
434      if ( m_vdc.s.control & 0x08 )
435      {
436         UINT16 color = ( m_vdc.s.color & 7 ) | ( ( m_vdc.s.color >> 3 ) & 0x08 );
437         int    x_grid_offset = 8;
438         int    y_grid_offset = 24;
439         int    width = 16;
440         int    height = 24;
441         int    w = ( m_vdc.s.control & 0x80 ) ? width : 2;
442
443         /* Draw horizontal part of grid */
444         for ( int j = 1, y = 0; y < 9; y++, j <<= 1 )
445         {
446            if ( y_grid_offset + y * height <= scanline && scanline < y_grid_offset + y * height + 3 )
447            {
448               for ( int i = 0; i < 9; i++ )
449               {
450                  if ( ( m_vdc.s.hgrid[0][i] & j ) || ( m_vdc.s.hgrid[1][i] & ( j >> 8 ) ) )
451                  {
452                     for ( int k = 0; k < width + 2; k++ )
453                     {
454                        int px = x_grid_offset + i * width + k;
455                        collision_map[ px ] |= COLLISION_HORIZ_GRID_DOTS;
456                        m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * px ) = color;
457                        m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * px + 1 ) = color;
458                     }
459                  }
460               }
461            }
462         }
463
464         /* Draw vertical part of grid */
465         for( int j = 1, y = 0; y < 8; y++, j <<= 1 )
466         {
467            if ( y_grid_offset + y * height <= scanline && scanline < y_grid_offset + ( y + 1 ) * height )
468            {
469               for ( int i = 0; i < 10; i++ )
470               {
471                  if ( m_vdc.s.vgrid[i] & j )
472                  {
473                     for ( int k = 0; k < w; k++ )
474                     {
475                        int px = x_grid_offset + i * width + k;
476
477                        /* Check if we collide with an already drawn source object */
478                        if ( collision_map[ px ] & m_vdc.s.collision )
479                        {
480                           m_collision_status |= COLLISION_VERTICAL_GRID;
481                        }
482                        /* Check if an already drawn object would collide with us */
483                        if ( COLLISION_VERTICAL_GRID & m_vdc.s.collision && collision_map[ px ] )
484                        {
485                           m_collision_status |= collision_map[ px ];
486                        }
487                        collision_map[ px ] |= COLLISION_VERTICAL_GRID;
488                        m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * px ) = color;
489                        m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * px + 1 ) = color;
490                     }
491                  }
492               }
493            }
494         }
495      }
496
497      /* Display objects if enabled */
498      if ( m_vdc.s.control & 0x20 )
499      {
500         /* Regular foreground objects */
501         for ( int i = 0; i < ARRAY_LENGTH( m_vdc.s.foreground ); i++ )
502         {
503            int   y = m_vdc.s.foreground[i].y & 0xFE;
504            int   height = 8 - ( ( ( y >> 1 ) + m_vdc.s.foreground[i].ptr ) & 7 );
505
506            if ( y >= 0x0E && y <= scanline && scanline < y + height * 2 )
507            {
508               UINT16 color = 8 + bgr2rgb[ ( ( m_vdc.s.foreground[i].color >> 1 ) & 0x07 ) ];
509               int    offset = ( m_vdc.s.foreground[i].ptr | ( ( m_vdc.s.foreground[i].color & 0x01 ) << 8 ) ) + ( y >> 1 ) + ( ( scanline - y ) >> 1 );
510               UINT8  chr = c_shape[ offset & 0x1FF ];
511               int    x = m_vdc.s.foreground[i].x;
512
513               for ( UINT8 m = 0x80; m > 0; m >>= 1, x++ )
514               {
515                  if ( chr & m )
516                  {
517                     if ( x >= 0 && x < 160 )
518                     {
519                        /* Check if we collide with an already drawn source object */
520                        if ( collision_map[ x ] & m_vdc.s.collision )
521                        {
522                           m_collision_status |= COLLISION_CHARACTERS;
523                        }
524                        /* Check if an already drawn object would collide with us */
525                        if ( COLLISION_CHARACTERS & m_vdc.s.collision && collision_map[ x ] )
526                        {
527                           m_collision_status |= collision_map[ x ];
528                        }
529                        collision_map[ x ] |= COLLISION_CHARACTERS;
530                        m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * x ) = color;
531                        m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * x + 1 ) = color;
532                     }
533                  }
534               }
535            }
536         }
537
538         /* Quad objects */
539         for ( int i = 0; i < ARRAY_LENGTH( m_vdc.s.quad ); i++ )
540         {
541            int y = m_vdc.s.quad[i].single[0].y;
542            int height = 8;
543
544            if ( y <= scanline && scanline < y + height * 2 )
545            {
546               int   x = m_vdc.s.quad[i].single[0].x;
547
548               // Charaecter height is always determined by the height of the 4th character
549               int char_height = 8 - ( ( ( y >> 1 ) + m_vdc.s.quad[i].single[3].ptr ) & 7 );
550
551               for ( int j = 0; j < ARRAY_LENGTH( m_vdc.s.quad[0].single ); j++, x += 8 )
552               {
553                  if ( y <= scanline && scanline < y + char_height * 2 )
554                  {
555
556                     UINT16 color = 8 + bgr2rgb[ ( ( m_vdc.s.quad[i].single[j].color >> 1 ) & 0x07 ) ];
557                     int offset = ( m_vdc.s.quad[i].single[j].ptr | ( ( m_vdc.s.quad[i].single[j].color & 0x01 ) << 8 ) ) + ( y >> 1 ) + ( ( scanline - y ) >> 1 );
558                     UINT8 chr = c_shape[ offset & 0x1FF ];
559
560                     for ( UINT8 m = 0x80; m > 0; m >>= 1, x++ )
561                     {
562                        if ( chr & m )
563                        {
564                           if ( x >= 0 && x < 160 )
565                           {
566                              /* Check if we collide with an already drawn source object */
567                              if ( collision_map[ x ] & m_vdc.s.collision )
568                              {
569                                 m_collision_status |= COLLISION_CHARACTERS;
570                              }
571                              /* Check if an already drawn object would collide with us */
572                              if ( COLLISION_CHARACTERS & m_vdc.s.collision && collision_map[ x ] )
573                              {
574                                 m_collision_status |= collision_map[ x ];
575                              }
576                              collision_map[ x ] |= COLLISION_CHARACTERS;
577                              m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * x ) = color;
578                              m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * x + 1 ) = color;
579                           }
580                        }
581                     }
582                  }
583                  else
584                  {
585                     x += 8;
586                  }
587               }
588            }
589         }
590
591         /* Sprites */
592         for ( int i = 0; i < ARRAY_LENGTH( m_vdc.s.sprites ); i++ )
593         {
594            int y = m_vdc.s.sprites[i].y;
595            int height = 8;
596
597            if ( m_vdc.s.sprites[i].color & 4 )
598            {
599               /* Zoomed sprite */
600               if ( y <= scanline && scanline < y + height * 4 )
601               {
602                  UINT16 color = 8 + bgr2rgb[ ( ( m_vdc.s.sprites[i].color >> 3 ) & 0x07 ) ];
603                  UINT8  chr = m_vdc.s.shape[i][ ( ( scanline - y ) >> 2 ) ];
604                  int    x = m_vdc.s.sprites[i].x;
605                  int    x_shift = 0;
606
607                  switch ( m_vdc.s.sprites[i].color & 0x03 )
608                  {
609                     case 1:    // Xg attribute set
610                        x_shift = 2;
611                        break;
612                     case 2:    // S attribute set
613                        x_shift = ( ( ( scanline - y ) >> 1 ) & 0x01 ) ^ 0x01;
614                        break;
615                     case 3:    // Xg and S attributes set
616                        x_shift = ( ( scanline - y ) >> 1 ) & 0x01;
617                        break;
618                  }
619                  x_shift <<= 1;
620
621                  for ( UINT8 m = 0x01; m > 0; m <<= 1, x += 2 )
622                  {
623                     if ( chr & m )
624                     {
625                        if ( x >= 0 && x < 160 )
626                        {
627                           /* Check if we collide with an already drawn source object */
628                           if ( collision_map[ x ] & m_vdc.s.collision )
629                           {
630                              m_collision_status |= ( 1 << i );
631                           }
632                           /* Check if an already drawn object would collide with us */
633                           if ( ( 1 << i ) & m_vdc.s.collision && collision_map[ x ] )
634                           {
635                              m_collision_status |= collision_map[ x ];
636                           }
637                           collision_map[ x ] |= ( 1 << i );
638                           m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + x_shift + 2 * x ) = color;
639                           m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + x_shift + 2 * x + 1 ) = color;
640                        }
641                        if ( x >= -1 && x < 159 )
642                        {
643                           /* Check if we collide with an already drawn source object */
644                           if ( collision_map[ x ] & m_vdc.s.collision )
645                           {
646                              m_collision_status |= ( 1 << i );
647                           }
648                           /* Check if an already drawn object would collide with us */
649                           if ( ( 1 << i ) & m_vdc.s.collision && collision_map[ x ] )
650                           {
651                              m_collision_status |= collision_map[ x ];
652                           }
653                           collision_map[ x ] |= ( 1 << i );
654                           m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + x_shift + 2 * x + 2 ) = color;
655                           m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + x_shift + 2 * x + 3 ) = color;
656                        }
657                     }
658                  }
659               }
660            }
661            else
662            {
663               /* Regular sprite */
664               if ( y <= scanline && scanline < y + height * 2 )
665               {
666                  UINT16 color = 8 + bgr2rgb[ ( ( m_vdc.s.sprites[i].color >> 3 ) & 0x07 ) ];
667                  UINT8  chr = m_vdc.s.shape[i][ ( ( scanline - y ) >> 1 ) ];
668                  int    x = m_vdc.s.sprites[i].x;
669                  int    x_shift = 0;
670
671                  switch ( m_vdc.s.sprites[i].color & 0x03 )
672                  {
673                     case 1:    // Xg attribute set
674                        x_shift = 1;
675                        break;
676                     case 2:    // S attribute set
677                        x_shift = ( ( ( scanline - y ) >> 1 ) & 0x01 ) ^ 0x01;
678                        break;
679                     case 3:    // Xg and S attributes set
680                        x_shift = ( ( scanline - y ) >> 1 ) & 0x01;
681                        break;
682                  }
683
684                  for ( UINT8 m = 0x01; m > 0; m <<= 1, x++ )
685                  {
686                     if ( chr & m )
687                     {
688                        if ( x >= 0 && x < 160 )
689                        {
690                           /* Check if we collide with an already drawn source object */
691                           if ( collision_map[ x ] & m_vdc.s.collision )
692                           {
693                              m_collision_status |= ( 1 << i );
694                           }
695                           /* Check if an already drawn object would collide with us */
696                           if ( ( 1 << i ) & m_vdc.s.collision && collision_map[ x ] )
697                           {
698                              m_collision_status |= collision_map[ x ];
699                           }
700                           collision_map[ x ] |= ( 1 << i );
701                           m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + x_shift + 2 * x ) = color;
702                           m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + x_shift + 2 * x + 1 ) = color;
703                        }
704                     }
705                  }
706               }
707            }
708         }
709      }
710   }
711
712   // Allow driver to do additional processing
713   m_postprocess_func( vpos );
714
715   /* Check for start of VBlank */
716   if ( vpos == m_start_vblank )
717   {
718      m_control_status |= 0x08;
719      if ( ! m_iff )
720      {
721         m_iff = 1;
722         m_irq_func(ASSERT_LINE);
723      }
724   }
725}
726
727
728void i8244_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
729{
730   UINT32 old_signal, signal;
731   int ii;
732   int period;
733   stream_sample_t *buffer = outputs[0];
734
735   /* Generate the signal */
736   old_signal = signal = m_vdc.s.shift3 | (m_vdc.s.shift2 << 8) | (m_vdc.s.shift1 << 16);
737
738   if( m_vdc.s.sound & 0x80 )   /* Sound is enabled */
739   {
740      for( ii = 0; ii < samples; ii++, buffer++ )
741      {
742         *buffer = 0;
743         *buffer = signal & 0x1;
744         period = (m_vdc.s.sound & 0x20) ? 1 : 4;
745         if( ++m_sh_count >= period )
746         {
747            m_sh_count = 0;
748            signal >>= 1;
749            /* Loop sound */
750            signal |= *buffer << 23;
751            /* Check if noise should be applied */
752            if ( m_vdc.s.sound & 0x10 )
753            {
754               /* Noise tap is on bits 0 and 5 and fed back to bits 15 (and 23!) */
755               UINT32 new_bit = ( ( old_signal ) ^ ( old_signal >> 5 ) ) & 0x01;
756               signal = ( old_signal & 0xFF0000 ) | ( ( old_signal & 0xFFFF ) >> 1 ) | ( new_bit << 15 ) | ( new_bit << 23 );
757            }
758            m_vdc.s.shift3 = signal & 0xFF;
759            m_vdc.s.shift2 = ( signal >> 8 ) & 0xFF;
760            m_vdc.s.shift1 = ( signal >> 16 ) & 0xFF;
761            old_signal = signal;
762         }
763
764         /* Throw an interrupt if enabled */
765         if( m_vdc.s.control & 0x4 )
766         {
767            // This feature does not seem to be finished/enabled in hardware!
768         }
769
770         /* Adjust volume */
771         *buffer *= m_vdc.s.sound & 0xf;
772         /* Pump the volume up */
773         *buffer <<= 10;
774      }
775   }
776   else
777   {
778      /* Sound disabled, so clear the buffer */
779      for( ii = 0; ii < samples; ii++, buffer++ )
780      {
781         *buffer = 0;
782      }
783   }
784}
785
786
787UINT32 i8244_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
788{
789   copybitmap( bitmap, m_tmp_bitmap, 0, 0, 0, 0, cliprect );
790
791   return 0;
792}
793
794
trunk/src/emu/video/i8244.h
r0r20209
1/***************************************************************************
2
3    i8244.h
4
5    Intel 8244 (NTSC)/8245 (PAL) Graphics and sound chip
6
7***************************************************************************/
8
9#pragma once
10
11#ifndef __I8244_H__
12#define __I8244_H__
13
14#include "emu.h"
15
16
17/***************************************************************************
18    DEVICE CONFIGURATION MACROS
19***************************************************************************/
20
21#define MCFG_I8244_ADD(_tag, _clock, _screen_tag, _irq_cb, _postprocess_cb) \
22   MCFG_DEVICE_ADD(_tag, I8244, _clock) \
23   MCFG_I8244_SCREEN_TAG(_screen_tag) \
24   MCFG_I8244_IRQ_CB(_irq_cb) \
25   MCFG_I8244_POSTPROCESS_CB(_postprocess_cb) \
26
27#define MCFG_I8244_SCREEN_TAG(_screen_tag) \
28   i8244_device::set_screen_tag(*device, _screen_tag); \
29
30#define MCFG_I8244_IRQ_CB(_devcb) \
31   devcb = &i8244_device::set_irq_cb(*device, DEVCB2_##_devcb); \
32
33#define MCFG_I8244_POSTPROCESS_CB(_devcb) \
34   devcb = &i8244_device::set_postprocess_cb(*device, DEVCB2_##_devcb); \
35
36#define MCFG_I8245_ADD(_tag, _clock, _screen_tag, _irq_cb, _postprocess_cb) \
37   MCFG_DEVICE_ADD(_tag, I8245, _clock) \
38   MCFG_I8244_SCREEN_TAG(_screen_tag) \
39   MCFG_I8244_IRQ_CB(_irq_cb) \
40   MCFG_I8244_POSTPROCESS_CB(_postprocess_cb ) \
41
42
43/***************************************************************************
44    TYPE DEFINITIONS
45***************************************************************************/
46
47union vdc_t {
48   UINT8 reg[0x100];
49   struct {
50      struct {
51          UINT8 y,x,color,res;
52      } sprites[4];
53      struct {
54          UINT8 y,x,ptr,color;
55      } foreground[12];
56      struct {
57          struct {
58            UINT8 y,x,ptr,color;
59          } single[4];
60      } quad[4];
61      UINT8 shape[4][8];
62      UINT8 control;
63      UINT8 status;
64      UINT8 collision;
65      UINT8 color;
66      UINT8 y;
67      UINT8 x;
68      UINT8 res;
69      UINT8 shift1;
70      UINT8 shift2;
71      UINT8 shift3;
72      UINT8 sound;
73      UINT8 res2[5+0x10];
74      UINT8 hgrid[2][0x10];
75      UINT8 vgrid[0x10];
76   } s;
77};
78
79
80// ======================> i8244_device
81
82class i8244_device :  public device_t
83               , public device_sound_interface
84{
85public:
86    // construction/destruction
87    i8244_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
88   i8244_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int lines);
89
90   // static configuration helpers
91   static void set_screen_tag(device_t &device, const char *screen_tag) { downcast<i8244_device &>(device).m_screen_tag = screen_tag; }
92   template<class _Object> static devcb2_base &set_irq_cb(device_t &device, _Object object) { return downcast<i8244_device &>(device).m_irq_func.set_callback(object); }
93   template<class _Object> static devcb2_base &set_postprocess_cb(device_t &device, _Object object) { return downcast<i8244_device &>(device).m_postprocess_func.set_callback(object); }
94
95   virtual void palette_init();
96
97   DECLARE_READ8_MEMBER(read);
98   DECLARE_WRITE8_MEMBER(write);
99   DECLARE_READ_LINE_MEMBER(vblank);
100   DECLARE_READ_LINE_MEMBER(hblank);
101
102   UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
103
104   inline bitmap_ind16 *get_bitmap() { return &m_tmp_bitmap; }
105
106   // Global constants
107   static const int START_ACTIVE_SCAN = 42;
108   static const int END_ACTIVE_SCAN   = 42 + 10 + 320 + 10;
109   static const int START_Y           = 1;
110   static const int SCREEN_HEIGHT     = 243;
111   static const int LINE_CLOCKS       = 455;
112   static const int LINES             = 262;
113
114protected:
115   // device-level overrides
116   virtual void device_start();
117   virtual void device_reset();
118   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
119
120   // device_sound_interface overrides
121   virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
122
123   void render_scanline(int vpos);
124   int get_y_beam();
125   int get_x_beam();
126   offs_t fix_register_mirrors( offs_t offset );
127
128   // Local constants
129   static const UINT8 VDC_CONTROL_REG_STROBE_XY = 0x02;
130
131   /* timers */
132   static const device_timer_id TIMER_LINE = 0;
133   static const device_timer_id TIMER_HBLANK = 1;
134
135    // callbacks
136    devcb2_write_line m_irq_func;
137   devcb2_write16 m_postprocess_func;
138
139   const char *m_screen_tag;
140   screen_device *m_screen;
141   bitmap_ind16 m_tmp_bitmap;
142   emu_timer *m_line_timer;
143   emu_timer *m_hblank_timer;
144   sound_stream *m_stream;
145
146   int m_start_vpos;
147   int m_start_vblank;
148   int m_screen_lines;
149
150   vdc_t m_vdc;
151   UINT16 m_sh_count;
152   UINT8 m_x_beam_pos;
153   UINT8 m_y_beam_pos;
154   UINT8 m_control_status;
155   UINT8 m_collision_status;
156   int m_iff;
157};
158
159
160class i8245_device :  public i8244_device
161{
162public:
163   // construction/destruction
164   i8245_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
165
166   static const int LINES = 312;
167};
168
169
170// device type definition
171extern const device_type I8244;
172extern const device_type I8245;
173
174
175#endif  /* __I8244_H__ */
trunk/src/emu/emu.mak
r20208r20209
308308   $(EMUVIDEO)/huc6261.o       \
309309   $(EMUVIDEO)/huc6270.o       \
310310   $(EMUVIDEO)/huc6272.o       \
311   $(EMUVIDEO)/i8244.o         \
311312   $(EMUVIDEO)/i8275.o         \
312313   $(EMUVIDEO)/i8275x.o        \
313314   $(EMUVIDEO)/k053250.o       \
trunk/src/mess/drivers/odyssey2.c
r20208r20209
2121#include "includes/odyssey2.h"
2222#include "imagedev/cartslot.h"
2323#include "sound/sp0256.h"
24#include "video/i8244.h"
2425
2526
2627static ADDRESS_MAP_START( odyssey2_mem , AS_PROGRAM, 8, odyssey2_state )
r20208r20209
4647   AM_RANGE(MCS48_PORT_P2,   MCS48_PORT_P2)   AM_READWRITE(p2_read, p2_write)
4748   AM_RANGE(MCS48_PORT_BUS,  MCS48_PORT_BUS)  AM_READWRITE(bus_read, bus_write)
4849   AM_RANGE(MCS48_PORT_T0,   MCS48_PORT_T0)   AM_READ(t0_read)
49   AM_RANGE(MCS48_PORT_T1,   MCS48_PORT_T1)   AM_READ(t1_read)
50   AM_RANGE(MCS48_PORT_T1,   MCS48_PORT_T1)   AM_READ(t1_read_g7400)
5051   AM_RANGE(MCS48_PORT_PROG, MCS48_PORT_PROG) AM_DEVWRITE("i8243", i8243_device, i8243_prog_w);
5152ADDRESS_MAP_END
5253
r20208r20209
130131INPUT_PORTS_END
131132
132133
134WRITE_LINE_MEMBER(odyssey2_state::irq_callback)
135{
136   m_maincpu->set_input_line(0, state);
137}
138
139
133140static const gfx_layout odyssey2_graphicslayout =
134141{
135142   8,1,
r20208r20209
255262
256263   /* video hardware */
257264   MCFG_SCREEN_ADD("screen", RASTER)
258   MCFG_SCREEN_RAW_PARAMS( 3547000*2, 2*I824X_LINE_CLOCKS, 2*I824X_START_ACTIVE_SCAN, 2*I824X_END_ACTIVE_SCAN, 312, I824X_START_Y, I824X_START_Y + I824X_SCREEN_HEIGHT + 10 )
265   MCFG_SCREEN_RAW_PARAMS( 3540000*2, i8244_device::LINE_CLOCKS, i8244_device::START_ACTIVE_SCAN, i8244_device::END_ACTIVE_SCAN, i8245_device::LINES, i8244_device::START_Y, i8244_device::START_Y + i8244_device::SCREEN_HEIGHT )
259266   MCFG_SCREEN_UPDATE_DRIVER(odyssey2_state, screen_update_odyssey2)
260267
261268   MCFG_VIDEO_START_OVERRIDE(odyssey2_state,g7400)
r20208r20209
265272
266273   MCFG_I8243_ADD( "i8243", NOOP, WRITE8(odyssey2_state,i8243_port_w))
267274
268   /* sound hardware */
269275   MCFG_SPEAKER_STANDARD_MONO("mono")
270   MCFG_SOUND_ADD("custom", ODYSSEY2, 3547000)
276   MCFG_I8244_ADD( "i8244", 3540000, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( odyssey2_state, scanline_postprocess ) )
271277   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
272278
273279   MCFG_FRAGMENT_ADD(odyssey2_cartslot)
trunk/src/mess/machine/odyssey2.c
r20208r20209
155155{
156156   if ((m_p1 & (P1_VDC_COPY_MODE_ENABLE | P1_VDC_ENABLE)) == 0)
157157   {
158      return video_read(space, offset); /* seems to have higher priority than ram??? */
158      return m_i8244->read(space, offset); /* seems to have higher priority than ram??? */
159159   }
160160   else if (!(m_p1 & P1_EXT_RAM_ENABLE))
161161   {
r20208r20209
178178   }
179179   else if (!(m_p1 & P1_VDC_ENABLE))
180180   {
181      video_write(space, offset, data);
181      m_i8244->write(space, offset, data);
182182   }
183183   else
184184   {
trunk/src/mess/includes/odyssey2.h
r20208r20209
88#define ODYSSEY2_H_
99
1010#include "machine/i8243.h"
11#include "video/i8244.h"
1112
1213
1314#define P1_BANK_LO_BIT            (0x01)
r20208r20209
1920
2021#define P2_KEYBOARD_SELECT_MASK   (0x07)  /* select row to scan */
2122
22#define VDC_CONTROL_REG_STROBE_XY (0x02)
23#define OLD_VDC_CONTROL_REG_STROBE_XY (0x02)
2324
2425#define I824X_START_ACTIVE_SCAN         6
2526#define I824X_END_ACTIVE_SCAN           (6 + 160)
r20208r20209
8182      , m_maincpu(*this, "maincpu")
8283      , m_screen(*this, "screen")
8384      , m_i8243(*this, "i8243")
85      , m_i8244(*this, "i8244")
8486      , m_g7400(false)
8587      { }
8688
8789   required_device<cpu_device> m_maincpu;
8890   required_device<screen_device> m_screen;
8991   optional_device<i8243_device> m_i8243;
92   optional_device<i8244_device> m_i8244;
9093
9194   int m_the_voice_lrq_state;
9295   UINT8 *m_ram;
r20208r20209
121124   DECLARE_WRITE8_MEMBER(video_write);
122125   DECLARE_WRITE8_MEMBER(lum_write);
123126   DECLARE_READ8_MEMBER(t1_read);
127   DECLARE_READ8_MEMBER(t1_read_g7400);
124128   DECLARE_DRIVER_INIT(odyssey2);
125129   virtual void machine_start();
126130   virtual void machine_reset();
r20208r20209
130134   UINT32 screen_update_odyssey2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
131135   DECLARE_WRITE_LINE_MEMBER(the_voice_lrq_callback);
132136   DECLARE_WRITE8_MEMBER(i8243_port_w);
137   DECLARE_WRITE_LINE_MEMBER(irq_callback);
133138
134139   void ef9341_w( UINT8 command, UINT8 b, UINT8 data );
135140   UINT8 ef9341_r( UINT8 command, UINT8 b );
136141
142   DECLARE_WRITE16_MEMBER(scanline_postprocess);
143
137144protected:
138145   ef9340_t m_ef9340;
139146   ef9341_t m_ef9341;
trunk/src/mess/video/odyssey2.c
r20208r20209
3434const UINT8 odyssey2_colors[] =
3535{
3636   /* Background,Grid Dim */
37   0x00,0x00,0x00,
38   0x00,0x00,0xFF,   /* Blue */
39   0x00,0x80,0x00,   /* DK Green */
40   0xff,0x9b,0x60,
41   0xCC,0x00,0x00,   /* Red */
42   0xa9,0x80,0xff,
43   0x82,0xfd,0xdb,
44   0xFF,0xFF,0xFF,
37   0x00, 0x00, 0x00, //   0x00,0x00,0x00,                  // i r g b
38   0x00, 0x00, 0xAA, //   0x00,0x00,0xFF,   /* Blue */      // i r g B
39   0x00, 0xAA, 0x00, //   0x00,0x80,0x00,   /* DK Green */   // i r G b
40   0x00, 0xAA, 0xAA, //   0xff,0x9b,0x60,                  // i r G B
41   0xAA, 0x00, 0x00, //   0xCC,0x00,0x00,   /* Red */         // i R g b
42   0xAA, 0x00, 0xAA, //   0xa9,0x80,0xff,                  // i R g B
43   0xAA, 0xAA, 0x00, //   0x82,0xfd,0xdb,                  // i R G b
44   0xAA, 0xAA, 0xAA, //   0xFF,0xFF,0xFF,                  // i R G B
4545
4646   /* Background,Grid Bright */
47   0x80,0x80,0x80,
48   0x50,0xAE,0xFF,   /* Blue */
49   0x00,0xFF,0x00,   /* Dk Green */
50   0x82,0xfb,0xdb,   /* Lt Grey */
51   0xEC,0x02,0x60,   /* Red */
52   0xa9,0x80,0xff,   /* Violet */
53   0xff,0x9b,0x60,   /* Orange */
54   0xFF,0xFF,0xFF,
47   0x55, 0x55, 0x55, //   0x80,0x80,0x80,                  // I r g b
48   0x55, 0x55, 0xFF, //   0x50,0xAE,0xFF,   /* Blue */      // I r g B
49   0x55, 0xFF, 0x55, //   0x00,0xFF,0x00,   /* Dk Green */   // I r G b
50   0x55, 0xFF, 0xFF, //   0x82,0xfb,0xdb,   /* Lt Grey */      // I r G B
51   0xFF, 0x55, 0x55, //   0xEC,0x02,0x60,   /* Red */         // I R g b
52   0xFF, 0x55, 0xFF, //   0xa9,0x80,0xff,   /* Violet */      // I R g B
53   0xFF, 0xFF, 0x55, //   0xff,0x9b,0x60,   /* Orange */      // I R G b
54   0xFF, 0xFF, 0xFF, //   0xFF,0xFF,0xFF,                  // I R G B
5555
5656   /* Character,Sprite colors */
57   0x80,0x80,0x80,   /* Dark Grey */
58   0xFF,0x80,0x80,   /* Red */
59   0x00,0xC0,0x00,   /* Green */
60   0xff,0x9b,0x60,   /* Orange */
61   0x50,0xAE,0xFF,   /* Blue */
62   0xa9,0x80,0xff,   /* Violet */
63   0x82,0xfb,0xdb,   /* Lt Grey */
64   0xff,0xff,0xff,   /* White */
57   0x80,0x80,0x80,   /* Dark Grey */   // I r g b
58   0xFF,0x80,0x80,   /* Red */         // I R g b
59   0x00,0xC0,0x00,   /* Green */      // I r G b
60   0xff,0x9b,0x60,   /* Orange */      // I R G b
61   0x50,0xAE,0xFF,   /* Blue */      // I r g B
62   0xa9,0x80,0xff,   /* Violet */      // I R g B
63   0x82,0xfb,0xdb,   /* Lt Grey */      // I r G B
64   0xff,0xff,0xff,   /* White */      // I R G B
6565
6666   /* EF9340/EF9341 colors */
6767   0x00, 0x00, 0x00,
r20208r20209
175175         break;
176176
177177      case 0xa4:
178         if (m_o2_vdc.s.control & VDC_CONTROL_REG_STROBE_XY)
178         if (m_o2_vdc.s.control & OLD_VDC_CONTROL_REG_STROBE_XY)
179179         {
180180            m_y_beam_pos = m_screen->vpos() - m_start_vpos;
181181         }
r20208r20209
187187
188188      case 0xa5:
189189
190         if ((m_o2_vdc.s.control & VDC_CONTROL_REG_STROBE_XY))
190         if ((m_o2_vdc.s.control & OLD_VDC_CONTROL_REG_STROBE_XY))
191191         {
192192            m_x_beam_pos = m_screen->hpos();
193193            if ( m_x_beam_pos < I824X_START_ACTIVE_SCAN )
r20208r20209
219219      m_sh_channel->update();
220220
221221   if (offset == 0xa0) {
222      if (    m_o2_vdc.s.control & VDC_CONTROL_REG_STROBE_XY
223            && !(data & VDC_CONTROL_REG_STROBE_XY))
222      if (    m_o2_vdc.s.control & OLD_VDC_CONTROL_REG_STROBE_XY
223            && !(data & OLD_VDC_CONTROL_REG_STROBE_XY))
224224      {
225225         /* Toggling strobe bit, tuck away values */
226226         m_x_beam_pos = m_screen->hpos();
r20208r20209
243243
244244WRITE8_MEMBER(odyssey2_state::lum_write)
245245{
246   m_lum = data;
246   m_lum = ( data & 0x01 ) << 3;
247247}
248248
249249
250WRITE16_MEMBER(odyssey2_state::scanline_postprocess)
251{
252   int vpos = data;
253   bitmap_ind16 *bitmap = m_i8244->get_bitmap();
254
255   // apply external LUM setting
256   for ( int x = i8244_device::START_ACTIVE_SCAN; x < i8244_device::END_ACTIVE_SCAN; x++ )
257   {
258      bitmap->pix16( vpos, x ) |= ( m_lum ^ 0x08 );
259   }
260}
261
262
250263READ8_MEMBER(odyssey2_state::t1_read)
251264{
252265   if ( m_screen->vpos() > m_start_vpos && m_screen->vpos() < m_start_vblank )
r20208r20209
260273}
261274
262275
276READ8_MEMBER(odyssey2_state::t1_read_g7400)
277{
278   if ( m_i8244->vblank() || m_i8244->hblank() )
279   {
280      return 1;
281   }
282   return 0;
283}
284
285
263286void odyssey2_state::i824x_scanline(int vpos)
264287{
265288   UINT8   collision_map[160];
r20208r20209
647670{
648671   copybitmap( bitmap, m_tmp_bitmap, 0, 0, 0, 0, cliprect );
649672
673   if ( m_i8244 )
674   {
675      return m_i8244->screen_update(screen, bitmap, cliprect);
676   }
650677   return 0;
651678}
652679

Previous 199869 Revisions Next


© 1997-2024 The MAME Team