1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4
5 Videa Gridlee hardware
6
7 driver by Aaron Giles
8
9 Based on the Bally/Sente SAC system
10
11 ***************************************************************************/
12
13 #include "emu.h"
14 #include "includes/gridlee.h"
15
16
17 /*************************************
18 *
19 * Color PROM conversion
20 *
21 *************************************/
22
gridlee_palette(palette_device & palette) const23 void gridlee_state::gridlee_palette(palette_device &palette) const
24 {
25 const uint8_t *color_prom = memregion("proms")->base();
26
27 for (int i = 0; i < palette.entries(); i++)
28 {
29 palette.set_pen_color(i, pal4bit(color_prom[0x0000]), pal4bit(color_prom[0x0800]), pal4bit(color_prom[0x1000]));
30 color_prom++;
31 }
32 }
33
34
35
36 /*************************************
37 *
38 * Video system restart
39 *
40 *************************************/
41
expand_pixels()42 void gridlee_state::expand_pixels()
43 {
44 for (int offset = 0; offset < 0x77ff; offset++)
45 {
46 m_local_videoram[offset * 2 + 0] = m_videoram[offset] >> 4;
47 m_local_videoram[offset * 2 + 1] = m_videoram[offset] & 15;
48 }
49 }
50
51
52
53 /*************************************
54 *
55 * Video system start
56 *
57 *************************************/
58
video_start()59 void gridlee_state::video_start()
60 {
61 /* allocate a local copy of video RAM */
62 m_local_videoram = make_unique_clear<uint8_t[]>(256 * 256);
63
64 /* reset the palette */
65 m_palettebank_vis = 0;
66
67 save_pointer(NAME(m_local_videoram), 256 * 256);
68 save_item(NAME(m_cocktail_flip));
69 save_item(NAME(m_palettebank_vis));
70 machine().save().register_postload(save_prepost_delegate(FUNC(gridlee_state::expand_pixels), this));
71 }
72
73
74
75 /*************************************
76 *
77 * Cocktail flip
78 *
79 *************************************/
80
WRITE_LINE_MEMBER(gridlee_state::cocktail_flip_w)81 WRITE_LINE_MEMBER(gridlee_state::cocktail_flip_w)
82 {
83 m_cocktail_flip = state;
84 }
85
86
87
88 /*************************************
89 *
90 * Video RAM write
91 *
92 *************************************/
93
gridlee_videoram_w(offs_t offset,uint8_t data)94 void gridlee_state::gridlee_videoram_w(offs_t offset, uint8_t data)
95 {
96 m_videoram[offset] = data;
97
98 /* expand the two pixel values into two bytes */
99 m_local_videoram[offset * 2 + 0] = data >> 4;
100 m_local_videoram[offset * 2 + 1] = data & 15;
101 }
102
103
104
105 /*************************************
106 *
107 * Palette banking
108 *
109 *************************************/
110
gridlee_palette_select_w(uint8_t data)111 void gridlee_state::gridlee_palette_select_w(uint8_t data)
112 {
113 /* update the scanline palette */
114 m_screen->update_partial(m_screen->vpos() - 1 + GRIDLEE_VBEND);
115 m_palettebank_vis = data & 0x3f;
116 }
117
118
119
120 /*************************************
121 *
122 * Main screen refresh
123 *
124 *************************************/
125
126 /* all the GRIDLEE_VBEND adjustments are needed because the hardware has a separate counting chain
127 to address the video memory instead of using the video chain directly */
128
screen_update_gridlee(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)129 uint32_t gridlee_state::screen_update_gridlee(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
130 {
131 pen_t const *const pens = &m_palette->pen(m_palettebank_vis * 32);
132
133 /* draw scanlines from the VRAM directly */
134 for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
135 {
136 /* non-flipped: draw directly from the bitmap */
137 if (!m_cocktail_flip)
138 draw_scanline8(bitmap, 0, y, 256, &m_local_videoram[(y - GRIDLEE_VBEND) * 256], pens + 16);
139
140 /* flipped: x-flip the scanline into a temp buffer and draw that */
141 else
142 {
143 int srcy = GRIDLEE_VBSTART - 1 - y;
144 uint8_t temp[256];
145
146 for (int xx = 0; xx < 256; xx++)
147 temp[xx] = m_local_videoram[srcy * 256 + 255 - xx];
148 draw_scanline8(bitmap, 0, y, 256, temp, pens + 16);
149 }
150 }
151
152 /* draw the sprite images */
153 uint8_t const *const gfx = memregion("gfx1")->base();
154 for (int i = 0; i < 32; i++)
155 {
156 const uint8_t *sprite = m_spriteram + i * 4;
157 int image = sprite[0];
158 int ypos = sprite[2] + 17 + GRIDLEE_VBEND;
159 int xpos = sprite[3];
160
161 /* get a pointer to the source image */
162 const uint8_t *src = &gfx[64 * image];
163
164 /* loop over y */
165 for (int y = 0; y < 16; y++, ypos = (ypos + 1) & 255)
166 {
167 int currxor = 0;
168
169 /* adjust for flip */
170 if (m_cocktail_flip)
171 {
172 ypos = 271 - ypos;
173 currxor = 0xff;
174 }
175
176 if (ypos >= (16 + GRIDLEE_VBEND) && ypos >= cliprect.min_y && ypos <= cliprect.max_y)
177 {
178 int currx = xpos;
179
180 /* loop over x */
181 for (int x = 0; x < 4; x++)
182 {
183 int ipixel = *src++;
184 int left = ipixel >> 4;
185 int right = ipixel & 0x0f;
186
187 /* left pixel */
188 if (left && currx >= 0 && currx < 256)
189 bitmap.pix(ypos, currx ^ currxor) = pens[left];
190 currx++;
191
192 /* right pixel */
193 if (right && currx >= 0 && currx < 256)
194 bitmap.pix(ypos, currx ^ currxor) = pens[right];
195 currx++;
196 }
197 }
198 else
199 src += 4;
200
201 /* de-adjust for flip */
202 if (m_cocktail_flip)
203 ypos = 271 - ypos;
204 }
205 }
206 return 0;
207 }
208