UINT32 pzletime_state::screen_update_pzletime(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { int count; int y, x; bitmap.fill(machine().pens[0], cliprect); //bg pen m_txt_tilemap->set_scrolly(0, m_tilemap_regs[0] - 3); m_txt_tilemap->set_scrollx(0, m_tilemap_regs[1]); m_mid_tilemap->set_scrolly(0, m_tilemap_regs[2] - 3); m_mid_tilemap->set_scrollx(0, m_tilemap_regs[3] - 7); if (m_video_regs[2] & 1) { count = 0; for (y = 255; y >= 0; y--) { for (x = 0; x < 512; x++) { if (m_bg_videoram[count] & 0x8000) bitmap.pix16((y - 18) & 0xff, (x - 32) & 0x1ff) = 0x300 + (m_bg_videoram[count] & 0x7fff); count++; } } } m_mid_tilemap->draw(screen, bitmap, cliprect, 0, 0); { UINT16 *spriteram = m_spriteram; int offs, spr_offs, colour, sx, sy; for(offs = 0; offs < 0x2000 / 2; offs += 4) { if(spriteram[offs + 0] == 8) break; spr_offs = spriteram[offs + 3] & 0x0fff; sy = 0x200 - (spriteram[offs + 0] & 0x1ff) - 35; sx = (spriteram[offs + 1] & 0x1ff) - 30; colour = (spriteram[offs + 0] & 0xf000) >> 12; // is spriteram[offs + 0] & 0x200 flipy? it's always set drawgfx_transpen(bitmap, cliprect, machine().gfx[1], spr_offs, colour, 0, 1, sx, sy, 0); } } m_txt_tilemap->draw(screen, bitmap, cliprect, 0, 0); if ((screen.frame_number() % 16) != 0) m_txt_tilemap->draw(screen, bitmap, cliprect, 1, 0); return 0; }
void bt459_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, u8 *pixel_data) { // initialise the blink timer if (m_blink_start > screen.frame_number()) m_blink_start = screen.frame_number(); // compute the blink state according to the programmed duty cycle const bool blink_state = ((screen.frame_number() - m_blink_start) & ( (m_command_0 & CR0302) == CR0302_1616 ? 0x10 : (m_command_0 & CR0302) == CR0302_3232 ? 0x20 : (m_command_0 & CR0302) == CR0302_6464 ? 0x40 : 0x30)) == 0; // compute the pixel mask from the pixel read mask and blink mask/state const u8 pixel_mask = m_pixel_read_mask & (blink_state ? 0xffU : ~m_pixel_blink_mask); // draw visible pixel data switch (m_command_0 & CR0100) { case CR0100_1BPP: for (int y = screen.visible_area().min_y; y <= screen.visible_area().max_y; y++) for (int x = screen.visible_area().min_x; x <= screen.visible_area().max_x; x += 8) { u8 data = *pixel_data++; bitmap.pix(y, x + 7) = get_rgb(data & 0x1, pixel_mask); data >>= 1; bitmap.pix(y, x + 6) = get_rgb(data & 0x1, pixel_mask); data >>= 1; bitmap.pix(y, x + 5) = get_rgb(data & 0x1, pixel_mask); data >>= 1; bitmap.pix(y, x + 4) = get_rgb(data & 0x1, pixel_mask); data >>= 1; bitmap.pix(y, x + 3) = get_rgb(data & 0x1, pixel_mask); data >>= 1; bitmap.pix(y, x + 2) = get_rgb(data & 0x1, pixel_mask); data >>= 1; bitmap.pix(y, x + 1) = get_rgb(data & 0x1, pixel_mask); data >>= 1; bitmap.pix(y, x + 0) = get_rgb(data & 0x1, pixel_mask); } break; case CR0100_2BPP: for (int y = screen.visible_area().min_y; y <= screen.visible_area().max_y; y++) for (int x = screen.visible_area().min_x; x <= screen.visible_area().max_x; x += 4) { u8 data = *pixel_data++; bitmap.pix(y, x + 3) = get_rgb(data & 0x3, pixel_mask); data >>= 2; bitmap.pix(y, x + 2) = get_rgb(data & 0x3, pixel_mask); data >>= 2; bitmap.pix(y, x + 1) = get_rgb(data & 0x3, pixel_mask); data >>= 2; bitmap.pix(y, x + 0) = get_rgb(data & 0x3, pixel_mask); } break; case CR0100_4BPP: for (int y = screen.visible_area().min_y; y <= screen.visible_area().max_y; y++) for (int x = screen.visible_area().min_x; x <= screen.visible_area().max_x; x += 2) { u8 data = *pixel_data++; bitmap.pix(y, x + 1) = get_rgb(data & 0x7, pixel_mask); data >>= 4; bitmap.pix(y, x + 0) = get_rgb(data & 0x7, pixel_mask); } break; case CR0100_8BPP: for (int y = screen.visible_area().min_y; y <= screen.visible_area().max_y; y++) for (int x = screen.visible_area().min_x; x <= screen.visible_area().max_x; x++) bitmap.pix(y, x) = get_rgb(*pixel_data++, pixel_mask); break; } // draw cursors when visible and not blinked off if ((m_cursor_command & (CR47 | CR46 | CR45 | CR44)) && ((m_cursor_command & CR40) == 0 || blink_state)) { // get 64x64 bitmap and cross hair cursor plane enable const u8 bm_cursor_enable = (m_cursor_command & (CR47 | CR46)) >> 6; const u8 ch_cursor_enable = (m_cursor_command & (CR45 | CR44)) >> 4; // get cross hair cursor half thickness const int ch_thickness = (m_cursor_command & CR4241) >> 1; /* * The cursor (x) value to be written is calculated as follows: * * Cx = desired display screen (x) position + H - P * * where * * P = 37 if 1:1 input multiplexing, 52 if 4:1 input multiplexing, * 57 if 5:1 input multiplexing * H = number of pixels between the first rising edge of LD* * following the falling edge of HSYNC* to active video * * The cursor (y) value to be written is calculated as follows: * * Cy = desired display screen (y) position + V - 32 * * where * * V = number of scan lines from the second sync pulse during * vertical blanking to active video * * Values from $0FC0 (-64) to $0FBF (+4031) may be loaded into the * cursor (y) register. The negative values ($0FC0 to $0FFF) are used * in situations where V < 32, and the cursor must be moved off the * top of the screen. */ const int cursor_x = m_cursor_x + ( (m_command_0 & CR0706) == CR0706_11MPX ? 37 : (m_command_0 & CR0706) == CR0706_41MPX ? 52 : (m_command_0 & CR0706) == CR0706_51MPX ? 57 : 0); const int cursor_y = (m_cursor_y < 0xfc0 ? m_cursor_y : m_cursor_y - 0x1000) + 32; // 64x64 bitmap cursor if (bm_cursor_enable) { // compute target 64x64 rectangle rectangle cursor(cursor_x - 31, cursor_x + 32, cursor_y - 31, cursor_y + 32); // intersect with screen bitmap cursor &= bitmap.cliprect(); // draw if any portion is visible if (!cursor.empty()) { for (int y = 0; y < 64; y++) { // get screen y pixel coordinate const int ypos = cursor_y - 31 + y; for (int x = 0; x < 64; x++) { // get screen x pixel coordinate const int xpos = cursor_x - 31 + x; // check if pixel is visible if (cursor.contains(xpos, ypos)) { // retrieve 2 bits of 64x64 bitmap cursor data u8 data = (m_cursor_ram[y * 16 + (x >> 2)] >> ((3 - (x & 3)) << 1)) & bm_cursor_enable; // check for dual-cursor mode and combine with cross-hair data if (ch_cursor_enable) if (((x >= 31 - ch_thickness) && (x <= 31 + ch_thickness)) || ((y >= 31 - ch_thickness) && (y <= 31 + ch_thickness))) data = (m_cursor_command & CR43) ? data | ch_cursor_enable : data ^ ch_cursor_enable; // write cursor data to screen (normal or X Window mode) if (data && !((m_command_2 & CR21) && data == 1)) bitmap.pix(ypos, xpos) = m_cursor_color[data - 1]; } } } } } // cross hair cursor if (ch_cursor_enable) { // get the cross hair cursor color const rgb_t ch_color = m_cursor_color[ch_cursor_enable - 1]; /* * The window (x) value to be written is calculated as follows: * * Wx = desired display screen (x) position + H - P * * where * * P = 5 if 1:1 input multiplexing, 20 if 4:1 input multiplexing, * 25 if 5:1 input multiplexing * H = number of pixels between the first rising edge of LD* * following the falling edge of HSYNC* to active video * * The window (y) value to be written is calculated as follows: * * Wy = desired display screen (y) position + V * * where * * V = number of scan lines from the second sync pulse during * vertical blanking to active video * * Values from $0000 to $0FFF may be written to the window (x) and * (y) registers. A full-screen cross hair is implemented by * loading the window (x,y) registers with $0000, and the window * width and height registers with $0FFF. */ const bool full_screen = (m_window_x == 0 && m_window_y == 0 && m_window_w == 0x0fff && m_window_h == 0x0fff); const int window_x = full_screen ? screen.visible_area().min_x : m_window_x + ( (m_command_0 & CR0706) == CR0706_11MPX ? 5 : (m_command_0 & CR0706) == CR0706_41MPX ? 20 : (m_command_0 & CR0706) == CR0706_51MPX ? 25 : 0); const int window_y = full_screen ? screen.visible_area().min_y : m_window_y; /* * The actual window width is 2, 8 or 10 pixels more than the * value specified by the window width register, depending on * whether 1:1, 4:1 or 5:1 input multiplexing is specified. The * actual window height is 2 pixels more than the value specified * by the window height register. Therefore, the minimum window * width is 2, 8 or 10 pixels for 1:1, 4:1 and 5:1 multiplexing, * respectively. The minimum window height is 2 pixels. * * Values from $0000 to $0FFF may be written to the window width * and height registers. * * Note: testing indicates the cross-hair cursor should be drawn * strictly inside the window, although this is not 100% clear from * the documentation. */ const int window_w = full_screen ? screen.visible_area().width() : m_window_w + ( (m_command_0 & CR0706) == CR0706_11MPX ? 2 : (m_command_0 & CR0706) == CR0706_41MPX ? 8 : (m_command_0 & CR0706) == CR0706_51MPX ? 10 : 0); const int window_h = full_screen ? screen.visible_area().height() : m_window_h + 2; // check for dual-cursor mode if (bm_cursor_enable) { // draw the cross hair cursor as vertical and horizontal filled rectangles broken by the 64x64 cursor area rectangle v1(cursor_x - ch_thickness, cursor_x + ch_thickness, window_y + 1, cursor_y - 32); rectangle v2(cursor_x - ch_thickness, cursor_x + ch_thickness, cursor_y + 33, window_y + window_h); rectangle h1(window_x + 1, cursor_x - 32, cursor_y - ch_thickness, cursor_y + ch_thickness); rectangle h2(cursor_x + 33, window_x + window_w, cursor_y - ch_thickness, cursor_y + ch_thickness); v1 &= bitmap.cliprect(); v2 &= bitmap.cliprect(); h1 &= bitmap.cliprect(); h2 &= bitmap.cliprect(); if (!v1.empty()) bitmap.fill(ch_color, v1); if (!v2.empty()) bitmap.fill(ch_color, v2); if (!h1.empty()) bitmap.fill(ch_color, h1); if (!h2.empty()) bitmap.fill(ch_color, h2); } else { // draw the cross hair cursor as unbroken vertical and horizontal filled rectangles rectangle v(cursor_x - ch_thickness, cursor_x + ch_thickness, window_y + 1, window_y + window_h); rectangle h(window_x + 1, window_x + window_w, cursor_y - ch_thickness, cursor_y + ch_thickness); v &= bitmap.cliprect(); h &= bitmap.cliprect(); if (!v.empty()) bitmap.fill(ch_color, v); if (!h.empty()) bitmap.fill(ch_color, h); } } }