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