1 // license:BSD-3-Clause
2 // copyright-holders:Lee Taylor
3 // thanks-to:John Clegg,Tomasz Slanina
4 /***************************************************************************
5
6 video.c
7
8 Traverse USA
9
10 L Taylor
11 J Clegg
12
13 Functions to emulate the video hardware of the machine.
14
15 ***************************************************************************/
16
17 #include "emu.h"
18 #include "includes/travrusa.h"
19
20 /***************************************************************************
21
22 Convert the color PROMs into a more useable format.
23
24 Traverse USA has one 256x8 character palette PROM (some versions have two
25 256x4), one 32x8 sprite palette PROM, and one 256x4 sprite color lookup
26 table PROM.
27
28 I don't know for sure how the palette PROMs are connected to the RGB
29 output, but it's probably something like this; note that RED and BLUE
30 are swapped wrt the usual configuration.
31
32 bit 7 -- 220 ohm resistor -- RED
33 -- 470 ohm resistor -- RED
34 -- 220 ohm resistor -- GREEN
35 -- 470 ohm resistor -- GREEN
36 -- 1 kohm resistor -- GREEN
37 -- 220 ohm resistor -- BLUE
38 -- 470 ohm resistor -- BLUE
39 bit 0 -- 1 kohm resistor -- BLUE
40
41 ***************************************************************************/
42
travrusa_palette(palette_device & palette) const43 void travrusa_state::travrusa_palette(palette_device &palette) const
44 {
45 const uint8_t *color_prom = memregion("proms")->base();
46
47 // create a lookup table for the palette
48 for (int i = 0; i < 0x80; i++)
49 {
50 int bit0, bit1, bit2;
51
52 // red component
53 bit0 = 0;
54 bit1 = BIT(color_prom[i], 6);
55 bit2 = BIT(color_prom[i], 7);
56 int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
57
58 // green component
59 bit0 = BIT(color_prom[i], 3);
60 bit1 = BIT(color_prom[i], 4);
61 bit2 = BIT(color_prom[i], 5);
62 int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
63
64 // blue component
65 bit0 = BIT(color_prom[i], 0);
66 bit1 = BIT(color_prom[i], 1);
67 bit2 = BIT(color_prom[i], 2);
68 int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
69
70 palette.set_indirect_color(i, rgb_t(r, g, b));
71 }
72
73 for (int i = 0x80; i < 0x90; i++)
74 {
75 int bit0, bit1, bit2;
76
77 // red component
78 bit0 = 0;
79 bit1 = BIT(color_prom[(i - 0x80) + 0x200], 6);
80 bit2 = BIT(color_prom[(i - 0x80) + 0x200], 7);
81 int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
82
83 // green component
84 bit0 = BIT(color_prom[(i - 0x80) + 0x200], 3);
85 bit1 = BIT(color_prom[(i - 0x80) + 0x200], 4);
86 bit2 = BIT(color_prom[(i - 0x80) + 0x200], 5);
87 int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
88
89 // blue component
90 bit0 = BIT(color_prom[(i - 0x80) + 0x200], 0);
91 bit1 = BIT(color_prom[(i - 0x80) + 0x200], 1);
92 bit2 = BIT(color_prom[(i - 0x80) + 0x200], 2);
93 int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
94
95 palette.set_indirect_color(i, rgb_t(r, g, b));
96 }
97
98 // color_prom now points to the beginning of the lookup table
99 color_prom += 0x220;
100
101 // characters
102 for (int i = 0; i < 0x80; i++)
103 palette.set_pen_indirect(i, i);
104
105 // sprites
106 for (int i = 0x80; i < 0x100; i++)
107 {
108 uint8_t const ctabentry = (color_prom[i - 0x80] & 0x0f) | 0x80;
109 palette.set_pen_indirect(i, ctabentry);
110 }
111 }
112
shtrider_palette(palette_device & palette) const113 void travrusa_state::shtrider_palette(palette_device &palette) const
114 {
115 const uint8_t *color_prom = memregion("proms")->base();
116
117 // create a lookup table for the palette
118 for (int i = 0; i < 0x80; i++)
119 {
120 int bit0, bit1, bit2;
121
122 // red component
123 bit0 = 0;
124 bit1 = BIT(color_prom[i + 0x000], 2);
125 bit2 = BIT(color_prom[i + 0x000], 3);
126 int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
127
128 // green component
129 bit0 = BIT(color_prom[i + 0x100], 3);
130 bit1 = BIT(color_prom[i + 0x000], 0);
131 bit2 = BIT(color_prom[i + 0x000], 1);
132 int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
133
134 // blue component
135 bit0 = BIT(color_prom[i + 0x100], 0);
136 bit1 = BIT(color_prom[i + 0x100], 1);
137 bit2 = BIT(color_prom[i + 0x100], 2);
138 int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
139
140 palette.set_indirect_color(i, rgb_t(r, g, b));
141 }
142
143 for (int i = 0x80; i < 0x90; i++)
144 {
145 int bit0, bit1, bit2;
146
147 // red component
148 bit0 = 0;
149 bit1 = BIT(color_prom[(i - 0x80) + 0x200], 6);
150 bit2 = BIT(color_prom[(i - 0x80) + 0x200], 7);
151 int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
152
153 // green component
154 bit0 = BIT(color_prom[(i - 0x80) + 0x200], 3);
155 bit1 = BIT(color_prom[(i - 0x80) + 0x200], 4);
156 bit2 = BIT(color_prom[(i - 0x80) + 0x200], 5);
157 int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
158
159 // blue component
160 bit0 = BIT(color_prom[(i - 0x80) + 0x200], 0);
161 bit1 = BIT(color_prom[(i - 0x80) + 0x200], 1);
162 bit2 = BIT(color_prom[(i - 0x80) + 0x200], 2);
163 int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
164
165 palette.set_indirect_color(i, rgb_t(r, g, b));
166 }
167
168 // color_prom now points to the beginning of the lookup table
169 color_prom += 0x220;
170
171 // characters
172 for (int i = 0; i < 0x80; i++)
173 palette.set_pen_indirect(i, i);
174
175 // sprites
176 for (int i = 0x80; i < 0x100; i++)
177 {
178 uint8_t const ctabentry = (color_prom[i - 0x80] & 0x0f) | 0x80;
179 palette.set_pen_indirect(i, ctabentry);
180 }
181 }
182
183
184
185 /***************************************************************************
186
187 Callbacks for the TileMap code
188
189 ***************************************************************************/
190
TILE_GET_INFO_MEMBER(travrusa_state::get_tile_info)191 TILE_GET_INFO_MEMBER(travrusa_state::get_tile_info)
192 {
193 uint8_t attr = m_videoram[2 * tile_index + 1];
194 int flags = TILE_FLIPXY((attr & 0x30) >> 4);
195
196 tileinfo.group = ((attr & 0x0f) == 0x0f) ? 1 : 0; /* tunnels */
197
198 tileinfo.set(0,
199 m_videoram[2 * tile_index] + ((attr & 0xc0) << 2),
200 attr & 0x0f,
201 flags);
202 }
203
204
205
206 /***************************************************************************
207
208 Start the video hardware emulation.
209
210 ***************************************************************************/
211
video_start()212 void travrusa_state::video_start()
213 {
214 save_item(NAME(m_scrollx));
215
216 m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(travrusa_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
217
218 m_bg_tilemap->set_transmask(0, 0xff, 0x00); /* split type 0 is totally transparent in front half */
219 m_bg_tilemap->set_transmask(1, 0x3f, 0xc0); /* split type 1 has pens 6 and 7 opaque - tunnels */
220
221 m_bg_tilemap->set_scroll_rows(4);
222 }
223
224
225
226 /***************************************************************************
227
228 Memory handlers
229
230 ***************************************************************************/
231
travrusa_videoram_w(offs_t offset,uint8_t data)232 void travrusa_state::travrusa_videoram_w(offs_t offset, uint8_t data)
233 {
234 m_videoram[offset] = data;
235 m_bg_tilemap->mark_tile_dirty(offset / 2);
236 }
237
238
set_scroll()239 void travrusa_state::set_scroll( )
240 {
241 int i;
242
243 for (i = 0; i <= 2; i++)
244 m_bg_tilemap->set_scrollx(i, m_scrollx[0] + 256 * m_scrollx[1]);
245
246 m_bg_tilemap->set_scrollx(3, 0);
247 }
248
travrusa_scroll_x_low_w(uint8_t data)249 void travrusa_state::travrusa_scroll_x_low_w(uint8_t data)
250 {
251 m_scrollx[0] = data;
252 set_scroll();
253 }
254
travrusa_scroll_x_high_w(uint8_t data)255 void travrusa_state::travrusa_scroll_x_high_w(uint8_t data)
256 {
257 m_scrollx[1] = data;
258 set_scroll();
259 }
260
261
travrusa_flipscreen_w(uint8_t data)262 void travrusa_state::travrusa_flipscreen_w(uint8_t data)
263 {
264 /* screen flip is handled both by software and hardware */
265 data ^= ~ioport("DSW2")->read() & 1;
266
267 flip_screen_set(data & 1);
268
269 machine().bookkeeping().coin_counter_w(0, data & 0x02);
270 machine().bookkeeping().coin_counter_w(1, data & 0x20);
271 }
272
273
274
275 /***************************************************************************
276
277 Display refresh
278
279 ***************************************************************************/
280
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect)281 void travrusa_state::draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect)
282 {
283 int offs;
284 const rectangle spritevisiblearea(1*8, 31*8-1, 0*8, 24*8-1);
285 const rectangle spritevisibleareaflip(1*8, 31*8-1, 8*8, 32*8-1);
286 rectangle clip = cliprect;
287 if (flip_screen())
288 clip &= spritevisibleareaflip;
289 else
290 clip &= spritevisiblearea;
291
292
293 for (offs = m_spriteram.bytes() - 4; offs >= 0; offs -= 4)
294 {
295 int sx = ((m_spriteram[offs + 3] + 8) & 0xff) - 8;
296 int sy = 240 - m_spriteram[offs];
297 int code = m_spriteram[offs + 2];
298 int attr = m_spriteram[offs + 1];
299 int flipx = attr & 0x40;
300 int flipy = attr & 0x80;
301
302 if (flip_screen())
303 {
304 sx = 240 - sx;
305 sy = 240 - sy;
306 flipx = !flipx;
307 flipy = !flipy;
308 }
309
310 m_gfxdecode->gfx(1)->transpen(bitmap,clip,
311 code,
312 attr & 0x0f,
313 flipx, flipy,
314 sx, sy, 0);
315 }
316 }
317
318
screen_update_travrusa(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)319 uint32_t travrusa_state::screen_update_travrusa(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
320 {
321 m_bg_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1, 0);
322 draw_sprites(bitmap,cliprect);
323 m_bg_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0, 0);
324 return 0;
325 }
326