/************************************* * * Draw a row of stars * *************************************/ void stars_draw_row(bitmap_rgb32 bitmap, int maxx, int y, uint32_t star_offs, uint8_t starmask) { int x; /* ensure our star offset is valid */ star_offs %= STAR_RNG_PERIOD; /* iterate over the specified number of 6MHz pixels */ for (x = 0; x < maxx; x++) { /* stars are suppressed unless V1 ^ H8 == 1 */ int enable_star = (y ^ (x >> 3)) & 1; uint8_t star; /* * The RNG clock is the master clock (18MHz) ANDed with the pixel clock (6MHz). * The divide-by-3 circuit that produces the pixel clock generates a square wave * with a 2/3 duty cycle, so the result of the AND generates a clock like this: * _ _ _ _ _ _ _ _ * MASTER: _| |_| |_| |_| |_| |_| |_| |_| | * _______ _______ ______ * PIXEL: _| |___| |___| * _ _ _ _ _ _ * RNG: _| |_| |_____| |_| |_____| |_| | * * Thus for each pixel, there are 3 master clocks and 2 RNG clocks, and the RNG * is clocked asymmetrically. To simulate this, we expand the horizontal screen * size by 3 and handle the first RNG clock with one pixel and the second RNG * clock with two pixels. */ /* first RNG clock: one pixel */ star = m_stars[star_offs++]; if (star_offs >= STAR_RNG_PERIOD) { star_offs = 0; } if (enable_star != 0 && (star & 0x80) != 0 && (star & starmask) != 0) { bitmap.pix(y, m_x_scale * x + 0)[0] = m_star_color[star & 0x3f]; } /* second RNG clock: two pixels */ star = m_stars[star_offs++]; if (star_offs >= STAR_RNG_PERIOD) { star_offs = 0; } if (enable_star != 0 && (star & 0x80) != 0 && (star & starmask) != 0) { bitmap.pix(y, m_x_scale * x + 1)[0] = m_star_color[star & 0x3f]; bitmap.pix(y, m_x_scale * x + 2)[0] = m_star_color[star & 0x3f]; } } }
/************************************* * * Bullet rendering * *************************************/ void galaxian_draw_pixel(bitmap_rgb32 bitmap, rectangle cliprect, int y, int x, rgb_t color) { if (y >= cliprect.min_y && y <= cliprect.max_y) { x *= GALAXIAN_XSCALE; x += GALAXIAN_H0START; if (x >= cliprect.min_x && x <= cliprect.max_x) { bitmap.pix(y, x)[0] = color; } x++; if (x >= cliprect.min_x && x <= cliprect.max_x) { bitmap.pix(y, x)[0] = color; } x++; if (x >= cliprect.min_x && x <= cliprect.max_x) { bitmap.pix(y, x)[0] = color; } } }
// snapshot/movie helpers //------------------------------------------------- // create_snapshot_bitmap - creates a // bitmap containing the screenshot for the // given screen //------------------------------------------------- //typedef software_renderer<UINT32, 0,0,0, 16,8,0, false, true> snap_renderer_bilinear; //typedef software_renderer<UINT32, 0,0,0, 16,8,0, false, false> snap_renderer; void create_snapshot_bitmap(screen_device screen) { // select the appropriate view in our dummy target if (m_snap_native && screen != null) { screen_device_enumerator iter = new screen_device_enumerator(machine().root_device()); int view_index = iter.indexof(screen); assert(view_index != -1); m_snap_target.set_view((unsigned)view_index); } // get the minimum width/height and set it on the target and bitmap s32 width; s32 height; compute_snapshot_size(out width, out height); m_snap_target.set_bounds(width, height); if (width != m_snap_bitmap.width() || height != m_snap_bitmap.height()) { m_snap_bitmap.resize(width, height); } // render the screen there render_primitive_list primlist = m_snap_target.get_primitives(); primlist.acquire_lock(); if (machine().options().snap_bilinear()) { //typedef software_renderer<u32, 0,0,0, 16,8,0, false, true> snap_renderer_bilinear; //snap_renderer_bilinear::draw_primitives(primlist, &m_snap_bitmap.pix(0), width, height, m_snap_bitmap.rowpixels()); software_renderer <u32, int_const_0, int_const_0, int_const_0, int_const_16, int_const_8, int_const_0, bool_const_false, bool_const_true> .draw_primitives(primlist, m_snap_bitmap.pix(0), (u32)width, (u32)height, (u32)m_snap_bitmap.rowpixels()); } else { //typedef software_renderer<u32, 0,0,0, 16,8,0, false, false> snap_renderer; //snap_renderer::draw_primitives(primlist, &m_snap_bitmap.pix(0), width, height, m_snap_bitmap.rowpixels()); software_renderer <u32, int_const_0, int_const_0, int_const_0, int_const_16, int_const_8, int_const_0, bool_const_false, bool_const_false> .draw_primitives(primlist, m_snap_bitmap.pix(0), (u32)width, (u32)height, (u32)m_snap_bitmap.rowpixels()); } primlist.release_lock(); }
/************************************* * * Space Encounters * *************************************/ //#define SPCENCTR_TOP_TRENCH_DARK_RGB32_PEN rgb_t(0x4d, 0x4d, 0x4d) //#define SPCENCTR_TOP_TRENCH_LIGHT_RGB32_PEN rgb_t(0xe6, 0xe6, 0xe6) //#define SPCENCTR_SIDE_TRENCH_DARK_RGB32_PEN rgb_t(0x1a, 0x1a, 0x1a) //#define SPCENCTR_SIDE_TRENCH_LIGHT_RGB32_PEN rgb_t(0x80, 0x80, 0x80) //#define SPCENCTR_BOTTOM_TRENCH_DARK_RGB32_PEN rgb_t(0x0d, 0x0d, 0x0d) //#define SPCENCTR_BOTTOM_TRENCH_LIGHT_RGB32_PEN rgb_t(0x66, 0x66, 0x66) //#define SPCENCTR_BRIGHTNESS_DECAY 10 //uint32_t spcenctr_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) /************************************* * * Phantom II * *************************************/ //#define PHANTOM2_CLOUD_COUNTER_START (0x0e0b) //#define PHANTOM2_CLOUD_COUNTER_END (0x1000) //#define PHANTOM2_CLOUD_COUNTER_PERIOD (PHANTOM2_CLOUD_COUNTER_END - PHANTOM2_CLOUD_COUNTER_START) //#define PHANTOM2_RGB32_CLOUD_PEN rgb_t(0xc0, 0xc0, 0xc0) //uint32_t mw8080bw_state::screen_update_phantom2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) //WRITE_LINE_MEMBER(mw8080bw_state::screen_vblank_phantom2) /************************************* * * Space Invaders * *************************************/ // the flip screen circuit is just a couple of relays on the monitor PCB uint32_t screen_update_invaders(screen_device screen, bitmap_rgb32 bitmap, rectangle cliprect) { uint8_t x = 0; uint8_t y = MW8080BW_VCOUNTER_START_NO_VBLANK; uint8_t video_data = 0; while (true) { // plot the current pixel pen_t pen = (video_data & 0x01) != 0 ? rgb_t.white() : rgb_t.black(); if (m_flip_screen != 0) { bitmap.pix(MW8080BW_VBSTART - 1 - (y - MW8080BW_VCOUNTER_START_NO_VBLANK), MW8080BW_HPIXCOUNT - 1 - x).SetUInt32(0, pen); } else { bitmap.pix(y - MW8080BW_VCOUNTER_START_NO_VBLANK, x).SetUInt32(0, pen); } // next pixel video_data = (uint8_t)(video_data >> 1); x = (uint8_t)(x + 1); // end of line? if (x == 0) { // yes, flush out the shift register for (int i = 0; i < 4; i++) { pen = (video_data & 0x01) != 0 ? rgb_t.white() : rgb_t.black(); if (m_flip_screen != 0) { bitmap.pix(MW8080BW_VBSTART - 1 - (y - MW8080BW_VCOUNTER_START_NO_VBLANK), MW8080BW_HPIXCOUNT - 1 - (256 + i)).SetUInt32(0, pen); } else { bitmap.pix(y - MW8080BW_VCOUNTER_START_NO_VBLANK, 256 + i).SetUInt32(0, pen); } video_data = (uint8_t)(video_data >> 1); } // next row, video_data is now 0, so the next line will start with 4 blank pixels y = (uint8_t)(y + 1); // end of screen? if (y == 0) { break; } } else if ((x & 0x07) == 0x04) // the video RAM is read at every 8 pixels starting with pixel 4 { offs_t offs = (offs_t)((y << 5) | (x >> 3)); video_data = m_main_ram[offs].op; } } return(0); }