summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/ninjaw.c
blob: 043fad6588772de434694a91a5e5f413352bae51 (plain) (blame)
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
#include "driver.h"
#include "video/taitoic.h"

#define TC0100SCN_GFX_NUM 1

struct tempsprite
{
	int gfx;
	int code,color;
	int flipx,flipy;
	int x,y;
	int zoomx,zoomy;
	int primask;
};
static struct tempsprite *spritelist;

static int taito_hide_pixels;



/**********************************************************/

static VIDEO_START( ninjaw_core )
{
	int chips;

	spritelist = auto_malloc(0x1000 * sizeof(*spritelist));

	chips = number_of_TC0100SCN();

	assert_always(chips > 0, "we have an erroneous TC0100SCN configuration");

	TC0100SCN_vh_start(machine,chips,TC0100SCN_GFX_NUM,taito_hide_pixels,0,0,0,0,0,2);

	if (has_TC0110PCR())
		TC0110PCR_vh_start();

	if (has_second_TC0110PCR())
		TC0110PCR_1_vh_start();

	if (has_third_TC0110PCR())
		TC0110PCR_2_vh_start();

	/* Ensure palette from correct TC0110PCR used for each screen */
	TC0100SCN_set_chip_colbanks(0x0,0x100,0x200);
}

VIDEO_START( ninjaw )
{
	taito_hide_pixels = 22;
	video_start_ninjaw_core(machine);
}

/************************************************************
            SPRITE DRAW ROUTINE
************************************************************/

static void draw_sprites(running_machine *machine, mame_bitmap *bitmap,const rectangle *cliprect,int primask,int x_offs,int y_offs)
{
	int offs, data, tilenum, color, flipx, flipy;
	int x, y, priority, curx, cury;
	int code;

#ifdef MAME_DEBUG
	int unknown=0;
#endif

	/* pdrawgfx() needs us to draw sprites front to back, so we have to build a list
       while processing sprite ram and then draw them all at the end */
	struct tempsprite *sprite_ptr = spritelist;

	for (offs = (spriteram_size/2)-4;offs >=0;offs -= 4)
	{
		data = spriteram16[offs+2];
		tilenum = data & 0x7fff;

		if (!tilenum) continue;

		data = spriteram16[offs+0];
		x = (data - 32) & 0x3ff;	/* aligns sprites on rock outcrops and sewer hole */

		data = spriteram16[offs+1];
		y = (data - 0) & 0x1ff;

		/* 
			The purpose of the bit at data&0x8 (below) is unknown, but it is set
			on Darius explosions, some enemy missiles and at least 1 boss.
			It is most likely another priority bit but as there are no obvious
			visual problems it will need checked against the original pcb.
			
			There is a report this bit is set when the player intersects
			the tank sprite in Ninja Warriors however I was unable to repro
			this or find any use of this bit in that game.  
			
			Bit&0x8000 is set on some sprites in later levels of Darius 
			but is again unknown, and there is no obvious visual problem.
		*/
		data = spriteram16[offs+3];
		flipx    = (data & 0x1);
		flipy    = (data & 0x2) >> 1;
		priority = (data & 0x4) >> 2; // 1 = low
		/* data&0x8 - unknown */
		if (priority != primask) continue;
		color    = (data & 0x7f00) >> 8;
		/* data&0x8000 - unknown */
		
#ifdef MAME_DEBUG
		if (data & 0x80f0)   unknown |= (data &0x80f0);
#endif

		x -= x_offs;
		y += y_offs;

		/* sprite wrap: coords become negative at high values */
		if (x>0x3c0) x -= 0x400;
		if (y>0x180) y -= 0x200;

		curx = x;
		cury = y;
		code = tilenum;

		sprite_ptr->code = code;
		sprite_ptr->color = color;
		sprite_ptr->flipx = flipx;
		sprite_ptr->flipy = flipy;
		sprite_ptr->x = curx;
		sprite_ptr->y = cury;

		drawgfx(bitmap,machine->gfx[0],
				sprite_ptr->code,
				sprite_ptr->color,
				sprite_ptr->flipx,sprite_ptr->flipy,
				sprite_ptr->x,sprite_ptr->y,
				cliprect,TRANSPARENCY_PEN,0);
	}

#ifdef MAME_DEBUG
	if (unknown)
		popmessage("unknown sprite bits: %04x",unknown);
#endif
}


/**************************************************************
                SCREEN REFRESH
**************************************************************/

VIDEO_UPDATE( ninjaw )
{
	int xoffs = 36*8*screen;

	UINT8 layer[3], nodraw;

	TC0100SCN_tilemap_update(machine);

	layer[0] = TC0100SCN_bottomlayer(0);
	layer[1] = layer[0]^1;
	layer[2] = 2;

	/* chip 0 does tilemaps on the left, chip 1 center, chip 2 the right */
	// draw bottom layer
	nodraw  = TC0100SCN_tilemap_draw(machine,bitmap,cliprect,screen,layer[0],TILEMAP_DRAW_OPAQUE,0);	/* left */

	/* Ensure screen blanked even when bottom layers not drawn due to disable bit */
	if (nodraw) fillbitmap(bitmap, get_black_pen(machine), cliprect);

	/* Sprites can be under/over the layer below text layer */
	draw_sprites(machine,bitmap,cliprect,1,xoffs,8); // draw sprites with priority 1 which are under the mid layer

	// draw middle layer
	TC0100SCN_tilemap_draw(machine,bitmap,cliprect,screen,layer[1],0,0);

	draw_sprites(machine,bitmap,cliprect,0,xoffs,8); // draw sprites with priority 0 which are over the mid layer

	// draw top(text) layer
	TC0100SCN_tilemap_draw(machine,bitmap,cliprect,screen,layer[2],0,0);
	return 0;
}