1 // license:BSD-3-Clause
2 // copyright-holders:Phil Stroffolino
3 /***************************************************************************
4 
5     Ninja Gaiden / Tecmo Knights Video Hardware
6 
7 ***************************************************************************/
8 
9 #include "emu.h"
10 #include "includes/gaiden.h"
11 
12 /***************************************************************************
13 
14   Callbacks for the TileMap code
15 
16 ***************************************************************************/
17 
TILE_GET_INFO_MEMBER(gaiden_state::get_bg_tile_info)18 TILE_GET_INFO_MEMBER(gaiden_state::get_bg_tile_info)
19 {
20 	uint16_t *videoram1 = &m_videoram[2][0x0800];
21 	uint16_t *videoram2 = m_videoram[2];
22 	tileinfo.set(1,
23 			videoram1[tile_index] & 0x0fff,
24 			(videoram2[tile_index] & 0xf0) >> 4,
25 			0);
26 }
27 
TILE_GET_INFO_MEMBER(gaiden_state::get_fg_tile_info)28 TILE_GET_INFO_MEMBER(gaiden_state::get_fg_tile_info)
29 {
30 	uint16_t *videoram1 = &m_videoram[1][0x0800];
31 	uint16_t *videoram2 = m_videoram[1];
32 	tileinfo.set(2,
33 			videoram1[tile_index] & 0x0fff,
34 			(videoram2[tile_index] & 0xf0) >> 4,
35 			0);
36 }
37 
TILE_GET_INFO_MEMBER(gaiden_state::get_fg_tile_info_raiga)38 TILE_GET_INFO_MEMBER(gaiden_state::get_fg_tile_info_raiga)
39 {
40 	uint16_t *videoram1 = &m_videoram[1][0x0800];
41 	uint16_t *videoram2 = m_videoram[1];
42 
43 	int colour = ((videoram2[tile_index] & 0xf0) >> 4);
44 
45 	/* bit 3 controls blending */
46 	if ((videoram2[tile_index] & 0x08))
47 		colour += 0x10;
48 
49 	tileinfo.set(2,
50 			videoram1[tile_index] & 0x0fff,
51 			colour,
52 			0);
53 }
54 
TILE_GET_INFO_MEMBER(gaiden_state::get_tx_tile_info)55 TILE_GET_INFO_MEMBER(gaiden_state::get_tx_tile_info)
56 {
57 	uint16_t *videoram1 = &m_videoram[0][0x0400];
58 	uint16_t *videoram2 = m_videoram[0];
59 	tileinfo.set(0,
60 			videoram1[tile_index] & 0x07ff,
61 			(videoram2[tile_index] & 0xf0) >> 4,
62 			0);
63 }
64 
65 
66 /***************************************************************************
67 
68   Start the video hardware emulation.
69 
70 ***************************************************************************/
71 
VIDEO_START_MEMBER(gaiden_state,gaiden)72 VIDEO_START_MEMBER(gaiden_state,gaiden)
73 {
74 	/* set up tile layers */
75 	m_screen->register_screen_bitmap(m_tile_bitmap_bg);
76 	m_screen->register_screen_bitmap(m_tile_bitmap_fg);
77 	m_screen->register_screen_bitmap(m_tile_bitmap_tx);
78 
79 	m_background = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gaiden_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32);
80 	m_foreground = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gaiden_state::get_fg_tile_info_raiga)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32);
81 	m_text_layer = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gaiden_state::get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
82 
83 //  m_background->set_transparent_pen(0);
84 //  m_foreground->set_transparent_pen(0);
85 	m_text_layer->set_transparent_pen(0);
86 
87 	m_background->set_scrolldy(0, 33);
88 	m_foreground->set_scrolldy(0, 33);
89 	m_text_layer->set_scrolldy(0, 33);
90 
91 	/* set up sprites */
92 	m_screen->register_screen_bitmap(m_sprite_bitmap);
93 }
94 
95 
VIDEO_START_MEMBER(gaiden_state,raiga)96 VIDEO_START_MEMBER(gaiden_state,raiga)
97 {
98 	/* set up tile layers */
99 	m_screen->register_screen_bitmap(m_tile_bitmap_bg);
100 	m_screen->register_screen_bitmap(m_tile_bitmap_fg);
101 	m_screen->register_screen_bitmap(m_tile_bitmap_tx);
102 
103 	m_background = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gaiden_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32);
104 	m_foreground = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gaiden_state::get_fg_tile_info_raiga)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32);
105 	m_text_layer = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gaiden_state::get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
106 
107 //  m_background->set_transparent_pen(0);
108 //  m_foreground->set_transparent_pen(0);
109 	m_text_layer->set_transparent_pen(0);
110 
111 	/* set up sprites */
112 	m_screen->register_screen_bitmap(m_sprite_bitmap);
113 
114 }
115 
VIDEO_START_MEMBER(gaiden_state,drgnbowl)116 VIDEO_START_MEMBER(gaiden_state,drgnbowl)
117 {
118 	/* set up tile layers */
119 	m_background = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gaiden_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32);
120 	m_foreground = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gaiden_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32);
121 	m_text_layer = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gaiden_state::get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
122 
123 	m_foreground->set_transparent_pen(15);
124 	m_text_layer->set_transparent_pen(15);
125 
126 	m_background->set_scrolldx(-248, 248);
127 	m_foreground->set_scrolldx(-252, 252);
128 }
129 
130 
131 
132 /***************************************************************************
133 
134   Memory handlers
135 
136 ***************************************************************************/
137 
gaiden_flip_w(offs_t offset,uint16_t data,uint16_t mem_mask)138 void gaiden_state::gaiden_flip_w(offs_t offset, uint16_t data, uint16_t mem_mask)
139 {
140 	if (ACCESSING_BITS_0_7)
141 		flip_screen_set(data & 1);
142 }
143 
gaiden_txscrollx_w(offs_t offset,uint16_t data,uint16_t mem_mask)144 void gaiden_state::gaiden_txscrollx_w(offs_t offset, uint16_t data, uint16_t mem_mask)
145 {
146 	COMBINE_DATA(&m_tx_scroll_x);
147 	m_text_layer->set_scrollx(0, m_tx_scroll_x);
148 }
149 
gaiden_txscrolly_w(offs_t offset,uint16_t data,uint16_t mem_mask)150 void gaiden_state::gaiden_txscrolly_w(offs_t offset, uint16_t data, uint16_t mem_mask)
151 {
152 	COMBINE_DATA(&m_tx_scroll_y);
153 	m_text_layer->set_scrolly(0, (m_tx_scroll_y - m_tx_offset_y) & 0xffff);
154 }
155 
gaiden_fgscrollx_w(offs_t offset,uint16_t data,uint16_t mem_mask)156 void gaiden_state::gaiden_fgscrollx_w(offs_t offset, uint16_t data, uint16_t mem_mask)
157 {
158 	COMBINE_DATA(&m_fg_scroll_x);
159 	m_foreground->set_scrollx(0, m_fg_scroll_x);
160 }
161 
gaiden_fgscrolly_w(offs_t offset,uint16_t data,uint16_t mem_mask)162 void gaiden_state::gaiden_fgscrolly_w(offs_t offset, uint16_t data, uint16_t mem_mask)
163 {
164 	COMBINE_DATA(&m_fg_scroll_y);
165 	m_foreground->set_scrolly(0, (m_fg_scroll_y - m_fg_offset_y) & 0xffff);
166 }
167 
gaiden_bgscrollx_w(offs_t offset,uint16_t data,uint16_t mem_mask)168 void gaiden_state::gaiden_bgscrollx_w(offs_t offset, uint16_t data, uint16_t mem_mask)
169 {
170 	COMBINE_DATA(&m_bg_scroll_x);
171 	m_background->set_scrollx(0, m_bg_scroll_x);
172 }
173 
gaiden_bgscrolly_w(offs_t offset,uint16_t data,uint16_t mem_mask)174 void gaiden_state::gaiden_bgscrolly_w(offs_t offset, uint16_t data, uint16_t mem_mask)
175 {
176 	COMBINE_DATA(&m_bg_scroll_y);
177 	m_background->set_scrolly(0, (m_bg_scroll_y - m_bg_offset_y) & 0xffff);
178 }
179 
gaiden_txoffsety_w(offs_t offset,uint16_t data,uint16_t mem_mask)180 void gaiden_state::gaiden_txoffsety_w(offs_t offset, uint16_t data, uint16_t mem_mask)
181 {
182 	if (ACCESSING_BITS_0_7) {
183 		m_tx_offset_y = data;
184 		m_text_layer->set_scrolly(0, (m_tx_scroll_y - m_tx_offset_y) & 0xffff);
185 	}
186 }
187 
gaiden_fgoffsety_w(offs_t offset,uint16_t data,uint16_t mem_mask)188 void gaiden_state::gaiden_fgoffsety_w(offs_t offset, uint16_t data, uint16_t mem_mask)
189 {
190 	if (ACCESSING_BITS_0_7) {
191 		m_fg_offset_y = data;
192 		m_foreground->set_scrolly(0, (m_fg_scroll_y - m_fg_offset_y) & 0xffff);
193 	}
194 }
195 
gaiden_bgoffsety_w(offs_t offset,uint16_t data,uint16_t mem_mask)196 void gaiden_state::gaiden_bgoffsety_w(offs_t offset, uint16_t data, uint16_t mem_mask)
197 {
198 	if (ACCESSING_BITS_0_7) {
199 		m_bg_offset_y = data;
200 		m_background->set_scrolly(0, (m_bg_scroll_y - m_bg_offset_y) & 0xffff);
201 	}
202 }
203 
gaiden_sproffsety_w(offs_t offset,uint16_t data,uint16_t mem_mask)204 void gaiden_state::gaiden_sproffsety_w(offs_t offset, uint16_t data, uint16_t mem_mask)
205 {
206 	if (ACCESSING_BITS_0_7) {
207 		m_spr_offset_y = data;
208 		// handled in draw_sprites
209 	}
210 }
211 
212 
bg_videoram_w(offs_t offset,uint16_t data,uint16_t mem_mask)213 void gaiden_state::bg_videoram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
214 {
215 	COMBINE_DATA(&m_videoram[2][offset]);
216 	m_background->mark_tile_dirty(offset & 0x07ff);
217 }
218 
fg_videoram_w(offs_t offset,uint16_t data,uint16_t mem_mask)219 void gaiden_state::fg_videoram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
220 {
221 	COMBINE_DATA(&m_videoram[1][offset]);
222 	m_foreground->mark_tile_dirty(offset & 0x07ff);
223 }
224 
tx_videoram_w(offs_t offset,uint16_t data,uint16_t mem_mask)225 void gaiden_state::tx_videoram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
226 {
227 	COMBINE_DATA(&m_videoram[0][offset]);
228 	m_text_layer->mark_tile_dirty(offset & 0x03ff);
229 }
230 
231 
232 /***************************************************************************
233 
234   Display refresh
235 
236 ***************************************************************************/
237 
238 // dragon bowl uses a bootleg format
239 /* sprite format:
240  *
241  *  word        bit                 usage
242  * --------+-fedcba9876543210-+----------------
243  *    0    | --------xxxxxxxx | sprite code (lower bits)
244  *         | ---xxxxx-------- | unused ?
245  *    1    | --------xxxxxxxx | y position
246  *         | ------x--------- | unused ?
247  *    2    | --------xxxxxxxx | x position
248  *         | -------x-------- | unused ?
249  *    3    | -----------xxxxx | sprite code (upper bits)
250  *         | ----------x----- | sprite-tile priority
251  *         | ---------x------ | flip x
252  *         | --------x------- | flip y
253  * 0x400   |-------------xxxx | color
254  *         |---------x------- | x position (high bit)
255  */
256 
drgnbowl_draw_sprites(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)257 void gaiden_state::drgnbowl_draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
258 {
259 	uint16_t const *const spriteram = m_spriteram->live(); // not buffered?
260 	int i, code, color, x, y, flipx, flipy, priority_mask;
261 
262 	for( i = 0; i < 0x800/2; i += 4 )
263 	{
264 		code = (spriteram[i + 0] & 0xff) | ((spriteram[i + 3] & 0x1f) << 8);
265 		y = 256 - (spriteram[i + 1] & 0xff) - 12;
266 		x = spriteram[i + 2] & 0xff;
267 		color = (spriteram[(0x800/2) + i] & 0x0f);
268 		flipx = spriteram[i + 3] & 0x40;
269 		flipy = spriteram[i + 3] & 0x80;
270 
271 		if(spriteram[(0x800/2) + i] & 0x80)
272 			x -= 256;
273 
274 		x += 256;
275 
276 		if(spriteram[i + 3] & 0x20)
277 			priority_mask = 0xf0 | 0xcc; /* obscured by foreground */
278 		else
279 			priority_mask = 0;
280 
281 		m_gfxdecode->gfx(3)->prio_transpen_raw(bitmap,cliprect,
282 				code,
283 				m_gfxdecode->gfx(3)->colorbase() + color * m_gfxdecode->gfx(3)->granularity(),
284 				flipx,flipy,x,y,
285 				screen.priority(), priority_mask,15);
286 
287 		/* wrap x*/
288 		m_gfxdecode->gfx(3)->prio_transpen_raw(bitmap,cliprect,
289 				code,
290 				m_gfxdecode->gfx(3)->colorbase() + color * m_gfxdecode->gfx(3)->granularity(),
291 				flipx,flipy,x-512,y,
292 				screen.priority(), priority_mask,15);
293 
294 	}
295 }
296 
screen_update_gaiden(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)297 uint32_t gaiden_state::screen_update_gaiden(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
298 {
299 	m_tile_bitmap_bg.fill(0, cliprect);
300 	m_tile_bitmap_fg.fill(0, cliprect);
301 	m_tile_bitmap_tx.fill(0, cliprect);
302 	m_sprite_bitmap.fill(0, cliprect);
303 	bitmap.fill(0, cliprect);
304 
305 	// non buffered?
306 	m_sprgen->gaiden_draw_sprites(screen, m_gfxdecode->gfx(3), cliprect, m_spriteram->live(), m_sprite_sizey, flip_screen() ? -m_spr_offset_y : m_spr_offset_y, flip_screen(), m_sprite_bitmap);
307 	m_background->draw(screen, m_tile_bitmap_bg, cliprect, 0, 0);
308 	m_foreground->draw(screen, m_tile_bitmap_fg, cliprect, 0, 0);
309 	m_text_layer->draw(screen, m_tile_bitmap_tx, cliprect, 0, 0);
310 
311 	m_mixer->mix_bitmaps(screen, bitmap, cliprect, *m_palette, &m_tile_bitmap_bg, &m_tile_bitmap_fg, &m_tile_bitmap_tx, &m_sprite_bitmap);
312 
313 	return 0;
314 }
315 
screen_update_raiga(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)316 uint32_t gaiden_state::screen_update_raiga(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
317 {
318 	m_tile_bitmap_bg.fill(0, cliprect);
319 	m_tile_bitmap_fg.fill(0, cliprect);
320 	m_tile_bitmap_tx.fill(0, cliprect);
321 	bitmap.fill(0, cliprect);
322 
323 	m_background->draw(screen, m_tile_bitmap_bg, cliprect, 0, 0);
324 	m_foreground->draw(screen, m_tile_bitmap_fg, cliprect, 0, 0);
325 	m_text_layer->draw(screen, m_tile_bitmap_tx, cliprect, 0, 0);
326 
327 	m_mixer->mix_bitmaps(screen, bitmap, cliprect, *m_palette, &m_tile_bitmap_bg, &m_tile_bitmap_fg, &m_tile_bitmap_tx, &m_sprite_bitmap);
328 
329 	return 0;
330 }
331 
screen_update_drgnbowl(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)332 uint32_t gaiden_state::screen_update_drgnbowl(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
333 {
334 	screen.priority().fill(0, cliprect);
335 
336 	m_background->draw(screen, bitmap, cliprect, 0, 1);
337 	m_foreground->draw(screen, bitmap, cliprect, 0, 2);
338 	m_text_layer->draw(screen, bitmap, cliprect, 0, 4);
339 	drgnbowl_draw_sprites(screen, bitmap, cliprect);
340 	return 0;
341 }
342 
WRITE_LINE_MEMBER(gaiden_state::screen_vblank_raiga)343 WRITE_LINE_MEMBER(gaiden_state::screen_vblank_raiga)
344 {
345 	if (state)
346 	{
347 		const rectangle visarea = m_screen->visible_area();
348 		// raiga sprite has 2 frame lags
349 		m_sprite_bitmap.fill(0, visarea);
350 		m_sprgen->gaiden_draw_sprites(*m_screen, m_gfxdecode->gfx(3), visarea, m_spriteram->buffer(), m_sprite_sizey, flip_screen() ? -m_spr_offset_y : m_spr_offset_y, flip_screen(), m_sprite_bitmap);
351 
352 		m_spriteram->copy();
353 	}
354 }
355