diff options
Diffstat (limited to 'src/mame/video/spacefb.c')
-rw-r--r-- | src/mame/video/spacefb.c | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/src/mame/video/spacefb.c b/src/mame/video/spacefb.c new file mode 100644 index 00000000000..f201664b7bb --- /dev/null +++ b/src/mame/video/spacefb.c @@ -0,0 +1,471 @@ +/*************************************************************************** + + Space Firebird hardware + +****************************************************************************/ + +#include "driver.h" +#include "spacefb.h" +#include "video/resnet.h" + + +UINT8 *spacefb_videoram; +size_t spacefb_videoram_size; + + +/* bitmap that marks whether a given pixel has a sprite/bullet there */ +static bitmap_t *object_present_map; + +static UINT8 flipscreen; +static UINT8 gfx_bank; +static UINT8 palette_bank; +static UINT8 background_red; +static UINT8 background_blue; +static UINT8 disable_star_field; +static UINT8 color_contrast_r; +static UINT8 color_contrast_g; +static UINT8 color_contrast_b; +static UINT32 star_shift_reg; + +static double color_weights_r[3], color_weights_g[3], color_weights_b[3]; + + + +/************************************* + * + * Port bit setters + * + *************************************/ + +void spacefb_set_flip_screen(UINT8 data) +{ + flipscreen = data; + + video_screen_update_partial(0, video_screen_get_vpos(0) - 1); +} + + +void spacefb_set_gfx_bank(UINT8 data) +{ + gfx_bank = data; + + video_screen_update_partial(0, video_screen_get_vpos(0) - 1); +} + + +void spacefb_set_palette_bank(UINT8 data) +{ + palette_bank = data; + + video_screen_update_partial(0, video_screen_get_vpos(0) - 1); +} + + +void spacefb_set_background_red(UINT8 data) +{ + background_red = data; + + video_screen_update_partial(0, video_screen_get_vpos(0) - 1); +} + + +void spacefb_set_background_blue(UINT8 data) +{ + background_blue = data; + + video_screen_update_partial(0, video_screen_get_vpos(0) - 1); +} + + +void spacefb_set_disable_star_field(UINT8 data) +{ + disable_star_field = data; + + video_screen_update_partial(0, video_screen_get_vpos(0) - 1); +} + + +void spacefb_set_color_contrast_r(UINT8 data) +{ + color_contrast_r = data; + + video_screen_update_partial(0, video_screen_get_vpos(0) - 1); +} + + +void spacefb_set_color_contrast_g(UINT8 data) +{ + color_contrast_g = data; + + video_screen_update_partial(0, video_screen_get_vpos(0) - 1); +} + + +void spacefb_set_color_contrast_b(UINT8 data) +{ + color_contrast_b = data; + + video_screen_update_partial(0, video_screen_get_vpos(0) - 1); +} + + + +/************************************* + * + * Video system start + * + * The sprites use a 32 bytes palette PROM, connected to the RGB output this + * way: + * + * bit 7 -- 220 ohm resistor -- BLUE + * -- 470 ohm resistor -- BLUE + * -- 220 ohm resistor -- GREEN + * -- 470 ohm resistor -- GREEN + * -- 1 kohm resistor -- GREEN + * -- 220 ohm resistor -- RED + * -- 470 ohm resistor -- RED + * bit 0 -- 1 kohm resistor -- RED + * + * + * The schematics show that the bullet color is connected this way, + * but this is impossible + * + * 860 ohm resistor -- RED + * 68 ohm resistor -- GREEN + * + * + * The background color is connected this way: + * + * Ra -- 220 ohm resistor -- BLUE + * Rb -- 470 ohm resistor -- BLUE + * Ga -- 220 ohm resistor -- GREEN + * Gb -- 470 ohm resistor -- GREEN + * Ba -- 220 ohm resistor -- RED + * Bb -- 470 ohm resistor -- RED + * + *************************************/ + +VIDEO_START( spacefb ) +{ + /* compute the color gun weights */ + static const int resistances_rg[] = { 1000, 470, 220 }; + static const int resistances_b [] = { 470, 220 }; + + compute_resistor_weights(0, 0xff, -1.0, + 3, resistances_rg, color_weights_r, 470, 0, + 3, resistances_rg, color_weights_g, 470, 0, + 2, resistances_b, color_weights_b, 470, 0); + + object_present_map = auto_bitmap_alloc(machine->screen[0].width, machine->screen[0].height, BITMAP_FORMAT_INDEXED8); + + /* this start value positions the stars to match the flyer screen shot, + but most likely, the actual star position is random as the hardware + uses whatever value is on the shift register on power-up */ + star_shift_reg = 0x18f89; +} + + + +/************************************* + * + * Star field generator + * + *************************************/ + +#define NUM_STARFIELD_PENS (0x40) + + +INLINE void shift_star_generator(void) +{ + star_shift_reg = ((star_shift_reg << 1) | (((~star_shift_reg >> 16) & 0x01) ^ ((star_shift_reg >> 4) & 0x01))) & 0x1ffff; +} + + +static void get_starfield_pens(pen_t *pens) +{ + /* generate the pens based on the various enable bits */ + int i; + + for (i = 0; i < NUM_STARFIELD_PENS; i++) + { + UINT8 gb = ((i >> 0) & 0x01) & color_contrast_g & !disable_star_field; + UINT8 ga = ((i >> 1) & 0x01) & !disable_star_field; + UINT8 bb = ((i >> 2) & 0x01) & color_contrast_b & !disable_star_field; + UINT8 ba = (((i >> 3) & 0x01) | background_blue) & !disable_star_field; + UINT8 ra = (((i >> 4) & 0x01) | background_red) & !disable_star_field; + UINT8 rb = ((i >> 5) & 0x01) & color_contrast_r & !disable_star_field; + + UINT8 r = combine_3_weights(color_weights_r, 0, rb, ra); + UINT8 g = combine_3_weights(color_weights_g, 0, gb, ga); + UINT8 b = combine_2_weights(color_weights_b, bb, ba); + + pens[i] = MAKE_RGB(r, g, b); + } + +} + + +static void draw_starfield(running_machine *machine, + int scrnum, + mame_bitmap *bitmap, + const rectangle *cliprect) +{ + int y; + pen_t pens[NUM_STARFIELD_PENS]; + + get_starfield_pens(pens); + + /* the shift register is always shifting -- do the portion in the top VBLANK */ + if (cliprect->min_y == machine->screen[scrnum].visarea.min_y) + { + int i; + + /* one cycle delay introduced by IC10 D flip-flop at the end of the VBLANK */ + int clock_count = (SPACEFB_HBSTART - SPACEFB_HBEND) * SPACEFB_VBEND - 1; + + for (i = 0; i < clock_count; i++) + shift_star_generator(); + } + + /* visible region of the screen */ + for (y = cliprect->min_y; y <= cliprect->max_y; y++) + { + int x; + + for (x = SPACEFB_HBEND; x < SPACEFB_HBSTART; x++) + { + if (!*BITMAP_ADDR8(object_present_map, y, x)) + { + /* draw the star - the 4 possible values come from the effect of the two XOR gates */ + if (((star_shift_reg & 0x1c0ff) == 0x0c0b7) || + ((star_shift_reg & 0x1c0ff) == 0x0c0d7) || + ((star_shift_reg & 0x1c0ff) == 0x0c0bb) || + ((star_shift_reg & 0x1c0ff) == 0x0c0db)) + *BITMAP_ADDR32(bitmap, y, x) = pens[(star_shift_reg >> 8) & 0x3f]; + else + *BITMAP_ADDR32(bitmap, y, x) = pens[0]; + } + + shift_star_generator(); + } + } + + /* do the shifting in the bottom VBLANK */ + if (cliprect->max_y == machine->screen[scrnum].visarea.max_y) + { + int i; + int clock_count = (SPACEFB_HBSTART - SPACEFB_HBEND) * (SPACEFB_VTOTAL - SPACEFB_VBSTART); + + for (i = 0; i < clock_count; i++) + shift_star_generator(); + } +} + + + +/************************************* + * + * Sprite/Bullet hardware + * + * Sprites are opaque wrt. each other, + * but transparent wrt. to the + * star field. + * + *************************************/ + +#define NUM_SPRITE_PENS (0x40) + + +static void get_sprite_pens(pen_t *pens) +{ + static const double fade_weights[] = { 1.0, 1.5, 2.5, 4.0 }; + + int i; + + for (i = 0; i < NUM_SPRITE_PENS; i++) + { + UINT8 data = memory_region(REGION_PROMS)[(palette_bank << 4) | (i & 0x0f)]; + + UINT8 r0 = (data >> 0) & 0x01; + UINT8 r1 = (data >> 1) & 0x01; + UINT8 r2 = (data >> 2) & 0x01; + + UINT8 g0 = (data >> 3) & 0x01; + UINT8 g1 = (data >> 4) & 0x01; + UINT8 g2 = (data >> 5) & 0x01; + + UINT8 b1 = (data >> 6) & 0x01; + UINT8 b2 = (data >> 7) & 0x01; + + UINT8 r = combine_3_weights(color_weights_r, r0, r1, r2); + UINT8 g = combine_3_weights(color_weights_g, g0, g1, g2); + UINT8 b = combine_2_weights(color_weights_b, b1, b2); + + if (i >> 4) + { + double fade_weight = fade_weights[i >> 4]; + + /* faded pens */ + r = (r / fade_weight) + 0.5; + g = (g / fade_weight) + 0.5; + b = (b / fade_weight) + 0.5; + } + + pens[i] = MAKE_RGB(r, g, b); + } +} + + +static void draw_bullet(offs_t offs, pen_t pen, mame_bitmap *bitmap, const rectangle *cliprect) +{ + UINT8 sy; + + UINT8 *gfx = memory_region(REGION_GFX2); + + UINT8 code = spacefb_videoram[offs + 0x0200] & 0x3f; + UINT8 y = ~spacefb_videoram[offs + 0x0100] - 2; + + for (sy = 0; sy < 4; sy++) + { + UINT8 sx, dy; + + UINT8 data = gfx[(code << 2) | sy]; + UINT8 x = spacefb_videoram[offs + 0x0000]; + + if (flipscreen) + dy = ~y; + else + dy = y; + + if ((dy > cliprect->min_y) && (dy < cliprect->max_y)) + { + for (sx = 0; sx < 4; sx++) + { + if (data & 0x01) + { + UINT16 dx; + + if (flipscreen) + dx = (255 - x) * 2; + else + dx = x * 2; + + *BITMAP_ADDR32(bitmap, dy, dx + 0) = pen; + *BITMAP_ADDR32(bitmap, dy, dx + 1) = pen; + + *BITMAP_ADDR8(object_present_map, dy, dx + 0) = 1; + *BITMAP_ADDR8(object_present_map, dy, dx + 1) = 1; + } + + x = x + 1; + data = data >> 1; + } + } + + y = y + 1; + } +} + + +static void draw_sprite(offs_t offs, pen_t* pens, mame_bitmap *bitmap, const rectangle *cliprect) +{ + UINT8 sy; + + UINT8 *gfx = memory_region(REGION_GFX1); + + UINT8 code = ~spacefb_videoram[offs + 0x0200]; + UINT8 color_base = (~spacefb_videoram[offs + 0x0300] & 0x0f) << 2; + UINT8 y = ~spacefb_videoram[offs + 0x0100] - 2; + + for (sy = 0; sy < 8; sy++) + { + UINT8 sx, dy; + + UINT8 data1 = gfx[0x0000 | (code << 3) | (sy ^ 0x07)]; + UINT8 data2 = gfx[0x0800 | (code << 3) | (sy ^ 0x07)]; + + UINT8 x = spacefb_videoram[offs + 0x0000] - 3; + + if (flipscreen) + dy = ~y; + else + dy = y; + + if ((dy > cliprect->min_y) && (dy < cliprect->max_y)) + { + for (sx = 0; sx < 8; sx++) + { + UINT16 dx; + UINT8 data; + pen_t pen; + + if (flipscreen) + dx = (255 - x) * 2; + else + dx = x * 2; + + data = ((data1 << 1) & 0x02) | (data2 & 0x01); + pen = pens[color_base | data]; + + *BITMAP_ADDR32(bitmap, dy, dx + 0) = pen; + *BITMAP_ADDR32(bitmap, dy, dx + 1) = pen; + + *BITMAP_ADDR8(object_present_map, dy, dx + 0) = (data != 0); + *BITMAP_ADDR8(object_present_map, dy, dx + 1) = (data != 0); + + x = x + 1; + data1 = data1 >> 1; + data2 = data2 >> 1; + } + } + + y = y + 1; + } +} + + +static void draw_objects(mame_bitmap *bitmap, const rectangle *cliprect) +{ + pen_t sprite_pens[NUM_SPRITE_PENS]; + + offs_t offs = gfx_bank ? 0x80 : 0x00; + + /* since the way the schematics show the bullet color + connected is impossible, just use pure red for now */ + pen_t bullet_pen = MAKE_RGB(0xff, 0x00, 0x00); + + get_sprite_pens(sprite_pens); + + while (1) + { + if (spacefb_videoram[offs + 0x0300] & 0x20) + draw_bullet(offs, bullet_pen, bitmap, cliprect); + else if (spacefb_videoram[offs + 0x0300] & 0x40) + draw_sprite(offs, sprite_pens, bitmap, cliprect); + + /* next object */ + offs = offs + 1; + + /* end of bank? */ + if ((offs & 0x7f) == 0) break; + } +} + + + +/************************************* + * + * Video update + * + *************************************/ + +VIDEO_UPDATE( spacefb ) +{ + fillbitmap(object_present_map, 0, cliprect); + + draw_objects(bitmap, cliprect); + + draw_starfield(machine, screen, bitmap, cliprect); + + return 0; +} |