summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/digfx.h
blob: ec13147e9667d7890c8cafdbf2cc1c8a2ebe0ca2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
// license:BSD-3-Clause
// copyright-holders:Nicola Salmoria, Aaron Giles, Alex W. Jackson
/***************************************************************************

    digfx.h

    Device graphics interfaces.

***************************************************************************/

#pragma once

#ifndef __EMU_H__
#error Dont include this file directly; include emu.h instead.
#endif

#ifndef __DIGFX_H__
#define __DIGFX_H__



//**************************************************************************
//  CONSTANTS
//**************************************************************************

const int MAX_GFX_ELEMENTS = 32;
const int MAX_GFX_PLANES = 8;
const int MAX_GFX_SIZE = 32;



//**************************************************************************
//  GRAPHICS LAYOUT MACROS
//**************************************************************************

#define EXTENDED_XOFFS          { 0 }
#define EXTENDED_YOFFS          { 0 }

#define GFX_RAW                 0x12345678
#define GFXLAYOUT_RAW( name, width, height, linemod, charmod ) \
const gfx_layout name = { width, height, RGN_FRAC(1,1), 8, { GFX_RAW }, { 0 }, { linemod }, charmod };
// When planeoffset[0] is set to GFX_RAW, the gfx data is left as-is, with no conversion.
// No buffer is allocated for the decoded data, and gfxdata is set to point to the source
// data.
// yoffset[0] is the line modulo (*8) and charincrement the char modulo (*8). They are *8
// for consistency with the usual behaviour, but the bottom 3 bits are not used.
//
// This special mode can be used for graphics that are already in 8bpp linear format,
// or for unusual formats that don't fit our generic model and need to be decoded using
// custom code. See blend_gfx() in atarigen.c for an example of the latter usage.


// these macros describe gfx_layouts in terms of fractions of a region
// they can be used for total, planeoffset, xoffset, yoffset
#define RGN_FRAC(num,den)       (0x80000000 | (((num) & 0x0f) << 27) | (((den) & 0x0f) << 23))
#define IS_FRAC(offset)         ((offset) & 0x80000000)
#define FRAC_NUM(offset)        (((offset) >> 27) & 0x0f)
#define FRAC_DEN(offset)        (((offset) >> 23) & 0x0f)
#define FRAC_OFFSET(offset)     ((offset) & 0x007fffff)

// these macros are useful in gfx_layouts
#define STEP2(START,STEP)       (START),(START)+(STEP)
#define STEP4(START,STEP)       STEP2(START,STEP),STEP2((START)+2*(STEP),STEP)
#define STEP8(START,STEP)       STEP4(START,STEP),STEP4((START)+4*(STEP),STEP)
#define STEP16(START,STEP)      STEP8(START,STEP),STEP8((START)+8*(STEP),STEP)
#define STEP32(START,STEP)      STEP16(START,STEP),STEP16((START)+16*(STEP),STEP)
#define STEP64(START,STEP)      STEP32(START,STEP),STEP32((START)+32*(STEP),STEP)
#define STEP128(START,STEP)     STEP64(START,STEP),STEP64((START)+64*(STEP),STEP)
#define STEP256(START,STEP)     STEP128(START,STEP),STEP128((START)+128*(STEP),STEP)
#define STEP512(START,STEP)     STEP256(START,STEP),STEP256((START)+256*(STEP),STEP)
#define STEP1024(START,STEP)    STEP512(START,STEP),STEP512((START)+512*(STEP),STEP)
#define STEP2048(START,STEP)    STEP1024(START,STEP),STEP1024((START)+1024*(STEP),STEP)



//**************************************************************************
//  GRAPHICS INFO MACROS
//**************************************************************************

// optional horizontal and vertical scaling factors
#define GFXENTRY_XSCALEMASK   0x000000ff
#define GFXENTRY_YSCALEMASK   0x0000ff00
#define GFXENTRY_XSCALE(x)    ((((x)-1) << 0) & GFXENTRY_XSCALEMASK)
#define GFXENTRY_YSCALE(x)    ((((x)-1) << 8) & GFXENTRY_YSCALEMASK)
#define GFXENTRY_GETXSCALE(x) ((((x) & GFXENTRY_XSCALEMASK) >> 0) + 1)
#define GFXENTRY_GETYSCALE(x) ((((x) & GFXENTRY_YSCALEMASK) >> 8) + 1)

// GFXENTRY_RAM means region tag refers to a RAM share instead of a ROM region
#define GFXENTRY_ROM          0x00000000
#define GFXENTRY_RAM          0x00010000
#define GFXENTRY_ISROM(x)     (((x) & GFXENTRY_RAM) == 0)
#define GFXENTRY_ISRAM(x)     (((x) & GFXENTRY_RAM) != 0)

// GFXENTRY_DEVICE means region tag is relative to this device instead of its owner
#define GFXENTRY_DEVICE       0x00020000
#define GFXENTRY_ISDEVICE(x)  (((x) & GFXENTRY_DEVICE) != 0)

// GFXENTRY_REVERSE reverses the bit order in the layout (0-7 = LSB-MSB instead of MSB-LSB)
#define GFXENTRY_REVERSE      0x00040000
#define GFXENTRY_ISREVERSE(x) (((x) & GFXENTRY_REVERSE) != 0)


// these macros are used for declaring gfx_decode_entry info arrays
#define GFXDECODE_NAME( name ) gfxdecodeinfo_##name
#define GFXDECODE_EXTERN( name ) extern const gfx_decode_entry GFXDECODE_NAME(name)[]
#define GFXDECODE_START( name ) const gfx_decode_entry GFXDECODE_NAME(name)[] = {
#define GFXDECODE_END { 0 } };

