// license:BSD-3-Clause // copyright-holders:Quench, David Haywood /* GP9001 Video Controller */ #ifndef MAME_VIDEO_GP9001_H #define MAME_VIDEO_GP9001_H #pragma once class gp9001vdp_device : public device_t, public device_gfx_interface, public device_video_interface, public device_memory_interface { enum { TIMER_RAISE_IRQ }; public: gp9001vdp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); auto vint_out_cb() { return m_vint_out_cb.bind(); } void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, const uint8_t* primap); void gp9001_draw_custom_tilemap(bitmap_ind16 &bitmap, int layer, const uint8_t* priremap, const uint8_t* pri_enable); void gp9001_render_vdp(bitmap_ind16 &bitmap, const rectangle &cliprect); void gp9001_screen_eof(); void create_tilemaps(); void init_scroll_regs(); bitmap_ind8 *custom_priority_bitmap; void map(address_map &map); // game-specific hack stuff void disable_sprite_buffer() { sp.use_sprite_buffer = 0; } void set_tm_extra_offsets(int layer, int xn, int yn, int xf, int yf) { tm[layer].set_extra_offsets(xn, yn, xf, yf); } void set_sp_extra_offsets(int xn, int yn, int xf, int yf) { sp.set_extra_offsets(xn, yn, xf, yf); } // ROM banking control void set_gfxrom_banked() { gfxrom_is_banked = true; } void set_gfxrom_bank(unsigned index, uint16_t value) { if (gfxrom_bank[index] != value) { gfxrom_bank[index] = value; gfxrom_bank_dirty = true; } } // access to VDP DECLARE_READ16_MEMBER(gp9001_vdp_r); DECLARE_WRITE16_MEMBER(gp9001_vdp_w); DECLARE_READ16_MEMBER(gp9001_vdp_alt_r); DECLARE_WRITE16_MEMBER(gp9001_vdp_alt_w); DECLARE_READ_LINE_MEMBER(hsync_r); DECLARE_READ_LINE_MEMBER(vsync_r); DECLARE_READ_LINE_MEMBER(fblank_r); // this bootleg has strange access DECLARE_READ16_MEMBER(pipibibi_bootleg_videoram16_r); DECLARE_WRITE16_MEMBER(pipibibi_bootleg_videoram16_w); DECLARE_READ16_MEMBER(pipibibi_bootleg_spriteram16_r); DECLARE_WRITE16_MEMBER(pipibibi_bootleg_spriteram16_w); DECLARE_WRITE16_MEMBER(pipibibi_bootleg_scroll_w); protected: virtual void device_start() override; virtual void device_reset() override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; virtual space_config_vector memory_space_config() const override; address_space_config m_space_config; template TILE_GET_INFO_MEMBER(get_tile_info); private: // internal handlers template DECLARE_WRITE16_MEMBER(tmap_w); static constexpr unsigned BG_VRAM_SIZE = 0x1000; /* Background RAM size */ static constexpr unsigned FG_VRAM_SIZE = 0x1000; /* Foreground RAM size */ static constexpr unsigned TOP_VRAM_SIZE = 0x1000; /* Top Layer RAM size */ static constexpr unsigned SPRITERAM_SIZE = 0x0800; /* Sprite RAM size */ static constexpr unsigned SPRITE_FLIPX = 0x1000; /* Sprite flip flags */ static constexpr unsigned SPRITE_FLIPY = 0x2000; struct gp9001layeroffsets { int normal; int flipped; }; struct gp9001layer { void set_extra_offsets(int xn, int yn, int xf, int yf) { extra_xoffset.normal = xn; extra_yoffset.normal = yn; extra_xoffset.flipped = xf; extra_yoffset.flipped = yf; } uint16_t flip; uint16_t scrollx; uint16_t scrolly; gp9001layeroffsets extra_xoffset; gp9001layeroffsets extra_yoffset; }; struct tilemaplayer : gp9001layer { void set_scrollx_and_flip_reg(uint16_t data, uint16_t mem_mask, bool f); void set_scrolly_and_flip_reg(uint16_t data, uint16_t mem_mask, bool f); tilemap_t *tmap; }; struct spritelayer : gp9001layer { void set_scrollx_and_flip_reg(uint16_t data, uint16_t mem_mask, bool f); void set_scrolly_and_flip_reg(uint16_t data, uint16_t mem_mask, bool f); bool use_sprite_buffer; std::unique_ptr vram16_buffer; // vram buffer for this layer }; int get_tile_number(int layer, int index) { uint16_t const value = m_vram[layer][(index << 1) | 1]; if (gfxrom_is_banked) return (gfxrom_bank[(value >> 13) & 7] << 13) | (value & 0x1fff); else return value; } static const gfx_layout tilelayout, spritelayout; DECLARE_GFXDECODE_MEMBER(gfxinfo); void gp9001_voffs_w(uint16_t data, uint16_t mem_mask); int gp9001_videoram16_r(void); void gp9001_videoram16_w(uint16_t data, uint16_t mem_mask); uint16_t gp9001_vdpstatus_r(void); void gp9001_scroll_reg_select_w(uint16_t data, uint16_t mem_mask); void gp9001_scroll_reg_data_w(uint16_t data, uint16_t mem_mask); uint16_t gp9001_voffs; uint16_t gp9001_scroll_reg; tilemaplayer tm[3]; spritelayer sp; // technically this is just rom banking, allowing the chip to see more graphic ROM, however it's easier to handle it // in the chip implementation than externally for now (which would require dynamic decoding of the entire charsets every // time the bank was changed) bool gfxrom_is_banked; bool gfxrom_bank_dirty; /* dirty flag of object bank (for Batrider) */ uint16_t gfxrom_bank[8]; /* Batrider object bank */ required_shared_ptr_array m_vram; required_shared_ptr m_spriteram; devcb_write_line m_vint_out_cb; emu_timer *m_raise_irq_timer; }; DECLARE_DEVICE_TYPE(GP9001_VDP, gp9001vdp_device) #endif // MAME_VIDEO_GP9001_H