1 // license:BSD-3-Clause
2 // copyright-holders:Lee Taylor
3 // thanks-to:John Clegg
4 /***************************************************************************
5 
6     Irem M58 hardware
7 
8 ***************************************************************************/
9 
10 #include "emu.h"
11 #include "video/resnet.h"
12 #include "includes/m58.h"
13 
14 
15 
16 /*************************************
17  *
18  *  Palette configuration
19  *
20  *************************************/
21 
m58_palette(palette_device & palette) const22 void m58_state::m58_palette(palette_device &palette) const
23 {
24 	uint8_t const *const color_prom = memregion("proms")->base();
25 	uint8_t const *const char_lopal = color_prom + 0x000;
26 	uint8_t const *const char_hipal = color_prom + 0x100;
27 	uint8_t const *const sprite_pal = color_prom + 0x200;
28 	uint8_t const *const sprite_table = color_prom + 0x220;
29 	uint8_t const *const radar_lopal = color_prom + 0x320;
30 	uint8_t const *const radar_hipal = color_prom + 0x420;
31 	static constexpr int resistances_3[3] = { 1000, 470, 220 };
32 	static constexpr int resistances_2[2]  = { 470, 220 };
33 	double weights_r[3], weights_g[3], weights_b[3], scale;
34 
35 	// compute palette information for characters/radar
36 	scale = compute_resistor_weights(0, 255, -1.0,
37 			2, resistances_2, weights_r, 0, 0,
38 			3, resistances_3, weights_g, 0, 0,
39 			3, resistances_3, weights_b, 0, 0);
40 
41 	// character palette
42 	for (int i = 0; i < 256; i++)
43 	{
44 		uint8_t const promval = (char_lopal[i] & 0x0f) | (char_hipal[i] << 4);
45 		int const r = combine_weights(weights_r, BIT(promval,6), BIT(promval,7));
46 		int const g = combine_weights(weights_g, BIT(promval,3), BIT(promval,4), BIT(promval,5));
47 		int const b = combine_weights(weights_b, BIT(promval,0), BIT(promval,1), BIT(promval,2));
48 
49 		palette.set_indirect_color(i, rgb_t(r, g, b));
50 	}
51 
52 	// radar palette
53 	for (int i = 0; i < 256; i++)
54 	{
55 		uint8_t const promval = (radar_lopal[i] & 0x0f) | (radar_hipal[i] << 4);
56 		int const r = combine_weights(weights_r, BIT(promval,6), BIT(promval,7));
57 		int const g = combine_weights(weights_g, BIT(promval,3), BIT(promval,4), BIT(promval,5));
58 		int const b = combine_weights(weights_b, BIT(promval,0), BIT(promval,1), BIT(promval,2));
59 
60 		palette.set_indirect_color(256 + i, rgb_t(r, g, b));
61 	}
62 
63 	// compute palette information for sprites
64 	scale = compute_resistor_weights(0, 255, scale,
65 			2, resistances_2, weights_r, 470, 0,
66 			3, resistances_3, weights_g, 470, 0,
67 			3, resistances_3, weights_b, 470, 0);
68 
69 	// sprite palette
70 	for (int i = 0; i < 16; i++)
71 	{
72 		uint8_t const promval = sprite_pal[i];
73 		int const r = combine_weights(weights_r, BIT(promval,6), BIT(promval,7));
74 		int const g = combine_weights(weights_g, BIT(promval,3), BIT(promval,4), BIT(promval,5));
75 		int const b = combine_weights(weights_b, BIT(promval,0), BIT(promval,1), BIT(promval,2));
76 
77 		palette.set_indirect_color(256 + 256 + i, rgb_t(r, g, b));
78 	}
79 
80 	// character lookup table
81 	for (int i = 0; i < 256; i++)
82 		palette.set_pen_indirect(i, i);
83 
84 	// radar lookup table
85 	for (int i = 0; i < 256; i++)
86 		palette.set_pen_indirect(256 + i, 256 + i);
87 
88 	// sprite lookup table
89 	for (int i = 0; i < 256; i++)
90 	{
91 		uint8_t const promval = sprite_table[i] & 0x0f;
92 		palette.set_pen_indirect(256 + 256 + i, 256 + 256 + promval);
93 	}
94 }
95 
96 
97 
98 /*************************************
99  *
100  *  Video RAM access
101  *
102  *************************************/
103 
videoram_w(offs_t offset,uint8_t data)104 void m58_state::videoram_w(offs_t offset, uint8_t data)
105 {
106 	m_videoram[offset] = data;
107 	m_bg_tilemap->mark_tile_dirty(offset / 2);
108 }
109 
110 
scroll_panel_w(offs_t offset,uint8_t data)111 void m58_state::scroll_panel_w(offs_t offset, uint8_t data)
112 {
113 	int sx = ( offset % 16 );
114 	int sy = ( offset / 16 );
115 
116 	if (sx < 1 || sx > 14)
117 		return;
118 
119 	sx = 4 * (sx - 1);
120 
121 	for (int i = 0;i < 4;i++)
122 	{
123 		int col;
124 
125 		col = (data >> i) & 0x11;
126 		col = ((col >> 3) | col) & 3;
127 
128 		m_scroll_panel_bitmap.pix(sy, sx + i) = 0x100 + (sy & 0xfc) + col;
129 		m_scroll_panel_bitmap.pix(sy, sx + i + 0x2c8) = 0x100 + (sy & 0xfc) + col; // for flipscreen
130 	}
131 }
132 
133 
134 
135 /*************************************
136  *
137  *  Tilemap info callback
138  *
139  *************************************/
140 
TILE_GET_INFO_MEMBER(m58_state::get_bg_tile_info)141 TILE_GET_INFO_MEMBER(m58_state::get_bg_tile_info)
142 {
143 	int offs = tile_index * 2;
144 	int attr = m_videoram[offs + 1];
145 	int code = m_videoram[offs] + ((attr & 0xc0) << 2);
146 	int color = attr & 0x1f;
147 	int flags = (attr & 0x20) ? TILE_FLIPX : 0;
148 
149 	tileinfo.set(0, code, color, flags);
150 }
151 
152 
TILEMAP_MAPPER_MEMBER(m58_state::tilemap_scan_rows)153 TILEMAP_MAPPER_MEMBER(m58_state::tilemap_scan_rows)
154 {
155 	/* logical (col,row) -> memory offset */
156 	if (col >= 32)
157 		return (row + 32) * 32 + col - 32;
158 	else
159 		return row * 32 + col;
160 }
161 
162 
163 
164 /*************************************
165  *
166  *  Video startup
167  *
168  *************************************/
169 
video_start()170 void m58_state::video_start()
171 {
172 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(m58_state::get_bg_tile_info)), tilemap_mapper_delegate(*this, FUNC(m58_state::tilemap_scan_rows)), 8, 8, 64, 32);
173 	m_bg_tilemap->set_scrolldy(32, 32);
174 
175 	m_screen->register_screen_bitmap(m_scroll_panel_bitmap);
176 	save_item(NAME(m_scroll_panel_bitmap));
177 }
178 
179 
180 
181 /*************************************
182  *
183  *  Outputs
184  *
185  *************************************/
186 
flipscreen_w(uint8_t data)187 void m58_state::flipscreen_w(uint8_t data)
188 {
189 	/* screen flip is handled both by software and hardware */
190 	flip_screen_set(BIT(data, 0) ^ BIT(~ioport("DSW2")->read(), 0));
191 
192 	machine().bookkeeping().coin_counter_w(0, data & 0x02);
193 	machine().bookkeeping().coin_counter_w(1, data & 0x20);
194 }
195 
196 
197 
198 /*************************************
199  *
200  *  Sprite rendering
201  *
202  *************************************/
203 
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect)204 void m58_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect )
205 {
206 	const rectangle &visarea = m_screen->visible_area();
207 
208 	for (int offs = m_spriteram.bytes() - 4; offs >= 0; offs -= 4)
209 	{
210 		int attr = m_spriteram[offs + 1];
211 		int bank = (attr & 0x20) >> 5;
212 		int code1 = m_spriteram[offs + 2] & 0xbf;
213 		int code2 = 0;
214 		int color = attr & 0x1f;
215 		int flipx = attr & 0x40;
216 		int flipy = attr & 0x80;
217 		int sx = m_spriteram[offs + 3];
218 		int sy1 = 233 - m_spriteram[offs];
219 		int sy2 = 0;
220 
221 		if (flipy)
222 		{
223 			code2 = code1;
224 			code1 += 0x40;
225 		}
226 		else
227 		{
228 			code2 = code1 + 0x40;
229 		}
230 
231 		if (flip_screen())
232 		{
233 			sx = 240 - sx;
234 			sy2 = 192 - sy1;
235 			sy1 = sy2 + 0x10;
236 			flipx = !flipx;
237 			flipy = !flipy;
238 		}
239 		else
240 		{
241 			sy2 = sy1 + 0x10;
242 		}
243 
244 		m_gfxdecode->gfx(1)->transmask(bitmap, cliprect,
245 			code1 + 256 * bank, color,
246 			flipx, flipy, sx, visarea.min_y + sy1,
247 			m_palette->transpen_mask(*m_gfxdecode->gfx(1), color, 512)
248 		);
249 		m_gfxdecode->gfx(1)->transmask(bitmap, cliprect,
250 			code2 + 256 * bank, color,
251 			flipx, flipy, sx, visarea.min_y + sy2,
252 			m_palette->transpen_mask(*m_gfxdecode->gfx(1), color, 512)
253 		);
254 	}
255 }
256 
257 
258 
259 /*************************************
260  *
261  *  Radar panel rendering
262  *
263  *************************************/
264 
draw_panel(bitmap_ind16 & bitmap,const rectangle & cliprect)265 void m58_state::draw_panel( bitmap_ind16 &bitmap, const rectangle &cliprect )
266 {
267 	if (!*m_score_panel_disabled)
268 	{
269 		const rectangle clippanel(26*8, 32*8-1, 1*8, 31*8-1);
270 		const rectangle clippanelflip(0*8, 6*8-1, 1*8, 31*8-1);
271 		rectangle clip = flip_screen() ? clippanelflip : clippanel;
272 		const rectangle &visarea = m_screen->visible_area();
273 		int sx = flip_screen() ? cliprect.min_x - 8 : cliprect.max_x + 1 - 14*4;
274 		int yoffs = flip_screen() ? -40 : -16;
275 
276 		clip.min_y += visarea.min_y + yoffs;
277 		clip.max_y += visarea.max_y + yoffs;
278 		clip &= cliprect;
279 
280 		copybitmap(bitmap, m_scroll_panel_bitmap, flip_screen(), flip_screen(), sx, visarea.min_y + yoffs, clip);
281 	}
282 }
283 
284 
285 
286 /*************************************
287  *
288  *  Video update
289  *
290  *************************************/
291 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)292 uint32_t m58_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
293 {
294 	m_bg_tilemap->set_scrollx(0, (*m_scroll_x_high * 0x100) + *m_scroll_x_low);
295 	m_bg_tilemap->set_scrolly(0, *m_scroll_y_low);
296 
297 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
298 	draw_sprites(bitmap, cliprect);
299 	draw_panel(bitmap, cliprect);
300 	return 0;
301 }
302