1 // license:BSD-3-Clause
2 // copyright-holders:Ernesto Corvi
3 /*******************************************************************
4 
5 Namco System 1 Video Hardware
6 
7 *******************************************************************/
8 
9 #include "emu.h"
10 #include "includes/namcos1.h"
11 #include "screen.h"
12 
13 
14 /*
15   video ram map
16   0000-1fff : scroll playfield (0) : 64*64*2
17   2000-3fff : scroll playfield (1) : 64*64*2
18   4000-5fff : scroll playfield (2) : 64*64*2
19   6000-6fff : scroll playfield (3) : 64*32*2
20   7000-700f : ?
21   7010-77ef : fixed playfield (4)  : 36*28*2
22   77f0-77ff : ?
23   7800-780f : ?
24   7810-7fef : fixed playfield (5)  : 36*28*2
25   7ff0-7fff : ?
26 */
27 
28 /*
29   paletteram map (s1ram  0x0000-0x7fff)
30   0000-17ff : palette page0 : sprite
31   2000-37ff : palette page1 : playfield
32   4000-57ff : palette page2 : playfield (shadow)
33   6000-77ff : palette page3 : work RAM
34 
35   x800-x807 : CUS116 registers (visibility window)
36 
37   so there is just 3x0x2000 RAM, plus the CUS116 internal registers.
38 */
39 
40 /*
41   spriteram map (s1ram 0x10000-0x10fff)
42   0000-07ff : work ram
43   0800-0fef : sprite ram    : 0x10 * 127
44   0ff0-0fff : display control registers
45 
46   1000-1fff : playfield control registers
47 */
48 
49 
50 /***************************************************************************
51 
52   Callbacks for the TileMap code
53 
54 ***************************************************************************/
55 
TilemapCB(u16 code,int * tile,int * mask)56 void namcos1_state::TilemapCB(u16 code, int *tile, int *mask)
57 {
58 	code &= 0x3fff;
59 	*tile = code;
60 	*mask = code;
61 }
62 
63 /***************************************************************************
64 
65   Start the video hardware emulation.
66 
67 ***************************************************************************/
68 
video_start()69 void namcos1_state::video_start()
70 {
71 	int i;
72 
73 	/* set table for sprite color == 0x7f */
74 	for (i = 0;i < 15;i++)
75 		m_drawmode_table[i] = DRAWMODE_SHADOW;
76 	m_drawmode_table[15] = DRAWMODE_NONE;
77 
78 	/* all palette entries are not affected by shadow sprites... */
79 	for (i = 0;i < 0x2000;i++)
80 		m_c116->shadow_table()[i] = i;
81 	/* ... except for tilemap colors */
82 	for (i = 0x0800;i < 0x1000;i++)
83 		m_c116->shadow_table()[i] = i + 0x0800;
84 
85 	m_copy_sprites = false;
86 
87 	save_item(NAME(m_copy_sprites));
88 }
89 
90 
91 
92 /***************************************************************************
93 
94   Memory handlers
95 
96 ***************************************************************************/
97 
spriteram_w(offs_t offset,u8 data)98 void namcos1_state::spriteram_w(offs_t offset, u8 data)
99 {
100 	/* 0000-07ff work ram */
101 	/* 0800-0fff sprite ram */
102 	m_spriteram[offset] = data;
103 
104 	/* a write to this offset tells the sprite chip to buffer the sprite list */
105 	if (offset == 0x0ff2)
106 		m_copy_sprites = true;
107 }
108 
109 
110 
111 /***************************************************************************
112 
113   Display refresh
114 
115 ***************************************************************************/
116 
117 /*
118 sprite format:
119 
120 0-3  scratchpad RAM
121 4-9  CPU writes here, hardware copies from here to 10-15
122 10   xx------  X size (16, 8, 32, 4)
123 10   --x-----  X flip
124 10   ---xx---  X offset inside 32x32 tile
125 10   -----xxx  tile bank
126 11   xxxxxxxx  tile number
127 12   xxxxxxx-  color
128 12   -------x  X position MSB
129 13   xxxxxxxx  X position
130 14   xxx-----  priority
131 14   ---xx---  Y offset inside 32x32 tile
132 14   -----xx-  Y size (16, 8, 32, 4)
133 14   -------x  Y flip
134 15   xxxxxxxx  Y position
135 */
136 
draw_sprites(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)137 void namcos1_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
138 {
139 	u8 *spriteram = m_spriteram + 0x800;
140 	const u8 *source = &spriteram[0x800-0x20];   /* the last is NOT a sprite */
141 	const u8 *finish = &spriteram[0];
142 	gfx_element *gfx = m_gfxdecode->gfx(0);
143 
144 	const int sprite_xoffs = spriteram[0x07f5] + ((spriteram[0x07f4] & 1) << 8);
145 	const int sprite_yoffs = spriteram[0x07f7];
146 
147 	while (source >= finish)
148 	{
149 		static const int sprite_size[4] = { 16, 8, 32, 4 };
150 		const u8 attr1 = source[10];
151 		const u8 attr2 = source[14];
152 		u32 color = source[12];
153 		int flipx = (attr1 & 0x20) >> 5;
154 		int flipy = (attr2 & 0x01);
155 		const u16 sizex = sprite_size[(attr1 & 0xc0) >> 6];
156 		const u16 sizey = sprite_size[(attr2 & 0x06) >> 1];
157 		const u16 tx = (attr1 & 0x18) & (~(sizex - 1));
158 		const u16 ty = (attr2 & 0x18) & (~(sizey - 1));
159 		int sx = source[13] + ((color & 0x01) << 8);
160 		int sy = -source[15] - sizey;
161 		u32 sprite = source[11];
162 		const u32 sprite_bank = attr1 & 7;
163 		const int priority = (source[14] & 0xe0) >> 5;
164 		const u8 pri_mask = (0xff << (priority + 1)) & 0xff;
165 
166 		sprite += sprite_bank * 256;
167 		color = color >> 1;
168 
169 		sx += sprite_xoffs;
170 		sy -= sprite_yoffs;
171 
172 		if (flip_screen())
173 		{
174 			sx = -sx - sizex;
175 			sy = -sy - sizey;
176 			flipx ^= 1;
177 			flipy ^= 1;
178 		}
179 
180 		sy++;   /* sprites are buffered and delayed by one scanline */
181 
182 		gfx->set_source_clip(tx, sizex, ty, sizey);
183 		if (color != 0x7f)
184 			gfx->prio_transpen(bitmap,cliprect,
185 					sprite,
186 					color,
187 					flipx,flipy,
188 					sx & 0x1ff,
189 					((sy + 16) & 0xff) - 16,
190 					screen.priority(), pri_mask,
191 					0xf);
192 		else
193 			gfx->prio_transtable(bitmap,cliprect,
194 					sprite,
195 					color,
196 					flipx,flipy,
197 					sx & 0x1ff,
198 					((sy + 16) & 0xff) - 16,
199 					screen.priority(), pri_mask,
200 					m_drawmode_table);
201 
202 		source -= 0x10;
203 	}
204 }
205 
206 
207 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)208 u32 namcos1_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
209 {
210 	int i;
211 	rectangle new_clip = cliprect;
212 
213 	/* flip screen is embedded in the sprite control registers */
214 	flip_screen_set(m_spriteram[0x0ff6] & 1);
215 
216 	/* background color */
217 	bitmap.fill(m_c116->black_pen(), cliprect);
218 
219 	/* berabohm uses asymmetrical visibility windows to iris on the character */
220 	i = m_c116->get_reg(0) - 1;                         // min x
221 	if (new_clip.min_x < i) new_clip.min_x = i;
222 	i = m_c116->get_reg(1) - 1 - 1;                     // max x
223 	if (new_clip.max_x > i) new_clip.max_x = i;
224 	i = m_c116->get_reg(2) - 0x11;                      // min y
225 	if (new_clip.min_y < i) new_clip.min_y = i;
226 	i = m_c116->get_reg(3) - 0x11 - 1;                  // max y
227 	if (new_clip.max_y > i) new_clip.max_y = i;
228 
229 	if (new_clip.empty())
230 		return 0;
231 
232 	m_c123tmap->init_scroll(flip_screen());
233 
234 	screen.priority().fill(0, new_clip);
235 
236 	/* bit 0-2 priority */
237 	/* bit 3   disable  */
238 	for (int priority = 0; priority < 8; priority++)
239 	{
240 		m_c123tmap->draw(screen, bitmap, new_clip, priority, priority, 0);
241 	}
242 
243 	draw_sprites(screen, bitmap, new_clip);
244 	return 0;
245 }
246 
247 
WRITE_LINE_MEMBER(namcos1_state::screen_vblank)248 WRITE_LINE_MEMBER(namcos1_state::screen_vblank)
249 {
250 	// rising edge
251 	if (state)
252 	{
253 		if (m_copy_sprites)
254 		{
255 			u8 *spriteram = m_spriteram + 0x800;
256 
257 			for (int i = 0; i < 0x800; i += 16)
258 			{
259 				for (int j = 10; j < 16; j++)
260 					spriteram[i + j] = spriteram[i + j - 6];
261 			}
262 
263 			m_copy_sprites = false;
264 		}
265 		m_maincpu->set_input_line(M6809_IRQ_LINE, ASSERT_LINE);
266 		m_subcpu->set_input_line(M6809_IRQ_LINE, ASSERT_LINE);
267 		m_audiocpu->set_input_line(M6809_IRQ_LINE, ASSERT_LINE);
268 		m_mcu->set_input_line(HD6301_IRQ_LINE, ASSERT_LINE);
269 	}
270 }
271