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