1 // license:BSD-3-Clause
2 // copyright-holders:Mirko Buffoni
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/senjyo.h"
13 
14 
15 /***************************************************************************
16 
17   Callbacks for the TileMap code
18 
19 ***************************************************************************/
20 
TILE_GET_INFO_MEMBER(senjyo_state::get_fg_tile_info)21 TILE_GET_INFO_MEMBER(senjyo_state::get_fg_tile_info)
22 {
23 	uint8_t attr = m_fgcolorram[tile_index];
24 	int flags = (attr & 0x80) ? TILE_FLIPY : 0;
25 
26 	if (m_is_senjyo && (tile_index & 0x1f) >= 32-8)
27 		flags |= TILE_FORCE_LAYER0;
28 
29 	tileinfo.set(0,
30 			m_fgvideoram[tile_index] + ((attr & 0x10) << 4),
31 			attr & 0x07,
32 			flags);
33 }
34 
TILE_GET_INFO_MEMBER(senjyo_state::senjyo_bg1_tile_info)35 TILE_GET_INFO_MEMBER(senjyo_state::senjyo_bg1_tile_info)
36 {
37 	uint8_t code = m_bg1videoram[tile_index];
38 
39 	tileinfo.set(1,
40 			code,
41 			(code & 0x70) >> 4,
42 			0);
43 }
44 
TILE_GET_INFO_MEMBER(senjyo_state::starforc_bg1_tile_info)45 TILE_GET_INFO_MEMBER(senjyo_state::starforc_bg1_tile_info)
46 {
47 	/* Star Force has more tiles in bg1, so to get a uniform color code spread */
48 	/* they wired bit 7 of the tile code in place of bit 4 to get the color code */
49 	uint8_t code = m_bg1videoram[tile_index];
50 
51 	tileinfo.set(1,
52 			code,
53 			bitswap<3>(((code & 0xe0) >> 5), 1, 0, 2),
54 			0);
55 }
56 
TILE_GET_INFO_MEMBER(senjyo_state::get_bg2_tile_info)57 TILE_GET_INFO_MEMBER(senjyo_state::get_bg2_tile_info)
58 {
59 	uint8_t code = m_bg2videoram[tile_index];
60 
61 	tileinfo.set(2,
62 			code,
63 			(code & 0xe0) >> 5,
64 			0);
65 }
66 
TILE_GET_INFO_MEMBER(senjyo_state::get_bg3_tile_info)67 TILE_GET_INFO_MEMBER(senjyo_state::get_bg3_tile_info)
68 {
69 	uint8_t code = m_bg3videoram[tile_index];
70 
71 	tileinfo.set(3,
72 			code,
73 			(code & 0xe0) >> 5,
74 			0);
75 }
76 
77 
78 
79 /***************************************************************************
80 
81   Start the video hardware emulation.
82 
83 ***************************************************************************/
84 
video_start()85 void senjyo_state::video_start()
86 {
87 	m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(senjyo_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
88 
89 	if (m_is_senjyo)
90 	{
91 		m_bg1_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(senjyo_state::senjyo_bg1_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 16, 32);
92 		m_bg2_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(senjyo_state::get_bg2_tile_info)),    TILEMAP_SCAN_ROWS, 16, 16, 16, 48);   // only 16x32 used by Star Force
93 		m_bg3_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(senjyo_state::get_bg3_tile_info)),    TILEMAP_SCAN_ROWS, 16, 16, 16, 56);   // only 16x32 used by Star Force
94 	}
95 	else
96 	{
97 		m_bg1_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(senjyo_state::starforc_bg1_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 16, 32);
98 		m_bg2_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(senjyo_state::get_bg2_tile_info)),      TILEMAP_SCAN_ROWS, 16, 16, 16, 32); // only 16x32 used by Star Force
99 		m_bg3_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(senjyo_state::get_bg3_tile_info)),      TILEMAP_SCAN_ROWS, 16, 16, 16, 32); // only 16x32 used by Star Force
100 	}
101 
102 	m_fg_tilemap->set_transparent_pen(0);
103 	m_bg1_tilemap->set_transparent_pen(0);
104 	m_bg2_tilemap->set_transparent_pen(0);
105 	m_bg3_tilemap->set_transparent_pen(0);
106 	m_fg_tilemap->set_scroll_cols(32);
107 }
108 
IIBBGGRR(uint32_t raw)109 rgb_t senjyo_state::IIBBGGRR(uint32_t raw)
110 {
111 	uint8_t const i = (raw >> 6) & 0x03;
112 	uint8_t const r = (raw << 2) & 0x0c;
113 	uint8_t const g = (raw     ) & 0x0c;
114 	uint8_t const b = (raw >> 2) & 0x0c;
115 
116 	return rgb_t(pal4bit(r ? (r | i) : 0), pal4bit(g ? (g | i) : 0), pal4bit(b ? (b | i) : 0));
117 }
118 
radar_palette(palette_device & palette) const119 void senjyo_state::radar_palette(palette_device &palette) const
120 {
121 	// two colors for the radar dots (verified on the real board)
122 	palette.set_pen_color(0, rgb_t(0xff, 0x00, 0x00));  // red for enemies
123 	palette.set_pen_color(1, rgb_t(0xff, 0xff, 0x00));  // yellow for player
124 }
125 
126 
127 /***************************************************************************
128 
129   Memory handlers
130 
131 ***************************************************************************/
132 
fgvideoram_w(offs_t offset,uint8_t data)133 void senjyo_state::fgvideoram_w(offs_t offset, uint8_t data)
134 {
135 	m_fgvideoram[offset] = data;
136 	m_fg_tilemap->mark_tile_dirty(offset);
137 }
fgcolorram_w(offs_t offset,uint8_t data)138 void senjyo_state::fgcolorram_w(offs_t offset, uint8_t data)
139 {
140 	m_fgcolorram[offset] = data;
141 	m_fg_tilemap->mark_tile_dirty(offset);
142 }
bg1videoram_w(offs_t offset,uint8_t data)143 void senjyo_state::bg1videoram_w(offs_t offset, uint8_t data)
144 {
145 	m_bg1videoram[offset] = data;
146 	m_bg1_tilemap->mark_tile_dirty(offset);
147 }
bg2videoram_w(offs_t offset,uint8_t data)148 void senjyo_state::bg2videoram_w(offs_t offset, uint8_t data)
149 {
150 	m_bg2videoram[offset] = data;
151 	m_bg2_tilemap->mark_tile_dirty(offset);
152 }
bg3videoram_w(offs_t offset,uint8_t data)153 void senjyo_state::bg3videoram_w(offs_t offset, uint8_t data)
154 {
155 	m_bg3videoram[offset] = data;
156 	m_bg3_tilemap->mark_tile_dirty(offset);
157 }
158 
159 /***************************************************************************
160 
161   Display refresh
162 
163 ***************************************************************************/
164 
draw_bgbitmap(bitmap_rgb32 & bitmap,const rectangle & cliprect)165 void senjyo_state::draw_bgbitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
166 {
167 	// assume +1 from disabling layer being 0xff
168 	uint8_t stripe_width = m_bgstripesram[0]+1;
169 	if (stripe_width == 0)
170 		bitmap.fill(m_palette->pen_color(0), cliprect);
171 	else
172 	{
173 		int flip = flip_screen();
174 
175 		int pen = 0;
176 		int count = 0;
177 		int strwid = stripe_width;
178 		if (strwid == 0) strwid = 0x100;
179 		if (flip) strwid ^= 0xff;
180 
181 		for (int x = 0;x < 256;x++)
182 		{
183 			if (flip)
184 				for (int y = 0;y < 256;y++)
185 					bitmap.pix(y, 255 - x) = m_palette->pen_color(384 + pen);
186 			else
187 				for (int y = 0;y < 256;y++)
188 					bitmap.pix(y, x) = m_palette->pen_color(384 + pen);
189 
190 			count += 0x10;
191 			if (count >= strwid)
192 			{
193 				pen = (pen + 1) & 0x0f;
194 				count -= strwid;
195 			}
196 		}
197 	}
198 }
199 
draw_radar(bitmap_rgb32 & bitmap,const rectangle & cliprect)200 void senjyo_state::draw_radar(bitmap_rgb32 &bitmap, const rectangle &cliprect)
201 {
202 	for (int offs = 0;offs < 0x400;offs++)
203 		for (int x = 0;x < 8;x++)
204 			if (m_radarram[offs] & (1 << x))
205 			{
206 				int sx, sy;
207 
208 				sx = (8 * (offs % 8) + x) + 256-64;
209 				sy = ((offs & 0x1ff) / 8) + 96;
210 
211 				if (flip_screen())
212 				{
213 					sx = 255 - sx;
214 					sy = 255 - sy;
215 				}
216 
217 				if (cliprect.contains(sx, sy))
218 					bitmap.pix(sy, sx) =  m_radar_palette->pen_color(offs < 0x200 ? 0 : 1);
219 			}
220 }
221 
draw_sprites(bitmap_rgb32 & bitmap,const rectangle & cliprect,int priority)222 void senjyo_state::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, int priority)
223 {
224 	for (int offs = m_spriteram.bytes() - 4; offs >= 0; offs -= 4)
225 	{
226 		int big,sx,sy,flipx,flipy;
227 
228 		if (((m_spriteram[offs+1] & 0x30) >> 4) == priority)
229 		{
230 			if (m_is_senjyo) /* Senjyo */
231 				big = (m_spriteram[offs] & 0x80);
232 			else    /* Star Force */
233 				big = ((m_spriteram[offs] & 0xc0) == 0xc0);
234 			sx = m_spriteram[offs+3];
235 			if (big)
236 				sy = 224-m_spriteram[offs+2];
237 			else
238 				sy = 240-m_spriteram[offs+2];
239 			flipx = m_spriteram[offs+1] & 0x40;
240 			flipy = m_spriteram[offs+1] & 0x80;
241 
242 			if (flip_screen())
243 			{
244 				flipx = !flipx;
245 				flipy = !flipy;
246 
247 				if (big)
248 				{
249 					sx = 224 - sx;
250 					sy = 226 - sy;
251 				}
252 				else
253 				{
254 					sx = 240 - sx;
255 					sy = 242 - sy;
256 				}
257 			}
258 
259 
260 			m_gfxdecode->gfx(big ? 5 : 4)->transpen(bitmap,cliprect,
261 					m_spriteram[offs],
262 					m_spriteram[offs + 1] & 0x07,
263 					flipx,flipy,
264 					sx,sy,0);
265 		}
266 	}
267 }
268 
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)269 uint32_t senjyo_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
270 {
271 	int flip = flip_screen();
272 
273 	for (int i = 0;i < 32;i++)
274 		m_fg_tilemap->set_scrolly(i, m_fgscroll[i]);
275 
276 	int scrollx = m_scrollx1[0];
277 	int scrolly = m_scrolly1[0] + 256 * m_scrolly1[1];
278 	if (flip)
279 		scrollx = -scrollx;
280 	m_bg1_tilemap->set_scrollx(0, scrollx);
281 	m_bg1_tilemap->set_scrolly(0, scrolly);
282 
283 	scrollx = m_scrollx2[0];
284 	scrolly = m_scrolly2[0] + 256 * m_scrolly2[1];
285 	if (m_scrollhack)   /* Star Force, but NOT the encrypted version */
286 	{
287 		scrollx = m_scrollx1[0];
288 		scrolly = m_scrolly1[0] + 256 * m_scrolly1[1];
289 	}
290 	if (flip)
291 		scrollx = -scrollx;
292 	m_bg2_tilemap->set_scrollx(0, scrollx);
293 	m_bg2_tilemap->set_scrolly(0, scrolly);
294 
295 	scrollx = m_scrollx3[0];
296 	scrolly = m_scrolly3[0] + 256 * m_scrolly3[1];
297 	if (flip)
298 		scrollx = -scrollx;
299 	m_bg3_tilemap->set_scrollx(0, scrollx);
300 	m_bg3_tilemap->set_scrolly(0, scrolly);
301 
302 	draw_bgbitmap(bitmap, cliprect);
303 	draw_sprites(bitmap, cliprect, 0);
304 	m_bg3_tilemap->draw(screen, bitmap, cliprect, 0, 0);
305 	draw_sprites(bitmap, cliprect, 1);
306 	m_bg2_tilemap->draw(screen, bitmap, cliprect, 0, 0);
307 	draw_sprites(bitmap, cliprect, 2);
308 	m_bg1_tilemap->draw(screen, bitmap, cliprect, 0, 0);
309 	draw_sprites(bitmap, cliprect, 3);
310 	m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
311 	draw_radar(bitmap, cliprect);
312 
313 #if 0
314 {
315 	char baf[80];
316 	uint8_t *senjyo_scrolly3 = m_scrolly3;
317 
318 	sprintf(baf,"%02x %02x %02x %02x %02x %02x %02x %02x",
319 		senjyo_scrolly3[0x00],
320 		senjyo_scrolly3[0x01],
321 		senjyo_scrolly3[0x02],
322 		senjyo_scrolly3[0x03],
323 		senjyo_scrolly3[0x04],
324 		senjyo_scrolly3[0x05],
325 		senjyo_scrolly3[0x06],
326 		senjyo_scrolly3[0x07]);
327 	ui_draw_text(baf,0,0);
328 	sprintf(baf,"%02x %02x %02x %02x %02x %02x %02x %02x",
329 		senjyo_scrolly3[0x08],
330 		senjyo_scrolly3[0x09],
331 		senjyo_scrolly3[0x0a],
332 		senjyo_scrolly3[0x0b],
333 		senjyo_scrolly3[0x0c],
334 		senjyo_scrolly3[0x0d],
335 		senjyo_scrolly3[0x0e],
336 		senjyo_scrolly3[0x0f]);
337 	ui_draw_text(baf,0,10);
338 	sprintf(baf,"%02x %02x %02x %02x %02x %02x %02x %02x",
339 		senjyo_scrolly3[0x10],
340 		senjyo_scrolly3[0x11],
341 		senjyo_scrolly3[0x12],
342 		senjyo_scrolly3[0x13],
343 		senjyo_scrolly3[0x14],
344 		senjyo_scrolly3[0x15],
345 		senjyo_scrolly3[0x16],
346 		senjyo_scrolly3[0x17]);
347 	ui_draw_text(baf,0,20);
348 	sprintf(baf,"%02x %02x %02x %02x %02x %02x %02x %02x",
349 		senjyo_scrolly3[0x18],
350 		senjyo_scrolly3[0x19],
351 		senjyo_scrolly3[0x1a],
352 		senjyo_scrolly3[0x1b],
353 		senjyo_scrolly3[0x1c],
354 		senjyo_scrolly3[0x1d],
355 		senjyo_scrolly3[0x1e],
356 		senjyo_scrolly3[0x1f]);
357 	ui_draw_text(baf,0,30);
358 }
359 #endif
360 	return 0;
361 }
362