From 817df6f79e99db669a122be7ab1934aec2460d0c Mon Sep 17 00:00:00 2001 From: Scott Stone Date: Thu, 11 Jul 2013 17:54:40 +0000 Subject: [PATCH] another missing from konicdev split (nw) --- .gitattributes | 1 + src/mame/video/k007121.c | 355 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 356 insertions(+) create mode 100644 src/mame/video/k007121.c diff --git a/.gitattributes b/.gitattributes index 60e589410b4..d44f12b5224 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5525,6 +5525,7 @@ src/mame/video/jalblend.c svneol=native#text/plain src/mame/video/jalblend.h svneol=native#text/plain src/mame/video/jedi.c svneol=native#text/plain src/mame/video/jpmimpct.c svneol=native#text/plain +src/mame/video/k007121.c svneol=native#text/plain src/mame/video/k007121.h svneol=native#text/plain src/mame/video/k007342.c svneol=native#text/plain src/mame/video/k007342.h svneol=native#text/plain diff --git a/src/mame/video/k007121.c b/src/mame/video/k007121.c new file mode 100644 index 00000000000..7c9a2bbc847 --- /dev/null +++ b/src/mame/video/k007121.c @@ -0,0 +1,355 @@ +/* +Konami 007121 +------ +This is an interesting beast. It is an evolution of the 005885, with more +features. Many games use two of these in pair. +It manages sprites and two 32x32 tilemaps. The tilemaps can be joined to form +a single 64x32 one, or one of them can be moved to the side of screen, giving +a high score display suitable for vertical games. +The chip also generates clock and interrupt signals suitable for a 6809. +It uses 0x2000 bytes of RAM for the tilemaps and sprites, and an additional +0x100 bytes, maybe for scroll RAM and line buffers. The maximum addressable +ROM is 0x80000 bytes (addressed 16 bits at a time). Tile and sprite data both +come from the same ROM space. +Two 256x4 lookup PROMs are also used to increase the color combinations. +All tilemap / sprite priority handling is done internally and the chip exports +7 bits of color code, composed of 2 bits of palette bank, 1 bit indicating tile +or sprite, and 4 bits of ROM data remapped through the PROM. + +inputs: +- address lines (A0-A13) +- data lines (DB0-DB7) +- misc interface stuff +- data from the gfx ROMs (RDL0-RDL7, RDU0-RDU7) +- data from the tile lookup PROMs (VCD0-VCD3) +- data from the sprite lookup PROMs (OCD0-OCD3) + +outputs: +- address lines for tilemap RAM (AX0-AX12) +- data lines for tilemap RAM (VO0-VO7) +- address lines for the small RAM (FA0-FA7) +- data lines for the small RAM (FD0-FD7) +- address lines for the gfx ROMs (R0-R17) +- address lines for the tile lookup PROMs (VCF0-VCF3, VCB0-VCB3) +- address lines for the sprite lookup PROMs (OCB0-OCB3, OCF0-OCF3) +- NNMI, NIRQ, NFIR, NE, NQ for the main CPU +- misc interface stuff +- color code to be output on screen (COA0-COA6) + + +control registers +000: scroll x (low 8 bits) +001: -------x scroll x (high bit) + ------x- enable rowscroll? (combatsc) + ----x--- this probably selects an alternate screen layout used in combat + school where tilemap #2 is overlayed on front and doesn't scroll. + The 32 lines of the front layer can be individually turned on or + off using the second 32 bytes of scroll RAM. +002: scroll y +003: -------x bit 13 of the tile code + ------x- unknown (contra) + -----x-- might be sprite / tilemap priority (0 = sprites have priority) + (combat school, contra, haunted castle(0/1), labyrunr) + ----x--- selects sprite buffer (and makes a copy to a private buffer?) + ---x---- screen layout selector: + when this is set, 5 columns are added on the left of the screen + (that means 5 rows at the top for vertical games), and the + rightmost 2 columns are chopped away. + Tilemap #2 is used to display the 5 additional columns on the + left. The rest of tilemap #2 is not used and can be used as work + RAM by the program. + The visible area becomes 280x224. + Note that labyrunr changes this at runtime, setting it during + gameplay and resetting it on the title screen and crosshatch. + --x----- might be sprite / tilemap priority (0 = sprites have priority) + (combat school, contra, haunted castle(0/1), labyrunr) + -x------ Chops away the leftmost and rightmost columns, switching the + visible area from 256 to 240 pixels. This is used by combatsc on + the scrolling stages, and by labyrunr on the title screen. + At first I thought that this enabled an extra bank of 0x40 + sprites, needed by combatsc, but labyrunr proves that this is not + the case + x------- unknown (contra) +004: ----xxxx bits 9-12 of the tile code. Only the bits enabled by the following + mask are actually used, and replace the ones selected by register + 005. + xxxx---- mask enabling the above bits +005: selects where in the attribute byte to pick bits 9-12 of the tile code, + output to pins R12-R15. The bit of the attribute byte to use is the + specified bit (0-3) + 3, that is one of bits 3-6. Bit 7 is hardcoded as + bit 8 of the code. Bits 0-2 are used for the color, however note that + some games use bit 3 as well (see below). + ------xx attribute bit to use for tile code bit 9 + ----xx-- attribute bit to use for tile code bit 10 + --xx---- attribute bit to use for tile code bit 11 + xx------ attribute bit to use for tile code bit 12 +006: ----xxxx select additional effect for bits 3-6 of the tile attribute (the + same ones indexed by register 005). Note that an attribute bit + can therefore be used at the same time to be BOTH a tile code bit + and an additional effect. + -------x bit 3 of attribute is bit 3 of color (combatsc, fastlane, flkatck) + ------x- bit 4 of attribute is tile flip X (assumption - no game uses this) + -----x-- bit 5 of attribute is tile flip Y (flkatck) + ----x--- bit 6 of attribute is tile priority over sprites (combatsc, hcastle, + labyrunr) + Note that hcastle sets this bit for layer 0, and bit 6 of the + attribute is also used as bit 12 of the tile code, however that + bit is ALWAYS set throughout the game. + combatsc uses the bit in the "graduation" scene during attract mode, + to place soldiers behind the stand. + Use in labyrunr has not been investigated yet. + --xx---- palette bank (both tiles and sprites, see contra) +007: -------x nmi enable + ------x- irq enable + -----x-- firq enable + ----x--- flip screen + ---x---- unknown (contra, labyrunr) + */ + +#include "emu.h" +#include "k007121.h" +#include "konami_helper.h" + +#define VERBOSE 0 +#define LOG(x) do { if (VERBOSE) logerror x; } while (0) + + +const device_type K007121 = &device_creator; + +k007121_device::k007121_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, K007121, "Konami 007121", tag, owner, clock, "k007121", __FILE__), + m_flipscreen(0) +{ +} + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void k007121_device::device_config_complete() +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void k007121_device::device_start() +{ + save_item(NAME(m_ctrlram)); + save_item(NAME(m_flipscreen)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void k007121_device::device_reset() +{ + int i; + + m_flipscreen = 0; + + for (i = 0; i < 8; i++) + m_ctrlram[i] = 0; +} + + +/***************************************************************************** + DEVICE HANDLERS +*****************************************************************************/ + +READ8_MEMBER( k007121_device::ctrlram_r ) +{ + assert(offset < 8); + + return m_ctrlram[offset]; +} + + +WRITE8_MEMBER( k007121_device::ctrl_w ) +{ + assert(offset < 8); + + switch (offset) + { + case 6: + /* palette bank change */ + if ((m_ctrlram[offset] & 0x30) != (data & 0x30)) + space.machine().tilemap().mark_all_dirty(); + break; + case 7: + m_flipscreen = data & 0x08; + break; + } + + m_ctrlram[offset] = data; +} + +/* + * Sprite Format + * ------------------ + * + * There are 0x40 sprites, each one using 5 bytes. However the number of + * sprites can be increased to 0x80 with a control register (Combat School + * sets it on and off during the game). + * + * Byte | Bit(s) | Use + * -----+-76543210-+---------------- + * 0 | xxxxxxxx | sprite code + * 1 | xxxx---- | color + * 1 | ----xx-- | sprite code low 2 bits for 16x8/8x8 sprites + * 1 | ------xx | sprite code bank bits 1/0 + * 2 | xxxxxxxx | y position + * 3 | xxxxxxxx | x position (low 8 bits) + * 4 | xx------ | sprite code bank bits 3/2 + * 4 | --x----- | flip y + * 4 | ---x---- | flip x + * 4 | ----xxx- | sprite size 000=16x16 001=16x8 010=8x16 011=8x8 100=32x32 + * 4 | -------x | x position (high bit) + * + * Flack Attack uses a different, "wider" layout with 32 bytes per sprite, + * mapped as follows, and the priority order is reversed. Maybe it is a + * compatibility mode with an older custom IC. It is not known how this + * alternate layout is selected. + * + * 0 -> e + * 1 -> f + * 2 -> 6 + * 3 -> 4 + * 4 -> 8 + * + */ + +void k007121_device::sprites_draw( bitmap_ind16 &bitmap, const rectangle &cliprect, gfx_element *gfx, colortable_t *ctable, + const UINT8 *source, int base_color, int global_x_offset, int bank_base, UINT32 pri_mask ) +{ + // gfx_element *gfx = gfxs[chip]; + bitmap_ind8 &priority_bitmap = gfx->machine().priority_bitmap; + int flipscreen = m_flipscreen; + int i, num, inc, offs[5]; + int is_flakatck = (ctable == NULL); + + if (is_flakatck) + { + num = 0x40; + inc = -0x20; + source += 0x3f * 0x20; + offs[0] = 0x0e; + offs[1] = 0x0f; + offs[2] = 0x06; + offs[3] = 0x04; + offs[4] = 0x08; + } + else /* all others */ + { + /* TODO: sprite limit is supposed to be per-line! (check MT #00185) */ + num = 0x40; + //num = (k007121->ctrlram[0x03] & 0x40) ? 0x80 : 0x40; /* WRONG!!! (needed by combatsc) */ + + inc = 5; + offs[0] = 0x00; + offs[1] = 0x01; + offs[2] = 0x02; + offs[3] = 0x03; + offs[4] = 0x04; + /* when using priority buffer, draw front to back */ + if (pri_mask != -1) + { + source += (num - 1)*inc; + inc = -inc; + } + } + + for (i = 0; i < num; i++) + { + int number = source[offs[0]]; /* sprite number */ + int sprite_bank = source[offs[1]] & 0x0f; /* sprite bank */ + int sx = source[offs[3]]; /* vertical position */ + int sy = source[offs[2]]; /* horizontal position */ + int attr = source[offs[4]]; /* attributes */ + int xflip = source[offs[4]] & 0x10; /* flip x */ + int yflip = source[offs[4]] & 0x20; /* flip y */ + int color = base_color + ((source[offs[1]] & 0xf0) >> 4); + int width, height; + int transparent_mask; + static const int x_offset[4] = {0x0,0x1,0x4,0x5}; + static const int y_offset[4] = {0x0,0x2,0x8,0xa}; + int x,y, ex, ey, flipx, flipy, destx, desty; + + if (attr & 0x01) sx -= 256; + if (sy >= 240) sy -= 256; + + number += ((sprite_bank & 0x3) << 8) + ((attr & 0xc0) << 4); + number = number << 2; + number += (sprite_bank >> 2) & 3; + + /* Flak Attack doesn't use a lookup PROM, it maps the color code directly */ + /* to a palette entry */ + if (is_flakatck) + transparent_mask = 1 << 0; + else + transparent_mask = colortable_get_transpen_mask(ctable, gfx, color, 0); + + if (!is_flakatck || source[0x00]) /* Flak Attack needs this */ + { + number += bank_base; + + switch (attr & 0xe) + { + case 0x06: width = height = 1; break; + case 0x04: width = 1; height = 2; number &= (~2); break; + case 0x02: width = 2; height = 1; number &= (~1); break; + case 0x00: width = height = 2; number &= (~3); break; + case 0x08: width = height = 4; number &= (~3); break; + default: width = 1; height = 1; +// logerror("Unknown sprite size %02x\n", attr & 0xe); +// popmessage("Unknown sprite size %02x\n", attr & 0xe); + } + + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + ex = xflip ? (width - 1 - x) : x; + ey = yflip ? (height - 1 - y) : y; + + if (flipscreen) + { + flipx = !xflip; + flipy = !yflip; + destx = 248 - (sx + x * 8); + desty = 248 - (sy + y * 8); + } + else + { + flipx = xflip; + flipy = yflip; + destx = global_x_offset + sx + x * 8; + desty = sy + y * 8; + } + + if (pri_mask != -1) + pdrawgfx_transmask(bitmap,cliprect,gfx, + number + x_offset[ex] + y_offset[ey], + color, + flipx,flipy, + destx,desty, + priority_bitmap,pri_mask, + transparent_mask); + else + drawgfx_transmask(bitmap,cliprect,gfx, + number + x_offset[ex] + y_offset[ey], + color, + flipx,flipy, + destx,desty, + transparent_mask); + } + } + } + + source += inc; + } +} \ No newline at end of file