1 /***************************************************************************
2 
3   vidhrdw.c
4 
5   Functions to emulate the video hardware of the machine.
6 
7 ***************************************************************************/
8 
9 #include "driver.h"
10 #include "vidhrdw/generic.h"
11 
12 
13 /* from sndhrdw/pleiads.c */
14 WRITE_HANDLER( pleiads_sound_control_c_w );
15 
16 unsigned char *naughtyb_videoram2;
17 
18 int videoreg;
19 
20 /* use these to draw charset B */
21 unsigned char *naughtyb_scrollreg;
22 
23 /* use this to select palette */
24 static unsigned char palreg;
25 
26 /* used in Naughty Boy to select video bank */
27 static int bankreg;
28 
29 
30 static struct rectangle scrollvisiblearea =
31 {
32 	2*8, 34*8-1,
33 	0*8, 28*8-1
34 };
35 
36 static struct rectangle leftvisiblearea =
37 {
38 	0*8, 2*8-1,
39 	0*8, 28*8-1
40 };
41 
42 static struct rectangle rightvisiblearea =
43 {
44 	34*8, 36*8-1,
45 	0*8, 28*8-1
46 };
47 
48 
49 
50 /***************************************************************************
51 
52   Convert the color PROMs into a more useable format.
53 
54   Naughty Boy has two 256x4 palette PROMs, one containing the high bits and
55   the other the low bits (2x2x2 color space).
56   The palette PROMs are connected to the RGB output this way:
57 
58   bit 3 --
59         -- 270 ohm resistor  -- GREEN
60         -- 270 ohm resistor  -- BLUE
61   bit 0 -- 270 ohm resistor  -- RED
62 
63   bit 3 --
64         -- GREEN
65         -- BLUE
66   bit 0 -- RED
67 
68   plus 270 ohm pullup and pulldown resistors on all lines
69 
70 ***************************************************************************/
naughtyb_vh_convert_color_prom(unsigned char * palette,unsigned short * colortable,const unsigned char * color_prom)71 void naughtyb_vh_convert_color_prom(unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom)
72 {
73 	int i;
74 	#define TOTAL_COLORS(gfxn) (Machine->gfx[gfxn]->total_colors * Machine->gfx[gfxn]->color_granularity)
75 	#define COLOR(gfxn,offs) (colortable[Machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs])
76 
77 
78 	for (i = 0;i < Machine->drv->total_colors;i++)
79 	{
80 		int bit0,bit1;
81 
82 
83 		bit0 = (color_prom[0] >> 0) & 0x01;
84 		bit1 = (color_prom[Machine->drv->total_colors] >> 0) & 0x01;
85 		*(palette++) = 0x55 * bit0 + 0xaa * bit1;
86 		bit0 = (color_prom[0] >> 2) & 0x01;
87 		bit1 = (color_prom[Machine->drv->total_colors] >> 2) & 0x01;
88 		*(palette++) = 0x55 * bit0 + 0xaa * bit1;
89 		bit0 = (color_prom[0] >> 1) & 0x01;
90 		bit1 = (color_prom[Machine->drv->total_colors] >> 1) & 0x01;
91 		*(palette++) = 0x55 * bit0 + 0xaa * bit1;
92 
93 		color_prom++;
94 	}
95 
96 	/* first bank of characters use colors 0-31, 64-95, 128-159 and 192-223 */
97 	for (i = 0;i < 8;i++)
98 	{
99 		int j;
100 
101 
102 		for (j = 0;j < 4;j++)
103 		{
104 			COLOR(0,4*i + j*4*8) = i + j*64;
105 			COLOR(0,4*i + j*4*8 + 1) = 8 + i + j*64;
106 			COLOR(0,4*i + j*4*8 + 2) = 2*8 + i + j*64;
107 			COLOR(0,4*i + j*4*8 + 3) = 3*8 + i + j*64;
108 		}
109 	}
110 
111 	/* second bank of characters use colors 32-63, 96-127, 160-191 and 224-255 */
112 	for (i = 0;i < 8;i++)
113 	{
114 		int j;
115 
116 
117 		for (j = 0;j < 4;j++)
118 		{
119 			COLOR(1,4*i + j*4*8) = i + 32 + j*64;
120 			COLOR(1,4*i + j*4*8 + 1) = 8 + i + 32 + j*64;
121 			COLOR(1,4*i + j*4*8 + 2) = 2*8 + i + 32 + j*64;
122 			COLOR(1,4*i + j*4*8 + 3) = 3*8 + i + 32 + j*64;
123 		}
124 	}
125 }
126 
127 
128 
129 /***************************************************************************
130 
131   Start the video hardware emulation.
132 
133 ***************************************************************************/
naughtyb_vh_start(void)134 int naughtyb_vh_start(void)
135 {
136 	videoreg = palreg = bankreg = 0;
137 
138 	/* Naughty Boy has a virtual screen twice as large as the visible screen */
139 	if ((dirtybuffer = (unsigned char*)malloc(videoram_size)) == 0)
140 		return 1;
141 	memset(dirtybuffer, 1, videoram_size);
142 
143 	if ((tmpbitmap = bitmap_alloc(68*8,28*8)) == 0)
144 	{
145 		free(dirtybuffer);
146 		return 1;
147 	}
148 
149 	return 0;
150 }
151 
152 
153 
154 /***************************************************************************
155 
156   Stop the video hardware emulation.
157 
158 ***************************************************************************/
naughtyb_vh_stop(void)159 void naughtyb_vh_stop(void)
160 {
161 	bitmap_free(tmpbitmap);
162 	free(dirtybuffer);
163 }
164 
165 
166 
WRITE_HANDLER(naughtyb_videoram2_w)167 WRITE_HANDLER( naughtyb_videoram2_w )
168 {
169 	if (naughtyb_videoram2[offset] != data)
170 	{
171 		dirtybuffer[offset] = 1;
172 
173 		naughtyb_videoram2[offset] = data;
174 	}
175 }
176 
177 
178 
WRITE_HANDLER(naughtyb_videoreg_w)179 WRITE_HANDLER( naughtyb_videoreg_w )
180 {
181 	/* bits 4+5 control the sound circuit */
182 	pleiads_sound_control_c_w(offset,data);
183 
184     if ((videoreg & 0x0f) != (data & 0x0f))
185 	{
186 		videoreg = data;
187 
188 		palreg  = (data >> 1) & 0x03;	/* pallette sel is bit 1 & 2 */
189 		bankreg = (data >> 2) & 0x01;	/* banksel is just bit 2 */
190 
191 		memset (dirtybuffer, 1, videoram_size);
192 	}
193 }
194 
WRITE_HANDLER(popflame_videoreg_w)195 WRITE_HANDLER( popflame_videoreg_w )
196 {
197 	/* bits 4+5 control the sound circuit */
198 	pleiads_sound_control_c_w(offset,data);
199 
200     if ((videoreg & 0x0f) != (data & 0x0f))
201 	{
202 		videoreg = data;
203 
204 		palreg  = (data >> 1) & 0x03;	/* pallette sel is bit 1 & 2 */
205 		bankreg = (data >> 3) & 0x01;	/* banksel is just bit 3 */
206 
207 		memset (dirtybuffer, 1, videoram_size);
208 	}
209 }
210 
211 
212 
213 /***************************************************************************
214 
215   Draw the game screen in the given osd_bitmap.
216   Do NOT call osd_update_display() from this function, it will be called by
217   the main emulation engine.
218 
219   The Naughty Boy screen is split into two sections by the hardware
220 
221   NonScrolled = 28x4 - (rows 0,1,34,35, as shown below)
222   this area is split between the top and bottom of the screen,
223   and the address mapping is really funky.
224 
225   Scrolled = 28x64, with a 28x32 viewport, as shown below
226   Each column in the virtual screen is 64 (40h) characters high.
227   Thus, column 27 is stored in VRAm at address 0-3fh,
228   column 26 is stored at 40-7f, and so on.
229   This illustration shows the horizonal scroll register set to zero,
230   so the topmost 32 rows of the virtual screen are shown.
231 
232   The following screen-to-memory mapping. This is shown from player's viewpoint,
233   which with the CRT rotated 90 degrees CCW. This example shows the horizonal
234   scroll register set to zero.
235 
236 
237                           COLUMN
238                 0   1   2    -    25  26  27
239               -------------------------------
240             0| 76E 76A 762   -   70A 706 702 |
241              |                               |  Nonscrolled display
242             1| 76F 76B 762   -   70B 707 703 |
243              |-------------------------------| -----
244             2| 6C0 680 640   -    80  40  00 |
245              |                               |
246         R   3| 6C1 681 641   -    81  41  01 |
247         O    |                               |  28 x 32 viewport
248         W   ||      |                 |      |  into 28x64 virtual,
249              |                               |  scrollable screen
250            32| 6DE 69E 65E        9E  5E  1E |
251              |                               |
252            33| 6DF 69F 65F   -    9F  5F  1F |
253              |-------------------------------| -----
254            34| 76C 768 764       708 704 700 |
255              |                               |  Nonscrolled display
256            35| 76D 769 765       709 705 701 |
257               -------------------------------
258 
259 
260 ***************************************************************************/
naughtyb_vh_screenrefresh(struct osd_bitmap * bitmap,int full_refresh)261 void naughtyb_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
262 {
263 	int offs;
264 
265 
266 	/* for every character in the Video RAM, check if it has been modified */
267 	/* since last time and update it accordingly. */
268 	for (offs = videoram_size - 1;offs >= 0;offs--)
269 	{
270 		if (dirtybuffer[offs])
271 		{
272 			int sx,sy;
273 
274 
275 			dirtybuffer[offs] = 0;
276 
277 			if (offs < 0x700)
278 			{
279 				sx = offs % 64;
280 				sy = offs / 64;
281 			}
282 			else
283 			{
284 				sx = 64 + (offs - 0x700) % 4;
285 				sy = (offs - 0x700) / 4;
286 			}
287 
288 			drawgfx(tmpbitmap,Machine->gfx[0],
289 					naughtyb_videoram2[offs] + 256 * bankreg,
290 					(naughtyb_videoram2[offs] >> 5) + 8 * palreg,
291 					0,0,
292 					8*sx,8*sy,
293 					0,TRANSPARENCY_NONE,0);
294 
295 			drawgfx(tmpbitmap,Machine->gfx[1],
296 					videoram[offs] + 256*bankreg,
297 					(videoram[offs] >> 5) + 8 * palreg,
298 					0,0,
299 					8*sx,8*sy,
300 					0,TRANSPARENCY_PEN,0);
301 		}
302 	}
303 
304 
305 	/* copy the temporary bitmap to the screen */
306 	{
307 		int scrollx;
308 
309 
310 		copybitmap(bitmap,tmpbitmap,0,0,-66*8,0,&leftvisiblearea,TRANSPARENCY_NONE,0);
311 		copybitmap(bitmap,tmpbitmap,0,0,-30*8,0,&rightvisiblearea,TRANSPARENCY_NONE,0);
312 
313 		scrollx = -*naughtyb_scrollreg + 16;
314 		copyscrollbitmap(bitmap,tmpbitmap,1,&scrollx,0,0,&scrollvisiblearea,TRANSPARENCY_NONE,0);
315 	}
316 }
317