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