1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria
3 /***************************************************************************
4
5 Technos Mysterious Stones hardware
6
7 driver by Nicola Salmoria
8
9 There are only a few differences between the video hardware of Mysterious
10 Stones and Mat Mania. The tile bank select bit is different and the sprite
11 selection seems to be different as well. Additionally, the palette is stored
12 differently. I'm also not sure that the 2nd tile page is really used in
13 Mysterious Stones.
14
15 ***************************************************************************/
16
17 #include "emu.h"
18 #include "video/resnet.h"
19 #include "includes/mystston.h"
20
21
22
23 /*************************************
24 *
25 * Video timing constants
26 *
27 *************************************/
28 // HMC20
29 // set_raw(XTAL(12'000'000)/2, 384, 0, 256, 272, 8, 248)
30 #define PIXEL_CLOCK (XTAL(12'000'000) / 2)
31 #define HTOTAL (384)
32 #define HBEND (0)
33 #define HBSTART (256)
34 #define VTOTAL (272) /* counts from 0x08-0xff, then from 0xe8-0xff */
35 #define VBEND (8)
36 #define VBSTART (248)
37 #define FIRST_INT_VPOS (0x008)
38 #define INT_HPOS (0x100)
39
40
41
42 /*************************************
43 *
44 * Scanline interrupt system
45 *
46 * There is an interrupt every 16
47 * scanlines, starting with 8.
48 *
49 *************************************/
50
TIMER_CALLBACK_MEMBER(mystston_state::interrupt_callback)51 TIMER_CALLBACK_MEMBER(mystston_state::interrupt_callback)
52 {
53 int scanline = param;
54
55 mystston_on_scanline_interrupt();
56
57 scanline = scanline + 16;
58 if (scanline >= VTOTAL)
59 scanline = FIRST_INT_VPOS;
60
61 /* the vertical synch chain is clocked by H256 -- this is probably not important, but oh well */
62 m_interrupt_timer->adjust(m_screen->time_until_pos(scanline - 1, INT_HPOS), scanline);
63 }
64
65
66
67 /*************************************
68 *
69 * Palette handling
70 *
71 *************************************/
72
set_palette()73 void mystston_state::set_palette()
74 {
75 int i;
76 static const int resistances_rg[3] = { 4700, 3300, 1500 };
77 static const int resistances_b [2] = { 3300, 1500 };
78 double weights_rg[3], weights_b[2];
79
80 uint8_t *color_prom = memregion("proms")->base();
81
82 compute_resistor_weights(0, 255, -1.0,
83 3, resistances_rg, weights_rg, 0, 4700,
84 2, resistances_b, weights_b, 0, 4700,
85 0, nullptr, nullptr, 0, 0);
86
87 for (i = 0; i < 0x40; i++)
88 {
89 uint8_t data;
90 int r, g, b;
91 int bit0, bit1, bit2;
92
93 /* first half is dynamic, second half is from the PROM */
94 if (i & 0x20)
95 data = color_prom[i & 0x1f];
96 else
97 data = m_paletteram[i];
98
99 /* red component */
100 bit0 = (data >> 0) & 0x01;
101 bit1 = (data >> 1) & 0x01;
102 bit2 = (data >> 2) & 0x01;
103 r = combine_weights(weights_rg, bit0, bit1, bit2);
104
105 /* green component */
106 bit0 = (data >> 3) & 0x01;
107 bit1 = (data >> 4) & 0x01;
108 bit2 = (data >> 5) & 0x01;
109 g = combine_weights(weights_rg, bit0, bit1, bit2);
110
111 /* blue component */
112 bit0 = (data >> 6) & 0x01;
113 bit1 = (data >> 7) & 0x01;
114 b = combine_weights(weights_b, bit0, bit1);
115
116 m_palette->set_pen_color(i, rgb_t(r, g, b));
117 }
118 }
119
120
121
122 /*************************************
123 *
124 * Video control register
125 *
126 *************************************/
127
mystston_video_control_w(uint8_t data)128 void mystston_state::mystston_video_control_w(uint8_t data)
129 {
130 *m_video_control = data;
131
132 /* D0-D1 - foreground text color */
133 /* D2 - background page select */
134 /* D3 - unused */
135
136 /* D4-D5 - coin counters in flipped order */
137 machine().bookkeeping().coin_counter_w(0, data & 0x20);
138 machine().bookkeeping().coin_counter_w(1, data & 0x10);
139
140 /* D6 - unused */
141 /* D7 - screen flip */
142 }
143
144
145
146 /*************************************
147 *
148 * Tilemap callbacks
149 *
150 *************************************/
151
TILE_GET_INFO_MEMBER(mystston_state::get_bg_tile_info)152 TILE_GET_INFO_MEMBER(mystston_state::get_bg_tile_info)
153 {
154 int page = (*m_video_control & 0x04) << 8;
155 int code = ((m_bg_videoram[page | 0x200 | tile_index] & 0x01) << 8) | m_bg_videoram[page | tile_index];
156 int flags = (tile_index & 0x10) ? TILE_FLIPY : 0;
157
158 tileinfo.set(1, code, 0, flags);
159 }
160
161
TILE_GET_INFO_MEMBER(mystston_state::get_fg_tile_info)162 TILE_GET_INFO_MEMBER(mystston_state::get_fg_tile_info)
163 {
164 int code = ((m_fg_videoram[0x400 | tile_index] & 0x07) << 8) | m_fg_videoram[tile_index];
165 int color = ((*m_video_control & 0x01) << 1) | ((*m_video_control & 0x02) >> 1);
166
167 tileinfo.set(0, code, color, 0);
168 }
169
170
171
172 /*************************************
173 *
174 * Sprite drawing
175 *
176 *************************************/
177
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect,gfx_element * gfx,int flip)178 void mystston_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, gfx_element *gfx, int flip)
179 {
180 int offs;
181
182 for (offs = 0; offs < 0x60; offs += 4)
183 {
184 int attr = m_spriteram[offs];
185
186 if (attr & 0x01)
187 {
188 int code = ((attr & 0x10) << 4) | m_spriteram[offs + 1];
189 int color = (attr & 0x08) >> 3;
190 int flipx = attr & 0x04;
191 int flipy = attr & 0x02;
192 int x = 240 - m_spriteram[offs + 3];
193 int y = (240 - m_spriteram[offs + 2]) & 0xff;
194
195 if (flip)
196 {
197 x = 240 - x;
198 y = 240 - y;
199 flipx = !flipx;
200 flipy = !flipy;
201 }
202
203 gfx->transpen(bitmap,cliprect, code, color, flipx, flipy, x, y, 0);
204 }
205 }
206 }
207
208
209
210 /*************************************
211 *
212 * Start
213 *
214 *************************************/
215
video_start()216 void mystston_state::video_start()
217 {
218 m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(mystston_state::get_bg_tile_info)), TILEMAP_SCAN_COLS_FLIP_X, 16, 16, 16, 32);
219
220 m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(mystston_state::get_fg_tile_info)), TILEMAP_SCAN_COLS_FLIP_X, 8, 8, 32, 32);
221 m_fg_tilemap->set_transparent_pen(0);
222
223 /* create the interrupt timer */
224 m_interrupt_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mystston_state::interrupt_callback),this));
225 }
226
227
228
229 /*************************************
230 *
231 * Reset
232 *
233 *************************************/
234
video_reset()235 void mystston_state::video_reset()
236 {
237 m_interrupt_timer->adjust(m_screen->time_until_pos(FIRST_INT_VPOS - 1, INT_HPOS), FIRST_INT_VPOS);
238 }
239
240
241
242 /*************************************
243 *
244 * Update
245 *
246 *************************************/
247
screen_update_mystston(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)248 uint32_t mystston_state::screen_update_mystston(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
249 {
250 int flip = (*m_video_control & 0x80) ^ ((ioport("DSW1")->read() & 0x20) << 2);
251
252 set_palette();
253
254 machine().tilemap().mark_all_dirty();
255 m_bg_tilemap->set_scrolly(0, *m_scroll);
256 machine().tilemap().set_flip_all(flip ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
257
258 m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
259 draw_sprites(bitmap, cliprect, m_gfxdecode->gfx(2), flip);
260 m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
261
262 return 0;
263 }
264
265
266
267 /*************************************
268 *
269 * Graphics decoding
270 *
271 *************************************/
272
273 static const gfx_layout charlayout =
274 {
275 8,8,
276 RGN_FRAC(1,3),
277 3,
278 { RGN_FRAC(2,3), RGN_FRAC(1,3), RGN_FRAC(0,3) },
279 { 0, 1, 2, 3, 4, 5, 6, 7 },
280 { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
281 8*8
282 };
283
284
285 static const gfx_layout spritelayout =
286 {
287 16,16,
288 RGN_FRAC(1,3),
289 3,
290 { RGN_FRAC(2,3), RGN_FRAC(1,3), RGN_FRAC(0,3) },
291 { 16*8+0, 16*8+1, 16*8+2, 16*8+3, 16*8+4, 16*8+5, 16*8+6, 16*8+7,
292 16*0+0, 16*0+1, 16*0+2, 16*0+3, 16*0+4, 16*0+5, 16*0+6, 16*0+7 },
293 { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,
294 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
295 32*8
296 };
297
298
299 static GFXDECODE_START( gfx_mystston )
300 GFXDECODE_ENTRY( "gfx1", 0, charlayout, 4*8, 4 )
301 GFXDECODE_ENTRY( "gfx2", 0, spritelayout, 2*8, 1 )
302 GFXDECODE_ENTRY( "gfx1", 0, spritelayout, 0*8, 2 )
303 GFXDECODE_END
304
305
306
307 /*************************************
308 *
309 * Machine driver
310 *
311 *************************************/
312
mystston_video(machine_config & config)313 void mystston_state::mystston_video(machine_config &config)
314 {
315 GFXDECODE(config, m_gfxdecode, m_palette, gfx_mystston);
316 PALETTE(config, m_palette).set_entries(0x40);
317
318 SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
319 m_screen->set_raw(PIXEL_CLOCK, HTOTAL, HBEND, HBSTART, VTOTAL, VBEND, VBSTART);
320 m_screen->set_screen_update(FUNC(mystston_state::screen_update_mystston));
321 m_screen->set_palette("palette");
322 }
323