1 /***************************************************************************
2
3 vidhrdw.c
4
5 Functions to emulate the video hardware of the machine.
6
7 ***************************************************************************/
8
9 #include "driver.h"
10 #include "vidhrdw/generic.h"
11
12 static struct tilemap *background_layer,*foreground_layer,*text_layer;
13
14 data16_t *toki_background1_videoram16;
15 data16_t *toki_background2_videoram16;
16 data16_t *toki_scrollram16;
17 static unsigned int toki_background_xscroll[256];
18 static unsigned int toki_foreground_xscroll[256];
19
20 /*************************************************************************
21 RASTER EFFECTS
22
23 Xscroll can be altered per scanline to create rowscroll effect.
24
25 (The driver does not implement rowscroll on the bootleg. It seems unlikely
26 the bootleggers would have been able to do this on their chipset. They
27 remapped the scroll registers, so obviously they were using a different
28 chip.
29
30 Why then would the old ghost of one of the remapped registers
31 still cause rowscroll? Probably the bootleggers simply didn't bother to
32 remove all the code writing the $a0000 area.)
33
34 *************************************************************************/
35
WRITE16_HANDLER(toki_control_w)36 WRITE16_HANDLER( toki_control_w )
37 {
38 int currline = cpu_getscanline();
39
40 COMBINE_DATA(&toki_scrollram16[offset]);
41
42 /* Keep a per-scanline record of X scroll offsets */
43 if (offset==0x15 || offset==0x16)
44 toki_foreground_xscroll[currline%256]=((toki_scrollram16[0x16] &0x7f) << 1)
45 |((toki_scrollram16[0x16] &0x80) >> 7)
46 |((toki_scrollram16[0x15] &0x10) << 4);
47
48 if (offset==0x05 || offset==0x06)
49 toki_background_xscroll[currline%256]=((toki_scrollram16[0x06] &0x7f) << 1)
50 |((toki_scrollram16[0x06] &0x80) >> 7)
51 |((toki_scrollram16[0x05] &0x10) << 4);
52 }
53
54 /* At EOF clear the previous frames scroll registers */
VIDEO_EOF(toki)55 VIDEO_EOF( toki )
56 {
57 int i;
58
59 toki_background_xscroll[0]=((toki_scrollram16[0x16] &0x7f) << 1)
60 |((toki_scrollram16[0x16] &0x80) >> 7)
61 |((toki_scrollram16[0x15] &0x10) << 4);
62 toki_foreground_xscroll[0]=((toki_scrollram16[0x06] &0x7f) << 1)
63 |((toki_scrollram16[0x06] &0x80) >> 7)
64 |((toki_scrollram16[0x05] &0x10) << 4);
65
66 for (i=1; i<256; i++)
67 toki_background_xscroll[i]=toki_foreground_xscroll[i]=0xffff;
68
69 buffer_spriteram16_w(0,0,0);
70 }
71
VIDEO_EOF(tokib)72 VIDEO_EOF( tokib )
73 {
74 buffer_spriteram16_w(0,0,0);
75 }
76
get_text_tile_info(int tile_index)77 static void get_text_tile_info(int tile_index)
78 {
79 int tile = videoram16[tile_index];
80 int color=(tile>>12)&0xf;
81
82 tile&=0xfff;
83
84 SET_TILE_INFO(
85 0,
86 tile,
87 color,
88 0)
89 }
90
get_back_tile_info(int tile_index)91 static void get_back_tile_info(int tile_index)
92 {
93 int tile = toki_background1_videoram16[tile_index];
94 int color=(tile>>12)&0xf;
95
96 tile&=0xfff;
97
98 SET_TILE_INFO(
99 2,
100 tile,
101 color,
102 0)
103 }
104
get_fore_tile_info(int tile_index)105 static void get_fore_tile_info(int tile_index)
106 {
107 int tile = toki_background2_videoram16[tile_index];
108 int color=(tile>>12)&0xf;
109
110 tile&=0xfff;
111
112 SET_TILE_INFO(
113 3,
114 tile,
115 color,
116 0)
117 }
118
119
120 /*************************************
121 *
122 * Start/Stop
123 *
124 *************************************/
125
VIDEO_START(toki)126 VIDEO_START( toki )
127 {
128 text_layer = tilemap_create(get_text_tile_info,tilemap_scan_rows,TILEMAP_TRANSPARENT, 8,8,32,32);
129 background_layer = tilemap_create(get_back_tile_info,tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,32,32);
130 foreground_layer = tilemap_create(get_fore_tile_info,tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,32,32);
131
132 if (!text_layer || !background_layer || !foreground_layer) return 1;
133
134 tilemap_set_transparent_pen(text_layer,15);
135 tilemap_set_transparent_pen(background_layer,15);
136 tilemap_set_transparent_pen(foreground_layer,15);
137 tilemap_set_scroll_rows(foreground_layer,512);
138 tilemap_set_scroll_rows(background_layer,512);
139
140 return 0;
141 }
142
143 /*************************************/
144
WRITE16_HANDLER(toki_foreground_videoram16_w)145 WRITE16_HANDLER( toki_foreground_videoram16_w )
146 {
147 int oldword = videoram16[offset];
148 COMBINE_DATA(&videoram16[offset]);
149 if (oldword != videoram16[offset])
150 tilemap_mark_tile_dirty(text_layer,offset);
151 }
152
WRITE16_HANDLER(toki_background1_videoram16_w)153 WRITE16_HANDLER( toki_background1_videoram16_w )
154 {
155 int oldword = toki_background1_videoram16[offset];
156 COMBINE_DATA(&toki_background1_videoram16[offset]);
157 if (oldword != toki_background1_videoram16[offset])
158 tilemap_mark_tile_dirty(background_layer,offset);
159 }
160
WRITE16_HANDLER(toki_background2_videoram16_w)161 WRITE16_HANDLER( toki_background2_videoram16_w )
162 {
163 int oldword = toki_background2_videoram16[offset];
164 COMBINE_DATA(&toki_background2_videoram16[offset]);
165 if (oldword != toki_background2_videoram16[offset])
166 tilemap_mark_tile_dirty(foreground_layer,offset);
167 }
168
169 /***************************************************************************
170 SPRITES
171
172 Original Spriteram
173 ------------------
174
175 It's not clear what purpose is served by marking tiles as being part of
176 big sprites. (Big sprites in the attract abduction scene have all tiles
177 marked as "first" unlike big sprites in-game.)
178
179 We just ignore this top nibble (although perhaps in theory the bits
180 enable X/Y offsets in the low byte).
181
182 +0 x....... ........ sprite disable ??
183 +0 .xx..... ........ tile is part of big sprite (4=first, 6=middle, 2=last)
184 +0 .....x.. ........ ??? always set? (could be priority - see Bloodbro)
185 +0 .......x ........ Flip x
186 +0 ........ xxxx.... X offset: add (this * 16) to X coord
187 +0 ........ ....xxxx Y offset: add (this * 16) to Y coord
188
189 +1 xxxx.... ........ Color bank
190 +1 ....xxxx xxxxxxxx Tile number (lo bits)
191 +2 x....... ........ Tile number (hi bit)
192 +2 .???.... ........ (set in not yet used entries)
193 +2 .......x xxxxxxxx X coordinate
194 +3 .......x xxxxxxxx Y coordinate
195
196 f000 0000 f000 0000 entry not yet used: unless this is honored there
197 will be junk sprites in top left corner
198 ffff ???? ???? ???? sprite marked as dead: unless this is honored
199 there will be junk sprites after floating monkey machine
200
201
202 Bootleg Spriteram
203 -----------------
204
205 +0 .......x xxxxxxxx Sprite Y coordinate
206 +1 ...xxxxx xxxxxxxx Sprite tile number
207 +1 .x...... ........ Sprite flip x
208 +2 xxxx.... ........ Sprite color bank
209 +3 .......x xxxxxxxx Sprite X coordinate
210
211 f100 ???? ???? ???? dead / unused sprite ??
212 ???? ???? 0000 ???? dead / unused sprite ??
213
214
215 ***************************************************************************/
216
217
toki_draw_sprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect)218 void toki_draw_sprites (struct mame_bitmap *bitmap,const struct rectangle *cliprect)
219 {
220 int x,y,xoffs,yoffs,tile,flipx,flipy,color,offs;
221 data16_t *sprite_word;
222
223 for (offs = (spriteram_size/2)-4;offs >= 0;offs -= 4)
224 {
225 sprite_word = &buffered_spriteram16[offs];
226
227 if ((sprite_word[2] != 0xf000) && (sprite_word[0] != 0xffff))
228 {
229 xoffs = (sprite_word[0] &0xf0);
230 x = (sprite_word[2] + xoffs) & 0x1ff;
231 if (x > 256)
232 x -= 512;
233
234 yoffs = (sprite_word[0] &0xf) << 4;
235 y = (sprite_word[3] + yoffs) & 0x1ff;
236 if (y > 256)
237 y -= 512;
238
239 color = sprite_word[1] >> 12;
240 flipx = sprite_word[0] & 0x100;
241 flipy = 0;
242 tile = (sprite_word[1] & 0xfff) + ((sprite_word[2] & 0x8000) >> 3);
243
244 if (flip_screen) {
245 x=240-x;
246 y=240-y;
247 if (flipx) flipx=0; else flipx=1;
248 flipy=1;
249 }
250
251 drawgfx (bitmap,Machine->gfx[1],
252 tile,
253 color,
254 flipx,flipy,
255 x,y,
256 cliprect,TRANSPARENCY_PEN,15);
257 }
258 }
259 }
260
261
tokib_draw_sprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect)262 void tokib_draw_sprites (struct mame_bitmap *bitmap,const struct rectangle *cliprect)
263 {
264 int x,y,tile,flipx,color,offs;
265 data16_t *sprite_word;
266
267 for (offs = 0;offs < spriteram_size / 2;offs += 4)
268 {
269 sprite_word = &buffered_spriteram16[offs];
270
271 if (sprite_word[0] == 0xf100)
272 break;
273 if (sprite_word[2])
274 {
275
276 x = sprite_word[3] & 0x1ff;
277 if (x > 256)
278 x -= 512;
279
280 y = sprite_word[0] & 0x1ff;
281 if (y > 256)
282 y = (512-y)+240;
283 else
284 y = 240-y;
285
286 flipx = sprite_word[1] & 0x4000;
287 tile = sprite_word[1] & 0x1fff;
288 color = sprite_word[2] >> 12;
289
290 drawgfx (bitmap,Machine->gfx[1],
291 tile,
292 color,
293 flipx,0,
294 x,y-1,
295 cliprect,TRANSPARENCY_PEN,15);
296 }
297 }
298 }
299
300 /*************************************
301 *
302 * Master update function
303 *
304 *************************************/
305
VIDEO_UPDATE(toki)306 VIDEO_UPDATE( toki )
307 {
308 int i,background_y_scroll,foreground_y_scroll,latch1,latch2;
309
310 background_y_scroll=((toki_scrollram16[0x0d]&0x10)<<4)+((toki_scrollram16[0x0e]&0x7f)<<1)+((toki_scrollram16[0x0e]&0x80)>>7);
311 foreground_y_scroll=((toki_scrollram16[0x1d]&0x10)<<4)+((toki_scrollram16[0x1e]&0x7f)<<1)+((toki_scrollram16[0x1e]&0x80)>>7);
312 tilemap_set_scrolly( background_layer, 0, background_y_scroll );
313 tilemap_set_scrolly( foreground_layer, 0, foreground_y_scroll );
314
315 latch1=toki_background_xscroll[0];
316 latch2=toki_foreground_xscroll[0];
317 for (i=0; i<256; i++) {
318 if (toki_background_xscroll[i]!=0xffff)
319 latch1=toki_background_xscroll[i];
320 if (toki_foreground_xscroll[i]!=0xffff)
321 latch2=toki_foreground_xscroll[i];
322
323 tilemap_set_scrollx( background_layer, (i+background_y_scroll)%512, latch1 );
324 tilemap_set_scrollx( foreground_layer, (i+foreground_y_scroll)%512, latch2 );
325 }
326
327 flip_screen_set((toki_scrollram16[0x28]&0x8000)==0);
328
329 if (toki_scrollram16[0x28]&0x100) {
330 tilemap_draw(bitmap,cliprect,background_layer,TILEMAP_IGNORE_TRANSPARENCY,0);
331 tilemap_draw(bitmap,cliprect,foreground_layer,0,0);
332 } else {
333 tilemap_draw(bitmap,cliprect,foreground_layer,TILEMAP_IGNORE_TRANSPARENCY,0);
334 tilemap_draw(bitmap,cliprect,background_layer,0,0);
335 }
336 toki_draw_sprites (bitmap,cliprect);
337 tilemap_draw(bitmap,cliprect,text_layer,0,0);
338 }
339
VIDEO_UPDATE(tokib)340 VIDEO_UPDATE( tokib )
341 {
342 tilemap_set_scroll_rows(foreground_layer,1);
343 tilemap_set_scroll_rows(background_layer,1);
344 tilemap_set_scrolly( background_layer, 0, toki_scrollram16[0]+1 );
345 tilemap_set_scrollx( background_layer, 0, toki_scrollram16[1]-0x103 );
346 tilemap_set_scrolly( foreground_layer, 0, toki_scrollram16[2]+1 );
347 tilemap_set_scrollx( foreground_layer, 0, toki_scrollram16[3]-0x101 );
348
349 if (toki_scrollram16[3]&0x2000) {
350 tilemap_draw(bitmap,cliprect,background_layer,TILEMAP_IGNORE_TRANSPARENCY,0);
351 tilemap_draw(bitmap,cliprect,foreground_layer,0,0);
352 } else {
353 tilemap_draw(bitmap,cliprect,foreground_layer,TILEMAP_IGNORE_TRANSPARENCY,0);
354 tilemap_draw(bitmap,cliprect,background_layer,0,0);
355 }
356
357 tokib_draw_sprites (bitmap,cliprect);
358 tilemap_draw(bitmap,cliprect,text_layer,0,0);
359 }
360