summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/video/gb_lcd.h
blob: 31bd0c3040397fa11cf462737e4ba023d51593cf (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
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol
/*****************************************************************************
 *
 * video/gb_lcd.h
 *
 ****************************************************************************/

#ifndef __GB_LCD_H__
#define __GB_LCD_H__

#include "emu.h"


#define _NR_GB_VID_REGS     0x40


struct layer_struct {
	UINT8  enabled;
	UINT8  *bg_tiles;
	UINT8  *bg_map;
	UINT8  xindex;
	UINT8  xshift;
	UINT8  xstart;
	UINT8  xend;
	/* GBC specific */
	UINT8  *gbc_map;
	INT16  bgline;
};


class gb_lcd_device :   public device_t,
						public device_video_interface
{
public:
	gb_lcd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
	gb_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);


	UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);

	DECLARE_READ8_MEMBER(vram_r);
	DECLARE_WRITE8_MEMBER(vram_w);
	DECLARE_READ8_MEMBER(oam_r);
	DECLARE_WRITE8_MEMBER(oam_w);
	virtual DECLARE_READ8_MEMBER(video_r);
	virtual DECLARE_WRITE8_MEMBER(video_w);

	// FIXME: remove it when proper sgb support is added
	void set_sgb_hack(bool val) { m_sgb_border_hack = val ? 1 : 0; }

protected:
	inline void plot_pixel(bitmap_ind16 &bitmap, int x, int y, UINT32 color);

	void select_sprites();
	virtual void update_sprites();
	virtual void update_scanline();

	// device-level overrides
	virtual void device_start();
	virtual void device_reset();
	void common_start();
	void common_reset();

	// pointer to the main system
	cpu_device *m_maincpu;

	// state variables
	bitmap_ind16 m_bitmap;

	UINT8 m_sgb_atf_data[4050];       /* (SGB) Attributes files */
	UINT32 m_sgb_atf;
	UINT16 m_sgb_pal_data[4096];
	UINT8 m_sgb_pal_map[20][18];
	UINT16 m_sgb_pal[128];
	UINT8 *m_sgb_tile_data;
	UINT8 m_sgb_tile_map[2048];
	UINT8 m_sgb_window_mask;

	// this is temporarily needed for a bunch of games which draw the border differently...
	int m_sgb_border_hack;

	int m_window_lines_drawn;

	UINT8   m_vid_regs[_NR_GB_VID_REGS];
	UINT8   m_bg_zbuf[160];

	UINT16  m_cgb_bpal[32];   /* CGB current background palette table */
	UINT16  m_cgb_spal[32];   /* CGB current sprite palette table */

	UINT8   m_gb_bpal[4];     /* Background palette */
	UINT8   m_gb_spal0[4];    /* Sprite 0 palette */
	UINT8   m_gb_spal1[4];    /* Sprite 1 palette */

	/* Things used to render current line */
	int m_current_line;       /* Current line */
	int m_cmp_line;           /* Compare line */
	int m_sprCount;           /* Number of sprites on current line */
	int m_sprite[10];         /* References to sprites to draw on current line */
	int m_previous_line;      /* Previous line we've drawn in */
	int m_start_x;            /* Pixel to start drawing from (inclusive) */
	int m_end_x;              /* Pixel to end drawing (exclusive) */
	int m_mode;               /* Keep track of internal STAT mode */
	int m_state;              /* Current state of the video state machine */
	int m_lcd_irq_line;
	int m_triggering_line_irq;
	int m_line_irq;
	int m_triggering_mode_irq;
	int m_mode_irq;
	int m_delayed_line_irq;
	int m_sprite_cycles;
	int m_scrollx_adjust;
	int m_oam_locked;
	int m_vram_locked;
	int m_pal_locked;
	int m_hdma_enabled;
	int m_hdma_possible;
	struct layer_struct m_layer[2];
	emu_timer *m_lcd_timer;
	int m_gbc_mode;

	UINT8   *m_vram;     // Pointer to VRAM
	UINT8   *m_oam;      // Pointer to OAM memory
	UINT8   m_gb_tile_no_mod;
	UINT32  m_gb_chrgen_offs;     // GB Character generator
	UINT32  m_gb_bgdtab_offs;     // GB Background character table
	UINT32  m_gb_wndtab_offs;     // GB Window character table
	UINT32  m_gbc_chrgen_offs;    // CGB Character generator
	UINT32  m_gbc_bgdtab_offs;    // CGB Background character table
	UINT32  m_gbc_wndtab_offs;    // CGB Window character table
	int     m_vram_bank;

	TIMER_CALLBACK_MEMBER(video_init_vbl);
	virtual TIMER_CALLBACK_MEMBER(lcd_timer_proc);
	virtual void videoptr_restore();
	void save_gb_video();
	void increment_scanline();
	void lcd_switch_on();
};


class mgb_lcd_device : public gb_lcd_device
{
public:
	mgb_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

protected:

	// device-level overrides
	virtual void device_start();
};


class sgb_lcd_device : public gb_lcd_device
{
public:
	sgb_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

	void sgb_io_write_pal(int offs, UINT8 *data);

protected:

	// device-level overrides
	virtual void device_start();
	virtual void device_reset();

	virtual void update_sprites();
	virtual void update_scanline();
	void refresh_border();
};


class cgb_lcd_device : public gb_lcd_device
{
public:
	cgb_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

	virtual DECLARE_READ8_MEMBER(video_r);
	virtual DECLARE_WRITE8_MEMBER(video_w);

protected:

	// device-level overrides
	virtual void device_start();
	virtual void device_reset();

	virtual void update_sprites();
	virtual void update_scanline();

	virtual TIMER_CALLBACK_MEMBER(lcd_timer_proc);
	virtual void videoptr_restore();
	void hdma_trans(UINT16 length);
};


extern const device_type GB_LCD_DMG;
extern const device_type GB_LCD_MGB;
extern const device_type GB_LCD_SGB;
extern const device_type GB_LCD_CGB;


#define MCFG_GB_LCD_DMG_ADD(_tag ) \
		MCFG_DEVICE_ADD( _tag, GB_LCD_DMG, 0 )

#define MCFG_GB_LCD_MGB_ADD(_tag ) \
		MCFG_DEVICE_ADD( _tag, GB_LCD_MGB, 0 )

#define MCFG_GB_LCD_SGB_ADD(_tag ) \
		MCFG_DEVICE_ADD( _tag, GB_LCD_SGB, 0 )

#define MCFG_GB_LCD_CGB_ADD(_tag ) \
		MCFG_DEVICE_ADD( _tag, GB_LCD_CGB, 0 )


#endif /* GB_LCD_H_ */