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