Previous 15994 Revisions Next

r7629 Wednesday 24th March, 2010 at 09:44:39 UTC by Dirk Best
[SAMCOUPE] Rewrote video rendering to render partial scanlines
[docs]messnew.txt
[src/mess/drivers]samcoupe.c
[src/mess/includes]samcoupe.h
[src/mess/machine]samcoupe.c
[src/mess/video]samcoupe.c

src/mess/video/samcoupe.c
r7628r7629
11/***************************************************************************
22
3 SAM Coupe Driver - Written By Lee Hammerton
3    SAM Coupe
44
5  Functions to emulate the video hardware of the coupe.
5    Functions to emulate the video hardware
66
7 At present these are not done using the mame driver standard, they are
8 simply plot pixelled.. I will fix this in a future version.
9
107***************************************************************************/
118
129#include "emu.h"
1310#include "includes/samcoupe.h"
1411
1512
13/***************************************************************************
14    MACROS
15***************************************************************************/
16
17/* border color from border register */
1618#define BORDER_COLOR(x)   ((x & 0x20) >> 2 | (x & 0x07))
1719
18static void draw_left_border(running_device *screen, bitmap_t *bitmap, int y)
19{
20   coupe_asic *asic = (coupe_asic *)screen->machine->driver_data;
20/* foreground and background color from attribute byte in mode 1 and 2 */
21#define ATTR_BG(x)      ((x >> 3) & 0x07)
22#define ATTR_FG(x)      (((x >> 3) & 0x08) | (x & 0x07))
2123
22   for (int x = 0; x < SAM_BORDER_LEFT; x++)
23      *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, x) = asic->clut[BORDER_COLOR(asic->border)];
24}
2524
26static void draw_right_border(running_device *screen, bitmap_t *bitmap, int y)
27{
28   coupe_asic *asic = (coupe_asic *)screen->machine->driver_data;
25/***************************************************************************
26    IMPLEMENTATION
27***************************************************************************/
2928
30   for (int x = SAM_BORDER_LEFT + SAM_SCREEN_WIDTH; x < SAM_BORDER_LEFT + SAM_SCREEN_WIDTH + SAM_BORDER_RIGHT; x++)
31      *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, x) = asic->clut[BORDER_COLOR(asic->border)];
32}
33
34static void draw_mode4_line(running_device *screen, bitmap_t *bitmap, int y)
29static void draw_mode4_line(running_machine *machine, int y, int hpos)
3530{
36   coupe_asic *asic = (coupe_asic *)screen->machine->driver_data;
31   coupe_asic *asic = (coupe_asic *)machine->driver_data;
3732
3833   /* get start address */
39   UINT8 *vram = screen->machine->generic.videoram.u8 + (y * 128);
34   UINT8 *vram = machine->generic.videoram.u8 + ((y - SAM_BORDER_TOP) * 128) + ((hpos - SAM_BORDER_LEFT) / 4);
4035
41   for (int x = 0; x < SAM_SCREEN_WIDTH/4; x++)
36   for (int i = 0; i < (SAM_BLOCK*2)/4; i++)
4237   {
4338      /* draw 2 pixels (doublewidth) */
44      *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, SAM_BORDER_LEFT + x * 4 + 0) = asic->clut[(*vram >> 4) & 0x0f];
45      *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, SAM_BORDER_LEFT + x * 4 + 1) = asic->clut[(*vram >> 4) & 0x0f];
46      *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, SAM_BORDER_LEFT + x * 4 + 2) = asic->clut[(*vram >> 0) & 0x0f];
47      *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, SAM_BORDER_LEFT + x * 4 + 3) = asic->clut[(*vram >> 0) & 0x0f];
39      *BITMAP_ADDR16(machine->generic.tmpbitmap, y, hpos + i * 4 + 0) = asic->clut[(*vram >> 4) & 0x0f];
40      *BITMAP_ADDR16(machine->generic.tmpbitmap, y, hpos + i * 4 + 1) = asic->clut[(*vram >> 4) & 0x0f];
41      *BITMAP_ADDR16(machine->generic.tmpbitmap, y, hpos + i * 4 + 2) = asic->clut[(*vram >> 0) & 0x0f];
42      *BITMAP_ADDR16(machine->generic.tmpbitmap, y, hpos + i * 4 + 3) = asic->clut[(*vram >> 0) & 0x0f];
4843
4944      /* move to next address */
5045      vram++;
46
47      /* attribute register contains the third displayed byte */
48      if (i == 2)
49         asic->attribute = *vram;
5150   }
5251}
5352
54static void draw_mode3_line(running_device *screen, bitmap_t *bitmap, int y)
53static void draw_mode3_line(running_machine *machine, int y, int hpos)
5554{
56   coupe_asic *asic = (coupe_asic *)screen->machine->driver_data;
55   coupe_asic *asic = (coupe_asic *)machine->driver_data;
5756
5857   /* get start address */
59   UINT8 *vram = screen->machine->generic.videoram.u8 + (y * 128);
58   UINT8 *vram = machine->generic.videoram.u8 + ((y - SAM_BORDER_TOP) * 128) + ((hpos - SAM_BORDER_LEFT) / 4);
6059
61   for (int x = 0; x < 512/4; x++)
60   for (int i = 0; i < (SAM_BLOCK*2)/4; i++)
6261   {
6362      /* draw 4 pixels */
64      *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, SAM_BORDER_LEFT + x * 4 + 0) = asic->clut[(*vram >> 6) & 0x03];
65      *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, SAM_BORDER_LEFT + x * 4 + 1) = asic->clut[(*vram >> 4) & 0x03];
66      *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, SAM_BORDER_LEFT + x * 4 + 2) = asic->clut[(*vram >> 2) & 0x03];
67      *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, SAM_BORDER_LEFT + x * 4 + 3) = asic->clut[(*vram >> 0) & 0x03];
63      *BITMAP_ADDR16(machine->generic.tmpbitmap, y, hpos + i * 4 + 0) = asic->clut[(*vram >> 6) & 0x03];
64      *BITMAP_ADDR16(machine->generic.tmpbitmap, y, hpos + i * 4 + 1) = asic->clut[(*vram >> 4) & 0x03];
65      *BITMAP_ADDR16(machine->generic.tmpbitmap, y, hpos + i * 4 + 2) = asic->clut[(*vram >> 2) & 0x03];
66      *BITMAP_ADDR16(machine->generic.tmpbitmap, y, hpos + i * 4 + 3) = asic->clut[(*vram >> 0) & 0x03];
6867
6968      /* move to next address */
7069      vram++;
70
71      /* attribute register contains the third displayed byte */
72      if (i == 2)
73         asic->attribute = *vram;
7174   }
7275}
7376
74static void draw_mode2_line(running_device *screen, bitmap_t *bitmap, int y)
77static void draw_mode12_block(coupe_asic *asic, bitmap_t *bitmap, int vpos, int hpos, UINT8 mask)
7578{
76   coupe_asic *asic = (coupe_asic *)screen->machine->driver_data;
77   int b, scrx = 0;
78   UINT16 ink = 127, pap = 0;
79   UINT8 *attr = screen->machine->generic.videoram.u8 + 32*192 + y*32;
80   int x;
79   /* extract colors from attribute */
80   UINT8 ink = asic->clut[ATTR_FG(asic->attribute)];
81   UINT8 pap = asic->clut[ATTR_BG(asic->attribute)];
8182
82   for (x = 0; x < 256/8; x++)
83   /* draw block of 8 pixels (doubled to 16) */
84   for (int i = 0; i < SAM_BLOCK; i++)
8385   {
84      UINT8 tmp = screen->machine->generic.videoram.u8[x + (y*32)];
85
86#ifndef MONO
87      ink = asic->clut[(*attr) & 0x07];
88      pap = asic->clut[((*attr) >> 3) & 0x07];
89#endif
90
91      attr++;
92
93      for (b = 0x80; b!= 0; b >>= 1)
94      {
95         *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, SAM_BORDER_LEFT + scrx++) = (tmp & b) ? ink : pap;
96         *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, SAM_BORDER_LEFT + scrx++) = (tmp & b) ? ink : pap;
97      }
86      *BITMAP_ADDR16(bitmap, vpos, hpos + i*2 + 0) = BIT(mask, 7 - i) ? ink : pap;
87      *BITMAP_ADDR16(bitmap, vpos, hpos + i*2 + 1) = BIT(mask, 7 - i) ? ink : pap;
9888   }
9989}
10090
101static void draw_mode1_line(running_device *screen, bitmap_t *bitmap, int y)
91static void draw_mode2_line(running_machine *machine, int y, int hpos)
10292{
103   coupe_asic *asic = (coupe_asic *)screen->machine->driver_data;
104   int block, x = 0;
93   coupe_asic *asic = (coupe_asic *)machine->driver_data;
10594
106   /* get base address of attribute and data values */
107   UINT8 *attr = screen->machine->generic.videoram.u8 + 32*192 + ((y & 0xf8) << 2);
108   UINT8 *data = screen->machine->generic.videoram.u8 + (((y & 0xc0) << 5) | ((y & 0x07) << 8) | ((y & 0x38) << 2));
95   int cell = (y - SAM_BORDER_TOP) * 32 + (hpos - SAM_BORDER_LEFT) / SAM_BLOCK / 2;
10996
110   /* loop over all 32 blocks */
111   for (block = 0; block < 32; block++)
112   {
113        int bit;
97   UINT8 mask = machine->generic.videoram.u8[cell];
98   asic->attribute = machine->generic.videoram.u8[cell + 0x2000];
11499
115        /* get current colors from attribute byte */
116        UINT8 ink = asic->clut[(*attr & 0x07) + ((*attr >> 3) & 0x08)];
117        UINT8 paper = asic->clut[(*attr >> 3) & 0x0f];
100   draw_mode12_block(asic, machine->generic.tmpbitmap, y, hpos, mask);
101}
118102
119        /* draw a block (8 pixels, doubled) */
120      for (bit = 0x80; bit != 0; bit >>= 1)
121      {
122         *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, SAM_BORDER_LEFT + x++) = (*data & bit) ? ink : paper;
123         *BITMAP_ADDR16(bitmap, SAM_BORDER_TOP + y, SAM_BORDER_LEFT + x++) = (*data & bit) ? ink : paper;
124      }
103static void draw_mode1_line(running_machine *machine, int y, int hpos)
104{
105   coupe_asic *asic = (coupe_asic *)machine->driver_data;
125106
126      /* save current attribute */
127      asic->attribute = *attr;
107   UINT8 mask = machine->generic.videoram.u8[((((y - SAM_BORDER_TOP) & 0xc0) << 5) | (((y - SAM_BORDER_TOP) & 0x07) << 8) | (((y - SAM_BORDER_TOP) & 0x38) << 2)) + (hpos - SAM_BORDER_LEFT) / SAM_BLOCK / 2];
108   asic->attribute = machine->generic.videoram.u8[32*192 + (((y - SAM_BORDER_TOP) & 0xf8) << 2) + (hpos - SAM_BORDER_LEFT) / SAM_BLOCK / 2];
128109
129      /* move to the next block of values */
130      attr++;
131      data++;
132   }
110   draw_mode12_block(asic, machine->generic.tmpbitmap, y, hpos, mask);
133111}
134112
135VIDEO_UPDATE( samcoupe )
113TIMER_CALLBACK( sam_video_update_callback )
136114{
137   int scanline = video_screen_get_vpos(screen);
138   coupe_asic *asic = (coupe_asic *)screen->machine->driver_data;
115   coupe_asic *asic = (coupe_asic *)machine->driver_data;
139116
140   /* border area? */
141   if (scanline < SAM_BORDER_TOP || scanline >= SAM_SCREEN_HEIGHT + SAM_BORDER_BOTTOM)
117   int vpos = video_screen_get_vpos(machine->primary_screen);
118   int hpos = video_screen_get_hpos(machine->primary_screen);
119
120   int next_vpos = vpos;
121   int next_hpos = hpos + SAM_BLOCK*2;
122
123   /* next scanline? */
124   if (next_hpos >= SAM_BORDER_LEFT + SAM_SCREEN_WIDTH + SAM_BORDER_RIGHT)
142125   {
143      plot_box(bitmap, 0, scanline, SAM_BORDER_LEFT + SAM_SCREEN_WIDTH + SAM_BORDER_RIGHT, 1, asic->clut[BORDER_COLOR(asic->border)]);
126      next_vpos = (vpos + 1) % (SAM_BORDER_TOP + SAM_SCREEN_HEIGHT + SAM_BORDER_BOTTOM);
127      next_hpos = 0;
144128   }
129
130   /* display disabled? (only in mode 3 or 4) */
131   if (BIT(asic->vmpr, 6) && BIT(asic->border, 7))
132   {
133      plot_box(machine->generic.tmpbitmap, hpos, vpos, SAM_BLOCK*2, 1, 0);
134   }
145135   else
146136   {
147      /* adjust for border */
148      scanline -= SAM_BORDER_TOP;
149
150      /* line interrupt? */
151      if (asic->line_int == scanline)
152         samcoupe_irq(screen->machine->firstcpu, SAM_LINE_INT);
153
154      /* display disabled? (only in mode 3 or 4) */
155      if ((asic->vmpr & 0x40) && (asic->border & 0x80))
137      /* border area? */
138      if (vpos < SAM_BORDER_TOP || vpos >= SAM_BORDER_TOP + SAM_SCREEN_HEIGHT || hpos < SAM_BORDER_LEFT || hpos >= SAM_BORDER_LEFT + SAM_SCREEN_WIDTH)
156139      {
157         /* display is disabled, draw a black screen */
158         bitmap_fill(bitmap, cliprect, 0);
140         asic->attribute = 0xff;
141         plot_box(machine->generic.tmpbitmap, hpos, vpos, SAM_BLOCK*2, 1, asic->clut[BORDER_COLOR(asic->border)]);
159142      }
160143      else
161144      {
162         /* display enabled, start drawing border */
163         draw_left_border(screen, bitmap, scanline);
164
165         /* draw line in the right screen mode */
145         /* main screen area */
166146         switch ((asic->vmpr & 0x60) >> 5)
167147         {
168         case 0:   draw_mode1_line(screen, bitmap, scanline); break;
169         case 1:   draw_mode2_line(screen, bitmap, scanline); break;
170         case 2:   draw_mode3_line(screen, bitmap, scanline); break;
171         case 3:   draw_mode4_line(screen, bitmap, scanline); break;
148         case 0:   draw_mode1_line(machine, vpos, hpos); break;
149         case 1:   draw_mode2_line(machine, vpos, hpos); break;
150         case 2:   draw_mode3_line(machine, vpos, hpos); break;
151         case 3:   draw_mode4_line(machine, vpos, hpos); break;
172152         }
173
174         /* rest of the border */
175         draw_right_border(screen, bitmap, scanline);
176153      }
177   //printf("videomode: %u\n", (asic->vmpr & 0x60) >> 5);
178154   }
179155
180   return 0;
156   /* do we need to trigger the scanline interrupt (interrupt happens at the start of the right border before the specified line)? */
157   if (asic->line_int < SAM_SCREEN_HEIGHT && hpos == SAM_BORDER_LEFT + SAM_SCREEN_WIDTH && vpos == (asic->line_int + SAM_BORDER_TOP - 1))
158      samcoupe_irq(machine->firstcpu, SAM_LINE_INT);
159
160   /* schedule next update */
161   timer_adjust_oneshot(asic->video_update_timer, video_screen_get_time_until_pos(machine->primary_screen, next_vpos, next_hpos), 0);
181162}
src/mess/includes/samcoupe.h
r7628r7629
1212#define SAMCOUPE_H_
1313
1414/* screen dimensions */
15#define SAM_TOTAL_WIDTH      768
15#define SAM_BLOCK         8
16
17#define SAM_TOTAL_WIDTH      SAM_BLOCK*96
1618#define SAM_TOTAL_HEIGHT   312
17#define SAM_SCREEN_WIDTH   512
19#define SAM_SCREEN_WIDTH   SAM_BLOCK*64
1820#define SAM_SCREEN_HEIGHT   192
19#define SAM_BORDER_LEFT      32
20#define SAM_BORDER_RIGHT   32
21#define SAM_BORDER_TOP      32
22#define SAM_BORDER_BOTTOM   32
21#define SAM_BORDER_LEFT      SAM_BLOCK*4
22#define SAM_BORDER_RIGHT   SAM_BLOCK*4
23#define SAM_BORDER_TOP      37
24#define SAM_BORDER_BOTTOM   46
2325
2426/* interrupt sources */
2527#define SAM_LINE_INT    0x01
r7628r7629
3638
3739   coupe_asic(running_machine &machine) { }
3840
41   emu_timer *video_update_timer;
42
3943   UINT8 lmpr, hmpr, vmpr; /* memory pages */
4044   UINT8 lext, hext;       /* extended memory page */
4145   UINT8 border;           /* border */
r7628r7629
7175
7276/*----------- defined in video/samcoupe.c -----------*/
7377
74VIDEO_UPDATE( samcoupe );
78TIMER_CALLBACK( sam_video_update_callback );
7579
7680
7781#endif /* SAMCOUPE_H_ */
src/mess/machine/samcoupe.c
r7628r7629
230230{
231231   coupe_asic *asic = (coupe_asic *)machine->driver_data;
232232   asic->mouse_reset = timer_alloc(machine, samcoupe_mouse_reset, 0);
233
234   /* schedule our video updates */
235   asic->video_update_timer = timer_alloc(machine, sam_video_update_callback, NULL);
236   timer_adjust_oneshot(asic->video_update_timer, video_screen_get_time_until_pos(machine->primary_screen, 0, 0), 0);
233237}
234238
235239/***************************************************************************
src/mess/drivers/samcoupe.c
r7628r7629
107107      int vpos = video_screen_get_vpos(scr);
108108
109109      /* return the current screen line or 192 for the border area */
110      if (vpos < SAM_BORDER_TOP || vpos >= SAM_SCREEN_HEIGHT + SAM_BORDER_BOTTOM)
110      if (vpos < SAM_BORDER_TOP || vpos >= SAM_BORDER_TOP + SAM_SCREEN_HEIGHT)
111111         data = 192;
112112      else
113113         data = vpos - SAM_BORDER_TOP;
r7628r7629
266266static READ8_HANDLER( samcoupe_attributes_r )
267267{
268268   coupe_asic *asic = (coupe_asic *)space->machine->driver_data;
269
270   if (video_screen_get_vblank(space->machine->primary_screen))
271      return 0xff; /* border areas return 0xff */
272   else
273      return asic->attribute;
269   return asic->attribute;
274270}
275271
276272static READ8_DEVICE_HANDLER( samcoupe_lpt1_busy_r )
r7628r7629
485481*/
486482static PALETTE_INIT( samcoupe )
487483{
488   int i;
489
490   for (i = 0; i < 128; i++)
484   for (int i = 0; i < 128; i++)
491485   {
492      UINT8 r = 0, g = 0, b = 0;
486      UINT8 b = BIT(i, 0) * 2 + BIT(i, 4) * 4 + BIT(i, 3);
487      UINT8 r = BIT(i, 1) * 2 + BIT(i, 5) * 4 + BIT(i, 3);
488      UINT8 g = BIT(i, 2) * 2 + BIT(i, 6) * 4 + BIT(i, 3);
493489
494      /* colors */
495      if (i & 0x01) b += 2;
496      if (i & 0x02) r += 2;
497      if (i & 0x04) g += 2;
498      if (i & 0x10) b += 4;
499      if (i & 0x20) r += 4;
500      if (i & 0x40) g += 4;
501
502      /* intensity bit */
503      if (i & 0x08)
504      {
505         r += 1;
506         g += 1;
507         b += 1;
508      }
509
510490      palette_set_color(machine, i, MAKE_RGB(r, g, b));
511491   }
512492
r7628r7629
594574   MDRV_PALETTE_LENGTH(128)
595575   MDRV_PALETTE_INIT(samcoupe)
596576
597   MDRV_VIDEO_UPDATE(samcoupe)
598   MDRV_VIDEO_ATTRIBUTES(VIDEO_UPDATE_SCANLINE | VIDEO_ALWAYS_UPDATE)
577   MDRV_VIDEO_START(generic_bitmapped)
578   MDRV_VIDEO_UPDATE(generic_bitmapped)
599579
600580   /* devices */
601581   MDRV_CENTRONICS_ADD("lpt1", standard_centronics)
docs/messnew.txt
r7628r7629
3232
3333- [SAMCOUPE] Added border rendering support.  [Dirk Best]
3434
35- [SAMCOUPE] Rewrote video rendering to render partial scanlines.  [Dirk Best]
36
3537- [TANDY2K] Implemented DMA mux register. [Curt Coder]
3638
3739- [TI99] Cleanups.  [Michael Zapf]

Previous 15994 Revisions Next


© 1998-2018 The MESS Team