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