1 /*******************************************************************************
2 
3 	Battle Rangers - Bryan McPhail, mish@tendril.co.uk
4 
5 	This file only implements necessary features - not all PC-Engine video
6 	features are used in this game (no DMA for one).
7 
8 *******************************************************************************/
9 
10 #include "driver.h"
11 #include "vidhrdw/generic.h"
12 #include "cpu/h6280/h6280.h"
13 
14 static int HuC6270_registers[20];
15 static int VDC_register,vram_ptr;
16 static unsigned char *HuC6270_vram,*tile_dirty,*sprite_dirty,*vram_dirty;
17 static struct osd_bitmap *tile_bitmap,*front_bitmap;
18 
19 static int current_scanline,/*next_update_first_line,*/inc_value;
20 static int irq_enable,rcr_enable,sb_enable,bb_enable,bldwolf_vblank;
21 
22 /******************************************************************************/
23 
WRITE_HANDLER(battlera_palette_w)24 WRITE_HANDLER( battlera_palette_w )
25 {
26 	int r,g,b,pal_word;
27 
28 	paletteram[offset]=data;
29 	if (offset%2) offset-=1;
30 
31 	pal_word=paletteram[offset] | (paletteram[offset+1]<<8);
32 
33 	r = ((pal_word >> 3) & 7) << 5;
34 	g = ((pal_word >> 6) & 7) << 5;
35 	b = ((pal_word >> 0) & 7) << 5;
36 	palette_change_color(offset/2, r, g, b);
37 }
38 
39 /******************************************************************************/
40 
draw_sprites(struct osd_bitmap * bitmap,const struct rectangle * clip,int pri)41 static void draw_sprites(struct osd_bitmap *bitmap,const struct rectangle *clip,int pri)
42 {
43 	int offs,my,mx,code,code2,fx,fy,cgy=0,cgx,colour,i;
44 
45 	/* Draw sprites, starting at SATB, draw in _reverse_ order */
46 	for (offs=(HuC6270_registers[19]<<1)+0x200-8; offs>=(HuC6270_registers[19]<<1); offs-=8)
47 	{
48 		if ((HuC6270_vram[offs+7]&0x80) && !pri) continue;
49 		if (!(HuC6270_vram[offs+7]&0x80) && pri) continue;
50 
51 		code=HuC6270_vram[offs+5] + (HuC6270_vram[offs+4]<<8);
52 		code=code>>1;
53 
54 		my=HuC6270_vram[offs+1] + (HuC6270_vram[offs+0]<<8);
55 		mx=HuC6270_vram[offs+3] + (HuC6270_vram[offs+2]<<8);
56 
57 		mx-=32;
58 		my-=57;
59 
60 		fx=HuC6270_vram[offs+6]&0x8;
61 		fy=HuC6270_vram[offs+6]&0x80;
62 		cgx=HuC6270_vram[offs+6]&1;
63 		colour=HuC6270_vram[offs+7]&0xf;
64 
65 		switch ((HuC6270_vram[offs+6]>>4)&3) {
66 		case 0: cgy=1; break;
67 		case 1: cgy=2; break;
68 		case 2: cgy=0; break; /* Illegal */
69 		case 3: cgy=4; break;
70 		}
71 
72 		if (cgx && cgy==2) code=code&0x3fc; /* Title screen */
73 
74 		if (fx && cgx) {code2=code; code++;} /* Swap tile order on X flips */
75 		else code2=code+1;
76 
77 		for (i=0; i<cgy; i++) {
78 			drawgfx(bitmap,Machine->gfx[1],
79 				code,
80 				colour,
81 				fx,fy,
82 				mx,my,
83 				clip,TRANSPARENCY_PEN,0);
84 
85 			if (cgx)
86 				drawgfx(bitmap,Machine->gfx[1],
87 						code2,
88 						colour,
89 						fx,fy,
90 						mx+16,my,
91 						clip,TRANSPARENCY_PEN,0);
92 			my+=16;
93 			/* if (cgx) */ /* Different from console? */
94 			code+=2;
95 			code2+=2;
96 			/*else code+=1; */ /* Different from console? */
97 		}
98 	}
99 
100 }
101 
screenrefresh(struct osd_bitmap * bitmap,const struct rectangle * clip)102 static void screenrefresh(struct osd_bitmap *bitmap,const struct rectangle *clip)
103 {
104 	int offs,code,scrollx,scrolly,mx,my;
105 
106 	/* Recalculate palette if needed */
107 	palette_init_used_colors();
108 
109 	for (offs=0; offs<256; offs++)
110 		if (!(offs%16))
111 			palette_used_colors[offs] = PALETTE_COLOR_TRANSPARENT;
112 		else
113 			palette_used_colors[offs] = PALETTE_COLOR_USED;
114 
115 	for (offs=256; offs<512; offs++)
116 			palette_used_colors[offs] = PALETTE_COLOR_USED;
117 
118 	if (palette_recalc())
119 		memset(vram_dirty,1,0x1000);
120 
121 	/* Dynamically decode chars if dirty */
122 	for (code = 0x0000;code < 0x1000;code++)
123 		if (tile_dirty[code])
124 			decodechar(Machine->gfx[0],code,HuC6270_vram,Machine->drv->gfxdecodeinfo[0].gfxlayout);
125 
126 	/* Dynamically decode sprites if dirty */
127 	for (code = 0x0000;code < 0x400;code++)
128 		if (sprite_dirty[code])
129 			decodechar(Machine->gfx[1],code,HuC6270_vram,Machine->drv->gfxdecodeinfo[1].gfxlayout);
130 
131 	/* NB: If first 0x1000 byte is always tilemap, no need to decode the first batch of tiles/sprites */
132 
133 	mx=-1;
134 	my=0;
135 	for (offs = 0x0000;offs < 0x2000;offs += 2)
136 	{
137 		mx++;
138 		if (mx==64) {mx=0; my++;}
139 		code=HuC6270_vram[offs+1] + ((HuC6270_vram[offs] & 0x0f) << 8);
140 
141 		/* If this tile was changed OR tilemap was changed, redraw */
142 		if (tile_dirty[code] || vram_dirty[offs/2]) {
143 			vram_dirty[offs/2]=0;
144 	        drawgfx(tile_bitmap,Machine->gfx[0],
145 					code,
146 					HuC6270_vram[offs] >> 4,
147 					0,0,
148 					8*mx,8*my,
149 					0,TRANSPARENCY_NONE,0);
150 			drawgfx(front_bitmap,Machine->gfx[2],
151 					0,
152 					0,
153 					0,0,
154 					8*mx,8*my,
155 					0,TRANSPARENCY_NONE,0);
156 	        drawgfx(front_bitmap,Machine->gfx[0],
157 					code,
158 					HuC6270_vram[offs] >> 4,
159 					0,0,
160 					8*mx,8*my,
161 					0,TRANSPARENCY_PENS,0x1);
162 			}
163 	}
164 
165 	/* Nothing dirty after a screen refresh */
166 	for (code = 0x0000;code < 0x1000;code++)
167 		tile_dirty[code]=0;
168 	for (code = 0x0000;code < 0x400;code++)
169 		sprite_dirty[code]=0;
170 
171 	/* Render bitmap */
172 	scrollx=-HuC6270_registers[7];
173 	scrolly=-HuC6270_registers[8]+clip->min_y-1;
174 
175 	copyscrollbitmap(bitmap,tile_bitmap,1,&scrollx,1,&scrolly,clip,TRANSPARENCY_NONE,0);
176 
177 	/* Todo:  Background enable (not used anyway) */
178 
179 	/* Render low priority sprites, if enabled */
180 	if (sb_enable) draw_sprites(bitmap,clip,0);
181 
182 	/* Render background over sprites */
183 	copyscrollbitmap(bitmap,front_bitmap,1,&scrollx,1,&scrolly,clip,TRANSPARENCY_PEN,palette_transparent_pen);
184 
185 	/* Render high priority sprites, if enabled */
186 	if (sb_enable) draw_sprites(bitmap,clip,1);
187 }
188 
189 /******************************************************************************/
190 
READ_HANDLER(HuC6270_register_r)191 READ_HANDLER( HuC6270_register_r )
192 {
193 	int rr;
194 
195 	if ((current_scanline+56)==HuC6270_registers[6]) rr=1; else rr=0;
196 
197 	return 0		/* CR flag */
198 		| (0 << 1)	/* OR flag */
199 		| (rr << 2)	/* RR flag */
200 		| (0 << 3)	/* DS flag */
201 		| (0 << 4)	/* DV flag */
202 		| (bldwolf_vblank << 5)	/* VD flag (1 when vblank else 0) */
203 		| (0 << 6)	/* BSY flag (1 when dma active, else 0) */
204 		| (0 << 7);	/* Always zero */
205 }
206 
WRITE_HANDLER(HuC6270_register_w)207 WRITE_HANDLER( HuC6270_register_w )
208 {
209 	switch (offset) {
210 	case 0: /* Select data region */
211 		VDC_register=data;
212 		break;
213 	case 1: /* Unused */
214 		break;
215 	}
216 }
217 
218 /******************************************************************************/
219 
READ_HANDLER(HuC6270_data_r)220 READ_HANDLER( HuC6270_data_r )
221 {
222 	int result;
223 
224 	switch (offset) {
225 		case 0: /* LSB */
226 			return HuC6270_vram[(HuC6270_registers[1]<<1)|1];
227 
228 		case 1:/* MSB */
229 			result=HuC6270_vram[(HuC6270_registers[1]<<1)|0];
230 			HuC6270_registers[1]=(HuC6270_registers[1]+inc_value)&0xffff;
231 			return result;
232 	}
233 
234 	return 0;
235 }
236 
WRITE_HANDLER(HuC6270_data_w)237 WRITE_HANDLER( HuC6270_data_w )
238 {
239 	switch (offset) {
240 		case 0: /* LSB */
241 			switch (VDC_register) {
242 
243 			case 0: /* MAWR */
244 				HuC6270_registers[0]=(HuC6270_registers[0]&0xff00) | (data);
245 				return;
246 
247 			case 1: /* MARR */
248 				HuC6270_registers[0]=(HuC6270_registers[1]&0xff00) | (data);
249 				return;
250 
251 			case 2: /* VRAM */
252 				if (HuC6270_vram[(HuC6270_registers[0]<<1)|1]!=data) {
253 					HuC6270_vram[(HuC6270_registers[0]<<1)|1]=data;
254 					tile_dirty[HuC6270_registers[0]>>4]=1;
255 					sprite_dirty[HuC6270_registers[0]>>6]=1;
256 				}
257 				if (HuC6270_registers[0]<0x1000) vram_dirty[HuC6270_registers[0]]=1;
258 				return;
259 
260 			case 3: break; /* Unused */
261 			case 4: break; /* Unused */
262 
263 			case 5: /* CR - Control register */
264 				/* Bits 0,1 unknown */
265 				rcr_enable=data&0x4; /* Raster interrupt enable */
266 				irq_enable=data&0x8; /* VBL interrupt enable */
267 				/* Bits 4,5 unknown (EX) */
268 				sb_enable=data&0x40; /* Sprites enable */
269 				bb_enable=data&0x80; /* Background enable */
270 				return;
271 
272 			case 6: /* RCR - Raster counter register */
273 				HuC6270_registers[6]=(HuC6270_registers[6]&0xff00) | (data);
274 				return;
275 
276 			case 7: /* BXR - X scroll */
277 				HuC6270_registers[7]=(HuC6270_registers[7]&0xff00) | (data);
278 				return;
279 
280 			case 8: /* BYR - Y scroll */
281 				HuC6270_registers[8]=(HuC6270_registers[8]&0xff00) | (data);
282 				return;
283 
284 			case 15: /* DMA */
285 			case 16:
286 			case 17:
287 			case 18:
288 				//logerror("%04x: dma 2 %02x\n",cpu_get_pc(),data);
289 				break;
290 
291 			case 19: /* SATB */
292 				HuC6270_registers[19]=(HuC6270_registers[19]&0xff00) | (data);
293 				return;
294 
295 			}
296 			break;
297 
298 		/*********************************************/
299 
300 		case 1: /* MSB (Autoincrement on this write) */
301 			switch (VDC_register) {
302 
303 			case 0: /* MAWR - Memory Address Write Register */
304 				HuC6270_registers[0]=(HuC6270_registers[0]&0xff) | (data<<8);
305 				return;
306 
307 			case 1: /* MARR */
308 				HuC6270_registers[1]=(HuC6270_registers[1]&0xff) | (data<<8);
309 				return;
310 
311 			case 2: /* VWR - VRAM */
312 				if (HuC6270_vram[(HuC6270_registers[0]<<1)|0]!=data) {
313 					HuC6270_vram[(HuC6270_registers[0]<<1)|0]=data;
314 					tile_dirty[HuC6270_registers[0]>>4]=1;
315 					sprite_dirty[HuC6270_registers[0]>>6]=1;
316 					if (HuC6270_registers[0]<0x1000) vram_dirty[HuC6270_registers[0]]=1;
317 				}
318 				HuC6270_registers[0]+=inc_value;
319 				HuC6270_registers[0]=HuC6270_registers[0]&0xffff;
320 				return;
321 
322 			case 5: /* CR */
323 				/* IW - Auto-increment values */
324 				switch ((data>>3)&3) {
325 					case 0: inc_value=1; break;
326 					case 1: inc_value=32;break;
327 					case 2: inc_value=64; break;
328 					case 3: inc_value=128; break;
329 				}
330 
331 				/* DR, TE unknown */
332 				return;
333 
334 			case 6: /* RCR - Raster counter register */
335 				HuC6270_registers[6]=(HuC6270_registers[6]&0xff) | (data<<8);
336 				return;
337 
338 			case 7: /* BXR - X scroll */
339 				HuC6270_registers[7]=(HuC6270_registers[7]&0xff) | (data<<8);
340 						return;
341 
342 			case 8: /* BYR - Y scroll */
343 				HuC6270_registers[8]=(HuC6270_registers[8]&0xff) | (data<<8);
344 				return;
345 
346 			case 15: /* DMA */
347 			case 16:
348 			case 17:
349 			case 18:
350 				//logerror("%04x: dma 2 %02x\n",cpu_get_pc(),data);
351 				break;
352 
353 			case 19: /* SATB - Sprites */
354 				HuC6270_registers[19]=(HuC6270_registers[19]&0xff) | (data<<8);
355 				return;
356 			}
357 			break;
358 	}
359 	//logerror("%04x: unknown write to  VDC_register %02x (%02x) at %02x\n",cpu_get_pc(),VDC_register,data,offset);
360 }
361 
362 /******************************************************************************/
363 
battlera_vh_screenrefresh(struct osd_bitmap * bitmap,int full_refresh)364 void battlera_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
365 {
366 	/* Nothing */
367 }
368 
369 /*static void partial_refresh(struct osd_bitmap *bitmap,int current_line)
370 {
371 	struct rectangle clip;
372 
373 	clip.min_x = Machine->visible_area.min_x;
374 	clip.max_x = Machine->visible_area.max_x;
375 	clip.min_y = next_update_first_line;
376 	clip.max_y = current_line;
377 	if (clip.min_y < Machine->visible_area.min_y)
378 		clip.min_y = Machine->visible_area.min_y;
379 	if (clip.max_y > Machine->visible_area.max_y)
380 		clip.max_y = Machine->visible_area.max_y;
381 
382 	if (clip.max_y >= clip.min_y)
383 	{
384 		screenrefresh(bitmap,&clip);
385 	}
386 
387 	next_update_first_line = current_line + 1;
388 }*/
389 
battlera_vh_raster_partial_refresh(struct osd_bitmap * bitmap,int start_line,int end_line)390 void battlera_vh_raster_partial_refresh(struct osd_bitmap *bitmap,int start_line,int end_line)
391 {
392 	struct rectangle clip;
393 
394 	clip.min_x = Machine->visible_area.min_x;
395 	clip.max_x = Machine->visible_area.max_x;
396 	clip.min_y = start_line;
397 	clip.max_y = end_line;
398 	if (clip.min_y < Machine->visible_area.min_y)
399 		clip.min_y = Machine->visible_area.min_y;
400 	if (clip.max_y > Machine->visible_area.max_y)
401 		clip.max_y = Machine->visible_area.max_y;
402 
403 	if (clip.max_y > clip.min_y)
404 	{
405 		screenrefresh(bitmap,&clip);
406 	}
407 }
408 
409 /******************************************************************************/
410 
battlera_interrupt(void)411 int battlera_interrupt(void)
412 {
413 	static int last_line=0;
414 
415 	current_scanline=255-cpu_getiloops(); /* 8 lines clipped at top */
416 
417 	/* If raster interrupt occurs, refresh screen _up_ to this point */
418 	if (rcr_enable && (current_scanline+56)==HuC6270_registers[6]) {
419 		battlera_vh_raster_partial_refresh(Machine->scrbitmap,last_line,current_scanline);
420 		last_line=current_scanline;
421 		return H6280_INT_IRQ1; /* RCR interrupt */
422 	}
423 
424 	/* Start of vblank */
425 	if (current_scanline==240) {
426 		bldwolf_vblank=1;
427 		battlera_vh_raster_partial_refresh(Machine->scrbitmap,last_line,240);
428 		if (irq_enable)
429 			return H6280_INT_IRQ1; /* VBL */
430 	}
431 
432 	/* End of vblank */
433 	if (current_scanline==254) {
434 		bldwolf_vblank=0;
435 		last_line=0;
436 	}
437 
438 	return 0;
439 }
440 
441 /******************************************************************************/
442 
READ_HANDLER(HuC6270_debug_r)443 READ_HANDLER( HuC6270_debug_r )
444 {
445 	return HuC6270_vram[offset];
446 }
447 
WRITE_HANDLER(HuC6270_debug_w)448 WRITE_HANDLER( HuC6270_debug_w )
449 {
450 	HuC6270_vram[offset]=data;
451 }
452 
453 /******************************************************************************/
454 
battlera_vh_stop(void)455 void battlera_vh_stop (void)
456 {
457 	free(tile_dirty);
458 	free(HuC6270_vram);
459 	free(sprite_dirty);
460 	free(vram_dirty);
461 
462 	bitmap_free(tile_bitmap);
463 	bitmap_free(front_bitmap);
464 }
465 
battlera_vh_start(void)466 int battlera_vh_start (void)
467 {
468 	HuC6270_vram=(unsigned char*)malloc(0x20000);
469 	tile_dirty=(unsigned char*)malloc(0x1000);
470 	sprite_dirty=(unsigned char*)malloc(0x400);
471 	vram_dirty=(unsigned char*)malloc(0x1000);
472 
473 	memset(HuC6270_vram,0,0x20000);
474 	memset(tile_dirty,1,0x1000);
475 	memset(sprite_dirty,1,0x400);
476 	memset(vram_dirty,1,0x1000);
477 
478 	tile_bitmap=bitmap_alloc(512,512);
479 	front_bitmap=bitmap_alloc(512,512);
480 
481 	if (!tile_bitmap || !front_bitmap || !tile_dirty || !HuC6270_vram || !sprite_dirty || !vram_dirty)
482 		return 1;
483 
484 	vram_ptr=0;
485 	inc_value=1;
486 	current_scanline=0;
487 	irq_enable=rcr_enable=sb_enable=bb_enable=0;
488 
489 	return 0;
490 }
491