// use these to declare a gfx_decode_entry array as a member of a device class
#define DECLARE_GFXDECODE_MEMBER( name ) static const gfx_decode_entry name[]
#define GFXDECODE_MEMBER( name ) const gfx_decode_entry name[] = {
// common gfx_decode_entry macros
#define GFXDECODE_ENTRYX(region,offset,layout,start,colors,flags) { region, offset, &layout, start, colors, flags },
#define GFXDECODE_ENTRY(region,offset,layout,start,colors) { region, offset, &layout, start, colors, 0 },

// specialized gfx_decode_entry macros
#define GFXDECODE_RAM(region,offset,layout,start,colors) { region, offset, &layout, start, colors, GFXENTRY_RAM },
#define GFXDECODE_DEVICE(region,offset,layout,start,colors) { region, offset, &layout, start, colors, GFXENTRY_DEVICE },
#define GFXDECODE_DEVICE_RAM(region,offset,layout,start,colors) { region, offset, &layout, start, colors, GFXENTRY_DEVICE | GFXENTRY_RAM },
#define GFXDECODE_SCALE(region,offset,layout,start,colors,x,y) { region, offset, &layout, start, colors, GFXENTRY_XSCALE(x) | GFXENTRY_YSCALE(y) },
#define GFXDECODE_REVERSEBITS(region,offset,layout,start,colors) { region, offset, &layout, start, colors, GFXENTRY_REVERSE },



//**************************************************************************
//  INTERFACE CONFIGURATION MACROS
//**************************************************************************

#define MCFG_GFX_PALETTE(_palette_tag) \
	device_gfx_interface::static_set_palette(*device, _palette_tag);

#define MCFG_GFX_INFO(_info) \
	device_gfx_interface::static_set_info(*device, GFXDECODE_NAME(_info));



//**************************************************************************
//  DEVICE CONFIGURATION MACROS
//**************************************************************************

#define MCFG_GFXDECODE_ADD(_tag, _palette_tag, _info) \
	MCFG_DEVICE_ADD(_tag, GFXDECODE, 0) \
	MCFG_GFX_PALETTE(_palette_tag) \
	MCFG_GFX_INFO(_info)

#define MCFG_GFXDECODE_MODIFY(_tag, _info) \
	MCFG_DEVICE_MODIFY(_tag) \
	MCFG_GFX_INFO(_info)



//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

// forward declarations
class gfx_element;
class palette_device;

struct gfx_layout
{
	UINT32 xoffs(int x) const { return (extxoffs != nullptr) ? extxoffs[x] : xoffset[x]; }
	UINT32 yoffs(int y) const { return (extyoffs != nullptr) ? extyoffs[y] : yoffset[y]; }

	UINT16          width;              // pixel width of each element
	UINT16          height;             // pixel height of each element
	UINT32          total;              // total number of elements, or RGN_FRAC()
	UINT16          planes;             // number of bitplanes
	UINT32          planeoffset[MAX_GFX_PLANES]; // bit offset of each bitplane
	UINT32          xoffset[MAX_GFX_SIZE]; // bit offset of each horizontal pixel
	UINT32          yoffset[MAX_GFX_SIZE]; // bit offset of each vertical pixel
	UINT32          charincrement;      // distance between two consecutive elements (in bits)
	const UINT32 *  extxoffs;           // extended X offset array for really big layouts
	const UINT32 *  extyoffs;           // extended Y offset array for really big layouts
};

struct gfx_decode_entry
{
	const char *    memory_region;      // memory region where the data resides
	UINT32          start;              // offset of beginning of data to decode
	const gfx_layout *gfxlayout;        // pointer to gfx_layout describing the layout; NULL marks the end of the array
	UINT16          color_codes_start;  // offset in the color lookup table where color codes start
	UINT16          total_color_codes;  // total number of color codes
	UINT32          flags;              // flags and optional scaling factors
};

// ======================> device_gfx_interface

class device_gfx_interface : public device_interface
{
public:
	// construction/destruction
	device_gfx_interface(const machine_config &mconfig, device_t &device,
						const gfx_decode_entry *gfxinfo = nullptr, const char *palette_tag = nullptr);
	virtual ~device_gfx_interface();

	// static configuration
	static void static_set_info(device_t &device, const gfx_decode_entry *gfxinfo);
	static void static_set_palette(device_t &device, const char *tag);

	// getters
	palette_device &palette() const { return *m_palette; }
	gfx_element *gfx(int index) const { assert(index < MAX_GFX_ELEMENTS); return m_gfx[index].get(); }

	// decoding
	void decode_gfx(const gfx_decode_entry *gfxdecodeinfo);
	void decode_gfx() { decode_gfx(m_gfxdecodeinfo); }

	void set_gfx(int index, std::unique_ptr<gfx_element> &&element) { assert(index < MAX_GFX_ELEMENTS); m_gfx[index] = std::move(element); }

protected:
	// interface-level overrides
	virtual void interface_validity_check(validity_checker &valid) const override;
	virtual void interface_pre_start() override;
	virtual void interface_post_start() override;

private:
	palette_device *            m_palette;                  // pointer to the palette device
	std::unique_ptr<gfx_element>  m_gfx[MAX_GFX_ELEMENTS];    // array of pointers to graphic sets

	// configuration
	const gfx_decode_entry *    m_gfxdecodeinfo;        // pointer to array of gfx decode information
	const char *                m_palette_tag;          // configured tag for palette device
	bool                        m_palette_is_sibling;   // is palette a sibling or a subdevice?

	// internal state
	bool                        m_decoded;                  // have we processed our decode info yet?
};

// iterator
typedef device_interface_iterator<device_gfx_interface> gfx_interface_iterator;


#endif  /* __DIGFX_H__ */