/*************************************************************************** -= Sky Fox / Exerizer =- driver by Luca Elia (l.elia@tin.it) [ 1 Background ] The stars in the background are not tile based (I think!) and their rendering is entirely guesswork for now.. I draw a star for each horizontal line using 2 bytes in the background rom: - the first byte seems a color / shape info - the second byte seems a position info The rom holds 4 chunks of $2000 bytes. Most of the data does not change between chunks, while the remaining part (which is rendered to what seems a "milky way") pulsates in color and/or shape to simulate the shimmering of stars (?!) if we draw one chunk only and cycle through the four. Indeed, there's a register cycling through 4 values. Since the result kind of matches a screenshot we have, I feel the drawn result is not that far from reality. On the other hand we have a random arrangement of stars, so it's hard to tell for sure.. [ 256 Sprites ] Sprites are 8 planes deep and can be 8x8, 16x16 or 32x32 pixels in size. They are stored as 32x32x8 tiles in the ROMs. ***************************************************************************/ #include "emu.h" #include "includes/skyfox.h" /*************************************************************************** Memory Handlers ***************************************************************************/ #ifdef UNUSED_FUNCTION READ8_HANDLER( skyfox_vregs_r ) // for debug { skyfox_state *state = space->machine().driver_data(); return state->m_vreg[offset]; } #endif WRITE8_HANDLER( skyfox_vregs_w ) { skyfox_state *state = space->machine().driver_data(); state->m_vreg[offset] = data; switch (offset) { case 0: state->m_bg_ctrl = data; break; case 1: soundlatch_w(space, 0, data); break; case 2: break; case 3: break; case 4: break; case 5: break; case 6: break; case 7: break; } } /*************************************************************************** Convert the color PROMs into a more useable format. There are three 256x4 palette PROMs (one per gun). I don't know the exact values of the resistors between the RAM and the RGB output. I assumed these values (the same as Commando) bit 3 -- 220 ohm resistor -- RED/GREEN/BLUE -- 470 ohm resistor -- RED/GREEN/BLUE -- 1 kohm resistor -- RED/GREEN/BLUE bit 0 -- 2.2kohm resistor -- RED/GREEN/BLUE ***************************************************************************/ PALETTE_INIT( skyfox ) { int i; for (i = 0; i < 256; i++) { int bit0, bit1, bit2, bit3, r, g, b; /* red component */ bit0 = (color_prom[i] >> 0) & 0x01; bit1 = (color_prom[i] >> 1) & 0x01; bit2 = (color_prom[i] >> 2) & 0x01; bit3 = (color_prom[i] >> 3) & 0x01; r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; /* green component */ bit0 = (color_prom[i + 256] >> 0) & 0x01; bit1 = (color_prom[i + 256] >> 1) & 0x01; bit2 = (color_prom[i + 256] >> 2) & 0x01; bit3 = (color_prom[i + 256] >> 3) & 0x01; g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; /* blue component */ bit0 = (color_prom[i + 2*256] >> 0) & 0x01; bit1 = (color_prom[i + 2*256] >> 1) & 0x01; bit2 = (color_prom[i + 2*256] >> 2) & 0x01; bit3 = (color_prom[i + 2*256] >> 3) & 0x01; b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; palette_set_color(machine, i, MAKE_RGB(r, g, b)); } /* Grey scale for the background??? */ for (i = 0; i < 256; i++) { palette_set_color(machine,i + 256, MAKE_RGB(i, i, i)); } } /*************************************************************************** Sprites Drawing Offset: Value: 03 Code: selects one of the 32x32 tiles in the ROMs. (Tiles $80-ff are bankswitched to cover $180 tiles) 02 Code + Attr 7654 ---- Code (low 4 bits) 8x8 sprites use bits 7654 (since there are 16 8x8 tiles in the 32x32 one) 16x16 sprites use bits --54 (since there are 4 16x16 tiles in the 32x32 one) 32x32 sprites use no bits (since the 32x32 tile is already selected) 7--- 3--- Size 1--- 1--- : 32x32 sprites 0--- 1--- : 16x16 sprites 8x8 sprites otherwise ---- -2-- Flip Y ---- --1- Flip X ---- ---0 X Low Bit 00 Y 01 X (High 8 Bits) ***************************************************************************/ static void draw_sprites( running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect ) { skyfox_state *state = machine.driver_data(); int offs; int width = machine.primary_screen->width(); int height = machine.primary_screen->height(); /* The 32x32 tiles in the 80-ff range are bankswitched */ int shift =(state->m_bg_ctrl & 0x80) ? (4 - 1) : 4; for (offs = 0; offs < state->m_spriteram_size; offs += 4) { int xstart, ystart, xend, yend; int xinc, yinc, dx, dy; int low_code, high_code, n; int y = state->m_spriteram[offs + 0]; int x = state->m_spriteram[offs + 1]; int code = state->m_spriteram[offs + 2] + state->m_spriteram[offs + 3] * 256; int flipx = code & 0x2; int flipy = code & 0x4; x = x * 2 + (code & 1); // add the least significant bit high_code = ((code >> 4) & 0x7f0) + ((code & 0x8000) >> shift); switch( code & 0x88 ) { case 0x88: n = 4; low_code = 0; break; case 0x08: n = 2; low_code = ((code & 0x20) ? 8 : 0) + ((code & 0x10) ? 2 : 0); break; default: n = 1; low_code = (code >> 4) & 0xf; } #define DRAW_SPRITE(DX,DY,CODE) \ drawgfx_transpen(bitmap,\ cliprect,machine.gfx[0], \ (CODE), \ 0, \ flipx,flipy, \ x + (DX),y + (DY), 0xff); \ if (state->m_bg_ctrl & 1) // flipscreen { x = width - x - (n - 1) * 8; y = height - y - (n - 1) * 8; flipx = !flipx; flipy = !flipy; } if (flipx) { xstart = n - 1; xend = -1; xinc = -1; } else { xstart = 0; xend = n; xinc = +1; } if (flipy) { ystart = n - 1; yend = -1; yinc = -1; } else { ystart = 0; yend = n; yinc = +1; } code = low_code + high_code; for (dy = ystart; dy != yend; dy += yinc) { for (dx = xstart; dx != xend; dx += xinc) DRAW_SPRITE(dx * 8, dy * 8, code++); if (n == 2) code += 2; } } } /*************************************************************************** Background Rendering ***************************************************************************/ static void draw_background(running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect) { skyfox_state *state = machine.driver_data(); UINT8 *RAM = machine.region("gfx2")->base(); int x, y, i; /* The foreground stars (sprites) move at twice this speed when the bg scroll rate [e.g. (skyfox_bg_reg >> 1) & 7] is 4 */ int pos = (state->m_bg_pos >> 4) & (512 * 2 - 1); for (i = 0 ; i < 0x1000; i++) { int pen, offs, j; offs = (i * 2 + ((state->m_bg_ctrl >> 4) & 0x3) * 0x2000) % 0x8000; pen = RAM[offs]; x = RAM[offs + 1] * 2 + (i & 1) + pos + ((i & 8) ? 512 : 0); y = ((i / 8) / 2) * 8 + (i % 8); if (state->m_bg_ctrl & 1) // flipscreen { x = 512 * 2 - (x % (512 * 2)); y = 256 - (y % 256); } for (j = 0 ; j <= ((pen & 0x80) ? 0 : 3); j++) *BITMAP_ADDR16(bitmap, (((j / 2) & 1) + y) % 256, ((j & 1) + x) % 512) = 256 + (pen & 0x7f); } } /*************************************************************************** Screen Drawing ***************************************************************************/ SCREEN_UPDATE( skyfox ) { bitmap_fill(bitmap, cliprect, 255); // the bg is black draw_background(screen->machine(), bitmap, cliprect); draw_sprites(screen->machine(), bitmap, cliprect); return 0; }