1 // license:BSD-3-Clause
2 // copyright-holders:Bryan McPhail
3 /***************************************************************************
4 
5   video.c
6 
7   Functions to emulate the video hardware of the machine.
8 
9 ***************************************************************************/
10 
11 #include "emu.h"
12 #include "includes/lastduel.h"
13 
14 
15 /***************************************************************************
16 
17   Callbacks for the TileMap code
18 
19 ***************************************************************************/
20 
TILE_GET_INFO_MEMBER(lastduel_state::ld_get_bg_tile_info)21 TILE_GET_INFO_MEMBER(lastduel_state::ld_get_bg_tile_info)
22 {
23 	int const tile = m_vram[1][2 * tile_index] & 0x1fff;
24 	int const color = m_vram[1][2 * tile_index + 1];
25 	tileinfo.set(2,
26 			tile,color & 0xf,
27 			TILE_FLIPYX((color & 0x60) >> 5));
28 }
29 
TILE_GET_INFO_MEMBER(lastduel_state::ld_get_fg_tile_info)30 TILE_GET_INFO_MEMBER(lastduel_state::ld_get_fg_tile_info)
31 {
32 	int const tile = m_vram[0][2 * tile_index] & 0x1fff;
33 	int const color = m_vram[0][2 * tile_index + 1];
34 	tileinfo.set(3,
35 			tile,
36 			color & 0xf,
37 			TILE_FLIPYX((color & 0x60) >> 5));
38 	tileinfo.group = (color & 0x80) >> 7;
39 }
40 
TILE_GET_INFO_MEMBER(lastduel_state::get_bg_tile_info)41 TILE_GET_INFO_MEMBER(lastduel_state::get_bg_tile_info)
42 {
43 	int const tile = m_vram[1][tile_index] & 0x1fff;
44 	int const color = m_vram[1][tile_index + 0x0800];
45 	tileinfo.set(2,
46 			tile,
47 			color & 0xf,
48 			TILE_FLIPYX((color & 0x60) >> 5));
49 }
50 
TILE_GET_INFO_MEMBER(lastduel_state::get_fg_tile_info)51 TILE_GET_INFO_MEMBER(lastduel_state::get_fg_tile_info)
52 {
53 	int const tile = m_vram[0][tile_index] & 0x1fff;
54 	int const color = m_vram[0][tile_index + 0x0800];
55 	tileinfo.set(3,
56 			tile,
57 			color & 0xf,
58 			TILE_FLIPYX((color & 0x60) >> 5));
59 	tileinfo.group = (color & 0x10) >> 4;
60 }
61 
TILE_GET_INFO_MEMBER(lastduel_state::get_fix_info)62 TILE_GET_INFO_MEMBER(lastduel_state::get_fix_info)
63 {
64 	int const tile = m_txram[tile_index];
65 	tileinfo.set(1,
66 			tile & 0x7ff,
67 			tile>>12,
68 			(tile & 0x800) ? TILE_FLIPY : 0);
69 }
70 
71 
72 
73 /***************************************************************************
74 
75   Start the video hardware emulation.
76 
77 ***************************************************************************/
78 
VIDEO_START_MEMBER(lastduel_state,lastduel)79 VIDEO_START_MEMBER(lastduel_state,lastduel)
80 {
81 	m_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(lastduel_state::ld_get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 64, 64);
82 	m_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(lastduel_state::ld_get_fg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 64, 64);
83 	m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(lastduel_state::get_fix_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
84 
85 	m_tilemap[0]->set_transmask(0, 0xffff, 0x0001);
86 	m_tilemap[0]->set_transmask(1, 0xf07f, 0x0f81);
87 	m_tx_tilemap->set_transparent_pen(3);
88 
89 	m_sprite_flipy_mask = 0x40;
90 	m_sprite_pri_mask = 0x00;
91 	m_tilemap_priority = 0;
92 }
93 
VIDEO_START_MEMBER(lastduel_state,madgear)94 VIDEO_START_MEMBER(lastduel_state,madgear)
95 {
96 	m_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(lastduel_state::get_bg_tile_info)), TILEMAP_SCAN_COLS, 16, 16, 64, 32);
97 	m_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(lastduel_state::get_fg_tile_info)), TILEMAP_SCAN_COLS, 16, 16, 64, 32);
98 	m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(lastduel_state::get_fix_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
99 
100 	m_tilemap[0]->set_transmask(0, 0xffff, 0x8000);
101 	m_tilemap[0]->set_transmask(1, 0x80ff, 0xff00);
102 	m_tx_tilemap->set_transparent_pen(3);
103 	m_tilemap[1]->set_transparent_pen(15);
104 
105 	m_sprite_flipy_mask = 0x80;
106 	m_sprite_pri_mask = 0x10;
107 }
108 
109 
110 
111 /***************************************************************************
112 
113   Memory handlers
114 
115 ***************************************************************************/
116 
flip_w(uint8_t data)117 void lastduel_state::flip_w(uint8_t data)
118 {
119 	flip_screen_set(data & 0x01);
120 
121 	machine().bookkeeping().coin_lockout_w(0, ~data & 0x10);
122 	machine().bookkeeping().coin_lockout_w(1, ~data & 0x20);
123 	machine().bookkeeping().coin_counter_w(0, data & 0x40);
124 	machine().bookkeeping().coin_counter_w(1, data & 0x80);
125 }
126 
vctrl_w(offs_t offset,uint16_t data,uint16_t mem_mask)127 void lastduel_state::vctrl_w(offs_t offset, uint16_t data, uint16_t mem_mask)
128 {
129 	data = COMBINE_DATA(&m_vctrl[offset]);
130 	switch (offset)
131 	{
132 		case 0: m_tilemap[0]->set_scrolly(0, data); break;
133 		case 1: m_tilemap[0]->set_scrollx(0, data); break;
134 		case 2: m_tilemap[1]->set_scrolly(0, data); break;
135 		case 3: m_tilemap[1]->set_scrollx(0, data); break;
136 		case 7: m_tilemap_priority = data; break;
137 		default:
138 			logerror("Unmapped video write %d %04x\n", offset, data);
139 			break;
140 	}
141 }
142 
txram_w(offs_t offset,uint16_t data,uint16_t mem_mask)143 void lastduel_state::txram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
144 {
145 	COMBINE_DATA(&m_txram[offset]);
146 	m_tx_tilemap->mark_tile_dirty(offset);
147 }
148 
lastduel_RRRRGGGGBBBBIIII(uint32_t raw)149 rgb_t lastduel_state::lastduel_RRRRGGGGBBBBIIII(uint32_t raw)
150 {
151 	// Brightness parameter interpreted same way as CPS1
152 	int const bright = 0x10 + (raw & 0x0f);
153 
154 	int const red   = ((raw >> 12) & 0x0f) * bright * 0x11 / 0x1f;
155 	int const green = ((raw >> 8)  & 0x0f) * bright * 0x11 / 0x1f;
156 	int const blue  = ((raw >> 4)  & 0x0f) * bright * 0x11 / 0x1f;
157 
158 	return rgb_t(red, green, blue);
159 }
160 
161 /***************************************************************************
162 
163   Display refresh
164 
165 ***************************************************************************/
166 
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect,int pri)167 void lastduel_state::draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect, int pri )
168 {
169 	const uint16_t *buffered_spriteram16 = m_spriteram->buffer();
170 	int offs;
171 
172 	if (!m_sprite_pri_mask)
173 		if (pri == 1)
174 			return; /* only low priority sprites in lastduel */
175 
176 	for (offs = 0x400 - 4; offs >= 0; offs -= 4)
177 	{
178 		int attr, sy, sx, flipx, flipy, code, color;
179 
180 		attr = buffered_spriteram16[offs + 1];
181 		if (m_sprite_pri_mask)   /* only madgear seems to have this */
182 		{
183 			if (pri == 1 && (attr & m_sprite_pri_mask))
184 				continue;
185 			if (pri == 0 && !(attr & m_sprite_pri_mask))
186 				continue;
187 		}
188 
189 		code = buffered_spriteram16[offs];
190 		sx = buffered_spriteram16[offs + 3] & 0x1ff;
191 		sy = buffered_spriteram16[offs + 2] & 0x1ff;
192 		if (sy > 0x100)
193 			sy -= 0x200;
194 
195 		flipx = attr & 0x20;
196 		flipy = attr & m_sprite_flipy_mask;  /* 0x40 for lastduel, 0x80 for madgear */
197 		color = attr & 0x0f;
198 
199 		if (flip_screen())
200 		{
201 			sx = 496 - sx;
202 			sy = 240 - sy;
203 			flipx = !flipx;
204 			flipy = !flipy;
205 		}
206 
207 		m_gfxdecode->gfx(0)->transpen(bitmap,cliprect,
208 		code,
209 		color,
210 		flipx,flipy,
211 		sx,sy,15);
212 	}
213 }
214 
screen_update_lastduel(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)215 uint32_t lastduel_state::screen_update_lastduel(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
216 {
217 	m_tilemap[1]->draw(screen, bitmap, cliprect, 0, 0);
218 	m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1, 0);
219 	draw_sprites(bitmap, cliprect, 0);
220 	m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0, 0);
221 	draw_sprites(bitmap, cliprect, 1);
222 	m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
223 	return 0;
224 }
225 
screen_update_madgear(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)226 uint32_t lastduel_state::screen_update_madgear(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
227 {
228 	if (m_tilemap_priority)
229 	{
230 		m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1 | TILEMAP_DRAW_OPAQUE, 0);
231 		draw_sprites(bitmap, cliprect, 0);
232 		m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0, 0);
233 		m_tilemap[1]->draw(screen, bitmap, cliprect, 0, 0);
234 		draw_sprites(bitmap, cliprect, 1);
235 	}
236 	else
237 	{
238 		m_tilemap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE, 0);
239 		m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1, 0);
240 		draw_sprites(bitmap, cliprect, 0);
241 		m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0, 0);
242 		draw_sprites(bitmap, cliprect, 1);
243 	}
244 	m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
245 	return 0;
246 }
247