summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/battlera.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/battlera.c')
-rw-r--r--src/mame/video/battlera.c413
1 files changed, 413 insertions, 0 deletions
diff --git a/src/mame/video/battlera.c b/src/mame/video/battlera.c
new file mode 100644
index 00000000000..99d3f132d4d
--- /dev/null
+++ b/src/mame/video/battlera.c
@@ -0,0 +1,413 @@
+/*******************************************************************************
+
+ Battle Rangers - Bryan McPhail, mish@tendril.co.uk
+
+ This file only implements necessary features - not all PC-Engine video
+ features are used in this game (no DMA for one).
+
+*******************************************************************************/
+
+#include "driver.h"
+#include "cpu/h6280/h6280.h"
+
+static int HuC6270_registers[20];
+static int VDC_register,vram_ptr;
+static UINT8 *HuC6270_vram,*tile_dirty,*sprite_dirty,*vram_dirty;
+static mame_bitmap *tile_bitmap,*front_bitmap;
+
+static int current_scanline,inc_value;
+static int irq_enable,rcr_enable,sb_enable,bb_enable,bldwolf_vblank;
+
+
+
+/******************************************************************************/
+
+VIDEO_START( battlera )
+{
+ HuC6270_vram=auto_malloc(0x20000);
+ tile_dirty=auto_malloc(0x1000);
+ sprite_dirty=auto_malloc(0x400);
+ vram_dirty=auto_malloc(0x1000);
+
+ memset(HuC6270_vram,0,0x20000);
+ memset(tile_dirty,1,0x1000);
+ memset(sprite_dirty,1,0x400);
+ memset(vram_dirty,1,0x1000);
+
+ tile_bitmap=auto_bitmap_alloc(512,512,machine->screen[0].format);
+ front_bitmap=auto_bitmap_alloc(512,512,machine->screen[0].format);
+
+ vram_ptr=0;
+ inc_value=1;
+ current_scanline=0;
+ irq_enable=rcr_enable=sb_enable=bb_enable=0;
+}
+
+/******************************************************************************/
+
+WRITE8_HANDLER( battlera_palette_w )
+{
+ int pal_word;
+
+ paletteram[offset]=data;
+ if (offset%2) offset-=1;
+
+ pal_word=paletteram[offset] | (paletteram[offset+1]<<8);
+ palette_set_color_rgb(Machine, offset/2, pal3bit(pal_word >> 3), pal3bit(pal_word >> 6), pal3bit(pal_word >> 0));
+}
+
+/******************************************************************************/
+
+READ8_HANDLER( HuC6270_debug_r )
+{
+ return HuC6270_vram[offset];
+}
+
+WRITE8_HANDLER( HuC6270_debug_w )
+{
+ HuC6270_vram[offset]=data;
+}
+READ8_HANDLER( HuC6270_register_r )
+{
+ int rr;
+
+ if ((current_scanline+56)==HuC6270_registers[6]) rr=1; else rr=0;
+
+ return 0 /* CR flag */
+ | (0 << 1) /* OR flag */
+ | (rr << 2) /* RR flag */
+ | (0 << 3) /* DS flag */
+ | (0 << 4) /* DV flag */
+ | (bldwolf_vblank << 5) /* VD flag (1 when vblank else 0) */
+ | (0 << 6) /* BSY flag (1 when dma active, else 0) */
+ | (0 << 7); /* Always zero */
+}
+
+WRITE8_HANDLER( HuC6270_register_w )
+{
+ switch (offset) {
+ case 0: /* Select data region */
+ VDC_register=data;
+ break;
+ case 1: /* Unused */
+ break;
+ }
+}
+
+/******************************************************************************/
+
+#ifdef UNUSED_FUNCTION
+READ8_HANDLER( HuC6270_data_r )
+{
+ int result;
+
+ switch (offset) {
+ case 0: /* LSB */
+ return HuC6270_vram[(HuC6270_registers[1]<<1)|1];
+
+ case 1:/* MSB */
+ result=HuC6270_vram[(HuC6270_registers[1]<<1)|0];
+ HuC6270_registers[1]=(HuC6270_registers[1]+inc_value)&0xffff;
+ return result;
+ }
+
+ return 0;
+}
+#endif
+
+WRITE8_HANDLER( HuC6270_data_w )
+{
+ switch (offset) {
+ case 0: /* LSB */
+ switch (VDC_register) {
+
+ case 0: /* MAWR */
+ HuC6270_registers[0]=(HuC6270_registers[0]&0xff00) | (data);
+ return;
+
+ case 1: /* MARR */
+ HuC6270_registers[0]=(HuC6270_registers[1]&0xff00) | (data);
+ return;
+
+ case 2: /* VRAM */
+ if (HuC6270_vram[(HuC6270_registers[0]<<1)|1]!=data) {
+ HuC6270_vram[(HuC6270_registers[0]<<1)|1]=data;
+ tile_dirty[HuC6270_registers[0]>>4]=1;
+ sprite_dirty[HuC6270_registers[0]>>6]=1;
+ }
+ if (HuC6270_registers[0]<0x1000) vram_dirty[HuC6270_registers[0]]=1;
+ return;
+
+ case 3: break; /* Unused */
+ case 4: break; /* Unused */
+
+ case 5: /* CR - Control register */
+ /* Bits 0,1 unknown */
+ rcr_enable=data&0x4; /* Raster interrupt enable */
+ irq_enable=data&0x8; /* VBL interrupt enable */
+ /* Bits 4,5 unknown (EX) */
+ sb_enable=data&0x40; /* Sprites enable */
+ bb_enable=data&0x80; /* Background enable */
+ return;
+
+ case 6: /* RCR - Raster counter register */
+ HuC6270_registers[6]=(HuC6270_registers[6]&0xff00) | (data);
+ return;
+
+ case 7: /* BXR - X scroll */
+ HuC6270_registers[7]=(HuC6270_registers[7]&0xff00) | (data);
+ return;
+
+ case 8: /* BYR - Y scroll */
+ HuC6270_registers[8]=(HuC6270_registers[8]&0xff00) | (data);
+ return;
+
+ case 15: /* DMA */
+ case 16:
+ case 17:
+ case 18:
+ logerror("%04x: dma 2 %02x\n",activecpu_get_pc(),data);
+ break;
+
+ case 19: /* SATB */
+ HuC6270_registers[19]=(HuC6270_registers[19]&0xff00) | (data);
+ return;
+
+ }
+ break;
+
+ /*********************************************/
+
+ case 1: /* MSB (Autoincrement on this write) */
+ switch (VDC_register) {
+
+ case 0: /* MAWR - Memory Address Write Register */
+ HuC6270_registers[0]=(HuC6270_registers[0]&0xff) | (data<<8);
+ return;
+
+ case 1: /* MARR */
+ HuC6270_registers[1]=(HuC6270_registers[1]&0xff) | (data<<8);
+ return;
+
+ case 2: /* VWR - VRAM */
+ if (HuC6270_vram[(HuC6270_registers[0]<<1)|0]!=data) {
+ HuC6270_vram[(HuC6270_registers[0]<<1)|0]=data;
+ tile_dirty[HuC6270_registers[0]>>4]=1;
+ sprite_dirty[HuC6270_registers[0]>>6]=1;
+ if (HuC6270_registers[0]<0x1000) vram_dirty[HuC6270_registers[0]]=1;
+ }
+ HuC6270_registers[0]+=inc_value;
+ HuC6270_registers[0]=HuC6270_registers[0]&0xffff;
+ return;
+
+ case 5: /* CR */
+ /* IW - Auto-increment values */
+ switch ((data>>3)&3) {
+ case 0: inc_value=1; break;
+ case 1: inc_value=32;break;
+ case 2: inc_value=64; break;
+ case 3: inc_value=128; break;
+ }
+
+ /* DR, TE unknown */
+ return;
+
+ case 6: /* RCR - Raster counter register */
+ HuC6270_registers[6]=(HuC6270_registers[6]&0xff) | (data<<8);
+ return;
+
+ case 7: /* BXR - X scroll */
+ HuC6270_registers[7]=(HuC6270_registers[7]&0xff) | (data<<8);
+ return;
+
+ case 8: /* BYR - Y scroll */
+ HuC6270_registers[8]=(HuC6270_registers[8]&0xff) | (data<<8);
+ return;
+
+ case 15: /* DMA */
+ case 16:
+ case 17:
+ case 18:
+ logerror("%04x: dma 2 %02x\n",activecpu_get_pc(),data);
+ break;
+
+ case 19: /* SATB - Sprites */
+ HuC6270_registers[19]=(HuC6270_registers[19]&0xff) | (data<<8);
+ return;
+ }
+ break;
+ }
+ logerror("%04x: unknown write to VDC_register %02x (%02x) at %02x\n",activecpu_get_pc(),VDC_register,data,offset);
+}
+
+/******************************************************************************/
+
+static void draw_sprites(running_machine *machine, mame_bitmap *bitmap,const rectangle *clip,int pri)
+{
+ int offs,my,mx,code,code2,fx,fy,cgy=0,cgx,colour,i,yinc;
+
+ /* Draw sprites, starting at SATB, draw in _reverse_ order */
+ for (offs=(HuC6270_registers[19]<<1)+0x200-8; offs>=(HuC6270_registers[19]<<1); offs-=8)
+ {
+ if ((HuC6270_vram[offs+7]&0x80) && !pri) continue;
+ if (!(HuC6270_vram[offs+7]&0x80) && pri) continue;
+
+ code=HuC6270_vram[offs+5] + (HuC6270_vram[offs+4]<<8);
+ code=code>>1;
+
+ my=HuC6270_vram[offs+1] + (HuC6270_vram[offs+0]<<8);
+ mx=HuC6270_vram[offs+3] + (HuC6270_vram[offs+2]<<8);
+
+ mx-=32;
+ my-=57;
+
+ fx=HuC6270_vram[offs+6]&0x8;
+ fy=HuC6270_vram[offs+6]&0x80;
+ cgx=HuC6270_vram[offs+6]&1;
+ colour=HuC6270_vram[offs+7]&0xf;
+
+ switch ((HuC6270_vram[offs+6]>>4)&3) {
+ case 0: cgy=1; break;
+ case 1: cgy=2; break;
+ case 2: cgy=0; break; /* Illegal */
+ case 3: cgy=4; break;
+ }
+
+ if (cgx && cgy==2) code=code&0x3fc; /* Title screen */
+
+ if (fx && cgx) {code2=code; code++;} /* Swap tile order on X flips */
+ else code2=code+1;
+
+ yinc = 16;
+ if (fy) { my += 16*(cgy-1); yinc = -16; } /* Swap tile order on Y flips */
+
+ for (i=0; i<cgy; i++) {
+ drawgfx(bitmap,machine->gfx[1],
+ code,
+ colour,
+ fx,fy,
+ mx,my,
+ clip,TRANSPARENCY_PEN,0);
+
+ if (cgx)
+ drawgfx(bitmap,machine->gfx[1],
+ code2,
+ colour,
+ fx,fy,
+ mx+16,my,
+ clip,TRANSPARENCY_PEN,0);
+ my += yinc;
+ /* if (cgx) */ /* Different from console? */
+ code += 2;
+ code2 += 2;
+ /*else code += 1; */ /* Different from console? */
+ }
+ }
+
+}
+
+static void screenrefresh(running_machine *machine, mame_bitmap *bitmap,const rectangle *clip)
+{
+ int offs,code,scrollx,scrolly,mx,my;
+
+ /* Dynamically decode chars if dirty */
+ for (code = 0x0000;code < 0x1000;code++)
+ if (tile_dirty[code])
+ decodechar(machine->gfx[0],code,HuC6270_vram,machine->drv->gfxdecodeinfo[0].gfxlayout);
+
+ /* Dynamically decode sprites if dirty */
+ for (code = 0x0000;code < 0x400;code++)
+ if (sprite_dirty[code])
+ decodechar(machine->gfx[1],code,HuC6270_vram,machine->drv->gfxdecodeinfo[1].gfxlayout);
+
+ /* NB: If first 0x1000 byte is always tilemap, no need to decode the first batch of tiles/sprites */
+
+ mx=-1;
+ my=0;
+ for (offs = 0x0000;offs < 0x2000;offs += 2)
+ {
+ mx++;
+ if (mx==64) {mx=0; my++;}
+ code=HuC6270_vram[offs+1] + ((HuC6270_vram[offs] & 0x0f) << 8);
+
+ /* If this tile was changed OR tilemap was changed, redraw */
+ if (tile_dirty[code] || vram_dirty[offs/2]) {
+ vram_dirty[offs/2]=0;
+ drawgfx(tile_bitmap,machine->gfx[0],
+ code,
+ HuC6270_vram[offs] >> 4,
+ 0,0,
+ 8*mx,8*my,
+ 0,TRANSPARENCY_NONE,0);
+ drawgfx(front_bitmap,machine->gfx[2],
+ 0,
+ 0, /* fill the spot with pen 256 */
+ 0,0,
+ 8*mx,8*my,
+ 0,TRANSPARENCY_NONE,0);
+ drawgfx(front_bitmap,machine->gfx[0],
+ code,
+ HuC6270_vram[offs] >> 4,
+ 0,0,
+ 8*mx,8*my,
+ 0,TRANSPARENCY_PENS,0x1);
+ }
+ }
+
+ /* Nothing dirty after a screen refresh */
+ for (code = 0x0000;code < 0x1000;code++)
+ tile_dirty[code]=0;
+ for (code = 0x0000;code < 0x400;code++)
+ sprite_dirty[code]=0;
+
+ /* Render bitmap */
+ scrollx=-HuC6270_registers[7];
+ scrolly=-HuC6270_registers[8]+clip->min_y-1;
+
+ copyscrollbitmap(bitmap,tile_bitmap,1,&scrollx,1,&scrolly,clip,TRANSPARENCY_NONE,0);
+
+ /* Todo: Background enable (not used anyway) */
+
+ /* Render low priority sprites, if enabled */
+ if (sb_enable) draw_sprites(machine,bitmap,clip,0);
+
+ /* Render background over sprites */
+ copyscrollbitmap(bitmap,front_bitmap,1,&scrollx,1,&scrolly,clip,TRANSPARENCY_COLOR,256);
+
+ /* Render high priority sprites, if enabled */
+ if (sb_enable) draw_sprites(machine,bitmap,clip,1);
+}
+
+/******************************************************************************/
+
+VIDEO_UPDATE( battlera )
+{
+ screenrefresh(machine,bitmap,cliprect);
+ return 0;
+}
+
+/******************************************************************************/
+
+INTERRUPT_GEN( battlera_interrupt )
+{
+ current_scanline=255-cpu_getiloops(); /* 8 lines clipped at top */
+
+ /* If raster interrupt occurs, refresh screen _up_ to this point */
+ if (rcr_enable && (current_scanline+56)==HuC6270_registers[6]) {
+ video_screen_update_partial(0, current_scanline);
+ cpunum_set_input_line(0, 0, HOLD_LINE); /* RCR interrupt */
+ }
+
+ /* Start of vblank */
+ else if (current_scanline==240) {
+ bldwolf_vblank=1;
+ video_screen_update_partial(0, 240);
+ if (irq_enable)
+ cpunum_set_input_line(0, 0, HOLD_LINE); /* VBL */
+ }
+
+ /* End of vblank */
+ if (current_scanline==254) {
+ bldwolf_vblank=0;
+ }
+}