summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/video/s2636.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/video/s2636.c')
-rw-r--r--trunk/src/emu/video/s2636.c377
1 files changed, 377 insertions, 0 deletions
diff --git a/trunk/src/emu/video/s2636.c b/trunk/src/emu/video/s2636.c
new file mode 100644
index 00000000000..8983ee59202
--- /dev/null
+++ b/trunk/src/emu/video/s2636.c
@@ -0,0 +1,377 @@
+/**********************************************************************
+
+ Signetics 2636 video chip
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+
+ PVI REGISTER DESCRIPTION
+ ------------------------
+
+ | bit |R/W| description
+ byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
+ | | |
+ FC0 | size 4| size 3| size 2| size 1| W | size of the 4 objects(=sprites)
+ | | |
+ FC1 | |C1 |C2 |C3 |C1 |C2 |C3 | W | colors of the 4 objects
+ | | color 1 | color 2 | |
+ FC2 | |C1 |C2 |C3 |C1 |C2 |C3 | W |
+ | | color 3 | color 4 | |
+ | | |
+ FC3 | |sh |pos| W | 1=shape 0=position
+ | | | display format and position
+ FC4 | (free) | |
+ FC5 | (free) | |
+ | | |
+ FC6 | |C1 |C2 |C3 |BG |scrn colr | W | background lock and color
+ | |backg colr |enb|C1 |C2 |C3 | | 3="enable"
+ | | |
+ FC7 | sound | W | squarewave output
+ | | |
+ FC8 | N1 | N2 | W | range of the 4 display digits
+ FC9 | N3 | N4 | W |
+ | | |
+ |obj/backgrnd |complete object| R |
+ FCA | 1 | 2 | 3 | 4 | 1 | 2 | 3 | 4 | |
+ | | |
+ FCB | |VR-| object collisions | R | Composition of object and back-
+ | |LE |1/2|1/3|1/3|1/4|2/4|3/4| | ground,collision detection and
+ | | | object display as a state display
+ | | | for the status register.Set VRLE.
+ | | | wait for VRST.Read out or transmit
+ | | | [copy?] all bits until reset by
+ | | | VRST.
+ | | |
+ FCC | PORT1 | R | PORT1 and PORT2 for the range of
+ FCD | PORT2 | | the A/D conversion.Cleared by VRST
+ FCE | (free) | |
+ FCF | (free) | |
+
+
+ Size control by byte FC0
+
+ bit matrix
+ |0|0| 8x10
+ |0|1| 16x20
+ |1|0| 32x40
+ |1|1| 64x80
+
+ CE1 and not-CE2 are outputs from the PVI.$E80..$EFF also controls the
+ analog multiplexer.
+
+
+ SPRITES
+ -------
+
+ each object field: (=sprite data structure)
+
+ 0 \ 10 bytes of bitmap (Each object is 8 pixels wide.)
+ 9 /
+ A HC horizontal object coordinate
+ B HCB horizontal duplicate coordinate
+ C VC vertical object coordinate
+ D VCB vertical duplicate coordinate
+
+*************************************************************/
+
+#include "emu.h"
+#include "video/s2636.h"
+#include "sound/s2636.h"
+
+/*************************************
+ *
+ * Constants
+ *
+ *************************************/
+
+#define SPRITE_WIDTH (8)
+#define SPRITE_HEIGHT (10)
+
+static const int sprite_offsets[4] = { 0x00, 0x10, 0x20, 0x40 };
+
+/*************************************
+ *
+ * Internal S2636 data structure
+ *
+ *************************************/
+
+typedef struct _s2636_state s2636_state;
+struct _s2636_state
+{
+ UINT8 *work_ram;
+ int work_ram_size;
+ int y_offset;
+ int x_offset;
+
+ bitmap_ind16 *bitmap;
+ bitmap_ind16 *collision_bitmap;
+};
+
+/*************************************
+ *
+ * Inline functions
+ *
+ *************************************/
+
+INLINE s2636_state *get_safe_token( device_t *device )
+{
+ assert(device != NULL);
+ assert(device->type() == S2636);
+
+ return (s2636_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+INLINE const s2636_interface *get_interface( device_t *device )
+{
+ assert(device != NULL);
+ assert((device->type() == S2636));
+ return (const s2636_interface *) device->static_config();
+}
+
+
+/*************************************
+ *
+ * Draw a sprite
+ *
+ *************************************/
+
+static void draw_sprite( UINT8 *gfx, int color, int y, int x, int expand, int or_mode, bitmap_ind16 &bitmap, const rectangle &cliprect )
+{
+ int sy;
+
+ /* for each row */
+ for (sy = 0; sy < SPRITE_HEIGHT; sy++)
+ {
+ int sx;
+
+ /* for each pixel on the row */
+ for (sx = 0; sx < SPRITE_WIDTH; sx++)
+ {
+ int ey;
+
+ /* each pixel can be expanded */
+ for (ey = 0; ey <= expand; ey++)
+ {
+ int ex;
+
+ for (ex = 0; ex <= expand; ex++)
+ {
+ /* compute effective destination pixel */
+ int ty = y + sy * (expand + 1) + ey;
+ int tx = x + sx * (expand + 1) + ex;
+
+ /* get out if outside the drawing region */
+ if (!cliprect.contains(tx, ty))
+ continue;
+
+ /* get out if current image bit is transparent */
+ if (((gfx[sy] << sx) & 0x80) == 0x00)
+ continue;
+
+ if (or_mode)
+ bitmap.pix16(ty, tx) = 0x08 | bitmap.pix16(ty, tx) | color;
+ else
+ bitmap.pix16(ty, tx) = 0x08 | color;
+ }
+ }
+ }
+ }
+}
+
+
+
+/*************************************
+ *
+ * Collision detection
+ *
+ *************************************/
+
+static int check_collision( device_t *device, int spriteno1, int spriteno2, const rectangle &cliprect )
+{
+ s2636_state *s2636 = get_safe_token(device);
+ int checksum = 0;
+
+ UINT8* attr1 = &s2636->work_ram[sprite_offsets[spriteno1]];
+ UINT8* attr2 = &s2636->work_ram[sprite_offsets[spriteno2]];
+
+ /* TODO: does not check shadow sprites yet */
+
+ s2636->collision_bitmap->fill(0, cliprect);
+
+ if ((attr1[0x0a] != 0xff) && (attr2[0x0a] != 0xff))
+ {
+ int x, y;
+
+ int x1 = attr1[0x0a] + s2636->x_offset;
+ int y1 = attr1[0x0c] + s2636->y_offset;
+ int x2 = attr2[0x0a] + s2636->x_offset;
+ int y2 = attr2[0x0c] + s2636->y_offset;
+
+ int expand1 = (s2636->work_ram[0xc0] >> (spriteno1 << 1)) & 0x03;
+ int expand2 = (s2636->work_ram[0xc0] >> (spriteno2 << 1)) & 0x03;
+
+ /* draw first sprite */
+ draw_sprite(attr1, 1, y1, x1, expand1, FALSE, *s2636->collision_bitmap, cliprect);
+
+ /* get fingerprint */
+ for (x = x1; x < x1 + SPRITE_WIDTH; x++)
+ for (y = y1; y < y1 + SPRITE_HEIGHT; y++)
+ {
+ if (!cliprect.contains(x, y))
+ continue;
+
+ checksum = checksum + s2636->collision_bitmap->pix16(y, x);
+ }
+
+ /* black out second sprite */
+ draw_sprite(attr2, 0, y2, x2, expand2, FALSE, *s2636->collision_bitmap, cliprect);
+
+ /* remove fingerprint */
+ for (x = x1; x < x1 + SPRITE_WIDTH; x++)
+ for (y = y1; y < y1 + SPRITE_HEIGHT; y++)
+ {
+ if (!cliprect.contains(x, y))
+ continue;
+
+ checksum = checksum - s2636->collision_bitmap->pix16(y, x);
+ }
+ }
+
+ return (checksum != 0);
+}
+
+
+
+/*************************************
+ *
+ * Main drawing
+ *
+ *************************************/
+
+bitmap_ind16 &s2636_update( device_t *device, const rectangle &cliprect )
+{
+ s2636_state *s2636 = get_safe_token(device);
+ UINT8 collision = 0;
+ int spriteno;
+
+ s2636->bitmap->fill(0, cliprect);
+
+ for (spriteno = 0; spriteno < 4; spriteno++)
+ {
+ int color, expand, x, y;
+ UINT8* attr = &s2636->work_ram[sprite_offsets[spriteno]];
+
+ /* get out if sprite is turned off */
+ if (attr[0x0a] == 0xff)
+ continue;
+
+ x = attr[0x0a] + s2636->x_offset;
+ y = attr[0x0c] + s2636->y_offset;
+
+ color = (s2636->work_ram[0xc1 + (spriteno >> 1)] >> ((spriteno & 1) ? 0 : 3)) & 0x07;
+ expand = (s2636->work_ram[0xc0] >> (spriteno << 1)) & 0x03;
+
+ draw_sprite(attr, color, y, x, expand, TRUE, *s2636->bitmap, cliprect);
+
+ /* bail if no shadow sprites */
+ if ((attr[0x0b] == 0xff) || (attr[0x0d] == 0xfe))
+ continue;
+
+ x = attr[0x0b] + s2636->x_offset;
+
+ while (y < 0xff)
+ {
+ y = y + SPRITE_HEIGHT + attr[0x0d];
+
+ draw_sprite(attr, color, y, x, expand, TRUE, *s2636->bitmap, cliprect);
+ }
+ }
+
+ /* collision detection */
+ if (check_collision(device, 0, 1, cliprect)) collision |= 0x20;
+ if (check_collision(device, 0, 2, cliprect)) collision |= 0x10;
+ if (check_collision(device, 0, 3, cliprect)) collision |= 0x08;
+ if (check_collision(device, 1, 2, cliprect)) collision |= 0x04;
+ if (check_collision(device, 1, 3, cliprect)) collision |= 0x02;
+ if (check_collision(device, 2, 3, cliprect)) collision |= 0x01;
+
+ s2636->work_ram[0xcb] = collision;
+
+ return *s2636->bitmap;
+}
+
+
+/*************************************
+ *
+ * Work RAM access handlers
+ *
+ *************************************/
+
+WRITE8_DEVICE_HANDLER( s2636_work_ram_w )
+{
+ s2636_state *s2636 = get_safe_token(device);
+
+ assert(offset < s2636->work_ram_size);
+
+ if ( offset == 0xc7 )
+ {
+ const s2636_interface *intf = get_interface(device);
+ if ( intf->sound && *intf->sound )
+ {
+ s2636_soundport_w(device->machine().device(intf->sound), 0, data);
+ }
+ }
+
+ s2636->work_ram[offset] = data;
+}
+
+
+READ8_DEVICE_HANDLER( s2636_work_ram_r )
+{
+ s2636_state *s2636 = get_safe_token(device);
+
+ assert(offset < s2636->work_ram_size);
+
+ return s2636->work_ram[offset];
+}
+
+/*************************************
+ *
+ * Device interface
+ *
+ *************************************/
+
+static DEVICE_START( s2636 )
+{
+ s2636_state *s2636 = get_safe_token(device);
+ const s2636_interface *intf = get_interface(device);
+ screen_device *screen = downcast<screen_device *>(device->machine().device(intf->screen));
+ int width = screen->width();
+ int height = screen->height();
+
+ s2636->work_ram_size = intf->work_ram_size;
+ s2636->x_offset = intf->x_offset;
+ s2636->y_offset = intf->y_offset;
+
+ s2636->work_ram = auto_alloc_array_clear(device->machine(), UINT8, intf->work_ram_size);
+ s2636->bitmap = auto_bitmap_ind16_alloc(device->machine(), width, height);
+ s2636->collision_bitmap = auto_bitmap_ind16_alloc(device->machine(), width, height);
+
+ device->save_item(NAME(s2636->x_offset));
+ device->save_item(NAME(s2636->y_offset));
+ device->save_pointer(NAME(s2636->work_ram), s2636->work_ram_size);
+ device->save_item(NAME(*s2636->bitmap));
+ device->save_item(NAME(*s2636->collision_bitmap));
+}
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID( p, s ) p##s2636##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START
+#define DEVTEMPLATE_NAME "Signetics 2636"
+#define DEVTEMPLATE_FAMILY "Signetics Video Chips"
+#include "devtempl.h"
+
+
+DEFINE_LEGACY_DEVICE(S2636, s2636);