1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
|
// license:BSD-3-Clause
// copyright-holders:David Graves
#include "emu.h"
#include "includes/topspeed.h"
#include "screen.h"
/****************************************************************************
NOTES
Raster line color control
-------------------------
Used to make the road move. Each word controls one pixel row.
0x800000 - 0x1ff raster color control for one road tilemap
0x800200 - 0x3ff raster color control for the other
Road tile colors are (all?) in the range 0x100-103. Top road section
(tilemap at 0xa08000) uses 0x100 and 0x101. Bottom section
(tilemap at 0xb00000) uses 0x102 and 0x103. This would allow colors
on left and right side of road to be different. In practice it seems
Taito didn't take advantage of this.
Each tilemap is usually all one color value. Every now and then (10s
or so) the value alternates. This seems to be determined by whether
the current section of road has white lines in the middle. (0x101/3
gives white lines.)
The raster line color control area has groups of four values which
cascade down through it so the road colors cascade down the screen.
There are three known groups (start is arbitrary; the cycles repeat ad
infinitum or until a different cycle starts; values given are from bottom
to top of screen):
(i) White lines in center of road
12 %10010
1f %11111
00 %00000
0d %01101
(ii) No lines in center of road
08 %01000
0c %01100
1a %11010
1e %11110
(iii) Under bridge or in tunnel [note almost identical to (i)]
ffe0 %00000
ffed %01101
fff2 %10010
ffef %01111
(iv) Unknown 4th group for tunnels in later parts of the game that have
no white lines, analogous to (ii) ?
Correlating with screenshots suggests that these bits refer to:
x.... road body ?
.x... lines in road center and inner edge
..x.. lines at road outer edge
...x. outside road ?
....x ???
Actual gfx tiles used for the road only use colors 1-5. Palette offsets:
(0 = transparency)
1 = lines in road center
2 = road edge (inner)
3 = road edge (outer)
4 = road body
5 = outside road
Each palette block contains three possible sets of 5 colors. Entries 1-5
(standard), 6-10 (alternate), 11-15 (tunnels).
In tunnels only 11-15 are used. Outside tunnels there is a choice between
the standard colors and the alternate colors. The road body could in theory
take a standard color while 'outside the road' took on an alternate. But
in practice the game is using a very limited choice of raster control words,
so we don't know.
Need to test whether sections of the road with unknown raster control words
(tunnels late in the game without central white lines) are correct against
a real machine.
Also are the 'prelines' shortly before white road lines appear correct?
CHECK screen inits at $1692
These suggest that rowscroll areas are all 0x1000 long and there are TWO
for each tilemap layer.
256 rows => 256 words => 0x200 bytes. So probably the inits are far too long.
Maybe the second area for each layer contains colscroll ?
****************************************************************************/
/****************************************************************************
SPRITES
Layout 8 bytes per sprite
-------------------------
+0x00 xxxxxxx. ........ Zoom Y
.......x xxxxxxxx Y
+0x02 x....... ........ Flip Y
........ .xxxxxxx Zoom X
+0x04 x....... ........ Priority
.x...... ........ Flip X
..x..... ........ Unknown
.......x xxxxxxxx X
+0x06 xxxxxxxx ........ Color
........ xxxxxxxx Tile number
********************************************************************************/
void topspeed_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
static const u32 primasks[2] = { 0xff00, 0xfffc }; /* Sprites are over bottom layer or under top layer */
/* Most of spriteram is not used by the 68000: rest is scratch space for the h/w perhaps ? */
for (int offs = 0; offs < m_spriteram.bytes() / 2; offs += 4)
{
const u16 data = m_spriteram[offs + 2];
const int tilenum = m_spriteram[offs + 3] & 0xff;
const u32 color = (m_spriteram[offs + 3] & 0xff00) >> 8;
const int flipx = (data & 0x4000) >> 14;
const int flipy = (m_spriteram[offs + 1] & 0x8000) >> 15;
int x = data & 0x1ff;
int y = m_spriteram[offs] & 0x1ff;
int zoomx = (m_spriteram[offs + 1]& 0x7f);
int zoomy = (m_spriteram[offs] & 0xfe00) >> 9;
const int priority = (data & 0x8000) >> 15;
// unknown = (data & 0x2000) >> 13;
/* End of sprite list */
if (y == 0x180)
break;
const int map_offset = tilenum << 7;
zoomx += 1;
zoomy += 1;
y += 3 + (128-zoomy);
/* treat coords as signed */
if (x > 0x140) x -= 0x200;
if (y > 0x140) y -= 0x200;
int bad_chunks = 0;
for (int sprite_chunk = 0; sprite_chunk < 128; sprite_chunk++)
{
const int k = sprite_chunk % 8; /* 8 sprite chunks per row */
const int j = sprite_chunk / 8; /* 16 rows */
/* pick tiles back to front for x and y flips */
const int px = (flipx) ? (7 - k) : (k);
const int py = (flipy) ? (15 - j) : (j);
const u16 code = m_spritemap[map_offset + (py << 3) + px];
if (code & 0x8000)
{
bad_chunks += 1;
continue;
}
const int curx = x + ((k * zoomx) / 8);
const int cury = y + ((j * zoomy) / 16);
const int zx = x + (((k + 1) * zoomx) / 8) - curx;
const int zy = y + (((j + 1) * zoomy) / 16) - cury;
m_gfxdecode->gfx(0)->prio_zoom_transpen(bitmap,cliprect,
code,
color,
flipx,flipy,
curx,cury,
zx << 12,zy << 13,
screen.priority(),primasks[priority],0);
}
if (bad_chunks)
logerror("Sprite number %04x had %02x invalid chunks\n",tilenum,bad_chunks);
}
}
/***************************************************************************/
u32 topspeed_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
u8 layer[4];
#ifdef MAME_DEBUG
if (machine().input().code_pressed_once (KEYCODE_V))
{
m_dislayer[0] ^= 1;
popmessage("bg: %01x", m_dislayer[0]);
}
if (machine().input().code_pressed_once (KEYCODE_B))
{
m_dislayer[1] ^= 1;
popmessage("fg: %01x", m_dislayer[1]);
}
if (machine().input().code_pressed_once (KEYCODE_N))
{
m_dislayer[2] ^= 1;
popmessage("bg2: %01x", m_dislayer[2]);
}
if (machine().input().code_pressed_once (KEYCODE_M))
{
m_dislayer[3] ^= 1;
popmessage("fg2: %01x", m_dislayer[3]);
}
if (machine().input().code_pressed_once (KEYCODE_C))
{
m_dislayer[4] ^= 1;
popmessage("sprites: %01x", m_dislayer[4]);
}
#endif
m_pc080sn[0]->tilemap_update();
m_pc080sn[1]->tilemap_update();
/* Tilemap layer priority seems hardwired (the order is odd, too) */
layer[0] = 1;
layer[1] = 0;
layer[2] = 1;
layer[3] = 0;
screen.priority().fill(0, cliprect);
bitmap.fill(0, cliprect);
#ifdef MAME_DEBUG
if (m_dislayer[3] == 0)
#endif
m_pc080sn[1]->tilemap_draw(screen, bitmap, cliprect, layer[0], TILEMAP_DRAW_OPAQUE, 1);
#ifdef MAME_DEBUG
if (m_dislayer[2] == 0)
#endif
m_pc080sn[1]->tilemap_draw_special(screen, bitmap, cliprect, layer[1], 0, 2, m_raster_ctrl);
#ifdef MAME_DEBUG
if (m_dislayer[1] == 0)
#endif
m_pc080sn[0]->tilemap_draw_special(screen, bitmap, cliprect, layer[2], 0, 4, m_raster_ctrl + 0x100);
#ifdef MAME_DEBUG
if (m_dislayer[0] == 0)
#endif
m_pc080sn[0]->tilemap_draw(screen, bitmap, cliprect, layer[3], 0, 8);
#ifdef MAME_DEBUG
if (m_dislayer[4] == 0)
#endif
draw_sprites(screen,bitmap,cliprect);
return 0;
}
|