1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria, Aaron Giles, Alex W. Jackson
3 /***************************************************************************
4 
5     digfx.h
6 
7     Device graphics interfaces.
8 
9 ***************************************************************************/
10 
11 #pragma once
12 
13 #ifndef __EMU_H__
14 #error Dont include this file directly; include emu.h instead.
15 #endif
16 
17 #ifndef MAME_EMU_DIGFX_H
18 #define MAME_EMU_DIGFX_H
19 
20 
21 
22 //**************************************************************************
23 //  CONSTANTS
24 //**************************************************************************
25 
26 constexpr u8 MAX_GFX_ELEMENTS = 32;
27 constexpr u16 MAX_GFX_PLANES = 8;
28 constexpr u16 MAX_GFX_SIZE = 32;
29 
30 
31 
32 //**************************************************************************
33 //  GRAPHICS LAYOUT MACROS
34 //**************************************************************************
35 
36 #define EXTENDED_XOFFS          { 0 }
37 #define EXTENDED_YOFFS          { 0 }
38 
39 #define GFX_RAW                 0x12345678
40 #define GFXLAYOUT_RAW( name, width, height, linemod, charmod ) \
41 const gfx_layout name = { width, height, RGN_FRAC(1,1), 8, { GFX_RAW }, { 0 }, { linemod }, charmod };
42 // When planeoffset[0] is set to GFX_RAW, the gfx data is left as-is, with no conversion.
43 // No buffer is allocated for the decoded data, and gfxdata is set to point to the source
44 // data.
45 // yoffset[0] is the line modulo (*8) and charincrement the char modulo (*8). They are *8
46 // for consistency with the usual behaviour, but the bottom 3 bits are not used.
47 //
48 // This special mode can be used for graphics that are already in 8bpp linear format,
49 // or for unusual formats that don't fit our generic model and need to be decoded using
50 // custom code. See blend_gfx() in atarigen.c for an example of the latter usage.
51 
52 
53 // these macros describe gfx_layouts in terms of fractions of a region
54 // they can be used for total, planeoffset, xoffset, yoffset
55 #define RGN_FRAC(num,den)       (0x80000000 | (((num) & 0x0f) << 27) | (((den) & 0x0f) << 23))
56 #define IS_FRAC(offset)         ((offset) & 0x80000000)
57 #define FRAC_NUM(offset)        (((offset) >> 27) & 0x0f)
58 #define FRAC_DEN(offset)        (((offset) >> 23) & 0x0f)
59 #define FRAC_OFFSET(offset)     ((offset) & 0x007fffff)
60 
61 // these macros are useful in gfx_layouts
62 #define STEP2(START,STEP)       (START),(START)+(STEP)
63 #define STEP4(START,STEP)       STEP2(START,STEP),STEP2((START)+2*(STEP),STEP)
64 #define STEP8(START,STEP)       STEP4(START,STEP),STEP4((START)+4*(STEP),STEP)
65 #define STEP16(START,STEP)      STEP8(START,STEP),STEP8((START)+8*(STEP),STEP)
66 #define STEP32(START,STEP)      STEP16(START,STEP),STEP16((START)+16*(STEP),STEP)
67 #define STEP64(START,STEP)      STEP32(START,STEP),STEP32((START)+32*(STEP),STEP)
68 #define STEP128(START,STEP)     STEP64(START,STEP),STEP64((START)+64*(STEP),STEP)
69 #define STEP256(START,STEP)     STEP128(START,STEP),STEP128((START)+128*(STEP),STEP)
70 #define STEP512(START,STEP)     STEP256(START,STEP),STEP256((START)+256*(STEP),STEP)
71 #define STEP1024(START,STEP)    STEP512(START,STEP),STEP512((START)+512*(STEP),STEP)
72 #define STEP2048(START,STEP)    STEP1024(START,STEP),STEP1024((START)+1024*(STEP),STEP)
73 
74 #define STEP2_INV(START,STEP)   (START)+(STEP),(START)
75 #define STEP4_INV(START,STEP)    STEP2_INV(START+2*STEP,STEP),STEP2_INV(START,STEP)
76 
77 //**************************************************************************
78 //  GRAPHICS INFO MACROS
79 //**************************************************************************
80 
81 // optional horizontal and vertical scaling factors
82 #define GFXENTRY_XSCALEMASK   0x000000ff
83 #define GFXENTRY_YSCALEMASK   0x0000ff00
84 #define GFXENTRY_XSCALE(x)    ((((x)-1) << 0) & GFXENTRY_XSCALEMASK)
85 #define GFXENTRY_YSCALE(x)    ((((x)-1) << 8) & GFXENTRY_YSCALEMASK)
86 #define GFXENTRY_GETXSCALE(x) ((((x) & GFXENTRY_XSCALEMASK) >> 0) + 1)
87 #define GFXENTRY_GETYSCALE(x) ((((x) & GFXENTRY_YSCALEMASK) >> 8) + 1)
88 
89 // GFXENTRY_RAM means region tag refers to a RAM share instead of a ROM region
90 #define GFXENTRY_ROM          0x00000000
91 #define GFXENTRY_RAM          0x00010000
92 #define GFXENTRY_ISROM(x)     (((x) & GFXENTRY_RAM) == 0)
93 #define GFXENTRY_ISRAM(x)     (((x) & GFXENTRY_RAM) != 0)
94 
95 // GFXENTRY_DEVICE means region tag is relative to this device instead of its owner
96 #define GFXENTRY_DEVICE       0x00020000
97 #define GFXENTRY_ISDEVICE(x)  (((x) & GFXENTRY_DEVICE) != 0)
98 
99 // GFXENTRY_REVERSE reverses the bit order in the layout (0-7 = LSB-MSB instead of MSB-LSB)
100 #define GFXENTRY_REVERSE      0x00040000
101 #define GFXENTRY_ISREVERSE(x) (((x) & GFXENTRY_REVERSE) != 0)
102 
103 
104 // these macros are used for declaring gfx_decode_entry info arrays
105 #define GFXDECODE_START( name ) const gfx_decode_entry name[] = {
106 #define GFXDECODE_END { 0 } };
107 
108 // use these to declare a gfx_decode_entry array as a member of a device class
109 #define DECLARE_GFXDECODE_MEMBER( name ) static const gfx_decode_entry name[]
110 #define GFXDECODE_MEMBER( name ) const gfx_decode_entry name[] = {
111 // common gfx_decode_entry macros
112 #define GFXDECODE_ENTRYX(region,offset,layout,start,colors,flags) { region, offset, &layout, start, colors, flags },
113 #define GFXDECODE_ENTRY(region,offset,layout,start,colors) { region, offset, &layout, start, colors, 0 },
114 
115 // specialized gfx_decode_entry macros
116 #define GFXDECODE_RAM(region,offset,layout,start,colors) { region, offset, &layout, start, colors, GFXENTRY_RAM },
117 #define GFXDECODE_DEVICE(region,offset,layout,start,colors) { region, offset, &layout, start, colors, GFXENTRY_DEVICE },
118 #define GFXDECODE_DEVICE_RAM(region,offset,layout,start,colors) { region, offset, &layout, start, colors, GFXENTRY_DEVICE | GFXENTRY_RAM },
119 #define GFXDECODE_SCALE(region,offset,layout,start,colors,x,y) { region, offset, &layout, start, colors, GFXENTRY_XSCALE(x) | GFXENTRY_YSCALE(y) },
120 #define GFXDECODE_REVERSEBITS(region,offset,layout,start,colors) { region, offset, &layout, start, colors, GFXENTRY_REVERSE },
121 
122 
123 
124 //**************************************************************************
125 //  TYPE DEFINITIONS
126 //**************************************************************************
127 
128 struct gfx_layout
129 {
xoffsgfx_layout130 	u32 xoffs(int x) const { return (extxoffs != nullptr) ? extxoffs[x] : xoffset[x]; }
yoffsgfx_layout131 	u32 yoffs(int y) const { return (extyoffs != nullptr) ? extyoffs[y] : yoffset[y]; }
132 
133 	u16             width;              // pixel width of each element
134 	u16             height;             // pixel height of each element
135 	u32             total;              // total number of elements, or RGN_FRAC()
136 	u16             planes;             // number of bitplanes
137 	u32             planeoffset[MAX_GFX_PLANES]; // bit offset of each bitplane
138 	u32             xoffset[MAX_GFX_SIZE]; // bit offset of each horizontal pixel
139 	u32             yoffset[MAX_GFX_SIZE]; // bit offset of each vertical pixel
140 	u32             charincrement;      // distance between two consecutive elements (in bits)
141 	const u32 *     extxoffs;           // extended X offset array for really big layouts
142 	const u32 *     extyoffs;           // extended Y offset array for really big layouts
143 };
144 
145 struct gfx_decode_entry
146 {
147 	const char *    memory_region;      // memory region where the data resides
148 	u32             start;              // offset of beginning of data to decode
149 	const gfx_layout *gfxlayout;        // pointer to gfx_layout describing the layout; nullptr marks the end of the array
150 	u16             color_codes_start;  // offset in the color lookup table where color codes start
151 	u16             total_color_codes;  // total number of color codes
152 	u32             flags;              // flags and optional scaling factors
153 };
154 
155 // ======================> device_gfx_interface
156 
157 class device_gfx_interface : public device_interface
158 {
159 public:
160 	static const gfx_decode_entry empty[];
161 
162 	// construction/destruction
163 	device_gfx_interface(const machine_config &mconfig, device_t &device,
164 						const gfx_decode_entry *gfxinfo = nullptr, const char *palette_tag = finder_base::DUMMY_TAG);
165 	virtual ~device_gfx_interface();
166 
167 	// configuration
set_info(const gfx_decode_entry * gfxinfo)168 	void set_info(const gfx_decode_entry *gfxinfo) { m_gfxdecodeinfo = gfxinfo; }
set_palette(T && tag)169 	template <typename T> void set_palette(T &&tag) { m_palette.set_tag(std::forward<T>(tag)); }
170 
171 	void set_palette_disable(bool disable);
172 
173 	// getters
palette()174 	device_palette_interface &palette() const { assert(m_palette); return *m_palette; }
gfx(u8 index)175 	gfx_element *gfx(u8 index) const { assert(index < MAX_GFX_ELEMENTS); return m_gfx[index].get(); }
176 
177 	// decoding
178 	void decode_gfx(const gfx_decode_entry *gfxdecodeinfo);
decode_gfx()179 	void decode_gfx() { decode_gfx(m_gfxdecodeinfo); }
180 
set_gfx(u8 index,std::unique_ptr<gfx_element> && element)181 	void set_gfx(u8 index, std::unique_ptr<gfx_element> &&element) { assert(index < MAX_GFX_ELEMENTS); m_gfx[index] = std::move(element); }
182 
183 protected:
184 	// interface-level overrides
185 	virtual void interface_validity_check(validity_checker &valid) const override;
186 	virtual void interface_pre_start() override;
187 	virtual void interface_post_start() override;
188 
189 private:
190 	optional_device<device_palette_interface> m_palette; // configured tag for palette device
191 	std::unique_ptr<gfx_element>  m_gfx[MAX_GFX_ELEMENTS];    // array of pointers to graphic sets
192 
193 	// configuration
194 	const gfx_decode_entry *    m_gfxdecodeinfo;        // pointer to array of gfx decode information
195 	bool                        m_palette_is_disabled;  // no palette associated with this gfx decode
196 
197 	// internal state
198 	bool                        m_decoded;                  // have we processed our decode info yet?
199 };
200 
201 // iterator
202 typedef device_interface_iterator<device_gfx_interface> gfx_interface_iterator;
203 
204 
205 #endif  /* MAME_EMU_DIGFX_H */
206