summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/btoads.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/btoads.c')
-rw-r--r--src/mame/video/btoads.c487
1 files changed, 487 insertions, 0 deletions
diff --git a/src/mame/video/btoads.c b/src/mame/video/btoads.c
new file mode 100644
index 00000000000..fb8306010ba
--- /dev/null
+++ b/src/mame/video/btoads.c
@@ -0,0 +1,487 @@
+/*************************************************************************
+
+ BattleToads
+
+ Video hardware emulation
+
+**************************************************************************/
+
+#include "driver.h"
+#include "cpu/tms34010/tms34010.h"
+#include "video/tlc34076.h"
+#include "btoads.h"
+
+
+#define BT_DEBUG 0
+
+
+
+/*************************************
+ *
+ * Global variables
+ *
+ *************************************/
+
+UINT16 *btoads_vram_fg0, *btoads_vram_fg1, *btoads_vram_fg_data;
+UINT16 *btoads_vram_bg0, *btoads_vram_bg1;
+UINT16 *btoads_sprite_scale;
+UINT16 *btoads_sprite_control;
+
+static UINT8 *vram_fg_draw, *vram_fg_display;
+
+static int xscroll0, yscroll0;
+static int xscroll1, yscroll1;
+static int screen_control;
+
+static UINT16 sprite_source_offs;
+static UINT8 *sprite_dest_base;
+static UINT16 sprite_dest_offs;
+
+static UINT16 misc_control;
+
+
+
+/*************************************
+ *
+ * Video system start
+ *
+ *************************************/
+
+VIDEO_START( btoads )
+{
+ /* initialize the swapped pointers */
+ vram_fg_draw = (UINT8 *)btoads_vram_fg0;
+ vram_fg_display = (UINT8 *)btoads_vram_fg1;
+}
+
+
+
+/*************************************
+ *
+ * Control registers
+ *
+ *************************************/
+
+WRITE16_HANDLER( btoads_misc_control_w )
+{
+ COMBINE_DATA(&misc_control);
+
+ /* bit 3 controls sound reset line */
+ cpunum_set_input_line(1, INPUT_LINE_RESET, (misc_control & 8) ? CLEAR_LINE : ASSERT_LINE);
+}
+
+
+WRITE16_HANDLER( btoads_display_control_w )
+{
+ if (ACCESSING_MSB)
+ {
+ /* allow multiple changes during display */
+ video_screen_update_partial(0, video_screen_get_vpos(0) - 1);
+
+ /* bit 15 controls which page is rendered and which page is displayed */
+ if (data & 0x8000)
+ {
+ vram_fg_draw = (UINT8 *)btoads_vram_fg1;
+ vram_fg_display = (UINT8 *)btoads_vram_fg0;
+ }
+ else
+ {
+ vram_fg_draw = (UINT8 *)btoads_vram_fg0;
+ vram_fg_display = (UINT8 *)btoads_vram_fg1;
+ }
+
+ /* stash the remaining data for later */
+ screen_control = data >> 8;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Scroll registers
+ *
+ *************************************/
+
+WRITE16_HANDLER( btoads_scroll0_w )
+{
+ /* allow multiple changes during display */
+ video_screen_update_partial(0, video_screen_get_vpos(0) - 1);
+
+ /* upper bits are Y scroll, lower bits are X scroll */
+ if (ACCESSING_MSB)
+ yscroll0 = data >> 8;
+ if (ACCESSING_LSB)
+ xscroll0 = data & 0xff;
+}
+
+
+WRITE16_HANDLER( btoads_scroll1_w )
+{
+ /* allow multiple changes during display */
+ video_screen_update_partial(0, video_screen_get_vpos(0) - 1);
+
+ /* upper bits are Y scroll, lower bits are X scroll */
+ if (ACCESSING_MSB)
+ yscroll1 = data >> 8;
+ if (ACCESSING_LSB)
+ xscroll1 = data & 0xff;
+}
+
+
+
+/*************************************
+ *
+ * Palette RAM
+ *
+ *************************************/
+
+WRITE16_HANDLER( btoads_paletteram_w )
+{
+ tlc34076_lsb_w(offset/2, data, mem_mask);
+}
+
+
+READ16_HANDLER( btoads_paletteram_r )
+{
+ return tlc34076_lsb_r(offset/2, mem_mask);
+}
+
+
+
+/*************************************
+ *
+ * Background video RAM
+ *
+ *************************************/
+
+WRITE16_HANDLER( btoads_vram_bg0_w )
+{
+ COMBINE_DATA(&btoads_vram_bg0[offset & 0x3fcff]);
+}
+
+
+WRITE16_HANDLER( btoads_vram_bg1_w )
+{
+ COMBINE_DATA(&btoads_vram_bg1[offset & 0x3fcff]);
+}
+
+
+READ16_HANDLER( btoads_vram_bg0_r )
+{
+ return btoads_vram_bg0[offset & 0x3fcff];
+}
+
+
+READ16_HANDLER( btoads_vram_bg1_r )
+{
+ return btoads_vram_bg1[offset & 0x3fcff];
+}
+
+
+
+/*************************************
+ *
+ * Foreground video RAM
+ *
+ *************************************/
+
+WRITE16_HANDLER( btoads_vram_fg_display_w )
+{
+ if (ACCESSING_LSB)
+ vram_fg_display[offset] = data;
+}
+
+
+WRITE16_HANDLER( btoads_vram_fg_draw_w )
+{
+ if (ACCESSING_LSB)
+ vram_fg_draw[offset] = data;
+}
+
+
+READ16_HANDLER( btoads_vram_fg_display_r )
+{
+ return vram_fg_display[offset];
+}
+
+
+READ16_HANDLER( btoads_vram_fg_draw_r )
+{
+ return vram_fg_draw[offset];
+}
+
+
+
+/*************************************
+ *
+ * Sprite rendering
+ *
+ *************************************/
+
+static void render_sprite_row(UINT16 *sprite_source, UINT32 address)
+{
+ int flipxor = ((*btoads_sprite_control >> 10) & 1) ? 0xffff : 0x0000;
+ int width = (~*btoads_sprite_control & 0x1ff) + 2;
+ int color = (~*btoads_sprite_control >> 8) & 0xf0;
+ int srcoffs = sprite_source_offs << 8;
+ int srcend = srcoffs + (width << 8);
+ int srcstep = 0x100 - btoads_sprite_scale[0];
+ int dststep = 0x100 - btoads_sprite_scale[8];
+ int dstoffs = sprite_dest_offs << 8;
+
+ /* non-shadow case */
+ if (!(misc_control & 0x10))
+ {
+ for ( ; srcoffs < srcend; srcoffs += srcstep, dstoffs += dststep)
+ {
+ UINT16 src = sprite_source[(srcoffs >> 10) & 0x1ff];
+ if (src)
+ {
+ src = (src >> (((srcoffs ^ flipxor) >> 6) & 0x0c)) & 0x0f;
+ if (src)
+ sprite_dest_base[(dstoffs >> 8) & 0x1ff] = src | color;
+ }
+ }
+ }
+
+ /* shadow case */
+ else
+ {
+ for ( ; srcoffs < srcend; srcoffs += srcstep, dstoffs += dststep)
+ {
+ UINT16 src = sprite_source[(srcoffs >> 10) & 0x1ff];
+ if (src)
+ {
+ src = (src >> (((srcoffs ^ flipxor) >> 6) & 0x0c)) & 0x0f;
+ if (src)
+ sprite_dest_base[(dstoffs >> 8) & 0x1ff] = color;
+ }
+ }
+ }
+
+ sprite_source_offs += width;
+ sprite_dest_offs = dstoffs >> 8;
+}
+
+
+
+/*************************************
+ *
+ * Shift register read/write
+ *
+ *************************************/
+
+void btoads_to_shiftreg(UINT32 address, UINT16 *shiftreg)
+{
+ address &= ~0x40000000;
+
+ /* reads from this first region are usual shift register reads */
+ if (address >= 0xa0000000 && address <= 0xa3ffffff)
+ memcpy(shiftreg, &vram_fg_display[TOWORD(address & 0x3fffff)], TOBYTE(0x1000));
+
+ /* reads from this region set the sprite destination address */
+ else if (address >= 0xa4000000 && address <= 0xa7ffffff)
+ {
+ sprite_dest_base = &vram_fg_draw[TOWORD(address & 0x3fc000)];
+ sprite_dest_offs = (INT16)((address & 0x3ff) << 2) >> 2;
+ }
+
+ /* reads from this region set the sprite source address */
+ else if (address >= 0xa8000000 && address <= 0xabffffff)
+ {
+ memcpy(shiftreg, &btoads_vram_fg_data[TOWORD(address & 0x7fc000)], TOBYTE(0x2000));
+ sprite_source_offs = (address & 0x003fff) >> 3;
+ }
+
+ else
+ logerror("%08X:btoads_to_shiftreg(%08X)\n", activecpu_get_pc(), address);
+}
+
+
+void btoads_from_shiftreg(UINT32 address, UINT16 *shiftreg)
+{
+ address &= ~0x40000000;
+
+ /* writes to this first region are usual shift register writes */
+ if (address >= 0xa0000000 && address <= 0xa3ffffff)
+ memcpy(&vram_fg_display[TOWORD(address & 0x3fc000)], shiftreg, TOBYTE(0x1000));
+
+ /* writes to this region are ignored for our purposes */
+ else if (address >= 0xa4000000 && address <= 0xa7ffffff)
+ ;
+
+ /* writes to this region copy standard data */
+ else if (address >= 0xa8000000 && address <= 0xabffffff)
+ memcpy(&btoads_vram_fg_data[TOWORD(address & 0x7fc000)], shiftreg, TOBYTE(0x2000));
+
+ /* writes to this region render the current sprite data */
+ else if (address >= 0xac000000 && address <= 0xafffffff)
+ render_sprite_row(shiftreg, address);
+
+ else
+ logerror("%08X:btoads_from_shiftreg(%08X)\n", activecpu_get_pc(), address);
+}
+
+
+
+/*************************************
+ *
+ * Main refresh
+ *
+ *************************************/
+
+void btoads_scanline_update(running_machine *machine, int screen, mame_bitmap *bitmap, int scanline, const tms34010_display_params *params)
+{
+ UINT32 fulladdr = ((params->rowaddr << 16) | params->coladdr) >> 4;
+ UINT16 *bg0_base = &btoads_vram_bg0[(fulladdr + (yscroll0 << 10)) & 0x3fc00];
+ UINT16 *bg1_base = &btoads_vram_bg1[(fulladdr + (yscroll1 << 10)) & 0x3fc00];
+ UINT8 *spr_base = &vram_fg_display[fulladdr & 0x3fc00];
+ UINT16 *dst = BITMAP_ADDR16(bitmap, scanline, 0);
+ int coladdr = fulladdr & 0x3ff;
+ int x;
+
+ /* for each scanline, switch off the render mode */
+ switch (screen_control & 3)
+ {
+ /* mode 0: used in ship level, snake boss, title screen (free play) */
+ case 0:
+
+ /* mode 2: used in EOA screen, jetpack level, first level, high score screen */
+ case 2:
+ for (x = params->heblnk; x < params->hsblnk; x += 2, coladdr++)
+ {
+ UINT8 sprpix = spr_base[coladdr & 0xff];
+
+ if (sprpix)
+ {
+ dst[x + 0] = sprpix;
+ dst[x + 1] = sprpix;
+ }
+ else
+ {
+ UINT16 bg0pix = bg0_base[(coladdr + xscroll0) & 0xff];
+ UINT16 bg1pix = bg1_base[(coladdr + xscroll1) & 0xff];
+
+ if (bg1pix & 0xff)
+ dst[x + 0] = bg1pix & 0xff;
+ else
+ dst[x + 0] = bg0pix & 0xff;
+
+ if (bg1pix >> 8)
+ dst[x + 1] = bg1pix >> 8;
+ else
+ dst[x + 1] = bg0pix >> 8;
+ }
+ }
+ break;
+
+ /* mode 1: used in snow level, title screen (free play), top part of rolling ball level */
+ case 1:
+ for (x = params->heblnk; x < params->hsblnk; x += 2, coladdr++)
+ {
+ UINT8 sprpix = spr_base[coladdr & 0xff];
+
+ if (sprpix && !(sprpix & 0x80))
+ {
+ dst[x + 0] = sprpix;
+ dst[x + 1] = sprpix;
+ }
+ else
+ {
+ UINT16 bg0pix = bg0_base[(coladdr + xscroll0) & 0xff];
+ UINT16 bg1pix = bg1_base[(coladdr + xscroll1) & 0xff];
+
+ if (bg0pix & 0xff)
+ dst[x + 0] = bg0pix & 0xff;
+ else if (bg1pix & 0x80)
+ dst[x + 0] = bg1pix & 0xff;
+ else if (sprpix)
+ dst[x + 0] = sprpix;
+ else
+ dst[x + 0] = bg1pix & 0xff;
+
+ if (bg0pix >> 8)
+ dst[x + 1] = bg0pix >> 8;
+ else if (bg1pix & 0x8000)
+ dst[x + 1] = bg1pix >> 8;
+ else if (sprpix)
+ dst[x + 1] = sprpix;
+ else
+ dst[x + 1] = bg1pix >> 8;
+ }
+ }
+ break;
+
+ /* mode 3: used in toilet level, toad intros, bottom of rolling ball level */
+ case 3:
+ for (x = params->heblnk; x < params->hsblnk; x += 2, coladdr++)
+ {
+ UINT16 bg0pix = bg0_base[(coladdr + xscroll0) & 0xff];
+ UINT16 bg1pix = bg1_base[(coladdr + xscroll1) & 0xff];
+ UINT8 sprpix = spr_base[coladdr & 0xff];
+
+ if (bg1pix & 0x80)
+ dst[x + 0] = bg1pix & 0xff;
+ else if (sprpix & 0x80)
+ dst[x + 0] = sprpix;
+ else if (bg1pix & 0xff)
+ dst[x + 0] = bg1pix & 0xff;
+ else if (sprpix)
+ dst[x + 0] = sprpix;
+ else
+ dst[x + 0] = bg0pix & 0xff;
+
+ if (bg1pix & 0x8000)
+ dst[x + 1] = bg1pix >> 8;
+ else if (sprpix & 0x80)
+ dst[x + 1] = sprpix;
+ else if (bg1pix >> 8)
+ dst[x + 1] = bg1pix >> 8;
+ else if (sprpix)
+ dst[x + 1] = sprpix;
+ else
+ dst[x + 1] = bg0pix >> 8;
+ }
+ break;
+ }
+
+ /* debugging - dump the screen contents to a file */
+#if BT_DEBUG
+ if (input_code_pressed(KEYCODE_X))
+ {
+ static int count = 0;
+ char name[10];
+ FILE *f;
+ int i;
+
+ sprintf(name, "disp%d.log", count++);
+ f = fopen(name, "w");
+ fprintf(f, "screen_control = %04X\n\n", screen_control << 8);
+
+ for (i = 0; i < 3; i++)
+ {
+ UINT16 *base = (i == 0) ? (UINT16 *)vram_fg_display : (i == 1) ? btoads_vram_bg0 : btoads_vram_bg1;
+ int xscr = (i == 0) ? 0 : (i == 1) ? xscroll0 : xscroll1;
+ int yscr = (i == 0) ? 0 : (i == 1) ? yscroll0 : yscroll1;
+ int y;
+
+ for (y = 0; y < 224; y++)
+ {
+ UINT32 offs = ((y + yscr) & 0xff) * TOWORD(0x4000);
+ for (x = 0; x < 256; x++)
+ {
+ UINT16 pix = base[offs + ((x + xscr) & 0xff)];
+ fprintf(f, "%02X%02X", pix & 0xff, pix >> 8);
+ if (x % 16 == 15) fprintf(f, " ");
+ }
+ fprintf(f, "\n");
+ }
+ fprintf(f, "\n\n");
+ }
+ fclose(f);
+ }
+
+ logerror("---VBLANK---\n");
+#endif
+}