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