1 // license:BSD-3-Clause
2 // copyright-holders:Tomasz Slanina, Pierpaolo Prazzoli
3 /***************************************************************************
4 
5   - BG layer 32x128 , 8x8 tiles 4bpp , 2 palettes  (2nd is black )
6   - TXT layer 32x32 , 8x8 tiles 4bpp , 2 palettes (2nd is black)
7   - Sprites 16x16 3bpp, 8 palettes (0-3 are black)
8 
9   'Special' effects :
10 
11   - spotlight - gfx(BG+Sprites) outside spotlight is using black pals
12                 spotlight masks are taken from ROM pr8
13                 simulated using bitmaps and custom clipping rect
14 
15   - lightning - BG color change (darkening ?) - simple analog circ.
16                             simulated by additional palette
17 
18 In debug build press 'w' for spotlight and 'e' for lightning
19 
20 ***************************************************************************/
21 #include "emu.h"
22 #include "includes/pitnrun.h"
23 
24 
25 
TILE_GET_INFO_MEMBER(pitnrun_state::get_tile_info1)26 TILE_GET_INFO_MEMBER(pitnrun_state::get_tile_info1)
27 {
28 	int code = m_videoram[tile_index];
29 	tileinfo.set(0,
30 		code,
31 		0,
32 		0);
33 }
34 
TILE_GET_INFO_MEMBER(pitnrun_state::get_tile_info2)35 TILE_GET_INFO_MEMBER(pitnrun_state::get_tile_info2)
36 {
37 	int code = m_videoram2[tile_index];
38 	tileinfo.set(1,
39 		code + (m_char_bank<<8),
40 		m_color_select&1,
41 		0);
42 }
43 
videoram_w(offs_t offset,uint8_t data)44 void pitnrun_state::videoram_w(offs_t offset, uint8_t data)
45 {
46 	m_videoram[offset] = data;
47 	m_fg ->mark_all_dirty();
48 }
49 
videoram2_w(offs_t offset,uint8_t data)50 void pitnrun_state::videoram2_w(offs_t offset, uint8_t data)
51 {
52 	m_videoram2[offset] = data;
53 	m_bg ->mark_all_dirty();
54 }
55 
WRITE_LINE_MEMBER(pitnrun_state::char_bank_select_w)56 WRITE_LINE_MEMBER(pitnrun_state::char_bank_select_w)
57 {
58 	m_char_bank = state;
59 	m_bg->mark_all_dirty();
60 }
61 
62 
scroll_w(offs_t offset,uint8_t data)63 void pitnrun_state::scroll_w(offs_t offset, uint8_t data)
64 {
65 	m_scroll = (m_scroll & (0xff<<((offset)?0:8))) |( data<<((offset)?8:0));
66 	m_bg->set_scrollx(0, m_scroll);
67 }
68 
scroll_y_w(uint8_t data)69 void pitnrun_state::scroll_y_w(uint8_t data)
70 {
71 	m_bg->set_scrolly(0, data);
72 }
73 
ha_w(uint8_t data)74 void pitnrun_state::ha_w(uint8_t data)
75 {
76 	m_ha=data;
77 }
78 
h_heed_w(uint8_t data)79 void pitnrun_state::h_heed_w(uint8_t data)
80 {
81 	m_h_heed=data;
82 }
83 
v_heed_w(uint8_t data)84 void pitnrun_state::v_heed_w(uint8_t data)
85 {
86 	m_v_heed=data;
87 }
88 
WRITE_LINE_MEMBER(pitnrun_state::color_select_w)89 WRITE_LINE_MEMBER(pitnrun_state::color_select_w)
90 {
91 	m_color_select = state;
92 	machine().tilemap().mark_all_dirty();
93 }
94 
spotlights()95 void pitnrun_state::spotlights()
96 {
97 	uint8_t const *const ROM = memregion("spot")->base();
98 	for (int i=0; i<4; i++)
99 	{
100 		for (int y=0; y<128; y++)
101 		{
102 			for (int x=0; x<16; x++)
103 			{
104 				int datapix = ROM[128*16*i + x + y*16];
105 				for(int b=0; b<8; b++)
106 				{
107 					m_tmp_bitmap[i]->pix(y, x*8 + (7 - b)) = (datapix & 1);
108 					datapix>>=1;
109 				}
110 			}
111 		}
112 	}
113 }
114 
115 
pitnrun_palette(palette_device & palette) const116 void pitnrun_state::pitnrun_palette(palette_device &palette) const
117 {
118 	uint8_t const *const color_prom = memregion("proms")->base();
119 
120 	for (int i = 0; i < 32*3; i++)
121 	{
122 		int bit0, bit1, bit2;
123 
124 		bit0 = BIT(color_prom[i], 0);
125 		bit1 = BIT(color_prom[i], 1);
126 		bit2 = BIT(color_prom[i], 2);
127 		int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
128 
129 		bit0 = BIT(color_prom[i], 3);
130 		bit1 = BIT(color_prom[i], 4);
131 		bit2 = BIT(color_prom[i], 5);
132 		int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
133 
134 		bit0 = 0;
135 		bit1 = BIT(color_prom[i], 6);
136 		bit2 = BIT(color_prom[i], 7);
137 		int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
138 
139 		palette.set_pen_color(i, rgb_t(r, g, b));
140 	}
141 
142 	// fake bg palette for lightning effect
143 	for (int i = 2*16; i < 2*16 + 16; i++)
144 	{
145 		int bit0, bit1, bit2;
146 
147 		bit0 = BIT(color_prom[i], 0);
148 		bit1 = BIT(color_prom[i], 1);
149 		bit2 = BIT(color_prom[i], 2);
150 		int r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
151 
152 		bit0 = BIT(color_prom[i], 3);
153 		bit1 = BIT(color_prom[i], 4);
154 		bit2 = BIT(color_prom[i], 5);
155 		int g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
156 
157 		bit0 = 0;
158 		bit1 = BIT(color_prom[i], 6);
159 		bit2 = BIT(color_prom[i], 7);
160 		int b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
161 
162 		r /= 3;
163 		g /= 3;
164 		b /= 3;
165 
166 		palette.set_pen_color(i + 16, (r > 0xff) ? 0xff : r, (g > 0xff) ? 0xff : g, (b > 0xff) ? 0xff : b);
167 
168 	}
169 }
170 
video_start()171 void pitnrun_state::video_start()
172 {
173 	m_fg = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(pitnrun_state::get_tile_info1)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
174 	m_bg = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(pitnrun_state::get_tile_info2)), TILEMAP_SCAN_ROWS, 8, 8, 32*4, 32);
175 	m_fg->set_transparent_pen(0 );
176 	m_tmp_bitmap[0] = std::make_unique<bitmap_ind16>(128,128);
177 	m_tmp_bitmap[1] = std::make_unique<bitmap_ind16>(128,128);
178 	m_tmp_bitmap[2] = std::make_unique<bitmap_ind16>(128,128);
179 	m_tmp_bitmap[3] = std::make_unique<bitmap_ind16>(128,128);
180 	spotlights();
181 
182 	save_item(NAME(m_h_heed));
183 	save_item(NAME(m_v_heed));
184 	save_item(NAME(m_ha));
185 	save_item(NAME(m_scroll));
186 	save_item(NAME(m_char_bank));
187 	save_item(NAME(m_color_select));
188 }
189 
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect)190 void pitnrun_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect )
191 {
192 	uint8_t *spriteram = m_spriteram;
193 	int sx, sy, flipx, flipy, offs,pal;
194 
195 	for (offs = 0 ; offs < 0x100; offs+=4)
196 	{
197 		pal=spriteram[offs+2]&0x3;
198 
199 		sy = 256-spriteram[offs+0]-16;
200 		sx = spriteram[offs+3]+1; // +1 needed to properly align Jump Kun
201 		flipy = (spriteram[offs+1]&0x80)>>7;
202 		flipx = (spriteram[offs+1]&0x40)>>6;
203 
204 		if (flip_screen_x())
205 		{
206 			sx = 256 - sx;
207 			flipx = !flipx;
208 		}
209 		if (flip_screen_y())
210 		{
211 			sy = 240 - sy;
212 			flipy = !flipy;
213 		}
214 
215 		m_gfxdecode->gfx(2)->transpen(bitmap,cliprect,
216 			(spriteram[offs+1]&0x3f)+((spriteram[offs+2]&0x80)>>1)+((spriteram[offs+2]&0x40)<<1),
217 			pal,
218 			flipx,flipy,
219 			sx,sy,0);
220 	}
221 }
222 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)223 uint32_t pitnrun_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
224 {
225 	int dx=0,dy=0;
226 	rectangle myclip=cliprect;
227 
228 #ifdef MAME_DEBUG
229 	if (machine().input().code_pressed_once(KEYCODE_Q))
230 	{
231 		uint8_t *ROM = memregion("maincpu")->base();
232 		ROM[0x84f6]=0; /* lap 0 - normal */
233 	}
234 
235 	if (machine().input().code_pressed_once(KEYCODE_W))
236 	{
237 		uint8_t *ROM = memregion("maincpu")->base();
238 		ROM[0x84f6]=6; /* lap 6 = spotlight */
239 	}
240 
241 	if (machine().input().code_pressed_once(KEYCODE_E))
242 	{
243 		uint8_t *ROM = memregion("maincpu")->base();
244 		ROM[0x84f6]=2; /* lap 3 (trial 2)= lightnings */
245 		ROM[0x8102]=1;
246 	}
247 #endif
248 
249 	bitmap.fill(0, cliprect);
250 
251 	if(!(m_ha&4))
252 		m_bg->draw(screen, bitmap, cliprect, 0,0);
253 	else
254 	{
255 		dx=128-m_h_heed+((m_ha&8)<<5)+3;
256 		dy=128-m_v_heed+((m_ha&0x10)<<4);
257 
258 		if (flip_screen_x())
259 			dx=128-dx+16;
260 
261 		if (flip_screen_y())
262 			dy=128-dy;
263 
264 		myclip.set(dx, dx+127, dy, dy+127);
265 		myclip &= cliprect;
266 
267 		m_bg->draw(screen, bitmap, myclip, 0,0);
268 	}
269 
270 	draw_sprites(bitmap,myclip);
271 
272 	if(m_ha&4)
273 		copybitmap_trans(bitmap,*m_tmp_bitmap[m_ha&3],flip_screen_x(),flip_screen_y(),dx,dy,myclip, 1);
274 	m_fg->draw(screen, bitmap, cliprect, 0,0);
275 	return 0;
276 }
277