// license:BSD-3-Clause // copyright-holders:Nathan Woods,Frank Palazzolo /***************************************************************************** * * includes/stic.h * ****************************************************************************/ #ifndef MAME_VIDEO_STIC_H #define MAME_VIDEO_STIC_H // the Intellivision emulation scales to match the output format at the last // step. The Intellivision keyboard component appears to be 320x96, but can // also run Intellivision carts, so x-coordinates are conditionally scaled // by 2. #define INTV_X_SCALE 1 #define INTV_Y_SCALE 1 #define INTVKBD_X_SCALE 2 #define INTVKBD_Y_SCALE INTV_Y_SCALE struct intv_sprite_type { int visible; int xpos; int ypos; int coll; int collision; int doublex; int doubley; int quady; int xflip; int yflip; int behind_foreground; int grom; int card; int color; int doubleyres; int dirty; }; // ======================> stic_device class stic_device : public device_t, public device_video_interface { public: // GROM/GRAM cards are 8x8 static constexpr unsigned CARD_WIDTH = 8; static constexpr unsigned CARD_HEIGHT = 8; // Intellivision resolution is 20x12 BACKTAB CARDs, minus the rightmost column, // for an effective resolution of (19 * 8 + 1 * 7) x (12 * 8) == 159x96. // // MOB scanline height can be half of a card scanline height, so y-coordinates // are scaled by 2. static constexpr unsigned X_SCALE = 1; static constexpr unsigned Y_SCALE = 2; // overscan sizes in intv pixels // these values are approximate. static constexpr unsigned OVERSCAN_LEFT_WIDTH = 13; static constexpr unsigned OVERSCAN_RIGHT_WIDTH = 17; static constexpr unsigned OVERSCAN_TOP_HEIGHT = 12; static constexpr unsigned OVERSCAN_BOTTOM_HEIGHT = 12; //Timing constants based on Joe Zbiciak's documentation static constexpr int CYCLES_PER_SCANLINE = 57; static constexpr int ROW_BUSRQ = 110; // CPU paused during backtab row buffering static constexpr int FRAME_BUSRQ = 42; // CPU paused just after end of vblank and before first row fetch (approximate) static constexpr int VBLANK_END = 3790; static constexpr int FIRST_FETCH = 3933; /*** BACKTAB ****************************************************************/ // BACKTAB is made up of 20x12 cards // (the first 19 columns are 8x8, the 20th column is 7x8) static constexpr unsigned BACKTAB_WIDTH = 20; static constexpr unsigned BACKTAB_HEIGHT = 12; static constexpr unsigned SCREEN_WIDTH = (OVERSCAN_LEFT_WIDTH + (BACKTAB_WIDTH * CARD_WIDTH) - 1 + OVERSCAN_RIGHT_WIDTH) * X_SCALE; static constexpr unsigned SCREEN_HEIGHT = (OVERSCAN_TOP_HEIGHT + (BACKTAB_HEIGHT * CARD_HEIGHT) + OVERSCAN_BOTTOM_HEIGHT) * Y_SCALE; // construction/destruction stic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); virtual ~stic_device(); DECLARE_READ16_MEMBER(read); DECLARE_READ16_MEMBER(gram_read); DECLARE_READ16_MEMBER(grom_read) { if (offset > 0x800) printf("help! %X\n", offset); return (0xff00 | m_grom[offset]); } DECLARE_WRITE16_MEMBER(write); DECLARE_WRITE16_MEMBER(gram_write); void write_to_btb(int h, int w, uint16_t data) { m_backtab_buffer[h][w] = data; } int read_row_delay() { return m_row_delay; } int read_stic_handshake() { return m_stic_handshake; } void set_x_scale(int val) { m_x_scale = val; } void set_y_scale(int val) { m_y_scale = val; } // device-level overrides virtual void device_start() override; virtual const tiny_rom_entry *device_rom_region() const override; virtual void device_reset() override; void screenrefresh(); uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); private: /*** STIC registers *********************************************************/ // number of STIC registers static constexpr unsigned STIC_REGISTERS = 0x33; // STIC MOBs (Moveable OBjects) enum { MOB0, MOB1, MOB2, MOB3, MOB4, MOB5, MOB6, MOB7, MOBS }; // STIC Color Stack enum { CSR0, CSR1, CSR2, CSR3, CSRS }; required_region_ptr m_grom; void intv_set_pixel(bitmap_ind16 &bitmap, int x, int y, uint32_t color); uint32_t intv_get_pixel(bitmap_ind16 &bitmap, int x, int y); void intv_plot_box(bitmap_ind16 &bm, int x, int y, int w, int h, int color); bool sprites_collide(int spriteNum1, int spriteNum2); void determine_sprite_collisions(); void render_sprites(); void render_line(bitmap_ind16 &bitmap, uint8_t nextByte, uint16_t x, uint16_t y, uint8_t fgcolor, uint8_t bgcolor); void render_colored_squares(bitmap_ind16 &bitmap, uint16_t x, uint16_t y, uint8_t color0, uint8_t color1, uint8_t color2, uint8_t color3); void render_color_stack_mode(bitmap_ind16 &bitmap); void render_fg_bg_mode(bitmap_ind16 &bitmap); void copy_sprites_to_background(bitmap_ind16 &bitmap); void render_background(bitmap_ind16 &bitmap); void draw_borders(bitmap_ind16 &bitmap); #ifdef UNUSED_CODE void draw_background(bitmap_ind16 &bitmap, int transparency); void draw_sprites(bitmap_ind16 &bitmap, int behind_foreground); #endif bitmap_ind16 m_bitmap; intv_sprite_type m_sprite[MOBS]; uint8_t m_sprite_buffers[MOBS][CARD_WIDTH * 2][CARD_HEIGHT * 4 * 2 * 2]; uint16_t m_backtab_buffer[BACKTAB_HEIGHT][BACKTAB_WIDTH]; int m_color_stack_mode; int m_stic_registers[STIC_REGISTERS]; int m_color_stack_offset; int m_stic_handshake; int m_border_color; int m_col_delay; int m_row_delay; int m_left_edge_inhibit; int m_top_edge_inhibit; int m_x_scale; int m_y_scale; uint8_t m_gramdirty; uint8_t m_gram[512]; uint8_t m_gramdirtybytes[512]; }; // device type definition DECLARE_DEVICE_TYPE(STIC, stic_device) #endif // MAME_VIDEO_STIC_H