1 // license:BSD-3-Clause
2 // copyright-holders:Yochizo
3 /***************************************************************************
4 
5 Functions to emulate the video hardware of the machine.
6 
7 
8 BG RAM format [Argus and Butasan]
9 -----------------------------------------------------------------------------
10  +0         +1
11  xxxx xxxx  ---- ---- = 1st - 8th bits of tile number
12  ---- ----  xx-- ---- = 9th and 10th bit of tile number
13  ---- ----  --x- ---- = flip y
14  ---- ----  ---x ---- = flip x
15  ---- ----  ---- xxxx = color
16 
17 BG RAM format [Valtric]
18 -----------------------------------------------------------------------------
19  +0         +1
20  xxxx xxxx  ---- ---- = 1st - 8th bits of tile number
21  ---- ----  xx-- ---- = 9th and 10th bit of tile number
22  ---- ----  --x- ---- = 11th bit of tile number
23  ---- ----  ---- xxxx = color
24 
25 
26 Text RAM format [Argus, Valtric and Butasan]
27 -----------------------------------------------------------------------------
28  +0         +1
29  xxxx xxxx  ---- ---- = low bits of tile number
30  ---- ----  xx-- ---- = high bits of tile number
31  ---- ----  --x- ---- = flip y
32  ---- ----  ---x ---- = flip x
33  ---- ----  ---- xxxx = color
34 
35 
36 Sprite RAM format [Argus]
37 -----------------------------------------------------------------------------
38  +11        +12        +13        +14        +15
39  xxxx xxxx  ---- ----  ---- ----  ---- ----  ---- ---- = sprite y
40  ---- ----  xxxx xxxx  ---- ----  ---- ----  ---- ---- = low bits of sprite x
41  ---- ----  ---- ----  xx-- ----  ---- ----  ---- ---- = high bits of tile number
42  ---- ----  ---- ----  --x- ----  ---- ----  ---- ---- = flip y
43  ---- ----  ---- ----  ---x ----  ---- ----  ---- ---- = flip x
44  ---- ----  ---- ----  ---- --x-  ---- ----  ---- ---- = high bit of sprite y
45  ---- ----  ---- ----  ---- ---x  ---- ----  ---- ---- = high bit of sprite x
46  ---- ----  ---- ----  ---- ----  xxxx xxxx  ---- ---- = low bits of tile number
47  ---- ----  ---- ----  ---- ----  ---- ----  ---- x--- = BG1 / sprite priority (Argus only)
48  ---- ----  ---- ----  ---- ----  ---- ----  ---- -xxx = color
49 
50 Sprite RAM format [Valtric]
51 -----------------------------------------------------------------------------
52  +11        +12        +13        +14        +15
53  xxxx xxxx  ---- ----  ---- ----  ---- ----  ---- ---- = sprite y
54  ---- ----  xxxx xxxx  ---- ----  ---- ----  ---- ---- = low bits of sprite x
55  ---- ----  ---- ----  xx-- ----  ---- ----  ---- ---- = high bits of tile number
56  ---- ----  ---- ----  --x- ----  ---- ----  ---- ---- = flip y
57  ---- ----  ---- ----  ---x ----  ---- ----  ---- ---- = flip x
58  ---- ----  ---- ----  ---- --x-  ---- ----  ---- ---- = high bit of sprite y
59  ---- ----  ---- ----  ---- ---x  ---- ----  ---- ---- = high bit of sprite x
60  ---- ----  ---- ----  ---- ----  xxxx xxxx  ---- ---- = low bits of tile number
61  ---- ----  ---- ----  ---- ----  ---- ----  ---- xxxx = color
62 
63 Sprite RAM format [Butasan]
64 -----------------------------------------------------------------------------
65  +8         +9         +10        +11        +12
66  ---- -x--  ---- ----  ---- ----  ---- ----  ---- ---- = flip y
67  ---- ---x  ---- ----  ---- ----  ---- ----  ---- ---- = flip x
68  ---- ----  ---- xxxx  ---- ----  ---- ----  ---- ---- = color ($00 - $0B)
69  ---- ----  ---- ----  xxxx xxxx  ---- ----  ---- ---- = low bits of sprite x
70  ---- ----  ---- ----  ---- ----  ---- ---x  ---- ---- = top bit of sprite x
71  ---- ----  ---- ----  ---- ----  ---- ----  xxxx xxxx = low bits of sprite y
72  +13        +14        +15
73  ---- ---x  ---- ----  ---- ---- = top bit of sprite y
74  ---- ----  xxxx xxxx  ---- ---- = low bits of tile number
75  ---- ----  ---- ----  ---- xxxx = top bits of tile number
76 
77 (*) Sprite size is defined by its offset.
78     $F000 - $F0FF : 16x32    $F100 - $F2FF : 16x16
79     $F300 - $F3FF : 16x32    $F400 - $F57F : 16x16
80     $F580 - $F61F : 32x32    $F620 - $F67F : 64x64
81 
82 
83 Scroll RAM of X and Y coordinates [Argus, Valtric and Butasan]
84 -----------------------------------------------------------------------------
85  +0         +1
86  xxxx xxxx  ---- ---- = scroll value
87  ---- ----  ---- ---x = top bit of scroll value
88 
89 
90 Video effect RAM ( $C30C )
91 -----------------------------------------------------------------------------
92  +0
93  ---- ---x  = BG enable bit
94  ---- --x-  = grey scale effect or tile bank select.
95 
96 
97 Flip screen controller
98 -----------------------------------------------------------------------------
99  +0
100  x--- ----  = flip screen
101 
102 
103 BG0 palette intensity ( $C47F, $C4FF )
104 -----------------------------------------------------------------------------
105  +0 (c47f)  +1 (c4ff)
106  xxxx ----  ---- ---- = red intensity
107  ---- xxxx  ---- ---- = green intensity
108  ---- ----  xxxx ---- = blue intensity
109 
110 
111 (*) Things which are not emulated.
112  - Color $000 - 00f, $01e, $02e ... are half transparent color.
113  - Sprite priority bit may be present in Butasan. But I don't know
114    what happens when it is set.
115 
116 ***************************************************************************/
117 
118 #include "emu.h"
119 #include "includes/argus.h"
120 
121 
122 /***************************************************************************
123   Callbacks for the tilemap code
124 ***************************************************************************/
125 
126 template<int Gfx>
TILE_GET_INFO_MEMBER(argus_common_state::get_tx_tile_info)127 TILE_GET_INFO_MEMBER(argus_common_state::get_tx_tile_info)
128 {
129 	tile_index <<= 1;
130 
131 	u8 lo = m_txram[tile_index];
132 	u8 hi = m_txram[tile_index + 1];
133 
134 	tileinfo.set(Gfx,
135 			((hi & 0xc0) << 2) | lo,
136 			hi & 0x0f,
137 			TILE_FLIPYX((hi & 0x30) >> 4));
138 }
139 
TILE_GET_INFO_MEMBER(argus_state::get_bg0_tile_info)140 TILE_GET_INFO_MEMBER(argus_state::get_bg0_tile_info)
141 {
142 	// logical width is 65536(4096*16) but we load only 1024 pixel each
143 	// for reduce RAM usage
144 	tile_index = (((m_vrom_offset << 9) + tile_index) & 0x1ffff) << 1;
145 	int vrom_offset = (tile_index >> 3);
146 	tile_index = (m_vrom[0][vrom_offset & ~1] << 4) | ((m_vrom[0][vrom_offset | 1] & 0x7) << 12) | (tile_index & 0xf);
147 
148 	u8 lo = m_vrom[1][tile_index];
149 	u8 hi = m_vrom[1][tile_index | 1];
150 
151 	tileinfo.set(1,
152 			((hi & 0xc0) << 2) | lo,
153 			hi & 0x0f,
154 			TILE_FLIPYX((hi & 0x30) >> 4));
155 }
156 
TILE_GET_INFO_MEMBER(argus_state::get_bg1_tile_info)157 TILE_GET_INFO_MEMBER(argus_state::get_bg1_tile_info)
158 {
159 	tile_index <<= 1;
160 
161 	u8 lo = m_bg1ram[tile_index];
162 	u8 hi = m_bg1ram[tile_index + 1];
163 
164 	tileinfo.set(2,
165 			lo,
166 			hi & 0x0f,
167 			TILE_FLIPYX((hi & 0x30) >> 4));
168 }
169 
TILE_GET_INFO_MEMBER(valtric_state::get_bg_tile_info)170 TILE_GET_INFO_MEMBER(valtric_state::get_bg_tile_info)
171 {
172 	tile_index <<= 1;
173 
174 	u8 lo = m_bg1ram[tile_index];
175 	u8 hi = m_bg1ram[tile_index + 1];
176 
177 	tileinfo.set(1,
178 			((hi & 0xc0) << 2) | ((hi & 0x20) << 5) | lo,
179 			hi & 0x0f,
180 			0);
181 }
182 
TILE_GET_INFO_MEMBER(butasan_state::get_tx_tile_info)183 TILE_GET_INFO_MEMBER(butasan_state::get_tx_tile_info)
184 {
185 	tile_index <<= 1;
186 
187 	u8 lo = m_butasan_txram[tile_index];
188 	u8 hi = m_butasan_txram[tile_index + 1];
189 
190 	tileinfo.set(3,
191 			((hi & 0xc0) << 2) | lo,
192 			hi & 0x0f,
193 			TILE_FLIPYX((hi & 0x30) >> 4));
194 }
195 
TILE_GET_INFO_MEMBER(butasan_state::get_bg0_tile_info)196 TILE_GET_INFO_MEMBER(butasan_state::get_bg0_tile_info)
197 {
198 	tile_index <<= 1;
199 
200 	u8 lo = m_butasan_bg0ram[tile_index];
201 	u8 hi = m_butasan_bg0ram[tile_index + 1];
202 
203 	tileinfo.set(1,
204 			((hi & 0xc0) << 2) | lo,
205 			hi & 0x0f,
206 			TILE_FLIPYX((hi & 0x30) >> 4));
207 }
208 
TILE_GET_INFO_MEMBER(butasan_state::get_bg1_tile_info)209 TILE_GET_INFO_MEMBER(butasan_state::get_bg1_tile_info)
210 {
211 	int const tile = m_butasan_bg1ram[tile_index] | ((m_butasan_bg1_status & 2) << 7);
212 
213 	tileinfo.set(2,
214 			tile,
215 			(tile & 0x80) >> 7,
216 			0);
217 }
218 
TILEMAP_MAPPER_MEMBER(butasan_state::bg_scan)219 TILEMAP_MAPPER_MEMBER(butasan_state::bg_scan)
220 {
221 	/* logical (col,row) -> memory offset */
222 	return (col & 0x0f) | ((row ^ 0x0f) << 4) | ((col & 0x10) << 5);
223 }
224 
TILEMAP_MAPPER_MEMBER(butasan_state::tx_scan)225 TILEMAP_MAPPER_MEMBER(butasan_state::tx_scan)
226 {
227 	/* logical (col,row) -> memory offset */
228 	return (col & 0x1f) | ((row ^ 0x1f) << 5);
229 }
230 
231 /***************************************************************************
232   Initialize and destroy video hardware emulation
233 ***************************************************************************/
234 
reset_common()235 void argus_common_state::reset_common()
236 {
237 	m_bg_status = 0x01;
238 	m_flipscreen = 0;
239 	m_palette_intensity = 0;
240 }
241 
video_start()242 void argus_state::video_start()
243 {
244 	/*                           info                     offset             w   h  col  row */
245 //  m_bg_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(argus_state::get_bg0_tile_info)),   TILEMAP_SCAN_COLS, 16, 16, 4096,    32); // full 65536 width tilemap
246 	m_bg_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(argus_state::get_bg0_tile_info)),   TILEMAP_SCAN_COLS, 16, 16, 1024/16, 32);
247 	m_bg_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(argus_state::get_bg1_tile_info)),   TILEMAP_SCAN_COLS, 16, 16, 32,      32);
248 	m_tx_tilemap    = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(argus_state::get_tx_tile_info<3>)), TILEMAP_SCAN_COLS,  8,  8, 32,      32);
249 
250 	m_bg_tilemap[1]->set_transparent_pen(15);
251 	m_tx_tilemap->set_transparent_pen(15);
252 
253 	save_item(NAME(m_bg_status));
254 	save_item(NAME(m_flipscreen));
255 	save_item(NAME(m_palette_intensity));
256 }
257 
video_reset()258 void argus_state::video_reset()
259 {
260 	m_bg_scrollx[0][0] = 0;
261 	m_bg_scrollx[0][1] = 0;
262 	reset_common();
263 }
264 
video_start()265 void valtric_state::video_start()
266 {
267 	/*                           info                      offset             w   h  col  row */
268 	m_bg_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(valtric_state::get_bg_tile_info)),    TILEMAP_SCAN_COLS, 16, 16, 32, 32);
269 	m_tx_tilemap    = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(valtric_state::get_tx_tile_info<2>)), TILEMAP_SCAN_COLS,  8,  8, 32, 32);
270 
271 	m_tx_tilemap->set_transparent_pen(15);
272 
273 	m_screen->register_screen_bitmap(m_mosaicbitmap);
274 
275 	save_item(NAME(m_bg_status));
276 	save_item(NAME(m_flipscreen));
277 	save_item(NAME(m_palette_intensity));
278 	save_item(NAME(m_valtric_mosaic));
279 	save_item(NAME(m_valtric_unknown));
280 	save_item(NAME(m_mosaic));
281 }
282 
video_reset()283 void valtric_state::video_reset()
284 {
285 	m_valtric_mosaic = 0x0f;
286 	reset_common();
287 }
288 
video_start()289 void butasan_state::video_start()
290 {
291 	/*                           info                       offset             w   h  col  row */
292 	m_bg_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(butasan_state::get_bg0_tile_info)), tilemap_mapper_delegate(*this, FUNC(butasan_state::bg_scan)), 16, 16, 32, 32);
293 	m_bg_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(butasan_state::get_bg1_tile_info)), tilemap_mapper_delegate(*this, FUNC(butasan_state::bg_scan)), 16, 16, 32, 32);
294 	m_tx_tilemap    = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(butasan_state::get_tx_tile_info)),  tilemap_mapper_delegate(*this, FUNC(butasan_state::tx_scan)),  8,  8, 32, 32);
295 
296 	m_bg_tilemap[1]->set_transparent_pen(15);
297 	m_tx_tilemap->set_transparent_pen(15);
298 
299 	m_butasan_pagedram[0] = std::make_unique<u8[]>(0x1000);
300 	m_butasan_pagedram[1] = std::make_unique<u8[]>(0x1000);
301 
302 	m_butasan_bg0ram     = &m_butasan_pagedram[0][0x000];
303 	m_butasan_bg0backram = &m_butasan_pagedram[0][0x800];
304 	m_butasan_txram      = &m_butasan_pagedram[1][0x000];
305 	m_butasan_txbackram  = &m_butasan_pagedram[1][0x800];
306 
307 	save_item(NAME(m_bg_status));
308 	save_item(NAME(m_flipscreen));
309 	save_item(NAME(m_palette_intensity));
310 	save_pointer(NAME(m_butasan_pagedram[0]), 0x1000);
311 	save_pointer(NAME(m_butasan_pagedram[1]), 0x1000);
312 	save_item(NAME(m_butasan_page_latch));
313 	save_item(NAME(m_butasan_bg1_status));
314 	save_item(NAME(m_butasan_unknown));
315 }
316 
video_reset()317 void butasan_state::video_reset()
318 {
319 	m_butasan_page_latch = 0;
320 	m_butasan_bg1_status = 0x01;
321 	memset(m_butasan_pagedram[0].get(), 0, 0x1000);
322 	memset(m_butasan_pagedram[1].get(), 0, 0x1000);
323 	reset_common();
324 }
325 
326 
327 /***************************************************************************
328   Functions for handler of MAP roms in Argus and palette color
329 ***************************************************************************/
330 
change_palette(int color,int lo_offs,int hi_offs)331 void argus_common_state::change_palette(int color, int lo_offs, int hi_offs)
332 {
333 	u8 lo = m_paletteram[lo_offs];
334 	u8 hi = m_paletteram[hi_offs];
335 	m_palette->set_pen_color(color, rgb_t(hi & 0x0f, pal4bit(lo >> 4), pal4bit(lo), pal4bit(hi >> 4)));
336 }
337 
change_bg_palette(int color,int lo_offs,int hi_offs)338 void argus_common_state::change_bg_palette(int color, int lo_offs, int hi_offs)
339 {
340 	u8 r,g,b,lo,hi,ir,ig,ib,ix;
341 	rgb_t rgb,irgb;
342 
343 	/* red,green,blue intensities */
344 	ir = pal4bit(m_palette_intensity >> 12);
345 	ig = pal4bit(m_palette_intensity >>  8);
346 	ib = pal4bit(m_palette_intensity >>  4);
347 	ix = m_palette_intensity & 0x0f;
348 
349 	irgb = rgb_t(ir,ig,ib);
350 
351 	lo = m_paletteram[lo_offs];
352 	hi = m_paletteram[hi_offs];
353 
354 	/* red,green,blue component */
355 	r = pal4bit(lo >> 4);
356 	g = pal4bit(lo);
357 	b = pal4bit(hi >> 4);
358 
359 	/* Grey background enable */
360 	if (m_bg_status & 2)
361 	{
362 		u8 val = (r + g + b) / 3;
363 		rgb = rgb_t(val,val,val);
364 	}
365 	else
366 	{
367 		rgb = rgb_t(r,g,b);
368 	}
369 
370 	rgb = m_blend->func(rgb,irgb,ix);
371 
372 	m_palette->set_pen_color(color,rgb);
373 }
374 
375 
376 /***************************************************************************
377   Memory handler
378 ***************************************************************************/
379 
mosaic_w(u8 data)380 void valtric_state::mosaic_w(u8 data)
381 {
382 	m_valtric_mosaic = data;
383 }
384 
txram_w(offs_t offset,u8 data)385 void argus_common_state::txram_w(offs_t offset, u8 data)
386 {
387 	m_txram[offset] = data;
388 	m_tx_tilemap->mark_tile_dirty(offset >> 1);
389 }
390 
bg1ram_w(offs_t offset,u8 data)391 void argus_common_state::bg1ram_w(offs_t offset, u8 data)
392 {
393 	m_bg1ram[offset] = data;
394 	m_bg_tilemap[1]->mark_tile_dirty(offset >> 1);
395 }
396 
bg_status_w(u8 data)397 void argus_state::bg_status_w(u8 data)
398 {
399 	if (m_bg_status != data)
400 	{
401 		m_bg_status = data;
402 
403 		/* Gray / purple scale */
404 		if (m_bg_status & 2)
405 		{
406 			int offs;
407 
408 			for (offs = 0x400; offs < 0x500; offs++)
409 			{
410 				change_bg_palette((offs - 0x400) + 0x080, offs, offs + 0x400);
411 			}
412 		}
413 	}
414 }
415 
bg_status_w(u8 data)416 void valtric_state::bg_status_w(u8 data)
417 {
418 	if (m_bg_status != data)
419 	{
420 		m_bg_status = data;
421 
422 		/* Gray / purple scale */
423 		if (m_bg_status & 2)
424 		{
425 			int offs;
426 
427 			for (offs = 0x400; offs < 0x600; offs += 2)
428 			{
429 				change_bg_palette(((offs - 0x400) >> 1) + 0x100, offs & ~1, offs | 1);
430 			}
431 		}
432 	}
433 }
434 
bg0_status_w(u8 data)435 void butasan_state::bg0_status_w(u8 data)
436 {
437 	m_bg_status = data;
438 }
439 
bg1_status_w(u8 data)440 void butasan_state::bg1_status_w(u8 data)
441 {
442 	if (m_butasan_bg1_status != data)
443 	{
444 		m_butasan_bg1_status = data;
445 
446 		/* Bank changed */
447 		m_bg_tilemap[1]->mark_all_dirty();
448 	}
449 }
450 
flipscreen_w(u8 data)451 void argus_common_state::flipscreen_w(u8 data)
452 {
453 	m_flipscreen = data & 0x80;
454 }
455 
paletteram_w(offs_t offset,u8 data)456 void argus_state::paletteram_w(offs_t offset, u8 data)
457 {
458 	int offs;
459 
460 	m_paletteram[offset] = data;
461 
462 	if (offset <= 0x0ff)                                /* sprite color */
463 	{
464 		offset &= 0x07f;
465 
466 		change_palette(offset, offset, offset + 0x080);
467 
468 		if (offset == 0x07f || offset == 0x0ff)
469 		{
470 			m_palette_intensity = m_paletteram[0x0ff] | (m_paletteram[0x07f] << 8);
471 
472 			for (offs = 0x400; offs < 0x500; offs++)
473 				change_bg_palette((offs & 0xff) + 0x080, offs, offs + 0x400);
474 		}
475 	}
476 	else if ((offset >= 0x400 && offset <= 0x4ff) ||
477 				(offset >= 0x800 && offset <= 0x8ff))       /* BG0 color */
478 	{
479 		offs = offset & 0xff;
480 		offset = offs | 0x400;
481 
482 		change_bg_palette(offs + 0x080, offset, offset + 0x400);
483 	}
484 	else if ((offset >= 0x500 && offset <= 0x5ff) ||
485 				(offset >= 0x900 && offset <= 0x9ff))       /* BG1 color */
486 	{
487 		offs = offset & 0xff;
488 		offset = offs | 0x500;
489 
490 		change_palette(offs + 0x180, offset, offset + 0x400);
491 	}
492 	else if ((offset >= 0x700 && offset <= 0x7ff) ||
493 				(offset >= 0xb00 && offset <= 0xbff))       /* text color */
494 	{
495 		offs = offset & 0xff;
496 		offset = offs | 0x700;
497 
498 		change_palette(offs + 0x280, offset, offset + 0x400);
499 	}
500 }
501 
paletteram_w(offs_t offset,u8 data)502 void valtric_state::paletteram_w(offs_t offset, u8 data)
503 {
504 	m_paletteram[offset] = data;
505 
506 	if (offset <= 0x1ff)                            /* Sprite color */
507 	{
508 		change_palette(offset >> 1, offset & ~1, offset | 1);
509 
510 		if (offset == 0x1fe || offset == 0x1ff)
511 		{
512 			int offs;
513 
514 			m_palette_intensity = m_paletteram[0x1ff] | (m_paletteram[0x1fe] << 8);
515 
516 			for (offs = 0x400; offs < 0x600; offs += 2)
517 				change_bg_palette(((offs & 0x1ff) >> 1) + 0x100, offs & ~1, offs | 1);
518 		}
519 	}
520 	else if (offset >= 0x400 && offset <= 0x5ff)        /* BG color */
521 	{
522 		change_bg_palette(((offset & 0x1ff) >> 1) + 0x100, offset & ~1, offset | 1);
523 	}
524 	else if (offset >= 0x600 && offset <= 0x7ff)        /* Text color */
525 	{
526 		change_palette(((offset & 0x1ff) >> 1) + 0x200, offset & ~1, offset | 1);
527 	}
528 }
529 
paletteram_w(offs_t offset,u8 data)530 void butasan_state::paletteram_w(offs_t offset, u8 data)
531 {
532 	m_paletteram[offset] = data;
533 
534 	if (offset <= 0x1ff)                            /* BG0 color */
535 	{
536 		change_palette((offset >> 1) + 0x100, offset & ~1, offset | 1);
537 	}
538 	else if (offset <= 0x23f)                       /* BG1 color */
539 	{
540 		change_palette(((offset & 0x3f) >> 1) + 0x0c0, offset & ~1, offset | 1);
541 	}
542 	else if (offset >= 0x400 && offset <= 0x47f)    /* Sprite color */
543 	{                                               /* 16 colors */
544 		change_palette((offset & 0x7f) >> 1, offset & ~1, offset | 1);
545 	}
546 	else if (offset >= 0x480 && offset <= 0x4ff)    /* Sprite color */
547 	{                                               /* 8  colors */
548 		int offs = (offset & 0x070) | ((offset & 0x00f) >> 1);
549 
550 		change_palette(offs + 0x040, offset & ~1, offset | 1);
551 		change_palette(offs + 0x048, offset & ~1, offset | 1);
552 	}
553 	else if (offset >= 0x600 && offset <= 0x7ff)    /* Text color */
554 	{
555 		change_palette(((offset & 0x1ff) >> 1) + 0x200, offset & ~1, offset | 1);
556 	}
557 	else if (offset >= 0x240 && offset <= 0x25f)    // dummy
558 		change_palette(((offset & 0x1f) >> 1) + 0xe0, offset & ~1, offset | 1);
559 	else if (offset >= 0x500 && offset <= 0x51f)    // dummy
560 		change_palette(((offset & 0x1f) >> 1) + 0xf0, offset & ~1, offset | 1);
561 }
562 
bg1ram_w(offs_t offset,u8 data)563 void butasan_state::bg1ram_w(offs_t offset, u8 data)
564 {
565 	m_butasan_bg1ram[offset] = data;
566 	m_bg_tilemap[1]->mark_tile_dirty(offset);
567 }
568 
pageselect_w(u8 data)569 void butasan_state::pageselect_w(u8 data)
570 {
571 	m_butasan_page_latch = data & 1;
572 }
573 
pagedram_r(offs_t offset)574 u8 butasan_state::pagedram_r(offs_t offset)
575 {
576 	if (offset <= 0x07ff)
577 		return m_butasan_pagedram[m_butasan_page_latch][offset];
578 	else
579 		return m_butasan_pagedram[0][offset];
580 }
581 
pagedram_w(offs_t offset,u8 data)582 void butasan_state::pagedram_w(offs_t offset, u8 data)
583 {
584 	m_butasan_pagedram[m_butasan_page_latch][offset] = data;
585 
586 	if (!m_butasan_page_latch)
587 	{
588 		if (offset <= 0x07ff)
589 			m_bg_tilemap[0]->mark_tile_dirty(offset >> 1);
590 	}
591 	else
592 	{
593 		if (offset <= 0x07ff)
594 			m_tx_tilemap->mark_tile_dirty(offset >> 1);
595 	}
596 }
597 
unknown_w(u8 data)598 void valtric_state::unknown_w(u8 data)
599 {
600 	m_valtric_unknown = data;
601 }
602 
unknown_w(u8 data)603 void butasan_state::unknown_w(u8 data)
604 {
605 	m_butasan_unknown = data;
606 }
607 
608 
609 /***************************************************************************
610   Screen refresh
611 ***************************************************************************/
612 
613 #define bg_scrollx(layer) (m_bg_scrollx[layer][0] | (m_bg_scrollx[layer][1] << 8))
614 #define bg_scrolly(layer) (m_bg_scrolly[layer][0] | (m_bg_scrolly[layer][1] << 8))
615 
bg_setting()616 void argus_common_state::bg_setting()
617 {
618 	machine().tilemap().set_flip_all(m_flipscreen ? TILEMAP_FLIPY|TILEMAP_FLIPX : 0);
619 
620 	if (!m_flipscreen)
621 	{
622 		if (m_bg_tilemap[0] != nullptr)
623 		{
624 			if ((m_vrom[0] != nullptr) && (m_vrom[1] != nullptr))
625 			{
626 				if (m_vrom_offset != m_bg_scrollx[0][1])
627 				{
628 					m_vrom_offset = m_bg_scrollx[0][1];
629 					m_bg_tilemap[0]->mark_all_dirty();
630 				}
631 				m_bg_tilemap[0]->set_scrollx(0, m_bg_scrollx[0][0]);
632 				m_bg_tilemap[0]->set_scrolly(0, bg_scrolly(0));
633 			}
634 			else
635 			{
636 				m_bg_tilemap[0]->set_scrollx(0, bg_scrollx(0));
637 				m_bg_tilemap[0]->set_scrolly(0, bg_scrolly(0));
638 			}
639 		}
640 		m_bg_tilemap[1]->set_scrollx(0, bg_scrollx(1) & 0x1ff);
641 		m_bg_tilemap[1]->set_scrolly(0, bg_scrolly(1) & 0x1ff);
642 	}
643 	else
644 	{
645 		if (m_bg_tilemap[0] != nullptr)
646 		{
647 			if ((m_vrom[0] != nullptr) && (m_vrom[1] != nullptr))
648 			{
649 				if (m_vrom_offset != ((m_bg_scrollx[0][1] + 1) & 0xff))
650 				{
651 					m_vrom_offset = ((m_bg_scrollx[0][1] + 1) & 0xff);
652 					m_bg_tilemap[0]->mark_all_dirty();
653 				}
654 				m_bg_tilemap[0]->set_scrollx(0, m_bg_scrollx[0][0]);
655 				m_bg_tilemap[0]->set_scrolly(0, (bg_scrolly(0) + 256));
656 			}
657 			else
658 			{
659 				m_bg_tilemap[0]->set_scrollx(0, (bg_scrollx(0) + 256));
660 				m_bg_tilemap[0]->set_scrolly(0, (bg_scrolly(0) + 256));
661 			}
662 		}
663 		m_bg_tilemap[1]->set_scrollx(0, (bg_scrollx(1) + 256) & 0x1ff);
664 		m_bg_tilemap[1]->set_scrolly(0, (bg_scrolly(1) + 256) & 0x1ff);
665 	}
666 }
667 
draw_sprites(bitmap_rgb32 & bitmap,const rectangle & cliprect,int priority)668 void argus_state::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, int priority)
669 {
670 	/* Draw the sprites */
671 	for (int offs = 0; offs < m_spriteram.bytes(); offs += 16)
672 	{
673 		if (!(m_spriteram[offs+15] == 0 && m_spriteram[offs+11] == 0xf0))
674 		{
675 			int sx, sy, tile, flipx, flipy, color, pri;
676 
677 			sx = m_spriteram[offs+12]; if (m_spriteram[offs+13] & 0x01) sx -= 256;
678 			sy = m_spriteram[offs+11]; if (!(m_spriteram[offs+13] & 0x02)) sy -= 256;
679 
680 			tile  = m_spriteram[offs+14] | ((m_spriteram[offs+13] & 0xc0) << 2);
681 			flipx = m_spriteram[offs+13] & 0x10;
682 			flipy = m_spriteram[offs+13] & 0x20;
683 			color = m_spriteram[offs+15] & 0x07;
684 			pri   = (m_spriteram[offs+15] & 0x08) >> 3;
685 
686 			if (m_flipscreen)
687 			{
688 				sx = 240 - sx;
689 				sy = 240 - sy;
690 				flipx = !flipx;
691 				flipy = !flipy;
692 			}
693 
694 			if (priority != pri)
695 				m_blend->drawgfx(
696 						*m_palette,
697 						bitmap,cliprect,m_gfxdecode->gfx(0),
698 						tile,
699 						color,
700 						flipx, flipy,
701 						sx, sy,
702 						15);
703 		}
704 	}
705 }
706 
707 #if 1
draw_mosaic(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)708 void valtric_state::draw_mosaic(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
709 {
710 	if (m_valtric_mosaic!=0x80)
711 	{
712 		m_mosaic=0x0f-(m_valtric_mosaic&0x0f);
713 		if (m_mosaic!=0) m_mosaic++;
714 		if (m_valtric_mosaic&0x80) m_mosaic*=-1;
715 	}
716 
717 	if (m_mosaic==0)
718 		m_bg_tilemap[1]->draw(screen, bitmap, cliprect, 0, 0);
719 	else
720 	{
721 		m_bg_tilemap[1]->draw(screen, m_mosaicbitmap, cliprect, 0, 0);
722 		int step=m_mosaic;
723 		int c=0;
724 		int width = screen.width();
725 		int height = screen.height();
726 
727 		if (m_mosaic<0)step*=-1;
728 
729 		for (int y=0;y<width+step;y+=step)
730 			for (int x=0;x<height+step;x+=step)
731 			{
732 				if (y < height && x < width)
733 					c=m_mosaicbitmap.pix(y, x);
734 
735 				if (m_mosaic<0)
736 					if (y+step-1<height && x+step-1< width)
737 						c = m_mosaicbitmap.pix(y+step-1, x+step-1);
738 
739 				for (int yy=0;yy<step;yy++)
740 					for (int xx=0;xx<step;xx++)
741 					{
742 						if (xx+x < width && yy+y<height)
743 							bitmap.pix(y+yy, x+xx) = c;
744 					}
745 			}
746 	}
747 }
748 #else
draw_mosaic(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)749 void valtric_state::draw_mosaic(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
750 {
751 	int step = 0x10 - (m_valtric_mosaic & 0x0f);
752 
753 	if (step == 1)
754 		m_bg_tilemap[1]->draw(screen, bitmap, cliprect, 0, 0);
755 	else
756 	{
757 		m_bg_tilemap[1]->draw(screen, m_mosaicbitmap, cliprect, 0, 0);
758 		int c=0;
759 		int width = screen.width();
760 		int height = screen.height();
761 
762 		for (int y = 0; y < width+step; y += step)
763 			for (int x = 0; x < height+step; x += step)
764 			{
765 				if (y < height && x < width)
766 					c = m_mosaicbitmap.pix(y, x);
767 
768 				if (m_valtric_mosaic & 0x80)
769 					if (y+step-1 < height && x+step-1 < width)
770 						c = m_mosaicbitmap.pix(y+step-1, x+step-1);
771 
772 				for (int yy = 0; yy < step; yy++)
773 					for (int xx = 0; xx < step; xx++)
774 					{
775 						if (xx+x < width && yy+y < height)
776 							bitmap.pix(y+yy, x+xx) = c;
777 					}
778 			}
779 	}
780 }
781 #endif
782 
draw_sprites(bitmap_rgb32 & bitmap,const rectangle & cliprect)783 void valtric_state::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect)
784 {
785 	/* Draw the sprites */
786 	for (int offs = 0; offs < m_spriteram.bytes(); offs += 16)
787 	{
788 		if (!(m_spriteram[offs+15] == 0 && m_spriteram[offs+11] == 0xf0))
789 		{
790 			int sx, sy, tile, flipx, flipy, color;
791 
792 			sx = m_spriteram[offs+12]; if (m_spriteram[offs+13] & 0x01) sx -= 256;
793 			sy = m_spriteram[offs+11]; if (!(m_spriteram[offs+13] & 0x02)) sy -= 256;
794 
795 			tile  = m_spriteram[offs+14] | ((m_spriteram[offs+13] & 0xc0) << 2);
796 			flipx = m_spriteram[offs+13] & 0x10;
797 			flipy = m_spriteram[offs+13] & 0x20;
798 			color = m_spriteram[offs+15] & 0x0f;
799 
800 			if (m_flipscreen)
801 			{
802 				sx = 240 - sx;
803 				sy = 240 - sy;
804 				flipx = !flipx;
805 				flipy = !flipy;
806 			}
807 
808 			m_blend->drawgfx(*m_palette,
809 						bitmap,cliprect,m_gfxdecode->gfx(0),
810 						tile,
811 						color,
812 						flipx, flipy,
813 						sx, sy,
814 						15);
815 		}
816 	}
817 }
818 
draw_sprites(bitmap_rgb32 & bitmap,const rectangle & cliprect)819 void butasan_state::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect)
820 {
821 	/* Draw the sprites */
822 	for (int offs = 0; offs < m_spriteram.bytes(); offs += 16)
823 	{
824 		int sx, sy, tile, flipx, flipy, color;
825 		int fx, fy;
826 
827 		tile  = m_spriteram[offs+14] | ((m_spriteram[offs+15] & 0x0f) << 8);
828 		flipx = m_spriteram[offs+8] & 0x01;
829 		flipy = m_spriteram[offs+8] & 0x04;
830 		color = m_spriteram[offs+9] & 0x0f;
831 
832 		sx = m_spriteram[offs+10];
833 		sy = m_spriteram[offs+12];
834 
835 		if (m_spriteram[offs+11] & 0x01) sx-=256;
836 		if (m_spriteram[offs+13] & 0x01) sy-=256;
837 
838 		sy = 240 - sy;
839 
840 		if (m_flipscreen)
841 		{
842 			sx = 240 - sx;
843 			sy = 240 - sy;
844 			flipx = !flipx;
845 			flipy = !flipy;
846 		}
847 
848 		fx = flipx;
849 		fy = flipy;
850 
851 		{
852 			int i, j, td;
853 
854 			if ((offs >= 0x100 && offs <= 0x2ff) || (offs >= 0x400 && offs <= 0x57f))
855 			{
856 				m_blend->drawgfx(*m_palette,
857 							bitmap,cliprect,m_gfxdecode->gfx(0),
858 							tile,
859 							color,
860 							flipx, flipy,
861 							sx, sy,
862 							7);
863 			}
864 			else if ((offs >= 0x000 && offs <= 0x0ff) || (offs >= 0x300 && offs <= 0x3ff))
865 			{
866 				for (i = 0; i <= 1; i++)
867 				{
868 					td = (fx) ? (1 - i) : i;
869 
870 					m_blend->drawgfx(*m_palette,
871 								bitmap,cliprect,m_gfxdecode->gfx(0),
872 								tile + td,
873 								color,
874 								flipx, flipy,
875 								sx + i * 16, sy,
876 								7);
877 				}
878 			}
879 			else if (offs >= 0x580 && offs <= 0x61f)
880 			{
881 				for (i = 0; i <= 1; i++)
882 				{
883 					for (j = 0; j <= 1; j++)
884 					{
885 						if (fy)
886 							td = (fx) ? ((1 - i) * 2) + 1 - j : (1 - i) * 2 + j;
887 						else
888 							td = (fx) ? (i * 2) + 1 - j : i * 2 + j;
889 
890 						m_blend->drawgfx(*m_palette,
891 									bitmap,cliprect,m_gfxdecode->gfx(0),
892 									tile + td,
893 									color,
894 									flipx, flipy,
895 									sx + j * 16, sy - i * 16,
896 									7);
897 					}
898 				}
899 			}
900 			else if (offs >= 0x620 && offs <= 0x67f)
901 			{
902 				for (i = 0; i <= 3; i++)
903 				{
904 					for (j = 0; j <= 3; j++)
905 					{
906 						if (fy)
907 							td = (fx) ? ((3 - i) * 4) + 3 - j : (3 - i) * 4 + j;
908 						else
909 							td = (fx) ? (i * 4) + 3 - j : i * 4 + j;
910 
911 						m_blend->drawgfx(*m_palette,
912 									bitmap,cliprect,m_gfxdecode->gfx(0),
913 									tile + td,
914 									color,
915 									flipx, flipy,
916 									sx + j * 16, sy - i * 16,
917 									7);
918 					}
919 				}
920 			}
921 		}
922 	}
923 }
924 
925 
log_vram()926 void butasan_state::log_vram()
927 {
928 #ifdef MAME_DEBUG
929 	int offs;
930 
931 	if (machine().input().code_pressed(KEYCODE_M))
932 	{
933 		u8 *spriteram = &m_spriteram[0];
934 		int i;
935 		logerror("\nSprite RAM\n");
936 		logerror("---------------------------------------\n");
937 		logerror("       +0 +1 +2 +3 +4 +5 +6 +7  +8 +9 +a +b +c +d +e +f\n");
938 		for (offs = 0; offs < m_spriteram.bytes(); offs += 16)
939 		{
940 			for (i = 0; i < 16; i++)
941 			{
942 				if (i == 0)
943 				{
944 					logerror("%04x : ", offs + 0xf000);
945 					logerror("%02x ", spriteram[offs]);
946 				}
947 				else if (i == 7)
948 					logerror("%02x  ", spriteram[offs + 7]);
949 				else if (i == 15)
950 					logerror("%02x\n", spriteram[offs + 15]);
951 				else
952 					logerror("%02x ", spriteram[offs + i]);
953 			}
954 		}
955 		logerror("\nColor RAM\n");
956 		logerror("---------------------------------------\n");
957 		logerror("       +0 +1 +2 +3 +4 +5 +6 +7  +8 +9 +a +b +c +d +e +f\n");
958 		for (offs = 0; offs < 0xbf0; offs += 16)
959 		{
960 			for (i = 0; i < 16; i++)
961 			{
962 				if (i == 0)
963 				{
964 					logerror("%04x : ", offs + 0xc400);
965 					logerror("%02x ", m_paletteram[offs]);
966 				}
967 				else if (i == 7)
968 					logerror("%02x  ", m_paletteram[offs + 7]);
969 				else if (i == 15)
970 					logerror("%02x\n", m_paletteram[offs + 15]);
971 				else
972 					logerror("%02x ", m_paletteram[offs + i]);
973 			}
974 		}
975 	}
976 #endif
977 }
978 
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)979 u32 argus_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
980 {
981 	bg_setting();
982 
983 	m_bg_tilemap[0]->draw(screen, bitmap, cliprect, 0, 0);
984 	draw_sprites(bitmap, cliprect, 0);
985 	if (m_bg_status & 1)    /* Background enable */
986 		m_bg_tilemap[1]->draw(screen, bitmap, cliprect, 0, 0);
987 	draw_sprites(bitmap, cliprect, 1);
988 	m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
989 	return 0;
990 }
991 
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)992 u32 valtric_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
993 {
994 	bg_setting();
995 
996 	if (m_bg_status & 1)    /* Background enable */
997 		draw_mosaic(screen, bitmap, cliprect);
998 	else
999 		bitmap.fill(m_palette->black_pen(), cliprect);
1000 	draw_sprites(bitmap, cliprect);
1001 	m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
1002 	return 0;
1003 }
1004 
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)1005 u32 butasan_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
1006 {
1007 	bg_setting();
1008 
1009 	if (m_bg_status & 1)    /* Background enable */
1010 		m_bg_tilemap[0]->draw(screen, bitmap, cliprect, 0, 0);
1011 	else
1012 		bitmap.fill(m_palette->black_pen(), cliprect);
1013 	if (m_butasan_bg1_status & 1) m_bg_tilemap[1]->draw(screen, bitmap, cliprect, 0, 0);
1014 	draw_sprites(bitmap, cliprect);
1015 	m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
1016 
1017 	log_vram();
1018 	return 0;
1019 }
1020