Previous 199869 Revisions Next

r19393 Friday 7th December, 2012 at 16:06:31 UTC by Curt Coder
(MESS) Removed unused legacy code. (nw)
[src/mess]mess.mak
[src/mess/video]vdc8563.c vdc8563.h vic6567.c vic6567.h

trunk/src/mess/video/vdc8563.c
r19392r19393
1/***************************************************************************
2
3  CBM Video Device Chip 8563
4
5  Original code by PeT (peter.trauner@jk.uni-linz.ac.at)
6
7    2010-02: converted to be a device
8
9    TODO:
10      - clean up the code
11      - add RAM with an internal address map
12
13***************************************************************************/
14/*
15 several graphic problems
16 some are in the rastering engine and should be solved during its evalution
17 rare and short documentation,
18 registers and some words of description in the c128 user guide */
19/* seems to be a motorola m6845 variant */
20
21
22#include "emu.h"
23#include "video/vdc8563.h"
24
25struct vdc8563_state
26{
27   screen_device *screen;
28
29   int state;
30   UINT8 reg[37];
31   UINT8 index;
32
33   UINT16 addr, src;
34
35   UINT16 videoram_start, colorram_start, fontram_start;
36   UINT16 videoram_size;
37
38   int rastering;
39
40   UINT8 *ram;
41   UINT8 *dirty;
42   UINT8 fontdirty[0x200];
43   UINT16 mask, fontmask;
44
45   double cursor_time;
46   int   cursor_on;
47
48   int changed;
49};
50
51/*****************************************************************************
52    CONSTANTS
53*****************************************************************************/
54
55#define VERBOSE_LEVEL 0
56#define DBG_LOG(N, M, A)      \
57   do { \
58      if (VERBOSE_LEVEL >= N) \
59      { \
60         if (M) \
61            logerror("%11.6f: %-24s",device->machine().time().as_double(),(char*)M ); \
62         logerror A; \
63      } \
64   } while (0)
65
66
67static const struct {
68   int stored,
69      read;
70} reg_mask[]= {
71   { 0xff, 0 },
72   { 0xff, 0 },
73   { 0xff, 0 },
74   { 0xff, 0 },
75   { 0xff, 0 },
76   { 0x1f, 0 },
77   { 0xff, 0 },
78   { 0xff, 0 },
79   {  0x3, 0 }, //8
80   {  0x1f, 0 },
81   {  0x7f, 0 },
82   {  0x1f, 0 },
83   {  0xff, 0xff },
84   {  0xff, 0xff },
85   {  0xff, 0xff },
86   {  0xff, 0xff },
87   {  -1, 0xff }, //0x10
88   {  -1, 0xff },
89   {  0xff, 0xff },
90   {  0xff, 0xff },
91   {  0xff, -1 },
92   {  0x1f, -1 },
93   {  0xff, -1 },
94   {  0xff, -1 },
95   {  0xff, -1 },//0x18
96   {  0xff, -1 },
97   {  0xff, -1 },
98   {  0xff, -1 },
99   {  0xf0, -1 },
100   {  0x1f, -1 },
101   {  0xff, -1 },
102   {  0xff, -1 },
103   {  0xff, -1 }, //0x20
104   {  0xff, -1 },
105   {  0xff, -1 },
106   {  0xff, -1 },
107   {  0x0f, -1 },
108};
109#define REG(x)          (vdc8563->reg[x] & reg_mask[x].stored)
110
111
112#define CHAR_WIDTH      (((vdc8563->reg[0x16] & 0xf0) >> 4) + 1)
113#define CHAR_WIDTH_VISIBLE ((vdc8563->reg[0x16] & 0x0f) + 1)
114
115#define BLOCK_COPY      (vdc8563->reg[0x18] & 0x80)
116
117#define MONOTEXT        ((vdc8563->reg[0x19] & 0xc0) == 0)
118#define TEXT            ((vdc8563->reg[0x19] & 0xc0) == 0x40)
119#define GRAPHIC         (vdc8563->reg[0x19] & 0x80)
120
121#define FRAMECOLOR      (vdc8563->reg[0x1a] & 0x0f)
122#define MONOCOLOR       (vdc8563->reg[0x1a] >> 4)
123
124#define LINEDIFF        (vdc8563->reg[0x1b])
125#define FONT_START      ((vdc8563->reg[0x1c] & 0xe0) << 8)
126/* 0x1c 0x10 dram 0:4416, 1: 4164 */
127
128/* 0x1d 0x1f counter for underlining */
129
130#define FILLBYTE        vdc8563->reg[0x1f]
131
132#define CLOCK_HALFING   (vdc8563->reg[25] & 0x10)
133
134
135/* the regs below corresponds to the ones used by 6845, hence we borrow the macros */
136#define CRTC6845_COLUMNS (REG(0) + 1)
137#define CRTC6845_CHAR_COLUMNS (REG(1))
138#define CRTC6845_CHAR_LINES REG(6)
139#define CRTC6845_CHAR_HEIGHT ((REG(9) & 0x1f) + 1)
140#define CRTC6845_LINES (REG(4) * CRTC6845_CHAR_HEIGHT + REG(5))
141#define CRTC6845_VIDEO_START ((REG(0xc) << 8) | REG(0xd))
142#define CRTC6845_INTERLACE_MODE (REG(8) & 3)
143#define CRTC6845_INTERLACE_SIGNAL 1
144#define CRTC6845_INTERLACE 3
145#define CRTC6845_CURSOR_MODE (REG(0xa) & 0x60)
146#define CRTC6845_CURSOR_OFF 0x20
147#define CRTC6845_CURSOR_16FRAMES 0x40
148#define CRTC6845_CURSOR_32FRAMES 0x60
149#define CRTC6845_SKEW   (REG(8) & 15)
150#define CRTC6845_CURSOR_POS ((REG(0xe) << 8) | REG(0xf))
151#define CRTC6845_CURSOR_TOP   (REG(0xa) & 0x1f)
152#define CRTC6845_CURSOR_BOTTOM REG(0xb)
153
154
155/*****************************************************************************
156    INLINE FUNCTIONS
157*****************************************************************************/
158
159INLINE vdc8563_state *get_safe_token( device_t *device )
160{
161   assert(device != NULL);
162   assert(device->type() == VDC8563);
163
164   return (vdc8563_state *)downcast<vdc8563_device *>(device)->token();
165}
166
167INLINE const vdc8563_interface *get_interface( device_t *device )
168{
169   assert(device != NULL);
170   assert((device->type() == VDC8563));
171   return (const vdc8563_interface *) device->static_config();
172}
173
174/*****************************************************************************
175    IMPLEMENTATION
176*****************************************************************************/
177
178static void vdc_videoram_w( device_t *device, int offset, int data )
179{
180   vdc8563_state *vdc8563 = get_safe_token(device);
181
182   offset &= vdc8563->mask;
183
184   if (vdc8563->ram[offset] != data)
185   {
186      vdc8563->ram[offset] = data;
187      vdc8563->dirty[offset] = 1;
188      if ((vdc8563->fontram_start & vdc8563->fontmask) == (offset & vdc8563->fontmask))
189         vdc8563->fontdirty[(offset & 0x1ff0) >> 4] = 1;
190   }
191}
192
193INLINE int vdc_videoram_r( device_t *device, int offset )
194{
195   vdc8563_state *vdc8563 = get_safe_token(device);
196   return vdc8563->ram[offset & vdc8563->mask];
197}
198
199void vdc8563_set_rastering( device_t *device, int on )
200{
201   vdc8563_state *vdc8563 = get_safe_token(device);
202   vdc8563->rastering = on;
203   vdc8563->changed |= 1;
204}
205
206
207
208/* 0x22 number of chars from start of line to positiv edge of display enable */
209/* 0x23 number of chars from start of line to negativ edge of display enable */
210/* 0x24 0xf number of refresh cycles per line */
211
212WRITE8_DEVICE_HANDLER( vdc8563_port_w )
213{
214   vdc8563_state *vdc8563 = get_safe_token(device);
215   UINT8 i;
216
217   if (offset & 1)
218   {
219      if ((vdc8563->index & 0x3f) < 37)
220      {
221         switch (vdc8563->index & 0x3f)
222         {
223         case 1: case 4: case 0x1b:
224            vdc8563->reg[vdc8563->index] = data;
225            vdc8563->videoram_size = CRTC6845_CHAR_LINES * (CRTC6845_CHAR_COLUMNS + LINEDIFF);
226            vdc8563->changed = 1;
227            break;
228         case 0xe: case 0xf: case 0xa: case 0xb:
229            vdc8563->dirty[CRTC6845_CURSOR_POS & vdc8563->mask] = 1;
230            vdc8563->reg[vdc8563->index] = data;
231            break;
232         case 0xc: case 0xd:
233            vdc8563->reg[vdc8563->index] = data;
234            vdc8563->videoram_start = CRTC6845_VIDEO_START;
235            vdc8563->changed = 1;
236            break;
237         case 0x12:
238            vdc8563->addr = (vdc8563->addr & 0x00ff) | (data << 8);
239            break;
240         case 0x13:
241            vdc8563->addr = (vdc8563->addr & 0xff00) | data;
242            break;
243         case 0x20:
244            vdc8563->src = (vdc8563->src & 0x00ff) | (data << 8);
245            break;
246         case 0x21:
247            vdc8563->src = (vdc8563->src & 0xff00) | data;
248            break;
249         case 0x14: case 0x15:
250            vdc8563->reg[vdc8563->index] = data;
251            vdc8563->colorram_start = (vdc8563->reg[0x14] << 8) | vdc8563->reg[0x15];
252            vdc8563->changed = 1;
253            break;
254         case 0x1c:
255            vdc8563->reg[vdc8563->index] = data;
256            vdc8563->fontram_start = FONT_START;
257            vdc8563->changed = 1;
258            break;
259         case 0x16: case 0x19: case 0x1a:
260            vdc8563->reg[vdc8563->index] = data;
261            vdc8563->changed = 1;
262            break;
263         case 0x1e:
264            vdc8563->reg[vdc8563->index] = data;
265            if (BLOCK_COPY)
266            {
267               DBG_LOG(2, "vdc block copy", ("src:%.4x dst:%.4x size:%.2x\n", vdc8563->src, vdc8563->addr, data));
268               i = data;
269               do {
270                  vdc_videoram_w(device, vdc8563->addr++, vdc_videoram_r(device, vdc8563->src++));
271               } while (--i != 0);
272            }
273            else
274            {
275               DBG_LOG(2, "vdc block set", ("dest:%.4x value:%.2x size:%.2x\n", vdc8563->addr, FILLBYTE, data));
276               i = data;
277               do {
278                  vdc_videoram_w(device, vdc8563->addr++, FILLBYTE);
279               } while (--i != 0);
280            }
281            break;
282         case 0x1f:
283            DBG_LOG(2, "vdc written", ("dest:%.4x size:%.2x\n", vdc8563->addr, data));
284            vdc8563->reg[vdc8563->index] = data;
285            vdc_videoram_w(device, vdc8563->addr++, data);
286            break;
287         default:
288            vdc8563->reg[vdc8563->index] = data;
289            DBG_LOG(2, "vdc8563_port_w", ("%.2x:%.2x\n", vdc8563->index, data));
290            break;
291         }
292      }
293      DBG_LOG(3, "vdc8563_port_w", ("%.2x:%.2x\n", vdc8563->index, data));
294   }
295   else
296   {
297      vdc8563->index = data;
298   }
299}
300
301READ8_DEVICE_HANDLER( vdc8563_port_r )
302{
303   vdc8563_state *vdc8563 = get_safe_token(device);
304   int val;
305
306   val = 0xff;
307   if (offset & 1)
308   {
309      if ((vdc8563->index & 0x3f) < 37)
310      {
311         switch (vdc8563->index & 0x3f)
312         {
313         case 0x12:
314            val = vdc8563->addr >> 8;
315            break;
316         case 0x13:
317            val = vdc8563->addr & 0xff;
318            break;
319         case 0x1e:
320            val = 0;
321            break;
322         case 0x1f:
323            val = vdc_videoram_r(device, vdc8563->addr);
324            DBG_LOG(2, "vdc read", ("%.4x %.2x\n", vdc8563->addr, val));
325            break;
326         case 0x20:
327            val = vdc8563->src >> 8;
328            break;
329         case 0x21:
330            val = vdc8563->src & 0xff;
331            break;
332         default:
333            val = vdc8563->reg[vdc8563->index & 0x3f] & reg_mask[vdc8563->index & 0x3f].read;
334         }
335      }
336      DBG_LOG(2, "vdc8563_port_r", ("%.2x:%.2x\n", vdc8563->index, val));
337   }
338   else
339   {
340      val = vdc8563->index;
341      if (vdc8563->state)
342         val |= 0x80;
343   }
344   return val;
345}
346
347static int vdc8563_clocks_in_frame( device_t *device )
348{
349   vdc8563_state *vdc8563 = get_safe_token(device);
350   int clocks = CRTC6845_COLUMNS * CRTC6845_LINES;
351
352   switch (CRTC6845_INTERLACE_MODE)
353   {
354   case CRTC6845_INTERLACE_SIGNAL: // interlace generation of video signals only
355   case CRTC6845_INTERLACE: // interlace
356      return clocks / 2;
357   default:
358      return clocks;
359   }
360}
361
362static void vdc8563_time( device_t *device )
363{
364   vdc8563_state *vdc8563 = get_safe_token(device);
365   double newtime, ftime;
366   newtime = device->machine().time().as_double();
367
368   if (vdc8563_clocks_in_frame(device) == 0.0)
369      return;
370
371   ftime = 16 * vdc8563_clocks_in_frame(device) / 2000000.0;
372   if (CLOCK_HALFING)
373      ftime *= 2;
374   switch (CRTC6845_CURSOR_MODE)
375   {
376   case CRTC6845_CURSOR_OFF:
377      vdc8563->cursor_on = 0;
378      break;
379   case CRTC6845_CURSOR_32FRAMES:
380      ftime *= 2;
381   case CRTC6845_CURSOR_16FRAMES:
382      if (newtime - vdc8563->cursor_time > ftime)
383      {
384         vdc8563->cursor_time += ftime;
385         vdc8563->dirty[CRTC6845_CURSOR_POS & vdc8563->mask] = 1;
386         vdc8563->cursor_on ^= 1;
387      }
388      break;
389   default:
390      vdc8563->cursor_on = 1;
391      break;
392   }
393}
394
395static void vdc8563_monotext_screenrefresh( device_t *device, bitmap_ind16 &bitmap, int full_refresh )
396{
397   vdc8563_state *vdc8563 = get_safe_token(device);
398   running_machine &machine = device->machine();
399   int x, y, i;
400   rectangle rect;
401   int w = CRTC6845_CHAR_COLUMNS;
402   int h = CRTC6845_CHAR_LINES;
403   int height = CRTC6845_CHAR_HEIGHT;
404
405   rect.setx(vdc8563->screen->visible_area().min_x, vdc8563->screen->visible_area().max_x);
406
407   if (full_refresh)
408      memset(vdc8563->dirty + vdc8563->videoram_start, 1, vdc8563->videoram_size);
409
410   for (y = 0, rect.min_y = height, rect.max_y = rect.min_y + height - 1, i = vdc8563->videoram_start & vdc8563->mask; y < h;
411      y++, rect.min_y += height, rect.max_y += height)
412   {
413      for (x = 0; x < w; x++, i = (i + 1) & vdc8563->mask)
414      {
415         if (vdc8563->dirty[i])
416         {
417            drawgfx_opaque(bitmap,rect,machine.gfx[0], vdc8563->ram[i], FRAMECOLOR | (MONOCOLOR << 4), 0, 0,
418                  machine.gfx[0]->width() * x + 8, height * y + height);
419
420            if ((vdc8563->cursor_on) && (i == (CRTC6845_CURSOR_POS & vdc8563->mask)))
421            {
422               int k = height - CRTC6845_CURSOR_TOP;
423               if (CRTC6845_CURSOR_BOTTOM < height)
424                  k = CRTC6845_CURSOR_BOTTOM - CRTC6845_CURSOR_TOP + 1;
425
426               if (k > 0)
427                  bitmap.plot_box(machine.gfx[0]->width() * x + 8, height * y + height + CRTC6845_CURSOR_TOP, machine.gfx[0]->width(), k, FRAMECOLOR);
428            }
429
430            vdc8563->dirty[i] = 0;
431         }
432      }
433      i += LINEDIFF;
434   }
435}
436
437static void vdc8563_text_screenrefresh( device_t *device, bitmap_ind16 &bitmap, int full_refresh )
438{
439   vdc8563_state *vdc8563 = get_safe_token(device);
440   running_machine &machine = device->machine();
441   int x, y, i, j;
442   rectangle rect;
443   int w = CRTC6845_CHAR_COLUMNS;
444   int h = CRTC6845_CHAR_LINES;
445   int height = CRTC6845_CHAR_HEIGHT;
446
447   rect.setx(vdc8563->screen->visible_area().min_x, vdc8563->screen->visible_area().max_x);
448
449   if (full_refresh)
450      memset(vdc8563->dirty + vdc8563->videoram_start, 1, vdc8563->videoram_size);
451
452   for (y = 0, rect.min_y = height, rect.max_y = rect.min_y + height - 1, i = vdc8563->videoram_start & vdc8563->mask,
453      j = vdc8563->colorram_start & vdc8563->mask; y < h; y++, rect.min_y += height, rect.max_y += height)
454   {
455      for (x = 0; x < w; x++, i = (i + 1) & vdc8563->mask, j = (j + 1) & vdc8563->mask)
456      {
457         if (vdc8563->dirty[i] || vdc8563->dirty[j])
458         {
459            {
460               UINT16 ch, fg, bg;
461               const UINT8 *charptr;
462               int v, h2;
463               UINT16 *pixel;
464
465               ch = vdc8563->ram[i] | ((vdc8563->ram[j] & 0x80) ? 0x100 : 0);
466               charptr = &vdc8563->ram[(vdc8563->fontram_start + (ch * 16)) & vdc8563->mask];
467               fg = ((vdc8563->ram[j] & 0x0f) >> 0) + 0x10;
468               bg = ((vdc8563->ram[j] & 0x70) >> 4) + 0x10;
469
470               for (v = 0; v < 16; v++)
471               {
472                  for (h2 = 0; h2 < 8; h2++)
473                  {
474                     pixel = &bitmap.pix16((y * height) + height + v, (x * 8) + 8 + h2);
475                     *pixel = (charptr[v] & (0x80 >> h2)) ? fg : bg;
476                  }
477               }
478            }
479
480            if ((vdc8563->cursor_on) && (i == (CRTC6845_CURSOR_POS & vdc8563->mask)))
481            {
482               int k = height - CRTC6845_CURSOR_TOP;
483               if (CRTC6845_CURSOR_BOTTOM < height)
484                  k = CRTC6845_CURSOR_BOTTOM - CRTC6845_CURSOR_TOP + 1;
485
486               if (k > 0)
487                  bitmap.plot_box(machine.gfx[0]->width() * x + 8, height * y + height + CRTC6845_CURSOR_TOP, machine.gfx[0]->width(),
488                        k, 0x10 | (vdc8563->ram[j] & 0x0f));
489            }
490
491            vdc8563->dirty[i] = 0;
492            vdc8563->dirty[j] = 0;
493         }
494      }
495      i += LINEDIFF;
496      j += LINEDIFF;
497   }
498}
499
500static void vdc8563_graphic_screenrefresh( device_t *device, bitmap_ind16 &bitmap, int full_refresh )
501{
502   vdc8563_state *vdc8563 = get_safe_token(device);
503   running_machine &machine = device->machine();
504   int x, y, i, j, k;
505   rectangle rect;
506   int w = CRTC6845_CHAR_COLUMNS;
507   int h = CRTC6845_CHAR_LINES;
508   int height = CRTC6845_CHAR_HEIGHT;
509
510   rect.setx(vdc8563->screen->visible_area().min_x, vdc8563->screen->visible_area().max_x);
511
512   if (full_refresh)
513      memset(vdc8563->dirty, 1, vdc8563->mask + 1);
514
515   for (y = 0, rect.min_y = height, rect.max_y = rect.min_y + height - 1, i = vdc8563->videoram_start & vdc8563->mask; y < h;
516      y++, rect.min_y += height, rect.max_y += height)
517   {
518      for (x = 0; x < w; x++, i = (i + 1) & vdc8563->mask)
519      {
520         for (j = 0; j < height; j++)
521         {
522            k = ((i << 4) + j) & vdc8563->mask;
523            if (vdc8563->dirty[k])
524            {
525               drawgfx_opaque(bitmap, rect, machine.gfx[1], vdc8563->ram[k], FRAMECOLOR | (MONOCOLOR << 4), 0, 0,
526                     machine.gfx[0]->width() * x + 8, height * y + height + j);
527               vdc8563->dirty[k] = 0;
528            }
529         }
530      }
531      i += LINEDIFF;
532   }
533}
534
535UINT32 vdc8563_video_update( device_t *device, bitmap_ind16 &bitmap, const rectangle &cliprect )
536{
537   vdc8563_state *vdc8563 = get_safe_token(device);
538   int i;
539   int full_refresh = 1;
540
541   if (!vdc8563->rastering)
542      return 0;
543
544   vdc8563_time(device);
545
546   full_refresh |= vdc8563->changed;
547
548   if (GRAPHIC)
549   {
550      vdc8563_graphic_screenrefresh(device, bitmap, full_refresh);
551   }
552   else
553   {
554      for (i = 0; i < 512; i++)
555      {
556         if (full_refresh || vdc8563->fontdirty[i])
557         {
558            device->machine().gfx[0]->mark_dirty(i);
559            vdc8563->fontdirty[i] = 0;
560         }
561      }
562      if (TEXT)
563         vdc8563_text_screenrefresh(device, bitmap, full_refresh);
564      else
565         vdc8563_monotext_screenrefresh(device, bitmap, full_refresh);
566   }
567
568   if (full_refresh)
569   {
570      int w = CRTC6845_CHAR_COLUMNS;
571      int h = CRTC6845_CHAR_LINES;
572      int height = CRTC6845_CHAR_HEIGHT;
573
574      bitmap.plot_box(0, 0, device->machine().gfx[0]->width() * (w + 2), height, FRAMECOLOR);
575
576      bitmap.plot_box(0, height, device->machine().gfx[0]->width(), height * h, FRAMECOLOR);
577
578      bitmap.plot_box(device->machine().gfx[0]->width() * (w + 1), height, device->machine().gfx[0]->width(), height * h, FRAMECOLOR);
579
580      bitmap.plot_box(0, height * (h + 1), device->machine().gfx[0]->width() * (w + 2), height, FRAMECOLOR);
581   }
582
583   vdc8563->changed = 0;
584   return 0;
585}
586
587/*****************************************************************************
588    DEVICE INTERFACE
589*****************************************************************************/
590
591static DEVICE_START( vdc8563 )
592{
593   vdc8563_state *vdc8563 = get_safe_token(device);
594   const vdc8563_interface *intf = (vdc8563_interface *)device->static_config();
595
596   vdc8563->screen = device->machine().device<screen_device>(intf->screen);
597
598   vdc8563->ram = auto_alloc_array_clear(device->machine(), UINT8, 0x20000);
599   vdc8563->dirty = vdc8563->ram + 0x10000;
600
601   /* currently no driver uses 16k only */
602   if (intf->ram16konly)
603   {
604      vdc8563->mask = 0x3fff;
605      vdc8563->fontmask = 0x2000;
606   }
607   else
608   {
609      vdc8563->mask = 0xffff;
610      vdc8563->fontmask = 0xe000;
611   }
612
613   device->save_pointer(NAME(vdc8563->ram), 0x20000);
614
615   device->save_item(NAME(vdc8563->reg));
616   device->save_item(NAME(vdc8563->state));
617   device->save_item(NAME(vdc8563->index));
618
619   device->save_item(NAME(vdc8563->addr));
620   device->save_item(NAME(vdc8563->src));
621
622   device->save_item(NAME(vdc8563->videoram_start));
623   device->save_item(NAME(vdc8563->colorram_start));
624   device->save_item(NAME(vdc8563->fontram_start));
625   device->save_item(NAME(vdc8563->videoram_size));
626
627   device->save_item(NAME(vdc8563->rastering));
628
629   device->save_item(NAME(vdc8563->fontdirty));
630
631   device->save_item(NAME(vdc8563->cursor_time));
632   device->save_item(NAME(vdc8563->cursor_on));
633
634   device->save_item(NAME(vdc8563->changed));
635}
636
637
638static DEVICE_RESET( vdc8563 )
639{
640   vdc8563_state *vdc8563 = get_safe_token(device);
641
642   memset(vdc8563->reg, 0, ARRAY_LENGTH(vdc8563->reg));
643   memset(vdc8563->fontdirty, 0, ARRAY_LENGTH(vdc8563->fontdirty));
644
645   vdc8563->cursor_time = 0.0;
646   vdc8563->state = 1;
647
648   vdc8563->index = 0;
649   vdc8563->addr = 0;
650   vdc8563->src = 0;
651   vdc8563->videoram_start = 0;
652   vdc8563->colorram_start = 0;
653   vdc8563->fontram_start = 0;
654   vdc8563->videoram_size = 0;
655   vdc8563->rastering = 1;
656   vdc8563->cursor_on = 0;
657   vdc8563->changed = 0;
658}
659
660const device_type VDC8563 = &device_creator<vdc8563_device>;
661
662vdc8563_device::vdc8563_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
663   : device_t(mconfig, VDC8563, "8563 / 8568 VDC", tag, owner, clock)
664{
665   m_token = global_alloc_clear(vdc8563_state);
666}
667
668//-------------------------------------------------
669//  device_config_complete - perform any
670//  operations now that the configuration is
671//  complete
672//-------------------------------------------------
673
674void vdc8563_device::device_config_complete()
675{
676}
677
678//-------------------------------------------------
679//  device_start - device-specific startup
680//-------------------------------------------------
681
682void vdc8563_device::device_start()
683{
684   DEVICE_START_NAME( vdc8563 )(this);
685}
686
687//-------------------------------------------------
688//  device_reset - device-specific reset
689//-------------------------------------------------
690
691void vdc8563_device::device_reset()
692{
693   DEVICE_RESET_NAME( vdc8563 )(this);
694}
695
696
trunk/src/mess/video/vdc8563.h
r19392r19393
1/*****************************************************************************
2 *
3 * video/vdc8563.h
4 *
5 * CBM Video Device Chip 8563
6 *
7 * peter.trauner@jk.uni-linz.ac.at, 2000
8 *
9 ****************************************************************************/
10
11#ifndef __VDC8563_H__
12#define __VDC8563_H__
13
14#include "devcb.h"
15
16
17/***************************************************************************
18    TYPE DEFINITIONS
19***************************************************************************/
20
21struct vdc8563_interface
22{
23   const char         *screen;
24   int                ram16konly;
25};
26
27/***************************************************************************
28    DEVICE CONFIGURATION MACROS
29***************************************************************************/
30
31class vdc8563_device : public device_t
32{
33public:
34   vdc8563_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
35   ~vdc8563_device() { global_free(m_token); }
36
37   // access to legacy token
38   void *token() const { assert(m_token != NULL); return m_token; }
39protected:
40   // device-level overrides
41   virtual void device_config_complete();
42   virtual void device_start();
43   virtual void device_reset();
44private:
45   // internal state
46   void *m_token;
47};
48
49extern const device_type VDC8563;
50
51
52#define MCFG_VDC8563_ADD(_tag, _interface) \
53   MCFG_DEVICE_ADD(_tag, VDC8563, 0) \
54   MCFG_DEVICE_CONFIG(_interface)
55
56
57/*----------- defined in video/vdc8563.c -----------*/
58
59void vdc8563_set_rastering(device_t *device, int on);
60UINT32 vdc8563_video_update(device_t *device, bitmap_ind16 &bitmap, const rectangle &cliprect);
61
62DECLARE_WRITE8_DEVICE_HANDLER( vdc8563_port_w );
63DECLARE_READ8_DEVICE_HANDLER( vdc8563_port_r );
64
65
66#endif /* __VDC8563_H__ */
trunk/src/mess/video/vic6567.c
r19392r19393
1/***************************************************************************
2
3    Video Interface Chip (6567R8 for NTSC system and 6569 for PAL system)
4
5    original emulation by PeT (mess@utanet.at)
6
7    A part of the code (cycle routine and drawing routines) is a modified version of the vic ii emulation used in
8    commodore 64 emulator "frodo" by Christian Bauer
9
10    http://frodo.cebix.net/
11    The rights on the source code remain at the author.
12    It may not - not even in parts - used for commercial purposes without explicit written permission by the author.
13    Permission to use it for non-commercial purposes is hereby granted als long as my copyright notice remains in the program.
14    You are not allowed to use the source to create and distribute a modified version of Frodo.
15
16    2010-02: converted to be a device and split vic III emulation (which still uses old cycle & drawing routines)
17
18    TODO:
19      - plenty of cleanups
20      - emulate variants of the vic chip
21      - update vic III to use new code for the vic II compatibility
22
23***************************************************************************/
24/* mos videochips
25  vic (6560 NTSC, 6561 PAL)
26  used in commodore vic20
27
28  vic II
29   6566 NTSC
30    no dram refresh?
31   6567 NTSC
32   6569 PAL-B
33   6572 PAL-N
34   6573 PAL-M
35   8562 NTSC
36   8565 PAL
37  used in commodore c64
38  complete different to vic
39
40  ted
41   7360/8360 (NTSC-M, PAL-B by same chip ?)
42   8365 PAL-N
43   8366 PAL-M
44  used in c16 c116 c232 c264 plus4 c364
45  based on the vic II
46  but no sprites and not register compatible
47  includes timers, input port, sound generators
48  memory interface, dram refresh, clock generation
49
50  vic IIe
51   8564 NTSC-M
52   8566 PAL-B
53   8569 PAL-N
54  used in commodore c128
55  vic II with some additional features
56   3 programmable output pins k0 k1 k2
57
58  vic III
59   4567
60  used in commodore c65 prototype
61  vic II compatible (mode only?)
62  several additional features
63   different resolutions, more colors, ...
64   (maybe like in the amiga graphic chip docu)
65
66  vdc
67   8563
68   8568 (composite video and composite sync)
69  second graphic chip in c128
70  complete different to above chips
71*/
72
73
74#include "emu.h"
75#include "video/vic6567.h"
76
77struct vic2_state
78{
79   vic2_type  type;
80
81   screen_device *screen;         // screen which sets bitmap properties
82   cpu_device *cpu;
83
84   UINT8 rdy_cycles;
85   UINT8 reg[0x80];
86
87   int on;                        /* rastering of the screen */
88
89   UINT16 chargenaddr, videoaddr, bitmapaddr;
90
91   bitmap_ind16 *bitmap;
92
93   UINT16 colors[4], spritemulti[4];
94
95   int rasterline;
96   UINT64 cycles_counter;
97   UINT8 cycle;
98   UINT16 raster_x;
99   UINT16 graphic_x;
100
101   /* convert multicolor byte to background/foreground for sprite collision */
102   UINT16 expandx[256];
103   UINT16 expandx_multi[256];
104
105   /* Display */
106   UINT16 dy_start;
107   UINT16 dy_stop;
108
109   /* GFX */
110   UINT8 draw_this_line;
111   UINT8 is_bad_line;
112   UINT8 bad_lines_enabled;
113   UINT8 display_state;
114   UINT8 char_data;
115   UINT8 gfx_data;
116   UINT8 color_data;
117   UINT8 last_char_data;
118   UINT8 matrix_line[40];                  // Buffer for video line, read in Bad Lines
119   UINT8 color_line[40];                  // Buffer for color line, read in Bad Lines
120   UINT8 vblanking;
121   UINT16 ml_index;
122   UINT8 rc;
123   UINT16 vc;
124   UINT16 vc_base;
125   UINT8 ref_cnt;
126
127   /* Sprites */
128   UINT8 spr_coll_buf[0x400];               // Buffer for sprite-sprite collisions and priorities
129   UINT8 fore_coll_buf[0x400];               // Buffer for foreground-sprite collisions and priorities
130   UINT8 spr_draw_data[8][4];               // Sprite data for drawing
131   UINT8 spr_exp_y;
132   UINT8 spr_dma_on;
133   UINT8 spr_draw;
134   UINT8 spr_disp_on;
135   UINT16 spr_ptr[8];
136   UINT8 spr_data[8][4];
137   UINT16 mc_base[8];                  // Sprite data counter bases
138   UINT16 mc[8];                     // Sprite data counters
139
140   /* Border */
141   UINT8 border_on;
142   UINT8 ud_border_on;
143   UINT8 border_on_sample[5];
144   UINT8 border_color_sample[0x400 / 8];         // Samples of border color at each "displayed" cycle
145
146   /* Cycles */
147   UINT64 first_ba_cycle;
148   UINT8 device_suspended;
149
150   /* DMA */
151   devcb_resolved_read8          in_dma_read_func;
152   devcb_resolved_read8    in_dma_read_color_func;
153
154   /* IRQ */
155   devcb_resolved_write_line               out_interrupt_func;
156
157   /* RDY */
158   devcb_resolved_read8      in_rdy_workaround_func;
159
160   /* lightpen */
161   devcb_resolved_read8 in_lightpen_button_func;
162   devcb_resolved_read8 in_lightpen_x_func;
163   devcb_resolved_read8 in_lightpen_y_func;
164};
165
166
167/*****************************************************************************
168    CONSTANTS
169*****************************************************************************/
170
171#define VERBOSE_LEVEL 0
172#define DBG_LOG(N,M,A) \
173   do { \
174      if(VERBOSE_LEVEL >= N) \
175      { \
176         if( M ) \
177            logerror("%11.6f: %-24s", machine.time().as_double(), (char*) M ); \
178         logerror A; \
179      } \
180   } while (0)
181
182#define ROW25_YSTART      0x33
183#define ROW25_YSTOP       0xfb
184#define ROW24_YSTART      0x37
185#define ROW24_YSTOP       0xf7
186
187#define RASTERLINE_2_C64(a)      (a)
188#define C64_2_RASTERLINE(a)      (a)
189#define XPOS            (VIC2_STARTVISIBLECOLUMNS + (VIC2_VISIBLECOLUMNS - VIC2_HSIZE) / 2)
190#define YPOS            (VIC2_STARTVISIBLELINES /* + (VIC2_VISIBLELINES - VIC2_VSIZE) / 2 */)
191#define FIRSTCOLUMN         50
192
193/* 2008-05 FP: lightpen code needs to read input port from c64.c and cbmb.c */
194
195#define LIGHTPEN_BUTTON      (vic2->in_lightpen_button_func(0))
196#define LIGHTPEN_X_VALUE   (vic2->in_lightpen_x_func(0))
197#define LIGHTPEN_Y_VALUE   (vic2->in_lightpen_y_func(0))
198
199/* lightpen delivers values from internal counters; they do not start with the visual area or frame area */
200#define VIC2_MAME_XPOS         0
201#define VIC2_MAME_YPOS         0
202#define VIC6567_X_BEGIN         38
203#define VIC6567_Y_BEGIN         -6            /* first 6 lines after retrace not for lightpen! */
204#define VIC6569_X_BEGIN         38
205#define VIC6569_Y_BEGIN         -6
206#define VIC2_X_BEGIN         ((vic2->type == VIC6569 || vic2->type == VIC8566) ? VIC6569_X_BEGIN : VIC6567_X_BEGIN)
207#define VIC2_Y_BEGIN         ((vic2->type == VIC6569 || vic2->type == VIC8566) ? VIC6569_Y_BEGIN : VIC6567_Y_BEGIN)
208#define VIC2_X_VALUE         ((LIGHTPEN_X_VALUE / 1.3) + 12)
209#define VIC2_Y_VALUE         ((LIGHTPEN_Y_VALUE      ) + 10)
210
211#define VIC2E_K0_LEVEL         (vic2->reg[0x2f] & 0x01)
212#define VIC2E_K1_LEVEL         (vic2->reg[0x2f] & 0x02)
213#define VIC2E_K2_LEVEL         (vic2->reg[0x2f] & 0x04)
214
215
216/* sprites 0 .. 7 */
217#define SPRITEON(nr)         (vic2->reg[0x15] & (1 << nr))
218#define SPRITE_Y_EXPAND(nr)      (vic2->reg[0x17] & (1 << nr))
219#define SPRITE_Y_SIZE(nr)      (SPRITE_Y_EXPAND(nr) ? 2 * 21 : 21)
220#define SPRITE_X_EXPAND(nr)      (vic2->reg[0x1d] & (1 << nr))
221#define SPRITE_X_SIZE(nr)      (SPRITE_X_EXPAND(nr) ? 2 * 24 : 24)
222#define SPRITE_X_POS(nr)      (vic2->reg[(nr) * 2] | (vic2->reg[0x10] & (1 << (nr)) ? 0x100 : 0))
223#define SPRITE_Y_POS(nr)      (vic2->reg[1 + 2 * (nr)])
224#define SPRITE_MULTICOLOR(nr)      (vic2->reg[0x1c] & (1 << nr))
225#define SPRITE_PRIORITY(nr)      (vic2->reg[0x1b] & (1 << nr))
226#define SPRITE_MULTICOLOR1      (vic2->reg[0x25] & 0x0f)
227#define SPRITE_MULTICOLOR2      (vic2->reg[0x26] & 0x0f)
228#define SPRITE_COLOR(nr)      (vic2->reg[0x27+nr] & 0x0f)
229#define SPRITE_ADDR(nr)         (vic2->videoaddr | 0x3f8 | nr)
230#define SPRITE_COLL         (vic2->reg[0x1e])
231#define SPRITE_BG_COLL         (vic2->reg[0x1f])
232
233#define GFXMODE            ((vic2->reg[0x11] & 0x60) | (vic2->reg[0x16] & 0x10)) >> 4
234#define SCREENON            (vic2->reg[0x11] & 0x10)
235#define VERTICALPOS         (vic2->reg[0x11] & 0x07)
236#define HORIZONTALPOS         (vic2->reg[0x16] & 0x07)
237#define ECMON            (vic2->reg[0x11] & 0x40)
238#define HIRESON            (vic2->reg[0x11] & 0x20)
239#define COLUMNS40            (vic2->reg[0x16] & 0x08)         /* else 38 Columns */
240
241#define VIDEOADDR            ((vic2->reg[0x18] & 0xf0) << (10 - 4))
242#define CHARGENADDR         ((vic2->reg[0x18] & 0x0e) << 10)
243#define BITMAPADDR         ((data & 0x08) << 10)
244
245#define RASTERLINE         (((vic2->reg[0x11] & 0x80) << 1) | vic2->reg[0x12])
246
247#define FRAMECOLOR         (vic2->reg[0x20] & 0x0f)
248#define BACKGROUNDCOLOR         (vic2->reg[0x21] & 0x0f)
249#define MULTICOLOR1         (vic2->reg[0x22] & 0x0f)
250#define MULTICOLOR2         (vic2->reg[0x23] & 0x0f)
251#define FOREGROUNDCOLOR         (vic2->reg[0x24] & 0x0f)
252
253#define VIC2_LINES      ((vic2->type == VIC6569 || vic2->type == VIC8566) ? VIC6569_LINES : VIC6567_LINES)
254#define VIC2_FIRST_DMA_LINE   ((vic2->type == VIC6569 || vic2->type == VIC8566) ? VIC6569_FIRST_DMA_LINE : VIC6567_FIRST_DMA_LINE)
255#define VIC2_LAST_DMA_LINE   ((vic2->type == VIC6569 || vic2->type == VIC8566) ? VIC6569_LAST_DMA_LINE : VIC6567_LAST_DMA_LINE)
256#define VIC2_FIRST_DISP_LINE   ((vic2->type == VIC6569 || vic2->type == VIC8566) ? VIC6569_FIRST_DISP_LINE : VIC6567_FIRST_DISP_LINE)
257#define VIC2_LAST_DISP_LINE   ((vic2->type == VIC6569 || vic2->type == VIC8566) ? VIC6569_LAST_DISP_LINE : VIC6567_LAST_DISP_LINE)
258#define VIC2_RASTER_2_EMU(a)   ((vic2->type == VIC6569 || vic2->type == VIC8566) ? VIC6569_RASTER_2_EMU(a) : VIC6567_RASTER_2_EMU(a))
259#define VIC2_FIRSTCOLUMN   ((vic2->type == VIC6569 || vic2->type == VIC8566) ? VIC6569_FIRSTCOLUMN : VIC6567_FIRSTCOLUMN)
260#define VIC2_X_2_EMU(a)      ((vic2->type == VIC6569 || vic2->type == VIC8566) ? VIC6569_X_2_EMU(a) : VIC6567_X_2_EMU(a))
261
262/*****************************************************************************
263    INLINE FUNCTIONS
264*****************************************************************************/
265
266INLINE vic2_state *get_safe_token( device_t *device )
267{
268   assert(device != NULL);
269   assert(device->type() == VIC2);
270
271   return (vic2_state *)downcast<vic2_device *>(device)->token();
272}
273
274INLINE const vic2_interface *get_interface( device_t *device )
275{
276   assert(device != NULL);
277   assert((device->type() == VIC2));
278   return (const vic2_interface *) device->static_config();
279}
280
281/*****************************************************************************
282    IMPLEMENTATION
283*****************************************************************************/
284
285static void vic2_set_interrupt( running_machine &machine, int mask, vic2_state *vic2 )
286{
287   if (((vic2->reg[0x19] ^ mask) & vic2->reg[0x1a] & 0xf))
288   {
289      if (!(vic2->reg[0x19] & 0x80))
290      {
291         DBG_LOG(2, "vic2", ("irq start %.2x\n", mask));
292         vic2->reg[0x19] |= 0x80;
293         vic2->out_interrupt_func(1);
294      }
295   }
296   vic2->reg[0x19] |= mask;
297}
298
299static void vic2_clear_interrupt( running_machine &machine, int mask, vic2_state *vic2 )
300{
301   vic2->reg[0x19] &= ~mask;
302   if ((vic2->reg[0x19] & 0x80) && !(vic2->reg[0x19] & vic2->reg[0x1a] & 0xf))
303   {
304      DBG_LOG(2, "vic2", ("irq end %.2x\n", mask));
305      vic2->reg[0x19] &= ~0x80;
306      vic2->out_interrupt_func(0);
307   }
308}
309
310void vic2_lightpen_write( device_t *device, int level )
311{
312   /* calculate current position, write it and raise interrupt */
313}
314
315static TIMER_CALLBACK( vic2_timer_timeout )
316{
317   vic2_state *vic2 = (vic2_state *)ptr;
318   int which = param;
319
320   DBG_LOG(3, "vic2 ", ("timer %d timeout\n", which));
321
322   switch (which)
323   {
324      case 1:                     /* light pen */
325         /* and diode must recognize light */
326         if (1)
327         {
328            vic2->reg[0x13] = VIC2_X_VALUE;
329            vic2->reg[0x14] = VIC2_Y_VALUE;
330         }
331         vic2_set_interrupt(machine, 8, vic2);
332         break;
333   }
334}
335
336
337// modified VIC II emulation by Christian Bauer starts here...
338
339// Idle access
340INLINE void vic2_idle_access( running_machine &machine, vic2_state *vic2 )
341{
342   vic2->in_dma_read_func(0x3fff);
343}
344
345// Fetch sprite data pointer
346INLINE void vic2_spr_ptr_access( running_machine &machine, vic2_state *vic2, int num )
347{
348   vic2->spr_ptr[num] = vic2->in_dma_read_func(SPRITE_ADDR(num)) << 6;
349}
350
351// Fetch sprite data, increment data counter
352INLINE void vic2_spr_data_access( running_machine &machine, vic2_state *vic2, int num, int bytenum )
353{
354   if (vic2->spr_dma_on & (1 << num))
355   {
356      vic2->spr_data[num][bytenum] = vic2->in_dma_read_func((vic2->mc[num] & 0x3f) | vic2->spr_ptr[num]);
357      vic2->mc[num]++;
358   }
359   else
360      if (bytenum == 1)
361         vic2_idle_access(machine, vic2);
362}
363
364// Turn on display if Bad Line
365INLINE void vic2_display_if_bad_line( vic2_state *vic2 )
366{
367   if (vic2->is_bad_line)
368      vic2->display_state = 1;
369}
370
371// Suspend CPU
372INLINE void vic2_suspend_cpu( running_machine &machine, vic2_state *vic2 )
373{
374   if (vic2->device_suspended == 0)
375   {
376      vic2->first_ba_cycle = vic2->cycles_counter;
377      if (vic2->in_rdy_workaround_func(0) != 7 )
378      {
379//          machine.firstcpu->suspend(SUSPEND_REASON_SPIN, 0);
380      }
381      vic2->device_suspended = 1;
382   }
383}
384
385// Resume CPU
386INLINE void vic2_resume_cpu( running_machine &machine, vic2_state *vic2 )
387{
388   if (vic2->device_suspended == 1)
389   {
390   //  machine.firstcpu->resume(SUSPEND_REASON_SPIN);
391      vic2->device_suspended = 0;
392   }
393}
394
395// Refresh access
396INLINE void vic2_refresh_access( running_machine &machine, vic2_state *vic2 )
397{
398   vic2->in_dma_read_func(0x3f00 | vic2->ref_cnt--);
399}
400
401
402INLINE void vic2_fetch_if_bad_line( vic2_state *vic2 )
403{
404   if (vic2->is_bad_line)
405      vic2->display_state = 1;
406}
407
408
409// Turn on display and matrix access and reset RC if Bad Line
410INLINE void vic2_rc_if_bad_line( vic2_state *vic2 )
411{
412   if (vic2->is_bad_line)
413   {
414      vic2->display_state = 1;
415      vic2->rc = 0;
416   }
417}
418
419// Sample border color and increment vic2->graphic_x
420INLINE void vic2_sample_border( vic2_state *vic2 )
421{
422   if (vic2->draw_this_line)
423   {
424      if (vic2->border_on)
425         vic2->border_color_sample[vic2->cycle - 13] = FRAMECOLOR;
426      vic2->graphic_x += 8;
427   }
428}
429
430
431// Turn on sprite DMA if necessary
432INLINE void vic2_check_sprite_dma( vic2_state *vic2 )
433{
434   int i;
435   UINT8 mask = 1;
436
437   for (i = 0; i < 8; i++, mask <<= 1)
438      if (SPRITEON(i) && ((vic2->rasterline & 0xff) == SPRITE_Y_POS(i)))
439      {
440         vic2->spr_dma_on |= mask;
441         vic2->mc_base[i] = 0;
442         if (SPRITE_Y_EXPAND(i))
443            vic2->spr_exp_y &= ~mask;
444      }
445}
446
447// Video matrix access
448INLINE void vic2_matrix_access( running_machine &machine, vic2_state *vic2 )
449{
450//  if (vic2->device_suspended == 1)
451   {
452      if (vic2->cycles_counter < vic2->first_ba_cycle)
453         vic2->matrix_line[vic2->ml_index] = vic2->color_line[vic2->ml_index] = 0xff;
454      else
455      {
456         UINT16 adr = (vic2->vc & 0x03ff) | VIDEOADDR;
457         vic2->matrix_line[vic2->ml_index] = vic2->in_dma_read_func(adr); \
458         vic2->color_line[vic2->ml_index] = vic2->in_dma_read_color_func((adr & 0x03ff)); \
459      }
460   }
461}
462
463// Graphics data access
464INLINE void vic2_graphics_access( running_machine &machine, vic2_state *vic2 )
465{
466   if (vic2->display_state == 1)
467   {
468      UINT16 adr;
469      if (HIRESON)
470         adr = ((vic2->vc & 0x03ff) << 3) | vic2->bitmapaddr | vic2->rc;
471      else
472         adr = (vic2->matrix_line[vic2->ml_index] << 3) | vic2->chargenaddr | vic2->rc;
473      if (ECMON)
474         adr &= 0xf9ff;
475      vic2->gfx_data = vic2->in_dma_read_func(adr);
476      vic2->char_data = vic2->matrix_line[vic2->ml_index];
477      vic2->color_data = vic2->color_line[vic2->ml_index];
478      vic2->ml_index++;
479      vic2->vc++;
480   }
481   else
482   {
483      vic2->gfx_data = vic2->in_dma_read_func((ECMON ? 0x39ff : 0x3fff));
484      vic2->char_data = 0;
485   }
486}
487
488INLINE void vic2_draw_background( vic2_state *vic2 )
489{
490   if (vic2->draw_this_line)
491   {
492      UINT8 c;
493
494      switch (GFXMODE)
495      {
496         case 0:
497         case 1:
498         case 3:
499            c = vic2->colors[0];
500            break;
501         case 2:
502            c = vic2->last_char_data & 0x0f;
503            break;
504         case 4:
505            if (vic2->last_char_data & 0x80)
506               if (vic2->last_char_data & 0x40)
507                  c = vic2->colors[3];
508               else
509                  c = vic2->colors[2];
510            else
511               if (vic2->last_char_data & 0x40)
512                  c = vic2->colors[1];
513               else
514                  c = vic2->colors[0];
515            break;
516         default:
517            c = 0;
518            break;
519      }
520      vic2->bitmap->plot_box(vic2->graphic_x, VIC2_RASTER_2_EMU(vic2->rasterline), 8, 1, c);
521   }
522}
523
524INLINE void vic2_draw_mono( vic2_state *vic2, UINT16 p, UINT8 c0, UINT8 c1 )
525{
526   UINT8 c[2];
527   UINT8 data = vic2->gfx_data;
528
529   c[0] = c0;
530   c[1] = c1;
531
532   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 7) = c[data & 1];
533   vic2->fore_coll_buf[p + 7] = data & 1; data >>= 1;
534   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 6) = c[data & 1];
535   vic2->fore_coll_buf[p + 6] = data & 1; data >>= 1;
536   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 5) = c[data & 1];
537   vic2->fore_coll_buf[p + 5] = data & 1; data >>= 1;
538   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 4) = c[data & 1];
539   vic2->fore_coll_buf[p + 4] = data & 1; data >>= 1;
540   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 3) = c[data & 1];
541   vic2->fore_coll_buf[p + 3] = data & 1; data >>= 1;
542   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 2) = c[data & 1];
543   vic2->fore_coll_buf[p + 2] = data & 1; data >>= 1;
544   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 1) = c[data & 1];
545   vic2->fore_coll_buf[p + 1] = data & 1; data >>= 1;
546   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 0) = c[data];
547   vic2->fore_coll_buf[p + 0] = data & 1;
548}
549
550INLINE void vic2_draw_multi( vic2_state *vic2, UINT16 p, UINT8 c0, UINT8 c1, UINT8 c2, UINT8 c3 )
551{
552   UINT8 c[4];
553   UINT8 data = vic2->gfx_data;
554
555   c[0] = c0;
556   c[1] = c1;
557   c[2] = c2;
558   c[3] = c3;
559
560   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 7) = c[data & 3];
561   vic2->fore_coll_buf[p + 7] = data & 2;
562   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 6) = c[data & 3];
563   vic2->fore_coll_buf[p + 6] = data & 2; data >>= 2;
564   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 5) = c[data & 3];
565   vic2->fore_coll_buf[p + 5] = data & 2;
566   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 4) = c[data & 3];
567   vic2->fore_coll_buf[p + 4] = data & 2; data >>= 2;
568   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 3) = c[data & 3];
569   vic2->fore_coll_buf[p + 3] = data & 2;
570   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 2) = c[data & 3];
571   vic2->fore_coll_buf[p + 2] = data & 2; data >>= 2;
572   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 1) = c[data];
573   vic2->fore_coll_buf[p + 1] = data & 2;
574   vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 0) = c[data];
575   vic2->fore_coll_buf[p + 0] = data & 2;
576}
577
578// Graphics display (8 pixels)
579static void vic2_draw_graphics( vic2_state *vic2 )
580{
581   if (vic2->draw_this_line == 0)
582   {
583      UINT16 p = vic2->graphic_x + HORIZONTALPOS;
584      vic2->fore_coll_buf[p + 7] = 0;
585      vic2->fore_coll_buf[p + 6] = 0;
586      vic2->fore_coll_buf[p + 5] = 0;
587      vic2->fore_coll_buf[p + 4] = 0;
588      vic2->fore_coll_buf[p + 3] = 0;
589      vic2->fore_coll_buf[p + 2] = 0;
590      vic2->fore_coll_buf[p + 1] = 0;
591      vic2->fore_coll_buf[p + 0] = 0;
592   }
593   else if (vic2->ud_border_on)
594   {
595      UINT16 p = vic2->graphic_x + HORIZONTALPOS;
596      vic2->fore_coll_buf[p + 7] = 0;
597      vic2->fore_coll_buf[p + 6] = 0;
598      vic2->fore_coll_buf[p + 5] = 0;
599      vic2->fore_coll_buf[p + 4] = 0;
600      vic2->fore_coll_buf[p + 3] = 0;
601      vic2->fore_coll_buf[p + 2] = 0;
602      vic2->fore_coll_buf[p + 1] = 0;
603      vic2->fore_coll_buf[p + 0] = 0;
604      vic2_draw_background(vic2);
605   }
606   else
607   {
608      UINT8 tmp_col;
609      UINT16 p = vic2->graphic_x + HORIZONTALPOS;
610      switch (GFXMODE)
611      {
612         case 0:
613            vic2_draw_mono(vic2, p, vic2->colors[0], vic2->color_data & 0x0f);
614            break;
615         case 1:
616            if (vic2->color_data & 0x08)
617               vic2_draw_multi(vic2, p, vic2->colors[0], vic2->colors[1], vic2->colors[2], vic2->color_data & 0x07);
618            else
619               vic2_draw_mono(vic2, p, vic2->colors[0], vic2->color_data & 0x0f);
620            break;
621         case 2:
622            vic2_draw_mono(vic2, p, vic2->char_data & 0x0f, vic2->char_data >> 4);
623            break;
624         case 3:
625            vic2_draw_multi(vic2, p, vic2->colors[0], vic2->char_data >> 4, vic2->char_data & 0x0f, vic2->color_data & 0x0f);
626            break;
627         case 4:
628            if (vic2->char_data & 0x80)
629               if (vic2->char_data & 0x40)
630                  tmp_col = vic2->colors[3];
631               else
632                  tmp_col = vic2->colors[2];
633            else
634               if (vic2->char_data & 0x40)
635                  tmp_col = vic2->colors[1];
636               else
637                  tmp_col = vic2->colors[0];
638            vic2_draw_mono(vic2, p, tmp_col, vic2->color_data & 0x0f);
639            break;
640         case 5:
641            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 7) = 0;
642            vic2->fore_coll_buf[p + 7] = 0;
643            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 6) = 0;
644            vic2->fore_coll_buf[p + 6] = 0;
645            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 5) = 0;
646            vic2->fore_coll_buf[p + 5] = 0;
647            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 4) = 0;
648            vic2->fore_coll_buf[p + 4] = 0;
649            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 3) = 0;
650            vic2->fore_coll_buf[p + 3] = 0;
651            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 2) = 0;
652            vic2->fore_coll_buf[p + 2] = 0;
653            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 1) = 0;
654            vic2->fore_coll_buf[p + 1] = 0;
655            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 0) = 0;
656            vic2->fore_coll_buf[p + 0] = 0;
657            break;
658         case 6:
659            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 7) = 0;
660            vic2->fore_coll_buf[p + 7] = 0;
661            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 6) = 0;
662            vic2->fore_coll_buf[p + 6] = 0;
663            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 5) = 0;
664            vic2->fore_coll_buf[p + 5] = 0;
665            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 4) = 0;
666            vic2->fore_coll_buf[p + 4] = 0;
667            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 3) = 0;
668            vic2->fore_coll_buf[p + 3] = 0;
669            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 2) = 0;
670            vic2->fore_coll_buf[p + 2] = 0;
671            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 1) = 0;
672            vic2->fore_coll_buf[p + 1] = 0;
673            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 0) = 0;
674            vic2->fore_coll_buf[p + 0] = 0;
675            break;
676         case 7:
677            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 7) = 0;
678            vic2->fore_coll_buf[p + 7] = 0;
679            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 6) = 0;
680            vic2->fore_coll_buf[p + 6] = 0;
681            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 5) = 0;
682            vic2->fore_coll_buf[p + 5] = 0;
683            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 4) = 0;
684            vic2->fore_coll_buf[p + 4] = 0;
685            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 3) = 0;
686            vic2->fore_coll_buf[p + 3] = 0;
687            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 2) = 0;
688            vic2->fore_coll_buf[p + 2] = 0;
689            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 1) = 0;
690            vic2->fore_coll_buf[p + 1] = 0;
691            vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + 0) = 0;
692            vic2->fore_coll_buf[p + 0] = 0;
693            break;
694      }
695   }
696}
697
698static void vic2_draw_sprites( running_machine &machine, vic2_state *vic2 )
699{
700   int i;
701   UINT8 snum, sbit;
702   UINT8 spr_coll = 0, gfx_coll = 0;
703   UINT32 plane0_l, plane0_r, plane1_l, plane1_r;
704   UINT32 sdata_l = 0, sdata_r = 0;
705
706   for (i = 0; i < 0x400; i++)
707      vic2->spr_coll_buf[i] = 0;
708
709   for (snum = 0, sbit = 1; snum < 8; snum++, sbit <<= 1)
710   {
711      if ((vic2->spr_draw & sbit) && (SPRITE_X_POS(snum) <= (403 - (VIC2_FIRSTCOLUMN + 1))))
712      {
713         UINT16 p = SPRITE_X_POS(snum) + VIC2_X_2_EMU(0) + 8;
714         UINT8 color = SPRITE_COLOR(snum);
715         UINT32 sdata = (vic2->spr_draw_data[snum][0] << 24) | (vic2->spr_draw_data[snum][1] << 16) | (vic2->spr_draw_data[snum][2] << 8);
716
717         if (SPRITE_X_EXPAND(snum))
718         {
719            if (SPRITE_X_POS(snum) > (403 - 24 - (VIC2_FIRSTCOLUMN + 1)))
720               continue;
721
722            if (SPRITE_MULTICOLOR(snum))
723            {
724               sdata_l = (vic2->expandx_multi[(sdata >> 24) & 0xff] << 16) | vic2->expandx_multi[(sdata >> 16) & 0xff];
725               sdata_r = vic2->expandx_multi[(sdata >> 8) & 0xff] << 16;
726               plane0_l = (sdata_l & 0x55555555) | (sdata_l & 0x55555555) << 1;
727               plane1_l = (sdata_l & 0xaaaaaaaa) | (sdata_l & 0xaaaaaaaa) >> 1;
728               plane0_r = (sdata_r & 0x55555555) | (sdata_r & 0x55555555) << 1;
729               plane1_r = (sdata_r & 0xaaaaaaaa) | (sdata_r & 0xaaaaaaaa) >> 1;
730               for (i = 0; i < 32; i++, plane0_l <<= 1, plane1_l <<= 1)
731               {
732                  UINT8 col;
733
734                  if (plane1_l & 0x80000000)
735                  {
736                     if (vic2->fore_coll_buf[p + i])
737                     {
738                        gfx_coll |= sbit;
739                     }
740                     if (plane0_l & 0x80000000)
741                        col = vic2->spritemulti[3];
742                     else
743                        col = color;
744                  }
745                  else
746                  {
747                     if (plane0_l & 0x80000000)
748                     {
749                        if (vic2->fore_coll_buf[p + i])
750                        {
751                           gfx_coll |= sbit;
752                        }
753                        col = vic2->spritemulti[1];
754                     }
755                     else
756                        continue;
757                  }
758
759                  if (vic2->spr_coll_buf[p + i])
760                     spr_coll |= vic2->spr_coll_buf[p + i] | sbit;
761                  else
762                  {
763                     if (SPRITE_PRIORITY(snum))
764                     {
765                        if (vic2->fore_coll_buf[p + i] == 0)
766                           vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + i) = col;
767                        vic2->spr_coll_buf[p + i] = sbit;
768                     }
769                     else
770                     {
771                        vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + i) = col;
772                        vic2->spr_coll_buf[p + i] = sbit;
773                     }
774                  }
775               }
776
777               for (; i < 48; i++, plane0_r <<= 1, plane1_r <<= 1)
778               {
779                  UINT8 col;
780
781                  if(plane1_r & 0x80000000)
782                  {
783                     if (vic2->fore_coll_buf[p + i])
784                     {
785                        gfx_coll |= sbit;
786                     }
787
788                     if (plane0_r & 0x80000000)
789                        col = vic2->spritemulti[3];
790                     else
791                        col = color;
792                  }
793                  else
794                  {
795                     if (plane0_r & 0x80000000)
796                     {
797                        if (vic2->fore_coll_buf[p + i])
798                        {
799                           gfx_coll |= sbit;
800                        }
801                        col =  vic2->spritemulti[1];
802                     }
803                     else
804                        continue;
805                  }
806
807                  if (vic2->spr_coll_buf[p + i])
808                     spr_coll |= vic2->spr_coll_buf[p + i] | sbit;
809                  else
810                  {
811                     if (SPRITE_PRIORITY(snum))
812                     {
813                        if (vic2->fore_coll_buf[p + i] == 0)
814                           vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + i) = col;
815                        vic2->spr_coll_buf[p + i] = sbit;
816                     }
817                     else
818                     {
819                        vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + i) = col;
820                        vic2->spr_coll_buf[p + i] = sbit;
821                     }
822                  }
823               }
824            }
825            else
826            {
827               sdata_l = (vic2->expandx[(sdata >> 24) & 0xff] << 16) | vic2->expandx[(sdata >> 16) & 0xff];
828               sdata_r = vic2->expandx[(sdata >> 8) & 0xff] << 16;
829
830               for (i = 0; i < 32; i++, sdata_l <<= 1)
831                  if (sdata_l & 0x80000000)
832                  {
833                     if (vic2->fore_coll_buf[p + i])
834                     {
835                        gfx_coll |= sbit;
836                     }
837
838                     if (vic2->spr_coll_buf[p + i])
839                        spr_coll |= vic2->spr_coll_buf[p + i] | sbit;
840                     else
841                     {
842                        if (SPRITE_PRIORITY(snum))
843                        {
844                           if (vic2->fore_coll_buf[p + i] == 0)
845                              vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + i) = color;
846                           vic2->spr_coll_buf[p + i] = sbit;
847                        }
848                        else
849                        {
850                           vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + i) = color;
851                           vic2->spr_coll_buf[p + i] = sbit;
852                        }
853                     }
854                  }
855
856               for (; i < 48; i++, sdata_r <<= 1)
857                  if (sdata_r & 0x80000000)
858                  {
859                     if (vic2->fore_coll_buf[p + i])
860                     {
861                        gfx_coll |= sbit;
862                     }
863
864                     if (vic2->spr_coll_buf[p + i])
865                        spr_coll |= vic2->spr_coll_buf[p + i] | sbit;
866                     else
867                     {
868                        if (SPRITE_PRIORITY(snum))
869                        {
870                           if (vic2->fore_coll_buf[p + i] == 0)
871                              vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + i) = color;
872                           vic2->spr_coll_buf[p + i] = sbit;
873                        }
874                        else
875                        {
876                           vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + i) = color;
877                           vic2->spr_coll_buf[p + i] = sbit;
878                        }
879                     }
880                  }
881            }
882         }
883         else
884         {
885            if (SPRITE_MULTICOLOR(snum))
886            {
887               UINT32 plane0 = (sdata & 0x55555555) | (sdata & 0x55555555) << 1;
888               UINT32 plane1 = (sdata & 0xaaaaaaaa) | (sdata & 0xaaaaaaaa) >> 1;
889
890               for (i = 0; i < 24; i++, plane0 <<= 1, plane1 <<= 1)
891               {
892                  UINT8 col;
893
894                  if (plane1 & 0x80000000)
895                  {
896                     if (vic2->fore_coll_buf[p + i])
897                     {
898                        gfx_coll |= sbit;
899                     }
900
901                     if (plane0 & 0x80000000)
902                        col = vic2->spritemulti[3];
903                     else
904                        col = color;
905                  }
906                  else
907                  {
908                     if (vic2->fore_coll_buf[p + i])
909                     {
910                        gfx_coll |= sbit;
911                     }
912
913                     if (plane0 & 0x80000000)
914                        col = vic2->spritemulti[1];
915                     else
916                        continue;
917                  }
918
919                  if (vic2->spr_coll_buf[p + i])
920                     spr_coll |= vic2->spr_coll_buf[p + i] | sbit;
921                  else
922                  {
923                     if (SPRITE_PRIORITY(snum))
924                     {
925                        if (vic2->fore_coll_buf[p + i] == 0)
926                           vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + i) = col;
927                        vic2->spr_coll_buf[p + i] = sbit;
928                     }
929                     else
930                     {
931                        vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + i) = col;
932                        vic2->spr_coll_buf[p + i] = sbit;
933                     }
934                  }
935               }
936            }
937            else
938            {
939               for (i = 0; i < 24; i++, sdata <<= 1)
940               {
941                  if (sdata & 0x80000000)
942                  {
943                     if (vic2->fore_coll_buf[p + i])
944                     {
945                        gfx_coll |= sbit;
946                     }
947                     if (vic2->spr_coll_buf[p + i])
948                     {
949                        spr_coll |= vic2->spr_coll_buf[p + i] | sbit;
950                     }
951                     else
952                     {
953                        if (SPRITE_PRIORITY(snum))
954                        {
955                           if (vic2->fore_coll_buf[p + i] == 0)
956                              vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + i) = color;
957                           vic2->spr_coll_buf[p + i] = sbit;
958                        }
959                        else
960                        {
961                           vic2->bitmap->pix16(VIC2_RASTER_2_EMU(vic2->rasterline), p + i) = color;
962                           vic2->spr_coll_buf[p + i] = sbit;
963                        }
964                     }
965                  }
966               }
967            }
968         }
969      }
970   }
971
972   if (SPRITE_COLL)
973      SPRITE_COLL |= spr_coll;
974   else
975   {
976      SPRITE_COLL = spr_coll;
977      if (SPRITE_COLL)
978         vic2_set_interrupt(machine, 4, vic2);
979   }
980
981   if (SPRITE_BG_COLL)
982      SPRITE_BG_COLL |= gfx_coll;
983   else
984   {
985      SPRITE_BG_COLL = gfx_coll;
986      if (SPRITE_BG_COLL)
987         vic2_set_interrupt(machine, 2, vic2);
988   }
989}
990
991
992static TIMER_CALLBACK( pal_timer_callback )
993{
994   vic2_state *vic2 = (vic2_state *)ptr;
995   int i;
996   UINT8 mask;
997   //static int adjust[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
998
999   UINT8 cpu_cycles = vic2->cpu->total_cycles() & 0xff;
1000   UINT8 vic_cycles = (vic2->cycles_counter + 1) & 0xff;
1001   vic2->cycles_counter++;
1002
1003//  printf("%02x %02x %02x\n",cpu_cycles,vic_cycles,vic2->rdy_cycles);
1004#if 0
1005if (machine.input().code_pressed(KEYCODE_X))
1006{
1007if (machine.input().code_pressed_once(KEYCODE_Q)) adjust[1]++;
1008if (machine.input().code_pressed_once(KEYCODE_W)) adjust[2]++;
1009if (machine.input().code_pressed_once(KEYCODE_E)) adjust[3]++;
1010if (machine.input().code_pressed_once(KEYCODE_R)) adjust[4]++;
1011if (machine.input().code_pressed_once(KEYCODE_T)) adjust[5]++;
1012if (machine.input().code_pressed_once(KEYCODE_Y)) adjust[6]++;
1013if (machine.input().code_pressed_once(KEYCODE_U)) adjust[7]++;
1014if (machine.input().code_pressed_once(KEYCODE_I)) adjust[8]++;
1015if (machine.input().code_pressed_once(KEYCODE_A)) adjust[1]--;
1016if (machine.input().code_pressed_once(KEYCODE_S)) adjust[2]--;
1017if (machine.input().code_pressed_once(KEYCODE_D)) adjust[3]--;
1018if (machine.input().code_pressed_once(KEYCODE_F)) adjust[4]--;
1019if (machine.input().code_pressed_once(KEYCODE_G)) adjust[5]--;
1020if (machine.input().code_pressed_once(KEYCODE_H)) adjust[6]--;
1021if (machine.input().code_pressed_once(KEYCODE_J)) adjust[7]--;
1022if (machine.input().code_pressed_once(KEYCODE_K)) adjust[8]--;
1023if (machine.input().code_pressed_once(KEYCODE_C)) adjust[0]++;
1024if (machine.input().code_pressed_once(KEYCODE_V)) adjust[0]--;
1025if (machine.input().code_pressed_once(KEYCODE_Z)) printf("b:%02x 1:%02x 2:%02x 3:%02x 4:%02x 5:%02x 6:%02x 7:%02x 8:%02x\n",
1026                                adjust[0],adjust[1],adjust[2],adjust[3],adjust[4],adjust[5],adjust[6],adjust[7],adjust[8]);
1027}
1028#define adjust(x) adjust[x]
1029#else
1030#define adjust(x) 0
1031#endif
1032
1033   switch(vic2->cycle)
1034   {
1035
1036   // Sprite 3, raster counter, raster IRQ, bad line
1037   case 1:
1038      if (vic2->rasterline == (VIC2_LINES - 1))
1039      {
1040         vic2->vblanking = 1;
1041
1042//          if (LIGHTPEN_BUTTON)
1043         {
1044            /* lightpen timer start */
1045            machine.scheduler().timer_set(attotime(0, 0), FUNC(vic2_timer_timeout), 1, vic2);
1046         }
1047      }
1048      else
1049      {
1050         vic2->rasterline++;
1051
1052         if (vic2->rasterline == VIC2_FIRST_DMA_LINE)
1053            vic2->bad_lines_enabled = SCREENON;
1054
1055         vic2->is_bad_line = ((vic2->rasterline >= VIC2_FIRST_DMA_LINE) && (vic2->rasterline <= VIC2_LAST_DMA_LINE) &&
1056                  ((vic2->rasterline & 0x07) == VERTICALPOS) && vic2->bad_lines_enabled);
1057
1058         vic2->draw_this_line =   ((VIC2_RASTER_2_EMU(vic2->rasterline) >= VIC2_RASTER_2_EMU(VIC2_FIRST_DISP_LINE)) &&
1059                  (VIC2_RASTER_2_EMU(vic2->rasterline ) <= VIC2_RASTER_2_EMU(VIC2_LAST_DISP_LINE)));
1060      }
1061
1062      vic2->border_on_sample[0] = vic2->border_on;
1063      vic2_spr_ptr_access(machine, vic2, 3);
1064      vic2_spr_data_access(machine, vic2, 3, 0);
1065      vic2_display_if_bad_line(vic2);
1066
1067      if (vic2->spr_dma_on & 0x08)
1068         vic2_suspend_cpu(machine, vic2);
1069      else
1070         vic2_resume_cpu(machine, vic2);
1071
1072      if (vic2->spr_dma_on & 0x08) vic2->rdy_cycles += (2 + adjust(1));
1073
1074      vic2->cycle++;
1075      break;
1076
1077   // Sprite 3
1078   case 2:
1079      if (vic2->vblanking)
1080      {
1081         // Vertical blank, reset counters
1082         vic2->rasterline = vic2->vc_base = 0;
1083         vic2->ref_cnt = 0xff;
1084         vic2->vblanking = 0;
1085
1086         // Trigger raster IRQ if IRQ in line 0
1087         if (RASTERLINE == 0)
1088         {
1089            vic2_set_interrupt(machine, 1, vic2);
1090         }
1091      }
1092
1093      if (vic2->rasterline == RASTERLINE)
1094      {
1095         vic2_set_interrupt(machine, 1, vic2);
1096      }
1097
1098      vic2->graphic_x = VIC2_X_2_EMU(0);
1099
1100      vic2_spr_data_access(machine, vic2, 3, 1);
1101      vic2_spr_data_access(machine, vic2, 3, 2);
1102      vic2_display_if_bad_line(vic2);
1103
1104      vic2->cycle++;
1105      break;
1106
1107   // Sprite 4
1108   case 3:
1109      vic2_spr_ptr_access(machine, vic2, 4);
1110      vic2_spr_data_access(machine, vic2, 4, 0);
1111      vic2_display_if_bad_line(vic2);
1112
1113      if (vic2->spr_dma_on & 0x10)
1114         vic2_suspend_cpu(machine, vic2);
1115      else
1116         vic2_resume_cpu(machine, vic2);
1117
1118      if (vic2->spr_dma_on & 0x10) vic2->rdy_cycles += (2 + adjust(2));
1119
1120      vic2->cycle++;
1121      break;
1122
1123   // Sprite 4
1124   case 4:
1125      vic2_spr_data_access(machine, vic2, 4, 1);
1126      vic2_spr_data_access(machine, vic2, 4, 2);
1127      vic2_display_if_bad_line(vic2);
1128
1129      vic2->cycle++;
1130      break;
1131
1132   // Sprite 5
1133   case 5:
1134      vic2_spr_ptr_access(machine, vic2, 5);
1135      vic2_spr_data_access(machine, vic2, 5, 0);
1136      vic2_display_if_bad_line(vic2);
1137
1138      if (vic2->spr_dma_on & 0x20)
1139         vic2_suspend_cpu(machine, vic2);
1140      else
1141         vic2_resume_cpu(machine, vic2);
1142
1143      if (vic2->spr_dma_on & 0x20) vic2->rdy_cycles += (2 + adjust(3));
1144
1145      vic2->cycle++;
1146      break;
1147
1148   // Sprite 5
1149   case 6:
1150      vic2_spr_data_access(machine, vic2, 5, 1);
1151      vic2_spr_data_access(machine, vic2, 5, 2);
1152      vic2_display_if_bad_line(vic2);
1153
1154      vic2->cycle++;
1155      break;
1156
1157   // Sprite 6
1158   case 7:
1159      vic2_spr_ptr_access(machine, vic2, 6);
1160      vic2_spr_data_access(machine, vic2, 6, 0);
1161      vic2_display_if_bad_line(vic2);
1162
1163      if (vic2->spr_dma_on & 0x40)
1164         vic2_suspend_cpu(machine, vic2);
1165      else
1166         vic2_resume_cpu(machine, vic2);
1167
1168      if (vic2->spr_dma_on & 0x40) vic2->rdy_cycles += (2 + adjust(4));
1169
1170      vic2->cycle++;
1171      break;
1172
1173   // Sprite 6
1174   case 8:
1175      vic2_spr_data_access(machine, vic2, 6, 1);
1176      vic2_spr_data_access(machine, vic2, 6, 2);
1177      vic2_display_if_bad_line(vic2);
1178
1179      vic2->cycle++;
1180      break;
1181
1182   // Sprite 7
1183   case 9:
1184      vic2_spr_ptr_access(machine, vic2, 7);
1185      vic2_spr_data_access(machine, vic2, 7, 0);
1186      vic2_display_if_bad_line(vic2);
1187
1188      if (vic2->spr_dma_on & 0x80)
1189         vic2_suspend_cpu(machine, vic2);
1190      else
1191         vic2_resume_cpu(machine, vic2);
1192
1193      if (vic2->spr_dma_on & 0x80) vic2->rdy_cycles += (2 + adjust(5));
1194
1195      vic2->cycle++;
1196      break;
1197
1198   // Sprite 7
1199   case 10:
1200      vic2_spr_data_access(machine, vic2, 7, 1);
1201      vic2_spr_data_access(machine, vic2, 7, 2);
1202      vic2_display_if_bad_line(vic2);
1203
1204      vic2->cycle++;
1205      break;
1206
1207   // Refresh
1208   case 11:
1209      vic2_refresh_access(machine, vic2);
1210      vic2_display_if_bad_line(vic2);
1211
1212      vic2_resume_cpu(machine, vic2);
1213
1214      vic2->cycle++;
1215      break;
1216
1217   // Refresh, fetch if bad line
1218   case 12:
1219      vic2_refresh_access(machine, vic2);
1220      vic2_fetch_if_bad_line(vic2);
1221
1222      vic2->cycle++;
1223      break;
1224
1225   // Refresh, fetch if bad line, raster_x
1226   case 13:
1227      vic2_draw_background(vic2);
1228      vic2_sample_border(vic2);
1229      vic2_refresh_access(machine, vic2);
1230      vic2_fetch_if_bad_line(vic2);
1231
1232      vic2->raster_x = 0xfffc;
1233
1234      if ((vic2->in_rdy_workaround_func(0) == 0 ) && (vic2->is_bad_line))
1235         vic2->rdy_cycles += (43+adjust(0));
1236
1237      vic2->cycle++;
1238      break;
1239
1240   // Refresh, fetch if bad line, RC, VC
1241   case 14:
1242      vic2_draw_background(vic2);
1243      vic2_sample_border(vic2);
1244      vic2_refresh_access(machine, vic2);
1245      vic2_rc_if_bad_line(vic2);
1246
1247      vic2->vc = vic2->vc_base;
1248
1249      if ((vic2->in_rdy_workaround_func(0) == 1 ) && (vic2->is_bad_line))
1250         vic2->rdy_cycles += (42+adjust(0));
1251
1252      vic2->cycle++;
1253      break;
1254
1255   // Refresh, fetch if bad line, sprite y expansion
1256   case 15:
1257      vic2_draw_background(vic2);
1258      vic2_sample_border(vic2);
1259      vic2_refresh_access(machine, vic2);
1260      vic2_fetch_if_bad_line(vic2);
1261
1262      for (i = 0; i < 8; i++)
1263         if (vic2->spr_exp_y & (1 << i))
1264            vic2->mc_base[i] += 2;
1265
1266      vic2->ml_index = 0;
1267      vic2_matrix_access(machine, vic2);
1268
1269      if ((vic2->in_rdy_workaround_func(0) == 2 ) && (vic2->is_bad_line))
1270         vic2->rdy_cycles += (41+adjust(0));
1271
1272      vic2->cycle++;
1273      break;
1274
1275   // Graphics, sprite y expansion, sprite DMA
1276   case 16:
1277      vic2_draw_background(vic2);
1278      vic2_sample_border(vic2);
1279      vic2_graphics_access(machine, vic2);
1280      vic2_fetch_if_bad_line(vic2);
1281
1282      mask = 1;
1283      for (i = 0; i < 8; i++, mask <<= 1)
1284      {
1285         if (vic2->spr_exp_y & mask)
1286            vic2->mc_base[i]++;
1287         if ((vic2->mc_base[i] & 0x3f) == 0x3f)
1288            vic2->spr_dma_on &= ~mask;
1289      }
1290
1291      vic2_matrix_access(machine, vic2);
1292
1293      if ((vic2->in_rdy_workaround_func(0) == 3 ) && (vic2->is_bad_line))
1294         vic2->rdy_cycles += (40+adjust(0));
1295
1296      vic2->cycle++;
1297      break;
1298
1299   // Graphics, check border
1300   case 17:
1301      if (COLUMNS40)
1302      {
1303         if (vic2->rasterline == vic2->dy_stop)
1304            vic2->ud_border_on = 1;
1305         else
1306         {
1307            if (SCREENON)
1308            {
1309               if (vic2->rasterline == vic2->dy_start)
1310                  vic2->border_on = vic2->ud_border_on = 0;
1311               else
1312                  if (vic2->ud_border_on == 0)
1313                     vic2->border_on = 0;
1314            } else
1315               if (vic2->ud_border_on == 0)
1316                  vic2->border_on = 0;
1317         }
1318      }
1319
1320      // Second sample of border state
1321      vic2->border_on_sample[1] = vic2->border_on;
1322
1323      vic2_draw_background(vic2);
1324      vic2_draw_graphics(vic2);
1325      vic2_sample_border(vic2);
1326      vic2_graphics_access(machine, vic2);
1327      vic2_fetch_if_bad_line(vic2);
1328      vic2_matrix_access(machine, vic2);
1329
1330      if ((vic2->in_rdy_workaround_func(0) == 4 ) && (vic2->is_bad_line))
1331         vic2->rdy_cycles += (40+adjust(0));
1332
1333      vic2->cycle++;
1334      break;
1335
1336   // Check border
1337   case 18:
1338      if (!COLUMNS40)
1339      {
1340         if (vic2->rasterline == vic2->dy_stop)
1341            vic2->ud_border_on = 1;
1342         else
1343         {
1344            if (SCREENON)
1345            {
1346               if (vic2->rasterline == vic2->dy_start)
1347                  vic2->border_on = vic2->ud_border_on = 0;
1348               else
1349                  if (vic2->ud_border_on == 0)
1350                     vic2->border_on = 0;
1351            } else
1352               if (vic2->ud_border_on == 0)
1353                  vic2->border_on = 0;
1354         }
1355      }
1356
1357      // Third sample of border state
1358      vic2->border_on_sample[2] = vic2->border_on;
1359
1360   // Graphics
1361
1362   case 19:
1363   case 20:
1364   case 21:
1365   case 22:
1366   case 23:
1367   case 24:
1368   case 25:
1369   case 26:
1370   case 27:
1371   case 28:
1372   case 29:
1373   case 30:
1374   case 31:
1375   case 32:
1376   case 33:
1377   case 34:
1378   case 35:
1379   case 36:
1380   case 37:
1381   case 38:
1382   case 39:
1383   case 40:
1384   case 41:
1385   case 42:
1386   case 43:
1387   case 44:
1388   case 45:
1389   case 46:
1390   case 47:
1391   case 48:
1392   case 49:
1393   case 50:
1394   case 51:
1395   case 52:
1396   case 53:
1397   case 54:
1398      vic2_draw_graphics(vic2);
1399      vic2_sample_border(vic2);
1400      vic2_graphics_access(machine, vic2);
1401      vic2_fetch_if_bad_line(vic2);
1402      vic2_matrix_access(machine, vic2);
1403      vic2->last_char_data = vic2->char_data;
1404
1405      vic2->cycle++;
1406      break;
1407
1408   // Graphics, sprite y expansion, sprite DMA
1409   case 55:
1410      vic2_draw_graphics(vic2);
1411      vic2_sample_border(vic2);
1412      vic2_graphics_access(machine, vic2);
1413      vic2_display_if_bad_line(vic2);
1414
1415      // sprite y expansion
1416      mask = 1;
1417      for (i = 0; i < 8; i++, mask <<= 1)
1418         if (SPRITE_Y_EXPAND (i))
1419            vic2->spr_exp_y ^= mask;
1420
1421      vic2_check_sprite_dma(vic2);
1422
1423      vic2_resume_cpu(machine, vic2);
1424
1425      vic2->cycle++;
1426      break;
1427
1428   // Check border, sprite DMA
1429   case 56:
1430      if (!COLUMNS40)
1431         vic2->border_on = 1;
1432
1433      // Fourth sample of border state
1434      vic2->border_on_sample[3] = vic2->border_on;
1435
1436      vic2_draw_graphics(vic2);
1437      vic2_sample_border(vic2);
1438      vic2_idle_access(machine, vic2);
1439      vic2_display_if_bad_line(vic2);
1440      vic2_check_sprite_dma(vic2);
1441
1442      vic2->cycle++;
1443      break;
1444
1445   // Check border, sprites
1446   case 57:
1447      if (COLUMNS40)
1448         vic2->border_on = 1;
1449
1450      // Fifth sample of border state
1451      vic2->border_on_sample[4] = vic2->border_on;
1452
1453      // Sample spr_disp_on and spr_data for sprite drawing
1454      vic2->spr_draw = vic2->spr_disp_on;
1455      if (vic2->spr_draw)
1456         memcpy(vic2->spr_draw_data, vic2->spr_data, 8 * 4);
1457
1458      mask = 1;
1459      for (i = 0; i < 8; i++, mask <<= 1)
1460         if ((vic2->spr_disp_on & mask) && !(vic2->spr_dma_on & mask))
1461            vic2->spr_disp_on &= ~mask;
1462
1463      vic2_draw_background(vic2);
1464      vic2_sample_border(vic2);
1465      vic2_idle_access(machine, vic2);
1466      vic2_display_if_bad_line(vic2);
1467
1468      vic2->cycle++;
1469      break;
1470
1471   // Sprite 0, sprite DMA, MC, RC
1472   case 58:
1473      vic2_draw_background(vic2);
1474      vic2_sample_border(vic2);
1475
1476      mask = 1;
1477      for (i = 0; i < 8; i++, mask <<= 1)
1478      {
1479         vic2->mc[i] = vic2->mc_base[i];
1480         if ((vic2->spr_dma_on & mask) && ((vic2->rasterline & 0xff) == SPRITE_Y_POS(i)))
1481            vic2->spr_disp_on |= mask;
1482      }
1483
1484      vic2_spr_ptr_access(machine, vic2, 0);
1485      vic2_spr_data_access(machine, vic2, 0, 0);
1486
1487      if (vic2->rc == 7)
1488      {
1489         vic2->vc_base = vic2->vc;
1490         vic2->display_state = 0;
1491      }
1492
1493      if (vic2->is_bad_line || vic2->display_state)
1494      {
1495         vic2->display_state = 1;
1496         vic2->rc = (vic2->rc + 1) & 7;
1497      }
1498
1499      if (vic2->spr_dma_on & 0x01)
1500         vic2_suspend_cpu(machine, vic2);
1501      else
1502         vic2_resume_cpu(machine, vic2);
1503
1504      if (vic2->spr_dma_on & 0x01) vic2->rdy_cycles += (2 + adjust(6));
1505
1506      vic2->cycle++;
1507      break;
1508
1509   // Sprite 0
1510   case 59:
1511      vic2_draw_background(vic2);
1512      vic2_sample_border(vic2);
1513      vic2_spr_data_access(machine, vic2, 0, 1);
1514      vic2_spr_data_access(machine, vic2, 0, 2);
1515      vic2_display_if_bad_line(vic2);
1516
1517      vic2->cycle++;
1518      break;
1519
1520   // Sprite 1, draw
1521   case 60:
1522      vic2_draw_background(vic2);
1523      vic2_sample_border(vic2);
1524
1525      if (vic2->draw_this_line)
1526      {
1527         vic2_draw_sprites(machine, vic2);
1528
1529         if (vic2->border_on_sample[0])
1530            for (i = 0; i < 4; i++)
1531               vic2->bitmap->plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(vic2->rasterline), 8, 1, vic2->border_color_sample[i]);
1532
1533         if (vic2->border_on_sample[1])
1534            vic2->bitmap->plot_box(VIC2_X_2_EMU(4 * 8), VIC2_RASTER_2_EMU(vic2->rasterline), 8, 1, vic2->border_color_sample[4]);
1535
1536         if (vic2->border_on_sample[2])
1537            for (i = 5; i < 43; i++)
1538               vic2->bitmap->plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(vic2->rasterline), 8, 1, vic2->border_color_sample[i]);
1539
1540         if (vic2->border_on_sample[3])
1541            vic2->bitmap->plot_box(VIC2_X_2_EMU(43 * 8), VIC2_RASTER_2_EMU(vic2->rasterline), 8, 1, vic2->border_color_sample[43]);
1542
1543         if (vic2->border_on_sample[4])
1544         {
1545            for (i = 44; i < 48; i++)
1546               vic2->bitmap->plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(vic2->rasterline), 8, 1, vic2->border_color_sample[i]);
1547            for (i = 48; i < 51; i++)
1548               vic2->bitmap->plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(vic2->rasterline), 8, 1, vic2->border_color_sample[47]);
1549         }
1550      }
1551
1552      vic2_spr_ptr_access(machine, vic2, 1);
1553      vic2_spr_data_access(machine, vic2, 1, 0);
1554      vic2_display_if_bad_line(vic2);
1555
1556      if (vic2->spr_dma_on & 0x02)
1557         vic2_suspend_cpu(machine, vic2);
1558      else
1559         vic2_resume_cpu(machine, vic2);
1560
1561      if (vic2->spr_dma_on & 0x02) vic2->rdy_cycles += (2 + adjust(7));
1562
1563      vic2->cycle++;
1564      break;
1565
1566   // Sprite 1
1567   case 61:
1568      vic2_spr_data_access(machine, vic2, 1, 1);
1569      vic2_spr_data_access(machine, vic2, 1, 2);
1570      vic2_display_if_bad_line(vic2);
1571
1572      vic2->cycle++;
1573      break;
1574
1575   // Sprite 2
1576   case 62:
1577      vic2_spr_ptr_access(machine, vic2, 2);
1578      vic2_spr_data_access(machine, vic2, 2, 0);
1579      vic2_display_if_bad_line(vic2);
1580
1581      if (vic2->spr_dma_on & 0x04)
1582         vic2_suspend_cpu(machine, vic2);
1583      else
1584         vic2_resume_cpu(machine, vic2);
1585
1586      if (vic2->spr_dma_on & 0x04) vic2->rdy_cycles += (2 + adjust(8));
1587
1588      vic2->cycle++;
1589      break;
1590
1591   // Sprite 2
1592   case 63:
1593      vic2_spr_data_access(machine, vic2, 2, 1);
1594      vic2_spr_data_access(machine, vic2, 2, 2);
1595      vic2_display_if_bad_line(vic2);
1596
1597      if (vic2->rasterline == vic2->dy_stop)
1598         vic2->ud_border_on = 1;
1599      else
1600         if (SCREENON && (vic2->rasterline == vic2->dy_start))
1601            vic2->ud_border_on = 0;
1602
1603      // Last cycle
1604      vic2->cycle = 1;
1605   }
1606
1607   if ((cpu_cycles == vic_cycles) && (vic2->rdy_cycles > 0))
1608   {
1609      machine.firstcpu->spin_until_time(vic2->cpu->cycles_to_attotime(vic2->rdy_cycles));
1610      vic2->rdy_cycles = 0;
1611   }
1612
1613   vic2->raster_x += 8;
1614   machine.scheduler().timer_set(vic2->cpu->cycles_to_attotime(1), FUNC(pal_timer_callback), 0, vic2);
1615}
1616
1617static TIMER_CALLBACK( ntsc_timer_callback )
1618{
1619   vic2_state *vic2 = (vic2_state *)ptr;
1620   int i;
1621   UINT8 mask;
1622   vic2->cycles_counter++;
1623
1624   switch (vic2->cycle)
1625   {
1626
1627   // Sprite 3, raster counter, raster IRQ, bad line
1628   case 1:
1629      if (vic2->rasterline == (VIC2_LINES - 1))
1630      {
1631         vic2->vblanking = 1;
1632
1633//          if (LIGHTPEN_BUTTON)
1634         {
1635            /* lightpen timer starten */
1636            machine.scheduler().timer_set(attotime(0, 0), FUNC(vic2_timer_timeout), 1, vic2);
1637         }
1638      }
1639      else
1640      {
1641         vic2->rasterline++;
1642
1643         if (vic2->rasterline == VIC2_FIRST_DMA_LINE)
1644            vic2->bad_lines_enabled = SCREENON;
1645
1646         vic2->is_bad_line = ((vic2->rasterline >= VIC2_FIRST_DMA_LINE) && (vic2->rasterline <= VIC2_LAST_DMA_LINE) &&
1647                  ((vic2->rasterline & 0x07) == VERTICALPOS) && vic2->bad_lines_enabled);
1648
1649         vic2->draw_this_line = ((VIC2_RASTER_2_EMU(vic2->rasterline) >= VIC2_RASTER_2_EMU(VIC2_FIRST_DISP_LINE)) &&
1650                  (VIC2_RASTER_2_EMU(vic2->rasterline ) <= VIC2_RASTER_2_EMU(VIC2_LAST_DISP_LINE)));
1651      }
1652
1653      vic2->border_on_sample[0] = vic2->border_on;
1654      vic2_spr_ptr_access(machine, vic2, 3);
1655      vic2_spr_data_access(machine, vic2, 3, 0);
1656      vic2_display_if_bad_line(vic2);
1657
1658      if (vic2->spr_dma_on & 0x08)
1659         vic2_suspend_cpu(machine, vic2);
1660      else
1661         vic2_resume_cpu(machine, vic2);
1662
1663      vic2->cycle++;
1664      break;
1665
1666   // Sprite 3
1667   case 2:
1668      if (vic2->vblanking)
1669      {
1670         // Vertical blank, reset counters
1671         vic2->rasterline = vic2->vc_base = 0;
1672         vic2->ref_cnt = 0xff;
1673         vic2->vblanking = 0;
1674
1675         // Trigger raster IRQ if IRQ in line 0
1676         if (RASTERLINE == 0)
1677         {
1678            vic2_set_interrupt(machine, 1, vic2);
1679         }
1680      }
1681
1682      if (vic2->rasterline == RASTERLINE)
1683      {
1684         vic2_set_interrupt(machine, 1, vic2);
1685      }
1686
1687      vic2->graphic_x = VIC2_X_2_EMU(0);
1688
1689      vic2_spr_data_access(machine, vic2, 3, 1);
1690      vic2_spr_data_access(machine, vic2, 3, 2);
1691      vic2_display_if_bad_line(vic2);
1692
1693      vic2->cycle++;
1694      break;
1695
1696   // Sprite 4
1697   case 3:
1698      vic2_spr_ptr_access(machine, vic2, 4);
1699      vic2_spr_data_access(machine, vic2, 4, 0);
1700      vic2_display_if_bad_line(vic2);
1701
1702      if (vic2->spr_dma_on & 0x10)
1703         vic2_suspend_cpu(machine, vic2);
1704      else
1705         vic2_resume_cpu(machine, vic2);
1706
1707      vic2->cycle++;
1708      break;
1709
1710   // Sprite 4
1711   case 4:
1712      vic2_spr_data_access(machine, vic2, 4, 1);
1713      vic2_spr_data_access(machine, vic2, 4, 2);
1714      vic2_display_if_bad_line(vic2);
1715
1716      vic2->cycle++;
1717      break;
1718
1719   // Sprite 5
1720   case 5:
1721      vic2_spr_ptr_access(machine, vic2, 5);
1722      vic2_spr_data_access(machine, vic2, 5, 0);
1723      vic2_display_if_bad_line(vic2);
1724
1725      if (vic2->spr_dma_on & 0x20)
1726         vic2_suspend_cpu(machine, vic2);
1727      else
1728         vic2_resume_cpu(machine, vic2);
1729
1730      vic2->cycle++;
1731      break;
1732
1733   // Sprite 5
1734   case 6:
1735      vic2_spr_data_access(machine, vic2, 5, 1);
1736      vic2_spr_data_access(machine, vic2, 5, 2);
1737      vic2_display_if_bad_line(vic2);
1738
1739      vic2->cycle++;
1740      break;
1741
1742   // Sprite 6
1743   case 7:
1744      vic2_spr_ptr_access(machine, vic2, 6);
1745      vic2_spr_data_access(machine, vic2, 6, 0);
1746      vic2_display_if_bad_line(vic2);
1747
1748      if (vic2->spr_dma_on & 0x40)
1749         vic2_suspend_cpu(machine, vic2);
1750      else
1751         vic2_resume_cpu(machine, vic2);
1752
1753      vic2->cycle++;
1754      break;
1755
1756   // Sprite 6
1757   case 8:
1758      vic2_spr_data_access(machine, vic2, 6, 1);
1759      vic2_spr_data_access(machine, vic2, 6, 2);
1760      vic2_display_if_bad_line(vic2);
1761
1762      vic2->cycle++;
1763      break;
1764
1765   // Sprite 7
1766   case 9:
1767      vic2_spr_ptr_access(machine, vic2, 7);
1768      vic2_spr_data_access(machine, vic2, 7, 0);
1769      vic2_display_if_bad_line(vic2);
1770
1771      if (vic2->spr_dma_on & 0x80)
1772         vic2_suspend_cpu(machine, vic2);
1773      else
1774         vic2_resume_cpu(machine, vic2);
1775
1776      vic2->cycle++;
1777      break;
1778
1779   // Sprite 7
1780   case 10:
1781      vic2_spr_data_access(machine, vic2, 7, 1);
1782      vic2_spr_data_access(machine, vic2, 7, 2);
1783      vic2_display_if_bad_line(vic2);
1784
1785      vic2->cycle++;
1786      break;
1787
1788   // Refresh
1789   case 11:
1790      vic2_refresh_access(machine, vic2);
1791      vic2_display_if_bad_line(vic2);
1792
1793      vic2_resume_cpu(machine, vic2);
1794
1795      vic2->cycle++;
1796      break;
1797
1798   // Refresh, fetch if bad line
1799   case 12:
1800      vic2_refresh_access(machine, vic2);
1801      vic2_fetch_if_bad_line(vic2);
1802
1803      vic2->cycle++;
1804      break;
1805
1806   // Refresh, fetch if bad line, raster_x
1807   case 13:
1808      vic2_draw_background(vic2);
1809      vic2_sample_border(vic2);
1810      vic2_refresh_access(machine, vic2);
1811      vic2_fetch_if_bad_line(vic2);
1812
1813      vic2->raster_x = 0xfffc;
1814
1815      vic2->cycle++;
1816      break;
1817
1818   // Refresh, fetch if bad line, RC, VC
1819   case 14:
1820      vic2_draw_background(vic2);
1821      vic2_sample_border(vic2);
1822      vic2_refresh_access(machine, vic2);
1823      vic2_rc_if_bad_line(vic2);
1824
1825      vic2->vc = vic2->vc_base;
1826
1827      vic2->cycle++;
1828      break;
1829
1830   // Refresh, fetch if bad line, sprite y expansion
1831   case 15:
1832      vic2_draw_background(vic2);
1833      vic2_sample_border(vic2);
1834      vic2_refresh_access(machine, vic2);
1835      vic2_fetch_if_bad_line(vic2);
1836
1837      for (i = 0; i < 8; i++)
1838         if (vic2->spr_exp_y & (1 << i))
1839            vic2->mc_base[i] += 2;
1840
1841      if (vic2->is_bad_line)
1842         vic2_suspend_cpu(machine, vic2);
1843
1844      vic2->ml_index = 0;
1845      vic2_matrix_access(machine, vic2);
1846
1847      vic2->cycle++;
1848      break;
1849
1850   // Graphics, sprite y expansion, sprite DMA
1851   case 16:
1852      vic2_draw_background(vic2);
1853      vic2_sample_border(vic2);
1854      vic2_graphics_access(machine, vic2);
1855      vic2_fetch_if_bad_line(vic2);
1856
1857      mask = 1;
1858      for (i = 0; i < 8; i++, mask <<= 1)
1859      {
1860         if (vic2->spr_exp_y & mask)
1861            vic2->mc_base[i]++;
1862         if ((vic2->mc_base[i] & 0x3f) == 0x3f)
1863            vic2->spr_dma_on &= ~mask;
1864      }
1865
1866      vic2_matrix_access(machine, vic2);
1867
1868      vic2->cycle++;
1869      break;
1870
1871   // Graphics, check border
1872   case 17:
1873      if (COLUMNS40)
1874      {
1875         if (vic2->rasterline == vic2->dy_stop)
1876            vic2->ud_border_on = 1;
1877         else
1878         {
1879            if (SCREENON)
1880            {
1881               if (vic2->rasterline == vic2->dy_start)
1882                  vic2->border_on = vic2->ud_border_on = 0;
1883               else
1884                  if (vic2->ud_border_on == 0)
1885                     vic2->border_on = 0;
1886            }
1887            else
1888               if (vic2->ud_border_on == 0)
1889                  vic2->border_on = 0;
1890         }
1891      }
1892
1893      // Second sample of border state
1894      vic2->border_on_sample[1] = vic2->border_on;
1895
1896      vic2_draw_background(vic2);
1897      vic2_draw_graphics(vic2);
1898      vic2_sample_border(vic2);
1899      vic2_graphics_access(machine, vic2);
1900      vic2_fetch_if_bad_line(vic2);
1901      vic2_matrix_access(machine, vic2);
1902
1903      vic2->cycle++;
1904      break;
1905
1906   // Check border
1907   case 18:
1908      if (!COLUMNS40)
1909      {
1910         if (vic2->rasterline == vic2->dy_stop)
1911            vic2->ud_border_on = 1;
1912         else
1913         {
1914            if (SCREENON)
1915            {
1916               if (vic2->rasterline == vic2->dy_start)
1917                  vic2->border_on = vic2->ud_border_on = 0;
1918               else
1919                  if (vic2->ud_border_on == 0)
1920                     vic2->border_on = 0;
1921            }
1922            else
1923               if (vic2->ud_border_on == 0)
1924                  vic2->border_on = 0;
1925         }
1926      }
1927
1928      // Third sample of border state
1929      vic2->border_on_sample[2] = vic2->border_on;
1930
1931   // Graphics
1932
1933   case 19:
1934   case 20:
1935   case 21:
1936   case 22:
1937   case 23:
1938   case 24:
1939   case 25:
1940   case 26:
1941   case 27:
1942   case 28:
1943   case 29:
1944   case 30:
1945   case 31:
1946   case 32:
1947   case 33:
1948   case 34:
1949   case 35:
1950   case 36:
1951   case 37:
1952   case 38:
1953   case 39:
1954   case 40:
1955   case 41:
1956   case 42:
1957   case 43:
1958   case 44:
1959   case 45:
1960   case 46:
1961   case 47:
1962   case 48:
1963   case 49:
1964   case 50:
1965   case 51:
1966   case 52:
1967   case 53:
1968   case 54:
1969      vic2_draw_graphics(vic2);
1970      vic2_sample_border(vic2);
1971      vic2_graphics_access(machine, vic2);
1972      vic2_fetch_if_bad_line(vic2);
1973      vic2_matrix_access(machine, vic2);
1974      vic2->last_char_data = vic2->char_data;
1975
1976      vic2->cycle++;
1977      break;
1978
1979   // Graphics, sprite y expansion, sprite DMA
1980   case 55:
1981      vic2_draw_graphics(vic2);
1982      vic2_sample_border(vic2);
1983      vic2_graphics_access(machine, vic2);
1984      vic2_display_if_bad_line(vic2);
1985
1986      // sprite y expansion
1987      mask = 1;
1988      for (i = 0; i < 8; i++, mask <<= 1)
1989         if (SPRITE_Y_EXPAND (i))
1990            vic2->spr_exp_y ^= mask;
1991
1992      vic2_check_sprite_dma(vic2);
1993
1994      vic2_resume_cpu(machine, vic2);
1995
1996      vic2->cycle++;
1997      break;
1998
1999   // Check border, sprite DMA
2000   case 56:
2001      if (!COLUMNS40)
2002         vic2->border_on = 1;
2003
2004      // Fourth sample of border state
2005      vic2->border_on_sample[3] = vic2->border_on;
2006
2007      vic2_draw_graphics(vic2);
2008      vic2_sample_border(vic2);
2009      vic2_idle_access(machine, vic2);
2010      vic2_display_if_bad_line(vic2);
2011      vic2_check_sprite_dma(vic2);
2012
2013      vic2->cycle++;
2014      break;
2015
2016   // Check border, sprites
2017   case 57:
2018      if (COLUMNS40)
2019         vic2->border_on = 1;
2020
2021      // Fifth sample of border state
2022      vic2->border_on_sample[4] = vic2->border_on;
2023
2024      // Sample spr_disp_on and spr_data for sprite drawing
2025      vic2->spr_draw = vic2->spr_disp_on;
2026      if (vic2->spr_draw)
2027         memcpy(vic2->spr_draw_data, vic2->spr_data, 8 * 4);
2028
2029      mask = 1;
2030      for (i = 0; i < 8; i++, mask <<= 1)
2031         if ((vic2->spr_disp_on & mask) && !(vic2->spr_dma_on & mask))
2032            vic2->spr_disp_on &= ~mask;
2033
2034      vic2_draw_background(vic2);
2035      vic2_sample_border(vic2);
2036      vic2_idle_access(machine, vic2);
2037      vic2_display_if_bad_line(vic2);
2038
2039      vic2->cycle++;
2040      break;
2041
2042   // for NTSC 6567R8
2043   case 58:
2044      vic2_draw_background(vic2);
2045      vic2_sample_border(vic2);
2046      vic2_idle_access(machine, vic2);
2047      vic2_display_if_bad_line(vic2);
2048
2049      vic2->cycle++;
2050      break;
2051
2052   // for NTSC 6567R8
2053   case 59:
2054      vic2_draw_background(vic2);
2055      vic2_sample_border(vic2);
2056      vic2_idle_access(machine, vic2);
2057      vic2_display_if_bad_line(vic2);
2058
2059      vic2->cycle++;
2060      break;
2061
2062   // Sprite 0, sprite DMA, MC, RC
2063   case 60:
2064      vic2_draw_background(vic2);
2065      vic2_sample_border(vic2);
2066
2067      mask = 1;
2068      for (i = 0; i < 8; i++, mask <<= 1)
2069      {
2070         vic2->mc[i] = vic2->mc_base[i];
2071         if ((vic2->spr_dma_on & mask) && ((vic2->rasterline & 0xff) == SPRITE_Y_POS(i)))
2072            vic2->spr_disp_on |= mask;
2073      }
2074
2075      vic2_spr_ptr_access(machine, vic2, 0);
2076      vic2_spr_data_access(machine, vic2, 0, 0);
2077
2078      if (vic2->rc == 7)
2079      {
2080         vic2->vc_base = vic2->vc;
2081         vic2->display_state = 0;
2082      }
2083
2084      if (vic2->is_bad_line || vic2->display_state)
2085      {
2086         vic2->display_state = 1;
2087         vic2->rc = (vic2->rc + 1) & 7;
2088      }
2089
2090      if (vic2->spr_dma_on & 0x01)
2091         vic2_suspend_cpu(machine, vic2);
2092      else
2093         vic2_resume_cpu(machine, vic2);
2094
2095      vic2->cycle++;
2096      break;
2097
2098   // Sprite 0
2099   case 61:
2100      vic2_draw_background(vic2);
2101      vic2_sample_border(vic2);
2102      vic2_spr_data_access(machine, vic2, 0, 1);
2103      vic2_spr_data_access(machine, vic2, 0, 2);
2104      vic2_display_if_bad_line(vic2);
2105
2106      vic2->cycle++;
2107      break;
2108
2109   // Sprite 1, draw
2110   case 62:
2111      vic2_draw_background(vic2);
2112      vic2_sample_border(vic2);
2113
2114      if (vic2->draw_this_line)
2115      {
2116         vic2_draw_sprites(machine, vic2);
2117
2118         if (vic2->border_on_sample[0])
2119            for (i = 0; i < 4; i++)
2120               vic2->bitmap->plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(vic2->rasterline), 8, 1, vic2->border_color_sample[i]);
2121
2122         if (vic2->border_on_sample[1])
2123            vic2->bitmap->plot_box(VIC2_X_2_EMU(4 * 8), VIC2_RASTER_2_EMU(vic2->rasterline), 8, 1, vic2->border_color_sample[4]);
2124
2125         if (vic2->border_on_sample[2])
2126            for (i = 5; i < 43; i++)
2127               vic2->bitmap->plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(vic2->rasterline), 8, 1, vic2->border_color_sample[i]);
2128
2129         if (vic2->border_on_sample[3])
2130            vic2->bitmap->plot_box(VIC2_X_2_EMU(43 * 8), VIC2_RASTER_2_EMU(vic2->rasterline), 8, 1, vic2->border_color_sample[43]);
2131
2132         if (vic2->border_on_sample[4])
2133         {
2134            for (i = 44; i < 48; i++)
2135               vic2->bitmap->plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(vic2->rasterline), 8, 1, vic2->border_color_sample[i]);
2136            for (i = 48; i < 53; i++)
2137               vic2->bitmap->plot_box(VIC2_X_2_EMU(i * 8), VIC2_RASTER_2_EMU(vic2->rasterline), 8, 1, vic2->border_color_sample[47]);
2138         }
2139      }
2140
2141      vic2_spr_ptr_access(machine, vic2, 1);
2142      vic2_spr_data_access(machine, vic2, 1, 0);
2143      vic2_display_if_bad_line(vic2);
2144
2145      if (vic2->spr_dma_on & 0x02)
2146         vic2_suspend_cpu(machine, vic2);
2147      else
2148         vic2_resume_cpu(machine, vic2);
2149
2150      vic2->cycle++;
2151      break;
2152
2153   // Sprite 1
2154   case 63:
2155      vic2_spr_data_access(machine, vic2, 1, 1);
2156      vic2_spr_data_access(machine, vic2, 1, 2);
2157      vic2_display_if_bad_line(vic2);
2158
2159      vic2->cycle++;
2160      break;
2161
2162   // Sprite 2
2163   case 64:
2164      vic2_spr_ptr_access(machine, vic2, 2);
2165      vic2_spr_data_access(machine, vic2, 2, 0);
2166      vic2_display_if_bad_line(vic2);
2167
2168      if (vic2->spr_dma_on & 0x04)
2169         vic2_suspend_cpu(machine, vic2);
2170      else
2171         vic2_resume_cpu(machine, vic2);
2172
2173      vic2->cycle++;
2174      break;
2175
2176   // Sprite 2
2177   case 65:
2178      vic2_spr_data_access(machine, vic2, 2, 1);
2179      vic2_spr_data_access(machine, vic2, 2, 2);
2180      vic2_display_if_bad_line(vic2);
2181
2182      if (vic2->rasterline == vic2->dy_stop)
2183         vic2->ud_border_on = 1;
2184      else
2185         if (SCREENON && (vic2->rasterline == vic2->dy_start))
2186            vic2->ud_border_on = 0;
2187
2188      // Last cycle
2189      vic2->cycle = 1;
2190   }
2191
2192   vic2->raster_x += 8;
2193   machine.scheduler().timer_set(vic2->cpu->cycles_to_attotime(1), FUNC(ntsc_timer_callback), 0, vic2);
2194}
2195
2196
2197/*****************************************************************************
2198    I/O HANDLERS
2199*****************************************************************************/
2200
2201void vic2_set_rastering( device_t *device, int onoff )
2202{
2203   vic2_state *vic2 = get_safe_token(device);
2204   vic2->on = onoff;
2205}
2206
2207int vic2e_k0_r( device_t *device )
2208{
2209   vic2_state *vic2 = get_safe_token(device);
2210   return VIC2E_K0_LEVEL;
2211}
2212
2213int vic2e_k1_r( device_t *device )
2214{
2215   vic2_state *vic2 = get_safe_token(device);
2216   return VIC2E_K1_LEVEL;
2217}
2218
2219int vic2e_k2_r( device_t *device )
2220{
2221   vic2_state *vic2 = get_safe_token(device);
2222   return VIC2E_K2_LEVEL;
2223}
2224
2225
2226WRITE8_DEVICE_HANDLER( vic2_port_w )
2227{
2228   vic2_state *vic2 = get_safe_token(device);
2229   running_machine &machine = space.machine();
2230
2231   DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
2232   offset &= 0x3f;
2233
2234   switch (offset)
2235   {
2236   case 0x01:
2237   case 0x03:
2238   case 0x05:
2239   case 0x07:
2240   case 0x09:
2241   case 0x0b:
2242   case 0x0d:
2243   case 0x0f:
2244      vic2->reg[offset] = data;      /* sprite y positions */
2245      break;
2246
2247   case 0x00:
2248   case 0x02:
2249   case 0x04:
2250   case 0x06:
2251   case 0x08:
2252   case 0x0a:
2253   case 0x0c:
2254   case 0x0e:
2255      vic2->reg[offset] = data;      /* sprite x positions */
2256      break;
2257
2258   case 0x10:
2259      vic2->reg[offset] = data;      /* sprite x positions */
2260      break;
2261
2262   case 0x17:                     /* sprite y size */
2263      vic2->spr_exp_y |= ~data;
2264      if (vic2->reg[offset] != data)
2265      {
2266         vic2->reg[offset] = data;
2267      }
2268      break;
2269
2270   case 0x1d:                     /* sprite x size */
2271      if (vic2->reg[offset] != data)
2272      {
2273         vic2->reg[offset] = data;
2274      }
2275      break;
2276
2277   case 0x1b:                     /* sprite background priority */
2278      if (vic2->reg[offset] != data)
2279      {
2280         vic2->reg[offset] = data;
2281      }
2282      break;
2283
2284   case 0x1c:                     /* sprite multicolor mode select */
2285      if (vic2->reg[offset] != data)
2286      {
2287         vic2->reg[offset] = data;
2288      }
2289      break;
2290
2291   case 0x27:
2292   case 0x28:
2293   case 0x29:
2294   case 0x2a:
2295   case 0x2b:
2296   case 0x2c:
2297   case 0x2d:
2298   case 0x2e:
2299                           /* sprite colors */
2300      if (vic2->reg[offset] != data)
2301      {
2302         vic2->reg[offset] = data;
2303      }
2304      break;
2305
2306   case 0x25:                     /* sprite multicolor */
2307      if (vic2->reg[offset] != data)
2308      {
2309         vic2->reg[offset] = data;
2310         vic2->spritemulti[1] = SPRITE_MULTICOLOR1;
2311      }
2312      break;
2313
2314   case 0x26:                     /* sprite multicolor */
2315      if (vic2->reg[offset] != data)
2316      {
2317         vic2->reg[offset] = data;
2318         vic2->spritemulti[3] = SPRITE_MULTICOLOR2;
2319      }
2320      break;
2321
2322   case 0x19:
2323      vic2_clear_interrupt(machine, data & 0x0f, vic2);
2324      break;
2325
2326   case 0x1a:                     /* irq mask */
2327      vic2->reg[offset] = data;
2328      vic2_set_interrupt(machine, 0, vic2);   // beamrider needs this
2329      break;
2330
2331   case 0x11:
2332      if (vic2->reg[offset] != data)
2333      {
2334         vic2->reg[offset] = data;
2335         if (data & 8)
2336         {
2337            vic2->dy_start = ROW25_YSTART;
2338            vic2->dy_stop = ROW25_YSTOP;
2339         }
2340         else
2341         {
2342            vic2->dy_start = ROW24_YSTART;
2343            vic2->dy_stop = ROW24_YSTOP;
2344         }
2345      }
2346      break;
2347
2348   case 0x12:
2349      if (data != vic2->reg[offset])
2350      {
2351         vic2->reg[offset] = data;
2352      }
2353      break;
2354
2355   case 0x16:
2356      if (vic2->reg[offset] != data)
2357      {
2358         vic2->reg[offset] = data;
2359      }
2360      break;
2361
2362   case 0x18:
2363      if (vic2->reg[offset] != data)
2364      {
2365         vic2->reg[offset] = data;
2366         vic2->videoaddr = VIDEOADDR;
2367         vic2->chargenaddr = CHARGENADDR;
2368         vic2->bitmapaddr = BITMAPADDR;
2369      }
2370      break;
2371
2372   case 0x21:                     /* background color */
2373      if (vic2->reg[offset] != data)
2374      {
2375         vic2->reg[offset] = data;
2376         vic2->colors[0] = BACKGROUNDCOLOR;
2377      }
2378      break;
2379
2380   case 0x22:                     /* background color 1 */
2381      if (vic2->reg[offset] != data)
2382      {
2383         vic2->reg[offset] = data;
2384         vic2->colors[1] = MULTICOLOR1;
2385      }
2386      break;
2387
2388   case 0x23:                     /* background color 2 */
2389      if (vic2->reg[offset] != data)
2390      {
2391         vic2->reg[offset] = data;
2392         vic2->colors[2] = MULTICOLOR2;
2393      }
2394      break;
2395
2396   case 0x24:                     /* background color 3 */
2397      if (vic2->reg[offset] != data)
2398      {
2399         vic2->reg[offset] = data;
2400         vic2->colors[3] = FOREGROUNDCOLOR;
2401      }
2402      break;
2403
2404   case 0x20:                     /* framecolor */
2405      if (vic2->reg[offset] != data)
2406      {
2407         vic2->reg[offset] = data;
2408      }
2409      break;
2410
2411   case 0x2f:
2412      if (vic2->type == VIC8564 || vic2->type == VIC8566)
2413      {
2414         DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
2415         vic2->reg[offset] = data;
2416      }
2417      break;
2418
2419   case 0x30:
2420      if (vic2->type == VIC8564 || vic2->type == VIC8566)
2421      {
2422         vic2->reg[offset] = data;
2423      }
2424      break;
2425
2426   case 0x31:
2427   case 0x32:
2428   case 0x33:
2429   case 0x34:
2430   case 0x35:
2431   case 0x36:
2432   case 0x37:
2433   case 0x38:
2434   case 0x39:
2435   case 0x3a:
2436   case 0x3b:
2437   case 0x3c:
2438   case 0x3d:
2439   case 0x3e:
2440   case 0x3f:
2441      vic2->reg[offset] = data;
2442      DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
2443      break;
2444
2445   default:
2446      vic2->reg[offset] = data;
2447      break;
2448   }
2449}
2450
2451READ8_DEVICE_HANDLER( vic2_port_r )
2452{
2453   vic2_state *vic2 = get_safe_token(device);
2454   running_machine &machine = space.machine();
2455   int val = 0;
2456
2457   offset &= 0x3f;
2458
2459   switch (offset)
2460   {
2461   case 0x11:
2462      val = (vic2->reg[offset] & ~0x80) | ((vic2->rasterline & 0x100) >> 1);
2463      break;
2464
2465   case 0x12:
2466      val = vic2->rasterline & 0xff;
2467      break;
2468
2469   case 0x16:
2470      val = vic2->reg[offset] | 0xc0;
2471      break;
2472
2473   case 0x18:
2474      val = vic2->reg[offset] | 0x01;
2475      break;
2476
2477   case 0x19:                     /* interrupt flag register */
2478      /* vic2_clear_interrupt(0xf); */
2479      val = vic2->reg[offset] | 0x70;
2480      break;
2481
2482   case 0x1a:
2483      val = vic2->reg[offset] | 0xf0;
2484      break;
2485
2486   case 0x1e:                     /* sprite to sprite collision detect */
2487      val = vic2->reg[offset];
2488      vic2->reg[offset] = 0;
2489      vic2_clear_interrupt(machine, 4, vic2);
2490      break;
2491
2492   case 0x1f:                     /* sprite to background collision detect */
2493      val = vic2->reg[offset];
2494      vic2->reg[offset] = 0;
2495      vic2_clear_interrupt(machine, 2, vic2);
2496      break;
2497
2498   case 0x20:
2499   case 0x21:
2500   case 0x22:
2501   case 0x23:
2502   case 0x24:
2503      val = vic2->reg[offset];
2504      break;
2505
2506   case 0x00:
2507   case 0x01:
2508   case 0x02:
2509   case 0x03:
2510   case 0x04:
2511   case 0x05:
2512   case 0x06:
2513   case 0x07:
2514   case 0x08:
2515   case 0x09:
2516   case 0x0a:
2517   case 0x0b:
2518   case 0x0c:
2519   case 0x0d:
2520   case 0x0e:
2521   case 0x0f:
2522   case 0x10:
2523   case 0x17:
2524   case 0x1b:
2525   case 0x1c:
2526   case 0x1d:
2527   case 0x25:
2528   case 0x26:
2529   case 0x27:
2530   case 0x28:
2531   case 0x29:
2532   case 0x2a:
2533   case 0x2b:
2534   case 0x2c:
2535   case 0x2d:
2536   case 0x2e:
2537      val = vic2->reg[offset];
2538      break;
2539
2540   case 0x2f:
2541   case 0x30:
2542      if (vic2->type == VIC8564 || vic2->type == VIC8566)
2543      {
2544         val = vic2->reg[offset];
2545         DBG_LOG(2, "vic read", ("%.2x:%.2x\n", offset, val));
2546      }
2547      else
2548         val = 0xff;
2549      break;
2550
2551   case 0x31:
2552   case 0x32:
2553   case 0x33:
2554   case 0x34:
2555   case 0x35:
2556   case 0x36:
2557   case 0x37:
2558   case 0x38:
2559   case 0x39:
2560   case 0x3a:
2561   case 0x3b:
2562   case 0x3c:
2563   case 0x3d:
2564   case 0x3e:
2565   case 0x3f:                     /* not used */
2566      // val = vic2->reg[offset]; //
2567      val = 0xff;
2568      DBG_LOG(2, "vic read", ("%.2x:%.2x\n", offset, val));
2569      break;
2570
2571   default:
2572      val = vic2->reg[offset];
2573   }
2574
2575   if ((offset != 0x11) && (offset != 0x12))
2576      DBG_LOG(2, "vic read", ("%.2x:%.2x\n", offset, val));
2577   return val;
2578}
2579
2580UINT32 vic2_video_update( device_t *device, bitmap_ind16 &bitmap, const rectangle &cliprect )
2581{
2582   vic2_state *vic2 = get_safe_token(device);
2583
2584   if (vic2->on)
2585      copybitmap(bitmap, *vic2->bitmap, 0, 0, 0, 0, cliprect);
2586   return 0;
2587}
2588
2589/*****************************************************************************
2590    DEVICE INTERFACE
2591*****************************************************************************/
2592
2593static DEVICE_START( vic2 )
2594{
2595   vic2_state *vic2 = get_safe_token(device);
2596   const vic2_interface *intf = (vic2_interface *)device->static_config();
2597   int width, height;
2598   int i;
2599
2600   // resolve callbacks
2601   vic2->in_lightpen_x_func.resolve(intf->in_x_cb, *device);
2602   vic2->in_lightpen_y_func.resolve(intf->in_y_cb, *device);
2603   vic2->in_lightpen_button_func.resolve(intf->in_button_cb, *device);
2604   vic2->in_dma_read_func.resolve(intf->in_dma_read_cb, *device);
2605   vic2->in_dma_read_color_func.resolve(intf->in_dma_read_color_cb, *device);
2606   vic2->out_interrupt_func.resolve(intf->out_irq_cb, *device);
2607   vic2->in_rdy_workaround_func.resolve(intf->in_rdy_cb, *device);
2608
2609   vic2->cpu = device->machine().device<cpu_device>(intf->cpu);
2610
2611   vic2->screen = device->machine().device<screen_device>(intf->screen);
2612   width = vic2->screen->width();
2613   height = vic2->screen->height();
2614
2615   vic2->bitmap = auto_bitmap_ind16_alloc(device->machine(), width, height);
2616
2617   vic2->type = intf->type;
2618
2619   // immediately call the timer to handle the first line
2620   if (vic2->type == VIC6569 || vic2->type == VIC8566)
2621      device->machine().scheduler().timer_set(downcast<cpu_device *>(vic2->cpu)->cycles_to_attotime(0), FUNC(pal_timer_callback), 0, vic2);
2622   else
2623      device->machine().scheduler().timer_set(downcast<cpu_device *>(vic2->cpu)->cycles_to_attotime(0), FUNC(ntsc_timer_callback), 0, vic2);
2624
2625   for (i = 0; i < 256; i++)
2626   {
2627      vic2->expandx[i] = 0;
2628      if (i & 1)
2629         vic2->expandx[i] |= 3;
2630      if (i & 2)
2631         vic2->expandx[i] |= 0xc;
2632      if (i & 4)
2633         vic2->expandx[i] |= 0x30;
2634      if (i & 8)
2635         vic2->expandx[i] |= 0xc0;
2636      if (i & 0x10)
2637         vic2->expandx[i] |= 0x300;
2638      if (i & 0x20)
2639         vic2->expandx[i] |= 0xc00;
2640      if (i & 0x40)
2641         vic2->expandx[i] |= 0x3000;
2642      if (i & 0x80)
2643         vic2->expandx[i] |= 0xc000;
2644   }
2645
2646   for (i = 0; i < 256; i++)
2647   {
2648      vic2->expandx_multi[i] = 0;
2649      if (i & 1)
2650         vic2->expandx_multi[i] |= 5;
2651      if (i & 2)
2652         vic2->expandx_multi[i] |= 0xa;
2653      if (i & 4)
2654         vic2->expandx_multi[i] |= 0x50;
2655      if (i & 8)
2656         vic2->expandx_multi[i] |= 0xa0;
2657      if (i & 0x10)
2658         vic2->expandx_multi[i] |= 0x500;
2659      if (i & 0x20)
2660         vic2->expandx_multi[i] |= 0xa00;
2661      if (i & 0x40)
2662         vic2->expandx_multi[i] |= 0x5000;
2663      if (i & 0x80)
2664         vic2->expandx_multi[i] |= 0xa000;
2665   }
2666
2667   device->save_item(NAME(vic2->reg));
2668
2669   device->save_item(NAME(vic2->on));
2670
2671   //device->save_item(NAME(vic2->bitmap));
2672
2673   device->save_item(NAME(vic2->chargenaddr));
2674   device->save_item(NAME(vic2->videoaddr));
2675   device->save_item(NAME(vic2->bitmapaddr));
2676
2677   device->save_item(NAME(vic2->colors));
2678   device->save_item(NAME(vic2->spritemulti));
2679
2680   device->save_item(NAME(vic2->rasterline));
2681   device->save_item(NAME(vic2->cycles_counter));
2682   device->save_item(NAME(vic2->cycle));
2683   device->save_item(NAME(vic2->raster_x));
2684   device->save_item(NAME(vic2->graphic_x));
2685
2686   device->save_item(NAME(vic2->dy_start));
2687   device->save_item(NAME(vic2->dy_stop));
2688
2689   device->save_item(NAME(vic2->draw_this_line));
2690   device->save_item(NAME(vic2->is_bad_line));
2691   device->save_item(NAME(vic2->bad_lines_enabled));
2692   device->save_item(NAME(vic2->display_state));
2693   device->save_item(NAME(vic2->char_data));
2694   device->save_item(NAME(vic2->gfx_data));
2695   device->save_item(NAME(vic2->color_data));
2696   device->save_item(NAME(vic2->last_char_data));
2697   device->save_item(NAME(vic2->matrix_line));
2698   device->save_item(NAME(vic2->color_line));
2699   device->save_item(NAME(vic2->vblanking));
2700   device->save_item(NAME(vic2->ml_index));
2701   device->save_item(NAME(vic2->rc));
2702   device->save_item(NAME(vic2->vc));
2703   device->save_item(NAME(vic2->vc_base));
2704   device->save_item(NAME(vic2->ref_cnt));
2705
2706   device->save_item(NAME(vic2->spr_coll_buf));
2707   device->save_item(NAME(vic2->fore_coll_buf));
2708   device->save_item(NAME(vic2->spr_exp_y));
2709   device->save_item(NAME(vic2->spr_dma_on));
2710   device->save_item(NAME(vic2->spr_draw));
2711   device->save_item(NAME(vic2->spr_disp_on));
2712   device->save_item(NAME(vic2->spr_ptr));
2713   device->save_item(NAME(vic2->mc_base));
2714   device->save_item(NAME(vic2->mc));
2715
2716   for (i = 0; i < 8; i++)
2717   {
2718      device->save_item(NAME(vic2->spr_data[i]), i);
2719      device->save_item(NAME(vic2->spr_draw_data[i]), i);
2720   }
2721
2722   device->save_item(NAME(vic2->border_on));
2723   device->save_item(NAME(vic2->ud_border_on));
2724   device->save_item(NAME(vic2->border_on_sample));
2725   device->save_item(NAME(vic2->border_color_sample));
2726
2727   device->save_item(NAME(vic2->first_ba_cycle));
2728   device->save_item(NAME(vic2->device_suspended));
2729}
2730
2731static DEVICE_RESET( vic2 )
2732{
2733   vic2_state *vic2 = get_safe_token(device);
2734   int i, j;
2735
2736   memset(vic2->reg, 0, ARRAY_LENGTH(vic2->reg));
2737
2738   for (i = 0; i < ARRAY_LENGTH(vic2->mc); i++)
2739      vic2->mc[i] = 63;
2740
2741   // from 0 to 311 (0 first, PAL) or from 0 to 261 (? first, NTSC 6567R56A) or from 0 to 262 (? first, NTSC 6567R8)
2742   vic2->rasterline = 0; // VIC2_LINES - 1;
2743
2744   vic2->cycles_counter = -1;
2745   vic2->cycle = 63;
2746
2747   vic2->on = 1;
2748
2749   vic2->dy_start = ROW24_YSTART;
2750   vic2->dy_stop = ROW24_YSTOP;
2751
2752   vic2->draw_this_line = 0;
2753   vic2->is_bad_line = 0;
2754   vic2->bad_lines_enabled = 0;
2755   vic2->display_state = 0;
2756   vic2->char_data = 0;
2757   vic2->gfx_data = 0;
2758   vic2->color_data = 0;
2759   vic2->last_char_data = 0;
2760   vic2->vblanking = 0;
2761   vic2->ml_index = 0;
2762   vic2->rc = 0;
2763   vic2->vc = 0;
2764   vic2->vc_base = 0;
2765   vic2->ref_cnt = 0;
2766
2767   vic2->spr_exp_y = 0;
2768   vic2->spr_dma_on = 0;
2769   vic2->spr_draw = 0;
2770   vic2->spr_disp_on = 0;
2771
2772
2773   vic2->border_on = 0;
2774   vic2->ud_border_on = 0;
2775
2776   vic2->first_ba_cycle = 0;
2777   vic2->device_suspended = 0;
2778
2779   memset(vic2->matrix_line, 0, ARRAY_LENGTH(vic2->matrix_line));
2780   memset(vic2->color_line, 0, ARRAY_LENGTH(vic2->color_line));
2781
2782   memset(vic2->spr_coll_buf, 0, ARRAY_LENGTH(vic2->spr_coll_buf));
2783   memset(vic2->fore_coll_buf, 0, ARRAY_LENGTH(vic2->fore_coll_buf));
2784   memset(vic2->border_on_sample, 0, ARRAY_LENGTH(vic2->border_on_sample));
2785   memset(vic2->border_color_sample, 0, ARRAY_LENGTH(vic2->border_color_sample));
2786
2787   for (i = 0; i < 8; i++)
2788   {
2789      vic2->spr_ptr[i] = 0;
2790      vic2->mc_base[i] = 0;
2791      vic2->mc[i] = 0;
2792      for (j = 0; j < 4; j++)
2793      {
2794         vic2->spr_draw_data[i][j] = 0;
2795         vic2->spr_data[i][j] = 0;
2796      }
2797   }
2798
2799}
2800
2801
2802const device_type VIC2 = &device_creator<vic2_device>;
2803
2804vic2_device::vic2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
2805   : device_t(mconfig, VIC2, "6567 / 6569 VIC II", tag, owner, clock)
2806{
2807   m_token = global_alloc_clear(vic2_state);
2808}
2809
2810//-------------------------------------------------
2811//  device_config_complete - perform any
2812//  operations now that the configuration is
2813//  complete
2814//-------------------------------------------------
2815
2816void vic2_device::device_config_complete()
2817{
2818}
2819
2820//-------------------------------------------------
2821//  device_start - device-specific startup
2822//-------------------------------------------------
2823
2824void vic2_device::device_start()
2825{
2826   DEVICE_START_NAME( vic2 )(this);
2827}
2828
2829//-------------------------------------------------
2830//  device_reset - device-specific reset
2831//-------------------------------------------------
2832
2833void vic2_device::device_reset()
2834{
2835   DEVICE_RESET_NAME( vic2 )(this);
2836}
2837
2838
trunk/src/mess/video/vic6567.h
r19392r19393
1/*****************************************************************************
2 *
3 * video/vic6567.h
4 *
5 ****************************************************************************/
6
7#ifndef __VIC6567_H__
8#define __VIC6567_H__
9
10#include "devcb.h"
11
12
13/***************************************************************************
14    TYPE DEFINITIONS
15***************************************************************************/
16
17enum vic2_type
18{
19   VIC6567,   // VIC II NTSC
20   VIC6569,   // VIC II PAL
21   VIC8564,   // VIC IIe NTSC
22   VIC8566   // VIC IIe PAL
23};
24
25struct vic2_interface
26{
27   const char         *screen;
28   const char         *cpu;
29
30   vic2_type type;
31
32   devcb_read8         in_x_cb;
33   devcb_read8         in_y_cb;
34   devcb_read8         in_button_cb;
35
36   devcb_read8         in_dma_read_cb;
37   devcb_read8       in_dma_read_color_cb;
38   devcb_write_line   out_irq_cb;
39
40   devcb_read8         in_rdy_cb;
41};
42
43/***************************************************************************
44    CONSTANTS
45***************************************************************************/
46
47#define VIC6566_CLOCK         (XTAL_8MHz / 8) // 1000000
48#define VIC6567R56A_CLOCK      (XTAL_8MHz / 8) // 1000000
49#define VIC6567_CLOCK         (XTAL_14_31818MHz / 14) // 1022727
50#define VIC6569_CLOCK         (XTAL_17_734472MHz / 18) // 985248
51
52#define VIC6566_DOTCLOCK      (VIC6566_CLOCK * 8) // 8000000
53#define VIC6567R56A_DOTCLOCK   (VIC6567R56A_CLOCK * 8) // 8000000
54#define VIC6567_DOTCLOCK      (VIC6567_CLOCK * 8) // 8181818
55#define VIC6569_DOTCLOCK      (VIC6569_CLOCK * 8) // 7881988
56
57#define VIC6567_CYCLESPERLINE   65
58#define VIC6569_CYCLESPERLINE   63
59
60#define VIC6567_LINES      263
61#define VIC6569_LINES      312
62
63#define VIC6566_VRETRACERATE      ((float)VIC6566_CLOCK / 262 / 64)
64#define VIC6567R56A_VRETRACERATE   ((float)VIC6567R56A_CLOCK / 262 / 64)
65#define VIC6567_VRETRACERATE      ((float)VIC6567_CLOCK / 263 / 65)
66#define VIC6569_VRETRACERATE      ((float)VIC6569_CLOCK / 312 / 63)
67
68#define VIC6566_HRETRACERATE   (VIC6566_CLOCK / VIC6566_CYCLESPERLINE)
69#define VIC6567_HRETRACERATE   (VIC6567_CLOCK / VIC6567_CYCLESPERLINE)
70#define VIC6569_HRETRACERATE   (VIC6569_CLOCK / VIC6569_CYCLESPERLINE)
71
72#define VIC2_HSIZE      320
73#define VIC2_VSIZE      200
74
75#define VIC6567_VISIBLELINES   235
76#define VIC6569_VISIBLELINES   284
77
78#define VIC6567_FIRST_DMA_LINE   0x30
79#define VIC6569_FIRST_DMA_LINE   0x30
80
81#define VIC6567_LAST_DMA_LINE   0xf7
82#define VIC6569_LAST_DMA_LINE   0xf7
83
84#define VIC6567_FIRST_DISP_LINE   0x29
85#define VIC6569_FIRST_DISP_LINE   0x10
86
87#define VIC6567_LAST_DISP_LINE   (VIC6567_FIRST_DISP_LINE + VIC6567_VISIBLELINES - 1)
88#define VIC6569_LAST_DISP_LINE   (VIC6569_FIRST_DISP_LINE + VIC6569_VISIBLELINES - 1)
89
90#define VIC6567_RASTER_2_EMU(a) ((a >= VIC6567_FIRST_DISP_LINE) ? (a - VIC6567_FIRST_DISP_LINE) : (a + 222))
91#define VIC6569_RASTER_2_EMU(a) (a - VIC6569_FIRST_DISP_LINE)
92
93#define VIC6567_FIRSTCOLUMN   50
94#define VIC6569_FIRSTCOLUMN   50
95
96#define VIC6567_VISIBLECOLUMNS   418
97#define VIC6569_VISIBLECOLUMNS   403
98
99#define VIC6567_X_2_EMU(a)   (a)
100#define VIC6569_X_2_EMU(a)   (a)
101
102#define VIC6567_STARTVISIBLELINES ((VIC6567_LINES - VIC6567_VISIBLELINES)/2)
103#define VIC6569_STARTVISIBLELINES 16 /* ((VIC6569_LINES - VIC6569_VISIBLELINES)/2) */
104
105#define VIC6567_FIRSTRASTERLINE 34
106#define VIC6569_FIRSTRASTERLINE 0
107
108#define VIC6567_COLUMNS 512
109#define VIC6569_COLUMNS 504
110
111
112#define VIC6567_STARTVISIBLECOLUMNS ((VIC6567_COLUMNS - VIC6567_VISIBLECOLUMNS)/2)
113#define VIC6569_STARTVISIBLECOLUMNS ((VIC6569_COLUMNS - VIC6569_VISIBLECOLUMNS)/2)
114
115#define VIC6567_FIRSTRASTERCOLUMNS 412
116#define VIC6569_FIRSTRASTERCOLUMNS 404
117
118#define VIC6569_FIRST_X 0x194
119#define VIC6567_FIRST_X 0x19c
120
121#define VIC6569_FIRST_VISIBLE_X 0x1e0
122#define VIC6567_FIRST_VISIBLE_X 0x1e8
123
124#define VIC6569_MAX_X 0x1f7
125#define VIC6567_MAX_X 0x1ff
126
127#define VIC6569_LAST_VISIBLE_X 0x17c
128#define VIC6567_LAST_VISIBLE_X 0x184
129
130#define VIC6569_LAST_X 0x193
131#define VIC6567_LAST_X 0x19b
132
133
134/***************************************************************************
135    DEVICE CONFIGURATION MACROS
136***************************************************************************/
137
138class vic2_device : public device_t
139{
140public:
141   vic2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
142   ~vic2_device() { global_free(m_token); }
143
144   // access to legacy token
145   void *token() const { assert(m_token != NULL); return m_token; }
146protected:
147   // device-level overrides
148   virtual void device_config_complete();
149   virtual void device_start();
150   virtual void device_reset();
151private:
152   // internal state
153   void *m_token;
154};
155
156extern const device_type VIC2;
157
158
159#define MCFG_VIC2_ADD(_tag, _interface) \
160   MCFG_DEVICE_ADD(_tag, VIC2, 0) \
161   MCFG_DEVICE_CONFIG(_interface)
162
163
164/*----------- defined in video/vic6567.c -----------*/
165
166DECLARE_WRITE8_DEVICE_HANDLER ( vic2_port_w );
167DECLARE_READ8_DEVICE_HANDLER ( vic2_port_r );
168
169int vic2e_k0_r(device_t *device);
170int vic2e_k1_r(device_t *device);
171int vic2e_k2_r(device_t *device);
172
173void vic2_raster_interrupt_gen( device_t *device );
174UINT32 vic2_video_update( device_t *device, bitmap_ind16 &bitmap, const rectangle &cliprect );
175
176
177extern void vic2_set_rastering(device_t *device, int onoff);
178extern void vic2_lightpen_write(device_t *device, int level);
179
180
181
182#endif /* __VIC6567_H__ */
trunk/src/mess/mess.mak
r19392r19393
933933   $(MESS_MACHINE)/mos8722.o   \
934934   $(MESS_MACHINE)/mos8726.o   \
935935   $(MESS_MACHINE)/c2n.o      \
936   $(MESS_VIDEO)/vdc8563.o      \
937   $(MESS_VIDEO)/vic6567.o      \
938936   $(MESS_VIDEO)/vic4567.o      \
939937   $(MESS_VIDEO)/mos6566.o      \
940938   $(MESS_DRIVERS)/c900.o      \
r19392r19393
12841282   $(MESS_MACHINE)/abc99.o      \
12851283   $(MESS_MACHINE)/lux10828.o   \
12861284   $(MESS_MACHINE)/lux21046.o   \
1287   $(MESS_MACHINE)/abc830.o   \
12881285   $(MESS_MACHINE)/abc890.o   \
12891286   $(MESS_DRIVERS)/abc1600.o   \
12901287   $(MESS_MACHINE)/abc1600_bus.o   \

Previous 199869 Revisions Next


© 1997-2024 The MAME Team