1 // license:BSD-3-Clause
2 // copyright-holders:Luca Elia
3 /***************************************************************************
4 
5                             -=  SunA 16 Bit Games =-
6 
7                     driver by   Luca Elia (l.elia@tin.it)
8 
9 
10     These games have only sprites, of a peculiar type:
11 
12     there is a region of memory where 32 pages of 32x32 tile codes can
13     be written like a tilemap made of 32 pages of 256x256 pixels. Each
14     tile uses 2 words.
15 
16     Sprites are rectangular regions of *tiles* fetched from there and
17     sent to the screen. Each sprite uses 4 words, held where the last
18     page of tiles would be.
19 
20 
21                                 [ Sprites Format ]
22 
23 
24     Offset:     Bits:                   Value:
25 
26         0.w     fedc ---- ---- ----     Source Page (Low Bits)
27                 ---- ba98 ---- ----     Source Column (Bit 8 = Sprite Flip X)
28                 ---- ---- 7654 3210     Screen Y Position
29 
30         2.w     fedc ---- ---- ----     Tile Bank
31                 ---- ba-- ---- ----
32                 ---- --9- ---- ----     Source Page (High Bit)
33                 ---- ---8 7654 3210     Screen X Position
34 
35     $10000.w    fedc ba98 ---- ----
36                 ---- ---- 76-- ----     Sprite Size:
37                                         00 -> 16 x 16   (2x2  tiles)
38                                         01 -> 32 x 32   (4x4  tiles)
39                                         10 -> 16 x 256  (2x32 tiles)
40                                         11 -> 32 x 256  (4x32 tiles)
41                 ---- ---- --54 ----     ? (Bit 4 used by uballoon)
42                 ---- ---- ---- 3210     Source Row
43 
44     $10002.w                            -
45 
46 
47                             [ Sprite's Tiles Format ]
48 
49 
50     Offset:     Bits:                   Value:
51 
52         0.w     f--- ---- ---- ----     Flip Y
53                 -e-- ---- ---- ----     Flip X
54                 --dc ba98 7654 3210     Code
55 
56     $10000.w    fedc ba98 7654 ----
57                 ---- ---- ---- 3210     Color
58 
59 
60 ***************************************************************************/
61 
62 #include "emu.h"
63 #include "includes/suna16.h"
64 
flipscreen_w(offs_t offset,uint16_t data,uint16_t mem_mask)65 void suna16_state::flipscreen_w(offs_t offset, uint16_t data, uint16_t mem_mask)
66 {
67 	if (ACCESSING_BITS_0_7)
68 	{
69 		flip_screen_set(data & 1 );
70 		m_color_bank = ( data & 4 ) >> 2;
71 	}
72 	if (data & ~(1|4))  logerror("CPU#0 PC %06X - Flip screen unknown bits: %04X\n", m_maincpu->pc(), data);
73 }
74 
bestbest_flipscreen_w(offs_t offset,uint16_t data,uint16_t mem_mask)75 void suna16_state::bestbest_flipscreen_w(offs_t offset, uint16_t data, uint16_t mem_mask)
76 {
77 	if (ACCESSING_BITS_0_7)
78 	{
79 		flip_screen_set(data & 0x10 );
80 		//m_color_bank = ( data & 0x07 );
81 	}
82 	if (data & ~(0x10)) logerror("CPU#0 PC %06X - Flip screen unknown bits: %04X\n", m_maincpu->pc(), data);
83 }
84 
85 
86 /***************************************************************************
87 
88 
89                 Banked Palette RAM. Format is xBBBBBGGGGRRRRR
90 
91 
92 ***************************************************************************/
93 
video_start()94 void suna16_state::video_start()
95 {
96 	m_paletteram = std::make_unique<uint16_t[]>(m_palette->entries());
97 
98 	save_item(NAME(m_color_bank));
99 }
100 
paletteram_r(offs_t offset)101 uint16_t suna16_state::paletteram_r(offs_t offset)
102 {
103 	return m_paletteram[offset + m_color_bank * 256];
104 }
105 
paletteram_w(offs_t offset,uint16_t data,uint16_t mem_mask)106 void suna16_state::paletteram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
107 {
108 	offset += m_color_bank * 256;
109 	data = COMBINE_DATA(&m_paletteram[offset]);
110 	m_palette->set_pen_color( offset, pal5bit(data >> 0),pal5bit(data >> 5),pal5bit(data >> 10));
111 }
112 
113 
114 /***************************************************************************
115 
116 
117                                 Sprites Drawing
118 
119 
120 ***************************************************************************/
121 
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect,uint16_t * sprites,int gfx)122 void suna16_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, uint16_t *sprites, int gfx)
123 {
124 	int max_x = m_screen->width() - 8;
125 	int max_y = m_screen->height() - 8;
126 
127 	for ( int offs = 0xfc00/2; offs < 0x10000/2 ; offs += 4/2 )
128 	{
129 		int srcpg, srcx,srcy, dimx,dimy;
130 		int tile_x, tile_xinc, tile_xstart;
131 		int tile_y, tile_yinc;
132 		int dx, dy;
133 		int flipx, y0;
134 
135 		int y       =   sprites[ offs + 0 + 0x00000 / 2 ];
136 		int x       =   sprites[ offs + 1 + 0x00000 / 2 ];
137 		int dim     =   sprites[ offs + 0 + 0x10000 / 2 ];
138 
139 		int bank    =   (x >> 12) & 0xf;
140 
141 		srcpg   =   ((y & 0xf000) >> 12) + ((x & 0x0200) >> 5); // src page
142 		srcx    =   ((y   >> 8) & 0xf) * 2;                     // src col
143 		srcy    =   ((dim >> 0) & 0xf) * 2;                     // src row
144 
145 		switch ( (dim >> 4) & 0xc )
146 		{
147 			case 0x0:   dimx = 2;   dimy =  2;  y0 = 0x100; break;
148 			case 0x4:   dimx = 4;   dimy =  4;  y0 = 0x100; break;
149 			case 0x8:   dimx = 2;   dimy = 32;  y0 = 0x130; break;
150 			default:
151 			case 0xc:   dimx = 4;   dimy = 32;  y0 = 0x120; break;
152 		}
153 
154 		if (dimx==4)    { flipx = srcx & 2;     srcx &= ~2; }
155 		else            { flipx = 0; }
156 
157 		x = (x & 0xff) - (x & 0x100);
158 		y = (y0 - (y & 0xff) - dimy*8 ) & 0xff;
159 
160 		if (flipx)  { tile_xstart = dimx-1; tile_xinc = -1; }
161 		else        { tile_xstart = 0;      tile_xinc = +1; }
162 
163 		tile_y = 0;     tile_yinc = +1;
164 
165 		for (dy = 0; dy < dimy * 8; dy += 8)
166 		{
167 			tile_x = tile_xstart;
168 
169 			for (dx = 0; dx < dimx * 8; dx += 8)
170 			{
171 				int addr    =   (srcpg * 0x20 * 0x20) +
172 								((srcx + tile_x) & 0x1f) * 0x20 +
173 								((srcy + tile_y) & 0x1f);
174 
175 				int tile    =   sprites[ addr + 0x00000 / 2 ];
176 				int attr    =   sprites[ addr + 0x10000 / 2 ];
177 
178 				int sx      =   x + dx;
179 				int sy      =   (y + dy) & 0xff;
180 
181 				int tile_flipx  =   tile & 0x4000;
182 				int tile_flipy  =   tile & 0x8000;
183 
184 				if (flipx)  tile_flipx = !tile_flipx;
185 
186 				if (flip_screen())
187 				{
188 					sx = max_x - sx;
189 					sy = max_y - sy;
190 					tile_flipx = !tile_flipx;
191 					tile_flipy = !tile_flipy;
192 				}
193 
194 				m_gfxdecode->gfx(gfx)->transpen(bitmap,cliprect,
195 							(tile & 0x3fff) + bank*0x4000,
196 							attr + (m_color_bank << 4),
197 							tile_flipx, tile_flipy,
198 							sx, sy,15   );
199 
200 				tile_x += tile_xinc;
201 			}
202 
203 			tile_y += tile_yinc;
204 		}
205 
206 	}
207 
208 }
209 
210 
211 /***************************************************************************
212 
213 
214                                 Screen Drawing
215 
216 
217 ***************************************************************************/
218 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)219 uint32_t suna16_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
220 {
221 	/* Suna Quiz indicates the background is the last pen */
222 	bitmap.fill(0xff, cliprect);
223 	draw_sprites(bitmap, cliprect, m_spriteram, 0);
224 	return 0;
225 }
226 
screen_update_bestbest(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)227 uint32_t suna16_state::screen_update_bestbest(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
228 {
229 	int layers_ctrl = -1;
230 
231 #ifdef MAME_DEBUG
232 if (machine().input().code_pressed(KEYCODE_Z))
233 {   int msk = 0;
234 	if (machine().input().code_pressed(KEYCODE_Q))  msk |= 1;
235 	if (machine().input().code_pressed(KEYCODE_W))  msk |= 2;
236 	if (msk != 0) layers_ctrl &= msk;
237 }
238 #endif
239 
240 	/* Suna Quiz indicates the background is the last pen */
241 	bitmap.fill(0xff, cliprect);
242 	if (layers_ctrl & 1)    draw_sprites(bitmap, cliprect, m_spriteram,  0);
243 	if (layers_ctrl & 2)    draw_sprites(bitmap, cliprect, m_spriteram2, 1);
244 	return 0;
245 }
246