1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria
3 /***************************************************************************
4 
5  Pang Video Hardware
6 
7 ***************************************************************************/
8 
9 #include "emu.h"
10 #include "sound/okim6295.h"
11 #include "includes/mitchell.h"
12 
13 /***************************************************************************
14 
15   Callbacks for the TileMap code
16 
17 ***************************************************************************/
18 
TILE_GET_INFO_MEMBER(mitchell_state::get_tile_info)19 TILE_GET_INFO_MEMBER(mitchell_state::get_tile_info)
20 {
21 	uint8_t attr = m_colorram[tile_index];
22 	int code = m_videoram[2 * tile_index] + (m_videoram[2 * tile_index + 1] << 8);
23 	tileinfo.set(0,
24 			code,
25 			attr & 0x7f,
26 			(attr & 0x80) ? TILE_FLIPX : 0);
27 }
28 
29 
30 
31 /***************************************************************************
32 
33   Start the video hardware emulation.
34 
35 ***************************************************************************/
36 
VIDEO_START_MEMBER(mitchell_state,pang)37 VIDEO_START_MEMBER(mitchell_state,pang)
38 {
39 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(mitchell_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
40 	m_bg_tilemap->set_transparent_pen(15);
41 
42 	/* OBJ RAM */
43 	m_objram.resize(m_videoram.bytes());
44 
45 	/* Palette RAM */
46 	m_paletteram.resize(2 * m_palette->entries());
47 	m_palette->basemem().set(m_paletteram, ENDIANNESS_LITTLE, 2);
48 
49 	save_item(NAME(m_objram));
50 	save_item(NAME(m_paletteram));
51 }
52 
53 
54 
55 /***************************************************************************
56 
57   Memory handlers
58 
59 ***************************************************************************/
60 
61 /***************************************************************************
62   OBJ / CHAR RAM HANDLERS (BANK 0 = CHAR, BANK 1=OBJ)
63 ***************************************************************************/
64 
pang_video_bank_w(uint8_t data)65 void mitchell_state::pang_video_bank_w(uint8_t data)
66 {
67 	/* Bank handler (sets base pointers for video write) (doesn't apply to mgakuen) */
68 	m_video_bank = data;
69 }
70 
mstworld_video_bank_w(uint8_t data)71 void mitchell_state::mstworld_video_bank_w(uint8_t data)
72 {
73 	/* Monsters World seems to freak out if more bits are used.. */
74 	m_video_bank = data & 1;
75 }
76 
77 
mgakuen_videoram_w(offs_t offset,uint8_t data)78 void mitchell_state::mgakuen_videoram_w(offs_t offset, uint8_t data)
79 {
80 	m_videoram[offset] = data;
81 	m_bg_tilemap->mark_tile_dirty(offset / 2);
82 }
83 
mgakuen_videoram_r(offs_t offset)84 uint8_t mitchell_state::mgakuen_videoram_r(offs_t offset)
85 {
86 	return m_videoram[offset];
87 }
88 
mgakuen_objram_w(offs_t offset,uint8_t data)89 void mitchell_state::mgakuen_objram_w(offs_t offset, uint8_t data)
90 {
91 	m_objram[offset] = data;
92 }
93 
mgakuen_objram_r(offs_t offset)94 uint8_t mitchell_state::mgakuen_objram_r(offs_t offset)
95 {
96 	return m_objram[offset];
97 }
98 
pang_videoram_w(offs_t offset,uint8_t data)99 void mitchell_state::pang_videoram_w(offs_t offset, uint8_t data)
100 {
101 	if (m_video_bank)
102 		mgakuen_objram_w(offset, data);
103 	else
104 		mgakuen_videoram_w(offset, data);
105 }
106 
pang_videoram_r(offs_t offset)107 uint8_t mitchell_state::pang_videoram_r(offs_t offset)
108 {
109 	if (m_video_bank)
110 		return mgakuen_objram_r(offset);
111 	else
112 		return mgakuen_videoram_r(offset);
113 }
114 
115 /***************************************************************************
116   COLOUR RAM
117 ****************************************************************************/
118 
pang_colorram_w(offs_t offset,uint8_t data)119 void mitchell_state::pang_colorram_w(offs_t offset, uint8_t data)
120 {
121 	m_colorram[offset] = data;
122 	m_bg_tilemap->mark_tile_dirty(offset);
123 }
124 
pang_colorram_r(offs_t offset)125 uint8_t mitchell_state::pang_colorram_r(offs_t offset)
126 {
127 	return m_colorram[offset];
128 }
129 
130 /***************************************************************************
131   PALETTE HANDLERS (COLOURS: BANK 0 = 0x00-0x3f BANK 1=0x40-0xff)
132 ****************************************************************************/
133 
pang_gfxctrl_w(uint8_t data)134 void mitchell_state::pang_gfxctrl_w(uint8_t data)
135 {
136 logerror("PC %04x: pang_gfxctrl_w %02x\n",m_maincpu->pc(),data);
137 {
138 #if 0
139 	char baf[40];
140 	sprintf(baf,"%02x",data);
141 	popmessage(baf);
142 #endif
143 }
144 
145 	/* bit 0 is unknown (used, maybe back color enable?) */
146 
147 	/* bit 1 is coin counter */
148 	machine().bookkeeping().coin_counter_w(0, data & 2);
149 
150 	/* bit 2 is flip screen */
151 	if (m_flipscreen != (data & 0x04))
152 	{
153 		m_flipscreen = data & 0x04;
154 		machine().tilemap().set_flip_all(m_flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
155 	}
156 
157 	/* bit 3 is unknown (used, e.g. marukin pulses it on the title screen) */
158 
159 	/* bit 4 selects OKI M6295 bank */
160 	if (m_oki != nullptr)
161 		m_oki->set_rom_bank((data >> 4) & 1);
162 
163 	/* bit 5 is palette RAM bank selector (doesn't apply to mgakuen) */
164 	m_paletteram_bank = data & 0x20;
165 
166 	/* bits 6 and 7 are unknown, used in several places. At first I thought */
167 	/* they were bg and sprites enable, but this screws up spang (screen flickers */
168 	/* every time you pop a bubble). However, not using them as enable bits screws */
169 	/* up marukin - you can see partially built up screens during attract mode. */
170 }
171 
pangbl_gfxctrl_w(uint8_t data)172 void mitchell_state::pangbl_gfxctrl_w(uint8_t data)
173 {
174 logerror("PC %04x: pang_gfxctrl_w %02x\n",m_maincpu->pc(),data);
175 {
176 #if 0
177 	char baf[40];
178 	sprintf(baf,"%02x",data);
179 	popmessage(baf);
180 #endif
181 }
182 
183 	/* bit 0 is unknown (used, maybe back color enable?) */
184 
185 	/* bit 1 is coin counter */
186 	machine().bookkeeping().coin_counter_w(0, data & 2);
187 
188 	/* bit 2 is flip screen */
189 	if (m_flipscreen != (data & 0x04))
190 	{
191 		m_flipscreen = data & 0x04;
192 		machine().tilemap().set_flip_all(m_flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
193 	}
194 
195 	/* bit 3 is unknown (used, e.g. marukin pulses it on the title screen) */
196 
197 	/* bit 4 selects OKI M6295 bank, nop'ed here */
198 
199 	/* bit 5 is palette RAM bank selector (doesn't apply to mgakuen) */
200 	m_paletteram_bank = data & 0x20;
201 
202 	/* bits 6 and 7 are unknown, used in several places. At first I thought */
203 	/* they were bg and sprites enable, but this screws up spang (screen flickers */
204 	/* every time you pop a bubble). However, not using them as enable bits screws */
205 	/* up marukin - you can see partially built up screens during attract mode. */
206 }
207 
mstworld_gfxctrl_w(uint8_t data)208 void mitchell_state::mstworld_gfxctrl_w(uint8_t data)
209 {
210 logerror("PC %04x: pang_gfxctrl_w %02x\n",m_maincpu->pc(),data);
211 {
212 	char baf[40];
213 	sprintf(baf,"%02x",data);
214 //  popmessage(baf);
215 }
216 
217 	/* bit 0 is unknown (used, maybe back color enable?) */
218 
219 	/* bit 1 is coin counter */
220 	machine().bookkeeping().coin_counter_w(0, data & 2);
221 
222 	/* bit 2 is flip screen */
223 	if (m_flipscreen != (data & 0x04))
224 	{
225 		m_flipscreen = data & 0x04;
226 		machine().tilemap().set_flip_all(m_flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
227 	}
228 
229 	/* bit 3 is unknown (used, e.g. marukin pulses it on the title screen) */
230 
231 	/* bit 4 here does not select OKI M6295 bank: mstworld has its own z80 + sound banking */
232 
233 	/* bit 5 is palette RAM bank selector (doesn't apply to mgakuen) */
234 	m_paletteram_bank = data & 0x20;
235 
236 	/* bits 6 and 7 are unknown, used in several places. At first I thought */
237 	/* they were bg and sprites enable, but this screws up spang (screen flickers */
238 	/* every time you pop a bubble). However, not using them as enable bits screws */
239 	/* up marukin - you can see partially built up screens during attract mode. */
240 }
241 
pang_paletteram_w(offs_t offset,uint8_t data)242 void mitchell_state::pang_paletteram_w(offs_t offset, uint8_t data)
243 {
244 	m_palette->write8(offset + (m_paletteram_bank ? 0x800 : 0x000), data);
245 }
246 
pang_paletteram_r(offs_t offset)247 uint8_t mitchell_state::pang_paletteram_r(offs_t offset)
248 {
249 	return m_paletteram[offset + (m_paletteram_bank ? 0x800 : 0x000)];
250 }
251 
252 
253 
254 /***************************************************************************
255 
256   Display refresh
257 
258 ***************************************************************************/
259 
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect)260 void mitchell_state::draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect )
261 {
262 	int offs, sx, sy;
263 
264 	/* the last entry is not a sprite, we skip it otherwise spang shows a bubble */
265 	/* moving diagonally across the screen */
266 	for (offs = 0x1000 - 0x40; offs >= 0; offs -= 0x20)
267 	{
268 		int code = m_objram[offs];
269 		int attr = m_objram[offs + 1];
270 		int color = attr & 0x0f;
271 		sx = m_objram[offs + 3] + ((attr & 0x10) << 4);
272 		sy = ((m_objram[offs + 2] + 8) & 0xff) - 8;
273 		code += (attr & 0xe0) << 3;
274 		if (m_flipscreen)
275 		{
276 			sx = 496 - sx;
277 			sy = 240 - sy;
278 		}
279 		m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
280 					code,
281 					color,
282 					m_flipscreen, m_flipscreen,
283 					sx,sy,15);
284 	}
285 }
286 
screen_update_pang(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)287 uint32_t mitchell_state::screen_update_pang(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
288 {
289 	bitmap.fill(0, cliprect);
290 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
291 	draw_sprites(bitmap, cliprect);
292 	return 0;
293 }
294