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